3DScene mouse event handler partially moved to c++

This commit is contained in:
Enrico Turri 2018-05-31 13:51:50 +02:00
parent cf8e7475ca
commit 276533e236
11 changed files with 693 additions and 266 deletions

View File

@ -35,11 +35,8 @@ use Slic3r::Geometry qw(PI);
# _camera_type: 'perspective' or 'ortho' # _camera_type: 'perspective' or 'ortho'
#============================================================================================================================== #==============================================================================================================================
__PACKAGE__->mk_accessors( qw(_quat init __PACKAGE__->mk_accessors( qw(_quat init
enable_moving
on_viewport_changed on_viewport_changed
on_select on_select
on_double_click
on_right_click
on_move on_move
on_model_update on_model_update
volumes volumes
@ -220,9 +217,7 @@ sub new {
# $self->Refresh; # $self->Refresh;
# }); # });
# EVT_MOUSEWHEEL($self, \&mouse_wheel_event); # EVT_MOUSEWHEEL($self, \&mouse_wheel_event);
#============================================================================================================================== # EVT_MOUSE_EVENTS($self, \&mouse_event);
EVT_MOUSE_EVENTS($self, \&mouse_event);
#==============================================================================================================================
## EVT_KEY_DOWN($self, sub { ## EVT_KEY_DOWN($self, sub {
# EVT_CHAR($self, sub { # EVT_CHAR($self, sub {
# my ($s, $event) = @_; # my ($s, $event) = @_;
@ -433,139 +428,97 @@ sub Destroy {
# # Automatic action on mouse down with the same coordinate. # # Automatic action on mouse down with the same coordinate.
# $self->{layer_height_edit_timer}->Start(100, wxTIMER_CONTINUOUS); # $self->{layer_height_edit_timer}->Start(100, wxTIMER_CONTINUOUS);
#} #}
#============================================================================================================================== #
#sub mouse_event {
sub mouse_event { # my ($self, $e) = @_;
my ($self, $e) = @_; #
# my $pos = Slic3r::Pointf->new($e->GetPositionXY);
my $pos = Slic3r::Pointf->new($e->GetPositionXY);
#==============================================================================================================================
my $object_idx_selected = (Slic3r::GUI::_3DScene::is_layers_editing_enabled($self) && $self->{print}) ? Slic3r::GUI::_3DScene::get_layers_editing_first_selected_object_id($self, $self->{print}->object_count) : -1;
Slic3r::GUI::_3DScene::set_layers_editing_last_object_id($self, $object_idx_selected);
# my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id_for_variable_layer_height_editing : -1; # my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id_for_variable_layer_height_editing : -1;
#============================================================================================================================== #
#==============================================================================================================================
Slic3r::GUI::_3DScene::set_mouse_dragging($self, $e->Dragging);
# $self->_mouse_dragging($e->Dragging); # $self->_mouse_dragging($e->Dragging);
#============================================================================================================================== #
# if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) {
if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) { # # wxMSW needs focus in order to catch mouse wheel events
# wxMSW needs focus in order to catch mouse wheel events # $self->SetFocus;
$self->SetFocus; # $self->_drag_start_xy(undef);
$self->_drag_start_xy(undef); # } elsif ($e->LeftDClick) {
} elsif ($e->LeftDClick) {
#==============================================================================================================================
if ($object_idx_selected != -1 && Slic3r::GUI::_3DScene::bar_rect_contains($self, $e->GetX, $e->GetY)) {
# if ($object_idx_selected != -1 && $self->_variable_layer_thickness_bar_rect_mouse_inside($e)) { # if ($object_idx_selected != -1 && $self->_variable_layer_thickness_bar_rect_mouse_inside($e)) {
#============================================================================================================================== # } elsif ($self->on_double_click) {
} elsif ($self->on_double_click) { # $self->on_double_click->();
$self->on_double_click->(); # }
} # } elsif ($e->LeftDown || $e->RightDown) {
} elsif ($e->LeftDown || $e->RightDown) { # # If user pressed left or right button we first check whether this happened
# If user pressed left or right button we first check whether this happened # # on a volume or not.
# on a volume or not.
#==============================================================================================================================
my $volume_idx = Slic3r::GUI::_3DScene::get_hover_volume_id($self);
Slic3r::GUI::_3DScene::set_layers_editing_state($self, 0);
# my $volume_idx = $self->_hover_volume_idx // -1; # my $volume_idx = $self->_hover_volume_idx // -1;
# $self->_layer_height_edited(0); # $self->_layer_height_edited(0);
#==============================================================================================================================
#==============================================================================================================================
if ($object_idx_selected != -1 && Slic3r::GUI::_3DScene::bar_rect_contains($self, $e->GetX, $e->GetY)) {
# if ($object_idx_selected != -1 && $self->_variable_layer_thickness_bar_rect_mouse_inside($e)) { # if ($object_idx_selected != -1 && $self->_variable_layer_thickness_bar_rect_mouse_inside($e)) {
#============================================================================================================================== # # A volume is selected and the mouse is hovering over a layer thickness bar.
# A volume is selected and the mouse is hovering over a layer thickness bar. # # Start editing the layer height.
# Start editing the layer height.
#==============================================================================================================================
Slic3r::GUI::_3DScene::set_layers_editing_state($self, 1);
Slic3r::GUI::_3DScene::perform_layer_editing_action($self, $e->GetY, $e->ShiftDown, $e->RightIsDown);
# $self->_layer_height_edited(1); # $self->_layer_height_edited(1);
# $self->_variable_layer_thickness_action($e); # $self->_variable_layer_thickness_action($e);
#==============================================================================================================================
#==============================================================================================================================
} elsif ($object_idx_selected != -1 && Slic3r::GUI::_3DScene::reset_rect_contains($self, $e->GetX, $e->GetY)) {
# } elsif ($object_idx_selected != -1 && $self->_variable_layer_thickness_reset_rect_mouse_inside($e)) { # } elsif ($object_idx_selected != -1 && $self->_variable_layer_thickness_reset_rect_mouse_inside($e)) {
#============================================================================================================================== # $self->{print}->get_object($object_idx_selected)->reset_layer_height_profile;
$self->{print}->get_object($object_idx_selected)->reset_layer_height_profile; # # Index 2 means no editing, just wait for mouse up event.
# Index 2 means no editing, just wait for mouse up event.
#==============================================================================================================================
Slic3r::GUI::_3DScene::set_layers_editing_state($self, 2);
# $self->_layer_height_edited(2); # $self->_layer_height_edited(2);
#============================================================================================================================== # $self->Refresh;
$self->Refresh; # $self->Update;
$self->Update; # } else {
} else { # # The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y,
# The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y, # # an converts the screen space coordinate to unscaled object space.
# an converts the screen space coordinate to unscaled object space. # my $pos3d = ($volume_idx == -1) ? undef : $self->mouse_to_3d(@$pos);
my $pos3d = ($volume_idx == -1) ? undef : $self->mouse_to_3d(@$pos); #
# # Select volume in this 3D canvas.
# Select volume in this 3D canvas. # # Don't deselect a volume if layer editing is enabled. We want the object to stay selected
# Don't deselect a volume if layer editing is enabled. We want the object to stay selected # # during the scene manipulation.
# during the scene manipulation. #
#==============================================================================================================================
#==============================================================================================================================
if (Slic3r::GUI::_3DScene::is_picking_enabled($self) && ($volume_idx != -1 || ! Slic3r::GUI::_3DScene::is_layers_editing_enabled($self))) {
Slic3r::GUI::_3DScene::deselect_volumes($self);
Slic3r::GUI::_3DScene::select_volume($self, $volume_idx);
# if ($self->enable_picking && ($volume_idx != -1 || ! $self->layer_editing_enabled)) { # if ($self->enable_picking && ($volume_idx != -1 || ! $self->layer_editing_enabled)) {
# $self->deselect_volumes; # $self->deselect_volumes;
# $self->select_volume($volume_idx); # $self->select_volume($volume_idx);
#============================================================================================================================== #
# if ($volume_idx != -1) {
if ($volume_idx != -1) { # my $group_id = $self->volumes->[$volume_idx]->select_group_id;
my $group_id = $self->volumes->[$volume_idx]->select_group_id; # my @volumes;
my @volumes; # if ($group_id != -1) {
if ($group_id != -1) {
#==============================================================================================================================
Slic3r::GUI::_3DScene::select_volume($self, $_)
# $self->select_volume($_) # $self->select_volume($_)
#============================================================================================================================== # for grep $self->volumes->[$_]->select_group_id == $group_id,
for grep $self->volumes->[$_]->select_group_id == $group_id, # 0..$#{$self->volumes};
0..$#{$self->volumes}; # }
} # }
} #
# $self->Refresh;
$self->Refresh; # $self->Update;
$self->Update; # }
} #
# # propagate event through callback
# propagate event through callback # $self->on_select->($volume_idx)
$self->on_select->($volume_idx) # if $self->on_select;
if $self->on_select; #
# if ($volume_idx != -1) {
if ($volume_idx != -1) { # if ($e->LeftDown && $self->enable_moving) {
if ($e->LeftDown && $self->enable_moving) { # # Only accept the initial position, if it is inside the volume bounding box.
# Only accept the initial position, if it is inside the volume bounding box. # my $volume_bbox = $self->volumes->[$volume_idx]->transformed_bounding_box;
my $volume_bbox = $self->volumes->[$volume_idx]->transformed_bounding_box; # $volume_bbox->offset(1.);
$volume_bbox->offset(1.); # if ($volume_bbox->contains_point($pos3d)) {
if ($volume_bbox->contains_point($pos3d)) { # # The dragging operation is initiated.
# The dragging operation is initiated. # $self->_drag_volume_idx($volume_idx);
$self->_drag_volume_idx($volume_idx); # $self->_drag_start_pos($pos3d);
$self->_drag_start_pos($pos3d); # # Remember the shift to to the object center. The object center will later be used
# Remember the shift to to the object center. The object center will later be used # # to limit the object placement close to the bed.
# to limit the object placement close to the bed. # $self->_drag_volume_center_offset($pos3d->vector_to($volume_bbox->center));
$self->_drag_volume_center_offset($pos3d->vector_to($volume_bbox->center)); # }
} # } elsif ($e->RightDown) {
} elsif ($e->RightDown) { # # if right clicking on volume, propagate event through callback
# if right clicking on volume, propagate event through callback # $self->on_right_click->($e->GetPosition)
$self->on_right_click->($e->GetPosition) # if $self->on_right_click;
if $self->on_right_click; # }
} # }
} # }
}
#==============================================================================================================================
} elsif ($e->Dragging && $e->LeftIsDown && (Slic3r::GUI::_3DScene::get_layers_editing_state($self) == 0) && defined($self->_drag_volume_idx)) {
# } elsif ($e->Dragging && $e->LeftIsDown && ! $self->_layer_height_edited && defined($self->_drag_volume_idx)) { # } elsif ($e->Dragging && $e->LeftIsDown && ! $self->_layer_height_edited && defined($self->_drag_volume_idx)) {
#============================================================================================================================== # # Get new position at the same Z of the initial click point.
# Get new position at the same Z of the initial click point. # my $cur_pos = Slic3r::Linef3->new(
my $cur_pos = Slic3r::Linef3->new( # $self->mouse_to_3d($e->GetX, $e->GetY, 0),
$self->mouse_to_3d($e->GetX, $e->GetY, 0), # $self->mouse_to_3d($e->GetX, $e->GetY, 1))
$self->mouse_to_3d($e->GetX, $e->GetY, 1)) # ->intersect_plane($self->_drag_start_pos->z);
->intersect_plane($self->_drag_start_pos->z);
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
# >>>>>>>>>>>>>>>>>>>>>>>>>> TEMPORARY DISABLED DUE TO bed_polygon REMOVAL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# #
# # Clip the new position, so the object center remains close to the bed. # # Clip the new position, so the object center remains close to the bed.
# { # {
@ -578,124 +531,96 @@ sub mouse_event {
# } # }
# $cur_pos->translate(@{$self->_drag_volume_center_offset->negative}); # $cur_pos->translate(@{$self->_drag_volume_center_offset->negative});
# } # }
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ # # Calculate the translation vector.
# Calculate the translation vector. # my $vector = $self->_drag_start_pos->vector_to($cur_pos);
my $vector = $self->_drag_start_pos->vector_to($cur_pos); # # Get the volume being dragged.
# Get the volume being dragged. # my $volume = $self->volumes->[$self->_drag_volume_idx];
my $volume = $self->volumes->[$self->_drag_volume_idx]; # # Get all volumes belonging to the same group, if any.
# Get all volumes belonging to the same group, if any. # my @volumes = ($volume->drag_group_id == -1) ?
my @volumes = ($volume->drag_group_id == -1) ? # ($volume) :
($volume) : # grep $_->drag_group_id == $volume->drag_group_id, @{$self->volumes};
grep $_->drag_group_id == $volume->drag_group_id, @{$self->volumes}; # # Apply new temporary volume origin and ignore Z.
# Apply new temporary volume origin and ignore Z. # $_->translate($vector->x, $vector->y, 0) for @volumes;
$_->translate($vector->x, $vector->y, 0) for @volumes; # $self->_drag_start_pos($cur_pos);
$self->_drag_start_pos($cur_pos); # $self->_dragged(1);
$self->_dragged(1); # $self->Refresh;
$self->Refresh; # $self->Update;
$self->Update; # } elsif ($e->Dragging) {
} elsif ($e->Dragging) {
#==============================================================================================================================
if ((Slic3r::GUI::_3DScene::get_layers_editing_state($self) > 0) && ($object_idx_selected != -1)) {
Slic3r::GUI::_3DScene::perform_layer_editing_action($self, $e->GetY, $e->ShiftDown, $e->RightIsDown) if (Slic3r::GUI::_3DScene::get_layers_editing_state($self) == 1);
# if ($self->_layer_height_edited && $object_idx_selected != -1) { # if ($self->_layer_height_edited && $object_idx_selected != -1) {
# $self->_variable_layer_thickness_action($e) if ($self->_layer_height_edited == 1); # $self->_variable_layer_thickness_action($e) if ($self->_layer_height_edited == 1);
#============================================================================================================================== # } elsif ($e->LeftIsDown) {
} elsif ($e->LeftIsDown) { # # if dragging over blank area with left button, rotate
# if dragging over blank area with left button, rotate # if (defined $self->_drag_start_pos) {
if (defined $self->_drag_start_pos) { # my $orig = $self->_drag_start_pos;
my $orig = $self->_drag_start_pos; # if (TURNTABLE_MODE) {
if (TURNTABLE_MODE) { # # Turntable mode is enabled by default.
# Turntable mode is enabled by default.
#==============================================================================================================================
Slic3r::GUI::_3DScene::set_camera_phi($self, Slic3r::GUI::_3DScene::get_camera_phi($self) + ($pos->x - $orig->x) * TRACKBALLSIZE);
Slic3r::GUI::_3DScene::set_camera_theta($self, Slic3r::GUI::_3DScene::get_camera_theta($self) - ($pos->y - $orig->y) * TRACKBALLSIZE);
# $self->_sphi($self->_sphi + ($pos->x - $orig->x) * TRACKBALLSIZE); # $self->_sphi($self->_sphi + ($pos->x - $orig->x) * TRACKBALLSIZE);
# $self->_stheta($self->_stheta - ($pos->y - $orig->y) * TRACKBALLSIZE); #- # $self->_stheta($self->_stheta - ($pos->y - $orig->y) * TRACKBALLSIZE); #-
# $self->_stheta(GIMBALL_LOCK_THETA_MAX) if $self->_stheta > GIMBALL_LOCK_THETA_MAX; # $self->_stheta(GIMBALL_LOCK_THETA_MAX) if $self->_stheta > GIMBALL_LOCK_THETA_MAX;
# $self->_stheta(0) if $self->_stheta < 0; # $self->_stheta(0) if $self->_stheta < 0;
#============================================================================================================================== # } else {
} else { # my $size = $self->GetClientSize;
my $size = $self->GetClientSize; # my @quat = trackball(
my @quat = trackball( # $orig->x / ($size->width / 2) - 1,
$orig->x / ($size->width / 2) - 1, # 1 - $orig->y / ($size->height / 2), #/
1 - $orig->y / ($size->height / 2), #/ # $pos->x / ($size->width / 2) - 1,
$pos->x / ($size->width / 2) - 1, # 1 - $pos->y / ($size->height / 2), #/
1 - $pos->y / ($size->height / 2), #/ # );
); # $self->_quat(mulquats($self->_quat, \@quat));
$self->_quat(mulquats($self->_quat, \@quat)); # }
} # $self->on_viewport_changed->() if $self->on_viewport_changed;
$self->on_viewport_changed->() if $self->on_viewport_changed; # $self->Refresh;
$self->Refresh; # $self->Update;
$self->Update; # }
} # $self->_drag_start_pos($pos);
$self->_drag_start_pos($pos); # } elsif ($e->MiddleIsDown || $e->RightIsDown) {
} elsif ($e->MiddleIsDown || $e->RightIsDown) { # # If dragging over blank area with right button, pan.
# If dragging over blank area with right button, pan. # if (defined $self->_drag_start_xy) {
if (defined $self->_drag_start_xy) { # # get point in model space at Z = 0
# get point in model space at Z = 0 # my $cur_pos = $self->mouse_to_3d($e->GetX, $e->GetY, 0);
my $cur_pos = $self->mouse_to_3d($e->GetX, $e->GetY, 0); # my $orig = $self->mouse_to_3d($self->_drag_start_xy->x, $self->_drag_start_xy->y, 0);
my $orig = $self->mouse_to_3d($self->_drag_start_xy->x, $self->_drag_start_xy->y, 0);
#==============================================================================================================================
my $camera_target = Slic3r::GUI::_3DScene::get_camera_target($self);
$camera_target->translate(@{$orig->vector_to($cur_pos)->negative});
Slic3r::GUI::_3DScene::set_camera_target($self, $camera_target);
# $self->_camera_target->translate(@{$orig->vector_to($cur_pos)->negative}); # $self->_camera_target->translate(@{$orig->vector_to($cur_pos)->negative});
#============================================================================================================================== # $self->on_viewport_changed->() if $self->on_viewport_changed;
$self->on_viewport_changed->() if $self->on_viewport_changed; # $self->Refresh;
$self->Refresh; # $self->Update;
$self->Update; # }
} # $self->_drag_start_xy($pos);
$self->_drag_start_xy($pos); # }
} # } elsif ($e->LeftUp || $e->MiddleUp || $e->RightUp) {
} elsif ($e->LeftUp || $e->MiddleUp || $e->RightUp) {
#==============================================================================================================================
if (Slic3r::GUI::_3DScene::get_layers_editing_state($self) > 0) {
Slic3r::GUI::_3DScene::set_layers_editing_state($self, 0);
Slic3r::GUI::_3DScene::stop_timer($self);
# if ($self->_layer_height_edited) { # if ($self->_layer_height_edited) {
# $self->_layer_height_edited(undef); # $self->_layer_height_edited(undef);
# $self->{layer_height_edit_timer}->Stop; # $self->{layer_height_edit_timer}->Stop;
#============================================================================================================================== # $self->on_model_update->()
$self->on_model_update->() # if ($object_idx_selected != -1 && $self->on_model_update);
if ($object_idx_selected != -1 && $self->on_model_update); # } elsif ($self->on_move && defined($self->_drag_volume_idx) && $self->_dragged) {
} elsif ($self->on_move && defined($self->_drag_volume_idx) && $self->_dragged) { # # get all volumes belonging to the same group, if any
# get all volumes belonging to the same group, if any # my @volume_idxs;
my @volume_idxs; # my $group_id = $self->volumes->[$self->_drag_volume_idx]->drag_group_id;
my $group_id = $self->volumes->[$self->_drag_volume_idx]->drag_group_id; # if ($group_id == -1) {
if ($group_id == -1) { # @volume_idxs = ($self->_drag_volume_idx);
@volume_idxs = ($self->_drag_volume_idx); # } else {
} else { # @volume_idxs = grep $self->volumes->[$_]->drag_group_id == $group_id,
@volume_idxs = grep $self->volumes->[$_]->drag_group_id == $group_id, # 0..$#{$self->volumes};
0..$#{$self->volumes}; # }
} # $self->on_move->(@volume_idxs);
$self->on_move->(@volume_idxs); # }
} # $self->_drag_volume_idx(undef);
$self->_drag_volume_idx(undef); # $self->_drag_start_pos(undef);
$self->_drag_start_pos(undef); # $self->_drag_start_xy(undef);
$self->_drag_start_xy(undef); # $self->_dragged(undef);
$self->_dragged(undef); # } elsif ($e->Moving) {
} elsif ($e->Moving) {
#==============================================================================================================================
Slic3r::GUI::_3DScene::set_mouse_position($self, $pos);
# $self->_mouse_pos($pos); # $self->_mouse_pos($pos);
#============================================================================================================================== # # Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor
# Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor # # hovers over.
# hovers over.
#==============================================================================================================================
if (Slic3r::GUI::_3DScene::is_picking_enabled($self)) {
# if ($self->enable_picking) { # if ($self->enable_picking) {
#============================================================================================================================== # $self->Update;
$self->Update; # $self->Refresh;
$self->Refresh; # }
} # } else {
} else { # $e->Skip();
$e->Skip(); # }
} #}
} #
#==============================================================================================================================
#sub mouse_wheel_event { #sub mouse_wheel_event {
# my ($self, $e) = @_; # my ($self, $e) = @_;
# #
@ -1165,23 +1090,25 @@ sub mulquats {
@$q1[3] * @$rq[3] - @$q1[0] * @$rq[0] - @$q1[1] * @$rq[1] - @$q1[2] * @$rq[2]) @$q1[3] * @$rq[3] - @$q1[0] * @$rq[0] - @$q1[1] * @$rq[1] - @$q1[2] * @$rq[2])
} }
# Convert the screen space coordinate to an object space coordinate. #==============================================================================================================================
# If the Z screen space coordinate is not provided, a depth buffer value is substituted. ## Convert the screen space coordinate to an object space coordinate.
sub mouse_to_3d { ## If the Z screen space coordinate is not provided, a depth buffer value is substituted.
my ($self, $x, $y, $z) = @_; #sub mouse_to_3d {
# my ($self, $x, $y, $z) = @_;
return unless $self->GetContext; #
$self->SetCurrent($self->GetContext); # return unless $self->GetContext;
# $self->SetCurrent($self->GetContext);
my @viewport = glGetIntegerv_p(GL_VIEWPORT); # 4 items #
my @mview = glGetDoublev_p(GL_MODELVIEW_MATRIX); # 16 items # my @viewport = glGetIntegerv_p(GL_VIEWPORT); # 4 items
my @proj = glGetDoublev_p(GL_PROJECTION_MATRIX); # 16 items # my @mview = glGetDoublev_p(GL_MODELVIEW_MATRIX); # 16 items
# my @proj = glGetDoublev_p(GL_PROJECTION_MATRIX); # 16 items
$y = $viewport[3] - $y; #
$z //= glReadPixels_p($x, $y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT); # $y = $viewport[3] - $y;
my @projected = gluUnProject_p($x, $y, $z, @mview, @proj, @viewport); # $z //= glReadPixels_p($x, $y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT);
return Slic3r::Pointf3->new(@projected); # my @projected = gluUnProject_p($x, $y, $z, @mview, @proj, @viewport);
} # return Slic3r::Pointf3->new(@projected);
#}
#==============================================================================================================================
sub GetContext { sub GetContext {
my ($self) = @_; my ($self) = @_;

View File

@ -84,13 +84,19 @@ sub new {
$self->object_settings_dialog if $self->selected_object; $self->object_settings_dialog if $self->selected_object;
}; };
my $on_right_click = sub { my $on_right_click = sub {
my ($canvas, $click_pos) = @_; #==============================================================================================================================
my ($canvas, $click_pos_x, $click_pos_y) = @_;
# my ($canvas, $click_pos) = @_;
#==============================================================================================================================
my ($obj_idx, $object) = $self->selected_object; my ($obj_idx, $object) = $self->selected_object;
return if !defined $obj_idx; return if !defined $obj_idx;
my $menu = $self->object_menu; my $menu = $self->object_menu;
$canvas->PopupMenu($menu, $click_pos); #==============================================================================================================================
$canvas->PopupMenu($menu, $click_pos_x, $click_pos_y);
# $canvas->PopupMenu($menu, $click_pos);
#==============================================================================================================================
$menu->Destroy; $menu->Destroy;
}; };
my $on_instances_moved = sub { my $on_instances_moved = sub {
@ -111,8 +117,12 @@ sub new {
$self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config}); $self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config});
$self->{preview_notebook}->AddPage($self->{canvas3D}, L('3D')); $self->{preview_notebook}->AddPage($self->{canvas3D}, L('3D'));
$self->{canvas3D}->set_on_select_object($on_select_object); $self->{canvas3D}->set_on_select_object($on_select_object);
$self->{canvas3D}->set_on_double_click($on_double_click); #==============================================================================================================================
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); }); Slic3r::GUI::_3DScene::register_on_double_click_callback($self->{canvas3D}, $on_double_click);
Slic3r::GUI::_3DScene::register_on_right_click_callback($self->{canvas3D}, sub { $on_right_click->($self->{canvas3D}, @_); });
# $self->{canvas3D}->set_on_double_click($on_double_click);
# $self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
#==============================================================================================================================
$self->{canvas3D}->set_on_arrange(sub { $self->arrange }); $self->{canvas3D}->set_on_arrange(sub { $self->arrange });
$self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') }); $self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') });
$self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') }); $self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') });

