diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ed1ebcc6d..d1ccf07d5 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -105,6 +105,34 @@ sub new { $self->{btn_print}->Enable($enable); $self->{btn_send_gcode}->Enable($enable); }; + + # callback to react to gizmo scale + my $on_gizmo_scale_uniformly = sub { + my ($scale) = @_; + + my ($obj_idx, $object) = $self->selected_object; + return if !defined $obj_idx; + + my $model_object = $self->{model}->objects->[$obj_idx]; + my $model_instance = $model_object->instances->[0]; + + my $variation = $scale / $model_instance->scaling_factor; + #FIXME Scale the layer height profile? + foreach my $range (@{ $model_object->layer_height_ranges }) { + $range->[0] *= $variation; + $range->[1] *= $variation; + } + $_->set_scaling_factor($scale) for @{ $model_object->instances }; + $object->transform_thumbnail($self->{model}, $obj_idx); + + #update print and start background processing + $self->stop_background_process; + $self->{print}->add_model_object($model_object, $obj_idx); + + $self->selection_changed(1); # refresh info (size, volume etc.) + $self->update; + $self->schedule_background_process; + }; # Initialize 3D plater if ($Slic3r::GUI::have_OpenGL) { @@ -122,6 +150,7 @@ sub new { Slic3r::GUI::_3DScene::register_on_remove_object_callback($self->{canvas3D}, sub { $self->remove() }); Slic3r::GUI::_3DScene::register_on_instance_moved_callback($self->{canvas3D}, $on_instances_moved); Slic3r::GUI::_3DScene::register_on_enable_action_buttons_callback($self->{canvas3D}, $enable_action_buttons); + Slic3r::GUI::_3DScene::register_on_gizmo_scale_uniformly_callback($self->{canvas3D}, $on_gizmo_scale_uniformly); Slic3r::GUI::_3DScene::enable_gizmos($self->{canvas3D}, 1); Slic3r::GUI::_3DScene::enable_shader($self->{canvas3D}, 1); Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($self->{canvas3D}, 1); diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp index 05eaf282f..921841a27 100644 --- a/xs/src/libslic3r/Utils.hpp +++ b/xs/src/libslic3r/Utils.hpp @@ -95,6 +95,7 @@ public: void call(int i) const; void call(int i, int j) const; void call(const std::vector& ints) const; + void call(double d) const; void call(double x, double y) const; void call(bool b) const; private: diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 83c45b190..745d07fcd 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -247,6 +247,21 @@ void PerlCallback::call(const std::vector& ints) const LEAVE; } +void PerlCallback::call(double d) const +{ + if (!m_callback) + return; + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVnv(d))); + PUTBACK; + perl_call_sv(SvRV((SV*)m_callback), G_DISCARD); + FREETMPS; + LEAVE; +} + void PerlCallback::call(double x, double y) const { if (!m_callback) diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 34d066730..1879b3082 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -2038,6 +2038,11 @@ void _3DScene::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, vo s_canvas_mgr.register_on_enable_action_buttons_callback(canvas, callback); } +void _3DScene::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_on_gizmo_scale_uniformly_callback(canvas, callback); +} + static inline int hex_digit_to_int(const char c) { return diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 26b9911e0..c6a166397 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -312,9 +312,9 @@ public: // Boolean: Is mouse over this object? bool hover; // Wheter or not this volume has been generated from a modifier - bool is_modifier; + bool is_modifier; // Wheter or not this volume has been generated from the wipe tower - bool is_wipe_tower; + bool is_wipe_tower; // Interleaved triangles & normals with indexed triangles & quads. GLIndexedVertexArray indexed_vertex_array; @@ -589,6 +589,7 @@ public: static void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback); static void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback); static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); + static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); static std::vector load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector instance_idxs); static std::vector load_object(wxGLCanvas* canvas, const Model* model, int obj_idx); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index ae5125d6c..f9c10017e 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1263,6 +1263,25 @@ void GLCanvas3D::Gizmos::update(const Pointf& mouse_pos) curr->update(mouse_pos); } +void GLCanvas3D::Gizmos::update_data(float scale) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(Scale); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_scale(scale); +} + +bool GLCanvas3D::Gizmos::is_running() const +{ + if (!m_enabled) + return false; + + GLGizmoBase* curr = _get_current(); + return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false; +} + bool GLCanvas3D::Gizmos::is_dragging() const { return m_dragging; @@ -1281,6 +1300,15 @@ void GLCanvas3D::Gizmos::stop_dragging() m_dragging = false; } +float GLCanvas3D::Gizmos::get_scale() const +{ + if (!m_enabled) + return 1.0f; + + GizmosMap::const_iterator it = m_gizmos.find(Scale); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_scale() : 1.0f; +} + void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const { if (!m_enabled) @@ -2443,6 +2471,12 @@ void GLCanvas3D::register_on_enable_action_buttons_callback(void* callback) m_on_enable_action_buttons_callback.register_callback(callback); } +void GLCanvas3D::register_on_gizmo_scale_uniformly_callback(void* callback) +{ + if (callback != nullptr) + m_on_gizmo_scale_uniformly_callback.register_callback(callback); +} + void GLCanvas3D::bind_event_handlers() { if (m_canvas != nullptr) @@ -2661,11 +2695,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if ((selected_object_idx != -1) && gizmos_overlay_contains_mouse) { m_gizmos.update_on_off_state(*this, m_mouse.position); + _update_gizmos_data(); m_dirty = true; } else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) - { + { + _update_gizmos_data(); m_gizmos.start_dragging(); + m_dirty = true; } else { @@ -2688,6 +2725,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) vol->selected = true; } } + + if (m_gizmos.is_running()) + _update_gizmos_data(); + m_dirty = true; } } @@ -2779,6 +2820,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) const Pointf3& cur_pos = _mouse_to_bed_3d(pos); m_gizmos.update(Pointf(cur_pos.x, cur_pos.y)); + + m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); m_dirty = true; } else if (evt.Dragging() && !gizmos_overlay_contains_mouse) @@ -3120,6 +3163,7 @@ void GLCanvas3D::_deregister_callbacks() m_on_instance_moved_callback.deregister_callback(); m_on_wipe_tower_moved_callback.deregister_callback(); m_on_enable_action_buttons_callback.deregister_callback(); + m_on_gizmo_scale_uniformly_callback.deregister_callback(); } void GLCanvas3D::_mark_volumes_for_layer_height() const @@ -3549,28 +3593,9 @@ Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) Pointf3 GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos) { - if (!set_current()) - return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX); - - GLint viewport[4]; - ::glGetIntegerv(GL_VIEWPORT, viewport); - - _camera_tranform(); - - GLdouble modelview_matrix[16]; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); - GLdouble projection_matrix[16]; - ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); - - GLint y = viewport[3] - (GLint)mouse_pos.y; - - GLdouble x0, y0, z0; - ::gluUnProject((GLdouble)mouse_pos.x, (GLdouble)y, 0.1, modelview_matrix, projection_matrix, viewport, &x0, &y0, &z0); - - GLdouble x1, y1, z1; - ::gluUnProject((GLdouble)mouse_pos.x, (GLdouble)y, 0.9, modelview_matrix, projection_matrix, viewport, &x1, &y1, &z1); - - return Linef3(Pointf3(x0, y0, z0), Pointf3(x1, y1, z1)).intersect_plane(0.0); + float z0 = 0.0f; + float z1 = 1.0f; + return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1)).intersect_plane(0.0); } void GLCanvas3D::_start_timer() @@ -4239,6 +4264,21 @@ void GLCanvas3D::_on_select(int volume_idx) m_on_select_object_callback.call(id); } +void GLCanvas3D::_update_gizmos_data() +{ + int id = _get_first_selected_object_id(); + if ((id != -1) && (m_model != nullptr)) + { + ModelObject* model_object = m_model->objects[id]; + if (model_object != nullptr) + { + ModelInstance* model_instance = model_object->instances[0]; + if (model_instance != nullptr) + m_gizmos.update_data(model_instance->scaling_factor); + } + } +} + std::vector GLCanvas3D::_parse_colors(const std::vector& colors) { static const float INV_255 = 1.0f / 255.0f; diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 32dc1d934..c503d1845 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -360,11 +360,15 @@ public: bool overlay_contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; bool grabber_contains_mouse() const; void update(const Pointf& mouse_pos); + void update_data(float scale); + bool is_running() const; bool is_dragging() const; void start_dragging(); void stop_dragging(); + float get_scale() const; + void render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const; void render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const; @@ -437,6 +441,7 @@ private: PerlCallback m_on_instance_moved_callback; PerlCallback m_on_wipe_tower_moved_callback; PerlCallback m_on_enable_action_buttons_callback; + PerlCallback m_on_gizmo_scale_uniformly_callback; public: GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context); @@ -542,6 +547,7 @@ public: void register_on_instance_moved_callback(void* callback); void register_on_wipe_tower_moved_callback(void* callback); void register_on_enable_action_buttons_callback(void* callback); + void register_on_gizmo_scale_uniformly_callback(void* callback); void bind_event_handlers(); void unbind_event_handlers(); @@ -622,6 +628,8 @@ private: void _on_move(const std::vector& volume_idxs); void _on_select(int volume_idx); + void _update_gizmos_data(); + static std::vector _parse_colors(const std::vector& colors); }; diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 97af89fb7..f288ee456 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -678,6 +678,13 @@ void GLCanvas3DManager::register_on_enable_action_buttons_callback(wxGLCanvas* c it->second->register_on_enable_action_buttons_callback(callback); } +void GLCanvas3DManager::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_on_gizmo_scale_uniformly_callback(callback); +} + GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) { return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index 95bd2af80..6989da791 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -152,6 +152,7 @@ public: void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback); void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback); void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); + void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); private: CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 706c41675..d3aae33e8 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -115,8 +115,7 @@ void GLGizmoBase::set_hover_id(int id) void GLGizmoBase::start_dragging() { - if (m_hover_id != -1) - m_start_drag_position = m_grabbers[m_hover_id].center; + on_start_dragging(); } void GLGizmoBase::update(const Pointf& mouse_pos) @@ -135,6 +134,10 @@ void GLGizmoBase::render_for_picking(const BoundingBoxf3& box) const on_render_for_picking(box); } +void GLGizmoBase::on_start_dragging() +{ +} + void GLGizmoBase::render_grabbers() const { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) @@ -156,8 +159,6 @@ const float GLGizmoRotate::GrabberOffset = 5.0f; GLGizmoRotate::GLGizmoRotate() : GLGizmoBase() -// , m_angle_x(0.0f) -// , m_angle_y(0.0f) , m_angle_z(0.0f) , m_center(Pointf(0.0, 0.0)) , m_radius(0.0f) @@ -332,7 +333,7 @@ void GLGizmoRotate::_render_grabber() const ::glVertex3f((GLfloat)m_grabbers[0].center.x, (GLfloat)m_grabbers[0].center.y, 0.0f); ::glEnd(); - ::memcpy((void*)m_grabbers[0].color, (const void*)HighlightColor, 4 * sizeof(float)); + ::memcpy((void*)m_grabbers[0].color, (const void*)HighlightColor, 3 * sizeof(float)); render_grabbers(); } @@ -340,12 +341,21 @@ const float GLGizmoScale::Offset = 5.0f; GLGizmoScale::GLGizmoScale() : GLGizmoBase() - , m_scale_x(1.0f) - , m_scale_y(1.0f) - , m_scale_z(1.0f) + , m_scale(1.0f) + , m_starting_scale(1.0f) { } +float GLGizmoScale::get_scale() const +{ + return m_scale; +} + +void GLGizmoScale::set_scale(float scale) +{ + m_starting_scale = scale; +} + bool GLGizmoScale::on_init() { std::string path = resources_dir() + "/icons/overlay/"; @@ -370,17 +380,21 @@ bool GLGizmoScale::on_init() return true; } +void GLGizmoScale::on_start_dragging() +{ + if (m_hover_id != -1) + m_starting_drag_position = m_grabbers[m_hover_id].center; +} + void GLGizmoScale::on_update(const Pointf& mouse_pos) { Pointf center(0.5 * (m_grabbers[1].center.x + m_grabbers[0].center.x), 0.5 * (m_grabbers[3].center.y + m_grabbers[0].center.y)); - coordf_t orig_len = length(m_start_drag_position - center); + coordf_t orig_len = length(m_starting_drag_position - center); coordf_t new_len = length(mouse_pos - center); coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0; - m_scale_x = (float)ratio; - m_scale_y = (float)ratio; - m_scale_z = (float)ratio; + m_scale = m_starting_scale * (float)ratio; } void GLGizmoScale::on_render(const BoundingBoxf3& box) const @@ -388,14 +402,10 @@ void GLGizmoScale::on_render(const BoundingBoxf3& box) const ::glDisable(GL_LIGHTING); ::glDisable(GL_DEPTH_TEST); - const Pointf3& size = box.size(); - const Pointf3& center = box.center(); - - Pointf half_scaled_size = 0.5 * Pointf((coordf_t)m_scale_x * size.x, (coordf_t)m_scale_y * size.y); - coordf_t min_x = center.x - half_scaled_size.x - (coordf_t)Offset; - coordf_t max_x = center.x + half_scaled_size.x + (coordf_t)Offset; - coordf_t min_y = center.y - half_scaled_size.y - (coordf_t)Offset; - coordf_t max_y = center.y + half_scaled_size.y + (coordf_t)Offset; + coordf_t min_x = box.min.x - (coordf_t)Offset; + coordf_t max_x = box.max.x + (coordf_t)Offset; + coordf_t min_y = box.min.y - (coordf_t)Offset; + coordf_t max_y = box.max.y + (coordf_t)Offset; m_grabbers[0].center.x = min_x; m_grabbers[0].center.y = min_y; @@ -419,7 +429,7 @@ void GLGizmoScale::on_render(const BoundingBoxf3& box) const // draw grabbers for (unsigned int i = 0; i < 4; ++i) { - ::memcpy((void*)m_grabbers[i].color, (const void*)HighlightColor, 4 * sizeof(float)); + ::memcpy((void*)m_grabbers[i].color, (const void*)HighlightColor, 3 * sizeof(float)); } render_grabbers(); } diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 432a20958..2baec8f9b 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -47,7 +47,6 @@ protected: GLTexture m_textures[Num_States]; int m_hover_id; mutable std::vector m_grabbers; - Pointf m_start_drag_position; public: GLGizmoBase(); @@ -72,6 +71,7 @@ public: protected: virtual bool on_init() = 0; + virtual void on_start_dragging(); virtual void on_update(const Pointf& mouse_pos) = 0; virtual void on_render(const BoundingBoxf3& box) const = 0; virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; @@ -92,8 +92,6 @@ class GLGizmoRotate : public GLGizmoBase static const unsigned int SnapRegionsCount; static const float GrabberOffset; -// float m_angle_x; -// float m_angle_y; float m_angle_z; mutable Pointf m_center; @@ -121,15 +119,20 @@ class GLGizmoScale : public GLGizmoBase { static const float Offset; - float m_scale_x; - float m_scale_y; - float m_scale_z; + float m_scale; + + Pointf m_starting_drag_position; + float m_starting_scale; public: GLGizmoScale(); + float get_scale() const; + void set_scale(float scale); + protected: virtual bool on_init(); + virtual void on_start_dragging(); virtual void on_update(const Pointf& mouse_pos); virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 426395ef2..29f35293b 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -598,6 +598,13 @@ register_on_enable_action_buttons_callback(canvas, callback) CODE: _3DScene::register_on_enable_action_buttons_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); +void +register_on_gizmo_scale_uniformly_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_on_gizmo_scale_uniformly_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + unsigned int finalize_legend_texture() CODE: