Merge branch 'master' of https://github.com/prusa3d/Slic3r
This commit is contained in:
commit
cdd415bb0c
7 changed files with 195 additions and 58 deletions
|
@ -5,8 +5,8 @@
|
|||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
#include "TriangleMesh.hpp"
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
#include <libslic3r/TriangleMesh.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace sla {
|
||||
|
@ -53,7 +53,7 @@ struct Contour3D {
|
|||
|
||||
void merge(const Contour3D& ctr) {
|
||||
auto s3 = coord_t(points.size());
|
||||
auto s = coord_t(indices.size());
|
||||
auto s = indices.size();
|
||||
|
||||
points.insert(points.end(), ctr.points.begin(), ctr.points.end());
|
||||
indices.insert(indices.end(), ctr.indices.begin(), ctr.indices.end());
|
||||
|
@ -62,6 +62,17 @@ struct Contour3D {
|
|||
auto& idx = indices[n]; x(idx) += s3; y(idx) += s3; z(idx) += s3;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the index triangle structure to OBJ file for debugging purposes.
|
||||
void to_obj(std::ostream& stream) {
|
||||
for(auto& p : points) {
|
||||
stream << "v " << p.transpose() << "\n";
|
||||
}
|
||||
|
||||
for(auto& f : indices) {
|
||||
stream << "f " << (f + Vec3i(1, 1, 1)).transpose() << "\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//using PointSet = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign>; //Eigen::MatrixXd;
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#include "SLASpatIndex.hpp"
|
||||
#include "SLABasePool.hpp"
|
||||
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Model.hpp"
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
#include <libslic3r/Model.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
|
@ -176,6 +176,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||
Vec3d jp = {0, 0, 0};
|
||||
Vec3d endp = {0, 0, h};
|
||||
|
||||
// Upper circle points
|
||||
for(int i = 0; i < steps; ++i) {
|
||||
double phi = i*a;
|
||||
double ex = endp(X) + r*std::cos(phi);
|
||||
|
@ -183,6 +184,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||
points.emplace_back(ex, ey, endp(Z));
|
||||
}
|
||||
|
||||
// Lower circle points
|
||||
for(int i = 0; i < steps; ++i) {
|
||||
double phi = i*a;
|
||||
double x = jp(X) + r*std::cos(phi);
|
||||
|
@ -190,6 +192,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||
points.emplace_back(x, y, jp(Z));
|
||||
}
|
||||
|
||||
// Now create long triangles connecting upper and lower circles
|
||||
indices.reserve(2*ssteps);
|
||||
auto offs = steps;
|
||||
for(int i = 0; i < steps - 1; ++i) {
|
||||
|
@ -197,10 +200,26 @@ Contour3D cylinder(double r, double h, size_t ssteps) {
|
|||
indices.emplace_back(i, offs + i + 1, i + 1);
|
||||
}
|
||||
|
||||
// Last triangle connecting the first and last vertices
|
||||
auto last = steps - 1;
|
||||
indices.emplace_back(0, last, offs);
|
||||
indices.emplace_back(last, offs + last, offs);
|
||||
|
||||
// According to the slicing algorithms, we need to aid them with generating
|
||||
// a watertight body. So we create a triangle fan for the upper and lower
|
||||
// ending of the cylinder to close the geometry.
|
||||
points.emplace_back(jp); size_t ci = points.size() - 1;
|
||||
for(int i = 0; i < steps - 1; ++i)
|
||||
indices.emplace_back(i + offs + 1, i + offs, ci);
|
||||
|
||||
indices.emplace_back(offs, steps + offs - 1, ci);
|
||||
|
||||
points.emplace_back(endp); ci = points.size() - 1;
|
||||
for(int i = 0; i < steps - 1; ++i)
|
||||
indices.emplace_back(ci, i, i + 1);
|
||||
|
||||
indices.emplace_back(steps - 1, 0, ci);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -352,6 +371,8 @@ struct Pillar {
|
|||
r(radius), steps(st), endpoint(endp), starts_from_head(false)
|
||||
{
|
||||
assert(steps > 0);
|
||||
assert(jp(Z) > endp(Z)); // Endpoint is below the starting point
|
||||
|
||||
int steps_1 = int(steps - 1);
|
||||
|
||||
auto& points = mesh.points;
|
||||
|
@ -382,6 +403,22 @@ struct Pillar {
|
|||
|
||||
indices.emplace_back(0, steps_1, offs);
|
||||
indices.emplace_back(steps_1, offs + steps_1, offs);
|
||||
|
||||
// According to the slicing algorithms, we need to aid them with
|
||||
// generating a watertight body. So we create a triangle fan for the
|
||||
// upper and lower ending of the cylinder to close the geometry.
|
||||
points.emplace_back(jp); size_t ci = points.size() - 1;
|
||||
int stepsi = int(steps);
|
||||
for(int i = 0; i < stepsi - 1; ++i)
|
||||
indices.emplace_back(ci, i, i + 1);
|
||||
|
||||
indices.emplace_back(stepsi - 1, 0, ci);
|
||||
|
||||
points.emplace_back(endp); ci = points.size() - 1;
|
||||
for(int i = 0; i < stepsi - 1; ++i)
|
||||
indices.emplace_back(i + offs + 1, i + offs, ci);
|
||||
|
||||
indices.emplace_back(offs, stepsi + offs - 1, ci);
|
||||
}
|
||||
|
||||
Pillar(const Junction& junc, const Vec3d& endp):
|
||||
|
@ -461,6 +498,8 @@ struct Bridge {
|
|||
Vec3d dir = (j2 - j1).normalized();
|
||||
double d = distance(j2, j1);
|
||||
|
||||
assert(d > 0);
|
||||
|
||||
mesh = cylinder(r, d, steps);
|
||||
|
||||
auto quater = Quaternion::FromTwoVectors(Vec3d{0,0,1}, dir);
|
||||
|
|
|
@ -270,16 +270,11 @@ void GUI_App::set_label_clr_sys(const wxColour& clr) {
|
|||
|
||||
void GUI_App::recreate_GUI()
|
||||
{
|
||||
std::cerr << "recreate_GUI" << std::endl;
|
||||
// to make sure nobody accesses data from the soon-to-be-destroyed widgets:
|
||||
tabs_list.clear();
|
||||
plater_ = nullptr;
|
||||
|
||||
clear_tabs_list();
|
||||
if (plater_) {
|
||||
// before creating a new plater let's delete old one
|
||||
plater_->Destroy();
|
||||
plater_ = nullptr;
|
||||
}
|
||||
|
||||
MainFrame* topwindow = dynamic_cast<MainFrame*>(GetTopWindow());
|
||||
MainFrame* topwindow = mainframe;
|
||||
mainframe = new MainFrame();
|
||||
sidebar().obj_list()->init_objects(); // propagate model objects to object list
|
||||
|
||||
|
@ -691,15 +686,6 @@ void GUI_App::load_current_presets()
|
|||
}
|
||||
}
|
||||
|
||||
void GUI_App::clear_tabs_list()
|
||||
{
|
||||
for (auto tab : tabs_list) {
|
||||
tab->Destroy();
|
||||
tab = nullptr;
|
||||
}
|
||||
tabs_list.clear();
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
// wxWidgets override to get an event on open files.
|
||||
void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
||||
|
|
|
@ -134,7 +134,6 @@ public:
|
|||
bool check_unsaved_changes();
|
||||
bool checked_tab(Tab* tab);
|
||||
void load_current_presets();
|
||||
void clear_tabs_list();
|
||||
|
||||
#ifdef __APPLE__
|
||||
// wxWidgets override to get an event on open files.
|
||||
|
|
|
@ -21,8 +21,6 @@ namespace GUI
|
|||
|
||||
wxDEFINE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
|
||||
|
||||
typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle;
|
||||
|
||||
// pt_FFF
|
||||
FreqSettingsBundle FREQ_SETTINGS_BUNDLE_FFF =
|
||||
{
|
||||
|
@ -587,9 +585,9 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
|
||||
// Context Menu
|
||||
|
||||
std::vector<std::string> get_options(const bool is_part, const bool is_sla)
|
||||
std::vector<std::string> ObjectList::get_options(const bool is_part)
|
||||
{
|
||||
if (is_sla) {
|
||||
if (wxGetApp().plater()->printer_technology() == ptSLA) {
|
||||
SLAPrintObjectConfig full_sla_config;
|
||||
auto options = full_sla_config.keys();
|
||||
options.erase(find(options.begin(), options.end(), "layer_height"));
|
||||
|
@ -605,13 +603,8 @@ std::vector<std::string> get_options(const bool is_part, const bool is_sla)
|
|||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
std::vector<std::string> get_options(const bool is_part)
|
||||
{
|
||||
return get_options(is_part, wxGetApp().plater()->printer_technology() == ptSLA);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& get_options_for_bundle(const wxString& bundle_name)
|
||||
const std::vector<std::string>& ObjectList::get_options_for_bundle(const wxString& bundle_name)
|
||||
{
|
||||
const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
FREQ_SETTINGS_BUNDLE_SLA : FREQ_SETTINGS_BUNDLE_FFF;
|
||||
|
@ -621,15 +614,25 @@ const std::vector<std::string>& get_options_for_bundle(const wxString& bundle_na
|
|||
if (bundle_name == _(it.first))
|
||||
return it.second;
|
||||
}
|
||||
#if 0
|
||||
// if "Quick menu" is selected
|
||||
FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
m_freq_settings_sla: m_freq_settings_fff;
|
||||
|
||||
for (auto& it : bundle_quick)
|
||||
{
|
||||
if ( bundle_name == wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)) )
|
||||
return it.second;
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::vector<std::string> empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
// category -> vector ( option ; label )
|
||||
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
|
||||
void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part, const bool is_sla)
|
||||
void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part)
|
||||
{
|
||||
auto options = get_options(is_part, is_sla);
|
||||
auto options = get_options(is_part);
|
||||
|
||||
auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
|
||||
wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
|
@ -654,11 +657,6 @@ void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part
|
|||
}
|
||||
}
|
||||
|
||||
void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part)
|
||||
{
|
||||
get_options_menu(settings_menu, is_part, wxGetApp().plater()->printer_technology() == ptSLA);
|
||||
}
|
||||
|
||||
void ObjectList::get_settings_choice(const wxString& category_name)
|
||||
{
|
||||
wxArrayString names;
|
||||
|
@ -692,10 +690,59 @@ void ObjectList::get_settings_choice(const wxString& category_name)
|
|||
if (wxGetSelectedChoices(selections, _(L("Select showing settings")), category_name, names) == -1)
|
||||
return;
|
||||
|
||||
const int selection_cnt = selections.size();
|
||||
#if 0
|
||||
if (selection_cnt > 0)
|
||||
{
|
||||
// Add selected items to the "Quick menu"
|
||||
FreqSettingsBundle& freq_settings = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
m_freq_settings_sla : m_freq_settings_fff;
|
||||
bool changed_existing = false;
|
||||
|
||||
std::vector<std::string> tmp_freq_cat = {};
|
||||
|
||||
for (auto& cat : freq_settings)
|
||||
{
|
||||
if (_(cat.first) == category_name)
|
||||
{
|
||||
std::vector<std::string>& freq_settings_category = cat.second;
|
||||
freq_settings_category.clear();
|
||||
freq_settings_category.reserve(selection_cnt);
|
||||
for (auto sel : selections)
|
||||
freq_settings_category.push_back((*settings_list)[sel].first);
|
||||
|
||||
changed_existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed_existing)
|
||||
{
|
||||
// Create new "Quick menu" item
|
||||
for (auto& cat : settings_menu)
|
||||
{
|
||||
if (_(cat.first) == category_name)
|
||||
{
|
||||
freq_settings[cat.first] = std::vector<std::string> {};
|
||||
|
||||
std::vector<std::string>& freq_settings_category = freq_settings.find(cat.first)->second;
|
||||
freq_settings_category.reserve(selection_cnt);
|
||||
for (auto sel : selections)
|
||||
freq_settings_category.push_back((*settings_list)[sel].first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector <std::string> selected_options;
|
||||
selected_options.reserve(selection_cnt);
|
||||
for (auto sel : selections)
|
||||
selected_options.push_back((*settings_list)[sel].first);
|
||||
|
||||
const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
|
||||
for (auto& setting : (*settings_list))
|
||||
{
|
||||
auto& opt_key = setting.first;
|
||||
|
@ -704,8 +751,17 @@ void ObjectList::get_settings_choice(const wxString& category_name)
|
|||
m_config->erase(opt_key);
|
||||
|
||||
if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() &&
|
||||
find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end())
|
||||
m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone());
|
||||
find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end()) {
|
||||
const ConfigOption* option = from_config.option(opt_key);
|
||||
if (!option) {
|
||||
// if current option doesn't exist in prints.get_edited_preset(),
|
||||
// get it from m_default_config
|
||||
if (m_default_config) delete m_default_config;
|
||||
m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false));
|
||||
option = m_default_config->option(opt_key);
|
||||
}
|
||||
m_config->set_key_value(opt_key, option->clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -719,10 +775,20 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name)
|
|||
|
||||
auto opt_keys = m_config->keys();
|
||||
|
||||
const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
for (auto& opt_key : options)
|
||||
{
|
||||
if ( find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() )
|
||||
m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone());
|
||||
if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end()) {
|
||||
const ConfigOption* option = from_config.option(opt_key);
|
||||
if (!option) {
|
||||
// if current option doesn't exist in prints.get_edited_preset(),
|
||||
// get it from m_default_config
|
||||
if (m_default_config) delete m_default_config;
|
||||
m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false));
|
||||
option = m_default_config->option(opt_key);
|
||||
}
|
||||
m_config->set_key_value(opt_key, option->clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Add settings item for object
|
||||
|
@ -836,7 +902,20 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
|||
if (settings_id != wxNOT_FOUND)
|
||||
menu->Destroy(settings_id);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (auto& it : m_freq_settings_fff)
|
||||
{
|
||||
settings_id = menu->FindItem(wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)));
|
||||
if (settings_id != wxNOT_FOUND)
|
||||
menu->Destroy(settings_id);
|
||||
}
|
||||
for (auto& it : m_freq_settings_sla)
|
||||
{
|
||||
settings_id = menu->FindItem(wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)));
|
||||
if (settings_id != wxNOT_FOUND)
|
||||
menu->Destroy(settings_id);
|
||||
}
|
||||
#endif
|
||||
menu->DestroySeparators(); // delete old separators
|
||||
|
||||
const auto sel_vol = get_selected_model_volume();
|
||||
|
@ -938,6 +1017,7 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
|
|||
|
||||
void ObjectList::create_freq_settings_popupmenu(wxMenu *menu)
|
||||
{
|
||||
// Add default settings bundles
|
||||
const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptFFF ?
|
||||
FREQ_SETTINGS_BUNDLE_FFF : FREQ_SETTINGS_BUNDLE_SLA;
|
||||
|
||||
|
@ -952,6 +1032,20 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu)
|
|||
[menu, this](wxCommandEvent& event) { get_freq_settings_choice(menu->GetLabel(event.GetId())); },
|
||||
CATEGORY_ICON.find(it.first) == CATEGORY_ICON.end() ? wxNullBitmap : CATEGORY_ICON.at(it.first), menu);
|
||||
}
|
||||
#if 0
|
||||
// Add "Quick" settings bundles
|
||||
const FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptFFF ?
|
||||
m_freq_settings_fff : m_freq_settings_sla;
|
||||
|
||||
for (auto& it : bundle_quick) {
|
||||
if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1)
|
||||
continue;
|
||||
|
||||
append_menu_item(menu, wxID_ANY, wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)), "",
|
||||
[menu, this](wxCommandEvent& event) { get_freq_settings_choice(menu->GetLabel(event.GetId())); },
|
||||
CATEGORY_ICON.find(it.first) == CATEGORY_ICON.end() ? wxNullBitmap : CATEGORY_ICON.at(it.first), menu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObjectList::update_opt_keys(t_config_option_keys& opt_keys)
|
||||
|
@ -1379,9 +1473,6 @@ void ObjectList::part_selection_changed()
|
|||
m_config = &(*m_objects)[obj_idx_]->config;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_default_config) delete m_default_config;
|
||||
m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@ class ModelVolume;
|
|||
// FIXME: broken build on mac os because of this is missing:
|
||||
typedef std::vector<std::string> t_config_option_keys;
|
||||
|
||||
typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle;
|
||||
|
||||
// category -> vector ( option ; label )
|
||||
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
|
||||
|
@ -129,6 +134,11 @@ class ObjectList : public wxDataViewCtrl
|
|||
|
||||
int m_selected_row = 0;
|
||||
|
||||
#if 0
|
||||
FreqSettingsBundle m_freq_settings_fff;
|
||||
FreqSettingsBundle m_freq_settings_sla;
|
||||
#endif
|
||||
|
||||
public:
|
||||
ObjectList(wxWindow* parent);
|
||||
~ObjectList();
|
||||
|
@ -264,6 +274,10 @@ private:
|
|||
|
||||
void ItemValueChanged(wxDataViewEvent &event);
|
||||
void OnEditingDone(wxDataViewEvent &event);
|
||||
|
||||
std::vector<std::string> get_options(const bool is_part);
|
||||
const std::vector<std::string>& get_options_for_bundle(const wxString& bundle_name);
|
||||
void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -95,14 +95,10 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
|||
_3DScene::remove_all_canvases();
|
||||
// Slic3r::GUI::deregister_on_request_update_callback();
|
||||
|
||||
// destroy and set to null tabs and a platter
|
||||
// set to null tabs and a platter
|
||||
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
|
||||
wxGetApp().clear_tabs_list();
|
||||
if (wxGetApp().plater_) {
|
||||
// before creating a new plater let's delete old one
|
||||
wxGetApp().plater_->Destroy();
|
||||
wxGetApp().plater_ = nullptr;
|
||||
}
|
||||
wxGetApp().tabs_list.clear();
|
||||
wxGetApp().plater_ = nullptr;
|
||||
|
||||
// propagate event
|
||||
event.Skip();
|
||||
|
@ -113,6 +109,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
|||
update_ui_from_settings(); // FIXME (?)
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::init_tabpanel()
|
||||
{
|
||||
m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
||||
|
|
Loading…
Reference in a new issue