View File

@ -222,7 +222,10 @@ sub mouse_event {
]; ];
$self->{drag_object} = [ $obj_idx, $instance_idx ]; $self->{drag_object} = [ $obj_idx, $instance_idx ];
} elsif ($event->RightDown) { } elsif ($event->RightDown) {
$self->{on_right_click}->($pos); #=======================================================================================================================================
$self->{on_right_click}->($pos->x, $pos->y);
# $self->{on_right_click}->($pos);
#=======================================================================================================================================
} }
last OBJECTS; last OBJECTS;

View File

@ -21,9 +21,10 @@ sub new {
my $self = $class->SUPER::new($parent); my $self = $class->SUPER::new($parent);
#============================================================================================================================== #==============================================================================================================================
Slic3r::GUI::_3DScene::enable_picking($self, 1); Slic3r::GUI::_3DScene::enable_picking($self, 1);
Slic3r::GUI::_3DScene::enable_moving($self, 1);
# $self->enable_picking(1); # $self->enable_picking(1);
# $self->enable_moving(1);
#============================================================================================================================== #==============================================================================================================================
$self->enable_moving(1);
$self->select_by('object'); $self->select_by('object');
$self->drag_by('instance'); $self->drag_by('instance');
@ -46,6 +47,9 @@ sub new {
$self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx) $self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx)
if ($self->{on_select_object}); if ($self->{on_select_object});
}); });
#==============================================================================================================================
Slic3r::GUI::_3DScene::register_on_select_callback($self, $self->on_select);
#==============================================================================================================================
$self->on_move(sub { $self->on_move(sub {
my @volume_idxs = @_; my @volume_idxs = @_;
@ -125,15 +129,17 @@ sub set_on_select_object {
$self->{on_select_object} = $cb; $self->{on_select_object} = $cb;
} }
sub set_on_double_click { #==============================================================================================================================
my ($self, $cb) = @_; #sub set_on_double_click {
$self->on_double_click($cb); # my ($self, $cb) = @_;
} # $self->on_double_click($cb);
#}
sub set_on_right_click { #
my ($self, $cb) = @_; #sub set_on_right_click {
$self->on_right_click($cb); # my ($self, $cb) = @_;
} # $self->on_right_click($cb);
#}
#==============================================================================================================================
sub set_on_arrange { sub set_on_arrange {
my ($self, $cb) = @_; my ($self, $cb) = @_;

View File

@ -1939,6 +1939,11 @@ bool _3DScene::is_picking_enabled(wxGLCanvas* canvas)
return s_canvas_mgr.is_picking_enabled(canvas); return s_canvas_mgr.is_picking_enabled(canvas);
} }
bool _3DScene::is_moving_enabled(wxGLCanvas* canvas)
{
return s_canvas_mgr.is_moving_enabled(canvas);
}
bool _3DScene::is_layers_editing_allowed(wxGLCanvas* canvas) bool _3DScene::is_layers_editing_allowed(wxGLCanvas* canvas)
{ {
return s_canvas_mgr.is_layers_editing_allowed(canvas); return s_canvas_mgr.is_layers_editing_allowed(canvas);
@ -1969,6 +1974,11 @@ void _3DScene::enable_picking(wxGLCanvas* canvas, bool enable)
s_canvas_mgr.enable_picking(canvas, enable); s_canvas_mgr.enable_picking(canvas, enable);
} }
void _3DScene::enable_moving(wxGLCanvas* canvas, bool enable)
{
s_canvas_mgr.enable_moving(canvas, enable);
}
void _3DScene::enable_shader(wxGLCanvas* canvas, bool enable) void _3DScene::enable_shader(wxGLCanvas* canvas, bool enable)
{ {
s_canvas_mgr.enable_shader(canvas, enable); s_canvas_mgr.enable_shader(canvas, enable);
@ -2170,6 +2180,21 @@ void _3DScene::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* c
s_canvas_mgr.register_on_viewport_changed_callback(canvas, callback); s_canvas_mgr.register_on_viewport_changed_callback(canvas, callback);
} }
void _3DScene::register_on_double_click_callback(wxGLCanvas* canvas, void* callback)
{
s_canvas_mgr.register_on_double_click_callback(canvas, callback);
}
void _3DScene::register_on_right_click_callback(wxGLCanvas* canvas, void* callback)
{
s_canvas_mgr.register_on_right_click_callback(canvas, callback);
}
void _3DScene::register_on_select_callback(wxGLCanvas* canvas, void* callback)
{
s_canvas_mgr.register_on_select_callback(canvas, callback);
}
//void _3DScene::_glew_init() //void _3DScene::_glew_init()
//{ //{
// glewInit(); // glewInit();

View File

@ -598,6 +598,7 @@ public:
static bool is_layers_editing_enabled(wxGLCanvas* canvas); static bool is_layers_editing_enabled(wxGLCanvas* canvas);
static bool is_picking_enabled(wxGLCanvas* canvas); static bool is_picking_enabled(wxGLCanvas* canvas);
static bool is_moving_enabled(wxGLCanvas* canvas);
static bool is_layers_editing_allowed(wxGLCanvas* canvas); static bool is_layers_editing_allowed(wxGLCanvas* canvas);
static bool is_multisample_allowed(wxGLCanvas* canvas); static bool is_multisample_allowed(wxGLCanvas* canvas);
@ -605,6 +606,7 @@ public:
static void enable_warning_texture(wxGLCanvas* canvas, bool enable); static void enable_warning_texture(wxGLCanvas* canvas, bool enable);
static void enable_legend_texture(wxGLCanvas* canvas, bool enable); static void enable_legend_texture(wxGLCanvas* canvas, bool enable);
static void enable_picking(wxGLCanvas* canvas, bool enable); static void enable_picking(wxGLCanvas* canvas, bool enable);
static void enable_moving(wxGLCanvas* canvas, bool enable);
static void enable_shader(wxGLCanvas* canvas, bool enable); static void enable_shader(wxGLCanvas* canvas, bool enable);
static void allow_multisample(wxGLCanvas* canvas, bool allow); static void allow_multisample(wxGLCanvas* canvas, bool allow);
@ -663,6 +665,9 @@ public:
static void perform_layer_editing_action(wxGLCanvas* canvas, int y, bool shift_down, bool right_down); static void perform_layer_editing_action(wxGLCanvas* canvas, int y, bool shift_down, bool right_down);
static void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); static void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
static void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
static void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
static void register_on_select_callback(wxGLCanvas* canvas, void* callback);
// static void _glew_init(); // static void _glew_init();
//################################################################################################################## //##################################################################################################################

View File

@ -1048,6 +1048,52 @@ void GLCanvas3D::Mouse::set_position(const Pointf& position)
m_position = position; m_position = position;
} }
GLCanvas3D::Drag::Drag()
: m_start_mouse_position(DBL_MAX, DBL_MAX)
, m_volume_idx(-1)
{
}
const Point& GLCanvas3D::Drag::get_start_mouse_position() const
{
return m_start_mouse_position;
}
void GLCanvas3D::Drag::set_start_mouse_position(const Point& position)
{
m_start_mouse_position = position;
}
const Pointf3& GLCanvas3D::Drag::get_start_position_3D() const
{
return m_start_position_3D;
}
void GLCanvas3D::Drag::set_start_position_3D(const Pointf3& position)
{
m_start_position_3D = position;
}
const Vectorf3& GLCanvas3D::Drag::get_volume_center_offset() const
{
return m_volume_center_offset;
}
void GLCanvas3D::Drag::set_volume_center_offset(const Vectorf3& offset)
{
m_volume_center_offset = offset;
}
int GLCanvas3D::Drag::get_volume_idx() const
{
return m_volume_idx;
}
void GLCanvas3D::Drag::set_volume_idx(int idx)
{
m_volume_idx = idx;
}
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context)
: m_canvas(canvas) : m_canvas(canvas)
, m_context(context) , m_context(context)
@ -1061,6 +1107,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context)
, m_warning_texture_enabled(false) , m_warning_texture_enabled(false)
, m_legend_texture_enabled(false) , m_legend_texture_enabled(false)
, m_picking_enabled(false) , m_picking_enabled(false)
, m_moving_enabled(false)
, m_shader_enabled(false) , m_shader_enabled(false)
, m_multisample_allowed(false) , m_multisample_allowed(false)
{ {
@ -1439,6 +1486,11 @@ bool GLCanvas3D::is_picking_enabled() const
return m_picking_enabled; return m_picking_enabled;
} }
bool GLCanvas3D::is_moving_enabled() const
{
return m_moving_enabled;
}
bool GLCanvas3D::is_layers_editing_allowed() const bool GLCanvas3D::is_layers_editing_allowed() const
{ {
return m_layers_editing.is_allowed(); return m_layers_editing.is_allowed();
@ -1469,6 +1521,11 @@ void GLCanvas3D::enable_picking(bool enable)
m_picking_enabled = enable; m_picking_enabled = enable;
} }
void GLCanvas3D::enable_moving(bool enable)
{
m_moving_enabled = enable;
}
void GLCanvas3D::enable_shader(bool enable) void GLCanvas3D::enable_shader(bool enable)
{ {
m_shader_enabled = enable; m_shader_enabled = enable;
@ -1768,6 +1825,24 @@ void GLCanvas3D::register_on_viewport_changed_callback(void* callback)
m_on_viewport_changed_callback.register_callback(callback); m_on_viewport_changed_callback.register_callback(callback);
} }
void GLCanvas3D::register_on_double_click_callback(void* callback)
{
if (callback != nullptr)
m_on_double_click_callback.register_callback(callback);
}
void GLCanvas3D::register_on_right_click_callback(void* callback)
{
if (callback != nullptr)
m_on_right_click_callback.register_callback(callback);
}
void GLCanvas3D::register_on_select_callback(void* callback)
{
if (callback != nullptr)
m_on_select_callback.register_callback(callback);
}
void GLCanvas3D::on_size(wxSizeEvent& evt) void GLCanvas3D::on_size(wxSizeEvent& evt)
{ {
set_dirty(true); set_dirty(true);
@ -1805,7 +1880,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
{ {
// key B/b // key B/b
case 66: case 66:
case 98: { zoom_to_bed(); break; } case 98: { zoom_to_bed(); break; }
// key Z/z // key Z/z
case 90: case 90:
case 122: { zoom_to_volumes(); break; } case 122: { zoom_to_volumes(); break; }
@ -1869,6 +1944,231 @@ void GLCanvas3D::on_timer(wxTimerEvent& evt)
_perform_layer_editing_action(); _perform_layer_editing_action();
} }
void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
if ((m_canvas == nullptr) || (m_volumes == nullptr))
return;
Point pos(evt.GetX(), evt.GetY());
int selected_object_idx = (is_layers_editing_enabled() && (m_print != nullptr)) ? get_layers_editing_first_selected_object_id(m_print->objects.size()) : -1;
set_layers_editing_last_object_id(selected_object_idx);
set_mouse_dragging(evt.Dragging());
if (evt.Entering())
{
#if defined(__WXMSW__) || defined(__WXGTK__)
// On Windows and Linux needs focus in order to catch key events
m_canvas->SetFocus();
m_drag.set_start_mouse_position(Point(INT_MAX, INT_MAX));
#endif
}
else if (evt.LeftDClick())
{
m_on_double_click_callback.call();
}
else if (evt.LeftDown() || evt.RightDown())
{
// If user pressed left or right button we first check whether this happened
// on a volume or not.
int volume_idx = get_hover_volume_id();
set_layers_editing_state(0);
if ((selected_object_idx != -1) && bar_rect_contains(pos.x, pos.y))
{
// A volume is selected and the mouse is inside the layer thickness bar.
// Start editing the layer height.
set_layers_editing_state(1);
perform_layer_editing_action(evt.GetY(), evt.ShiftDown(), evt.RightDown());
}
else if ((selected_object_idx != -1) && reset_rect_contains(pos.x, pos.y))
{
if (evt.LeftDown())
{
// A volume is selected and the mouse is inside the reset button.
m_print->get_object(selected_object_idx)->reset_layer_height_profile();
// Index 2 means no editing, just wait for mouse up event.
set_layers_editing_state(2);
m_canvas->Refresh();
m_canvas->Update();
}
}
else
{
// Select volume in this 3D canvas.
// Don't deselect a volume if layer editing is enabled. We want the object to stay selected
// during the scene manipulation.
if (is_picking_enabled() && ((volume_idx != -1) || !is_layers_editing_enabled()))
{
deselect_volumes();
select_volume(volume_idx);
if (volume_idx != -1)
{
int group_id = m_volumes->volumes[volume_idx]->select_group_id;
if (group_id != -1)
{
for (GLVolume* vol : m_volumes->volumes)
{
if ((vol != nullptr) && (vol->select_group_id == group_id))
vol->selected = true;
}
}
}
m_canvas->Refresh();
m_canvas->Update();
}
// propagate event through callback
m_on_select_callback.call(volume_idx);
// The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate pos x, y,
// an converts the screen space coordinate to unscaled object space.
Pointf3 pos3d = (volume_idx == -1) ? Pointf3(DBL_MAX, DBL_MAX) : _mouse_to_3d(pos);
if (volume_idx != -1)
{
if (evt.LeftDown() && is_moving_enabled())
{
// Only accept the initial position, if it is inside the volume bounding box.
BoundingBoxf3 volume_bbox = m_volumes->volumes[volume_idx]->transformed_bounding_box();
volume_bbox.offset(1.0);
if (volume_bbox.contains(pos3d))
{
// The dragging operation is initiated.
m_drag.set_volume_idx(volume_idx);
m_drag.set_start_position_3D(pos3d);
// Remember the shift to to the object center.The object center will later be used
// to limit the object placement close to the bed.
m_drag.set_volume_center_offset(pos3d.vector_to(volume_bbox.center()));
}
}
else if (evt.RightDown())
{
// if right clicking on volume, propagate event through callback
if (m_volumes->volumes[volume_idx]->hover)
{
m_on_right_click_callback.call(pos.x, pos.y);
}
}
}
}
}
// } elsif($e->Dragging && $e->LeftIsDown && (Slic3r::GUI::_3DScene::get_layers_editing_state($self) == 0) && defined($self->_drag_volume_idx)) {
// # Get new position at the same Z of the initial click point.
// my $cur_pos = Slic3r::Linef3->new(
// $self->mouse_to_3d($e->GetX, $e->GetY, 0),
// $self->mouse_to_3d($e->GetX, $e->GetY, 1))
// ->intersect_plane($self->_drag_start_pos->z);
//
// # Clip the new position, so the object center remains close to the bed.
// {
// $cur_pos->translate(@{$self->_drag_volume_center_offset});
// my $cur_pos2 = Slic3r::Point->new(scale($cur_pos->x), scale($cur_pos->y));
// if (!$self->bed_polygon->contains_point($cur_pos2)) {
// my $ip = $self->bed_polygon->point_projection($cur_pos2);
// $cur_pos->set_x(unscale($ip->x));
// $cur_pos->set_y(unscale($ip->y));
// }
// $cur_pos->translate(@{$self->_drag_volume_center_offset->negative});
// }
//
// # Calculate the translation vector.
// my $vector = $self->_drag_start_pos->vector_to($cur_pos);
// # Get the volume being dragged.
// my $volume = $self->volumes->[$self->_drag_volume_idx];
// # Get all volumes belonging to the same group, if any.
// my @volumes = ($volume->drag_group_id == -1) ?
// ($volume) :
// grep $_->drag_group_id == $volume->drag_group_id, @{$self->volumes};
// # Apply new temporary volume origin and ignore Z.
// $_->translate($vector->x, $vector->y, 0) for @volumes;
// $self->_drag_start_pos($cur_pos);
// $self->_dragged(1);
// $self->Refresh;
// $self->Update;
// } elsif($e->Dragging) {
// if ((Slic3r::GUI::_3DScene::get_layers_editing_state($self) > 0) && ($object_idx_selected != -1)) {
// Slic3r::GUI::_3DScene::perform_layer_editing_action($self, $e->GetY, $e->ShiftDown, $e->RightIsDown) if (Slic3r::GUI::_3DScene::get_layers_editing_state($self) == 1);
// } elsif($e->LeftIsDown) {
//# if dragging over blank area with left button, rotate
// if (defined $self->_drag_start_pos) {
// my $orig = $self->_drag_start_pos;
// if (TURNTABLE_MODE) {
// # Turntable mode is enabled by default.
// Slic3r::GUI::_3DScene::set_camera_phi($self, Slic3r::GUI::_3DScene::get_camera_phi($self) + ($pos->x - $orig->x) * TRACKBALLSIZE);
// Slic3r::GUI::_3DScene::set_camera_theta($self, Slic3r::GUI::_3DScene::get_camera_theta($self) - ($pos->y - $orig->y) * TRACKBALLSIZE);
// }
// else {
// my $size = $self->GetClientSize;
// my @quat = trackball(
// $orig->x / ($size->width / 2) - 1,
// 1 - $orig->y / ($size->height / 2), # /
// $pos->x / ($size->width / 2) - 1,
// 1 - $pos->y / ($size->height / 2), # /
// );
// $self->_quat(mulquats($self->_quat, \@quat));
// }
// $self->on_viewport_changed->() if $self->on_viewport_changed;
// $self->Refresh;
// $self->Update;
// }
// $self->_drag_start_pos($pos);
// } elsif($e->MiddleIsDown || $e->RightIsDown) {
// # If dragging over blank area with right button, pan.
// if (defined $self->_drag_start_xy) {
// # get point in model space at Z = 0
// my $cur_pos = $self->mouse_to_3d($e->GetX, $e->GetY, 0);
// my $orig = $self->mouse_to_3d($self->_drag_start_xy->x, $self->_drag_start_xy->y, 0);
// my $camera_target = Slic3r::GUI::_3DScene::get_camera_target($self);
// $camera_target->translate(@{$orig->vector_to($cur_pos)->negative});
// Slic3r::GUI::_3DScene::set_camera_target($self, $camera_target);
// $self->on_viewport_changed->() if $self->on_viewport_changed;
// $self->Refresh;
// $self->Update;
// }
// $self->_drag_start_xy($pos);
// }
// } elsif($e->LeftUp || $e->MiddleUp || $e->RightUp) {
// if (Slic3r::GUI::_3DScene::get_layers_editing_state($self) > 0) {
// Slic3r::GUI::_3DScene::set_layers_editing_state($self, 0);
// Slic3r::GUI::_3DScene::stop_timer($self);
// $self->on_model_update->()
// if ($object_idx_selected != -1 && $self->on_model_update);
// } elsif($self->on_move && defined($self->_drag_volume_idx) && $self->_dragged) {
// # get all volumes belonging to the same group, if any
// my @volume_idxs;
// my $group_id = $self->volumes->[$self->_drag_volume_idx]->drag_group_id;
// if ($group_id == -1) {
// @volume_idxs = ($self->_drag_volume_idx);
// }
// else {
// @volume_idxs = grep $self->volumes->[$_]->drag_group_id == $group_id,
// 0..$#{$self->volumes};
// }
// $self->on_move->(@volume_idxs);
// }
// $self->_drag_volume_idx(undef);
// $self->_drag_start_pos(undef);
// $self->_drag_start_xy(undef);
// $self->_dragged(undef);
// }
else if (evt.Moving())
{
set_mouse_position(Pointf((coordf_t)pos.x, (coordf_t)pos.y));
// Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor hovers over.
if (is_picking_enabled())
{
m_canvas->Refresh();
m_canvas->Update();
}
}
else
evt.Skip();
}
Size GLCanvas3D::get_canvas_size() const Size GLCanvas3D::get_canvas_size() const
{ {
int w = 0; int w = 0;
@ -1997,6 +2297,9 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co
void GLCanvas3D::_deregister_callbacks() void GLCanvas3D::_deregister_callbacks()
{ {
m_on_viewport_changed_callback.deregister_callback(); m_on_viewport_changed_callback.deregister_callback();
m_on_double_click_callback.deregister_callback();
m_on_right_click_callback.deregister_callback();
m_on_select_callback.deregister_callback();
} }
void GLCanvas3D::_mark_volumes_for_layer_height() const void GLCanvas3D::_mark_volumes_for_layer_height() const
@ -2337,5 +2640,29 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
start_timer(); start_timer();
} }
Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z)
{
if (!set_current())
return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX);
GLint viewport[4];
::glGetIntegerv(GL_VIEWPORT, viewport);
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;
GLfloat mouse_z;
if (z == nullptr)
::glReadPixels((GLint)mouse_pos.x, (GLint)mouse_pos.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)&mouse_z);
else
mouse_z = *z;
GLdouble out_x, out_y, out_z;
::gluUnProject((GLdouble)mouse_pos.x, (GLdouble)mouse_pos.y, mouse_z, modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
return Pointf3((coordf_t)out_x, (coordf_t)out_y, (coordf_t)out_z);
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -306,6 +306,29 @@ public:
void set_position(const Pointf& position); void set_position(const Pointf& position);
}; };
class Drag
{
Point m_start_mouse_position;
Pointf3 m_start_position_3D;
Vectorf3 m_volume_center_offset;
int m_volume_idx;
public:
Drag();
const Point& get_start_mouse_position() const;
void set_start_mouse_position(const Point& mouse_position);
const Pointf3& get_start_position_3D() const;
void set_start_position_3D(const Pointf3& position);
const Vectorf3& get_volume_center_offset() const;
void set_volume_center_offset(const Vectorf3& offset);
int get_volume_idx() const;
void set_volume_idx(int idx);
};
private: private:
wxGLCanvas* m_canvas; wxGLCanvas* m_canvas;
wxGLContext* m_context; wxGLContext* m_context;
@ -317,6 +340,7 @@ private:
LayersEditing m_layers_editing; LayersEditing m_layers_editing;
Shader m_shader; Shader m_shader;
Mouse m_mouse; Mouse m_mouse;
Drag m_drag;
GLVolumeCollection* m_volumes; GLVolumeCollection* m_volumes;
DynamicPrintConfig* m_config; DynamicPrintConfig* m_config;
@ -328,10 +352,14 @@ private:
bool m_warning_texture_enabled; bool m_warning_texture_enabled;
bool m_legend_texture_enabled; bool m_legend_texture_enabled;
bool m_picking_enabled; bool m_picking_enabled;
bool m_moving_enabled;
bool m_shader_enabled; bool m_shader_enabled;
bool m_multisample_allowed; bool m_multisample_allowed;
PerlCallback m_on_viewport_changed_callback; PerlCallback m_on_viewport_changed_callback;
PerlCallback m_on_double_click_callback;
PerlCallback m_on_right_click_callback;
PerlCallback m_on_select_callback;
public: public:
GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context); GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context);
@ -398,6 +426,7 @@ public:
bool is_layers_editing_enabled() const; bool is_layers_editing_enabled() const;
bool is_picking_enabled() const; bool is_picking_enabled() const;
bool is_moving_enabled() const;
bool is_layers_editing_allowed() const; bool is_layers_editing_allowed() const;
bool is_multisample_allowed() const; bool is_multisample_allowed() const;
@ -405,6 +434,7 @@ public:
void enable_warning_texture(bool enable); void enable_warning_texture(bool enable);
void enable_legend_texture(bool enable); void enable_legend_texture(bool enable);
void enable_picking(bool enable); void enable_picking(bool enable);
void enable_moving(bool enable);
void enable_shader(bool enable); void enable_shader(bool enable);
void allow_multisample(bool allow); void allow_multisample(bool allow);
@ -459,12 +489,16 @@ public:
void render_texture(unsigned int tex_id, float left, float right, float bottom, float top) const; void render_texture(unsigned int tex_id, float left, float right, float bottom, float top) const;
void register_on_viewport_changed_callback(void* callback); void register_on_viewport_changed_callback(void* callback);
void register_on_double_click_callback(void* callback);
void register_on_right_click_callback(void* callback);
void register_on_select_callback(void* callback);
void on_size(wxSizeEvent& evt); void on_size(wxSizeEvent& evt);
void on_idle(wxIdleEvent& evt); void on_idle(wxIdleEvent& evt);
void on_char(wxKeyEvent& evt); void on_char(wxKeyEvent& evt);
void on_mouse_wheel(wxMouseEvent& evt); void on_mouse_wheel(wxMouseEvent& evt);
void on_timer(wxTimerEvent& evt); void on_timer(wxTimerEvent& evt);
void on_mouse(wxMouseEvent& evt);
Size get_canvas_size() const; Size get_canvas_size() const;
Point get_local_mouse_position() const; Point get_local_mouse_position() const;
@ -494,6 +528,10 @@ private:
void _render_layer_editing_overlay() const; void _render_layer_editing_overlay() const;
void _perform_layer_editing_action(wxMouseEvent* evt = nullptr); void _perform_layer_editing_action(wxMouseEvent* evt = nullptr);
// Convert the screen space coordinate to an object space coordinate.
// If the Z screen space coordinate is not provided, a depth buffer value is substituted.
Pointf3 _mouse_to_3d(const Point& mouse_pos, float* z = nullptr);
}; };
} // namespace GUI } // namespace GUI

View File

@ -78,6 +78,18 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas, wxGLContext* context)
canvas->Bind(wxEVT_CHAR, [canvas3D](wxKeyEvent& evt) { canvas3D->on_char(evt); }); canvas->Bind(wxEVT_CHAR, [canvas3D](wxKeyEvent& evt) { canvas3D->on_char(evt); });
canvas->Bind(wxEVT_MOUSEWHEEL, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse_wheel(evt); }); canvas->Bind(wxEVT_MOUSEWHEEL, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse_wheel(evt); });
canvas->Bind(wxEVT_TIMER, [canvas3D](wxTimerEvent& evt) { canvas3D->on_timer(evt); }); canvas->Bind(wxEVT_TIMER, [canvas3D](wxTimerEvent& evt) { canvas3D->on_timer(evt); });
canvas->Bind(wxEVT_LEFT_DOWN, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_LEFT_UP, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_MIDDLE_DOWN, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_MIDDLE_UP, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_RIGHT_DOWN, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_RIGHT_UP, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_MOTION, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_ENTER_WINDOW, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_LEAVE_WINDOW, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_LEFT_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_MIDDLE_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
canvas->Bind(wxEVT_RIGHT_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); });
m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D)); m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));
@ -384,6 +396,12 @@ bool GLCanvas3DManager::is_picking_enabled(wxGLCanvas* canvas) const
return (it != m_canvases.end()) ? it->second->is_picking_enabled() : false; return (it != m_canvases.end()) ? it->second->is_picking_enabled() : false;
} }
bool GLCanvas3DManager::is_moving_enabled(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->is_moving_enabled() : false;
}
bool GLCanvas3DManager::is_layers_editing_allowed(wxGLCanvas* canvas) const bool GLCanvas3DManager::is_layers_editing_allowed(wxGLCanvas* canvas) const
{ {
CanvasesMap::const_iterator it = _get_canvas(canvas); CanvasesMap::const_iterator it = _get_canvas(canvas);
@ -424,6 +442,13 @@ void GLCanvas3DManager::enable_picking(wxGLCanvas* canvas, bool enable)
it->second->enable_picking(enable); it->second->enable_picking(enable);
} }
void GLCanvas3DManager::enable_moving(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_moving(enable);
}
void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool enable) void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool enable)
{ {
CanvasesMap::iterator it = _get_canvas(canvas); CanvasesMap::iterator it = _get_canvas(canvas);
@ -692,6 +717,27 @@ void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas
it->second->register_on_viewport_changed_callback(callback); it->second->register_on_viewport_changed_callback(callback);
} }
void GLCanvas3DManager::register_on_double_click_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_double_click_callback(callback);
}
void GLCanvas3DManager::register_on_right_click_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_right_click_callback(callback);
}
void GLCanvas3DManager::register_on_select_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_select_callback(callback);
}
GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas)
{ {
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);

View File

@ -98,6 +98,7 @@ public:
bool is_layers_editing_enabled(wxGLCanvas* canvas) const; bool is_layers_editing_enabled(wxGLCanvas* canvas) const;
bool is_picking_enabled(wxGLCanvas* canvas) const; bool is_picking_enabled(wxGLCanvas* canvas) const;
bool is_moving_enabled(wxGLCanvas* canvas) const;
bool is_layers_editing_allowed(wxGLCanvas* canvas) const; bool is_layers_editing_allowed(wxGLCanvas* canvas) const;
bool is_multisample_allowed(wxGLCanvas* canvas) const; bool is_multisample_allowed(wxGLCanvas* canvas) const;
@ -105,6 +106,7 @@ public:
void enable_warning_texture(wxGLCanvas* canvas, bool enable); void enable_warning_texture(wxGLCanvas* canvas, bool enable);
void enable_legend_texture(wxGLCanvas* canvas, bool enable); void enable_legend_texture(wxGLCanvas* canvas, bool enable);
void enable_picking(wxGLCanvas* canvas, bool enable); void enable_picking(wxGLCanvas* canvas, bool enable);
void enable_moving(wxGLCanvas* canvas, bool enable);
void enable_shader(wxGLCanvas* canvas, bool enable); void enable_shader(wxGLCanvas* canvas, bool enable);
void allow_multisample(wxGLCanvas* canvas, bool allow); void allow_multisample(wxGLCanvas* canvas, bool allow);
@ -163,6 +165,9 @@ public:
void perform_layer_editing_action(wxGLCanvas* canvas, int y, bool shift_down, bool right_down); void perform_layer_editing_action(wxGLCanvas* canvas, int y, bool shift_down, bool right_down);
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
void register_on_select_callback(wxGLCanvas* canvas, void* callback);
private: private:
CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas);

