Object updated by scale gizmo

This commit is contained in:
Enrico Turri 2018-06-18 15:07:17 +02:00
parent 56ea84fef8
commit a3949b9f01
12 changed files with 179 additions and 52 deletions

View File

@ -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);

View File

@ -95,6 +95,7 @@ public:
void call(int i) const;
void call(int i, int j) const;
void call(const std::vector<int>& ints) const;
void call(double d) const;
void call(double x, double y) const;
void call(bool b) const;
private:

View File

@ -247,6 +247,21 @@ void PerlCallback::call(const std::vector<int>& 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)

View File

@ -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

View File

@ -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<int> load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs);
static std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);

View File

@ -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<GLGizmoScale*>(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<GLGizmoScale*>(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<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
{
static const float INV_255 = 1.0f / 255.0f;

View File

@ -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<int>& volume_idxs);
void _on_select(int volume_idx);
void _update_gizmos_data();
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
};

View File

@ -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);

View File

@ -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);

View File

@ -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();
}

View File

@ -47,7 +47,6 @@ protected:
GLTexture m_textures[Num_States];
int m_hover_id;
mutable std::vector<Grabber> 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;

View File

@ -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: