mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	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; | ||||
|     } | ||||
|     for (ModelVolume* volume : this->volumes) { | ||||
|         if (volume->type() != ModelVolumeType::MODEL_PART) | ||||
|             continue; | ||||
| 
 | ||||
|     ModelVolume* volume = this->volumes.front(); | ||||
|     TriangleMeshPtrs meshptrs = volume->mesh().split(); | ||||
|     size_t counter = 1; | ||||
|     for (TriangleMesh *mesh : meshptrs) { | ||||
|         TriangleMeshPtrs meshptrs = volume->mesh().split(); | ||||
|         size_t counter = 1; | ||||
|         for (TriangleMesh* mesh : meshptrs) { | ||||
| 
 | ||||
|         // FIXME: crashes if not satisfied
 | ||||
|         if (mesh->facets_count() < 3) continue; | ||||
|             // FIXME: crashes if not satisfied
 | ||||
|             if (mesh->facets_count() < 3) continue; | ||||
| 
 | ||||
|         mesh->repair(); | ||||
|             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++) : ""); | ||||
|             // 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)); | ||||
| 
 | ||||
|         // 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); | ||||
|             } | ||||
| 
 | ||||
|         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; | ||||
| 
 | ||||
|         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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vojtech Bubnik
						Vojtech Bubnik