mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	1st installment of copy and paste -> prototype for volumes copy and paste
This commit is contained in:
		
							parent
							
								
									53861b2012
								
							
						
					
					
						commit
						6cbf9d2523
					
				
					 8 changed files with 209 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -436,6 +436,43 @@ void ObjectList::selection_changed()
 | 
			
		|||
    part_selection_changed();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes)
 | 
			
		||||
{
 | 
			
		||||
    if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (volumes.empty())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ModelObject& model_object = *(*m_objects)[obj_idx];
 | 
			
		||||
    const auto object_item = m_objects_model->GetItemById(obj_idx);
 | 
			
		||||
 | 
			
		||||
    wxDataViewItemArray items;
 | 
			
		||||
 | 
			
		||||
    for (const ModelVolume* volume : volumes)
 | 
			
		||||
    {
 | 
			
		||||
        auto vol_item = m_objects_model->AddVolumeChild(object_item, volume->name, volume->type(),
 | 
			
		||||
            volume->config.has("extruder") ? volume->config.option<ConfigOptionInt>("extruder")->value : 0, false);
 | 
			
		||||
        auto opt_keys = volume->config.keys();
 | 
			
		||||
        if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder")))
 | 
			
		||||
            select_item(m_objects_model->AddSettingsChild(vol_item));
 | 
			
		||||
 | 
			
		||||
        items.Add(vol_item);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_parts_changed = true;
 | 
			
		||||
    parts_changed(obj_idx);
 | 
			
		||||
 | 
			
		||||
    select_items(items);
 | 
			
		||||
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | 
			
		||||
    selection_changed();
 | 
			
		||||
#endif //no __WXOSX__ //__WXMSW__
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObjectList::paste_object_into_list(const ModelObject& object)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObjectList::OnChar(wxKeyEvent& event)
 | 
			
		||||
{
 | 
			
		||||
    if (event.GetKeyCode() == WXK_BACK){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,10 @@ typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle;
 | 
			
		|||
//				  category ->		vector 			 ( option	;  label )
 | 
			
		||||
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
 | 
			
		||||
 | 
			
		||||
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | 
			
		||||
typedef std::vector<ModelVolume*> ModelVolumePtrs;
 | 
			
		||||
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | 
			
		||||
 | 
			
		||||
namespace GUI {
 | 
			
		||||
 | 
			
		||||
wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
 | 
			
		||||
| 
						 | 
				
			
			@ -285,6 +289,10 @@ public:
 | 
			
		|||
    void rename_item();
 | 
			
		||||
    void fix_through_netfabb() const;
 | 
			
		||||
    void update_item_error_icon(const int obj_idx, int vol_idx) const ;
 | 
			
		||||
 | 
			
		||||
    void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes);
 | 
			
		||||
    void paste_object_into_list(const ModelObject& object);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void OnChar(wxKeyEvent& event);
 | 
			
		||||
    void OnContextMenu(wxDataViewEvent &event);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -256,6 +256,16 @@ bool MainFrame::can_delete_all() const
 | 
			
		|||
    return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MainFrame::can_copy() const
 | 
			
		||||
{
 | 
			
		||||
    return (m_plater != nullptr) ? !m_plater->is_selection_empty() : false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MainFrame::can_paste() const
 | 
			
		||||
{
 | 
			
		||||
    return (m_plater != nullptr) ? !m_plater->is_selection_clipboard_empty() : false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
 | 
			
		||||
{
 | 
			
		||||
    // TODO
 | 
			
		||||
| 
						 | 
				
			
			@ -379,9 +389,18 @@ void MainFrame::init_menubar()
 | 
			
		|||
        wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")),
 | 
			
		||||
            [this](wxCommandEvent&) { m_plater->reset(); }, "");
 | 
			
		||||
 | 
			
		||||
        editMenu->AppendSeparator();
 | 
			
		||||
 | 
			
		||||
        wxMenuItem* item_copy = append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + "\tCtrl+C", _(L("Copy selection to clipboard")),
 | 
			
		||||
            [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, "");
 | 
			
		||||
        wxMenuItem* item_paste = append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + "\tCtrl+V", _(L("Paste clipboard")),
 | 
			
		||||
            [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, "");
 | 
			
		||||
 | 
			
		||||
        Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId());
 | 
			
		||||
        Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId());
 | 
			
		||||
        Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId());
 | 
			
		||||
        Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_copy()); }, item_copy->GetId());
 | 
			
		||||
        Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_paste()); }, item_paste->GetId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Window menu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,8 @@ class MainFrame : public DPIFrame
 | 
			
		|||
    bool can_select() const;
 | 
			
		||||
    bool can_delete() const;
 | 
			
		||||
    bool can_delete_all() const;
 | 
			
		||||
    bool can_copy() const;
 | 
			
		||||
    bool can_paste() const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void on_dpi_changed(const wxRect &suggested_rect);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3704,6 +3704,21 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
 | 
			
		|||
 | 
			
		||||
