Merge branch 'master' of https://github.com/Prusa3d/PrusaSlicer
This commit is contained in:
commit
fb9d537b58
14 changed files with 1376 additions and 1415 deletions
|
@ -28,6 +28,7 @@ src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
|
|||
src/slic3r/GUI/GUI.cpp
|
||||
src/slic3r/GUI/GUI_App.cpp
|
||||
src/slic3r/GUI/GUI_Init.cpp
|
||||
src/slic3r/GUI/GUI_Factories.cpp
|
||||
src/slic3r/GUI/GUI_ObjectLayers.cpp
|
||||
src/slic3r/GUI/GUI_ObjectList.cpp
|
||||
src/slic3r/GUI/GUI_ObjectManipulation.cpp
|
||||
|
|
|
@ -1302,52 +1302,54 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
|||
|
||||
void ModelObject::split(ModelObjectPtrs* new_objects)
|
||||
{
|
||||
if (this->volumes.size() > 1) {
|
||||
// We can't split meshes if there's more than one volume, because
|
||||
// we can't group the resulting meshes by object afterwards
|
||||
new_objects->emplace_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ModelVolume* volume = this->volumes.front();
|
||||
TriangleMeshPtrs meshptrs = volume->mesh().split();
|
||||
size_t counter = 1;
|
||||
for (TriangleMesh *mesh : meshptrs) {
|
||||
for (ModelVolume* volume : this->volumes) {
|
||||
if (volume->type() != ModelVolumeType::MODEL_PART)
|
||||
continue;
|
||||
|
||||
// FIXME: crashes if not satisfied
|
||||
if (mesh->facets_count() < 3) continue;
|
||||
TriangleMeshPtrs meshptrs = volume->mesh().split();
|
||||
size_t counter = 1;
|
||||
for (TriangleMesh* mesh : meshptrs) {
|
||||
|
||||
mesh->repair();
|
||||
|
||||
// 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 + (meshptrs.size() > 1 ? "_" + std::to_string(counter++) : "");
|
||||
// FIXME: crashes if not satisfied
|
||||
if (mesh->facets_count() < 3) continue;
|
||||
|
||||
// Don't copy the config's ID.
|
||||
new_object->config.assign_config(this->config);
|
||||
assert(new_object->config.id().valid());
|
||||
assert(new_object->config.id() != this->config.id());
|
||||
new_object->instances.reserve(this->instances.size());
|
||||
for (const ModelInstance *model_instance : this->instances)
|
||||
new_object->add_instance(*model_instance);
|
||||
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh));
|
||||
mesh->repair();
|
||||
|
||||
for (ModelInstance* model_instance : new_object->instances)
|
||||
{
|
||||
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
|
||||
model_instance->set_offset(model_instance->get_offset() + shift);
|
||||
// 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();
|
||||
if (meshptrs.size() == 1) {
|
||||
new_object->name = volume->name;
|
||||
// Don't copy the config's ID.
|
||||
new_object->config.assign_config(this->config.size() > 0 ? this->config : volume->config);
|
||||
}
|
||||
else {
|
||||
new_object->name = this->name + (meshptrs.size() > 1 ? "_" + std::to_string(counter++) : "");
|
||||
// Don't copy the config's ID.
|
||||
new_object->config.assign_config(this->config);
|
||||
}
|
||||
assert(new_object->config.id().valid());
|
||||
assert(new_object->config.id() != this->config.id());
|
||||
new_object->instances.reserve(this->instances.size());
|
||||
for (const ModelInstance* model_instance : this->instances)
|
||||
new_object->add_instance(*model_instance);
|
||||
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh));
|
||||
|
||||
for (ModelInstance* model_instance : new_object->instances)
|
||||
{
|
||||
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
|
||||
model_instance->set_offset(model_instance->get_offset() + shift);
|
||||
}
|
||||
|
||||
new_vol->set_offset(Vec3d::Zero());
|
||||
// reset the source to disable reload from disk
|
||||
new_vol->source = ModelVolume::Source();
|
||||
new_objects->emplace_back(new_object);
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
new_vol->set_offset(Vec3d::Zero());
|
||||
// reset the source to disable reload from disk
|
||||
new_vol->source = ModelVolume::Source();
|
||||
new_objects->emplace_back(new_object);
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ModelObject::merge()
|
||||
{
|
||||
if (this->volumes.size() == 1) {
|
||||
|
@ -1738,6 +1740,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
|||
this->object->volumes[ivolume]->translate(offset);
|
||||
this->object->volumes[ivolume]->name = name + "_" + std::to_string(idx + 1);
|
||||
this->object->volumes[ivolume]->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter));
|
||||
this->object->volumes[ivolume]->m_is_splittable = 0;
|
||||
delete mesh;
|
||||
++ idx;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/SavePresetDialog.cpp
|
||||
GUI/PhysicalPrinterDialog.hpp
|
||||
GUI/PhysicalPrinterDialog.cpp
|
||||
GUI/GUI_Factories.cpp
|
||||
GUI/GUI_Factories.hpp
|
||||
GUI/GUI_ObjectList.cpp
|
||||
GUI/GUI_ObjectList.hpp
|
||||
GUI/GUI_ObjectManipulation.cpp
|
||||
|
|
1027
src/slic3r/GUI/GUI_Factories.cpp
Normal file
1027
src/slic3r/GUI/GUI_Factories.cpp
Normal file
File diff suppressed because it is too large
Load diff
104
src/slic3r/GUI/GUI_Factories.hpp
Normal file
104
src/slic3r/GUI/GUI_Factories.hpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
#ifndef slic3r_GUI_Factories_hpp_
|
||||
#define slic3r_GUI_Factories_hpp_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
class wxMenu;
|
||||
class wxMenuItem;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class ModelVolumeType : int;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
struct SettingsFactory
|
||||
{
|
||||
// category -> vector ( option )
|
||||
typedef std::map<std::string, std::vector<std::string>> Bundle;
|
||||
static std::map<std::string, std::string> CATEGORY_ICON;
|
||||
|
||||
static wxBitmap get_category_bitmap(const std::string& category_name);
|
||||
static Bundle get_bundle(const DynamicPrintConfig* config, bool is_object_settings);
|
||||
static std::vector<std::string> get_options(bool is_part);
|
||||
};
|
||||
|
||||
class MenuFactory
|
||||
{
|
||||
public:
|
||||
static std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS;
|
||||
static std::vector<wxBitmap> get_volume_bitmaps();
|
||||
|
||||
MenuFactory();
|
||||
~MenuFactory() = default;
|
||||
|
||||
void init(wxWindow* parent);
|
||||
void update_object_menu();
|
||||
void msw_rescale();
|
||||
|
||||
wxMenu* default_menu();
|
||||
wxMenu* object_menu();
|
||||
wxMenu* sla_object_menu();
|
||||
wxMenu* part_menu();
|
||||
wxMenu* instance_menu();
|
||||
wxMenu* layer_menu();
|
||||
wxMenu* multi_selection_menu();
|
||||
|
||||
private:
|
||||
enum MenuType {
|
||||
mtObjectFFF = 0,
|
||||
mtObjectSLA,
|
||||
mtCount
|
||||
};
|
||||
|
||||
wxWindow* m_parent {nullptr};
|
||||
|
||||
MenuWithSeparators m_object_menu;
|
||||
MenuWithSeparators m_part_menu;
|
||||
MenuWithSeparators m_sla_object_menu;
|
||||
MenuWithSeparators m_default_menu;
|
||||
MenuWithSeparators m_instance_menu;
|
||||
|
||||
// Removed/Prepended Items according to the view mode
|
||||
std::array<wxMenuItem*, mtCount> items_increase;
|
||||
std::array<wxMenuItem*, mtCount> items_decrease;
|
||||
std::array<wxMenuItem*, mtCount> items_set_number_of_copies;
|
||||
|
||||
void create_default_menu();
|
||||
void create_common_object_menu(wxMenu *menu);
|
||||
void create_object_menu();
|
||||
void create_sla_object_menu();
|
||||
void create_part_menu();
|
||||
|
||||
wxMenu* append_submenu_add_generic(wxMenu* menu, ModelVolumeType type);
|
||||
void append_menu_items_add_volume(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_printable(wxMenu* menu);
|
||||
void append_menu_items_osx(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu);
|
||||
void append_menu_item_export_stl(wxMenu* menu);
|
||||
void append_menu_item_reload_from_disk(wxMenu* menu);
|
||||
void append_menu_item_change_extruder(wxMenu* menu);
|
||||
void append_menu_item_delete(wxMenu* menu);
|
||||
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
|
||||
void append_menu_items_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
|
||||
void append_menu_item_merge_to_multipart_object(wxMenu *menu);
|
||||
// void append_menu_item_merge_to_single_object(wxMenu *menu);
|
||||
void append_menu_items_mirror(wxMenu *menu);
|
||||
void append_menu_items_instance_manipulation(wxMenu *menu);
|
||||
void update_menu_items_instance_manipulation(MenuType type);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif //slic3r_GUI_Factories_hpp_
|
|
@ -260,16 +260,15 @@ void ObjectLayers::msw_rescale()
|
|||
editor->msw_rescale();
|
||||
}
|
||||
|
||||
const std::vector<size_t> btns = {2, 3}; // del_btn, add_btn
|
||||
for (auto btn : btns)
|
||||
{
|
||||
wxSizerItem* b_item = item->GetSizer()->GetItem(btn);
|
||||
if (b_item->IsWindow()) {
|
||||
auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
|
||||
if (button != nullptr)
|
||||
button->msw_rescale();
|
||||
}
|
||||
}
|
||||
if (item->GetSizer()->GetItemCount() > 2) // if there are Add/Del buttons
|
||||
for (size_t btn : {2, 3}) { // del_btn, add_btn
|
||||
wxSizerItem* b_item = item->GetSizer()->GetItem(btn);
|
||||
if (b_item->IsWindow()) {
|
||||
auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
|
||||
if (button != nullptr)
|
||||
button->msw_rescale();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_grid_sizer->Layout();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,18 +31,11 @@ class TriangleMesh;
|
|||
enum class ModelVolumeType : int;
|
||||
|
||||
// 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>> SettingsBundle;
|
||||
|
||||
// category -> vector ( option ; label )
|
||||
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
|
||||
|
||||
typedef std::vector<ModelVolume*> ModelVolumePtrs;
|
||||
|
||||
typedef double coordf_t;
|
||||
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
|
||||
typedef std::map<t_layer_height_range, ModelConfig> t_layer_config_ranges;
|
||||
typedef std::vector<std::string> t_config_option_keys;
|
||||
typedef std::vector<ModelVolume*> ModelVolumePtrs;
|
||||
typedef double coordf_t;
|
||||
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
|
||||
typedef std::map<t_layer_height_range, ModelConfig> t_layer_config_ranges;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
|
@ -106,7 +99,7 @@ public:
|
|||
|
||||
private:
|
||||
SELECTION_MODE m_selection_mode {smUndef};
|
||||
int m_selected_layers_range_idx;
|
||||
int m_selected_layers_range_idx {-1};
|
||||
|
||||
Clipboard m_clipboard;
|
||||
|
||||
|
@ -147,23 +140,6 @@ private:
|
|||
} m_dragged_data;
|
||||
|
||||
wxBoxSizer *m_sizer {nullptr};
|
||||
wxWindow *m_parent {nullptr};
|
||||
|
||||
ScalableBitmap m_bmp_modifiermesh;
|
||||
ScalableBitmap m_bmp_solidmesh;
|
||||
ScalableBitmap m_bmp_support_enforcer;
|
||||
ScalableBitmap m_bmp_support_blocker;
|
||||
ScalableBitmap m_bmp_manifold_warning;
|
||||
ScalableBitmap m_bmp_cog;
|
||||
|
||||
MenuWithSeparators m_menu_object;
|
||||
MenuWithSeparators m_menu_part;
|
||||
MenuWithSeparators m_menu_sla_object;
|
||||
MenuWithSeparators m_menu_instance;
|
||||
MenuWithSeparators m_menu_layer;
|
||||
MenuWithSeparators m_menu_default;
|
||||
wxMenuItem* m_menu_item_settings { nullptr };
|
||||
wxMenuItem* m_menu_item_split_instances { nullptr };
|
||||
|
||||
ObjectDataViewModel *m_objects_model{ nullptr };
|
||||
ModelConfig *m_config {nullptr};
|
||||
|
@ -185,7 +161,6 @@ private:
|
|||
// update_settings_items - updating canvas selection is undesirable,
|
||||
// because it would turn off the gizmos (mainly a problem for the SLA gizmo)
|
||||
|
||||
int m_selected_row = 0;
|
||||
wxDataViewItem m_last_selected_item {nullptr};
|
||||
#ifdef __WXMSW__
|
||||
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
||||
|
@ -193,8 +168,8 @@ private:
|
|||
#endif /* __MSW__ */
|
||||
|
||||
#if 0
|
||||
SettingsBundle m_freq_settings_fff;
|
||||
SettingsBundle m_freq_settings_sla;
|
||||
SettingsFactory::Bundle m_freq_settings_fff;
|
||||
SettingsFactory::Bundle m_freq_settings_sla;
|
||||
#endif
|
||||
|
||||
size_t m_items_count { size_t(-1) };
|
||||
|
@ -212,8 +187,6 @@ public:
|
|||
void set_min_height();
|
||||
void update_min_height();
|
||||
|
||||
std::map<std::string, wxBitmap> CATEGORY_ICON;
|
||||
|
||||
ObjectDataViewModel* GetModel() const { return m_objects_model; }
|
||||
ModelConfig* config() const { return m_config; }
|
||||
std::vector<ModelObject*>* objects() const { return m_objects; }
|
||||
|
@ -221,7 +194,6 @@ public:
|
|||
ModelObject* object(const int obj_idx) const ;
|
||||
|
||||
void create_objects_ctrl();
|
||||
void create_popup_menus();
|
||||
void update_objects_list_extruder_column(size_t extruders_count);
|
||||
void update_extruder_colors();
|
||||
// show/hide "Extruder" column for Objects List
|
||||
|
@ -232,9 +204,6 @@ public:
|
|||
void update_name_in_model(const wxDataViewItem& item) const;
|
||||
void update_extruder_values_for_items(const size_t max_extruder);
|
||||
|
||||
void init_icons();
|
||||
void msw_rescale_icons();
|
||||
|
||||
// Get obj_idx and vol_idx values for the selected (by default) or an adjusted item
|
||||
void get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& item = wxDataViewItem(0));
|
||||
void get_selection_indexes(std::vector<int>& obj_idxs, std::vector<int>& vol_idxs);
|
||||
|
@ -264,39 +233,11 @@ public:
|
|||
void increase_instances();
|
||||
void decrease_instances();
|
||||
|
||||
void get_settings_choice(const wxString& category_name);
|
||||
void get_freq_settings_choice(const wxString& bundle_name);
|
||||
void add_category_to_settings_from_selection(const std::vector< std::pair<std::string, bool> >& category_options, wxDataViewItem item);
|
||||
void add_category_to_settings_from_frequent(const std::vector<std::string>& category_options, wxDataViewItem item);
|
||||
void show_settings(const wxDataViewItem settings_item);
|
||||
bool is_instance_or_object_selected();
|
||||
|
||||
wxMenu* append_submenu_add_generic(wxMenu* menu, const ModelVolumeType type);
|
||||
void append_menu_items_add_volume(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_split(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu, wxWindow* parent);
|
||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu, wxWindow* parent = nullptr);
|
||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent);
|
||||
wxMenuItem* append_menu_item_printable(wxMenu* menu, wxWindow* parent);
|
||||
void append_menu_items_osx(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu);
|
||||
void append_menu_item_export_stl(wxMenu* menu) const;
|
||||
void append_menu_item_reload_from_disk(wxMenu* menu) const;
|
||||
void append_menu_item_change_extruder(wxMenu* menu);
|
||||
void append_menu_item_delete(wxMenu* menu);
|
||||
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
|
||||
void append_menu_items_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
|
||||
void append_menu_item_merge_to_multipart_object(wxMenu *menu);
|
||||
void append_menu_item_merge_to_single_object(wxMenu *menu);
|
||||
void create_object_popupmenu(wxMenu *menu);
|
||||
void create_sla_object_popupmenu(wxMenu*menu);
|
||||
void create_part_popupmenu(wxMenu*menu);
|
||||
void create_instance_popupmenu(wxMenu*menu);
|
||||
void create_default_popupmenu(wxMenu *menu);
|
||||
wxMenu* create_settings_popupmenu(wxMenu *parent_menu);
|
||||
void create_freq_settings_popupmenu(wxMenu *parent_menu, const bool is_object_settings = true);
|
||||
|
||||
void update_opt_keys(t_config_option_keys& t_optopt_keys, const bool is_object);
|
||||
|
||||
void load_subobject(ModelVolumeType type);
|
||||
void load_part(ModelObject* model_object, std::vector<std::pair<wxString, bool>> &volumes_info, ModelVolumeType type);
|
||||
void load_generic_subobject(const std::string& type_name, const ModelVolumeType type);
|
||||
|
@ -318,7 +259,7 @@ public:
|
|||
|
||||
DynamicPrintConfig get_default_layer_config(const int obj_idx);
|
||||
bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume);
|
||||
bool is_splittable();
|
||||
bool is_splittable(bool to_objects);
|
||||
bool selected_instances_of_same_object();
|
||||
bool can_split_instances();
|
||||
bool can_merge_to_multipart_object() const;
|
||||
|
@ -328,7 +269,6 @@ public:
|
|||
wxBoxSizer* get_sizer() {return m_sizer;}
|
||||
int get_selected_obj_idx() const;
|
||||
ModelConfig& get_item_config(const wxDataViewItem& item) const;
|
||||
SettingsBundle get_item_settings_bundle(const DynamicPrintConfig* config, const bool is_object_settings);
|
||||
|
||||
void changed_object(const int obj_idx = -1) const;
|
||||
void part_selection_changed();
|
||||
|
@ -404,11 +344,9 @@ public:
|
|||
void change_part_type();
|
||||
|
||||
void last_volume_is_deleted(const int obj_idx);
|
||||
void update_settings_items();
|
||||
void update_and_show_object_settings_item();
|
||||
void update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections);
|
||||
void update_object_list_by_printer_technology();
|
||||
void update_object_menu();
|
||||
|
||||
void instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idx);
|
||||
void instances_to_separated_objects(const int obj_idx);
|
||||
|
@ -433,7 +371,7 @@ public:
|
|||
void update_printable_state(int obj_idx, int instance_idx);
|
||||
void toggle_printable_state(wxDataViewItem item);
|
||||
|
||||
void show_multi_selection_menu();
|
||||
void set_extruder_for_selected_items(const int extruder) const ;
|
||||
|
||||
private:
|
||||
#ifdef __WXOSX__
|
||||
|
@ -454,11 +392,6 @@ private:
|
|||
#endif /* __WXMSW__ */
|
||||
void OnEditingDone(wxDataViewEvent &event);
|
||||
void extruder_selection();
|
||||
void set_extruder_for_selected_items(const int extruder) const ;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "GUI_ObjectSettings.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "GUI_Factories.hpp"
|
||||
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
@ -83,7 +84,7 @@ bool ObjectSettings::update_settings_list()
|
|||
return false;
|
||||
|
||||
const bool is_object_settings = objects_model->GetItemType(objects_model->GetParent(item)) == itObject;
|
||||
SettingsBundle cat_options = objects_ctrl->get_item_settings_bundle(&config->get(), is_object_settings);
|
||||
SettingsFactory::Bundle cat_options = SettingsFactory::get_bundle(&config->get(), is_object_settings);
|
||||
|
||||
if (!cat_options.empty())
|
||||
{
|
||||
|
|
|
@ -562,8 +562,6 @@ void MainFrame::init_tabpanel()
|
|||
|
||||
wxGetApp().plater_ = m_plater;
|
||||
|
||||
wxGetApp().obj_list()->create_popup_menus();
|
||||
|
||||
if (wxGetApp().is_editor())
|
||||
create_preset_tabs();
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "wxExtensions.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "GUI_Factories.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
@ -44,8 +44,9 @@ void ObjectDataViewModelNode::init_container()
|
|||
#endif //__WXGTK__
|
||||
}
|
||||
|
||||
#define LAYER_ROOT_ICON "edit_layers_all"
|
||||
#define LAYER_ICON "edit_layers_some"
|
||||
static constexpr char LayerRootIcon[] = "edit_layers_all";
|
||||
static constexpr char LayerIcon[] = "edit_layers_some";
|
||||
static constexpr char WarningIcon[] = "exclamation";
|
||||
|
||||
ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type) :
|
||||
m_parent(parent),
|
||||
|
@ -65,7 +66,7 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
|||
}
|
||||
else if (type == itLayerRoot)
|
||||
{
|
||||
m_bmp = create_scaled_bitmap(LAYER_ROOT_ICON); // FIXME: pass window ptr
|
||||
m_bmp = create_scaled_bitmap(LayerRootIcon); // FIXME: pass window ptr
|
||||
m_name = _(L("Layers"));
|
||||
}
|
||||
|
||||
|
@ -94,7 +95,7 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
|||
}
|
||||
const std::string label_range = (boost::format(" %.2f-%.2f ") % layer_range.first % layer_range.second).str();
|
||||
m_name = _(L("Range")) + label_range + "(" + _(L("mm")) + ")";
|
||||
m_bmp = create_scaled_bitmap(LAYER_ICON); // FIXME: pass window ptr
|
||||
m_bmp = create_scaled_bitmap(LayerIcon); // FIXME: pass window ptr
|
||||
|
||||
set_action_and_extruder_icons();
|
||||
init_container();
|
||||
|
@ -140,17 +141,14 @@ void ObjectDataViewModelNode::update_settings_digest_bitmaps()
|
|||
{
|
||||
m_bmp = m_empty_bmp;
|
||||
|
||||
std::map<std::string, wxBitmap>& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON;
|
||||
|
||||
std::string scaled_bitmap_name = m_name.ToUTF8().data();
|
||||
scaled_bitmap_name += "-em" + std::to_string(wxGetApp().em_unit()) + (wxGetApp().dark_mode() ? "-dm" : "");
|
||||
|
||||
wxBitmap *bmp = m_bitmap_cache->find(scaled_bitmap_name);
|
||||
if (bmp == nullptr) {
|
||||
std::vector<wxBitmap> bmps;
|
||||
for (auto& cat : m_opt_categories)
|
||||
bmps.emplace_back( categories_icon.find(cat) == categories_icon.end() ?
|
||||
wxNullBitmap : categories_icon.at(cat));
|
||||
for (auto& category : m_opt_categories)
|
||||
bmps.emplace_back(SettingsFactory::get_category_bitmap(category));
|
||||
bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps);
|
||||
}
|
||||
|
||||
|
@ -249,6 +247,9 @@ static int get_root_idx(ObjectDataViewModelNode *parent_node, const ItemType roo
|
|||
ObjectDataViewModel::ObjectDataViewModel()
|
||||
{
|
||||
m_bitmap_cache = new Slic3r::GUI::BitmapCache;
|
||||
|
||||
m_volume_bmps = MenuFactory::get_volume_bitmaps();
|
||||
m_warning_bmp = create_scaled_bitmap(WarningIcon);
|
||||
}
|
||||
|
||||
ObjectDataViewModel::~ObjectDataViewModel()
|
||||
|
@ -267,7 +268,7 @@ wxDataViewItem ObjectDataViewModel::Add(const wxString &name,
|
|||
auto root = new ObjectDataViewModelNode(name, extruder_str);
|
||||
// Add error icon if detected auto-repaire
|
||||
if (has_errors)
|
||||
root->m_bmp = *m_warning_bmp;
|
||||
root->m_bmp = m_warning_bmp;
|
||||
|
||||
m_objects.push_back(root);
|
||||
// notify control
|
||||
|
@ -317,7 +318,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
|
|||
|
||||
// if part with errors is added, but object wasn't marked, then mark it
|
||||
if (!obj_errors && has_errors)
|
||||
root->SetBitmap(*m_warning_bmp);
|
||||
root->SetBitmap(m_warning_bmp);
|
||||
|
||||
// notify control
|
||||
const wxDataViewItem child((void*)node);
|
||||
|
@ -1434,10 +1435,20 @@ void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r
|
|||
return;
|
||||
|
||||
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
|
||||
node->SetBitmap(*m_volume_bmps[int(type)]);
|
||||
node->SetVolumeType(type);
|
||||
node->SetBitmap(m_volume_bmps[int(type)]);
|
||||
ItemChanged(item);
|
||||
}
|
||||
|
||||
ModelVolumeType ObjectDataViewModel::GetVolumeType(const wxDataViewItem& item)
|
||||
{
|
||||
if (!item.IsOk() || GetItemType(item) != itVolume)
|
||||
return ModelVolumeType::INVALID;
|
||||
|
||||
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
|
||||
return node->GetVolumeType();
|
||||
}
|
||||
|
||||
wxDataViewItem ObjectDataViewModel::SetPrintableState(
|
||||
PrintIndicator printable,
|
||||
int obj_idx,
|
||||
|
@ -1480,6 +1491,9 @@ wxDataViewItem ObjectDataViewModel::SetObjectPrintableState(
|
|||
|
||||
void ObjectDataViewModel::Rescale()
|
||||
{
|
||||
m_volume_bmps = MenuFactory::get_volume_bitmaps();
|
||||
m_warning_bmp = create_scaled_bitmap(WarningIcon);
|
||||
|
||||
wxDataViewItemArray all_items;
|
||||
GetAllChildren(wxDataViewItem(0), all_items);
|
||||
|
||||
|
@ -1494,15 +1508,15 @@ void ObjectDataViewModel::Rescale()
|
|||
switch (node->m_type)
|
||||
{
|
||||
case itObject:
|
||||
if (node->m_bmp.IsOk()) node->m_bmp = *m_warning_bmp;
|
||||
if (node->m_bmp.IsOk()) node->m_bmp = m_warning_bmp;
|
||||
break;
|
||||
case itVolume:
|
||||
node->m_bmp = GetVolumeIcon(node->m_volume_type, node->m_bmp.GetWidth() != node->m_bmp.GetHeight());
|
||||
break;
|
||||
case itLayerRoot:
|
||||
node->m_bmp = create_scaled_bitmap(LAYER_ROOT_ICON);
|
||||
node->m_bmp = create_scaled_bitmap(LayerRootIcon);
|
||||
case itLayer:
|
||||
node->m_bmp = create_scaled_bitmap(LAYER_ICON);
|
||||
node->m_bmp = create_scaled_bitmap(LayerIcon);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -1514,7 +1528,7 @@ void ObjectDataViewModel::Rescale()
|
|||
wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const bool is_marked/* = false*/)
|
||||
{
|
||||
if (!is_marked)
|
||||
return *m_volume_bmps[static_cast<int>(vol_type)];
|
||||
return m_volume_bmps[static_cast<int>(vol_type)];
|
||||
|
||||
std::string scaled_bitmap_name = "warning" + std::to_string(static_cast<int>(vol_type));
|
||||
scaled_bitmap_name += "-em" + std::to_string(Slic3r::GUI::wxGetApp().em_unit());
|
||||
|
@ -1523,8 +1537,8 @@ wxBitmap ObjectDataViewModel::GetVolumeIcon(const Slic3r::ModelVolumeType vol_ty
|
|||
if (bmp == nullptr) {
|
||||
std::vector<wxBitmap> bmps;
|
||||
|
||||
bmps.emplace_back(*m_warning_bmp);
|
||||
bmps.emplace_back(*m_volume_bmps[static_cast<int>(vol_type)]);
|
||||
bmps.emplace_back(m_warning_bmp);
|
||||
bmps.emplace_back(m_volume_bmps[static_cast<int>(vol_type)]);
|
||||
|
||||
bmp = m_bitmap_cache->insert(scaled_bitmap_name, bmps);
|
||||
}
|
||||
|
@ -1543,7 +1557,7 @@ void ObjectDataViewModel::DeleteWarningIcon(const wxDataViewItem& item, const bo
|
|||
return;
|
||||
|
||||
if (node->GetType() & itVolume) {
|
||||
node->SetBitmap(*m_volume_bmps[static_cast<int>(node->volume_type())]);
|
||||
node->SetBitmap(m_volume_bmps[static_cast<int>(node->volume_type())]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,13 +171,14 @@ public:
|
|||
}
|
||||
|
||||
bool SetValue(const wxVariant &variant, unsigned int col);
|
||||
|
||||
void SetVolumeType(ModelVolumeType type) { m_volume_type = type; }
|
||||
void SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
|
||||
const wxBitmap& GetBitmap() const { return m_bmp; }
|
||||
const wxString& GetName() const { return m_name; }
|
||||
ItemType GetType() const { return m_type; }
|
||||
void SetIdx(const int& idx);
|
||||
int GetIdx() const { return m_idx; }
|
||||
ModelVolumeType GetVolumeType() { return m_volume_type; }
|
||||
t_layer_height_range GetLayerRange() const { return m_layer_range; }
|
||||
PrintIndicator IsPrintable() const { return m_printable; }
|
||||
|
||||
|
@ -241,8 +242,8 @@ wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent);
|
|||
class ObjectDataViewModel :public wxDataViewModel
|
||||
{
|
||||
std::vector<ObjectDataViewModelNode*> m_objects;
|
||||
std::vector<wxBitmap*> m_volume_bmps;
|
||||
wxBitmap* m_warning_bmp { nullptr };
|
||||
std::vector<wxBitmap> m_volume_bmps;
|
||||
wxBitmap m_warning_bmp;
|
||||
|
||||
wxDataViewCtrl* m_ctrl { nullptr };
|
||||
|
||||
|
@ -348,9 +349,8 @@ public:
|
|||
void UpdateObjectPrintable(wxDataViewItem parent_item);
|
||||
void UpdateInstancesPrintable(wxDataViewItem parent_item);
|
||||
|
||||
void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
|
||||
void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; }
|
||||
void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
|
||||
ModelVolumeType GetVolumeType(const wxDataViewItem &item);
|
||||
wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx,
|
||||
int subobj_idx = -1,
|
||||
ItemType subobj_type = itInstance);
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "GUI_ObjectManipulation.hpp"
|
||||
#include "GUI_ObjectLayers.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "GUI_Factories.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
|
@ -1323,7 +1324,7 @@ void Sidebar::update_mode()
|
|||
|
||||
p->object_list->unselect_objects();
|
||||
p->object_list->update_selections();
|
||||
p->object_list->update_object_menu();
|
||||
// p->object_list->update_object_menu();
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
@ -1405,23 +1406,7 @@ struct Plater::priv
|
|||
Plater *q;
|
||||
MainFrame *main_frame;
|
||||
|
||||
// Object popup menu
|
||||
MenuWithSeparators object_menu;
|
||||
// Part popup menu
|
||||
MenuWithSeparators part_menu;
|
||||
// SLA-Object popup menu
|
||||
MenuWithSeparators sla_object_menu;
|
||||
// Default popup menu (when nothing is selected on 3DScene)
|
||||
MenuWithSeparators default_menu;
|
||||
|
||||
// Removed/Prepended Items according to the view mode
|
||||
std::vector<wxMenuItem*> items_increase;
|
||||
std::vector<wxMenuItem*> items_decrease;
|
||||
std::vector<wxMenuItem*> items_set_number_of_copies;
|
||||
enum MenuIdentifier {
|
||||
miObjectFFF=0,
|
||||
miObjectSLA
|
||||
};
|
||||
MenuFactory menus;
|
||||
|
||||
// Data
|
||||
Slic3r::DynamicPrintConfig *config; // FIXME: leak?
|
||||
|
@ -1670,7 +1655,6 @@ struct Plater::priv
|
|||
void on_update_geometry(Vec3dsEvent<2>&);
|
||||
void on_3dcanvas_mouse_dragging_finished(SimpleEvent&);
|
||||
|
||||
void update_object_menu();
|
||||
void show_action_buttons(const bool is_ready_to_slice) const;
|
||||
|
||||
// Set the bed shape to a single closed 2D polygon(array of two element arrays),
|
||||
|
@ -1691,12 +1675,11 @@ struct Plater::priv
|
|||
bool can_set_instance_to_object() const;
|
||||
bool can_mirror() const;
|
||||
bool can_reload_from_disk() const;
|
||||
bool can_split(bool to_objects) const;
|
||||
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background);
|
||||
void generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background);
|
||||
|
||||
void msw_rescale_object_menu();
|
||||
|
||||
void bring_instance_forward() const;
|
||||
|
||||
// returns the path to project file with the given extension (none if extension == wxEmptyString)
|
||||
|
@ -1713,13 +1696,6 @@ struct Plater::priv
|
|||
bool inside_snapshot_capture() { return m_prevent_snapshots != 0; }
|
||||
bool process_completed_with_error { false };
|
||||
private:
|
||||
bool init_object_menu();
|
||||
bool init_common_menu(wxMenu* menu, const bool is_part = false);
|
||||
bool complit_init_object_menu();
|
||||
bool complit_init_sla_object_menu();
|
||||
bool complit_init_part_menu();
|
||||
|
||||
bool can_split() const;
|
||||
bool layers_height_allowed() const;
|
||||
|
||||
void update_fff_scene();
|
||||
|
@ -1829,7 +1805,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0);
|
||||
q->SetSizer(hsizer);
|
||||
|
||||
init_object_menu();
|
||||
menus.init(q);
|
||||
|
||||
// Events:
|
||||
|
||||
|
@ -2725,19 +2701,19 @@ void Plater::priv::split_object()
|
|||
Model new_model = model;
|
||||
ModelObject* current_model_object = new_model.objects[obj_idx];
|
||||
|
||||
if (current_model_object->volumes.size() > 1)
|
||||
{
|
||||
Slic3r::GUI::warning_catcher(q, _L("The selected object can't be split because it contains more than one volume/material."));
|
||||
return;
|
||||
}
|
||||
|
||||
wxBusyCursor wait;
|
||||
ModelObjectPtrs new_objects;
|
||||
current_model_object->split(&new_objects);
|
||||
if (new_objects.size() == 1)
|
||||
Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split because it contains only one part."));
|
||||
// #ysFIXME use notification
|
||||
Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split because it contains only one solid part."));
|
||||
else
|
||||
{
|
||||
if (current_model_object->volumes.size() != new_objects.size())
|
||||
notification_manager->push_notification(NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::RegularNotification,
|
||||
_u8L("All non-solid parts (modifiers) was deleted"));
|
||||
|
||||
Plater::TakeSnapshot snapshot(q, _L("Split to Objects"));
|
||||
|
||||
remove(obj_idx);
|
||||
|
@ -3732,70 +3708,25 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
|||
|
||||
wxMenu* menu = nullptr;
|
||||
|
||||
if (obj_idx == -1) // no one or several object are selected
|
||||
{
|
||||
if (obj_idx == -1) { // no one or several object are selected
|
||||
if (evt.data.second) // right button was clicked on empty space
|
||||
menu = &default_menu;
|
||||
menu = menus.default_menu();
|
||||
else
|
||||
{
|
||||
sidebar->obj_list()->show_multi_selection_menu();
|
||||
return;
|
||||
}
|
||||
menu = menus.multi_selection_menu();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// If in 3DScene is(are) selected volume(s), but right button was clicked on empty space
|
||||
if (evt.data.second)
|
||||
return;
|
||||
|
||||
int menu_item_convert_unit_position = 11;
|
||||
return;
|
||||
|
||||
if (printer_technology == ptSLA)
|
||||
menu = &sla_object_menu;
|
||||
else
|
||||
{
|
||||
menu = menus.sla_object_menu();
|
||||
else {
|
||||
// show "Object menu" for each one or several FullInstance instead of FullObject
|
||||
const bool is_some_full_instances = get_selection().is_single_full_instance() ||
|
||||
get_selection().is_single_full_object() ||
|
||||
get_selection().is_multiple_full_instance();
|
||||
menu = is_some_full_instances ? &object_menu : &part_menu;
|
||||
if (!is_some_full_instances)
|
||||
menu_item_convert_unit_position = 2;
|
||||
}
|
||||
|
||||
sidebar->obj_list()->append_menu_items_convert_unit(menu, menu_item_convert_unit_position);
|
||||
sidebar->obj_list()->append_menu_item_settings(menu);
|
||||
|
||||
if (printer_technology != ptSLA)
|
||||
sidebar->obj_list()->append_menu_item_change_extruder(menu);
|
||||
|
||||
if (menu != &part_menu)
|
||||
{
|
||||
/* Remove/Prepend "increase/decrease instances" menu items according to the view mode.
|
||||
* Suppress to show those items for a Simple mode
|
||||
*/
|
||||
const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
|
||||
if (wxGetApp().get_mode() == comSimple) {
|
||||
if (menu->FindItem(_L("Add instance")) != wxNOT_FOUND)
|
||||
{
|
||||
/* Detach an items from the menu, but don't delete them
|
||||
* so that they can be added back later
|
||||
* (after switching to the Advanced/Expert mode)
|
||||
*/
|
||||
menu->Remove(items_increase[id]);
|
||||
menu->Remove(items_decrease[id]);
|
||||
menu->Remove(items_set_number_of_copies[id]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (menu->FindItem(_L("Add instance")) == wxNOT_FOUND)
|
||||
{
|
||||
// Prepend items to the menu, if those aren't not there
|
||||
menu->Prepend(items_set_number_of_copies[id]);
|
||||
menu->Prepend(items_decrease[id]);
|
||||
menu->Prepend(items_increase[id]);
|
||||
}
|
||||
}
|
||||
menu = is_some_full_instances ? menus.object_menu() : menus.part_menu();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3842,26 +3773,6 @@ void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&)
|
|||
}
|
||||
}
|
||||
|
||||
bool Plater::priv::init_object_menu()
|
||||
{
|
||||
items_increase.reserve(2);
|
||||
items_decrease.reserve(2);
|
||||
items_set_number_of_copies.reserve(2);
|
||||
|
||||
init_common_menu(&object_menu);
|
||||
complit_init_object_menu();
|
||||
|
||||
init_common_menu(&sla_object_menu);
|
||||
complit_init_sla_object_menu();
|
||||
|
||||
init_common_menu(&part_menu, true);
|
||||
complit_init_part_menu();
|
||||
|
||||
sidebar->obj_list()->create_default_popupmenu(&default_menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background)
|
||||
{
|
||||
view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, show_bed, transparent_background);
|
||||
|
@ -3880,12 +3791,6 @@ void Plater::priv::generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds&
|
|||
}
|
||||
}
|
||||
|
||||
void Plater::priv::msw_rescale_object_menu()
|
||||
{
|
||||
for (MenuWithSeparators* menu : { &object_menu, &sla_object_menu, &part_menu, &default_menu })
|
||||
msw_rescale_menu(dynamic_cast<wxMenu*>(menu));
|
||||
}
|
||||
|
||||
wxString Plater::priv::get_project_filename(const wxString& extension) const
|
||||
{
|
||||
return m_project_filename.empty() ? "" : m_project_filename + extension;
|
||||
|
@ -3914,144 +3819,6 @@ void Plater::priv::set_project_filename(const wxString& filename)
|
|||
wxGetApp().mainframe->add_to_recent_projects(filename);
|
||||
}
|
||||
|
||||
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
|
||||
{
|
||||
if (is_part) {
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
|
||||
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
||||
|
||||
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected volumes from disk"),
|
||||
[this](wxCommandEvent&) { q->reload_from_disk(); }, "", menu, [this]() { return can_reload_from_disk(); }, q);
|
||||
|
||||
sidebar->obj_list()->append_menu_item_export_stl(menu);
|
||||
}
|
||||
else {
|
||||
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _L("Add instance") + "\t+", _L("Add one more instance of the selected object"),
|
||||
[this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
||||
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _L("Remove instance") + "\t-", _L("Remove one instance of the selected object"),
|
||||
[this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q);
|
||||
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _L("Set number of instances") + dots, _L("Change the number of instances of the selected object"),
|
||||
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
||||
append_menu_item(menu, wxID_ANY, _L("Fill bed with instances") + dots, _L("Fill the remaining area of bed with instances of the selected object"),
|
||||
[this](wxCommandEvent&) { q->fill_bed_with_instances(); }, "", nullptr, [this]() { return can_increase_instances(); }, q);
|
||||
|
||||
|
||||
items_increase.push_back(item_increase);
|
||||
items_decrease.push_back(item_decrease);
|
||||
items_set_number_of_copies.push_back(item_set_number_of_copies);
|
||||
|
||||
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
|
||||
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
|
||||
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
||||
|
||||
menu->AppendSeparator();
|
||||
sidebar->obj_list()->append_menu_item_instance_to_object(menu, q);
|
||||
menu->AppendSeparator();
|
||||
|
||||
wxMenuItem* menu_item_printable = sidebar->obj_list()->append_menu_item_printable(menu, q);
|
||||
menu->AppendSeparator();
|
||||
|
||||
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected object from disk"),
|
||||
[this](wxCommandEvent&) { reload_from_disk(); }, "", nullptr, [this]() { return can_reload_from_disk(); }, q);
|
||||
|
||||
append_menu_item(menu, wxID_ANY, _L("Export as STL") + dots, _L("Export the selected object as STL file"),
|
||||
[this](wxCommandEvent&) { q->export_stl(false, true); }, "", nullptr,
|
||||
[this]() {
|
||||
const Selection& selection = get_selection();
|
||||
return selection.is_single_full_instance() || selection.is_single_full_object();
|
||||
}, q);
|
||||
|
||||
menu->AppendSeparator();
|
||||
|
||||
// "Scale to print volume" makes a sense just for whole object
|
||||
sidebar->obj_list()->append_menu_item_scale_selection_to_fit_print_volume(menu);
|
||||
|
||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
|
||||
const Selection& selection = get_selection();
|
||||
int instance_idx = selection.get_instance_idx();
|
||||
evt.Enable(selection.is_single_full_instance() || selection.is_single_full_object());
|
||||
if (instance_idx != -1)
|
||||
{
|
||||
evt.Check(model.objects[selection.get_object_idx()]->instances[instance_idx]->printable);
|
||||
view3D->set_as_dirty();
|
||||
}
|
||||
}, menu_item_printable->GetId());
|
||||
}
|
||||
|
||||
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
|
||||
|
||||
wxMenu* mirror_menu = new wxMenu();
|
||||
if (mirror_menu == nullptr)
|
||||
return false;
|
||||
|
||||
append_menu_item(mirror_menu, wxID_ANY, _L("Along X axis"), _L("Mirror the selected object along the X axis"),
|
||||
[this](wxCommandEvent&) { mirror(X); }, "mark_X", menu);
|
||||
append_menu_item(mirror_menu, wxID_ANY, _L("Along Y axis"), _L("Mirror the selected object along the Y axis"),
|
||||
[this](wxCommandEvent&) { mirror(Y); }, "mark_Y", menu);
|
||||
append_menu_item(mirror_menu, wxID_ANY, _L("Along Z axis"), _L("Mirror the selected object along the Z axis"),
|
||||
[this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu);
|
||||
|
||||
append_submenu(menu, mirror_menu, wxID_ANY, _L("Mirror"), _L("Mirror the selected object"), "",
|
||||
[this]() { return can_mirror(); }, q);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plater::priv::complit_init_object_menu()
|
||||
{
|
||||
wxMenu* split_menu = new wxMenu();
|
||||
if (split_menu == nullptr)
|
||||
return false;
|
||||
|
||||
append_menu_item(split_menu, wxID_ANY, _L("To objects"), _L("Split the selected object into individual objects"),
|
||||
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
||||
append_menu_item(split_menu, wxID_ANY, _L("To parts"), _L("Split the selected object into individual sub-parts"),
|
||||
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
||||
|
||||
append_submenu(&object_menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "",
|
||||
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
|
||||
object_menu.AppendSeparator();
|
||||
|
||||
// Layers Editing for object
|
||||
sidebar->obj_list()->append_menu_item_layers_editing(&object_menu, q);
|
||||
object_menu.AppendSeparator();
|
||||
|
||||
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plater::priv::complit_init_sla_object_menu()
|
||||
{
|
||||
append_menu_item(&sla_object_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual objects"),
|
||||
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", nullptr, [this]() { return can_split(); }, q);
|
||||
|
||||
sla_object_menu.AppendSeparator();
|
||||
|
||||
// Add the automatic rotation sub-menu
|
||||
append_menu_item(
|
||||
&sla_object_menu, wxID_ANY, _(L("Optimize orientation")),
|
||||
_(L("Optimize the rotation of the object for better print results.")),
|
||||
[this](wxCommandEvent &) {
|
||||
m_ui_jobs.optimize_rotation();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plater::priv::complit_init_part_menu()
|
||||
{
|
||||
append_menu_item(&part_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual sub-parts"),
|
||||
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", nullptr, [this]() { return can_split(); }, q);
|
||||
|
||||
part_menu.AppendSeparator();
|
||||
|
||||
auto obj_list = sidebar->obj_list();
|
||||
obj_list->append_menu_item_change_type(&part_menu, q);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Plater::priv::set_current_canvas_as_dirty()
|
||||
{
|
||||
if (current_panel == view3D)
|
||||
|
@ -4201,9 +3968,9 @@ bool Plater::priv::can_set_instance_to_object() const
|
|||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
|
||||
}
|
||||
|
||||
bool Plater::priv::can_split() const
|
||||
bool Plater::priv::can_split(bool to_objects) const
|
||||
{
|
||||
return sidebar->obj_list()->is_splittable();
|
||||
return sidebar->obj_list()->is_splittable(to_objects);
|
||||
}
|
||||
|
||||
bool Plater::priv::layers_height_allowed() const
|
||||
|
@ -4319,12 +4086,12 @@ bool Plater::priv::can_decrease_instances() const
|
|||
|
||||
bool Plater::priv::can_split_to_objects() const
|
||||
{
|
||||
return can_split();
|
||||
return q->can_split(true);
|
||||
}
|
||||
|
||||
bool Plater::priv::can_split_to_volumes() const
|
||||
{
|
||||
return (printer_technology != ptSLA) && can_split();
|
||||
return (printer_technology != ptSLA) && q->can_split(false);
|
||||
}
|
||||
|
||||
bool Plater::priv::can_arrange() const
|
||||
|
@ -4337,11 +4104,6 @@ bool Plater::priv::can_layers_editing() const
|
|||
return layers_height_allowed();
|
||||
}
|
||||
|
||||
void Plater::priv::update_object_menu()
|
||||
{
|
||||
sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
|
||||
}
|
||||
|
||||
void Plater::priv::show_action_buttons(const bool ready_to_slice) const
|
||||
{
|
||||
// Cache this value, so that the callbacks from the RemovableDriveManager may repeat that value when calling show_action_buttons().
|
||||
|
@ -6061,9 +5823,12 @@ void Plater::suppress_background_process(const bool stop_background_process)
|
|||
}
|
||||
|
||||
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
|
||||
|
||||
void Plater::update_object_menu() { p->update_object_menu(); }
|
||||
void Plater::show_action_buttons(const bool ready_to_slice) const { p->show_action_buttons(ready_to_slice); }
|
||||
void Plater::mirror(Axis axis) { p->mirror(axis); }
|
||||
void Plater::split_object() { p->split_object(); }
|
||||
void Plater::split_volume() { p->split_volume(); }
|
||||
void Plater::optimize_rotation() { p->m_ui_jobs.optimize_rotation();}
|
||||
void Plater::update_object_menu() { p->menus.update_object_menu(); }
|
||||
void Plater::show_action_buttons(const bool ready_to_slice) const { p->show_action_buttons(ready_to_slice); }
|
||||
|
||||
void Plater::copy_selection_to_clipboard()
|
||||
{
|
||||
|
@ -6120,7 +5885,7 @@ void Plater::msw_rescale()
|
|||
|
||||
p->sidebar->msw_rescale();
|
||||
|
||||
p->msw_rescale_object_menu();
|
||||
p->menus.msw_rescale();
|
||||
|
||||
Layout();
|
||||
GetParent()->Layout();
|
||||
|
@ -6132,7 +5897,7 @@ void Plater::sys_color_changed()
|
|||
p->sidebar->sys_color_changed();
|
||||
|
||||
// msw_rescale_menu updates just icons, so use it
|
||||
p->msw_rescale_object_menu();
|
||||
p->menus.msw_rescale();
|
||||
|
||||
Layout();
|
||||
GetParent()->Layout();
|
||||
|
@ -6297,6 +6062,8 @@ bool Plater::can_copy_to_clipboard() const
|
|||
bool Plater::can_undo() const { return p->undo_redo_stack().has_undo_snapshot(); }
|
||||
bool Plater::can_redo() const { return p->undo_redo_stack().has_redo_snapshot(); }
|
||||
bool Plater::can_reload_from_disk() const { return p->can_reload_from_disk(); }
|
||||
bool Plater::can_mirror() const { return p->can_mirror(); }
|
||||
bool Plater::can_split(bool to_objects) const { return p->can_split(to_objects); }
|
||||
const UndoRedo::Stack& Plater::undo_redo_stack_main() const { return p->undo_redo_stack_main(); }
|
||||
void Plater::clear_undo_redo_stack_main() { p->undo_redo_stack_main().clear(); }
|
||||
void Plater::enter_gizmos_stack() { p->enter_gizmos_stack(); }
|
||||
|
@ -6338,6 +6105,15 @@ void Plater::bring_instance_forward()
|
|||
p->bring_instance_forward();
|
||||
}
|
||||
|
||||
wxMenu* Plater::object_menu() { return p->menus.object_menu(); }
|
||||
wxMenu* Plater::part_menu() { return p->menus.part_menu(); }
|
||||
wxMenu* Plater::sla_object_menu() { return p->menus.sla_object_menu(); }
|
||||
wxMenu* Plater::default_menu() { return p->menus.default_menu(); }
|
||||
wxMenu* Plater::instance_menu() { return p->menus.instance_menu(); }
|
||||
wxMenu* Plater::layer_menu() { return p->menus.layer_menu(); }
|
||||
wxMenu* Plater::multi_selection_menu() { return p->menus.multi_selection_menu(); }
|
||||
|
||||
|
||||
SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() :
|
||||
m_was_scheduled(wxGetApp().plater()->is_background_process_update_scheduled())
|
||||
{
|
||||
|
|
|
@ -271,6 +271,10 @@ public:
|
|||
void copy_selection_to_clipboard();
|
||||
void paste_from_clipboard();
|
||||
void search(bool plater_is_active);
|
||||
void mirror(Axis axis);
|
||||
void split_object();
|
||||
void split_volume();
|
||||
void optimize_rotation();
|
||||
|
||||
bool can_delete() const;
|
||||
bool can_delete_all() const;
|
||||
|
@ -287,6 +291,8 @@ public:
|
|||
bool can_undo() const;
|
||||
bool can_redo() const;
|
||||
bool can_reload_from_disk() const;
|
||||
bool can_mirror() const;
|
||||
bool can_split(bool to_objects) const;
|
||||
|
||||
void msw_rescale();
|
||||
void sys_color_changed();
|
||||
|
@ -375,6 +381,15 @@ public:
|
|||
bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition);
|
||||
bool PopupMenu(wxMenu *menu, int x, int y) { return this->PopupMenu(menu, wxPoint(x, y)); }
|
||||
|
||||
// get same Plater/ObjectList menus
|
||||
wxMenu* object_menu();
|
||||
wxMenu* part_menu();
|
||||
wxMenu* sla_object_menu();
|
||||
wxMenu* default_menu();
|
||||
wxMenu* instance_menu();
|
||||
wxMenu* layer_menu();
|
||||
wxMenu* multi_selection_menu();
|
||||
|
||||
private:
|
||||
struct priv;
|
||||
std::unique_ptr<priv> p;
|
||||
|
|
Loading…
Reference in a new issue