Merge remote-tracking branch 'origin/tm_sla_supports_backend' into vb_3dscene_partial_update
This commit is contained in:
commit
e3b858c45f
@ -152,7 +152,7 @@ if(SLIC3R_STATIC)
|
||||
# set(Boost_USE_STATIC_RUNTIME ON)
|
||||
endif()
|
||||
#set(Boost_DEBUG ON)
|
||||
set(Boost_COMPILER "-vc120")
|
||||
# set(Boost_COMPILER "-vc120")
|
||||
find_package(Boost REQUIRED COMPONENTS system filesystem thread log locale regex)
|
||||
if(Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
BIN
resources/icons/overlay/cut_hover.png
Normal file
BIN
resources/icons/overlay/cut_hover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/icons/overlay/cut_off.png
Normal file
BIN
resources/icons/overlay/cut_off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/icons/overlay/cut_on.png
Normal file
BIN
resources/icons/overlay/cut_on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@ -1,2 +1 @@
|
||||
add_subdirectory(slabasebed)
|
||||
add_subdirectory(slasupporttree)
|
||||
|
@ -1,2 +0,0 @@
|
||||
add_executable(slasupporttree EXCLUDE_FROM_ALL slasupporttree.cpp)
|
||||
target_link_libraries(slasupporttree libslic3r)
|
@ -1,48 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <libslic3r.h>
|
||||
#include "TriangleMesh.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "callback.hpp"
|
||||
#include "SLA/SLASupportTree.hpp"
|
||||
#include "benchmark.h"
|
||||
|
||||
const std::string USAGE_STR = {
|
||||
"Usage: slasupporttree stlfilename.stl"
|
||||
};
|
||||
|
||||
void confess_at(const char * /*file*/,
|
||||
int /*line*/,
|
||||
const char * /*func*/,
|
||||
const char * /*pat*/,
|
||||
...) {}
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void PerlCallback::deregister_callback() {}
|
||||
}
|
||||
|
||||
int main(const int argc, const char *argv[]) {
|
||||
using namespace Slic3r;
|
||||
using std::cout; using std::endl;
|
||||
|
||||
if(argc < 2) {
|
||||
cout << USAGE_STR << endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Benchmark bench;
|
||||
TriangleMesh result;
|
||||
|
||||
bench.start();
|
||||
sla::create_head(result, 3, 1, 4);
|
||||
bench.stop();
|
||||
|
||||
cout << "Support tree creation time: " << std::setprecision(10)
|
||||
<< bench.getElapsedSec() << " seconds." << endl;
|
||||
|
||||
result.write_ascii("out.stl");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -80,7 +80,7 @@ elseif (MSVC)
|
||||
# Manifest is provided through slic3r.rc, don't generate your own.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
|
||||
else ()
|
||||
target_link_libraries(slic3r -ldl -lstdc++)
|
||||
target_link_libraries(slic3r ${CMAKE_DL_LIBS} -lstdc++)
|
||||
endif ()
|
||||
|
||||
# Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries.
|
||||
|
@ -66,7 +66,7 @@ set(AVRDUDE_SOURCES
|
||||
avrdude-slic3r.hpp
|
||||
avrdude-slic3r.cpp
|
||||
)
|
||||
if (WIN32)
|
||||
if (MSVC)
|
||||
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
||||
windows/unistd.cpp
|
||||
windows/getopt.c
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(WIN32NATIVE)
|
||||
#if !defined(WIN32NATIVE) || defined(__GNUC__)
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
@ -1858,7 +1858,7 @@ namespace Slic3r {
|
||||
if (volume == nullptr)
|
||||
continue;
|
||||
|
||||
VolumeToOffsetsMap::iterator volume_it = volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first;
|
||||
volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first;
|
||||
|
||||
if (!volume->mesh.repaired)
|
||||
volume->mesh.repair();
|
||||
@ -1875,12 +1875,23 @@ namespace Slic3r {
|
||||
|
||||
vertices_count += stl.stats.shared_vertices;
|
||||
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
Transform3d matrix = volume->get_matrix();
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
|
||||
for (int i = 0; i < stl.stats.shared_vertices; ++i)
|
||||
{
|
||||
stream << " <" << VERTEX_TAG << " ";
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
Vec3d v = matrix * stl.v_shared[i].cast<double>();
|
||||
stream << "x=\"" << v(0) << "\" ";
|
||||
stream << "y=\"" << v(1) << "\" ";
|
||||
stream << "z=\"" << v(2) << "\" />\n";
|
||||
#else
|
||||
stream << "x=\"" << stl.v_shared[i](0) << "\" ";
|
||||
stream << "y=\"" << stl.v_shared[i](1) << "\" ";
|
||||
stream << "z=\"" << stl.v_shared[i](2) << "\" />\n";
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1663,8 +1663,9 @@ void GCode::append_full_config(const Print& print, std::string& str)
|
||||
}
|
||||
const DynamicConfig &full_config = print.placeholder_parser().config();
|
||||
for (const char *key : {
|
||||
"print_settings_id", "filament_settings_id", "sla_material_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant", "default_print_profile", "default_filament_profile", "default_sla_material_profile",
|
||||
"print_settings_id", "filament_settings_id", "sla_print_settings_id", "sla_material_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant",
|
||||
"default_print_profile", "default_filament_profile", "default_sla_print_profile", "default_sla_material_profile",
|
||||
"compatible_printers_condition_cummulative", "inherits_cummulative" }) {
|
||||
const ConfigOption *opt = full_config.option(key);
|
||||
if (opt != nullptr)
|
||||
|
@ -951,25 +951,54 @@ bool ModelObject::needed_repair() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelObject::cut(coordf_t z, Model* model) const
|
||||
template<class T> static void cut_reset_transform(T *thing) {
|
||||
const Vec3d offset = thing->get_offset();
|
||||
thing->set_transformation(Geometry::Transformation());
|
||||
thing->set_offset(offset);
|
||||
}
|
||||
|
||||
ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z)
|
||||
{
|
||||
// clone this one to duplicate instances, materials etc.
|
||||
ModelObject* upper = model->add_object(*this);
|
||||
ModelObject* lower = model->add_object(*this);
|
||||
// Clone the object to duplicate instances, materials etc.
|
||||
ModelObject* upper = ModelObject::new_clone(*this);
|
||||
ModelObject* lower = ModelObject::new_clone(*this);
|
||||
upper->set_model(nullptr);
|
||||
lower->set_model(nullptr);
|
||||
upper->sla_support_points.clear();
|
||||
lower->sla_support_points.clear();
|
||||
upper->clear_volumes();
|
||||
lower->clear_volumes();
|
||||
upper->input_file = "";
|
||||
lower->input_file = "";
|
||||
|
||||
for (ModelVolume *volume : this->volumes) {
|
||||
|
||||
const auto instance_matrix = instances[instance]->get_matrix(true);
|
||||
|
||||
// Because transformations are going to be applied to meshes directly,
|
||||
// we reset transformation of all instances and volumes,
|
||||
// _except_ for translation, which is preserved in the transformation matrix
|
||||
// and not applied to the mesh transform.
|
||||
// TODO: Do the same for Z-rotation as well?
|
||||
|
||||
// Convert z from relative to bb's base to object coordinates
|
||||
// FIXME: doesn't work well for rotated objects
|
||||
const auto bb = instance_bounding_box(instance, true);
|
||||
z -= bb.min(2);
|
||||
|
||||
for (auto *instance : upper->instances) { cut_reset_transform(instance); }
|
||||
for (auto *instance : lower->instances) { cut_reset_transform(instance); }
|
||||
|
||||
for (ModelVolume *volume : volumes) {
|
||||
if (! volume->is_model_part()) {
|
||||
// don't cut modifiers
|
||||
upper->add_volume(*volume);
|
||||
lower->add_volume(*volume);
|
||||
} else {
|
||||
TriangleMesh upper_mesh, lower_mesh;
|
||||
|
||||
// Transform the mesh by the object transformation matrix
|
||||
volume->mesh.transform(instance_matrix * volume->get_matrix(true));
|
||||
cut_reset_transform(volume);
|
||||
|
||||
TriangleMeshSlicer tms(&volume->mesh);
|
||||
tms.cut(z, &upper_mesh, &lower_mesh);
|
||||
|
||||
@ -977,7 +1006,7 @@ void ModelObject::cut(coordf_t z, Model* model) const
|
||||
lower_mesh.repair();
|
||||
upper_mesh.reset_repair_stats();
|
||||
lower_mesh.reset_repair_stats();
|
||||
|
||||
|
||||
if (upper_mesh.facets_count() > 0) {
|
||||
ModelVolume* vol = upper->add_volume(upper_mesh);
|
||||
vol->name = volume->name;
|
||||
@ -992,6 +1021,15 @@ void ModelObject::cut(coordf_t z, Model* model) const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upper->invalidate_bounding_box();
|
||||
lower->invalidate_bounding_box();
|
||||
|
||||
ModelObjectPtrs res;
|
||||
if (upper->volumes.size() > 0) { res.push_back(upper); }
|
||||
if (lower->volumes.size() > 0) { res.push_back(lower); }
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ModelObject::split(ModelObjectPtrs* new_objects)
|
||||
@ -1011,7 +1049,8 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
||||
|
||||
mesh->repair();
|
||||
|
||||
ModelObject* new_object = m_model->add_object();
|
||||
// XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed?
|
||||
ModelObject* new_object = m_model->add_object();
|
||||
new_object->name = this->name;
|
||||
new_object->config = this->config;
|
||||
new_object->instances.reserve(this->instances.size());
|
||||
|
@ -237,7 +237,7 @@ public:
|
||||
size_t materials_count() const;
|
||||
size_t facets_count() const;
|
||||
bool needed_repair() const;
|
||||
void cut(coordf_t z, Model* model) const;
|
||||
ModelObjectPtrs cut(size_t instance, coordf_t z);
|
||||
void split(ModelObjectPtrs* new_objects);
|
||||
void repair();
|
||||
|
||||
@ -607,7 +607,7 @@ public:
|
||||
bool delete_object(ModelID id);
|
||||
bool delete_object(ModelObject* object);
|
||||
void clear_objects();
|
||||
|
||||
|
||||
ModelMaterial* add_material(t_model_material_id material_id);
|
||||
ModelMaterial* add_material(t_model_material_id material_id, const ModelMaterial &other);
|
||||
ModelMaterial* get_material(t_model_material_id material_id) {
|
||||
|
@ -2434,6 +2434,128 @@ void PrintConfigDef::init_sla_params()
|
||||
|
||||
def = this->add("sla_material_settings_id", coString);
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
|
||||
def = this->add("default_sla_print_profile", coString);
|
||||
def->label = L("Default SLA material profile");
|
||||
def->tooltip = L("Default print profile associated with the current printer profile. "
|
||||
"On selection of the current printer profile, this print profile will be activated.");
|
||||
def->default_value = new ConfigOptionString();
|
||||
|
||||
def = this->add("sla_print_settings_id", coString);
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("support_head_front_radius", coFloat);
|
||||
def->label = L("Support head front radius");
|
||||
def->tooltip = L("Radius of the pointing side of the head");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0.2);
|
||||
|
||||
def = this->add("support_head_penetration", coFloat);
|
||||
def->label = L("Support head penetration");
|
||||
def->tooltip = L("How much the pinhead has to penetrate the model surface");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0.2);
|
||||
|
||||
def = this->add("support_head_back_radius", coFloat);
|
||||
def->label = L("Support head back radius");
|
||||
def->tooltip = L("Radius of the back side of the 3d arrow");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0.5);
|
||||
|
||||
def = this->add("support_head_width", coFloat);
|
||||
def->label = L("Support head width");
|
||||
def->tooltip = L("Width from the back sphere center to the front sphere center");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(1.0);
|
||||
|
||||
def = this->add("support_pillar_radius", coFloat);
|
||||
def->label = L("Support pillar radius");
|
||||
def->tooltip = L("Radius in mm of the support pillars");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0.8);
|
||||
|
||||
def = this->add("support_base_radius", coFloat);
|
||||
def->label = L("Support base radius");
|
||||
def->tooltip = L("Radius in mm of the pillar base");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(2.0);
|
||||
|
||||
def = this->add("support_base_height", coFloat);
|
||||
def->label = L("Support base height");
|
||||
def->tooltip = L("The height of the pillar base cone");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(1.0);
|
||||
|
||||
def = this->add("support_critical_angle", coFloat);
|
||||
def->label = L("Critical angle");
|
||||
def->tooltip = L("The default angle for connecting support sticks and junctions.");
|
||||
def->sidetext = L("°");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(45);
|
||||
|
||||
def = this->add("support_max_bridge_length", coFloat);
|
||||
def->label = L("Max bridge length");
|
||||
def->tooltip = L("The max length of a bridge");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(15.0);
|
||||
|
||||
def = this->add("support_object_elevation", coFloat);
|
||||
def->label = L("Object elevation");
|
||||
def->tooltip = L("How much the supports should lift up the supported object.");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(5.0);
|
||||
|
||||
def = this->add("pad_wall_thickness", coFloat);
|
||||
def->label = L("Pad wall thickness");
|
||||
def->tooltip = L("");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(2.0);
|
||||
|
||||
def = this->add("pad_wall_height", coFloat);
|
||||
def->label = L("Pad wall height");
|
||||
def->tooltip = L("");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(5.0);
|
||||
|
||||
def = this->add("pad_max_merge_distance", coFloat);
|
||||
def->label = L("Max merge distance");
|
||||
def->tooltip = L("");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(50.0);
|
||||
|
||||
def = this->add("pad_edge_radius", coFloat);
|
||||
def->label = L("Pad edge radius");
|
||||
def->tooltip = L("");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(1.0);
|
||||
}
|
||||
|
||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||
|
@ -31,7 +31,7 @@ enum PrinterTechnology
|
||||
};
|
||||
|
||||
enum GCodeFlavor {
|
||||
gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion,
|
||||
};
|
||||
|
||||
@ -167,7 +167,7 @@ private:
|
||||
// This definition is constant.
|
||||
extern const PrintConfigDef print_config_def;
|
||||
|
||||
// Slic3r dynamic configuration, used to override the configuration
|
||||
// Slic3r dynamic configuration, used to override the configuration
|
||||
// per object, per modification volume or per printing material.
|
||||
// The dynamic configuration is also used to store user modifications of the print global parameters,
|
||||
// so the modified configuration values may be diffed against the active configuration
|
||||
@ -274,12 +274,12 @@ protected:
|
||||
m_defaults = defaults;
|
||||
m_keys.clear();
|
||||
m_keys.reserve(m_map_name_to_offset.size());
|
||||
for (const auto &kvp : defs->options) {
|
||||
// Find the option given the option name kvp.first by an offset from (char*)m_defaults.
|
||||
ConfigOption *opt = this->optptr(kvp.first, m_defaults);
|
||||
if (opt == nullptr)
|
||||
// This option is not defined by the ConfigBase of type T.
|
||||
continue;
|
||||
for (const auto &kvp : defs->options) {
|
||||
// Find the option given the option name kvp.first by an offset from (char*)m_defaults.
|
||||
ConfigOption *opt = this->optptr(kvp.first, m_defaults);
|
||||
if (opt == nullptr)
|
||||
// This option is not defined by the ConfigBase of type T.
|
||||
continue;
|
||||
m_keys.emplace_back(kvp.first);
|
||||
const ConfigOptionDef *def = defs->get(kvp.first);
|
||||
assert(def != nullptr);
|
||||
@ -463,7 +463,7 @@ public:
|
||||
ConfigOptionInt top_solid_layers;
|
||||
ConfigOptionFloatOrPercent top_solid_infill_speed;
|
||||
ConfigOptionBool wipe_into_infill;
|
||||
|
||||
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
@ -768,7 +768,7 @@ public:
|
||||
ConfigOptionInt pixel_height;
|
||||
ConfigOptionFloat exp_time;
|
||||
ConfigOptionFloat exp_time_first;
|
||||
|
||||
|
||||
protected:
|
||||
PrintConfig(int) : GCodeConfig(1) {}
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
@ -859,7 +859,7 @@ public:
|
||||
ConfigOptionString printhost_cafile;
|
||||
ConfigOptionString serial_port;
|
||||
ConfigOptionInt serial_speed;
|
||||
|
||||
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
@ -873,14 +873,14 @@ protected:
|
||||
};
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::Full.
|
||||
class FullPrintConfig :
|
||||
public PrintObjectConfig,
|
||||
class FullPrintConfig :
|
||||
public PrintObjectConfig,
|
||||
public PrintRegionConfig,
|
||||
public PrintConfig,
|
||||
public HostConfig
|
||||
{
|
||||
STATIC_PRINT_CONFIG_CACHE_DERIVED(FullPrintConfig)
|
||||
FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) { initialize_cache(); *this = s_cache_FullPrintConfig.defaults(); }
|
||||
FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) { initialize_cache(); *this = s_cache_FullPrintConfig.defaults(); }
|
||||
|
||||
public:
|
||||
// Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
|
||||
@ -908,16 +908,17 @@ public:
|
||||
ConfigOptionFloat support_head_front_radius /*= 0.2*/;
|
||||
|
||||
// How much the pinhead has to penetrate the model surface
|
||||
ConfigOptionFloat support_head_penetraiton /*= 0.2*/;
|
||||
ConfigOptionFloat support_head_penetration /*= 0.2*/;
|
||||
|
||||
// Radius of the back side of the 3d arrow.
|
||||
// Radius of the back side of the 3d arrow. TODO: consider renaming this
|
||||
// to actual pillar radius, because that's what it boils down to.
|
||||
ConfigOptionFloat support_head_back_radius /*= 0.5*/;
|
||||
|
||||
// Width in mm from the back sphere center to the front sphere center.
|
||||
ConfigOptionFloat support_head_width /*= 1.0*/;
|
||||
|
||||
// Radius in mm of the support pillars.
|
||||
// TODO: This parameter is invalid. The pillar radius will be dynamic in
|
||||
// TODO: This parameter is questionable. The pillar radius will be dynamic in
|
||||
// nature. Merged pillars will have an increased thickness. This parameter
|
||||
// may serve as the maximum radius, or maybe an increase when two are merged
|
||||
// The default radius will be derived from head_back_radius_mm
|
||||
@ -930,16 +931,16 @@ public:
|
||||
ConfigOptionFloat support_base_height /*= 1.0*/;
|
||||
|
||||
// The default angle for connecting support sticks and junctions.
|
||||
ConfigOptionFloat support_critical_angle /*= M_PI/4*/;
|
||||
ConfigOptionFloat support_critical_angle /*= 45*/;
|
||||
|
||||
// The max length of a bridge in mm
|
||||
ConfigOptionFloat support_max_bridge_length /*= 15.0*/;
|
||||
|
||||
// The elevation in Z direction upwards. This is the space between the pad
|
||||
// and the model object's bounding box bottom.
|
||||
ConfigOptionFloat support_object_elevation;
|
||||
// and the model object's bounding box bottom. Units in mm.
|
||||
ConfigOptionFloat support_object_elevation /*= 5.0*/;
|
||||
|
||||
// Now for the base pool (plate) ///////////////////////////////////////////
|
||||
// Now for the base pool (pad) /////////////////////////////////////////////
|
||||
|
||||
ConfigOptionFloat pad_wall_thickness /*= 2*/;
|
||||
ConfigOptionFloat pad_wall_height /*= 5*/;
|
||||
@ -951,7 +952,7 @@ protected:
|
||||
{
|
||||
OPT_PTR(layer_height);
|
||||
OPT_PTR(support_head_front_radius);
|
||||
OPT_PTR(support_head_penetraiton);
|
||||
OPT_PTR(support_head_penetration);
|
||||
OPT_PTR(support_head_back_radius);
|
||||
OPT_PTR(support_head_width);
|
||||
OPT_PTR(support_pillar_radius);
|
||||
@ -959,6 +960,7 @@ protected:
|
||||
OPT_PTR(support_base_height);
|
||||
OPT_PTR(support_critical_angle);
|
||||
OPT_PTR(support_max_bridge_length);
|
||||
OPT_PTR(support_object_elevation);
|
||||
OPT_PTR(pad_wall_thickness);
|
||||
OPT_PTR(pad_wall_height);
|
||||
OPT_PTR(pad_max_merge_distance);
|
||||
@ -1068,7 +1070,7 @@ public:
|
||||
ConfigOptionFloat scale;
|
||||
// ConfigOptionPoint3 scale_to_fit;
|
||||
ConfigOptionBool slice;
|
||||
|
||||
|
||||
CLIConfig() : ConfigBase(), StaticConfig()
|
||||
{
|
||||
this->set_defaults();
|
||||
@ -1076,7 +1078,7 @@ public:
|
||||
|
||||
// Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
const ConfigDef* def() const override { return &cli_config_def; }
|
||||
t_config_option_keys keys() const override { return cli_config_def.keys(); }
|
||||
t_config_option_keys keys() const override { return cli_config_def.keys(); }
|
||||
|
||||
ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override
|
||||
{
|
||||
@ -1118,7 +1120,7 @@ private:
|
||||
class PrintAndCLIConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
PrintAndCLIConfigDef() {
|
||||
PrintAndCLIConfigDef() {
|
||||
this->options.insert(print_config_def.options.begin(), print_config_def.options.end());
|
||||
this->options.insert(cli_config_def.options.begin(), cli_config_def.options.end());
|
||||
}
|
||||
|
@ -424,12 +424,6 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
||||
TriangleMesh m = mesh;
|
||||
TriangleMeshSlicer slicer(&m);
|
||||
|
||||
// TriangleMesh upper, lower;
|
||||
// slicer.cut(h, &upper, &lower);
|
||||
|
||||
// TODO: this might be slow (in fact it was)
|
||||
// output = lower.horizontal_projection();
|
||||
|
||||
auto bb = mesh.bounding_box();
|
||||
float gnd = float(bb.min(Z));
|
||||
std::vector<float> heights = {float(bb.min(Z))};
|
||||
|
@ -213,6 +213,7 @@ struct Head {
|
||||
double r_back_mm = 1;
|
||||
double r_pin_mm = 0.5;
|
||||
double width_mm = 2;
|
||||
double penetration_mm = 0.5;
|
||||
|
||||
// For identification purposes. This will be used as the index into the
|
||||
// container holding the head structures. See SLASupportTree::Impl
|
||||
@ -224,11 +225,13 @@ struct Head {
|
||||
Head(double r_big_mm,
|
||||
double r_small_mm,
|
||||
double length_mm,
|
||||
double penetration,
|
||||
Vec3d direction = {0, 0, -1}, // direction (normal to the dull end )
|
||||
Vec3d offset = {0, 0, 0}, // displacement
|
||||
const size_t circlesteps = 45):
|
||||
steps(circlesteps), dir(direction), tr(offset),
|
||||
r_back_mm(r_big_mm), r_pin_mm(r_small_mm), width_mm(length_mm)
|
||||
r_back_mm(r_big_mm), r_pin_mm(r_small_mm), width_mm(length_mm),
|
||||
penetration_mm(penetration)
|
||||
{
|
||||
|
||||
// We create two spheres which will be connected with a robe that fits
|
||||
@ -281,7 +284,7 @@ struct Head {
|
||||
|
||||
// To simplify further processing, we translate the mesh so that the
|
||||
// last vertex of the pointing sphere (the pinpoint) will be at (0,0,0)
|
||||
for(auto& p : mesh.points) { z(p) -= (h + 0.5 * r_small_mm); }
|
||||
for(auto& p : mesh.points) z(p) -= (h + r_small_mm - penetration_mm);
|
||||
}
|
||||
|
||||
void transform()
|
||||
@ -298,11 +301,11 @@ struct Head {
|
||||
}
|
||||
|
||||
double fullwidth() const {
|
||||
return 1.5 * r_pin_mm + width_mm + 2*r_back_mm;
|
||||
return 2 * r_pin_mm + width_mm + 2*r_back_mm - penetration_mm;
|
||||
}
|
||||
|
||||
Vec3d junction_point() const {
|
||||
return tr + ( 1.5 * r_pin_mm + width_mm + r_back_mm)*dir;
|
||||
return tr + ( 2 * r_pin_mm + width_mm + r_back_mm - penetration_mm)*dir;
|
||||
}
|
||||
|
||||
double request_pillar_radius(double radius) const {
|
||||
@ -507,7 +510,9 @@ struct Pad {
|
||||
Pad(const TriangleMesh& object_support_mesh,
|
||||
const ExPolygons& baseplate,
|
||||
double ground_level,
|
||||
const PoolConfig& cfg) : zlevel(ground_level + cfg.min_wall_height_mm/2)
|
||||
const PoolConfig& pcfg) :
|
||||
cfg(pcfg),
|
||||
zlevel(ground_level + cfg.min_wall_height_mm/2)
|
||||
{
|
||||
ExPolygons basep;
|
||||
base_plate(object_support_mesh, basep,
|
||||
@ -538,19 +543,6 @@ EigenMesh3D to_eigenmesh(const Contour3D& cntr) {
|
||||
return emesh;
|
||||
}
|
||||
|
||||
void create_head(TriangleMesh& out, double r1_mm, double r2_mm, double width_mm)
|
||||
{
|
||||
Head head(r1_mm, r2_mm, width_mm, {0, std::sqrt(0.5), -std::sqrt(0.5)},
|
||||
{0, 0, 30});
|
||||
out.merge(mesh(head.mesh));
|
||||
|
||||
Pillar cst(head, {0, 0, 0});
|
||||
cst.add_base();
|
||||
|
||||
out.merge(mesh(cst.mesh));
|
||||
out.merge(mesh(cst.base));
|
||||
}
|
||||
|
||||
// The minimum distance for two support points to remain valid.
|
||||
static const double /*constexpr*/ D_SP = 0.1;
|
||||
|
||||
@ -593,21 +585,6 @@ EigenMesh3D to_eigenmesh(const ModelObject& modelobj) {
|
||||
return to_eigenmesh(modelobj.raw_mesh());
|
||||
}
|
||||
|
||||
EigenMesh3D to_eigenmesh(const Model& model) {
|
||||
TriangleMesh combined_mesh;
|
||||
|
||||
for(ModelObject *o : model.objects) {
|
||||
TriangleMesh tmp = o->raw_mesh();
|
||||
for(ModelInstance * inst: o->instances) {
|
||||
TriangleMesh ttmp(tmp);
|
||||
inst->transform_mesh(&ttmp);
|
||||
combined_mesh.merge(ttmp);
|
||||
}
|
||||
}
|
||||
|
||||
return to_eigenmesh(combined_mesh);
|
||||
}
|
||||
|
||||
PointSet to_point_set(const std::vector<Vec3d> &v)
|
||||
{
|
||||
PointSet ret(v.size(), 3);
|
||||
@ -619,43 +596,6 @@ Vec3d model_coord(const ModelInstance& object, const Vec3f& mesh_coord) {
|
||||
return object.transform_vector(mesh_coord.cast<double>());
|
||||
}
|
||||
|
||||
PointSet support_points(const Model& model) {
|
||||
size_t sum = 0;
|
||||
for(auto *o : model.objects)
|
||||
sum += o->instances.size() * o->sla_support_points.size();
|
||||
|
||||
PointSet ret(sum, 3);
|
||||
|
||||
for(ModelObject *o : model.objects)
|
||||
for(ModelInstance *inst : o->instances) {
|
||||
int i = 0;
|
||||
for(Vec3f& msource : o->sla_support_points) {
|
||||
ret.row(i++) = model_coord(*inst, msource);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PointSet support_points(const ModelObject& modelobject)
|
||||
{
|
||||
PointSet ret(modelobject.sla_support_points.size(), 3);
|
||||
auto rot = modelobject.instances.front()->get_rotation();
|
||||
// auto scaling = modelobject.instances.front()->get_scaling_factor();
|
||||
|
||||
// Transform3d tr;
|
||||
// tr.rotate(Eigen::AngleAxisd(rot(X), Vec3d::UnitX()) *
|
||||
// Eigen::AngleAxisd(rot(Y), Vec3d::UnitY()));
|
||||
|
||||
long i = 0;
|
||||
for(const Vec3f& msource : modelobject.sla_support_points) {
|
||||
Vec3d&& p = msource.cast<double>();
|
||||
// p = tr * p;
|
||||
ret.row(i++) = p;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double ray_mesh_intersect(const Vec3d& s,
|
||||
const Vec3d& dir,
|
||||
const EigenMesh3D& m);
|
||||
@ -1154,6 +1094,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
cfg.head_back_radius_mm,
|
||||
cfg.head_front_radius_mm,
|
||||
cfg.head_width_mm,
|
||||
cfg.head_penetration_mm,
|
||||
nmls.row(i), // dir
|
||||
head_pos.row(i) // displacement
|
||||
);
|
||||
@ -1521,6 +1462,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
Head base_head(cfg.head_back_radius_mm,
|
||||
cfg.head_front_radius_mm,
|
||||
cfg.head_width_mm,
|
||||
cfg.head_penetration_mm,
|
||||
{0.0, 0.0, 1.0},
|
||||
{headend(X), headend(Y), headend(Z) - gh});
|
||||
|
||||
@ -1719,10 +1661,10 @@ const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
|
||||
TriangleMesh mm;
|
||||
merged_mesh(mm);
|
||||
PoolConfig pcfg;
|
||||
// pcfg.min_wall_thickness_mm = min_wall_thickness_mm;
|
||||
// pcfg.min_wall_height_mm = min_wall_height_mm;
|
||||
// pcfg.max_merge_distance_mm = max_merge_distance_mm;
|
||||
// pcfg.edge_radius_mm = edge_radius_mm;
|
||||
pcfg.min_wall_thickness_mm = min_wall_thickness_mm;
|
||||
pcfg.min_wall_height_mm = min_wall_height_mm;
|
||||
pcfg.max_merge_distance_mm = max_merge_distance_mm;
|
||||
pcfg.edge_radius_mm = edge_radius_mm;
|
||||
return m_impl->create_pad(mm, baseplate, pcfg).tmesh;
|
||||
}
|
||||
|
||||
@ -1735,15 +1677,7 @@ double SLASupportTree::get_elevation() const
|
||||
{
|
||||
double ph = m_impl->pad().empty()? 0 :
|
||||
m_impl->pad().cfg.min_wall_height_mm/2.0;
|
||||
return -m_impl->ground_level + ph;
|
||||
}
|
||||
|
||||
SLASupportTree::SLASupportTree(const Model& model,
|
||||
const SupportConfig& cfg,
|
||||
const Controller& ctl):
|
||||
m_impl(new Impl()), m_ctl(ctl)
|
||||
{
|
||||
generate(support_points(model), to_eigenmesh(model), cfg, ctl);
|
||||
return m_elevation + ph;
|
||||
}
|
||||
|
||||
SLASupportTree::SLASupportTree(const PointSet &points,
|
||||
@ -1752,6 +1686,7 @@ SLASupportTree::SLASupportTree(const PointSet &points,
|
||||
const Controller &ctl):
|
||||
m_impl(new Impl()), m_ctl(ctl)
|
||||
{
|
||||
m_elevation = cfg.object_elevation_mm;
|
||||
m_impl->ground_level = emesh.ground_level - cfg.object_elevation_mm;
|
||||
generate(points, emesh, cfg, ctl);
|
||||
}
|
||||
@ -1767,66 +1702,5 @@ SLASupportTree &SLASupportTree::operator=(const SLASupportTree &c)
|
||||
|
||||
SLASupportTree::~SLASupportTree() {}
|
||||
|
||||
void add_sla_supports(Model &model,
|
||||
const SupportConfig &cfg,
|
||||
const Controller &ctl)
|
||||
{
|
||||
Benchmark bench;
|
||||
|
||||
bench.start();
|
||||
SLASupportTree _stree(model, cfg, ctl);
|
||||
bench.stop();
|
||||
|
||||
std::cout << "Support tree creation time: " << bench.getElapsedSec()
|
||||
<< " seconds" << std::endl;
|
||||
|
||||
bench.start();
|
||||
ModelObject* o = model.add_object();
|
||||
o->add_instance();
|
||||
|
||||
TriangleMesh streemsh;
|
||||
_stree.merged_mesh(streemsh);
|
||||
o->add_volume(streemsh);
|
||||
|
||||
bench.stop();
|
||||
std::cout << "support tree added to model in: " << bench.getElapsedSec()
|
||||
<< " seconds" << std::endl;
|
||||
|
||||
// TODO this would roughly be the code for the base pool
|
||||
ExPolygons plate;
|
||||
auto modelmesh = model.mesh();
|
||||
TriangleMesh poolmesh;
|
||||
sla::PoolConfig poolcfg;
|
||||
poolcfg.min_wall_height_mm = 1;
|
||||
poolcfg.edge_radius_mm = 0.1;
|
||||
poolcfg.min_wall_thickness_mm = 0.8;
|
||||
|
||||
bench.start();
|
||||
sla::base_plate(modelmesh, plate);
|
||||
bench.stop();
|
||||
|
||||
std::cout << "Base plate calculation time: " << bench.getElapsedSec()
|
||||
<< " seconds." << std::endl;
|
||||
|
||||
bench.start();
|
||||
sla::create_base_pool(plate, poolmesh, poolcfg);
|
||||
bench.stop();
|
||||
|
||||
std::cout << "Pool generation completed in " << bench.getElapsedSec()
|
||||
<< " second." << std::endl;
|
||||
|
||||
bench.start();
|
||||
poolmesh.translate(.0f, .0f, float(poolcfg.min_wall_height_mm / 2));
|
||||
o->add_volume(poolmesh);
|
||||
bench.stop();
|
||||
|
||||
// TODO: will cause incorrect placement of the model;
|
||||
// o->translate({0, 0, poolcfg.min_wall_height_mm / 2});
|
||||
|
||||
std::cout << "Added pool to model in " << bench.getElapsedSec()
|
||||
<< " seconds." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ struct SupportConfig {
|
||||
double head_front_radius_mm = 0.2;
|
||||
|
||||
// How much the pinhead has to penetrate the model surface
|
||||
double head_penetraiton = 0.2;
|
||||
double head_penetration_mm = 0.5;
|
||||
|
||||
// Radius of the back side of the 3d arrow.
|
||||
double head_back_radius_mm = 0.5;
|
||||
@ -90,34 +90,17 @@ struct EigenMesh3D {
|
||||
Eigen::MatrixXd V;
|
||||
Eigen::MatrixXi F;
|
||||
double ground_level = 0;
|
||||
|
||||
// igl crashes with the following data types:
|
||||
// Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> V;
|
||||
// Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> F;
|
||||
};
|
||||
|
||||
//using PointSet = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign>; //Eigen::MatrixXd;
|
||||
using PointSet = Eigen::MatrixXd;
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* TODO: May not be needed: */
|
||||
/* ************************************************************************** */
|
||||
|
||||
void create_head(TriangleMesh&, double r1_mm, double r2_mm, double width_mm);
|
||||
|
||||
/// Add support volumes to the model directly
|
||||
void add_sla_supports(Model& model, const SupportConfig& cfg = {},
|
||||
const Controller& ctl = {});
|
||||
|
||||
EigenMesh3D to_eigenmesh(const TriangleMesh& m);
|
||||
PointSet to_point_set(const std::vector<Vec3d>&);
|
||||
|
||||
|
||||
// obsolete, not used anymore
|
||||
EigenMesh3D to_eigenmesh(const Model& model);
|
||||
// needed for find best rotation
|
||||
EigenMesh3D to_eigenmesh(const ModelObject& model);
|
||||
PointSet support_points(const ModelObject& modelobject);
|
||||
PointSet support_points(const Model& model);
|
||||
|
||||
// Simple conversion of 'vector of points' to an Eigen matrix
|
||||
PointSet to_point_set(const std::vector<Vec3d>&);
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
@ -135,6 +118,9 @@ class SLASupportTree {
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
Controller m_ctl;
|
||||
|
||||
// the only value from config that is also needed after construction
|
||||
double m_elevation = 0;
|
||||
|
||||
Impl& get() { return *m_impl; }
|
||||
const Impl& get() const { return *m_impl; }
|
||||
|
||||
@ -149,11 +135,6 @@ class SLASupportTree {
|
||||
const Controller& ctl = {});
|
||||
public:
|
||||
|
||||
// Constructors will throw if the stop condition becomes true.
|
||||
SLASupportTree(const Model& model,
|
||||
const SupportConfig& cfg = {},
|
||||
const Controller& ctl = {});
|
||||
|
||||
SLASupportTree(const PointSet& pts,
|
||||
const EigenMesh3D& em,
|
||||
const SupportConfig& cfg = {},
|
||||
|
@ -85,7 +85,8 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
||||
// Temporary: just to have to correct layer height for the rasterization
|
||||
DynamicPrintConfig config(config_in);
|
||||
config.normalize();
|
||||
auto lh = config.opt<ConfigOptionFloat>("layer_height");
|
||||
m_material_config.initial_layer_height.set(
|
||||
config.opt<ConfigOptionFloat>("initial_layer_height"));
|
||||
|
||||
// Temporary quick fix, just invalidate everything.
|
||||
{
|
||||
@ -102,7 +103,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
||||
// Generate new SLAPrintObjects.
|
||||
for (ModelObject *model_object : m_model.objects) {
|
||||
auto po = new SLAPrintObject(this, model_object);
|
||||
po->m_config.layer_height.set(lh);
|
||||
|
||||
// po->m_config.layer_height.set(lh);
|
||||
po->m_config.apply(config, true);
|
||||
|
||||
m_objects.emplace_back(po);
|
||||
for (ModelInstance *oinst : model_object->instances) {
|
||||
Point tr = Point::new_scale(oinst->get_offset()(X),
|
||||
@ -126,6 +130,8 @@ void SLAPrint::process()
|
||||
// shortcut to initial layer height
|
||||
auto ilh = float(m_material_config.initial_layer_height.getFloat());
|
||||
|
||||
std::cout << "Initial layer height: " << m_material_config.initial_layer_height.getFloat() << std::endl;
|
||||
|
||||
// Slicing the model object. This method is oversimplified and needs to
|
||||
// be compared with the fff slicing algorithm for verification
|
||||
auto slice_model = [this, ilh](SLAPrintObject& po) {
|
||||
@ -137,8 +143,12 @@ void SLAPrint::process()
|
||||
|
||||
auto H = bb3d.max(Z) - bb3d.min(Z);
|
||||
auto gnd = float(bb3d.min(Z));
|
||||
|
||||
double elevation = po.m_config.support_object_elevation.getFloat();
|
||||
float ih = elevation > 0 ? lh : ilh;
|
||||
|
||||
std::vector<float> heights = {gnd};
|
||||
for(float h = gnd + ilh; h < gnd + H; h += lh) heights.emplace_back(h);
|
||||
for(float h = gnd + ih; h < gnd + H; h += lh) heights.emplace_back(h);
|
||||
|
||||
auto& layers = po.m_model_slices;
|
||||
slicer.slice(heights, &layers, [this](){
|
||||
@ -169,7 +179,17 @@ void SLAPrint::process()
|
||||
auto& emesh = po.m_supportdata->emesh;
|
||||
auto& pts = po.m_supportdata->support_points; // nowhere filled yet
|
||||
try {
|
||||
SupportConfig scfg; // TODO fill or replace with po.m_config
|
||||
sla::SupportConfig scfg;
|
||||
SLAPrintObjectConfig& c = po.m_config;
|
||||
|
||||
scfg.head_front_radius_mm = c.support_head_front_radius.getFloat();
|
||||
scfg.head_back_radius_mm = c.support_head_back_radius.getFloat();
|
||||
scfg.head_penetration_mm = c.support_head_penetration.getFloat();
|
||||
scfg.head_width_mm = c.support_head_width.getFloat();
|
||||
scfg.object_elevation_mm = c.support_object_elevation.getFloat();
|
||||
scfg.tilt = c.support_critical_angle.getFloat() * PI / 180.0 ;
|
||||
scfg.max_bridge_length_mm = c.support_max_bridge_length.getFloat();
|
||||
scfg.pillar_radius_mm = c.support_pillar_radius.getFloat();
|
||||
|
||||
sla::Controller ctl;
|
||||
ctl.statuscb = [this](unsigned st, const std::string& msg) {
|
||||
@ -207,9 +227,8 @@ void SLAPrint::process()
|
||||
double elevation = po.m_config.support_object_elevation.getFloat();
|
||||
|
||||
sla::ExPolygons bp;
|
||||
if(elevation < h/2)
|
||||
sla::base_plate(po.transformed_mesh(), bp,
|
||||
float(h/2), float(lh));
|
||||
if(elevation < h/2) sla::base_plate(po.transformed_mesh(), bp,
|
||||
float(h/2), float(lh));
|
||||
|
||||
po.m_supportdata->support_tree_ptr->add_pad(bp, wt, h, md, er);
|
||||
}
|
||||
@ -237,43 +256,59 @@ void SLAPrint::process()
|
||||
lref(std::cref(lyr)), copies(std::cref(cp)) {}
|
||||
};
|
||||
|
||||
using LevelID = long long;
|
||||
using LayerRefs = std::vector<LayerRef>;
|
||||
|
||||
// layers according to quantized height levels
|
||||
std::map<long long, LayerRefs> levels;
|
||||
std::map<LevelID, LayerRefs> levels;
|
||||
|
||||
auto sinitlh = LevelID(scale_(ilh));
|
||||
|
||||
// For all print objects, go through its initial layers and place them
|
||||
// into the layers hash
|
||||
for(SLAPrintObject *o : m_objects) {
|
||||
|
||||
double gndlvl = o->transformed_mesh().bounding_box().min(Z);
|
||||
double elevation = o->m_config.support_object_elevation.getFloat();
|
||||
|
||||
double lh = o->m_config.layer_height.getFloat();
|
||||
|
||||
// TODO: this juust misses the support layers with a slight offset...
|
||||
double ih = elevation > 0 ? lh : ilh;
|
||||
|
||||
auto sgl = LevelID(scale_(gndlvl));
|
||||
auto slh = LevelID(scale_(lh)); // scaled layer height
|
||||
auto sih = LevelID(scale_(ih));
|
||||
|
||||
SlicedModel & oslices = o->m_model_slices;
|
||||
for(int i = 0; i < oslices.size(); ++i) {
|
||||
int a = i == 0 ? 0 : 1;
|
||||
int b = i == 0 ? 0 : i - 1;
|
||||
|
||||
double h = gndlvl + ilh * a + b * lh;
|
||||
long long lyridx = static_cast<long long>(scale_(h));
|
||||
auto& lyrs = levels[lyridx]; // this initializes a new record
|
||||
LevelID h = sgl + sih * a + b * slh;
|
||||
|
||||
std::cout << "Model layer level: " << h << std::endl;
|
||||
|
||||
auto& lyrs = levels[h]; // this initializes a new record
|
||||
lyrs.emplace_back(oslices[i], o->m_instances);
|
||||
}
|
||||
|
||||
if(o->m_supportdata) { // deal with the support slices if present
|
||||
auto& sslices = o->m_supportdata->support_slices;
|
||||
double el = o->m_config.support_object_elevation.getFloat();
|
||||
//TODO: remove next line:
|
||||
el = SupportConfig().object_elevation_mm;
|
||||
|
||||
// Supports start below the ground level.
|
||||
// Counting the pad height as well
|
||||
double el = o->get_elevation();
|
||||
auto sel = LevelID(scale_(el));
|
||||
|
||||
for(int i = 0; i < sslices.size(); ++i) {
|
||||
int a = i == 0 ? 0 : 1;
|
||||
int b = i == 0 ? 0 : i - 1;
|
||||
|
||||
double h = gndlvl - el + ilh * a + b * lh;
|
||||
LevelID h = sgl - sel + sinitlh * a + b * slh;
|
||||
std::cout << "Support layer level: " << h << std::endl;
|
||||
|
||||
long long lyridx = static_cast<long long>(scale_(h));
|
||||
auto& lyrs = levels[lyridx];
|
||||
auto& lyrs = levels[h];
|
||||
lyrs.emplace_back(sslices[i], o->m_instances);
|
||||
}
|
||||
}
|
||||
@ -437,6 +472,26 @@ SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
|
||||
|
||||
SLAPrintObject::~SLAPrintObject() {}
|
||||
|
||||
double SLAPrintObject::get_elevation() const {
|
||||
return m_supportdata && m_supportdata->support_tree_ptr?
|
||||
m_supportdata->support_tree_ptr->get_elevation() :
|
||||
0;
|
||||
}
|
||||
|
||||
//const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
||||
//{
|
||||
// // I don't want to return a copy but the points may not exist, so ...
|
||||
// static const std::vector<ExPolygons> dummy_empty;
|
||||
|
||||
// if(!m_supportdata) return dummy_empty;
|
||||
// return m_supportdata->support_slices;
|
||||
//}
|
||||
|
||||
//const std::vector<ExPolygons> &SLAPrintObject::get_model_slices() const
|
||||
//{
|
||||
// return m_model_slices;
|
||||
//}
|
||||
|
||||
bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const
|
||||
{
|
||||
switch (step) {
|
||||
|
@ -63,6 +63,15 @@ public:
|
||||
|
||||
std::vector<Vec3d> transformed_support_points() const;
|
||||
|
||||
// Get the needed Z elevation for the model geometry if supports should be
|
||||
// displayed. This Z offset should also be applied to the support
|
||||
// geometries. Note that this is not the same as the value stored in config
|
||||
// as the pad height also needs to be considered.
|
||||
double get_elevation() const;
|
||||
|
||||
// const std::vector<ExPolygons>& get_support_slices() const;
|
||||
// const std::vector<ExPolygons>& get_model_slices() const;
|
||||
|
||||
// I refuse to grantee copying (Tamas)
|
||||
SLAPrintObject(const SLAPrintObject&) = delete;
|
||||
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
|
||||
@ -84,6 +93,7 @@ protected:
|
||||
bool invalidate_step(SLAPrintObjectStep step);
|
||||
|
||||
private:
|
||||
|
||||
// Object specific configuration, pulled from the configuration layer.
|
||||
SLAPrintObjectConfig m_config;
|
||||
// Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
|
||||
|
@ -68,6 +68,8 @@ namespace PerlUtils {
|
||||
extern std::string path_to_parent_path(const char *src);
|
||||
};
|
||||
|
||||
std::string string_printf(const char *format, ...);
|
||||
|
||||
// Timestamp formatted for header_slic3r_generated().
|
||||
extern std::string timestamp_str();
|
||||
// Standard "generated by Slic3r version xxx timestamp xxx" header string,
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <locale>
|
||||
#include <ctime>
|
||||
#include <cstdarg>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
@ -297,6 +299,25 @@ namespace PerlUtils {
|
||||
std::string path_to_parent_path(const char *src) { return boost::filesystem::path(src).parent_path().string(); }
|
||||
};
|
||||
|
||||
|
||||
std::string string_printf(const char *format, ...)
|
||||
{
|
||||
va_list args1;
|
||||
va_start(args1, format);
|
||||
va_list args2;
|
||||
va_copy(args2, args1);
|
||||
|
||||
size_t needed_size = ::vsnprintf(nullptr, 0, format, args1) + 1;
|
||||
va_end(args1);
|
||||
|
||||
std::string res(needed_size, '\0');
|
||||
::vsnprintf(&res.front(), res.size(), format, args2);
|
||||
va_end(args2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::string timestamp_str()
|
||||
{
|
||||
const auto now = boost::posix_time::second_clock::local_time();
|
||||
|
@ -192,20 +192,21 @@ int main(int argc, char **argv)
|
||||
model.repair();
|
||||
model.translate(0, 0, - model.bounding_box().min(2));
|
||||
if (! model.objects.empty()) {
|
||||
Model out;
|
||||
model.objects.front()->cut(cli_config.cut, &out);
|
||||
ModelObject &upper = *out.objects[0];
|
||||
ModelObject &lower = *out.objects[1];
|
||||
// Use the input name and trim off the extension.
|
||||
std::string outfile = cli_config.output.value;
|
||||
if (outfile.empty())
|
||||
outfile = model.objects.front()->input_file;
|
||||
outfile = outfile.substr(0, outfile.find_last_of('.'));
|
||||
std::cerr << outfile << "\n";
|
||||
if (upper.facets_count() > 0)
|
||||
upper.mesh().write_binary((outfile + "_upper.stl").c_str());
|
||||
if (lower.facets_count() > 0)
|
||||
lower.mesh().write_binary((outfile + "_lower.stl").c_str());
|
||||
// XXX
|
||||
// Model out;
|
||||
// model.objects.front()->cut(cli_config.cut, &out);
|
||||
// ModelObject &upper = *out.objects[0];
|
||||
// ModelObject &lower = *out.objects[1];
|
||||
// // Use the input name and trim off the extension.
|
||||
// std::string outfile = cli_config.output.value;
|
||||
// if (outfile.empty())
|
||||
// outfile = model.objects.front()->input_file;
|
||||
// outfile = outfile.substr(0, outfile.find_last_of('.'));
|
||||
// std::cerr << outfile << "\n";
|
||||
// if (upper.facets_count() > 0)
|
||||
// upper.mesh().write_binary((outfile + "_upper.stl").c_str());
|
||||
// if (lower.facets_count() > 0)
|
||||
// lower.mesh().write_binary((outfile + "_lower.stl").c_str());
|
||||
}
|
||||
} else if (cli_config.slice) {
|
||||
std::string outfile = cli_config.output.value;
|
||||
|
@ -1930,11 +1930,6 @@ void _3DScene::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape)
|
||||
s_canvas_mgr.set_bed_shape(canvas, shape);
|
||||
}
|
||||
|
||||
void _3DScene::set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons)
|
||||
{
|
||||
s_canvas_mgr.set_cutting_plane(canvas, z, polygons);
|
||||
}
|
||||
|
||||
void _3DScene::set_color_by(wxGLCanvas* canvas, const std::string& value)
|
||||
{
|
||||
s_canvas_mgr.set_color_by(canvas, value);
|
||||
|
@ -602,8 +602,6 @@ public:
|
||||
|
||||
static void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
|
||||
|
||||
static void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
|
||||
|
||||
static void set_color_by(wxGLCanvas* canvas, const std::string& value);
|
||||
|
||||
static bool is_layers_editing_enabled(wxGLCanvas* canvas);
|
||||
|
@ -241,6 +241,7 @@ void AppConfig::reset_selections()
|
||||
if (it != m_storage.end()) {
|
||||
it->second.erase("print");
|
||||
it->second.erase("filament");
|
||||
it->second.erase("sla_print");
|
||||
it->second.erase("sla_material");
|
||||
it->second.erase("printer");
|
||||
m_dirty = true;
|
||||
|
@ -641,70 +641,6 @@ void GLCanvas3D::Axes::render(bool depth_test) const
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
GLCanvas3D::CuttingPlane::CuttingPlane()
|
||||
: m_z(-1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
bool GLCanvas3D::CuttingPlane::set(float z, const ExPolygons& polygons)
|
||||
{
|
||||
m_z = z;
|
||||
|
||||
// grow slices in order to display them better
|
||||
ExPolygons expolygons = offset_ex(polygons, (float)scale_(0.1));
|
||||
Lines lines = to_lines(expolygons);
|
||||
return m_lines.set_from_lines(lines, m_z);
|
||||
}
|
||||
|
||||
void GLCanvas3D::CuttingPlane::render(const BoundingBoxf3& bb) const
|
||||
{
|
||||
_render_plane(bb);
|
||||
_render_contour();
|
||||
}
|
||||
|
||||
void GLCanvas3D::CuttingPlane::_render_plane(const BoundingBoxf3& bb) const
|
||||
{
|
||||
if (m_z >= 0.0f)
|
||||
{
|
||||
::glDisable(GL_CULL_FACE);
|
||||
::glEnable(GL_BLEND);
|
||||
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
float margin = 20.0f;
|
||||
float min_x = bb.min(0) - margin;
|
||||
float max_x = bb.max(0) + margin;
|
||||
float min_y = bb.min(1) - margin;
|
||||
float max_y = bb.max(1) + margin;
|
||||
|
||||
::glBegin(GL_QUADS);
|
||||
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
|
||||
::glVertex3f(min_x, min_y, m_z);
|
||||
::glVertex3f(max_x, min_y, m_z);
|
||||
::glVertex3f(max_x, max_y, m_z);
|
||||
::glVertex3f(min_x, max_y, m_z);
|
||||
::glEnd();
|
||||
|
||||
::glEnable(GL_CULL_FACE);
|
||||
::glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::CuttingPlane::_render_contour() const
|
||||
{
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (m_z >= 0.0f)
|
||||
{
|
||||
unsigned int lines_vcount = m_lines.get_vertices_count();
|
||||
|
||||
::glLineWidth(2.0f);
|
||||
::glColor3f(0.0f, 0.0f, 0.0f);
|
||||
::glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)m_lines.get_vertices());
|
||||
::glDrawArrays(GL_LINES, 0, (GLsizei)lines_vcount);
|
||||
}
|
||||
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
GLCanvas3D::Shader::Shader()
|
||||
: m_shader(nullptr)
|
||||
@ -2420,6 +2356,17 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
|
||||
|
||||
gizmo = new GLGizmoCut(parent);
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
if (!gizmo->init()) {
|
||||
_reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Cut, gizmo));
|
||||
|
||||
gizmo = new GLGizmoSlaSupports(parent);
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
@ -2431,7 +2378,6 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(SlaSupports, gizmo));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2457,7 +2403,7 @@ std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, con
|
||||
float top_y = 0.5f * (cnv_h - height);
|
||||
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if (it->second == nullptr)
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
float tex_size = (float)it->second->get_textures_size() * OverlayTexturesScale;
|
||||
@ -2487,7 +2433,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec
|
||||
float top_y = 0.5f * (cnv_h - height);
|
||||
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if (it->second == nullptr)
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
float tex_size = (float)it->second->get_textures_size() * OverlayTexturesScale;
|
||||
@ -2585,7 +2531,7 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const
|
||||
float top_y = 0.5f * (cnv_h - height);
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if (it->second == nullptr)
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
float tex_size = (float)it->second->get_textures_size() * OverlayTexturesScale;
|
||||
@ -2804,6 +2750,13 @@ void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas) const
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::create_external_gizmo_widgets(wxWindow *parent)
|
||||
{
|
||||
for (auto &entry : m_gizmos) {
|
||||
entry.second->create_external_gizmo_widgets(parent);
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::_reset()
|
||||
{
|
||||
for (GizmosMap::value_type& gizmo : m_gizmos)
|
||||
@ -2830,8 +2783,9 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas) const
|
||||
float scaled_gap_y = OverlayGapY * inv_zoom;
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if (it->first == SlaSupports && wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
float tex_size = (float)it->second->get_textures_size() * OverlayTexturesScale * inv_zoom;
|
||||
GLTexture::render_texture(it->second->get_texture_id(), top_x, top_x + tex_size, top_y - tex_size, top_y);
|
||||
top_y -= (tex_size + scaled_gap_y);
|
||||
@ -3206,6 +3160,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
|
||||
, m_regenerate_volumes(true)
|
||||
, m_color_by("volume")
|
||||
, m_reload_delayed(false)
|
||||
, m_external_gizmo_widgets_parent(nullptr)
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
{
|
||||
@ -3307,8 +3262,17 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
|
||||
if (!m_volumes.empty())
|
||||
m_volumes.finalize_geometry(m_use_VBOs);
|
||||
|
||||
if (m_gizmos.is_enabled() && !m_gizmos.init(*this))
|
||||
return false;
|
||||
if (m_gizmos.is_enabled()) {
|
||||
if (! m_gizmos.init(*this)) {
|
||||
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_external_gizmo_widgets_parent != nullptr) {
|
||||
m_gizmos.create_external_gizmo_widgets(m_external_gizmo_widgets_parent);
|
||||
m_canvas->GetParent()->Layout();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_init_toolbar())
|
||||
return false;
|
||||
@ -3411,11 +3375,6 @@ void GLCanvas3D::set_axes_length(float length)
|
||||
m_axes.length = length;
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_cutting_plane(float z, const ExPolygons& polygons)
|
||||
{
|
||||
m_cutting_plane.set(z, polygons);
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_color_by(const std::string& value)
|
||||
{
|
||||
m_color_by = value;
|
||||
@ -3669,7 +3628,6 @@ void GLCanvas3D::render()
|
||||
#endif // ENABLE_GIZMOS_ON_TOP
|
||||
|
||||
_render_current_gizmo();
|
||||
_render_cutting_plane();
|
||||
#if ENABLE_SHOW_CAMERA_TARGET
|
||||
_render_camera_target();
|
||||
#endif // ENABLE_SHOW_CAMERA_TARGET
|
||||
@ -3949,9 +3907,25 @@ void GLCanvas3D::reload_scene(bool force)
|
||||
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, -1, instance_idx);
|
||||
}
|
||||
}
|
||||
for (size_t istep = 0; istep < sla_steps.size(); ++ istep)
|
||||
if (! instances[istep].empty())
|
||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_use_VBOs && m_initialized);
|
||||
|
||||
// stores the current volumes count
|
||||
size_t volumes_count = m_volumes.volumes.size();
|
||||
|
||||
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
||||
if (!instances[istep].empty())
|
||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_use_VBOs && m_initialized);
|
||||
|
||||
if (volumes_count != m_volumes.volumes.size())
|
||||
{
|
||||
// If any volume has been added
|
||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||
Vec3d shift_z(0.0, 0.0, print_object->get_elevation());
|
||||
for (GLVolume* volume : m_volumes.volumes)
|
||||
{
|
||||
if (volume->object_idx() == object_idx)
|
||||
volume->set_instance_offset(volume->get_instance_offset() + shift_z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4748,6 +4722,11 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_external_gizmo_widgets_parent(wxWindow *parent)
|
||||
{
|
||||
m_external_gizmo_widgets_parent = parent;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_is_shown_on_screen() const
|
||||
{
|
||||
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
||||
@ -4848,14 +4827,6 @@ bool GLCanvas3D::_init_toolbar()
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
item.name = "cut";
|
||||
item.tooltip = GUI::L_str("Cut...");
|
||||
item.sprite_id = 7;
|
||||
item.is_toggable = false;
|
||||
item.action_event = EVT_GLTOOLBAR_CUT;
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
if (!m_toolbar.add_separator())
|
||||
return false;
|
||||
|
||||
@ -5254,11 +5225,6 @@ void GLCanvas3D::_render_selection() const
|
||||
m_selection.render();
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_cutting_plane() const
|
||||
{
|
||||
m_cutting_plane.render(volumes_bounding_box());
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_warning_texture() const
|
||||
{
|
||||
if (!m_warning_texture_enabled)
|
||||
|
@ -16,6 +16,7 @@ class wxKeyEvent;
|
||||
class wxMouseEvent;
|
||||
class wxTimerEvent;
|
||||
class wxPaintEvent;
|
||||
class wxGLCanvas;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
@ -219,23 +220,6 @@ class GLCanvas3D
|
||||
void render(bool depth_test) const;
|
||||
};
|
||||
|
||||
class CuttingPlane
|
||||
{
|
||||
float m_z;
|
||||
GeometryBuffer m_lines;
|
||||
|
||||
public:
|
||||
CuttingPlane();
|
||||
|
||||
bool set(float z, const ExPolygons& polygons);
|
||||
|
||||
void render(const BoundingBoxf3& bb) const;
|
||||
|
||||
private:
|
||||
void _render_plane(const BoundingBoxf3& bb) const;
|
||||
void _render_contour() const;
|
||||
};
|
||||
|
||||
class Shader
|
||||
{
|
||||
GLShader* m_shader;
|
||||
@ -479,6 +463,8 @@ public:
|
||||
Selection();
|
||||
|
||||
void set_volumes(GLVolumePtrs* volumes);
|
||||
|
||||
Model* get_model() const { return m_model; }
|
||||
void set_model(Model* model);
|
||||
|
||||
EMode get_mode() const { return m_mode; }
|
||||
@ -582,6 +568,7 @@ private:
|
||||
Scale,
|
||||
Rotate,
|
||||
Flatten,
|
||||
Cut,
|
||||
SlaSupports,
|
||||
Num_Types
|
||||
};
|
||||
@ -645,6 +632,8 @@ private:
|
||||
|
||||
void render_overlay(const GLCanvas3D& canvas) const;
|
||||
|
||||
void create_external_gizmo_widgets(wxWindow *parent);
|
||||
|
||||
private:
|
||||
void _reset();
|
||||
|
||||
@ -701,7 +690,6 @@ private:
|
||||
Camera m_camera;
|
||||
Bed m_bed;
|
||||
Axes m_axes;
|
||||
CuttingPlane m_cutting_plane;
|
||||
LayersEditing m_layers_editing;
|
||||
Shader m_shader;
|
||||
Mouse m_mouse;
|
||||
@ -738,6 +726,8 @@ private:
|
||||
|
||||
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
|
||||
|
||||
wxWindow *m_external_gizmo_widgets_parent;
|
||||
|
||||
void post_event(wxEvent &&event);
|
||||
void viewport_changed();
|
||||
|
||||
@ -779,8 +769,6 @@ public:
|
||||
|
||||
void set_axes_length(float length);
|
||||
|
||||
void set_cutting_plane(float z, const ExPolygons& polygons);
|
||||
|
||||
void set_color_by(const std::string& value);
|
||||
|
||||
float get_camera_zoom() const;
|
||||
@ -856,6 +844,8 @@ public:
|
||||
|
||||
void set_tooltip(const std::string& tooltip) const;
|
||||
|
||||
void set_external_gizmo_widgets_parent(wxWindow *parent);
|
||||
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
void _force_zoom_to_bed();
|
||||
@ -882,7 +872,6 @@ private:
|
||||
void _render_axes(bool depth_test) const;
|
||||
void _render_objects() const;
|
||||
void _render_selection() const;
|
||||
void _render_cutting_plane() const;
|
||||
void _render_warning_texture() const;
|
||||
void _render_legend_texture() const;
|
||||
void _render_layer_editing_overlay() const;
|
||||
|
@ -293,13 +293,6 @@ void GLCanvas3DManager::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape)
|
||||
it->second->set_bed_shape(shape);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_cutting_plane(z, polygons);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_color_by(wxGLCanvas* canvas, const std::string& value)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
|
@ -99,8 +99,6 @@ public:
|
||||
|
||||
void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
|
||||
|
||||
void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
|
||||
|
||||
void set_color_by(wxGLCanvas* canvas, const std::string& value);
|
||||
|
||||
bool is_layers_editing_enabled(wxGLCanvas* canvas) const;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "GLGizmo.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
@ -8,15 +8,29 @@
|
||||
#include "PresetBundle.hpp"
|
||||
|
||||
#include <Eigen/Dense>
|
||||
#include "../../libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
|
||||
#include <igl/unproject_onto_mesh.h>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <SLA/SLASupportTree.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
// TODO: Display tooltips quicker on Linux
|
||||
|
||||
static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f };
|
||||
static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f };
|
||||
@ -252,6 +266,8 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoBase::create_external_gizmo_widgets(wxWindow *parent) {}
|
||||
|
||||
void GLGizmoBase::set_tooltip(const std::string& tooltip) const
|
||||
{
|
||||
m_parent.set_tooltip(tooltip);
|
||||
@ -259,9 +275,7 @@ void GLGizmoBase::set_tooltip(const std::string& tooltip) const
|
||||
|
||||
std::string GLGizmoBase::format(float value, unsigned int decimals) const
|
||||
{
|
||||
char buf[1024];
|
||||
::sprintf(buf, "%.*f", decimals, value);
|
||||
return buf;
|
||||
return Slic3r::string_printf("%.*f", decimals, value);
|
||||
}
|
||||
|
||||
const float GLGizmoRotate::Offset = 5.0f;
|
||||
@ -1765,10 +1779,247 @@ bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection)
|
||||
return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA);
|
||||
}
|
||||
|
||||
bool GLGizmoSlaSupports::on_is_selectable() const
|
||||
{
|
||||
return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA);
|
||||
}
|
||||
|
||||
std::string GLGizmoSlaSupports::on_get_name() const
|
||||
{
|
||||
return L("SLA Support Points");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// GLGizmoCut
|
||||
|
||||
class GLGizmoCutPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
GLGizmoCutPanel(wxWindow *parent);
|
||||
|
||||
void display(bool display);
|
||||
private:
|
||||
bool m_active;
|
||||
wxCheckBox *m_cb_rotate;
|
||||
wxButton *m_btn_cut;
|
||||
wxButton *m_btn_cancel;
|
||||
};
|
||||
|
||||
GLGizmoCutPanel::GLGizmoCutPanel(wxWindow *parent)
|
||||
: wxPanel(parent)
|
||||
, m_active(false)
|
||||
, m_cb_rotate(new wxCheckBox(this, wxID_ANY, _(L("Rotate lower part upwards"))))
|
||||
, m_btn_cut(new wxButton(this, wxID_OK, _(L("Perform cut"))))
|
||||
, m_btn_cancel(new wxButton(this, wxID_CANCEL, _(L("Cancel"))))
|
||||
{
|
||||
enum { MARGIN = 5 };
|
||||
|
||||
auto *sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto *label = new wxStaticText(this, wxID_ANY, _(L("Cut object:")));
|
||||
sizer->Add(label, 0, wxALL | wxALIGN_CENTER, MARGIN);
|
||||
sizer->Add(m_cb_rotate, 0, wxALL | wxALIGN_CENTER, MARGIN);
|
||||
sizer->AddStretchSpacer();
|
||||
sizer->Add(m_btn_cut, 0, wxALL | wxALIGN_CENTER, MARGIN);
|
||||
sizer->Add(m_btn_cancel, 0, wxALL | wxALIGN_CENTER, MARGIN);
|
||||
|
||||
SetSizer(sizer);
|
||||
}
|
||||
|
||||
void GLGizmoCutPanel::display(bool display)
|
||||
{
|
||||
Show(display);
|
||||
GetParent()->Layout();
|
||||
}
|
||||
|
||||
|
||||
const double GLGizmoCut::Offset = 10.0;
|
||||
const double GLGizmoCut::Margin = 20.0;
|
||||
const std::array<float, 3> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 };
|
||||
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
, m_cut_z(0.0)
|
||||
, m_panel(nullptr)
|
||||
{}
|
||||
|
||||
void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent)
|
||||
{
|
||||
wxASSERT(m_panel == nullptr);
|
||||
|
||||
m_panel = new GLGizmoCutPanel(parent);
|
||||
parent->GetSizer()->Add(m_panel, 0, wxEXPAND);
|
||||
|
||||
parent->Layout();
|
||||
parent->Fit();
|
||||
auto prev_heigh = parent->GetMinSize().GetHeight();
|
||||
parent->SetMinSize(wxSize(-1, std::max(prev_heigh, m_panel->GetSize().GetHeight())));
|
||||
|
||||
m_panel->Hide();
|
||||
m_panel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
perform_cut();
|
||||
}, wxID_OK);
|
||||
}
|
||||
|
||||
bool GLGizmoCut::on_init()
|
||||
{
|
||||
// TODO: icon
|
||||
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "cut_off.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "cut_hover.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "cut_on.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_grabbers.emplace_back();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GLGizmoCut::on_get_name() const
|
||||
{
|
||||
return L("Cut");
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_set_state()
|
||||
{
|
||||
// Reset m_cut_z on gizmo activation
|
||||
if (get_state() == On) {
|
||||
m_cut_z = 0.0;
|
||||
}
|
||||
|
||||
// Display or hide the extra panel
|
||||
if (m_panel != nullptr) {
|
||||
m_panel->display(get_state() == On);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const
|
||||
{
|
||||
return selection.is_single_full_instance() && !selection.is_wipe_tower();
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
if (m_hover_id == -1) { return; }
|
||||
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
m_start_z = m_cut_z;
|
||||
m_max_z = box.size()(2) / 2.0;
|
||||
m_drag_pos = m_grabbers[m_hover_id].center;
|
||||
m_drag_center = box.center();
|
||||
m_drag_center(2) += m_cut_z;
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_update(const UpdateData& data)
|
||||
{
|
||||
if (m_hover_id != -1) {
|
||||
// Clamp the plane to the object's bounding box
|
||||
const double new_z = m_start_z + calc_projection(data.mouse_ray);
|
||||
m_cut_z = std::max(-m_max_z, std::min(m_max_z, new_z));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const
|
||||
{
|
||||
if (m_grabbers[0].dragging) {
|
||||
set_tooltip("Z: " + format(m_cut_z, 2));
|
||||
}
|
||||
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
Vec3d plane_center = box.center();
|
||||
plane_center(2) += m_cut_z;
|
||||
|
||||
const float min_x = box.min(0) - Margin;
|
||||
const float max_x = box.max(0) + Margin;
|
||||
const float min_y = box.min(1) - Margin;
|
||||
const float max_y = box.max(1) + Margin;
|
||||
::glEnable(GL_DEPTH_TEST);
|
||||
::glDisable(GL_CULL_FACE);
|
||||
::glEnable(GL_BLEND);
|
||||
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Draw the cutting plane
|
||||
::glBegin(GL_QUADS);
|
||||
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
|
||||
::glVertex3f(min_x, min_y, plane_center(2));
|
||||
::glVertex3f(max_x, min_y, plane_center(2));
|
||||
::glVertex3f(max_x, max_y, plane_center(2));
|
||||
::glVertex3f(min_x, max_y, plane_center(2));
|
||||
::glEnd();
|
||||
|
||||
::glEnable(GL_CULL_FACE);
|
||||
::glDisable(GL_BLEND);
|
||||
|
||||
// TODO: draw cut part contour?
|
||||
|
||||
// Draw the grabber and the connecting line
|
||||
m_grabbers[0].center = plane_center;
|
||||
m_grabbers[0].center(2) = plane_center(2) + Offset;
|
||||
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f);
|
||||
::glColor3f(1.0, 1.0, 0.0);
|
||||
::glBegin(GL_LINES);
|
||||
::glVertex3dv(plane_center.data());
|
||||
::glVertex3dv(m_grabbers[0].center.data());
|
||||
::glEnd();
|
||||
|
||||
std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_grabbers[0].color);
|
||||
m_grabbers[0].render(m_hover_id == 0, box.max_size());
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const
|
||||
{
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
render_grabbers_for_picking(selection.get_bounding_box());
|
||||
}
|
||||
|
||||
void GLGizmoCut::perform_cut()
|
||||
{
|
||||
const auto &selection = m_parent.get_selection();
|
||||
|
||||
const auto instance_idx = selection.get_instance_idx();
|
||||
const auto object_idx = selection.get_object_idx();
|
||||
|
||||
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
|
||||
|
||||
wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z);
|
||||
}
|
||||
|
||||
double GLGizmoCut::calc_projection(const Linef3& mouse_ray) const
|
||||
{
|
||||
double projection = 0.0;
|
||||
|
||||
const Vec3d starting_vec = m_drag_pos - m_drag_center;
|
||||
const double len_starting_vec = starting_vec.norm();
|
||||
if (len_starting_vec != 0.0)
|
||||
{
|
||||
Vec3d mouse_dir = mouse_ray.unit_vector();
|
||||
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
||||
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
|
||||
// in our case plane normal and ray direction are the same (orthogonal view)
|
||||
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
|
||||
Vec3d inters = mouse_ray.a + (m_drag_pos - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
|
||||
// vector from the starting position to the found intersection
|
||||
Vec3d inters_vec = inters - m_drag_pos;
|
||||
|
||||
// finds projection of the vector along the staring direction
|
||||
projection = inters_vec.dot(starting_vec.normalized());
|
||||
}
|
||||
return projection;
|
||||
}
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
@ -6,7 +6,13 @@
|
||||
#include "../../libslic3r/Point.hpp"
|
||||
#include "../../libslic3r/BoundingBox.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
|
||||
class wxWindow;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -95,6 +101,7 @@ public:
|
||||
void set_state(EState state) { m_state = state; on_set_state(); }
|
||||
|
||||
bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); }
|
||||
bool is_selectable() const { return on_is_selectable(); }
|
||||
|
||||
unsigned int get_texture_id() const { return m_textures[m_state].get_id(); }
|
||||
int get_textures_size() const { return m_textures[Off].get_width(); }
|
||||
@ -120,12 +127,15 @@ public:
|
||||
void render(const GLCanvas3D::Selection& selection) const { on_render(selection); }
|
||||
void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); }
|
||||
|
||||
virtual void create_external_gizmo_widgets(wxWindow *parent);
|
||||
|
||||
protected:
|
||||
virtual bool on_init() = 0;
|
||||
virtual std::string on_get_name() const = 0;
|
||||
virtual void on_set_state() {}
|
||||
virtual void on_set_hover_id() {}
|
||||
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; }
|
||||
virtual bool on_is_selectable() const { return true; }
|
||||
virtual void on_enable_grabber(unsigned int id) {}
|
||||
virtual void on_disable_grabber(unsigned int id) {}
|
||||
virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {}
|
||||
@ -446,10 +456,48 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
std::string on_get_name() const override;
|
||||
bool on_is_activable(const GLCanvas3D::Selection& selection) const override;
|
||||
virtual std::string on_get_name() const;
|
||||
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
|
||||
virtual bool on_is_selectable() const;
|
||||
};
|
||||
|
||||
|
||||
class GLGizmoCutPanel;
|
||||
|
||||
class GLGizmoCut : public GLGizmoBase
|
||||
{
|
||||
static const double Offset;
|
||||
static const double Margin;
|
||||
static const std::array<float, 3> GrabberColor;
|
||||
|
||||
double m_cut_z;
|
||||
double m_start_z;
|
||||
double m_max_z;
|
||||
Vec3d m_drag_pos;
|
||||
Vec3d m_drag_center;
|
||||
GLGizmoCutPanel *m_panel;
|
||||
|
||||
public:
|
||||
explicit GLGizmoCut(GLCanvas3D& parent);
|
||||
|
||||
virtual void create_external_gizmo_widgets(wxWindow *parent);
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
virtual std::string on_get_name() const;
|
||||
virtual void on_set_state();
|
||||
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
|
||||
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
|
||||
virtual void on_update(const UpdateData& data);
|
||||
virtual void on_render(const GLCanvas3D::Selection& selection) const;
|
||||
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
|
||||
|
||||
private:
|
||||
void perform_cut();
|
||||
double calc_projection(const Linef3& mouse_ray) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -24,7 +24,6 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
|
||||
|
||||
|
||||
|
@ -24,7 +24,6 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
|
||||
|
||||
class GLToolbarItem
|
||||
|
@ -1123,7 +1123,8 @@ void ObjectList::add_object_to_list(size_t obj_idx)
|
||||
m_objects_model->AddVolumeChild(item,
|
||||
model_object->volumes[id]->name,
|
||||
ModelVolume::MODEL_PART,
|
||||
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
|
||||
!model_object->volumes[id]->config.has("extruder") ? 0 :
|
||||
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
|
||||
false);
|
||||
Expand(item);
|
||||
}
|
||||
|
@ -15,6 +15,18 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
wxTopLevelWindow* find_toplevel_parent(wxWindow *window)
|
||||
{
|
||||
for (; window != nullptr; window = window->GetParent()) {
|
||||
if (window->IsTopLevel()) {
|
||||
return dynamic_cast<wxTopLevelWindow*>(window);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
|
||||
: wxPanel(parent, wxID_ANY)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/panel.h>
|
||||
@ -19,6 +20,48 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
|
||||
|
||||
|
||||
class EventGuard
|
||||
{
|
||||
public:
|
||||
EventGuard() {}
|
||||
EventGuard(const EventGuard&) = delete;
|
||||
EventGuard(EventGuard &&other) : unbinder(std::move(other.unbinder)) {}
|
||||
|
||||
~EventGuard() {
|
||||
if (unbinder) {
|
||||
unbinder(false);
|
||||
}
|
||||
}
|
||||
|
||||
template<class EvTag, class Fun> void bind(wxEvtHandler *emitter, const EvTag &type, Fun fun)
|
||||
{
|
||||
// This is a way to type-erase both the event type as well as the handler:
|
||||
|
||||
unbinder = std::move([=](bool bind) {
|
||||
if (bind) {
|
||||
emitter->Bind(type, fun);
|
||||
} else {
|
||||
emitter->Unbind(type, fun);
|
||||
}
|
||||
});
|
||||
|
||||
unbinder(true);
|
||||
}
|
||||
|
||||
EventGuard& operator=(const EventGuard&) = delete;
|
||||
EventGuard& operator=(EventGuard &&other)
|
||||
{
|
||||
unbinder.swap(other.unbinder);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
std::function<void(bool)> unbinder;
|
||||
};
|
||||
|
||||
|
||||
class CheckboxFileDialog : public wxFileDialog
|
||||
{
|
||||
public:
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <wx/menu.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include "Tab.hpp"
|
||||
@ -100,7 +101,6 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
||||
});
|
||||
|
||||
update_ui_from_settings();
|
||||
return;
|
||||
}
|
||||
|
||||
void MainFrame::init_tabpanel()
|
||||
@ -109,20 +109,15 @@ void MainFrame::init_tabpanel()
|
||||
|
||||
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&) {
|
||||
auto panel = m_tabpanel->GetCurrentPage();
|
||||
// panel->OnActivate(); if panel->can('OnActivate');
|
||||
|
||||
if (panel == nullptr)
|
||||
return;
|
||||
|
||||
for (auto& tab_name : { "print", "filament", "printer" }) {
|
||||
if (tab_name == panel->GetName()) {
|
||||
// On GTK, the wxEVT_NOTEBOOK_PAGE_CHANGED event is triggered
|
||||
// before the MainFrame is fully set up.
|
||||
auto it = m_options_tabs.find(tab_name);
|
||||
assert(it != m_options_tabs.end());
|
||||
if (it != m_options_tabs.end())
|
||||
it->second->OnActivate();
|
||||
}
|
||||
auto& tabs_list = wxGetApp().tabs_list;
|
||||
if (find(tabs_list.begin(), tabs_list.end(), panel) != tabs_list.end()) {
|
||||
// On GTK, the wxEVT_NOTEBOOK_PAGE_CHANGED event is triggered
|
||||
// before the MainFrame is fully set up.
|
||||
static_cast<Tab*>(panel)->OnActivate();
|
||||
}
|
||||
});
|
||||
|
||||
@ -140,9 +135,6 @@ void MainFrame::init_tabpanel()
|
||||
Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this);
|
||||
|
||||
create_preset_tabs();
|
||||
std::vector<std::string> tab_names = { "print", "filament", "sla_material", "printer" };
|
||||
for (auto tab_name : tab_names)
|
||||
m_options_tabs[tab_name] = get_preset_tab(tab_name.c_str());
|
||||
|
||||
if (m_plater) {
|
||||
// load initial config
|
||||
@ -157,44 +149,12 @@ void MainFrame::init_tabpanel()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PresetTab> preset_tabs = {
|
||||
{ "print", nullptr, ptFFF },
|
||||
{ "filament", nullptr, ptFFF },
|
||||
{ "sla_material", nullptr, ptSLA }
|
||||
};
|
||||
|
||||
std::vector<PresetTab>& MainFrame::get_preset_tabs() {
|
||||
return preset_tabs;
|
||||
}
|
||||
|
||||
Tab* MainFrame::get_tab(const std::string& name)
|
||||
{
|
||||
std::vector<PresetTab>::iterator it = std::find_if(preset_tabs.begin(), preset_tabs.end(),
|
||||
[name](PresetTab& tab) { return name == tab.name; });
|
||||
return it != preset_tabs.end() ? it->panel : nullptr;
|
||||
}
|
||||
|
||||
Tab* MainFrame::get_preset_tab(const std::string& name)
|
||||
{
|
||||
Tab* tab = get_tab(name);
|
||||
if (tab) return tab;
|
||||
|
||||
for (size_t i = 0; i < m_tabpanel->GetPageCount(); ++i) {
|
||||
tab = dynamic_cast<Tab*>(m_tabpanel->GetPage(i));
|
||||
if (!tab)
|
||||
continue;
|
||||
if (tab->name() == name) {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MainFrame::create_preset_tabs()
|
||||
{
|
||||
wxGetApp().update_label_colours_from_appconfig();
|
||||
add_created_tab(new TabPrint(m_tabpanel));
|
||||
add_created_tab(new TabFilament(m_tabpanel));
|
||||
add_created_tab(new TabSLAPrint(m_tabpanel));
|
||||
add_created_tab(new TabSLAMaterial(m_tabpanel));
|
||||
add_created_tab(new TabPrinter(m_tabpanel));
|
||||
}
|
||||
@ -203,17 +163,9 @@ void MainFrame::add_created_tab(Tab* panel)
|
||||
{
|
||||
panel->create_preset_tab();
|
||||
|
||||
const wxString& tab_name = panel->GetName();
|
||||
bool add_panel = true;
|
||||
const auto printer_tech = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
|
||||
auto it = std::find_if(preset_tabs.begin(), preset_tabs.end(),
|
||||
[tab_name](PresetTab& tab) {return tab.name == tab_name; });
|
||||
if (it != preset_tabs.end()) {
|
||||
it->panel = panel;
|
||||
add_panel = it->technology == wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
}
|
||||
|
||||
if (add_panel)
|
||||
if (panel->supports_printer_technology(printer_tech))
|
||||
m_tabpanel->AddPage(panel, panel->title());
|
||||
}
|
||||
|
||||
@ -768,8 +720,8 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re
|
||||
// Also update the platter with the new presets.
|
||||
void MainFrame::load_config(const DynamicPrintConfig& config)
|
||||
{
|
||||
for (auto tab : m_options_tabs)
|
||||
tab.second->load_config(config);
|
||||
for (auto tab : wxGetApp().tabs_list)
|
||||
tab->load_config(config);
|
||||
if (m_plater)
|
||||
m_plater->on_config_change(config);
|
||||
}
|
||||
@ -797,7 +749,6 @@ void MainFrame::on_presets_changed(SimpleEvent &event)
|
||||
// Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs.
|
||||
auto presets = tab->get_presets();
|
||||
if (m_plater != nullptr && presets != nullptr) {
|
||||
// auto reload_dependent_tabs = tab->get_dependent_tabs();
|
||||
|
||||
// FIXME: The preset type really should be a property of Tab instead
|
||||
Slic3r::Preset::Type preset_type = tab->type();
|
||||
@ -805,25 +756,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event)
|
||||
wxASSERT(false);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
m_plater->sidebar().update_presets(preset_type);
|
||||
|
||||
if (preset_type == Slic3r::Preset::TYPE_PRINTER) {
|
||||
// Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
|
||||
// XXX: Do this in a more C++ way
|
||||
for (const auto tab_name_other : { "print", "filament", "sla_material" }) {
|
||||
Tab* cur_tab = m_options_tabs[tab_name_other];
|
||||
// If the printer tells us that the print or filament preset has been switched or invalidated,
|
||||
// refresh the print or filament tab page.Otherwise just refresh the combo box.
|
||||
if (reload_dependent_tabs.empty() ||
|
||||
find(reload_dependent_tabs.begin(), reload_dependent_tabs.end(), tab_name_other) ==
|
||||
reload_dependent_tabs.end() )
|
||||
cur_tab->update_tab_ui();
|
||||
else
|
||||
cur_tab->load_current_preset();
|
||||
}
|
||||
}
|
||||
*/
|
||||
m_plater->on_config_change(*tab->get_config());
|
||||
m_plater->sidebar().update_presets(preset_type);
|
||||
}
|
||||
@ -858,11 +791,7 @@ void MainFrame::update_ui_from_settings()
|
||||
{
|
||||
m_menu_item_reslice_now->Enable(wxGetApp().app_config->get("background_processing") == "1");
|
||||
// if (m_plater) m_plater->update_ui_from_settings();
|
||||
/*
|
||||
std::vector<std::string> tab_names = { "print", "filament", "printer" };
|
||||
for (auto tab_name: tab_names)
|
||||
m_options_tabs[tab_name]->update_ui_from_settings();
|
||||
*/
|
||||
|
||||
for (auto tab: wxGetApp().tabs_list)
|
||||
tab->update_ui_from_settings();
|
||||
}
|
||||
|
@ -53,8 +53,6 @@ class MainFrame : public wxFrame
|
||||
wxString m_qs_last_output_file = wxEmptyString;
|
||||
wxString m_last_config = wxEmptyString;
|
||||
|
||||
std::map<std::string, Tab*> m_options_tabs;
|
||||
|
||||
wxMenuItem* m_menu_item_repeat { nullptr };
|
||||
wxMenuItem* m_menu_item_reslice_now { nullptr };
|
||||
#if !ENABLE_NEW_MENU_LAYOUT
|
||||
@ -67,7 +65,6 @@ class MainFrame : public wxFrame
|
||||
|
||||
void on_presets_changed(SimpleEvent&);
|
||||
void on_value_changed(wxCommandEvent&);
|
||||
Tab* get_tab(const std::string& name);
|
||||
|
||||
#if ENABLE_NEW_MENU_LAYOUT
|
||||
bool can_save() const;
|
||||
@ -81,10 +78,9 @@ public:
|
||||
MainFrame(const bool no_plater, const bool loaded);
|
||||
~MainFrame() {}
|
||||
|
||||
Plater* plater() { return m_plater; }
|
||||
|
||||
void init_tabpanel();
|
||||
const std::map<std::string, Tab*>& options_tabs() const { return m_options_tabs; }
|
||||
Tab* get_preset_tab(const std::string& name);
|
||||
void create_preset_tabs();
|
||||
void add_created_tab(Tab* panel);
|
||||
void init_menubar();
|
||||
@ -104,8 +100,6 @@ public:
|
||||
void select_tab(size_t tab) const;
|
||||
void select_view(const std::string& direction);
|
||||
|
||||
std::vector<PresetTab>& get_preset_tabs();
|
||||
|
||||
Plater* m_plater { nullptr };
|
||||
wxNotebook* m_tabpanel { nullptr };
|
||||
wxProgressDialog* m_progress_dialog { nullptr };
|
||||
|
@ -20,7 +20,8 @@
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/colordlg.h>
|
||||
#include <wx/numdlg.h>
|
||||
#include <wx/numdlg.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
@ -34,7 +35,6 @@
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Format/AMF.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
//#include "slic3r/AppController.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
@ -423,6 +423,7 @@ struct Sidebar::priv
|
||||
PresetComboBox *combo_print;
|
||||
std::vector<PresetComboBox*> combos_filament;
|
||||
wxBoxSizer *sizer_filaments;
|
||||
PresetComboBox *combo_sla_print;
|
||||
PresetComboBox *combo_sla_material;
|
||||
PresetComboBox *combo_printer;
|
||||
|
||||
@ -453,7 +454,7 @@ void Sidebar::priv::show_preset_comboboxes()
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
sizer_presets->Show(i, !showSLA);
|
||||
|
||||
for (size_t i = 4; i < 6; ++i) {
|
||||
for (size_t i = 4; i < 8; ++i) {
|
||||
if (sizer_presets->IsShown(i) != showSLA)
|
||||
sizer_presets->Show(i, showSLA);
|
||||
}
|
||||
@ -478,7 +479,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->scrolled->SetSizer(scrolled_sizer);
|
||||
|
||||
// The preset chooser
|
||||
p->sizer_presets = new wxFlexGridSizer(4, 2, 1, 2);
|
||||
p->sizer_presets = new wxFlexGridSizer(5, 2, 1, 2);
|
||||
p->sizer_presets->AddGrowableCol(1, 1);
|
||||
p->sizer_presets->SetFlexibleDirection(wxBOTH);
|
||||
p->sizer_filaments = new wxBoxSizer(wxVERTICAL);
|
||||
@ -501,10 +502,11 @@ Sidebar::Sidebar(Plater *parent)
|
||||
};
|
||||
|
||||
p->combos_filament.push_back(nullptr);
|
||||
init_combo(&p->combo_print, _(L("Print settings")), Preset::TYPE_PRINT, false);
|
||||
init_combo(&p->combos_filament[0], _(L("Filament")), Preset::TYPE_FILAMENT, true);
|
||||
init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false);
|
||||
init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false);
|
||||
init_combo(&p->combo_print, _(L("Print settings")), Preset::TYPE_PRINT, false);
|
||||
init_combo(&p->combos_filament[0], _(L("Filament")), Preset::TYPE_FILAMENT, true);
|
||||
init_combo(&p->combo_sla_print, _(L("SLA print")), Preset::TYPE_SLA_PRINT, false);
|
||||
init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false);
|
||||
init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false);
|
||||
|
||||
// calculate width of the preset labels
|
||||
p->sizer_presets->Layout();
|
||||
@ -619,6 +621,10 @@ void Sidebar::update_presets(Preset::Type preset_type)
|
||||
preset_bundle.prints.update_platter_ui(p->combo_print);
|
||||
break;
|
||||
|
||||
case Preset::TYPE_SLA_PRINT:
|
||||
preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print);
|
||||
break;
|
||||
|
||||
case Preset::TYPE_SLA_MATERIAL:
|
||||
preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
|
||||
break;
|
||||
@ -628,8 +634,10 @@ void Sidebar::update_presets(Preset::Type preset_type)
|
||||
// Update the print choosers to only contain the compatible presets, update the dirty flags.
|
||||
if (p->plater->printer_technology() == ptFFF)
|
||||
preset_bundle.prints.update_platter_ui(p->combo_print);
|
||||
else
|
||||
preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
|
||||
else {
|
||||
preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print);
|
||||
preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
|
||||
}
|
||||
// Update the printer choosers, update the dirty flags.
|
||||
preset_bundle.printers.update_platter_ui(p->combo_printer);
|
||||
// Update the filament choosers to only contain the compatible presets, update the color preview,
|
||||
@ -880,6 +888,7 @@ struct Plater::priv
|
||||
// GUI elements
|
||||
wxNotebook *notebook;
|
||||
Sidebar *sidebar;
|
||||
wxPanel *panel3d;
|
||||
wxGLCanvas *canvas3D; // TODO: Use GLCanvas3D when we can
|
||||
Preview *preview;
|
||||
|
||||
@ -958,7 +967,6 @@ struct Plater::priv
|
||||
void on_action_add(SimpleEvent&);
|
||||
void on_action_split_objects(SimpleEvent&);
|
||||
void on_action_split_volumes(SimpleEvent&);
|
||||
void on_action_cut(SimpleEvent&);
|
||||
void on_action_layersediting(SimpleEvent&);
|
||||
|
||||
void on_object_select(SimpleEvent&);
|
||||
@ -977,7 +985,6 @@ private:
|
||||
bool can_decrease_instances() const;
|
||||
bool can_split_to_objects() const;
|
||||
bool can_split_to_volumes() const;
|
||||
bool can_cut_object() const;
|
||||
bool layers_height_allowed() const;
|
||||
bool can_delete_all() const;
|
||||
bool can_arrange() const;
|
||||
@ -987,19 +994,20 @@ private:
|
||||
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_zip_amf(".*[.]zip[.]amf", std::regex::icase);
|
||||
Plater::priv::priv(Plater *q, MainFrame *main_frame) :
|
||||
q(q),
|
||||
main_frame(main_frame),
|
||||
config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
|
||||
Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
: q(q)
|
||||
, main_frame(main_frame)
|
||||
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
|
||||
"bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance",
|
||||
"brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host",
|
||||
"printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material",
|
||||
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
|
||||
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology"
|
||||
})),
|
||||
notebook(new wxNotebook(q, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM)),
|
||||
sidebar(new Sidebar(q)),
|
||||
canvas3D(GLCanvas3DManager::create_wxglcanvas(notebook))
|
||||
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology"
|
||||
}))
|
||||
, notebook(new wxNotebook(q, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM))
|
||||
, sidebar(new Sidebar(q))
|
||||
, panel3d(new wxPanel(notebook, wxID_ANY))
|
||||
, canvas3D(GLCanvas3DManager::create_wxglcanvas(panel3d))
|
||||
#if ENABLE_NEW_MENU_LAYOUT
|
||||
, project_filename(wxEmptyString)
|
||||
#endif // ENABLE_NEW_MENU_LAYOUT
|
||||
@ -1023,9 +1031,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
|
||||
|
||||
_3DScene::add_canvas(canvas3D);
|
||||
_3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample());
|
||||
notebook->AddPage(canvas3D, _(L("3D")));
|
||||
|
||||
auto *panel3dsizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel3dsizer->Add(canvas3D, 1, wxEXPAND);
|
||||
auto *panel_gizmo_widgets = new wxPanel(panel3d, wxID_ANY);
|
||||
panel_gizmo_widgets->SetSizer(new wxBoxSizer(wxVERTICAL));
|
||||
panel3dsizer->Add(panel_gizmo_widgets, 0, wxEXPAND);
|
||||
|
||||
panel3d->SetSizer(panel3dsizer);
|
||||
notebook->AddPage(panel3d, _(L("3D")));
|
||||
preview = new GUI::Preview(notebook, config, &print, &gcode_preview_data, [this](){ schedule_background_process(); });
|
||||
|
||||
_3DScene::get_canvas(canvas3D)->set_external_gizmo_widgets_parent(panel_gizmo_widgets);
|
||||
|
||||
// XXX: If have OpenGL
|
||||
_3DScene::enable_picking(canvas3D, true);
|
||||
_3DScene::enable_moving(canvas3D, true);
|
||||
@ -1088,7 +1106,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
|
||||
canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); });
|
||||
canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
|
||||
canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this);
|
||||
canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this);
|
||||
canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
|
||||
|
||||
// Preview events:
|
||||
@ -1471,7 +1488,6 @@ void Plater::priv::selection_changed()
|
||||
_3DScene::enable_toolbar_item(canvas3D, "fewer", can_decrease_instances());
|
||||
_3DScene::enable_toolbar_item(canvas3D, "splitobjects", can_split_to_objects());
|
||||
_3DScene::enable_toolbar_item(canvas3D, "splitvolumes", can_split_to_volumes());
|
||||
_3DScene::enable_toolbar_item(canvas3D, "cut", can_cut_object());
|
||||
_3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed());
|
||||
// forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
|
||||
_3DScene::render(canvas3D);
|
||||
@ -1806,7 +1822,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx)
|
||||
void Plater::priv::on_notebook_changed(wxBookCtrlEvent&)
|
||||
{
|
||||
const auto current_id = notebook->GetCurrentPage()->GetId();
|
||||
if (current_id == canvas3D->GetId()) {
|
||||
if (current_id == panel3d->GetId()) {
|
||||
if (_3DScene::is_reload_delayed(canvas3D)) {
|
||||
// Delayed loading of the 3D scene.
|
||||
if (this->printer_technology == ptSLA) {
|
||||
@ -1859,8 +1875,6 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize config.ini with the current selections.
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
// update plater with new config
|
||||
wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config());
|
||||
}
|
||||
@ -1988,11 +2002,6 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
|
||||
split_volume();
|
||||
}
|
||||
|
||||
void Plater::priv::on_action_cut(SimpleEvent&)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Plater::priv::on_action_layersediting(SimpleEvent&)
|
||||
{
|
||||
bool enable = !_3DScene::is_layers_editing_enabled(canvas3D);
|
||||
@ -2036,7 +2045,7 @@ void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
|
||||
main_frame->get_preset_tab("print")->load_config(cfg);
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
|
||||
}
|
||||
|
||||
void Plater::priv::on_enable_action_buttons(Event<bool>&)
|
||||
@ -2132,12 +2141,6 @@ bool Plater::priv::can_split_to_volumes() const
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
|
||||
}
|
||||
|
||||
bool Plater::priv::can_cut_object() const
|
||||
{
|
||||
int obj_idx = get_selected_object_idx();
|
||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
|
||||
}
|
||||
|
||||
bool Plater::priv::layers_height_allowed() const
|
||||
{
|
||||
int obj_idx = get_selected_object_idx();
|
||||
@ -2331,6 +2334,21 @@ void Plater::set_number_of_copies(/*size_t num*/)
|
||||
decrease_instances(-diff);
|
||||
}
|
||||
|
||||
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z)
|
||||
{
|
||||
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
|
||||
auto *object = p->model.objects[obj_idx];
|
||||
|
||||
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
|
||||
|
||||
const auto new_objects = object->cut(instance_idx, z);
|
||||
|
||||
remove(obj_idx);
|
||||
p->load_model_objects(new_objects);
|
||||
|
||||
p->arrange();
|
||||
}
|
||||
|
||||
void Plater::export_gcode(fs::path output_path)
|
||||
{
|
||||
if (p->model.objects.empty())
|
||||
|
@ -135,6 +135,8 @@ public:
|
||||
void decrease_instances(size_t num = 1);
|
||||
void set_number_of_copies(/*size_t num*/);
|
||||
|
||||
void cut(size_t obj_idx, size_t instance_idx, coordf_t z);
|
||||
|
||||
// Note: empty path means "use the default"
|
||||
void export_gcode(boost::filesystem::path output_path = boost::filesystem::path());
|
||||
void export_stl();
|
||||
|
@ -396,6 +396,35 @@ const std::vector<std::string>& Preset::sla_material_options()
|
||||
return s_opts;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& Preset::sla_print_options()
|
||||
{
|
||||
static std::vector<std::string> s_opts;
|
||||
if (s_opts.empty()) {
|
||||
s_opts = {
|
||||
"layer_height",
|
||||
"support_head_front_radius",
|
||||
"support_head_penetration",
|
||||
"support_head_back_radius",
|
||||
"support_head_width",
|
||||
"support_pillar_radius",
|
||||
"support_base_radius",
|
||||
"support_base_height",
|
||||
"support_critical_angle",
|
||||
"support_max_bridge_length",
|
||||
"support_object_elevation",
|
||||
"pad_wall_thickness",
|
||||
"pad_wall_height",
|
||||
"pad_max_merge_distance",
|
||||
"pad_edge_radius",
|
||||
"default_sla_print_profile",
|
||||
"compatible_printers",
|
||||
"compatible_printers_condition",
|
||||
"inherits"
|
||||
};
|
||||
}
|
||||
return s_opts;
|
||||
}
|
||||
|
||||
PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name) :
|
||||
m_type(type),
|
||||
m_edited_preset(type, "", false),
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
{
|
||||
TYPE_INVALID,
|
||||
TYPE_PRINT,
|
||||
TYPE_SLA_PRINT,
|
||||
TYPE_FILAMENT,
|
||||
TYPE_SLA_MATERIAL,
|
||||
TYPE_PRINTER,
|
||||
@ -173,6 +174,7 @@ public:
|
||||
|
||||
static const std::vector<std::string>& sla_printer_options();
|
||||
static const std::vector<std::string>& sla_material_options();
|
||||
static const std::vector<std::string>& sla_print_options();
|
||||
|
||||
static void update_suffix_modified();
|
||||
static void normalize(DynamicPrintConfig &config);
|
||||
|
@ -45,6 +45,7 @@ PresetBundle::PresetBundle() :
|
||||
prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults())),
|
||||
filaments(Preset::TYPE_FILAMENT, Preset::filament_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults())),
|
||||
sla_materials(Preset::TYPE_SLA_MATERIAL, Preset::sla_material_options(), static_cast<const SLAMaterialConfig&>(SLAFullPrintConfig::defaults())),
|
||||
sla_prints(Preset::TYPE_SLA_PRINT, Preset::sla_print_options(), static_cast<const SLAPrintObjectConfig&>(SLAFullPrintConfig::defaults())),
|
||||
printers(Preset::TYPE_PRINTER, Preset::printer_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults()), "- default FFF -"),
|
||||
m_bitmapCompatible(new wxBitmap),
|
||||
m_bitmapIncompatible(new wxBitmap),
|
||||
@ -76,6 +77,10 @@ PresetBundle::PresetBundle() :
|
||||
this->sla_materials.default_preset().compatible_printers_condition();
|
||||
this->sla_materials.default_preset().inherits();
|
||||
|
||||
this->sla_prints.default_preset().config.optptr("sla_print_settings_id", true);
|
||||
this->sla_prints.default_preset().compatible_printers_condition();
|
||||
this->sla_prints.default_preset().inherits();
|
||||
|
||||
this->printers.add_default_preset(Preset::sla_printer_options(), static_cast<const SLAMaterialConfig&>(SLAFullPrintConfig::defaults()), "- default SLA -");
|
||||
this->printers.preset(1).printer_technology() = ptSLA;
|
||||
for (size_t i = 0; i < 2; ++ i) {
|
||||
@ -88,14 +93,18 @@ PresetBundle::PresetBundle() :
|
||||
if (i == 0) {
|
||||
preset.config.optptr("default_print_profile", true);
|
||||
preset.config.option<ConfigOptionStrings>("default_filament_profile", true)->values = { "" };
|
||||
} else
|
||||
}
|
||||
else {
|
||||
preset.config.optptr("default_sla_material_profile", true);
|
||||
preset.config.optptr("default_sla_print_profile", true);
|
||||
}
|
||||
// default_sla_material_profile
|
||||
preset.inherits();
|
||||
}
|
||||
|
||||
// Load the default preset bitmaps.
|
||||
this->prints .load_bitmap_default("cog.png");
|
||||
this->sla_prints .load_bitmap_default("package_green.png");
|
||||
this->filaments .load_bitmap_default("spool.png");
|
||||
this->sla_materials.load_bitmap_default("package_green.png");
|
||||
this->printers .load_bitmap_default("printer_empty.png");
|
||||
@ -103,6 +112,7 @@ PresetBundle::PresetBundle() :
|
||||
|
||||
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
|
||||
this->prints .select_preset(0);
|
||||
this->sla_prints .select_preset(0);
|
||||
this->filaments .select_preset(0);
|
||||
this->sla_materials.select_preset(0);
|
||||
this->printers .select_preset(0);
|
||||
@ -133,12 +143,14 @@ void PresetBundle::reset(bool delete_files)
|
||||
// Clear the existing presets, delete their respective files.
|
||||
this->vendors.clear();
|
||||
this->prints .reset(delete_files);
|
||||
this->sla_prints .reset(delete_files);
|
||||
this->filaments .reset(delete_files);
|
||||
this->sla_materials.reset(delete_files);
|
||||
this->printers .reset(delete_files);
|
||||
this->filament_presets.clear();
|
||||
this->filament_presets.emplace_back(this->filaments.get_selected_preset_name());
|
||||
this->obsolete_presets.prints.clear();
|
||||
this->obsolete_presets.sla_prints.clear();
|
||||
this->obsolete_presets.filaments.clear();
|
||||
this->obsolete_presets.sla_materials.clear();
|
||||
this->obsolete_presets.printers.clear();
|
||||
@ -156,12 +168,14 @@ void PresetBundle::setup_directories()
|
||||
data_dir / "presets",
|
||||
data_dir / "presets" / "print",
|
||||
data_dir / "presets" / "filament",
|
||||
data_dir / "presets" / "sla_print",
|
||||
data_dir / "presets" / "sla_material",
|
||||
data_dir / "presets" / "printer"
|
||||
#else
|
||||
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
|
||||
data_dir / "print",
|
||||
data_dir / "filament",
|
||||
data_dir / "sla_print",
|
||||
data_dir / "sla_material",
|
||||
data_dir / "printer"
|
||||
#endif
|
||||
@ -193,6 +207,11 @@ void PresetBundle::load_presets(const AppConfig &config)
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
try {
|
||||
this->sla_prints.load_presets(dir_user_presets, "sla_print");
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
try {
|
||||
this->filaments.load_presets(dir_user_presets, "filament");
|
||||
} catch (const std::runtime_error &err) {
|
||||
@ -267,13 +286,16 @@ std::vector<std::string> PresetBundle::merge_presets(PresetBundle &&other)
|
||||
{
|
||||
this->vendors.insert(other.vendors.begin(), other.vendors.end());
|
||||
std::vector<std::string> duplicate_prints = this->prints .merge_presets(std::move(other.prints), this->vendors);
|
||||
std::vector<std::string> duplicate_sla_prints = this->sla_prints .merge_presets(std::move(other.sla_prints), this->vendors);
|
||||
std::vector<std::string> duplicate_filaments = this->filaments .merge_presets(std::move(other.filaments), this->vendors);
|
||||
std::vector<std::string> duplicate_sla_materials = this->sla_materials.merge_presets(std::move(other.sla_materials), this->vendors);
|
||||
std::vector<std::string> duplicate_printers = this->printers .merge_presets(std::move(other.printers), this->vendors);
|
||||
append(this->obsolete_presets.prints, std::move(other.obsolete_presets.prints));
|
||||
append(this->obsolete_presets.sla_prints, std::move(other.obsolete_presets.sla_prints));
|
||||
append(this->obsolete_presets.filaments, std::move(other.obsolete_presets.filaments));
|
||||
append(this->obsolete_presets.sla_materials, std::move(other.obsolete_presets.sla_materials));
|
||||
append(this->obsolete_presets.printers, std::move(other.obsolete_presets.printers));
|
||||
append(duplicate_prints, std::move(duplicate_sla_prints));
|
||||
append(duplicate_prints, std::move(duplicate_filaments));
|
||||
append(duplicate_prints, std::move(duplicate_sla_materials));
|
||||
append(duplicate_prints, std::move(duplicate_printers));
|
||||
@ -307,6 +329,7 @@ void PresetBundle::load_selections(const AppConfig &config)
|
||||
|
||||
// Parse the initial print / filament / printer profile names.
|
||||
std::string initial_print_profile_name = remove_ini_suffix(config.get("presets", "print"));
|
||||
std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", "sla_print"));
|
||||
std::string initial_filament_profile_name = remove_ini_suffix(config.get("presets", "filament"));
|
||||
std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", "sla_material"));
|
||||
std::string initial_printer_profile_name = remove_ini_suffix(config.get("presets", "printer"));
|
||||
@ -320,10 +343,12 @@ void PresetBundle::load_selections(const AppConfig &config)
|
||||
if (printer_technology == ptFFF) {
|
||||
prints.select_preset_by_name_strict(initial_print_profile_name);
|
||||
filaments.select_preset_by_name_strict(initial_filament_profile_name);
|
||||
sla_prints.select_preset_by_name(initial_sla_material_profile_name, true);
|
||||
sla_materials.select_preset_by_name(initial_sla_material_profile_name, true);
|
||||
} else {
|
||||
prints.select_preset_by_name(initial_print_profile_name, true);
|
||||
filaments.select_preset_by_name(initial_filament_profile_name, true);
|
||||
sla_prints.select_preset_by_name_strict(initial_sla_material_profile_name);
|
||||
sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name);
|
||||
}
|
||||
|
||||
@ -364,6 +389,7 @@ void PresetBundle::export_selections(AppConfig &config)
|
||||
sprintf(name, "filament_%d", i);
|
||||
config.set("presets", name, filament_presets[i]);
|
||||
}
|
||||
config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
|
||||
config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
|
||||
config.set("presets", "printer", printers.get_selected_preset_name());
|
||||
}
|
||||
@ -378,6 +404,7 @@ void PresetBundle::export_selections(PlaceholderParser &pp)
|
||||
pp.set("filament_preset", filament_presets);
|
||||
break;
|
||||
case ptSLA:
|
||||
pp.set("sla_print_preset", sla_prints.get_selected_preset().name);
|
||||
pp.set("sla_material_preset", sla_materials.get_selected_preset().name);
|
||||
break;
|
||||
}
|
||||
@ -401,24 +428,28 @@ bool PresetBundle::load_compatible_bitmaps()
|
||||
if (loaded_compatible) {
|
||||
prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
filaments .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
|
||||
// printers .set_bitmap_compatible(m_bitmapCompatible);
|
||||
}
|
||||
if (loaded_incompatible) {
|
||||
prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
// printers .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
}
|
||||
if (loaded_lock) {
|
||||
prints .set_bitmap_lock(m_bitmapLock);
|
||||
filaments .set_bitmap_lock(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock(m_bitmapLock);
|
||||
printers .set_bitmap_lock(m_bitmapLock);
|
||||
}
|
||||
if (loaded_lock_open) {
|
||||
prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
filaments .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock_open(m_bitmapLock);
|
||||
printers .set_bitmap_lock_open(m_bitmapLock);
|
||||
}
|
||||
@ -533,14 +564,17 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
|
||||
{
|
||||
DynamicPrintConfig out;
|
||||
out.apply(SLAFullPrintConfig::defaults());
|
||||
out.apply(this->sla_prints.get_edited_preset().config);
|
||||
out.apply(this->sla_materials.get_edited_preset().config);
|
||||
out.apply(this->printers.get_edited_preset().config);
|
||||
// There are no project configuration values as of now, the project_config is reserved for FFF printers.
|
||||
// out.apply(this->project_config);
|
||||
|
||||
// Collect the "compatible_printers_condition" and "inherits" values over all presets (sla_materials, printers) into a single vector.
|
||||
// Collect the "compatible_printers_condition" and "inherits" values over all presets (sla_prints, sla_materials, printers) into a single vector.
|
||||
std::vector<std::string> compatible_printers_condition;
|
||||
std::vector<std::string> inherits;
|
||||
compatible_printers_condition.emplace_back(this->/*prints*/sla_prints.get_edited_preset().compatible_printers_condition());
|
||||
inherits .emplace_back(this->/*prints*/sla_prints.get_edited_preset().inherits());
|
||||
compatible_printers_condition.emplace_back(this->/*prints*/sla_materials.get_edited_preset().compatible_printers_condition());
|
||||
inherits .emplace_back(this->/*prints*/sla_materials.get_edited_preset().inherits());
|
||||
inherits .emplace_back(this->printers.get_edited_preset().inherits());
|
||||
@ -550,6 +584,7 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
|
||||
out.erase("compatible_printers_condition");
|
||||
out.erase("inherits");
|
||||
|
||||
out.option<ConfigOptionString >("sla_print_settings_id", true)->value = this->sla_prints.get_selected_preset().name;
|
||||
out.option<ConfigOptionString >("sla_material_settings_id", true)->value = this->sla_materials.get_selected_preset().name;
|
||||
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset().name;
|
||||
|
||||
@ -661,6 +696,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
||||
|
||||
// 2) If the loading succeeded, split and load the config into print / filament / printer settings.
|
||||
// First load the print and printer presets.
|
||||
|
||||
// #ys_FIXME_SLA_PRINT
|
||||
for (size_t i_group = 0; i_group < 2; ++ i_group) {
|
||||
PresetCollection &presets = (i_group == 0) ? ((printer_technology == ptFFF) ? this->prints : this->sla_materials) : this->printers;
|
||||
// Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles.
|
||||
@ -794,6 +831,7 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const
|
||||
return preset_name_dst;
|
||||
};
|
||||
load_one(this->prints, tmp_bundle.prints, tmp_bundle.prints .get_selected_preset().name, true);
|
||||
load_one(this->sla_prints, tmp_bundle.sla_prints, tmp_bundle.sla_prints .get_selected_preset().name, true);
|
||||
load_one(this->filaments, tmp_bundle.filaments, tmp_bundle.filaments .get_selected_preset().name, true);
|
||||
load_one(this->sla_materials, tmp_bundle.sla_materials, tmp_bundle.sla_materials.get_selected_preset().name, true);
|
||||
load_one(this->printers, tmp_bundle.printers, tmp_bundle.printers .get_selected_preset().name, true);
|
||||
@ -920,6 +958,7 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree)
|
||||
{
|
||||
flatten_configbundle_hierarchy(tree, "print");
|
||||
flatten_configbundle_hierarchy(tree, "filament");
|
||||
flatten_configbundle_hierarchy(tree, "sla_print");
|
||||
flatten_configbundle_hierarchy(tree, "sla_material");
|
||||
flatten_configbundle_hierarchy(tree, "printer");
|
||||
}
|
||||
@ -957,10 +996,12 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
||||
// Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
|
||||
std::vector<std::string> loaded_prints;
|
||||
std::vector<std::string> loaded_filaments;
|
||||
std::vector<std::string> loaded_sla_prints;
|
||||
std::vector<std::string> loaded_sla_materials;
|
||||
std::vector<std::string> loaded_printers;
|
||||
std::string active_print;
|
||||
std::vector<std::string> active_filaments;
|
||||
std::string active_sla_print;
|
||||
std::string active_sla_material;
|
||||
std::string active_printer;
|
||||
size_t presets_loaded = 0;
|
||||
@ -976,6 +1017,10 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
||||
presets = &this->filaments;
|
||||
loaded = &loaded_filaments;
|
||||
preset_name = section.first.substr(9);
|
||||
} else if (boost::starts_with(section.first, "sla_print:")) {
|
||||
presets = &this->sla_prints;
|
||||
loaded = &loaded_sla_prints;
|
||||
preset_name = section.first.substr(10);
|
||||
} else if (boost::starts_with(section.first, "sla_material:")) {
|
||||
presets = &this->sla_materials;
|
||||
loaded = &loaded_sla_materials;
|
||||
@ -996,6 +1041,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
||||
active_filaments.resize(idx + 1, std::string());
|
||||
active_filaments[idx] = kvp.second.data();
|
||||
}
|
||||
} else if (kvp.first == "sla_print") {
|
||||
active_sla_print = kvp.second.data();
|
||||
} else if (kvp.first == "sla_material") {
|
||||
active_sla_material = kvp.second.data();
|
||||
} else if (kvp.first == "printer") {
|
||||
@ -1011,6 +1058,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
||||
dst = &this->obsolete_presets.prints;
|
||||
else if (kvp.first == "filament")
|
||||
dst = &this->obsolete_presets.filaments;
|
||||
else if (kvp.first == "sla_print")
|
||||
dst = &this->obsolete_presets.sla_prints;
|
||||
else if (kvp.first == "sla_material")
|
||||
dst = &this->obsolete_presets.sla_materials;
|
||||
else if (kvp.first == "printer")
|
||||
@ -1113,6 +1162,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
||||
if ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) {
|
||||
if (! active_print.empty())
|
||||
prints.select_preset_by_name(active_print, true);
|
||||
if (! active_sla_print.empty())
|
||||
sla_materials.select_preset_by_name(active_sla_print, true);
|
||||
if (! active_sla_material.empty())
|
||||
sla_materials.select_preset_by_name(active_sla_material, true);
|
||||
if (! active_printer.empty())
|
||||
@ -1217,6 +1268,13 @@ void PresetBundle::update_compatible_with_printer(bool select_other_if_incompati
|
||||
this->sla_materials.update_compatible_with_printer(printer_preset, select_other_if_incompatible) :
|
||||
this->sla_materials.update_compatible_with_printer(printer_preset, select_other_if_incompatible,
|
||||
[&prefered_sla_material_profile](const std::string& profile_name){ return profile_name == prefered_sla_material_profile; });
|
||||
|
||||
const std::string &prefered_sla_print_profile = printer_preset.config.opt_string("default_sla_print_profile");
|
||||
prefered_sla_print_profile.empty() ?
|
||||
this->sla_prints.update_compatible_with_printer(printer_preset, select_other_if_incompatible) :
|
||||
this->sla_prints.update_compatible_with_printer(printer_preset, select_other_if_incompatible,
|
||||
[&prefered_sla_print_profile](const std::string& profile_name){ return profile_name == prefered_sla_print_profile; });
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1231,6 +1289,8 @@ void PresetBundle::export_configbundle(const std::string &path) //, const Dynami
|
||||
c << "# " << Slic3r::header_slic3r_generated() << std::endl;
|
||||
|
||||
// Export the print, filament and printer profiles.
|
||||
|
||||
// #ys_FIXME_SLA_PRINT
|
||||
for (size_t i_group = 0; i_group < 3; ++ i_group) {
|
||||
const PresetCollection &presets = (i_group == 0) ? this->prints : (i_group == 1) ? this->filaments : this->printers;
|
||||
for (const Preset &preset : presets()) {
|
||||
@ -1246,6 +1306,7 @@ void PresetBundle::export_configbundle(const std::string &path) //, const Dynami
|
||||
// Export the names of the active presets.
|
||||
c << std::endl << "[presets]" << std::endl;
|
||||
c << "print = " << this->prints.get_selected_preset().name << std::endl;
|
||||
c << "sla_print = " << this->sla_prints.get_selected_preset().name << std::endl;
|
||||
c << "sla_material = " << this->sla_materials.get_selected_preset().name << std::endl;
|
||||
c << "printer = " << this->printers.get_selected_preset().name << std::endl;
|
||||
for (size_t i = 0; i < this->filament_presets.size(); ++ i) {
|
||||
@ -1401,6 +1462,7 @@ void PresetBundle::set_default_suppressed(bool default_suppressed)
|
||||
{
|
||||
prints.set_default_suppressed(default_suppressed);
|
||||
filaments.set_default_suppressed(default_suppressed);
|
||||
sla_prints.set_default_suppressed(default_suppressed);
|
||||
sla_materials.set_default_suppressed(default_suppressed);
|
||||
printers.set_default_suppressed(default_suppressed);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
void export_selections(PlaceholderParser &pp);
|
||||
|
||||
PresetCollection prints;
|
||||
PresetCollection sla_prints;
|
||||
PresetCollection filaments;
|
||||
PresetCollection sla_materials;
|
||||
PrinterPresetCollection printers;
|
||||
@ -57,6 +58,7 @@ public:
|
||||
|
||||
struct ObsoletePresets {
|
||||
std::vector<std::string> prints;
|
||||
std::vector<std::string> sla_prints;
|
||||
std::vector<std::string> filaments;
|
||||
std::vector<std::string> sla_materials;
|
||||
std::vector<std::string> printers;
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "wxExtensions.hpp"
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include <chrono>
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
@ -41,6 +40,7 @@ wxDEFINE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent);
|
||||
void Tab::set_type()
|
||||
{
|
||||
if (m_name == "print") { m_type = Slic3r::Preset::TYPE_PRINT; }
|
||||
else if (m_name == "sla_print") { m_type = Slic3r::Preset::TYPE_SLA_PRINT; }
|
||||
else if (m_name == "filament") { m_type = Slic3r::Preset::TYPE_FILAMENT; }
|
||||
else if (m_name == "sla_material") { m_type = Slic3r::Preset::TYPE_SLA_MATERIAL; }
|
||||
else if (m_name == "printer") { m_type = Slic3r::Preset::TYPE_PRINTER; }
|
||||
@ -765,9 +765,7 @@ void Tab::on_presets_changed()
|
||||
{
|
||||
// If the printer tells us that the print or filament/sla_material preset has been switched or invalidated,
|
||||
// refresh the print or filament/sla_material tab page.
|
||||
Tab* tab = wxGetApp().get_tab(t);
|
||||
if (tab)
|
||||
tab->load_current_preset();
|
||||
wxGetApp().get_tab(t)->load_current_preset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -828,6 +826,10 @@ void Tab::update_preset_description_line()
|
||||
const std::string &default_sla_material_profile = preset.config.opt_string("default_sla_material_profile");
|
||||
if (!default_sla_material_profile.empty())
|
||||
description_line += "\n\n\t" + _(L("default SLA material profile")) + ": \n\t\t" + default_sla_material_profile;
|
||||
|
||||
const std::string &default_sla_print_profile = preset.config.opt_string("default_sla_print_profile");
|
||||
if (!default_sla_print_profile.empty())
|
||||
description_line += "\n\n\t" + _(L("default SLA print profile")) + ": \n\t\t" + default_sla_print_profile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2247,14 +2249,16 @@ void Tab::load_current_preset()
|
||||
PrinterTechnology& printer_technology = m_presets->get_edited_preset().printer_technology();
|
||||
if (printer_technology != static_cast<TabPrinter*>(this)->m_printer_technology)
|
||||
{
|
||||
for (auto& tab : wxGetApp().mainframe->get_preset_tabs()) {
|
||||
if (tab.technology != printer_technology)
|
||||
{
|
||||
int page_id = wxGetApp().tab_panel()->FindPage(tab.panel);
|
||||
for (auto tab : wxGetApp().tabs_list) {
|
||||
if (tab->type() == Preset::TYPE_PRINTER) // Printer tab is shown every time
|
||||
continue;
|
||||
if (tab->supports_printer_technology(printer_technology))
|
||||
wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab, tab->title());
|
||||
else {
|
||||
int page_id = wxGetApp().tab_panel()->FindPage(tab);
|
||||
wxGetApp().tab_panel()->GetPage(page_id)->Show(false);
|
||||
wxGetApp().tab_panel()->RemovePage(page_id);
|
||||
} else
|
||||
wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab.panel, tab.panel->title());
|
||||
}
|
||||
}
|
||||
static_cast<TabPrinter*>(this)->m_printer_technology = printer_technology;
|
||||
}
|
||||
@ -2347,6 +2351,7 @@ void Tab::select_preset(std::string preset_name)
|
||||
auto current_dirty = m_presets->current_is_dirty();
|
||||
auto printer_tab = m_presets->name() == "printer";
|
||||
auto canceled = false;
|
||||
// m_reload_dependent_tabs = {};
|
||||
m_dependent_tabs = {};
|
||||
if (current_dirty && !may_discard_current_dirty_preset()) {
|
||||
canceled = true;
|
||||
@ -2370,6 +2375,7 @@ void Tab::select_preset(std::string preset_name)
|
||||
};
|
||||
std::vector<PresetUpdate> updates = {
|
||||
{ Preset::Type::TYPE_PRINT, &m_preset_bundle->prints, ptFFF },
|
||||
{ Preset::Type::TYPE_SLA_PRINT, &m_preset_bundle->sla_prints, ptSLA },
|
||||
{ Preset::Type::TYPE_FILAMENT, &m_preset_bundle->filaments, ptFFF },
|
||||
{ Preset::Type::TYPE_SLA_MATERIAL,&m_preset_bundle->sla_materials, ptSLA }
|
||||
};
|
||||
@ -2382,8 +2388,10 @@ void Tab::select_preset(std::string preset_name)
|
||||
if (! canceled) {
|
||||
for (PresetUpdate &pu : updates) {
|
||||
// The preset will be switched to a different, compatible preset, or the '-- default --'.
|
||||
if (pu.technology == new_printer_technology)
|
||||
if (pu.technology == new_printer_technology) {
|
||||
// m_reload_dependent_tabs.emplace_back(pu.name);
|
||||
m_dependent_tabs.emplace_back(pu.tab_type);
|
||||
}
|
||||
if (pu.old_preset_dirty)
|
||||
pu.presets->discard_current_changes();
|
||||
}
|
||||
@ -2918,7 +2926,7 @@ void TabSLAMaterial::build()
|
||||
auto page = add_options_page(_(L("Material")), "package_green.png");
|
||||
|
||||
auto optgroup = page->new_optgroup(_(L("Layers")));
|
||||
optgroup->append_single_option_line("layer_height");
|
||||
// optgroup->append_single_option_line("layer_height");
|
||||
optgroup->append_single_option_line("initial_layer_height");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Exposure")));
|
||||
@ -2973,7 +2981,66 @@ void TabSLAMaterial::build()
|
||||
void TabSLAMaterial::update()
|
||||
{
|
||||
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF)
|
||||
return; // ys_FIXME
|
||||
return; // #ys_FIXME
|
||||
}
|
||||
|
||||
void TabSLAPrint::build()
|
||||
{
|
||||
m_presets = &m_preset_bundle->sla_prints;
|
||||
load_initial_data();
|
||||
|
||||
auto page = add_options_page(_(L("Layers and perimeters")), "package_green.png");
|
||||
|
||||
auto optgroup = page->new_optgroup(_(L("Layers")));
|
||||
optgroup->append_single_option_line("layer_height");
|
||||
|
||||
page = add_options_page(_(L("Supports")), "building.png");
|
||||
optgroup = page->new_optgroup(_(L("Support head")));
|
||||
optgroup->append_single_option_line("support_head_front_radius");
|
||||
optgroup->append_single_option_line("support_head_back_radius");
|
||||
optgroup->append_single_option_line("support_head_penetration");
|
||||
optgroup->append_single_option_line("support_head_width");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Support pillar")));
|
||||
optgroup->append_single_option_line("support_pillar_radius");
|
||||
optgroup->append_single_option_line("support_base_radius");
|
||||
optgroup->append_single_option_line("support_base_height");
|
||||
optgroup->append_single_option_line("support_object_elevation");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Connection of the support sticks and junctions")));
|
||||
optgroup->append_single_option_line("support_critical_angle");
|
||||
optgroup->append_single_option_line("support_max_bridge_length");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Pad")));
|
||||
optgroup->append_single_option_line("pad_wall_thickness");
|
||||
optgroup->append_single_option_line("pad_wall_height");
|
||||
optgroup->append_single_option_line("pad_max_merge_distance");
|
||||
optgroup->append_single_option_line("pad_edge_radius");
|
||||
|
||||
page = add_options_page(_(L("Dependencies")), "wrench.png");
|
||||
optgroup = page->new_optgroup(_(L("Profile dependencies")));
|
||||
Line line = optgroup->create_single_option_line("compatible_printers");//Line { _(L("Compatible printers")), "" };
|
||||
line.widget = [this](wxWindow* parent) {
|
||||
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
|
||||
};
|
||||
optgroup->append_line(line, &m_colored_Label);
|
||||
|
||||
Option option = optgroup->get_option("compatible_printers_condition");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
line = Line{ "", "" };
|
||||
line.full_width = 1;
|
||||
line.widget = [this](wxWindow* parent) {
|
||||
return description_line_widget(parent, &m_parent_preset_description_line);
|
||||
};
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
|
||||
void TabSLAPrint::update()
|
||||
{
|
||||
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF)
|
||||
return; // #ys_FIXME
|
||||
}
|
||||
|
||||
} // GUI
|
||||
|
@ -370,6 +370,19 @@ public:
|
||||
bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptSLA; }
|
||||
};
|
||||
|
||||
class TabSLAPrint : public Tab
|
||||
{
|
||||
public:
|
||||
TabSLAPrint() {}
|
||||
TabSLAPrint(wxNotebook* parent) :
|
||||
Tab(parent, _(L("SLA Print Settings")), "sla_print") {}
|
||||
~TabSLAPrint() {}
|
||||
void build() override;
|
||||
void update() override;
|
||||
// void init_options_list() override;
|
||||
bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptSLA; }
|
||||
};
|
||||
|
||||
class SavePresetWindow :public wxDialog
|
||||
{
|
||||
public:
|
||||
|
@ -308,7 +308,7 @@ bool PrusaCollapsiblePaneMSW::Create(wxWindow *parent, wxWindowID id, const wxSt
|
||||
m_pPane = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxTAB_TRAVERSAL | wxNO_BORDER, wxT("wxCollapsiblePanePane"));
|
||||
|
||||
wxColour& clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
wxColour&& clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
m_pDisclosureTriangleButton->SetBackgroundColour(clr);
|
||||
this->SetBackgroundColour(clr);
|
||||
m_pPane->SetBackgroundColour(clr);
|
||||
|
@ -448,7 +448,8 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
||||
|
||||
for (const auto &name : bundle.obsolete_presets.prints) { obsolete_remover("print", name); }
|
||||
for (const auto &name : bundle.obsolete_presets.filaments) { obsolete_remover("filament", name); }
|
||||
for (const auto &name : bundle.obsolete_presets.filaments) { obsolete_remover("sla_material", name); }
|
||||
for (const auto &name : bundle.obsolete_presets.sla_prints) { obsolete_remover("sla_print", name); }
|
||||
for (const auto &name : bundle.obsolete_presets.sla_materials/*filaments*/) { obsolete_remover("sla_material", name); }
|
||||
for (const auto &name : bundle.obsolete_presets.printers) { obsolete_remover("printer", name); }
|
||||
}
|
||||
}
|
||||
|
@ -231,12 +231,6 @@ ModelMaterial::attributes()
|
||||
void rotate(float angle, Vec3d* axis)
|
||||
%code{% THIS->rotate(angle, *axis); %};
|
||||
void mirror(Axis axis);
|
||||
|
||||
Model* cut(double z)
|
||||
%code%{
|
||||
RETVAL = new Model();
|
||||
THIS->cut(z, RETVAL);
|
||||
%};
|
||||
|
||||
ModelObjectPtrs* split_object()
|
||||
%code%{
|
||||
|
Loading…
Reference in New Issue
Block a user