void Plater::update_object_menu() { p->update_object_menu(); }
 | 
			
		||||
 | 
			
		||||
void Plater::copy_selection_to_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    p->view3D->get_canvas3d()->get_selection().copy_to_clipboard();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Plater::paste_from_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Plater::is_selection_clipboard_empty() const
 | 
			
		||||
{
 | 
			
		||||
    return p->view3D->get_canvas3d()->get_selection().is_clipboard_empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Plater::can_delete() const { return p->can_delete(); }
 | 
			
		||||
bool Plater::can_delete_all() const { return p->can_delete_all(); }
 | 
			
		||||
bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -182,6 +182,10 @@ public:
 | 
			
		|||
    PrinterTechnology   printer_technology() const;
 | 
			
		||||
    void                set_printer_technology(PrinterTechnology printer_technology);
 | 
			
		||||
 | 
			
		||||
    void copy_selection_to_clipboard();
 | 
			
		||||
    void paste_from_clipboard();
 | 
			
		||||
    bool is_selection_clipboard_empty() const;
 | 
			
		||||
 | 
			
		||||
    bool can_delete() const;
 | 
			
		||||
    bool can_delete_all() const;
 | 
			
		||||
    bool can_increase_instances() const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,23 @@ Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_trans
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Selection::Clipboard::Clipboard()
 | 
			
		||||
    : m_object(nullptr)
 | 
			
		||||
{
 | 
			
		||||
    m_object = m_model.add_object();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::Clipboard::add_volume(const ModelVolume& volume)
 | 
			
		||||
{
 | 
			
		||||
    ModelVolume* v = m_object->add_volume(volume);
 | 
			
		||||
    v->config = volume.config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ModelVolume* Selection::Clipboard::get_volume(unsigned int id) const
 | 
			
		||||
{
 | 
			
		||||
    return (id < (unsigned int)m_object->volumes.size()) ? m_object->volumes[id] : nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Selection::Selection()
 | 
			
		||||
    : m_volumes(nullptr)
 | 
			
		||||
    , m_model(nullptr)
 | 
			
		||||
| 
						 | 
				
			
			@ -1022,6 +1039,53 @@ bool Selection::requires_local_axes() const
 | 
			
		|||
    return (m_mode == Volume) && is_from_single_instance();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::copy_to_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    if (!m_valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    m_clipboard.reset();
 | 
			
		||||
 | 
			
		||||
    for (unsigned int i : m_list)
 | 
			
		||||
    {
 | 
			
		||||
        const GLVolume* volume = (*m_volumes)[i];
 | 
			
		||||
        int obj_idx = volume->object_idx();
 | 
			
		||||
        if ((0 <= obj_idx) && (obj_idx < (int)m_model->objects.size()))
 | 
			
		||||
        {
 | 
			
		||||
            const ModelObject* model_object = m_model->objects[obj_idx];
 | 
			
		||||
            int vol_idx = volume->volume_idx();
 | 
			
		||||
            if ((0 <= vol_idx) && (vol_idx < (int)model_object->volumes.size()))
 | 
			
		||||
                m_clipboard.add_volume(*model_object->volumes[vol_idx]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int obj_idx = get_object_idx();
 | 
			
		||||
    if ((0 <= obj_idx) && (obj_idx < (int)m_model->objects.size()))
 | 
			
		||||
        m_clipboard.get_object()->config = m_model->objects[obj_idx]->config;
 | 
			
		||||
 | 
			
		||||
    m_clipboard.set_mode(m_mode);
 | 
			
		||||
    m_clipboard.set_type(m_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::paste_from_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    if (!m_valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (m_clipboard.is_empty())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if ((m_clipboard.get_mode() == Volume) && is_from_single_instance())
 | 
			
		||||
        paste_volumes_from_clipboard();
 | 
			
		||||
    else
 | 
			
		||||
        paste_object_from_clipboard();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Selection::is_clipboard_empty()
 | 
			
		||||
{
 | 
			
		||||
    return m_clipboard.is_empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::update_valid()
 | 
			
		||||
{
 | 
			
		||||
    m_valid = (m_volumes != nullptr) && (m_model != nullptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -1697,5 +1761,33 @@ bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
 | 
			
		|||
    return count == (unsigned int)m_model->objects[object_idx]->volumes.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::paste_volumes_from_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    int obj_idx = get_object_idx();
 | 
			
		||||
    if ((obj_idx < 0) || ((int)m_model->objects.size() <= obj_idx))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ModelObject& model_object = *m_model->objects[obj_idx];
 | 
			
		||||
    unsigned int count = m_clipboard.get_volumes_count();
 | 
			
		||||
    ModelVolumePtrs volumes;
 | 
			
		||||
    for (unsigned int i = 0; i < count; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        const ModelVolume* volume = m_clipboard.get_volume(i);
 | 
			
		||||
        ModelVolume* new_volume = model_object.add_volume(*volume);
 | 
			
		||||
        new_volume->config = volume->config;
 | 
			
		||||
        new_volume->set_new_unique_id();
 | 
			
		||||
        volumes.push_back(new_volume);
 | 
			
		||||
    }
 | 
			
		||||
    wxGetApp().obj_list()->paste_volumes_into_list(obj_idx, volumes);
 | 
			
		||||
    int a = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Selection::paste_object_from_clipboard()
 | 
			
		||||
{
 | 
			
		||||
    ModelObject* model_object = m_clipboard.get_object();
 | 
			
		||||
    if (model_object != nullptr)
 | 
			
		||||
        wxGetApp().obj_list()->paste_object_into_list(*model_object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace GUI
 | 
			
		||||
} // namespace Slic3r
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -151,6 +151,31 @@ private:
 | 
			
		|||
        ObjectIdxsToInstanceIdxsMap content;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Clipboard
 | 
			
		||||
    {
 | 
			
		||||
        Model m_model;
 | 
			
		||||
        ModelObject* m_object;
 | 
			
		||||
        Selection::EMode m_mode;
 | 
			
		||||
        Selection::EType m_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        Clipboard();
 | 
			
		||||
 | 
			
		||||
        void reset() { if (m_object != nullptr) m_object->clear_volumes(); }
 | 
			
		||||
        void add_volume(const ModelVolume& volume);
 | 
			
		||||
        const ModelVolume* get_volume(unsigned int id) const;
 | 
			
		||||
        ModelObject* get_object() { return m_object; }
 | 
			
		||||
        const ModelObject* get_object() const { return m_object; }
 | 
			
		||||
        const unsigned int get_volumes_count() const { return (unsigned int)m_object->volumes.size(); }
 | 
			
		||||
 | 
			
		||||
        bool is_empty() const { return (m_object == nullptr) || m_object->volumes.empty(); }
 | 
			
		||||
 | 
			
		||||
        Selection::EMode get_mode() const { return m_mode; }
 | 
			
		||||
        void set_mode(Selection::EMode mode) { m_mode = mode; }
 | 
			
		||||
        Selection::EType get_type() const { return m_type; }
 | 
			
		||||
        void set_type(Selection::EType type) { m_type = type; }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Volumes owned by GLCanvas3D.
 | 
			
		||||
    GLVolumePtrs* m_volumes;
 | 
			
		||||
    // Model, not owned.
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +188,7 @@ private:
 | 
			
		|||
    // set of indices to m_volumes
 | 
			
		||||
    IndicesList m_list;
 | 
			
		||||
    Cache m_cache;
 | 
			
		||||
    Clipboard m_clipboard;
 | 
			
		||||
    mutable BoundingBoxf3 m_bounding_box;
 | 
			
		||||
    mutable bool m_bounding_box_dirty;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -267,6 +293,10 @@ public:
 | 
			
		|||
 | 
			
		||||
    bool requires_local_axes() const;
 | 
			
		||||
 | 
			
		||||
    void copy_to_clipboard();
 | 
			
		||||
    void paste_from_clipboard();
 | 
			
		||||
    bool is_clipboard_empty();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void update_valid();
 | 
			
		||||
    void update_type();
 | 
			
		||||
| 
						 | 
				
			
			@ -301,6 +331,8 @@ private:
 | 
			
		|||
    void synchronize_unselected_volumes();
 | 
			
		||||
    void ensure_on_bed();
 | 
			
		||||
    bool is_from_fully_selected_instance(unsigned int volume_idx) const;
 | 
			
		||||
    void paste_volumes_from_clipboard();
 | 
			
		||||
    void paste_object_from_clipboard();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace GUI
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue