diff --git a/src/GUI/Plater.cpp b/src/GUI/Plater.cpp index af7688394..f72a70b96 100644 --- a/src/GUI/Plater.cpp +++ b/src/GUI/Plater.cpp @@ -88,6 +88,9 @@ Plater::Plater(wxWindow* parent, const wxString& title) : canvas3D = new Plate3D(preview_notebook, wxDefaultSize, objects, model, config); preview_notebook->AddPage(canvas3D, _("3D")); + canvas3D->on_select_object = std::function(on_select_object); + canvas3D->on_instances_moved = std::function(on_instances_moved); + preview3D = new Preview3D(preview_notebook, wxDefaultSize, objects, model, config); preview_notebook->AddPage(preview3D, _("Preview")); @@ -494,6 +497,7 @@ void Plater::arrange() { } void Plater::on_model_change(bool force_autocenter) { + Log::info(LogChannel, L"Called on_modal_change"); // reload the select submenu (if already initialized) { @@ -562,6 +566,7 @@ void Plater::select_object() { void Plater::selection_changed() { // Remove selection in 2D plater this->canvas2D->set_selected(-1, -1); + this->canvas3D->selection_changed(); auto obj = this->selected_object(); bool have_sel {obj != this->objects.end()}; diff --git a/src/GUI/Plater/Plate3D.cpp b/src/GUI/Plater/Plate3D.cpp index 1aa6544d8..185d06e6c 100644 --- a/src/GUI/Plater/Plate3D.cpp +++ b/src/GUI/Plater/Plate3D.cpp @@ -6,30 +6,74 @@ namespace Slic3r { namespace GUI { Plate3D::Plate3D(wxWindow* parent, const wxSize& size, std::vector& _objects, std::shared_ptr _model, std::shared_ptr _config) : Scene3D(parent, size), objects(_objects), model(_model), config(_config) { - - //this->glContext = new wxGLContext(this); - //this->Bind(wxEVT_PAINT, [this](wxPaintEvent& e) { this->repaint(e); }); - //delete this->glContext; - //this->glContext = new wxGLContext(this); // Update glContext (look for better way) - //}); - - // Bind the varying mouse events + // Bind the extra mouse events this->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { this->mouse_down(e); }); this->Bind(wxEVT_RIGHT_DOWN, [this](wxMouseEvent &e) { this->mouse_down(e); }); } void Plate3D::mouse_down(wxMouseEvent &e){ - if(!hover){ - //select logic + if(hover){ + on_select_object(hover_object); + moving = true; + moving_volume = hover_volume; + move_start = Point(e.GetX(),e.GetY()); + }else{ + on_select_object(-1); } + hover = false; } - +void Plate3D::mouse_up(wxMouseEvent &e){ + if(moving){ + //translate object + moving = false; + uint i = 0; + for(const PlaterObject &object: objects){ + const auto &modelobj = model->objects.at(object.identifier); + for(ModelInstance *instance: modelobj->instances){ + uint size = modelobj->volumes.size(); + if(i <= moving_volume && moving_volume < i+size){ + + instance->offset.translate(volumes.at(i).origin); + modelobj->update_bounding_box(); + on_instances_moved(); + Refresh(); + return; + }else{ + i+=size; + } + } + } + } + Scene3D::mouse_up(e); +} void Plate3D::mouse_move(wxMouseEvent &e){ if(!e.Dragging()){ pos = Point(e.GetX(),e.GetY()); mouse = true; Refresh(); + } else if(moving){ + const auto p = Point(e.GetX(),e.GetY()); + const auto current = mouse_ray(p).intersect_plane(0); + const auto old = mouse_ray(move_start).intersect_plane(0); + move_start = p; + uint i = 0; + for(const PlaterObject &object: objects){ + const auto &modelobj = model->objects.at(object.identifier); + for(ModelInstance *instance: modelobj->instances){ + uint size = modelobj->volumes.size(); + if(i <= moving_volume && moving_volume < i+size){ + for(ModelVolume* volume: modelobj->volumes){ + volumes.at(i).origin.translate(old.vector_to(current)); + i++; + } + Refresh(); + return; + }else{ + i+=size; + } + } + } } else { Scene3D::mouse_move(e); } @@ -47,32 +91,37 @@ void Plate3D::update(){ } } color_volumes(); + Refresh(); } void Plate3D::color_volumes(){ uint i = 0; for(const PlaterObject &object: objects){ const auto &modelobj = model->objects.at(object.identifier); + bool hover_object = hover && i <= hover_volume && hover_volume < i+modelobj->instances.size()*modelobj->volumes.size(); for(ModelInstance *instance: modelobj->instances){ for(ModelVolume* volume: modelobj->volumes){ auto& rendervolume = volumes.at(i); if(object.selected){ rendervolume.color = ui_settings->color->SELECTED_COLOR(); - }else{ + }else if(hover_object){ + rendervolume.color = ui_settings->color->HOVER_COLOR(); + } else { rendervolume.color = ui_settings->color->COLOR_PARTS(); } i++; } } } - if(hover){ - volumes.at(hover_volume).color = ui_settings->color->HOVER_COLOR(); - } } void Plate3D::before_render(){ - if (!mouse)return; + if (!mouse){ + color_volumes(); + return; + } + // Color each volume a different color, render and test which color is beneath the mouse. //glDisable(GL_MULTISAMPLE) if ($self->{can_multisample}); glDisable(GL_LIGHTING); uint i = 1; @@ -86,6 +135,8 @@ void Plate3D::before_render(){ GLubyte color[4] = {0,0,0,0}; glReadPixels(pos.x, GetSize().GetHeight()- pos.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color); + + // Handle the hovered volume uint index = (color[0]<<16) + (color[1]<<8) + color[2]; hover = false; ///*$self->_hover_volume_idx(undef); @@ -93,6 +144,15 @@ void Plate3D::before_render(){ if (index != 0 && index <= volumes.size()) { hover = true; hover_volume = index - 1; + uint k = 0; + for(const PlaterObject &object: objects){ + const auto &modelobj = model->objects.at(object.identifier); + if(k <= hover_volume && hover_volume < k+modelobj->instances.size()*modelobj->volumes.size()){ + hover_object = k; + break; + } + k++; + } /* $self->volumes->[$volume_idx]->hover(1); my $group_id = $self->volumes->[$volume_idx]->select_group_id; diff --git a/src/GUI/Plater/Plate3D.hpp b/src/GUI/Plater/Plate3D.hpp index 1c5954c87..f83dbc292 100644 --- a/src/GUI/Plater/Plate3D.hpp +++ b/src/GUI/Plater/Plate3D.hpp @@ -15,16 +15,22 @@ namespace Slic3r { namespace GUI { class Plate3D : public Scene3D { public: void update(); + /// Registered function to fire when objects are selected. + std::function on_select_object {}; + /// Registered function to fire when an instance is moved. + std::function on_instances_moved {}; + void selection_changed(){Refresh();} Plate3D(wxWindow* parent, const wxSize& size, std::vector& _objects, std::shared_ptr _model, std::shared_ptr _config); protected: void before_render(); + void mouse_up(wxMouseEvent &e); void mouse_move(wxMouseEvent &e); void mouse_down(wxMouseEvent &e); private: void color_volumes(); - Point pos; - bool hover = false, mouse = false; - uint hover_volume; + Point pos, move_start; + bool hover = false, mouse = false, moving = false; + uint hover_volume, hover_object, moving_volume; std::vector& objects; //< reference to parent vector std::shared_ptr model; std::shared_ptr config; diff --git a/src/GUI/Scene3D.cpp b/src/GUI/Scene3D.cpp index e379eda27..110d06eb4 100644 --- a/src/GUI/Scene3D.cpp +++ b/src/GUI/Scene3D.cpp @@ -47,7 +47,7 @@ float clamp(float low, float x, float high){ return x; } -Linef3 mouse_ray(Point win){ +Linef3 Scene3D::mouse_ray(Point win){ GLdouble proj[16], mview[16]; glGetDoublev(GL_MODELVIEW_MATRIX, mview); glGetDoublev(GL_PROJECTION_MATRIX, proj); diff --git a/src/GUI/Scene3D.hpp b/src/GUI/Scene3D.hpp index d78ec01b9..02daa984a 100644 --- a/src/GUI/Scene3D.hpp +++ b/src/GUI/Scene3D.hpp @@ -39,6 +39,7 @@ private: void draw_ground(); void draw_axes(Pointf3 center, float length, int width, bool alwaysvisible); protected: + Linef3 mouse_ray(Point win); void draw_volumes(); virtual void mouse_up(wxMouseEvent &e); virtual void mouse_move(wxMouseEvent &e);