View File

@ -467,6 +467,14 @@ is_picking_enabled(canvas)
OUTPUT: OUTPUT:
RETVAL RETVAL
bool
is_moving_enabled(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::is_moving_enabled((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
bool bool
is_layers_editing_allowed(canvas) is_layers_editing_allowed(canvas)
SV *canvas; SV *canvas;
@ -503,7 +511,7 @@ enable_legend_texture(canvas, enable)
bool enable; bool enable;
CODE: CODE:
_3DScene::enable_legend_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable); _3DScene::enable_legend_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void void
enable_picking(canvas, enable) enable_picking(canvas, enable)
SV *canvas; SV *canvas;
@ -511,6 +519,13 @@ enable_picking(canvas, enable)
CODE: CODE:
_3DScene::enable_picking((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable); _3DScene::enable_picking((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_moving(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_moving((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void void
enable_shader(canvas, enable) enable_shader(canvas, enable)
SV *canvas; SV *canvas;
@ -810,7 +825,27 @@ register_on_viewport_changed_callback(canvas, callback)
SV *callback; SV *callback;
CODE: CODE:
_3DScene::register_on_viewport_changed_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); _3DScene::register_on_viewport_changed_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_double_click_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_double_click_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_right_click_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_right_click_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_select_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_select_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
unsigned int unsigned int