Merge remote-tracking branch 'remotes/origin/opengl_to_cpp'

This commit is contained in:
bubnikv 2018-06-19 16:08:53 +02:00
commit 5a56f08aad
49 changed files with 10551 additions and 3604 deletions

View File

@ -223,8 +223,8 @@ sub system_info {
my $opengl_info_txt = ''; my $opengl_info_txt = '';
if (defined($self->{mainframe}) && defined($self->{mainframe}->{plater}) && if (defined($self->{mainframe}) && defined($self->{mainframe}->{plater}) &&
defined($self->{mainframe}->{plater}->{canvas3D})) { defined($self->{mainframe}->{plater}->{canvas3D})) {
$opengl_info = $self->{mainframe}->{plater}->{canvas3D}->opengl_info(format => 'html'); $opengl_info = Slic3r::GUI::_3DScene::get_gl_info(1, 1);
$opengl_info_txt = $self->{mainframe}->{plater}->{canvas3D}->opengl_info; $opengl_info_txt = Slic3r::GUI::_3DScene::get_gl_info(0, 1);
} }
my $about = Slic3r::GUI::SystemInfo->new( my $about = Slic3r::GUI::SystemInfo->new(
parent => undef, parent => undef,

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ sub new {
my ($class, %params) = @_; my ($class, %params) = @_;
my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE); my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
Slic3r::GUI::set_main_frame($self); Slic3r::GUI::set_main_frame($self);
if ($^O eq 'MSWin32') { if ($^O eq 'MSWin32') {
# Load the icon either from the exe, or from the ico file. # Load the icon either from the exe, or from the ico file.
my $iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe'; my $iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe';
@ -90,6 +90,8 @@ sub new {
# Save the slic3r.ini. Usually the ini file is saved from "on idle" callback, # Save the slic3r.ini. Usually the ini file is saved from "on idle" callback,
# but in rare cases it may not have been called yet. # but in rare cases it may not have been called yet.
wxTheApp->{app_config}->save; wxTheApp->{app_config}->save;
$self->{plater}->{print} = undef if($self->{plater});
Slic3r::GUI::_3DScene::remove_all_canvases();
# propagate event # propagate event
$event->Skip; $event->Skip;
}); });

View File

@ -78,19 +78,19 @@ sub new {
my $on_select_object = sub { my $on_select_object = sub {
my ($obj_idx) = @_; my ($obj_idx) = @_;
# Ignore the special objects (the wipe tower proxy and such). # Ignore the special objects (the wipe tower proxy and such).
$self->select_object((defined($obj_idx) && $obj_idx < 1000) ? $obj_idx : undef); $self->select_object((defined($obj_idx) && $obj_idx >= 0 && $obj_idx < 1000) ? $obj_idx : undef);
}; };
my $on_double_click = sub { my $on_double_click = sub {
$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 ($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);
$menu->Destroy; $menu->Destroy;
}; };
my $on_instances_moved = sub { my $on_instances_moved = sub {
@ -106,31 +106,64 @@ sub new {
$self->{btn_send_gcode}->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 # Initialize 3D plater
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$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); Slic3r::GUI::_3DScene::register_on_select_object_callback($self->{canvas3D}, $on_select_object);
$self->{canvas3D}->set_on_double_click($on_double_click); Slic3r::GUI::_3DScene::register_on_double_click_callback($self->{canvas3D}, $on_double_click);
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); }); Slic3r::GUI::_3DScene::register_on_right_click_callback($self->{canvas3D}, sub { $on_right_click->($self->{canvas3D}, @_); });
$self->{canvas3D}->set_on_arrange(sub { $self->arrange }); Slic3r::GUI::_3DScene::register_on_arrange_callback($self->{canvas3D}, sub { $self->arrange });
$self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') }); Slic3r::GUI::_3DScene::register_on_rotate_object_left_callback($self->{canvas3D}, sub { $self->rotate(-45, Z, 'relative') });
$self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') }); Slic3r::GUI::_3DScene::register_on_rotate_object_right_callback($self->{canvas3D}, sub { $self->rotate( 45, Z, 'relative') });
$self->{canvas3D}->set_on_scale_object_uniformly(sub { $self->changescale(undef) }); Slic3r::GUI::_3DScene::register_on_scale_object_uniformly_callback($self->{canvas3D}, sub { $self->changescale(undef) });
$self->{canvas3D}->set_on_increase_objects(sub { $self->increase() }); Slic3r::GUI::_3DScene::register_on_increase_objects_callback($self->{canvas3D}, sub { $self->increase() });
$self->{canvas3D}->set_on_decrease_objects(sub { $self->decrease() }); Slic3r::GUI::_3DScene::register_on_decrease_objects_callback($self->{canvas3D}, sub { $self->decrease() });
$self->{canvas3D}->set_on_remove_object(sub { $self->remove() }); Slic3r::GUI::_3DScene::register_on_remove_object_callback($self->{canvas3D}, sub { $self->remove() });
$self->{canvas3D}->set_on_instances_moved($on_instances_moved); Slic3r::GUI::_3DScene::register_on_instance_moved_callback($self->{canvas3D}, $on_instances_moved);
$self->{canvas3D}->set_on_enable_action_buttons($enable_action_buttons); Slic3r::GUI::_3DScene::register_on_enable_action_buttons_callback($self->{canvas3D}, $enable_action_buttons);
$self->{canvas3D}->use_plain_shader(1); Slic3r::GUI::_3DScene::register_on_gizmo_scale_uniformly_callback($self->{canvas3D}, $on_gizmo_scale_uniformly);
$self->{canvas3D}->set_on_wipe_tower_moved(sub { Slic3r::GUI::_3DScene::enable_gizmos($self->{canvas3D}, 1);
my ($new_pos_3f) = @_; Slic3r::GUI::_3DScene::enable_shader($self->{canvas3D}, 1);
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($self->{canvas3D}, 1);
Slic3r::GUI::_3DScene::register_on_wipe_tower_moved_callback($self->{canvas3D}, sub {
my ($x, $y) = @_;
my $cfg = Slic3r::Config->new; my $cfg = Slic3r::Config->new;
$cfg->set('wipe_tower_x', $new_pos_3f->x); $cfg->set('wipe_tower_x', $x);
$cfg->set('wipe_tower_y', $new_pos_3f->y); $cfg->set('wipe_tower_y', $y);
$self->GetFrame->{options_tabs}{print}->load_config($cfg); $self->GetFrame->{options_tabs}{print}->load_config($cfg);
}); });
$self->{canvas3D}->set_on_model_update(sub {
Slic3r::GUI::_3DScene::register_on_model_update_callback($self->{canvas3D}, sub {
if (wxTheApp->{app_config}->get("background_processing")) { if (wxTheApp->{app_config}->get("background_processing")) {
$self->schedule_background_process; $self->schedule_background_process;
} else { } else {
@ -138,9 +171,8 @@ sub new {
$self->{"print_info_box_show"}->(0); $self->{"print_info_box_show"}->(0);
} }
}); });
$self->{canvas3D}->on_viewport_changed(sub {
$self->{preview3D}->canvas->set_viewport_from_scene($self->{canvas3D}); Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{canvas3D}, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{preview3D}->canvas, $self->{canvas3D}); });
});
} }
# Initialize 2D preview canvas # Initialize 2D preview canvas
@ -154,9 +186,8 @@ sub new {
# Initialize 3D toolpaths preview # Initialize 3D toolpaths preview
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config}); $self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
$self->{preview3D}->canvas->on_viewport_changed(sub { Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas); Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
});
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview')); $self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1; $self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
} }
@ -171,13 +202,25 @@ sub new {
my $preview = $self->{preview_notebook}->GetCurrentPage; my $preview = $self->{preview_notebook}->GetCurrentPage;
if ($preview == $self->{preview3D}) if ($preview == $self->{preview3D})
{ {
$self->{preview3D}->canvas->set_legend_enabled(1); Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 1);
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
$self->{preview3D}->load_print(1); $self->{preview3D}->load_print(1);
} else { } else {
$self->{preview3D}->canvas->set_legend_enabled(0); Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 0);
} }
$preview->OnActivate if $preview->can('OnActivate'); if ($preview == $self->{canvas3D}) {
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 1);
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) {
my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
}
} else {
$preview->OnActivate if $preview->can('OnActivate');
}
}); });
# toolbar for object manipulation # toolbar for object manipulation
@ -314,7 +357,7 @@ sub new {
EVT_TOOL($self, TB_CUT, sub { $_[0]->object_cut_dialog }); EVT_TOOL($self, TB_CUT, sub { $_[0]->object_cut_dialog });
EVT_TOOL($self, TB_SETTINGS, sub { $_[0]->object_settings_dialog }); EVT_TOOL($self, TB_SETTINGS, sub { $_[0]->object_settings_dialog });
EVT_TOOL($self, TB_LAYER_EDITING, sub { EVT_TOOL($self, TB_LAYER_EDITING, sub {
my $state = $self->{canvas3D}->layer_editing_enabled; my $state = Slic3r::GUI::_3DScene::is_layers_editing_enabled($self->{canvas3D});
$self->{htoolbar}->ToggleTool(TB_LAYER_EDITING, ! $state); $self->{htoolbar}->ToggleTool(TB_LAYER_EDITING, ! $state);
$self->on_layer_editing_toggled(! $state); $self->on_layer_editing_toggled(! $state);
}); });
@ -369,11 +412,11 @@ sub new {
$self->{canvas}->update_bed_size; $self->{canvas}->update_bed_size;
if ($self->{canvas3D}) { if ($self->{canvas3D}) {
$self->{canvas3D}->update_bed_size; Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape);
$self->{canvas3D}->zoom_to_bed; Slic3r::GUI::_3DScene::zoom_to_bed($self->{canvas3D});
} }
if ($self->{preview3D}) { if ($self->{preview3D}) {
$self->{preview3D}->set_bed_shape($self->{config}->bed_shape); Slic3r::GUI::_3DScene::set_bed_shape($self->{preview3D}->canvas, $self->{config}->bed_shape);
} }
$self->update; $self->update;
@ -590,8 +633,8 @@ sub _on_select_preset {
sub on_layer_editing_toggled { sub on_layer_editing_toggled {
my ($self, $new_state) = @_; my ($self, $new_state) = @_;
$self->{canvas3D}->layer_editing_enabled($new_state); Slic3r::GUI::_3DScene::enable_layers_editing($self->{canvas3D}, $new_state);
if ($new_state && ! $self->{canvas3D}->layer_editing_enabled) { if ($new_state && ! Slic3r::GUI::_3DScene::is_layers_editing_enabled($self->{canvas3D})) {
# Initialization of the OpenGL shaders failed. Disable the tool. # Initialization of the OpenGL shaders failed. Disable the tool.
if ($self->{htoolbar}) { if ($self->{htoolbar}) {
$self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 0); $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 0);
@ -825,8 +868,7 @@ sub load_model_objects {
$self->update; $self->update;
# zoom to objects # zoom to objects
$self->{canvas3D}->zoom_to_volumes Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D};
if $self->{canvas3D};
$self->{list}->Update; $self->{list}->Update;
$self->{list}->Select($obj_idx[-1], 1); $self->{list}->Select($obj_idx[-1], 1);
@ -1217,8 +1259,7 @@ sub async_apply_config {
my $invalidated = $self->{print}->apply_config(wxTheApp->{preset_bundle}->full_config); my $invalidated = $self->{print}->apply_config(wxTheApp->{preset_bundle}->full_config);
# Just redraw the 3D canvas without reloading the scene. # Just redraw the 3D canvas without reloading the scene.
# $self->{canvas3D}->Refresh if ($invalidated && $self->{canvas3D}->layer_editing_enabled); $self->{canvas3D}->Refresh if Slic3r::GUI::_3DScene::is_layers_editing_enabled($self->{canvas3D});
$self->{canvas3D}->Refresh if ($self->{canvas3D}->layer_editing_enabled);
# Hide the slicing results if the current slicing status is no more valid. # Hide the slicing results if the current slicing status is no more valid.
$self->{"print_info_box_show"}->(0) if $invalidated; $self->{"print_info_box_show"}->(0) if $invalidated;
@ -1751,7 +1792,9 @@ sub update {
} }
$self->{canvas}->reload_scene if $self->{canvas}; $self->{canvas}->reload_scene if $self->{canvas};
$self->{canvas3D}->reload_scene if $self->{canvas3D}; my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
$self->{preview3D}->reset_gcode_preview_data if $self->{preview3D}; $self->{preview3D}->reset_gcode_preview_data if $self->{preview3D};
$self->{preview3D}->reload_print if $self->{preview3D}; $self->{preview3D}->reload_print if $self->{preview3D};
} }
@ -1806,9 +1849,8 @@ sub on_config_change {
$self->{config}->set($opt_key, $config->get($opt_key)); $self->{config}->set($opt_key, $config->get($opt_key));
if ($opt_key eq 'bed_shape') { if ($opt_key eq 'bed_shape') {
$self->{canvas}->update_bed_size; $self->{canvas}->update_bed_size;
$self->{canvas3D}->update_bed_size if $self->{canvas3D}; Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape) if $self->{canvas3D};
$self->{preview3D}->set_bed_shape($self->{config}->bed_shape) Slic3r::GUI::_3DScene::set_bed_shape($self->{preview3D}->canvas, $self->{config}->bed_shape) if $self->{preview3D};
if $self->{preview3D};
$update_scheduled = 1; $update_scheduled = 1;
} elsif ($opt_key =~ '^wipe_tower' || $opt_key eq 'single_extruder_multi_material') { } elsif ($opt_key =~ '^wipe_tower' || $opt_key eq 'single_extruder_multi_material') {
$update_scheduled = 1; $update_scheduled = 1;
@ -1827,10 +1869,10 @@ sub on_config_change {
$self->{"btn_layer_editing"}->Disable; $self->{"btn_layer_editing"}->Disable;
$self->{"btn_layer_editing"}->SetValue(0); $self->{"btn_layer_editing"}->SetValue(0);
} }
$self->{canvas3D}->layer_editing_enabled(0); Slic3r::GUI::_3DScene::enable_layers_editing($self->{canvas3D}, 0);
$self->{canvas3D}->Refresh; $self->{canvas3D}->Refresh;
$self->{canvas3D}->Update; $self->{canvas3D}->Update;
} elsif ($self->{canvas3D}->layer_editing_allowed) { } elsif (Slic3r::GUI::_3DScene::is_layers_editing_allowed($self->{canvas3D})) {
# Want to allow the layer editing, but do it only if the OpenGL supports it. # Want to allow the layer editing, but do it only if the OpenGL supports it.
if ($self->{htoolbar}) { if ($self->{htoolbar}) {
$self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 1); $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 1);
@ -1862,8 +1904,8 @@ sub list_item_deselected {
if ($self->{list}->GetFirstSelected == -1) { if ($self->{list}->GetFirstSelected == -1) {
$self->select_object(undef); $self->select_object(undef);
$self->{canvas}->Refresh; $self->{canvas}->Refresh;
$self->{canvas3D}->deselect_volumes if $self->{canvas3D}; Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D}) if $self->{canvas3D};
$self->{canvas3D}->Render if $self->{canvas3D}; Slic3r::GUI::_3DScene::render($self->{canvas3D}) if $self->{canvas3D};
} }
undef $self->{_lecursor}; undef $self->{_lecursor};
} }
@ -1875,11 +1917,23 @@ sub list_item_selected {
my $obj_idx = $event->GetIndex; my $obj_idx = $event->GetIndex;
$self->select_object($obj_idx); $self->select_object($obj_idx);
$self->{canvas}->Refresh; $self->{canvas}->Refresh;
$self->{canvas3D}->update_volumes_selection if $self->{canvas3D}; if ($self->{canvas3D}) {
$self->{canvas3D}->Render if $self->{canvas3D}; my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::render($self->{canvas3D});
}
undef $self->{_lecursor}; undef $self->{_lecursor};
} }
sub collect_selections {
my ($self) = @_;
my $selections = [];
foreach my $o (@{$self->{objects}}) {
push(@$selections, $o->selected);
}
return $selections;
}
sub list_item_activated { sub list_item_activated {
my ($self, $event, $obj_idx) = @_; my ($self, $event, $obj_idx) = @_;
@ -1936,7 +1990,7 @@ sub object_cut_dialog {
$self->remove($obj_idx); $self->remove($obj_idx);
$self->load_model_objects(grep defined($_), @new_objects); $self->load_model_objects(grep defined($_), @new_objects);
$self->arrange; $self->arrange;
$self->{canvas3D}->zoom_to_volumes if $self->{canvas3D}; Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D};
} }
} }
@ -1972,7 +2026,9 @@ sub object_settings_dialog {
$self->{print}->reload_object($obj_idx); $self->{print}->reload_object($obj_idx);
$self->schedule_background_process; $self->schedule_background_process;
$self->{canvas}->reload_scene if $self->{canvas}; $self->{canvas}->reload_scene if $self->{canvas};
$self->{canvas3D}->reload_scene if $self->{canvas3D}; my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
} else { } else {
$self->resume_background_process; $self->resume_background_process;
} }
@ -1985,7 +2041,7 @@ sub object_list_changed {
# Enable/disable buttons depending on whether there are any objects on the platter. # Enable/disable buttons depending on whether there are any objects on the platter.
my $have_objects = @{$self->{objects}} ? 1 : 0; my $have_objects = @{$self->{objects}} ? 1 : 0;
my $variable_layer_height_allowed = $self->{config}->variable_layer_height && $self->{canvas3D}->layer_editing_allowed; my $variable_layer_height_allowed = $self->{config}->variable_layer_height && Slic3r::GUI::_3DScene::is_layers_editing_allowed($self->{canvas3D});
if ($self->{htoolbar}) { if ($self->{htoolbar}) {
# On OSX or Linux # On OSX or Linux
$self->{htoolbar}->EnableTool($_, $have_objects) $self->{htoolbar}->EnableTool($_, $have_objects)
@ -2000,7 +2056,7 @@ sub object_list_changed {
} }
my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file};
my $model_fits = $self->{canvas3D} ? $self->{canvas3D}->volumes->check_outside_state($self->{config}) : 1; my $model_fits = $self->{canvas3D} ? Slic3r::GUI::_3DScene::check_volumes_outside_state($self->{canvas3D}, $self->{config}) : 1;
my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable'; my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable';
$self->{"btn_$_"}->$method $self->{"btn_$_"}->$method
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);
@ -2220,11 +2276,11 @@ sub select_view {
my $idx_page = $self->{preview_notebook}->GetSelection; my $idx_page = $self->{preview_notebook}->GetSelection;
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? L('3D') : $self->{preview_notebook}->GetPageText($idx_page); my $page = ($idx_page == &Wx::wxNOT_FOUND) ? L('3D') : $self->{preview_notebook}->GetPageText($idx_page);
if ($page eq L('Preview')) { if ($page eq L('Preview')) {
$self->{preview3D}->canvas->select_view($direction); Slic3r::GUI::_3DScene::select_view($self->{preview3D}->canvas, $direction);
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas); Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas);
} else { } else {
$self->{canvas3D}->select_view($direction); Slic3r::GUI::_3DScene::select_view($self->{canvas3D}, $direction);
$self->{preview3D}->canvas->set_viewport_from_scene($self->{canvas3D}); Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{preview3D}->canvas, $self->{canvas3D});
} }
} }

View File

@ -222,7 +222,7 @@ 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);
} }
last OBJECTS; last OBJECTS;

View File

@ -5,264 +5,279 @@ use utf8;
use List::Util qw(); use List::Util qw();
use Wx qw(:misc :pen :brush :sizer :font :cursor :keycode wxTAB_TRAVERSAL); use Wx qw(:misc :pen :brush :sizer :font :cursor :keycode wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR); #==============================================================================================================================
#use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR);
#==============================================================================================================================
use base qw(Slic3r::GUI::3DScene Class::Accessor); use base qw(Slic3r::GUI::3DScene Class::Accessor);
use Wx::Locale gettext => 'L'; #==============================================================================================================================
#use Wx::Locale gettext => 'L';
__PACKAGE__->mk_accessors(qw( #
on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly #__PACKAGE__->mk_accessors(qw(
on_remove_object on_increase_objects on_decrease_objects on_enable_action_buttons)); # on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
# on_remove_object on_increase_objects on_decrease_objects on_enable_action_buttons));
#==============================================================================================================================
sub new { sub new {
my $class = shift; my $class = shift;
my ($parent, $objects, $model, $print, $config) = @_; my ($parent, $objects, $model, $print, $config) = @_;
my $self = $class->SUPER::new($parent); my $self = $class->SUPER::new($parent);
$self->enable_picking(1); #==============================================================================================================================
$self->enable_moving(1); Slic3r::GUI::_3DScene::enable_picking($self, 1);
$self->select_by('object'); Slic3r::GUI::_3DScene::enable_moving($self, 1);
$self->drag_by('instance'); Slic3r::GUI::_3DScene::set_select_by($self, 'object');
Slic3r::GUI::_3DScene::set_drag_by($self, 'instance');
$self->{objects} = $objects; Slic3r::GUI::_3DScene::set_model($self, $model);
$self->{model} = $model; Slic3r::GUI::_3DScene::set_print($self, $print);
$self->{print} = $print; Slic3r::GUI::_3DScene::set_config($self, $config);
$self->{config} = $config; # $self->enable_picking(1);
$self->{on_select_object} = sub {}; # $self->enable_moving(1);
$self->{on_instances_moved} = sub {}; # $self->select_by('object');
$self->{on_wipe_tower_moved} = sub {}; # $self->drag_by('instance');
#
$self->{objects_volumes_idxs} = []; # $self->{objects} = $objects;
# $self->{model} = $model;
$self->on_select(sub { # $self->{print} = $print;
my ($volume_idx) = @_; # $self->{config} = $config;
$self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx) # $self->{on_select_object} = sub {};
if ($self->{on_select_object}); # $self->{on_instances_moved} = sub {};
}); # $self->{on_wipe_tower_moved} = sub {};
$self->on_move(sub { #
my @volume_idxs = @_; # $self->{objects_volumes_idxs} = [];
#
my %done = (); # prevent moving instances twice # $self->on_select(sub {
my $object_moved; # my ($volume_idx) = @_;
my $wipe_tower_moved; # $self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx)
foreach my $volume_idx (@volume_idxs) { # if ($self->{on_select_object});
my $volume = $self->volumes->[$volume_idx]; # });
my $obj_idx = $volume->object_idx; #
my $instance_idx = $volume->instance_idx; # $self->on_move(sub {
next if $done{"${obj_idx}_${instance_idx}"}; # my @volume_idxs = @_;
$done{"${obj_idx}_${instance_idx}"} = 1; # my %done = (); # prevent moving instances twice
if ($obj_idx < 1000) { # my $object_moved;
# Move a regular object. # my $wipe_tower_moved;
my $model_object = $self->{model}->get_object($obj_idx); # foreach my $volume_idx (@volume_idxs) {
$model_object # my $volume = $self->volumes->[$volume_idx];
->instances->[$instance_idx] # my $obj_idx = $volume->object_idx;
->offset # my $instance_idx = $volume->instance_idx;
->translate($volume->origin->x, $volume->origin->y); #)) # next if $done{"${obj_idx}_${instance_idx}"};
$model_object->invalidate_bounding_box; # $done{"${obj_idx}_${instance_idx}"} = 1;
$object_moved = 1; # if ($obj_idx < 1000) {
} elsif ($obj_idx == 1000) { # # Move a regular object.
# Move a wipe tower proxy. # my $model_object = $self->{model}->get_object($obj_idx);
$wipe_tower_moved = $volume->origin; # $model_object
} # ->instances->[$instance_idx]
} # ->offset
# ->translate($volume->origin->x, $volume->origin->y); #))
$self->{on_instances_moved}->() # $model_object->invalidate_bounding_box;
if $object_moved && $self->{on_instances_moved}; # $object_moved = 1;
$self->{on_wipe_tower_moved}->($wipe_tower_moved) # } elsif ($obj_idx == 1000) {
if $wipe_tower_moved && $self->{on_wipe_tower_moved}; # # Move a wipe tower proxy.
}); # $wipe_tower_moved = $volume->origin;
# }
EVT_KEY_DOWN($self, sub { # }
my ($s, $event) = @_; #
if ($event->HasModifiers) { # $self->{on_instances_moved}->()
$event->Skip; # if $object_moved && $self->{on_instances_moved};
} else { # $self->{on_wipe_tower_moved}->($wipe_tower_moved)
my $key = $event->GetKeyCode; # if $wipe_tower_moved && $self->{on_wipe_tower_moved};
if ($key == WXK_DELETE) { # });
$self->on_remove_object->() if $self->on_remove_object; #
} else { # EVT_KEY_DOWN($self, sub {
$event->Skip; # my ($s, $event) = @_;
} # if ($event->HasModifiers) {
} # $event->Skip;
}); # } else {
# my $key = $event->GetKeyCode;
EVT_CHAR($self, sub { # if ($key == WXK_DELETE) {
my ($s, $event) = @_; # $self->on_remove_object->() if $self->on_remove_object;
if ($event->HasModifiers) { # } else {
$event->Skip; # $event->Skip;
} else { # }
my $key = $event->GetKeyCode; # }
if ($key == ord('a')) { # });
$self->on_arrange->() if $self->on_arrange; #
} elsif ($key == ord('l')) { # EVT_CHAR($self, sub {
$self->on_rotate_object_left->() if $self->on_rotate_object_left; # my ($s, $event) = @_;
} elsif ($key == ord('r')) { # if ($event->HasModifiers) {
$self->on_rotate_object_right->() if $self->on_rotate_object_right; # $event->Skip;
} elsif ($key == ord('s')) { # } else {
$self->on_scale_object_uniformly->() if $self->on_scale_object_uniformly; # my $key = $event->GetKeyCode;
} elsif ($key == ord('+')) { # if ($key == ord('a')) {
$self->on_increase_objects->() if $self->on_increase_objects; # $self->on_arrange->() if $self->on_arrange;
} elsif ($key == ord('-')) { # } elsif ($key == ord('l')) {
$self->on_decrease_objects->() if $self->on_decrease_objects; # $self->on_rotate_object_left->() if $self->on_rotate_object_left;
} else { # } elsif ($key == ord('r')) {
$event->Skip; # $self->on_rotate_object_right->() if $self->on_rotate_object_right;
} # } elsif ($key == ord('s')) {
} # $self->on_scale_object_uniformly->() if $self->on_scale_object_uniformly;
}); # } elsif ($key == ord('+')) {
# $self->on_increase_objects->() if $self->on_increase_objects;
# } elsif ($key == ord('-')) {
# $self->on_decrease_objects->() if $self->on_decrease_objects;
# } else {
# $event->Skip;
# }
# }
# });
#==============================================================================================================================
return $self; return $self;
} }
sub set_on_select_object { #==============================================================================================================================
my ($self, $cb) = @_; #sub set_on_select_object {
$self->{on_select_object} = $cb; # my ($self, $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 { #
my ($self, $cb) = @_; #sub set_on_arrange {
$self->on_arrange($cb); # my ($self, $cb) = @_;
} # $self->on_arrange($cb);
#}
sub set_on_rotate_object_left { #
my ($self, $cb) = @_; #sub set_on_rotate_object_left {
$self->on_rotate_object_left($cb); # my ($self, $cb) = @_;
} # $self->on_rotate_object_left($cb);
#}
sub set_on_rotate_object_right { #
my ($self, $cb) = @_; #sub set_on_rotate_object_right {
$self->on_rotate_object_right($cb); # my ($self, $cb) = @_;
} # $self->on_rotate_object_right($cb);
#}
sub set_on_scale_object_uniformly { #
my ($self, $cb) = @_; #sub set_on_scale_object_uniformly {
$self->on_scale_object_uniformly($cb); # my ($self, $cb) = @_;
} # $self->on_scale_object_uniformly($cb);
#}
sub set_on_increase_objects { #
my ($self, $cb) = @_; #sub set_on_increase_objects {
$self->on_increase_objects($cb); # my ($self, $cb) = @_;
} # $self->on_increase_objects($cb);
#}
sub set_on_decrease_objects { #
my ($self, $cb) = @_; #sub set_on_decrease_objects {
$self->on_decrease_objects($cb); # my ($self, $cb) = @_;
} # $self->on_decrease_objects($cb);
#}
sub set_on_remove_object { #
my ($self, $cb) = @_; #sub set_on_remove_object {
$self->on_remove_object($cb); # my ($self, $cb) = @_;
} # $self->on_remove_object($cb);
#}
sub set_on_instances_moved { #
my ($self, $cb) = @_; #sub set_on_instances_moved {
$self->{on_instances_moved} = $cb; # my ($self, $cb) = @_;
} # $self->{on_instances_moved} = $cb;
#}
sub set_on_wipe_tower_moved { #
my ($self, $cb) = @_; #sub set_on_wipe_tower_moved {
$self->{on_wipe_tower_moved} = $cb; # my ($self, $cb) = @_;
} # $self->{on_wipe_tower_moved} = $cb;
#}
sub set_on_model_update { #
my ($self, $cb) = @_; #sub set_on_model_update {
$self->on_model_update($cb); # my ($self, $cb) = @_;
} # $self->on_model_update($cb);
#}
sub set_on_enable_action_buttons { #
my ($self, $cb) = @_; #sub set_on_enable_action_buttons {
$self->on_enable_action_buttons($cb); # my ($self, $cb) = @_;
} # $self->on_enable_action_buttons($cb);
#}
sub update_volumes_selection { #
my ($self) = @_; #sub update_volumes_selection {
# my ($self) = @_;
foreach my $obj_idx (0..$#{$self->{model}->objects}) { #
if ($self->{objects}[$obj_idx]->selected) { # foreach my $obj_idx (0..$#{$self->{model}->objects}) {
my $volume_idxs = $self->{objects_volumes_idxs}->[$obj_idx]; # if ($self->{objects}[$obj_idx]->selected) {
$self->select_volume($_) for @{$volume_idxs}; # my $volume_idxs = $self->{objects_volumes_idxs}->[$obj_idx];
} # $self->select_volume($_) for @{$volume_idxs};
} # }
} # }
#}
sub reload_scene { #
my ($self, $force) = @_; #sub reload_scene {
# my ($self, $force) = @_;
$self->reset_objects; #
$self->update_bed_size; # $self->reset_objects;
# $self->update_bed_size;
if (! $self->IsShown && ! $force) { #
$self->{reload_delayed} = 1; # if (! $self->IsShown && ! $force) {
return; # $self->{reload_delayed} = 1;
} # return;
# }
$self->{reload_delayed} = 0; #
# $self->{reload_delayed} = 0;
$self->{objects_volumes_idxs} = []; #
foreach my $obj_idx (0..$#{$self->{model}->objects}) { # $self->{objects_volumes_idxs} = [];
my @volume_idxs = $self->load_object($self->{model}, $self->{print}, $obj_idx); # foreach my $obj_idx (0..$#{$self->{model}->objects}) {
push(@{$self->{objects_volumes_idxs}}, \@volume_idxs); # my @volume_idxs = $self->load_object($self->{model}, $self->{print}, $obj_idx);
} # push(@{$self->{objects_volumes_idxs}}, \@volume_idxs);
# }
$self->update_volumes_selection; #
# $self->update_volumes_selection;
if (defined $self->{config}->nozzle_diameter) { #
# Should the wipe tower be visualized? # if (defined $self->{config}->nozzle_diameter) {
my $extruders_count = scalar @{ $self->{config}->nozzle_diameter }; # # Should the wipe tower be visualized?
# Height of a print. # my $extruders_count = scalar @{ $self->{config}->nozzle_diameter };
my $height = $self->{model}->bounding_box->z_max; # # Height of a print.
# Show at least a slab. # my $height = $self->{model}->bounding_box->z_max;
$height = 10 if $height < 10; # # Show at least a slab.
if ($extruders_count > 1 && $self->{config}->single_extruder_multi_material && $self->{config}->wipe_tower && # $height = 10 if $height < 10;
! $self->{config}->complete_objects) { # if ($extruders_count > 1 && $self->{config}->single_extruder_multi_material && $self->{config}->wipe_tower &&
$self->volumes->load_wipe_tower_preview(1000, # ! $self->{config}->complete_objects) {
$self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, $self->{config}->wipe_tower_width, # $self->volumes->load_wipe_tower_preview(1000,
#$self->{config}->wipe_tower_per_color_wipe# 15 * ($extruders_count - 1), # this is just a hack when the config parameter became obsolete # $self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, $self->{config}->wipe_tower_width,
15 * ($extruders_count - 1), # #$self->{config}->wipe_tower_per_color_wipe# 15 * ($extruders_count - 1), # this is just a hack when the config parameter became obsolete
$self->{model}->bounding_box->z_max, $self->{config}->wipe_tower_rotation_angle, $self->UseVBOs); # 15 * ($extruders_count - 1),
} # $self->{model}->bounding_box->z_max, $self->{config}->wipe_tower_rotation_angle, $self->UseVBOs);
} # }
# }
$self->update_volumes_colors_by_extruder($self->{config}); #
# $self->update_volumes_colors_by_extruder($self->{config});
# checks for geometry outside the print volume to render it accordingly #
if (scalar @{$self->volumes} > 0) # # checks for geometry outside the print volume to render it accordingly
{ # if (scalar @{$self->volumes} > 0)
my $contained = $self->volumes->check_outside_state($self->{config}); # {
if (!$contained) { # my $contained = $self->volumes->check_outside_state($self->{config});
$self->set_warning_enabled(1); # if (!$contained) {
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume")); # $self->set_warning_enabled(1);
$self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons); # Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
} else { # $self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons);
$self->set_warning_enabled(0); # } else {
$self->volumes->reset_outside_state(); # $self->set_warning_enabled(0);
Slic3r::GUI::_3DScene::reset_warning_texture(); # $self->volumes->reset_outside_state();
$self->on_enable_action_buttons->(scalar @{$self->{model}->objects} > 0) if ($self->on_enable_action_buttons); # Slic3r::GUI::_3DScene::reset_warning_texture();
} # $self->on_enable_action_buttons->(scalar @{$self->{model}->objects} > 0) if ($self->on_enable_action_buttons);
} else { # }
$self->set_warning_enabled(0); # } else {
Slic3r::GUI::_3DScene::reset_warning_texture(); # $self->set_warning_enabled(0);
} # Slic3r::GUI::_3DScene::reset_warning_texture();
} # }
#}
sub update_bed_size { #
my ($self) = @_; #sub update_bed_size {
$self->set_bed_shape($self->{config}->bed_shape); # my ($self) = @_;
} # $self->set_bed_shape($self->{config}->bed_shape);
#}
# Called by the Platter wxNotebook when this page is activated. #
sub OnActivate { ## Called by the Platter wxNotebook when this page is activated.
my ($self) = @_; #sub OnActivate {
$self->reload_scene(1) if ($self->{reload_delayed}); # my ($self) = @_;
} # $self->reload_scene(1) if ($self->{reload_delayed});
#}
#==============================================================================================================================
1; 1;

View File

@ -24,7 +24,7 @@ sub new {
# init GUI elements # init GUI elements
my $canvas = Slic3r::GUI::3DScene->new($self); my $canvas = Slic3r::GUI::3DScene->new($self);
$canvas->use_plain_shader(1); Slic3r::GUI::_3DScene::enable_shader($canvas, 1);
$self->canvas($canvas); $self->canvas($canvas);
my $slider_low = Wx::Slider->new( my $slider_low = Wx::Slider->new(
$self, -1, $self, -1,
@ -278,7 +278,7 @@ sub new {
sub reload_print { sub reload_print {
my ($self, $force) = @_; my ($self, $force) = @_;
$self->canvas->reset_objects; Slic3r::GUI::_3DScene::reset_volumes($self->canvas);
$self->_loaded(0); $self->_loaded(0);
if (! $self->IsShown && ! $force) { if (! $self->IsShown && ! $force) {
@ -304,7 +304,7 @@ sub refresh_print {
sub reset_gcode_preview_data { sub reset_gcode_preview_data {
my ($self) = @_; my ($self) = @_;
$self->gcode_preview_data->reset; $self->gcode_preview_data->reset;
$self->canvas->reset_legend_texture(); Slic3r::GUI::_3DScene::reset_legend_texture();
} }
sub load_print { sub load_print {
@ -329,7 +329,7 @@ sub load_print {
if ($n_layers == 0) { if ($n_layers == 0) {
$self->reset_sliders; $self->reset_sliders;
$self->canvas->reset_legend_texture(); Slic3r::GUI::_3DScene::reset_legend_texture();
$self->canvas->Refresh; # clears canvas $self->canvas->Refresh; # clears canvas
return; return;
} }
@ -364,23 +364,25 @@ sub load_print {
if ($self->gcode_preview_data->empty) { if ($self->gcode_preview_data->empty) {
# load skirt and brim # load skirt and brim
$self->canvas->load_print_toolpaths($self->print, \@colors); Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
$self->canvas->load_wipe_tower_toolpaths($self->print, \@colors); Slic3r::GUI::_3DScene::load_print_toolpaths($self->canvas);
Slic3r::GUI::_3DScene::load_wipe_tower_toolpaths($self->canvas, \@colors);
foreach my $object (@{$self->print->objects}) { foreach my $object (@{$self->print->objects}) {
$self->canvas->load_print_object_toolpaths($object, \@colors); Slic3r::GUI::_3DScene::load_print_object_toolpaths($self->canvas, $object, \@colors);
# Show the objects in very transparent color. # Show the objects in very transparent color.
#my @volume_ids = $self->canvas->load_object($object->model_object); #my @volume_ids = $self->canvas->load_object($object->model_object);
#$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids; #$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
} }
$self->show_hide_ui_elements('simple'); $self->show_hide_ui_elements('simple');
$self->canvas->reset_legend_texture(); Slic3r::GUI::_3DScene::reset_legend_texture();
} else { } else {
$self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0); $self->{force_sliders_full_range} = (Slic3r::GUI::_3DScene::get_volumes_count($self->canvas) == 0);
$self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors); Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
Slic3r::GUI::_3DScene::load_gcode_preview($self->canvas, $self->gcode_preview_data, \@colors);
$self->show_hide_ui_elements('full'); $self->show_hide_ui_elements('full');
# recalculates zs and update sliders accordingly # recalculates zs and update sliders accordingly
$self->{layers_z} = $self->canvas->get_current_print_zs(1); $self->{layers_z} = Slic3r::GUI::_3DScene::get_current_print_zs($self->canvas, 1);
$n_layers = scalar(@{$self->{layers_z}}); $n_layers = scalar(@{$self->{layers_z}});
if ($n_layers == 0) { if ($n_layers == 0) {
# all layers filtered out # all layers filtered out
@ -466,7 +468,7 @@ sub set_z_range
$self->{z_label_low}->SetLabel(sprintf '%.2f', $z_low); $self->{z_label_low}->SetLabel(sprintf '%.2f', $z_low);
$self->{z_label_high}->SetLabel(sprintf '%.2f', $z_high); $self->{z_label_high}->SetLabel(sprintf '%.2f', $z_high);
my $layers_z = $self->canvas->get_current_print_zs(0); my $layers_z = Slic3r::GUI::_3DScene::get_current_print_zs($self->canvas, 0);
for (my $i = 0; $i < scalar(@{$layers_z}); $i += 1) { for (my $i = 0; $i < scalar(@{$layers_z}); $i += 1) {
if (($z_low - 1e-6 < @{$layers_z}[$i]) && (@{$layers_z}[$i] < $z_low + 1e-6)) { if (($z_low - 1e-6 < @{$layers_z}[$i]) && (@{$layers_z}[$i] < $z_low + 1e-6)) {
$self->{z_label_low_idx}->SetLabel(sprintf '%d', $i + 1); $self->{z_label_low_idx}->SetLabel(sprintf '%d', $i + 1);
@ -480,7 +482,7 @@ sub set_z_range
} }
} }
$self->canvas->set_toolpaths_range($z_low - 1e-6, $z_high + 1e-6); Slic3r::GUI::_3DScene::set_toolpaths_range($self->canvas, $z_low - 1e-6, $z_high + 1e-6);
$self->canvas->Refresh if $self->IsShown; $self->canvas->Refresh if $self->IsShown;
} }
@ -510,11 +512,6 @@ sub set_z_idx_high
} }
} }
sub set_bed_shape {
my ($self, $bed_shape) = @_;
$self->canvas->set_bed_shape($bed_shape);
}
sub set_number_extruders { sub set_number_extruders {
my ($self, $number_extruders) = @_; my ($self, $number_extruders) = @_;
if ($self->{number_extruders} != $number_extruders) { if ($self->{number_extruders} != $number_extruders) {

View File

@ -9,6 +9,7 @@ use utf8;
use Slic3r::Geometry qw(PI X); use Slic3r::Geometry qw(PI X);
use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL); use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_CLOSE EVT_BUTTON); use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
use List::Util qw(max);
use base 'Wx::Dialog'; use base 'Wx::Dialog';
sub new { sub new {
@ -112,10 +113,13 @@ sub new {
my $canvas; my $canvas;
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self); $canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
$canvas->load_object($self->{model_object}, undef, undef, [0]); Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
$canvas->set_auto_bed_shape; Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
$canvas->SetSize([500,500]); $canvas->SetSize([500,500]);
$canvas->SetMinSize($canvas->GetSize); $canvas->SetMinSize($canvas->GetSize);
Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config});
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
} }
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
@ -144,6 +148,7 @@ sub new {
# Note that the window was already closed, so a pending update will not be executed. # Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1; $self->{already_closed} = 1;
$self->EndModal(wxID_OK); $self->EndModal(wxID_OK);
$self->{canvas}->Destroy;
$self->Destroy(); $self->Destroy();
}); });
@ -151,6 +156,7 @@ sub new {
# Note that the window was already closed, so a pending update will not be executed. # Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1; $self->{already_closed} = 1;
$self->EndModal(wxID_CANCEL); $self->EndModal(wxID_CANCEL);
$self->{canvas}->Destroy;
$self->Destroy(); $self->Destroy();
}); });
@ -242,14 +248,11 @@ sub _update {
$expolygon->translate(map Slic3r::Geometry::scale($_), @{ $self->{model_object}->instances->[0]->offset }); $expolygon->translate(map Slic3r::Geometry::scale($_), @{ $self->{model_object}->instances->[0]->offset });
} }
$self->{canvas}->reset_objects; Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
$self->{canvas}->load_object($_, undef, undef, [0]) for @objects; Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
$self->{canvas}->SetCuttingPlane( Slic3r::GUI::_3DScene::set_cutting_plane($self->{canvas}, $self->{cut_options}{z}, [@expolygons]);
$self->{cut_options}{z}, Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
[@expolygons], Slic3r::GUI::_3DScene::render($self->{canvas});
);
$self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->{config});
$self->{canvas}->Render;
} }
} }

View File

@ -10,6 +10,7 @@ use File::Basename qw(basename);
use Wx qw(:misc :sizer :treectrl :button :keycode wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxID_CANCEL wxMOD_CONTROL use Wx qw(:misc :sizer :treectrl :button :keycode wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxID_CANCEL wxMOD_CONTROL
wxTheApp); wxTheApp);
use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN EVT_KEY_DOWN); use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN EVT_KEY_DOWN);
use List::Util qw(max);
use base 'Wx::Panel'; use base 'Wx::Panel';
use constant ICON_OBJECT => 0; use constant ICON_OBJECT => 0;
@ -150,19 +151,19 @@ sub new {
my $canvas; my $canvas;
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self); $canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
$canvas->enable_picking(1); Slic3r::GUI::_3DScene::enable_picking($canvas, 1);
$canvas->select_by('volume'); Slic3r::GUI::_3DScene::set_select_by($canvas, 'volume');
Slic3r::GUI::_3DScene::register_on_select_object_callback($canvas, sub {
$canvas->on_select(sub {
my ($volume_idx) = @_; my ($volume_idx) = @_;
# convert scene volume to model object volume $self->reload_tree($volume_idx);
$self->reload_tree(($volume_idx == -1) ? undef : $canvas->volumes->[$volume_idx]->volume_idx);
}); });
Slic3r::GUI::_3DScene::load_model_object($canvas, $self->{model_object}, 0, [0]);
$canvas->load_object($self->{model_object}, undef, undef, [0]); Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
$canvas->set_auto_bed_shape; Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
$canvas->SetSize([500,700]); $canvas->SetSize([500,700]);
$canvas->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config});
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($canvas);
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
} }
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
@ -262,7 +263,7 @@ sub selection_changed {
# deselect all meshes # deselect all meshes
if ($self->{canvas}) { if ($self->{canvas}) {
$_->set_selected(0) for @{$self->{canvas}->volumes}; Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas});
} }
# disable things as if nothing is selected # disable things as if nothing is selected
@ -290,7 +291,7 @@ sub selection_changed {
if ($itemData->{type} eq 'volume') { if ($itemData->{type} eq 'volume') {
# select volume in 3D preview # select volume in 3D preview
if ($self->{canvas}) { if ($self->{canvas}) {
$self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1); Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
} }
$self->{btn_delete}->Enable; $self->{btn_delete}->Enable;
$self->{btn_split}->Enable; $self->{btn_split}->Enable;
@ -333,7 +334,7 @@ sub selection_changed {
$self->{settings_panel}->enable; $self->{settings_panel}->enable;
} }
$self->{canvas}->Render if $self->{canvas}; Slic3r::GUI::_3DScene::render($self->{canvas}) if $self->{canvas};
} }
sub on_btn_load { sub on_btn_load {
@ -429,7 +430,7 @@ sub on_btn_move_up {
if ($itemData && $itemData->{type} eq 'volume') { if ($itemData && $itemData->{type} eq 'volume') {
my $volume_id = $itemData->{volume_id}; my $volume_id = $itemData->{volume_id};
if ($self->{model_object}->move_volume_up($volume_id)) { if ($self->{model_object}->move_volume_up($volume_id)) {
$self->{canvas}->volumes->move_volume_up($volume_id); Slic3r::GUI::_3DScene::move_volume_up($self->{canvas}, $volume_id);
$self->{parts_changed} = 1; $self->{parts_changed} = 1;
$self->reload_tree($volume_id - 1); $self->reload_tree($volume_id - 1);
} }
@ -442,7 +443,7 @@ sub on_btn_move_down {
if ($itemData && $itemData->{type} eq 'volume') { if ($itemData && $itemData->{type} eq 'volume') {
my $volume_id = $itemData->{volume_id}; my $volume_id = $itemData->{volume_id};
if ($self->{model_object}->move_volume_down($volume_id)) { if ($self->{model_object}->move_volume_down($volume_id)) {
$self->{canvas}->volumes->move_volume_down($volume_id); Slic3r::GUI::_3DScene::move_volume_down($self->{canvas}, $volume_id);
$self->{parts_changed} = 1; $self->{parts_changed} = 1;
$self->reload_tree($volume_id + 1); $self->reload_tree($volume_id + 1);
} }
@ -487,11 +488,11 @@ sub _parts_changed {
$self->reload_tree; $self->reload_tree;
if ($self->{canvas}) { if ($self->{canvas}) {
$self->{canvas}->reset_objects; Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
$self->{canvas}->load_object($self->{model_object}); Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
$self->{canvas}->zoom_to_volumes; Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas});
$self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
$self->{canvas}->Render; Slic3r::GUI::_3DScene::render($self->{canvas});
} }
} }
@ -511,6 +512,11 @@ sub CanClose {
return ! Slic3r::GUI::catch_error($self); return ! Slic3r::GUI::catch_error($self);
} }
sub Destroy {
my ($self) = @_;
$self->{canvas}->Destroy if ($self->{canvas});
}
sub PartsChanged { sub PartsChanged {
my ($self) = @_; my ($self) = @_;
return $self->{parts_changed}; return $self->{parts_changed};
@ -525,18 +531,18 @@ sub _update_canvas {
my ($self) = @_; my ($self) = @_;
if ($self->{canvas}) { if ($self->{canvas}) {
$self->{canvas}->reset_objects; Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
$self->{canvas}->load_object($self->{model_object}); Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
# restore selection, if any # restore selection, if any
if (my $itemData = $self->get_selection) { if (my $itemData = $self->get_selection) {
if ($itemData->{type} eq 'volume') { if ($itemData->{type} eq 'volume') {
$self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1); Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
} }
} }
$self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
$self->{canvas}->Render; Slic3r::GUI::_3DScene::render($self->{canvas});
} }
} }
@ -558,10 +564,10 @@ sub _update {
$self->{parts_changed} = 1; $self->{parts_changed} = 1;
my @objects = (); my @objects = ();
push @objects, $self->{model_object}; push @objects, $self->{model_object};
$self->{canvas}->reset_objects; Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
$self->{canvas}->load_object($_, undef, [0]) for @objects; Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
$self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
$self->{canvas}->Render; Slic3r::GUI::_3DScene::render($self->{canvas});
} }
1; 1;

View File

@ -36,6 +36,7 @@ sub new {
wxTheApp->save_window_pos($self, "object_settings"); wxTheApp->save_window_pos($self, "object_settings");
$self->EndModal(wxID_OK); $self->EndModal(wxID_OK);
$self->{parts}->Destroy;
$self->Destroy; $self->Destroy;
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,18 @@
#version 110
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
// x = tainted, y = specular;
varying vec2 intensity;
varying vec3 delta_box_min;
varying vec3 delta_box_max;
uniform vec4 uniform_color;
void main()
{
// if the fragment is outside the print volume -> use darker color
vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb;
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a);
}

View File

@ -0,0 +1,70 @@
#version 110
#define INTENSITY_CORRECTION 0.6
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SHININESS 20.0
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SHININESS 5.0
#define INTENSITY_AMBIENT 0.3
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
struct PrintBoxDetection
{
vec3 min;
vec3 max;
// xyz contains the offset, if w == 1.0 detection needs to be performed
vec4 volume_origin;
};
uniform PrintBoxDetection print_box;
// x = tainted, y = specular;
varying vec2 intensity;
varying vec3 delta_box_min;
varying vec3 delta_box_max;
void main()
{
// First transform the normal into camera space and normalize the result.
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
intensity.y = 0.0;
if (NdotL > 0.0)
intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
// compute deltas for out of print volume detection (world coordinates)
if (print_box.volume_origin.w == 1.0)
{
vec3 v = gl_Vertex.xyz + print_box.volume_origin.xyz;
delta_box_min = v - print_box.min;
delta_box_max = v - print_box.max;
}
else
{
delta_box_min = ZERO;
delta_box_max = ZERO;
}
gl_Position = ftransform();
}

View File

@ -0,0 +1,40 @@
#version 110
#define M_PI 3.1415926535897932384626433832795
// 2D texture (1D texture split by the rows) of color along the object Z axis.
uniform sampler2D z_texture;
// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
uniform float z_to_texture_row;
uniform float z_texture_row_to_normalized;
uniform float z_cursor;
uniform float z_cursor_band_width;
// x = tainted, y = specular;
varying vec2 intensity;
varying float object_z;
void main()
{
float object_z_row = z_to_texture_row * object_z;
// Index of the row in the texture.
float z_texture_row = floor(object_z_row);
// Normalized coordinate from 0. to 1.
float z_texture_col = object_z_row - z_texture_row;
float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25;
// Calculate level of detail from the object Z coordinate.
// This makes the slowly sloping surfaces to be show with high detail (with stripes),
// and the vertical surfaces to be shown with low detail (no stripes)
float z_in_cells = object_z_row * 190.;
// Gradient of Z projected on the screen.
float dx_vtc = dFdx(z_in_cells);
float dy_vtc = dFdy(z_in_cells);
float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.);
// Sample the Z texture. Texture coordinates are normalized to <0, 1>.
vec4 color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.),
texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod);
// Mix the final color.
gl_FragColor = vec4(intensity.y, intensity.y, intensity.y, 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
}

View File

@ -0,0 +1,46 @@
#version 110
#define INTENSITY_CORRECTION 0.6
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
#define LIGHT_TOP_SHININESS 20.0
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SHININESS 5.0
#define INTENSITY_AMBIENT 0.3
// x = tainted, y = specular;
varying vec2 intensity;
varying float object_z;
void main()
{
// First transform the normal into camera space and normalize the result.
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
intensity.y = 0.0;
if (NdotL > 0.0)
intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular)
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
// Scaled to widths of the Z texture.
object_z = gl_Vertex.z;
gl_Position = ftransform();
}

View File

@ -189,6 +189,14 @@ add_library(libslic3r_gui STATIC
${LIBDIR}/slic3r/GUI/3DScene.hpp ${LIBDIR}/slic3r/GUI/3DScene.hpp
${LIBDIR}/slic3r/GUI/GLShader.cpp ${LIBDIR}/slic3r/GUI/GLShader.cpp
${LIBDIR}/slic3r/GUI/GLShader.hpp ${LIBDIR}/slic3r/GUI/GLShader.hpp
${LIBDIR}/slic3r/GUI/GLCanvas3D.hpp
${LIBDIR}/slic3r/GUI/GLCanvas3D.cpp
${LIBDIR}/slic3r/GUI/GLCanvas3DManager.hpp
${LIBDIR}/slic3r/GUI/GLCanvas3DManager.cpp
${LIBDIR}/slic3r/GUI/GLGizmo.hpp
${LIBDIR}/slic3r/GUI/GLGizmo.cpp
${LIBDIR}/slic3r/GUI/GLTexture.hpp
${LIBDIR}/slic3r/GUI/GLTexture.cpp
${LIBDIR}/slic3r/GUI/Preferences.cpp ${LIBDIR}/slic3r/GUI/Preferences.cpp
${LIBDIR}/slic3r/GUI/Preferences.hpp ${LIBDIR}/slic3r/GUI/Preferences.hpp
${LIBDIR}/slic3r/GUI/Preset.cpp ${LIBDIR}/slic3r/GUI/Preset.cpp
@ -566,13 +574,13 @@ if (SLIC3R_PRUSACONTROL)
set(wxWidgets_UseAlienWx 1) set(wxWidgets_UseAlienWx 1)
if (wxWidgets_UseAlienWx) if (wxWidgets_UseAlienWx)
set(AlienWx_DEBUG 1) set(AlienWx_DEBUG 1)
find_package(AlienWx REQUIRED COMPONENTS base core adv html) find_package(AlienWx REQUIRED COMPONENTS base core adv html gl)
include_directories(${AlienWx_INCLUDE_DIRS}) include_directories(${AlienWx_INCLUDE_DIRS})
#add_compile_options(${AlienWx_CXX_FLAGS}) #add_compile_options(${AlienWx_CXX_FLAGS})
add_definitions(${AlienWx_DEFINITIONS}) add_definitions(${AlienWx_DEFINITIONS})
set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES})
else () else ()
find_package(wxWidgets REQUIRED COMPONENTS base core adv html) find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl)
include(${wxWidgets_USE_FILE}) include(${wxWidgets_USE_FILE})
endif () endif ()
add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS)

View File

@ -12,6 +12,8 @@ our $VERSION = '0.01';
BEGIN { BEGIN {
if ($^O eq 'MSWin32') { if ($^O eq 'MSWin32') {
eval "use Wx"; eval "use Wx";
eval "use Wx::GLCanvas";
eval "use Wx::GLContext";
eval "use Wx::Html"; eval "use Wx::Html";
eval "use Wx::Print"; # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code) eval "use Wx::Print"; # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code)
} }
@ -280,6 +282,7 @@ for my $class (qw(
Slic3r::Geometry::BoundingBox Slic3r::Geometry::BoundingBox
Slic3r::Geometry::BoundingBoxf Slic3r::Geometry::BoundingBoxf
Slic3r::Geometry::BoundingBoxf3 Slic3r::Geometry::BoundingBoxf3
Slic3r::GUI::_3DScene::GLShader
Slic3r::GUI::_3DScene::GLVolume Slic3r::GUI::_3DScene::GLVolume
Slic3r::GUI::Preset Slic3r::GUI::Preset
Slic3r::GUI::PresetCollection Slic3r::GUI::PresetCollection

View File

@ -222,6 +222,14 @@ BoundingBox3Base<PointClass>::center() const
} }
template Pointf3 BoundingBox3Base<Pointf3>::center() const; template Pointf3 BoundingBox3Base<Pointf3>::center() const;
template <class PointClass> coordf_t
BoundingBox3Base<PointClass>::max_size() const
{
PointClass s = size();
return std::max(s.x, std::max(s.y, s.z));
}
template coordf_t BoundingBox3Base<Pointf3>::max_size() const;
// Align a coordinate to a grid. The coordinate may be negative, // Align a coordinate to a grid. The coordinate may be negative,
// the aligned value will never be bigger than the original one. // the aligned value will never be bigger than the original one.
static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) { static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {

View File

@ -94,6 +94,7 @@ public:
void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); } void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); }
void offset(coordf_t delta); void offset(coordf_t delta);
PointClass center() const; PointClass center() const;
coordf_t max_size() const;
bool contains(const PointClass &point) const { bool contains(const PointClass &point) const {
return BoundingBoxBase<PointClass>::contains(point) && point.z >= this->min.z && point.z <= this->max.z; return BoundingBoxBase<PointClass>::contains(point) && point.z >= this->min.z && point.z <= this->max.z;

View File

@ -603,7 +603,10 @@ void ModelObject::clear_instances()
// Returns the bounding box of the transformed instances. // Returns the bounding box of the transformed instances.
// This bounding box is approximate and not snug. // This bounding box is approximate and not snug.
const BoundingBoxf3& ModelObject::bounding_box() //========================================================================================================
const BoundingBoxf3& ModelObject::bounding_box() const
//const BoundingBoxf3& ModelObject::bounding_box()
//========================================================================================================
{ {
if (! m_bounding_box_valid) { if (! m_bounding_box_valid) {
BoundingBoxf3 raw_bbox; BoundingBoxf3 raw_bbox;

View File

@ -103,7 +103,10 @@ public:
// Returns the bounding box of the transformed instances. // Returns the bounding box of the transformed instances.
// This bounding box is approximate and not snug. // This bounding box is approximate and not snug.
// This bounding box is being cached. // This bounding box is being cached.
const BoundingBoxf3& bounding_box(); //========================================================================================================
const BoundingBoxf3& bounding_box() const;
// const BoundingBoxf3& bounding_box();
//========================================================================================================
void invalidate_bounding_box() { m_bounding_box_valid = false; } void invalidate_bounding_box() { m_bounding_box_valid = false; }
// Returns a snug bounding box of the transformed instances. // Returns a snug bounding box of the transformed instances.
// This bounding box is not being cached. // This bounding box is not being cached.
@ -145,8 +148,10 @@ private:
// Parent object, owning this ModelObject. // Parent object, owning this ModelObject.
Model *m_model; Model *m_model;
// Bounding box, cached. // Bounding box, cached.
BoundingBoxf3 m_bounding_box; //========================================================================================================
bool m_bounding_box_valid; mutable BoundingBoxf3 m_bounding_box;
mutable bool m_bounding_box_valid;
//========================================================================================================
}; };
// An object STL, or a modifier volume, over which a different set of parameters shall be applied. // An object STL, or a modifier volume, over which a different set of parameters shall be applied.

View File

@ -238,6 +238,11 @@ inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x * v2.x + v
inline coordf_t dot(const Pointf &v) { return v.x * v.x + v.y * v.y; } inline coordf_t dot(const Pointf &v) { return v.x * v.x + v.y * v.y; }
inline double length(const Vectorf &v) { return sqrt(dot(v)); } inline double length(const Vectorf &v) { return sqrt(dot(v)); }
inline double l2(const Vectorf &v) { return dot(v); } inline double l2(const Vectorf &v) { return dot(v); }
inline Vectorf normalize(const Vectorf& v)
{
coordf_t len = ::sqrt(sqr(v.x) + sqr(v.y));
return (len != 0.0) ? 1.0 / len * v : Vectorf(0.0, 0.0);
}
class Pointf3 : public Pointf class Pointf3 : public Pointf
{ {

View File

@ -184,6 +184,8 @@ public:
void reset_layer_height_profile(); void reset_layer_height_profile();
void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action);
// Collect the slicing parameters, to be used by variable layer thickness algorithm, // Collect the slicing parameters, to be used by variable layer thickness algorithm,
// by the interactive layer height editor and by the printing process itself. // by the interactive layer height editor and by the printing process itself.
// The slicing parameters are dependent on various configuration values // The slicing parameters are dependent on various configuration values

View File

@ -4,6 +4,7 @@
#include "Geometry.hpp" #include "Geometry.hpp"
#include "SupportMaterial.hpp" #include "SupportMaterial.hpp"
#include "Surface.hpp" #include "Surface.hpp"
#include "Slicing.hpp"
#include <utility> #include <utility>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@ -1961,4 +1962,12 @@ void PrintObject::reset_layer_height_profile()
this->model_object()->layer_height_profile_valid = false; this->model_object()->layer_height_profile_valid = false;
} }
void PrintObject::adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
{
update_layer_height_profile(_model_object->layer_height_profile);
Slic3r::adjust_layer_height_profile(slicing_parameters(), _model_object->layer_height_profile, z, layer_thickness_delta, band_width, LayerHeightEditActionType(action));
_model_object->layer_height_profile_valid = true;
layer_height_profile_valid = false;
}
} // namespace Slic3r } // namespace Slic3r

View File

@ -91,10 +91,13 @@ public:
~PerlCallback() { this->deregister_callback(); } ~PerlCallback() { this->deregister_callback(); }
void register_callback(void *sv); void register_callback(void *sv);
void deregister_callback(); void deregister_callback();
void call(); void call() const;
void call(int i); void call(int i) const;
void call(int i, int j); void call(int i, int j) const;
// void call(const std::vector<int> &ints); 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: private:
void *m_callback; void *m_callback;
}; };

View File

@ -184,7 +184,7 @@ void PerlCallback::deregister_callback()
} }
} }
void PerlCallback::call() void PerlCallback::call() const
{ {
if (! m_callback) if (! m_callback)
return; return;
@ -198,7 +198,7 @@ void PerlCallback::call()
LEAVE; LEAVE;
} }
void PerlCallback::call(int i) void PerlCallback::call(int i) const
{ {
if (! m_callback) if (! m_callback)
return; return;
@ -213,7 +213,7 @@ void PerlCallback::call(int i)
LEAVE; LEAVE;
} }
void PerlCallback::call(int i, int j) void PerlCallback::call(int i, int j) const
{ {
if (! m_callback) if (! m_callback)
return; return;
@ -229,8 +229,7 @@ void PerlCallback::call(int i, int j)
LEAVE; LEAVE;
} }
/* void PerlCallback::call(const std::vector<int>& ints) const
void PerlCallback::call(const std::vector<int> &ints)
{ {
if (! m_callback) if (! m_callback)
return; return;
@ -238,16 +237,51 @@ void PerlCallback::call(const std::vector<int> &ints)
ENTER; ENTER;
SAVETMPS; SAVETMPS;
PUSHMARK(SP); PUSHMARK(SP);
AV* av = newAV();
for (int i : ints) for (int i : ints)
av_push(av, newSViv(i)); {
XPUSHs(av); XPUSHs(sv_2mortal(newSViv(i)));
}
PUTBACK; PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD); perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS; FREETMPS;
LEAVE; 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)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(x)));
XPUSHs(sv_2mortal(newSVnv(y)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(bool b) const
{
call(b ? 1 : 0);
}
#ifdef WIN32 #ifdef WIN32
#ifndef NOMINMAX #ifndef NOMINMAX

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,10 @@
#include "../../libslic3r/Line.hpp" #include "../../libslic3r/Line.hpp"
#include "../../libslic3r/TriangleMesh.hpp" #include "../../libslic3r/TriangleMesh.hpp"
#include "../../libslic3r/Utils.hpp" #include "../../libslic3r/Utils.hpp"
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
class wxBitmap; class wxBitmap;
class wxWindow;
namespace Slic3r { namespace Slic3r {
@ -17,6 +19,11 @@ class Model;
class ModelObject; class ModelObject;
class GCodePreviewData; class GCodePreviewData;
class DynamicPrintConfig; class DynamicPrintConfig;
class ExtrusionPath;
class ExtrusionMultiPath;
class ExtrusionLoop;
class ExtrusionEntity;
class ExtrusionEntityCollection;
// A container for interleaved arrays of 3D vertices and normals, // A container for interleaved arrays of 3D vertices and normals,
// possibly indexed by triangles and / or quads. // possibly indexed by triangles and / or quads.
@ -305,9 +312,9 @@ public:
// Boolean: Is mouse over this object? // Boolean: Is mouse over this object?
bool hover; bool hover;
// Wheter or not this volume has been generated from a modifier // 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 // 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. // Interleaved triangles & normals with indexed triangles & quads.
GLIndexedVertexArray indexed_vertex_array; GLIndexedVertexArray indexed_vertex_array;
@ -437,35 +444,6 @@ private:
class _3DScene class _3DScene
{ {
struct GCodePreviewVolumeIndex
{
enum EType
{
Extrusion,
Travel,
Retraction,
Unretraction,
Shell,
Num_Geometry_Types
};
struct FirstVolume
{
EType type;
unsigned int flag;
// Index of the first volume in a GLVolumeCollection.
unsigned int id;
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
};
std::vector<FirstVolume> first_volumes;
void reset() { first_volumes.clear(); }
};
static GCodePreviewVolumeIndex s_gcode_preview_volume_index;
class TextureBase class TextureBase
{ {
protected: protected:
@ -525,12 +503,106 @@ class _3DScene
static LegendTexture s_legend_texture; static LegendTexture s_legend_texture;
static WarningTexture s_warning_texture; static WarningTexture s_warning_texture;
static GUI::GLCanvas3DManager s_canvas_mgr;
public: public:
static void _glew_init(); static void init_gl();
static std::string get_gl_info(bool format_as_html, bool extensions);
static bool use_VBOs();
static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs); static bool add_canvas(wxGLCanvas* canvas);
static bool remove_canvas(wxGLCanvas* canvas);
static void remove_all_canvases();
static bool init(wxGLCanvas* canvas);
static void set_active(wxGLCanvas* canvas, bool active);
static unsigned int get_volumes_count(wxGLCanvas* canvas);
static void reset_volumes(wxGLCanvas* canvas);
static void deselect_volumes(wxGLCanvas* canvas);
static void select_volume(wxGLCanvas* canvas, unsigned int id);
static void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
static bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config);
static bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
static bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
static void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections);
static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config);
static void set_print(wxGLCanvas* canvas, Print* print);
static void set_model(wxGLCanvas* canvas, Model* model);
static void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
static void set_auto_bed_shape(wxGLCanvas* canvas);
static BoundingBoxf3 get_volumes_bounding_box(wxGLCanvas* canvas);
static void set_axes_length(wxGLCanvas* canvas, float length);
static void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
static void set_color_by(wxGLCanvas* canvas, const std::string& value);
static void set_select_by(wxGLCanvas* canvas, const std::string& value);
static void set_drag_by(wxGLCanvas* canvas, const std::string& value);
static bool is_layers_editing_enabled(wxGLCanvas* canvas);
static bool is_layers_editing_allowed(wxGLCanvas* canvas);
static bool is_shader_enabled(wxGLCanvas* canvas);
static bool is_reload_delayed(wxGLCanvas* canvas);
static void enable_layers_editing(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_picking(wxGLCanvas* canvas, bool enable);
static void enable_moving(wxGLCanvas* canvas, bool enable);
static void enable_gizmos(wxGLCanvas* canvas, bool enable);
static void enable_shader(wxGLCanvas* canvas, bool enable);
static void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
static void allow_multisample(wxGLCanvas* canvas, bool allow);
static void zoom_to_bed(wxGLCanvas* canvas);
static void zoom_to_volumes(wxGLCanvas* canvas);
static void select_view(wxGLCanvas* canvas, const std::string& direction);
static void set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other);
static void update_volumes_colors_by_extruder(wxGLCanvas* canvas);
static void render(wxGLCanvas* canvas);
static std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only);
static void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
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_object_callback(wxGLCanvas* canvas, void* callback);
static void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
static void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
static void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
static void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
static void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
static void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
static void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
static void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
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);
static void reload_scene(wxGLCanvas* canvas, bool force);
static void load_print_toolpaths(wxGLCanvas* canvas);
static void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors);
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
// generates the legend texture in dependence of the current shown view type
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
static unsigned int get_legend_texture_width(); static unsigned int get_legend_texture_width();
static unsigned int get_legend_texture_height(); static unsigned int get_legend_texture_height();
@ -545,42 +617,16 @@ public:
static void reset_warning_texture(); static void reset_warning_texture();
static unsigned int finalize_warning_texture(); static unsigned int finalize_warning_texture();
static void _load_print_toolpaths( static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
const Print *print, static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
GLVolumeCollection *volumes, static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
const std::vector<std::string> &tool_colors, static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GLVolume& volume);
bool use_VBOs); static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GLVolume& volume);
static void _load_print_object_toolpaths( static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GLVolume& volume);
const PrintObject *print_object, static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GLVolume& volume);
GLVolumeCollection *volumes, static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume);
const std::vector<std::string> &tool_colors, static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume);
bool use_VBOs);
static void _load_wipe_tower_toolpaths(
const Print *print,
GLVolumeCollection *volumes,
const std::vector<std::string> &tool_colors_str,
bool use_VBOs);
private:
// generates gcode extrusion paths geometry
static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
// generates gcode travel paths geometry
static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors);
// generates gcode retractions geometry
static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
// generates gcode unretractions geometry
static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
// sets gcode geometry visibility according to user selection
static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
// generates the legend texture in dependence of the current shown view type
static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates objects and wipe tower geometry
static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,639 @@
#ifndef slic3r_GLCanvas3D_hpp_
#define slic3r_GLCanvas3D_hpp_
#include "../../slic3r/GUI/3DScene.hpp"
#include "../../slic3r/GUI/GLTexture.hpp"
class wxTimer;
class wxSizeEvent;
class wxIdleEvent;
class wxKeyEvent;
class wxMouseEvent;
class wxTimerEvent;
class wxPaintEvent;
namespace Slic3r {
class GLShader;
class ExPolygon;
namespace GUI {
class GLGizmoBase;
class GeometryBuffer
{
std::vector<float> m_vertices;
std::vector<float> m_tex_coords;
public:
bool set_from_triangles(const Polygons& triangles, float z, bool generate_tex_coords);
bool set_from_lines(const Lines& lines, float z);
const float* get_vertices() const;
const float* get_tex_coords() const;
unsigned int get_vertices_count() const;
};
class Size
{
int m_width;
int m_height;
public:
Size();
Size(int width, int height);
int get_width() const;
void set_width(int width);
int get_height() const;
void set_height(int height);
};
class Rect
{
float m_left;
float m_top;
float m_right;
float m_bottom;
public:
Rect();
Rect(float left, float top, float right, float bottom);
float get_left() const;
void set_left(float left);
float get_top() const;
void set_top(float top);
float get_right() const;
void set_right(float right);
float get_bottom() const;
void set_bottom(float bottom);
};
class GLCanvas3D
{
struct GCodePreviewVolumeIndex
{
enum EType
{
Extrusion,
Travel,
Retraction,
Unretraction,
Shell,
Num_Geometry_Types
};
struct FirstVolume
{
EType type;
unsigned int flag;
// Index of the first volume in a GLVolumeCollection.
unsigned int id;
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
};
std::vector<FirstVolume> first_volumes;
void reset() { first_volumes.clear(); }
};
public:
struct Camera
{
enum EType : unsigned char
{
Unknown,
// Perspective,
Ortho,
Num_types
};
EType type;
float zoom;
float phi;
// float distance;
Pointf3 target;
private:
float m_theta;
public:
Camera();
std::string get_type_as_string() const;
float get_theta() const;
void set_theta(float theta);
};
class Bed
{
public:
enum EType : unsigned char
{
MK2,
MK3,
Custom,
Num_Types
};
private:
EType m_type;
Pointfs m_shape;
BoundingBoxf3 m_bounding_box;
Polygon m_polygon;
GeometryBuffer m_triangles;
GeometryBuffer m_gridlines;
mutable GLTexture m_top_texture;
mutable GLTexture m_bottom_texture;
public:
Bed();
bool is_prusa() const;
bool is_custom() const;
const Pointfs& get_shape() const;
void set_shape(const Pointfs& shape);
const BoundingBoxf3& get_bounding_box() const;
bool contains(const Point& point) const;
Point point_projection(const Point& point) const;
void render(float theta) const;
private:
void _calc_bounding_box();
void _calc_triangles(const ExPolygon& poly);
void _calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
EType _detect_type() const;
void _render_mk2(float theta) const;
void _render_mk3(float theta) const;
void _render_prusa(float theta) const;
void _render_custom() const;
static bool _are_equal(const Pointfs& bed_1, const Pointfs& bed_2);
};
struct Axes
{
Pointf3 origin;
float length;
Axes();
void render(bool depth_test) const;
};
class CuttingPlane
{
float m_z;
GeometryBuffer m_lines;
public:
CuttingPlane();
bool set(float z, const ExPolygons& polygons);
void render(const BoundingBoxf3& bb) const;
private:
void _render_plane(const BoundingBoxf3& bb) const;
void _render_contour() const;
};
class Shader
{
GLShader* m_shader;
public:
Shader();
~Shader();
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
bool is_initialized() const;
bool start_using() const;
void stop_using() const;
void set_uniform(const std::string& name, float value) const;
const GLShader* get_shader() const;
private:
void _reset();
};
class LayersEditing
{
public:
enum EState : unsigned char
{
Unknown,
Editing,
Completed,
Num_States
};
private:
bool m_use_legacy_opengl;
bool m_enabled;
Shader m_shader;
unsigned int m_z_texture_id;
mutable GLTexture m_tooltip_texture;
mutable GLTexture m_reset_texture;
public:
EState state;
float band_width;
float strength;
int last_object_id;
float last_z;
unsigned int last_action;
LayersEditing();
~LayersEditing();
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
bool is_allowed() const;
void set_use_legacy_opengl(bool use_legacy_opengl);
bool is_enabled() const;
void set_enabled(bool enabled);
unsigned int get_z_texture_id() const;
void render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const;
int get_shader_program_id() const;
static float get_cursor_z_relative(const GLCanvas3D& canvas);
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y);
static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
static Rect get_reset_rect_screen(const GLCanvas3D& canvas);
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
static Rect get_reset_rect_viewport(const GLCanvas3D& canvas);
private:
bool _is_initialized() const;
void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
void _render_reset_texture(const Rect& reset_rect) const;
void _render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const;
void _render_profile(const PrintObject& print_object, const Rect& bar_rect) const;
};
struct Mouse
{
struct Drag
{
static const Point Invalid_2D_Point;
static const Pointf3 Invalid_3D_Point;
Point start_position_2D;
Pointf3 start_position_3D;
Vectorf3 volume_center_offset;
int volume_idx;
public:
Drag();
};
bool dragging;
Pointf position;
Drag drag;
Mouse();
void set_start_position_2D_as_invalid();
void set_start_position_3D_as_invalid();
bool is_start_position_2D_defined() const;
bool is_start_position_3D_defined() const;
};
class Gizmos
{
static const float OverlayOffsetX;
static const float OverlayGapY;
public:
enum EType : unsigned char
{
Undefined,
Scale,
Rotate,
Num_Types
};
private:
bool m_enabled;
typedef std::map<EType, GLGizmoBase*> GizmosMap;
GizmosMap m_gizmos;
EType m_current;
bool m_dragging;
public:
Gizmos();
~Gizmos();
bool init();
bool is_enabled() const;
void set_enabled(bool enable);
void update_hover_state(const GLCanvas3D& canvas, const Pointf& mouse_pos);
void update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos);
void reset_all_states();
void set_hover_id(int id);
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;
private:
void _reset();
void _render_overlay(const GLCanvas3D& canvas) const;
void _render_current_gizmo(const BoundingBoxf3& box) const;
float _get_total_overlay_height() const;
GLGizmoBase* _get_current() const;
};
private:
wxGLCanvas* m_canvas;
wxGLContext* m_context;
wxTimer* m_timer;
Camera m_camera;
Bed m_bed;
Axes m_axes;
CuttingPlane m_cutting_plane;
LayersEditing m_layers_editing;
Shader m_shader;
Mouse m_mouse;
mutable Gizmos m_gizmos;
mutable GLVolumeCollection m_volumes;
DynamicPrintConfig* m_config;
Print* m_print;
Model* m_model;
bool m_dirty;
// the active member has been introduced to overcome a bug in wxWidgets method IsShownOnScreen() which always return true
// when a window is inside a wxNotebook
bool m_active;
bool m_initialized;
bool m_use_VBOs;
bool m_force_zoom_to_bed_enabled;
bool m_apply_zoom_to_volumes_filter;
mutable int m_hover_volume_id;
bool m_warning_texture_enabled;
bool m_legend_texture_enabled;
bool m_picking_enabled;
bool m_moving_enabled;
bool m_shader_enabled;
bool m_multisample_allowed;
std::string m_color_by;
std::string m_select_by;
std::string m_drag_by;
bool m_reload_delayed;
std::vector<std::vector<int>> m_objects_volumes_idxs;
std::vector<int> m_objects_selections;
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
PerlCallback m_on_viewport_changed_callback;
PerlCallback m_on_double_click_callback;
PerlCallback m_on_right_click_callback;
PerlCallback m_on_select_object_callback;
PerlCallback m_on_model_update_callback;
PerlCallback m_on_remove_object_callback;
PerlCallback m_on_arrange_callback;
PerlCallback m_on_rotate_object_left_callback;
PerlCallback m_on_rotate_object_right_callback;
PerlCallback m_on_scale_object_uniformly_callback;
PerlCallback m_on_increase_objects_callback;
PerlCallback m_on_decrease_objects_callback;
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);
~GLCanvas3D();
bool init(bool useVBOs, bool use_legacy_opengl);
bool set_current();
void set_active(bool active);
unsigned int get_volumes_count() const;
void reset_volumes();
void deselect_volumes();
void select_volume(unsigned int id);
void update_volumes_selection(const std::vector<int>& selections);
bool check_volumes_outside_state(const DynamicPrintConfig* config) const;
bool move_volume_up(unsigned int id);
bool move_volume_down(unsigned int id);
void set_objects_selections(const std::vector<int>& selections);
void set_config(DynamicPrintConfig* config);
void set_print(Print* print);
void set_model(Model* model);
// Set the bed shape to a single closed 2D polygon(array of two element arrays),
// triangulate the bed and store the triangles into m_bed.m_triangles,
// fills the m_bed.m_grid_lines and sets m_bed.m_origin.
// Sets m_bed.m_polygon to limit the object placement.
void set_bed_shape(const Pointfs& shape);
// Used by ObjectCutDialog and ObjectPartsPanel to generate a rectangular ground plane to support the scene objects.
void set_auto_bed_shape();
void set_axes_length(float length);
void set_cutting_plane(float z, const ExPolygons& polygons);
void set_color_by(const std::string& value);
void set_select_by(const std::string& value);
void set_drag_by(const std::string& value);
float get_camera_zoom() const;
BoundingBoxf3 volumes_bounding_box() const;
bool is_layers_editing_enabled() const;
bool is_layers_editing_allowed() const;
bool is_shader_enabled() const;
bool is_reload_delayed() const;
void enable_layers_editing(bool enable);
void enable_warning_texture(bool enable);
void enable_legend_texture(bool enable);
void enable_picking(bool enable);
void enable_moving(bool enable);
void enable_gizmos(bool enable);
void enable_shader(bool enable);
void enable_force_zoom_to_bed(bool enable);
void allow_multisample(bool allow);
void zoom_to_bed();
void zoom_to_volumes();
void select_view(const std::string& direction);
void set_viewport_from_scene(const GLCanvas3D& other);
void update_volumes_colors_by_extruder();
void render();
std::vector<double> get_current_print_zs(bool active_only) const;
void set_toolpaths_range(double low, double high);
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
std::vector<int> load_object(const Model& model, int obj_idx);
void reload_scene(bool force);
// Create 3D thick extrusion lines for a skirt and brim.
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
void load_print_toolpaths();
// Create 3D thick extrusion lines for object forming extrusions.
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
// one for perimeters, one for infill and one for supports.
void load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
// Create 3D thick extrusion lines for wipe tower extrusions
void load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
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_object_callback(void* callback);
void register_on_model_update_callback(void* callback);
void register_on_remove_object_callback(void* callback);
void register_on_arrange_callback(void* callback);
void register_on_rotate_object_left_callback(void* callback);
void register_on_rotate_object_right_callback(void* callback);
void register_on_scale_object_uniformly_callback(void* callback);
void register_on_increase_objects_callback(void* callback);
void register_on_decrease_objects_callback(void* callback);
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();
void on_size(wxSizeEvent& evt);
void on_idle(wxIdleEvent& evt);
void on_char(wxKeyEvent& evt);
void on_mouse_wheel(wxMouseEvent& evt);
void on_timer(wxTimerEvent& evt);
void on_mouse(wxMouseEvent& evt);
void on_paint(wxPaintEvent& evt);
void on_key_down(wxKeyEvent& evt);
Size get_canvas_size() const;
Point get_local_mouse_position() const;
private:
bool _is_shown_on_screen() const;
void _force_zoom_to_bed();
void _resize(unsigned int w, unsigned int h);
BoundingBoxf3 _max_bounding_box() const;
BoundingBoxf3 _selected_volumes_bounding_box() const;
void _zoom_to_bounding_box(const BoundingBoxf3& bbox);
float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const;
void _deregister_callbacks();
void _mark_volumes_for_layer_height() const;
void _refresh_if_shown_on_screen();
void _camera_tranform() const;
void _picking_pass() const;
void _render_background() const;
void _render_bed(float theta) const;
void _render_axes(bool depth_test) const;
void _render_objects() const;
void _render_cutting_plane() const;
void _render_warning_texture() const;
void _render_legend_texture() const;
void _render_layer_editing_overlay() const;
void _render_volumes(bool fake_colors) const;
void _render_gizmo() const;
float _get_layers_editing_cursor_z_relative() const;
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);
// Convert the screen space coordinate to world coordinate on the bed.
Pointf3 _mouse_to_bed_3d(const Point& mouse_pos);
void _start_timer();
void _stop_timer();
int _get_first_selected_object_id() const;
// generates gcode extrusion paths geometry
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode travel paths geometry
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
bool _travel_paths_by_type(const GCodePreviewData& preview_data);
bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data);
bool _travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode retractions geometry
void _load_gcode_retractions(const GCodePreviewData& preview_data);
// generates gcode unretractions geometry
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
// generates objects and wipe tower geometry
void _load_shells();
// sets gcode geometry visibility according to user selection
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
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);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLCanvas3D_hpp_

View File

@ -0,0 +1,707 @@
#include "GLCanvas3DManager.hpp"
#include "../../slic3r/GUI/GUI.hpp"
#include "../../slic3r/GUI/AppConfig.hpp"
#include "../../slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <wx/glcanvas.h>
#include <wx/timer.h>
#include <vector>
#include <string>
#include <iostream>
namespace Slic3r {
namespace GUI {
GLCanvas3DManager::GLInfo::GLInfo()
: version("")
, glsl_version("")
, vendor("")
, renderer("")
{
}
bool GLCanvas3DManager::GLInfo::detect()
{
const char* data = (const char*)::glGetString(GL_VERSION);
if (data == nullptr)
return false;
version = data;
data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
if (data == nullptr)
return false;
glsl_version = data;
data = (const char*)::glGetString(GL_VENDOR);
if (data == nullptr)
return false;
vendor = data;
data = (const char*)::glGetString(GL_RENDERER);
if (data == nullptr)
return false;
renderer = data;
return true;
}
bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
{
std::vector<std::string> tokens;
boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on);
if (tokens.empty())
return false;
std::vector<std::string> numbers;
boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
unsigned int gl_major = 0;
unsigned int gl_minor = 0;
if (numbers.size() > 0)
gl_major = ::atoi(numbers[0].c_str());
if (numbers.size() > 1)
gl_minor = ::atoi(numbers[1].c_str());
if (gl_major < major)
return false;
else if (gl_major > major)
return true;
else
return gl_minor >= minor;
}
std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
{
std::stringstream out;
std::string h2_start = format_as_html ? "<b>" : "";
std::string h2_end = format_as_html ? "</b>" : "";
std::string b_start = format_as_html ? "<b>" : "";
std::string b_end = format_as_html ? "</b>" : "";
std::string line_end = format_as_html ? "<br>" : "\n";
out << h2_start << "OpenGL installation" << h2_end << line_end;
out << b_start << "GL version: " << b_end << version << line_end;
out << b_start << "Vendor: " << b_end << vendor << line_end;
out << b_start << "Renderer: " << b_end << renderer << line_end;
out << b_start << "GLSL version: " << b_end << glsl_version << line_end;
if (extensions)
{
out << h2_start << "Installed extensions:" << h2_end << line_end;
std::vector<std::string> extensions_list;
GLint num_extensions;
::glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; ++i)
{
const char* e = (const char*)::glGetStringi(GL_EXTENSIONS, i);
extensions_list.push_back(e);
}
std::sort(extensions_list.begin(), extensions_list.end());
for (const std::string& ext : extensions_list)
{
out << ext << line_end;
}
}
return out.str();
}
GLCanvas3DManager::GLCanvas3DManager()
: m_context(nullptr)
, m_gl_initialized(false)
, m_use_legacy_opengl(false)
, m_use_VBOs(false)
{
}
GLCanvas3DManager::~GLCanvas3DManager()
{
if (m_context != nullptr)
delete m_context;
}
bool GLCanvas3DManager::add(wxGLCanvas* canvas)
{
if (canvas == nullptr)
return false;
if (_get_canvas(canvas) != m_canvases.end())
return false;
if (m_context == nullptr)
{
m_context = new wxGLContext(canvas);
if (m_context == nullptr)
return false;
}
GLCanvas3D* canvas3D = new GLCanvas3D(canvas, m_context);
if (canvas3D == nullptr)
return false;
canvas3D->bind_event_handlers();
m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));
return true;
}
bool GLCanvas3DManager::remove(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it == m_canvases.end())
return false;
it->second->unbind_event_handlers();
delete it->second;
m_canvases.erase(it);
return true;
}
void GLCanvas3DManager::remove_all()
{
for (CanvasesMap::value_type& item : m_canvases)
{
item.second->unbind_event_handlers();
delete item.second;
}
m_canvases.clear();
}
unsigned int GLCanvas3DManager::count() const
{
return (unsigned int)m_canvases.size();
}
void GLCanvas3DManager::init_gl()
{
if (!m_gl_initialized)
{
glewInit();
if (m_gl_info.detect())
{
const AppConfig* config = GUI::get_app_config();
m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1");
m_use_VBOs = !m_use_legacy_opengl && m_gl_info.is_version_greater_or_equal_to(2, 0);
m_gl_initialized = true;
}
else
throw std::runtime_error(std::string("Unable to initialize OpenGL driver\n"));
}
}
std::string GLCanvas3DManager::get_gl_info(bool format_as_html, bool extensions) const
{
return m_gl_info.to_string(format_as_html, extensions);
}
bool GLCanvas3DManager::use_VBOs() const
{
return m_use_VBOs;
}
bool GLCanvas3DManager::init(wxGLCanvas* canvas)
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
return (it->second != nullptr) ? _init(*it->second) : false;
else
return false;
}
void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_active(active);
}
unsigned int GLCanvas3DManager::get_volumes_count(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->get_volumes_count() : 0;
}
void GLCanvas3DManager::reset_volumes(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->reset_volumes();
}
void GLCanvas3DManager::deselect_volumes(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->deselect_volumes();
}
void GLCanvas3DManager::select_volume(wxGLCanvas* canvas, unsigned int id)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->select_volume(id);
}
void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->update_volumes_selection(selections);
}
bool GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->check_volumes_outside_state(config) : false;
}
bool GLCanvas3DManager::move_volume_up(wxGLCanvas* canvas, unsigned int id)
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->move_volume_up(id) : false;
}
bool GLCanvas3DManager::move_volume_down(wxGLCanvas* canvas, unsigned int id)
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->move_volume_down(id) : false;
}
void GLCanvas3DManager::set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_objects_selections(selections);
}
void GLCanvas3DManager::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_config(config);
}
void GLCanvas3DManager::set_print(wxGLCanvas* canvas, Print* print)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_print(print);
}
void GLCanvas3DManager::set_model(wxGLCanvas* canvas, Model* model)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_model(model);
}
void GLCanvas3DManager::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_bed_shape(shape);
}
void GLCanvas3DManager::set_auto_bed_shape(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_auto_bed_shape();
}
BoundingBoxf3 GLCanvas3DManager::get_volumes_bounding_box(wxGLCanvas* canvas)
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->volumes_bounding_box() : BoundingBoxf3();
}
void GLCanvas3DManager::set_axes_length(wxGLCanvas* canvas, float length)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_axes_length(length);
}
void GLCanvas3DManager::set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_cutting_plane(z, polygons);
}
void GLCanvas3DManager::set_color_by(wxGLCanvas* canvas, const std::string& value)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_color_by(value);
}
void GLCanvas3DManager::set_select_by(wxGLCanvas* canvas, const std::string& value)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_select_by(value);
}
void GLCanvas3DManager::set_drag_by(wxGLCanvas* canvas, const std::string& value)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_drag_by(value);
}
bool GLCanvas3DManager::is_layers_editing_enabled(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->is_layers_editing_enabled() : false;
}
bool GLCanvas3DManager::is_layers_editing_allowed(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->is_layers_editing_allowed() : false;
}
bool GLCanvas3DManager::is_shader_enabled(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->is_shader_enabled() : false;
}
bool GLCanvas3DManager::is_reload_delayed(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->is_reload_delayed() : false;
}
void GLCanvas3DManager::enable_layers_editing(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_layers_editing(enable);
}
void GLCanvas3DManager::enable_warning_texture(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_warning_texture(enable);
}
void GLCanvas3DManager::enable_legend_texture(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_legend_texture(enable);
}
void GLCanvas3DManager::enable_picking(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
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_gizmos(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_gizmos(enable);
}
void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_shader(enable);
}
void GLCanvas3DManager::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_force_zoom_to_bed(enable);
}
void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->allow_multisample(allow);
}
void GLCanvas3DManager::zoom_to_bed(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->zoom_to_bed();
}
void GLCanvas3DManager::zoom_to_volumes(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->zoom_to_volumes();
}
void GLCanvas3DManager::select_view(wxGLCanvas* canvas, const std::string& direction)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->select_view(direction);
}
void GLCanvas3DManager::set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
{
CanvasesMap::iterator other_it = _get_canvas(other);
if (other_it != m_canvases.end())
it->second->set_viewport_from_scene(*other_it->second);
}
}
void GLCanvas3DManager::update_volumes_colors_by_extruder(wxGLCanvas* canvas)
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->update_volumes_colors_by_extruder();
}
void GLCanvas3DManager::render(wxGLCanvas* canvas) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->render();
}
std::vector<double> GLCanvas3DManager::get_current_print_zs(wxGLCanvas* canvas, bool active_only) const
{
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->get_current_print_zs(active_only) : std::vector<double>();
}
void GLCanvas3DManager::set_toolpaths_range(wxGLCanvas* canvas, double low, double high)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->set_toolpaths_range(low, high);
}
std::vector<int> GLCanvas3DManager::load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs)
{
if (model_object == nullptr)
return std::vector<int>();
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->load_object(*model_object, obj_idx, instance_idxs) : std::vector<int>();
}
std::vector<int> GLCanvas3DManager::load_object(wxGLCanvas* canvas, const Model* model, int obj_idx)
{
if (model == nullptr)
return std::vector<int>();
CanvasesMap::const_iterator it = _get_canvas(canvas);
return (it != m_canvases.end()) ? it->second->load_object(*model, obj_idx) : std::vector<int>();
}
void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->reload_scene(force);
}
void GLCanvas3DManager::load_print_toolpaths(wxGLCanvas* canvas)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->load_print_toolpaths();
}
void GLCanvas3DManager::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors)
{
if (print_object == nullptr)
return;
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->load_print_object_toolpaths(*print_object, tool_colors);
}
void GLCanvas3DManager::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->load_wipe_tower_toolpaths(str_tool_colors);
}
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
{
if (preview_data == nullptr)
return;
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->load_gcode_preview(*preview_data, str_tool_colors);
}
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
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_object_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_select_object_callback(callback);
}
void GLCanvas3DManager::register_on_model_update_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_model_update_callback(callback);
}
void GLCanvas3DManager::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_remove_object_callback(callback);
}
void GLCanvas3DManager::register_on_arrange_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_arrange_callback(callback);
}
void GLCanvas3DManager::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_rotate_object_left_callback(callback);
}
void GLCanvas3DManager::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_rotate_object_right_callback(callback);
}
void GLCanvas3DManager::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_scale_object_uniformly_callback(callback);
}
void GLCanvas3DManager::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_increase_objects_callback(callback);
}
void GLCanvas3DManager::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_decrease_objects_callback(callback);
}
void GLCanvas3DManager::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_instance_moved_callback(callback);
}
void GLCanvas3DManager::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->register_on_wipe_tower_moved_callback(callback);
}
void GLCanvas3DManager::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
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);
}
GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) const
{
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
}
bool GLCanvas3DManager::_init(GLCanvas3D& canvas)
{
if (!m_gl_initialized)
init_gl();
return canvas.init(m_use_VBOs, m_use_legacy_opengl);
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,167 @@
#ifndef slic3r_GLCanvas3DManager_hpp_
#define slic3r_GLCanvas3DManager_hpp_
#include "../../libslic3r/BoundingBox.hpp"
#include <map>
#include <vector>
class wxGLCanvas;
class wxGLContext;
namespace Slic3r {
class DynamicPrintConfig;
class Print;
class Model;
class ExPolygon;
typedef std::vector<ExPolygon> ExPolygons;
class ModelObject;
class PrintObject;
class GCodePreviewData;
namespace GUI {
class GLCanvas3D;
class GLCanvas3DManager
{
struct GLInfo
{
std::string version;
std::string glsl_version;
std::string vendor;
std::string renderer;
GLInfo();
bool detect();
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
std::string to_string(bool format_as_html, bool extensions) const;
};
typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap;
wxGLContext* m_context;
CanvasesMap m_canvases;
GLInfo m_gl_info;
bool m_gl_initialized;
bool m_use_legacy_opengl;
bool m_use_VBOs;
public:
GLCanvas3DManager();
~GLCanvas3DManager();
bool add(wxGLCanvas* canvas);
bool remove(wxGLCanvas* canvas);
void remove_all();
unsigned int count() const;
void init_gl();
std::string get_gl_info(bool format_as_html, bool extensions) const;
bool use_VBOs() const;
bool layer_editing_allowed() const;
bool init(wxGLCanvas* canvas);
void set_active(wxGLCanvas* canvas, bool active);
unsigned int get_volumes_count(wxGLCanvas* canvas) const;
void reset_volumes(wxGLCanvas* canvas);
void deselect_volumes(wxGLCanvas* canvas);
void select_volume(wxGLCanvas* canvas, unsigned int id);
void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const;
bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections);
void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config);
void set_print(wxGLCanvas* canvas, Print* print);
void set_model(wxGLCanvas* canvas, Model* model);
void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
void set_auto_bed_shape(wxGLCanvas* canvas);
BoundingBoxf3 get_volumes_bounding_box(wxGLCanvas* canvas);
void set_axes_length(wxGLCanvas* canvas, float length);
void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
void set_color_by(wxGLCanvas* canvas, const std::string& value);
void set_select_by(wxGLCanvas* canvas, const std::string& value);
void set_drag_by(wxGLCanvas* canvas, const std::string& value);
bool is_layers_editing_enabled(wxGLCanvas* canvas) const;
bool is_layers_editing_allowed(wxGLCanvas* canvas) const;
bool is_shader_enabled(wxGLCanvas* canvas) const;
bool is_reload_delayed(wxGLCanvas* canvas) const;
void enable_layers_editing(wxGLCanvas* canvas, bool enable);
void enable_warning_texture(wxGLCanvas* canvas, bool enable);
void enable_legend_texture(wxGLCanvas* canvas, bool enable);
void enable_picking(wxGLCanvas* canvas, bool enable);
void enable_moving(wxGLCanvas* canvas, bool enable);
void enable_gizmos(wxGLCanvas* canvas, bool enable);
void enable_shader(wxGLCanvas* canvas, bool enable);
void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
void allow_multisample(wxGLCanvas* canvas, bool allow);
void zoom_to_bed(wxGLCanvas* canvas);
void zoom_to_volumes(wxGLCanvas* canvas);
void select_view(wxGLCanvas* canvas, const std::string& direction);
void set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other);
void update_volumes_colors_by_extruder(wxGLCanvas* canvas);
void render(wxGLCanvas* canvas) const;
std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const;
void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
std::vector<int> load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs);
std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
void reload_scene(wxGLCanvas* canvas, bool force);
void load_print_toolpaths(wxGLCanvas* canvas);
void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors);
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
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_object_callback(wxGLCanvas* canvas, void* callback);
void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
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);
CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const;
bool _init(GLCanvas3D& canvas);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLCanvas3DManager_hpp_

View File

@ -0,0 +1,454 @@
#include "GLGizmo.hpp"
#include "../../libslic3r/Utils.hpp"
#include "../../libslic3r/BoundingBox.hpp"
#include <GL/glew.h>
#include <iostream>
namespace Slic3r {
namespace GUI {
const float GLGizmoBase::Grabber::HalfSize = 2.0f;
const float GLGizmoBase::Grabber::HoverOffset = 0.5f;
const float GLGizmoBase::BaseColor[3] = { 1.0f, 1.0f, 1.0f };
const float GLGizmoBase::HighlightColor[3] = { 1.0f, 0.38f, 0.0f };
GLGizmoBase::Grabber::Grabber()
: center(Pointf(0.0, 0.0))
, angle_z(0.0f)
{
color[0] = 1.0f;
color[1] = 1.0f;
color[2] = 1.0f;
}
void GLGizmoBase::Grabber::render(bool hover) const
{
float min_x = -HalfSize;
float max_x = +HalfSize;
float min_y = -HalfSize;
float max_y = +HalfSize;
::glColor3f((GLfloat)color[0], (GLfloat)color[1], (GLfloat)color[2]);
float angle_z_in_deg = angle_z * 180.0f / (float)PI;
::glPushMatrix();
::glTranslatef((GLfloat)center.x, (GLfloat)center.y, 0.0f);
::glRotatef((GLfloat)angle_z_in_deg, 0.0f, 0.0f, 1.0f);
::glDisable(GL_CULL_FACE);
::glBegin(GL_TRIANGLES);
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
::glVertex3f((GLfloat)max_x, (GLfloat)min_y, 0.0f);
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
::glVertex3f((GLfloat)min_x, (GLfloat)max_y, 0.0f);
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
::glEnd();
::glEnable(GL_CULL_FACE);
if (hover)
{
min_x -= HoverOffset;
max_x += HoverOffset;
min_y -= HoverOffset;
max_y += HoverOffset;
::glBegin(GL_LINE_LOOP);
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
::glVertex3f((GLfloat)max_x, (GLfloat)min_y, 0.0f);
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
::glVertex3f((GLfloat)min_x, (GLfloat)max_y, 0.0f);
::glEnd();
}
::glPopMatrix();
}
GLGizmoBase::GLGizmoBase()
: m_state(Off)
, m_hover_id(-1)
{
}
GLGizmoBase::~GLGizmoBase()
{
}
bool GLGizmoBase::init()
{
return on_init();
}
GLGizmoBase::EState GLGizmoBase::get_state() const
{
return m_state;
}
void GLGizmoBase::set_state(GLGizmoBase::EState state)
{
m_state = state;
}
unsigned int GLGizmoBase::get_textures_id() const
{
return m_textures[m_state].get_id();
}
int GLGizmoBase::get_textures_size() const
{
return m_textures[Off].get_width();
}
int GLGizmoBase::get_hover_id() const
{
return m_hover_id;
}
void GLGizmoBase::set_hover_id(int id)
{
if (id < (int)m_grabbers.size())
m_hover_id = id;
}
void GLGizmoBase::start_dragging()
{
on_start_dragging();
}
void GLGizmoBase::update(const Pointf& mouse_pos)
{
if (m_hover_id != -1)
on_update(mouse_pos);
}
void GLGizmoBase::render(const BoundingBoxf3& box) const
{
on_render(box);
}
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)
{
m_grabbers[i].render(m_hover_id == i);
}
}
const float GLGizmoRotate::Offset = 5.0f;
const unsigned int GLGizmoRotate::CircleResolution = 64;
const unsigned int GLGizmoRotate::AngleResolution = 64;
const unsigned int GLGizmoRotate::ScaleStepsCount = 60;
const float GLGizmoRotate::ScaleStepRad = 2.0f * (float)PI / GLGizmoRotate::ScaleStepsCount;
const unsigned int GLGizmoRotate::ScaleLongEvery = 5;
const float GLGizmoRotate::ScaleLongTooth = 2.0f;
const float GLGizmoRotate::ScaleShortTooth = 1.0f;
const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
const float GLGizmoRotate::GrabberOffset = 5.0f;
GLGizmoRotate::GLGizmoRotate()
: GLGizmoBase()
, m_angle_z(0.0f)
, m_center(Pointf(0.0, 0.0))
, m_radius(0.0f)
{
}
bool GLGizmoRotate::on_init()
{
std::string path = resources_dir() + "/icons/overlay/";
std::string filename = path + "rotate_off.png";
if (!m_textures[Off].load_from_file(filename, false))
return false;
filename = path + "rotate_hover.png";
if (!m_textures[Hover].load_from_file(filename, false))
return false;
filename = path + "rotate_on.png";
if (!m_textures[On].load_from_file(filename, false))
return false;
m_grabbers.push_back(Grabber());
return true;
}
void GLGizmoRotate::on_update(const Pointf& mouse_pos)
{
Vectorf orig_dir(1.0, 0.0);
Vectorf new_dir = normalize(mouse_pos - m_center);
coordf_t theta = ::acos(clamp(-1.0, 1.0, dot(new_dir, orig_dir)));
if (cross(orig_dir, new_dir) < 0.0)
theta = 2.0 * (coordf_t)PI - theta;
if (length(m_center.vector_to(mouse_pos)) < 2.0 * (double)m_radius / 3.0)
{
coordf_t step = 2.0 * (coordf_t)PI / (coordf_t)SnapRegionsCount;
theta = step * (coordf_t)std::round(theta / step);
}
if (theta == 2.0 * (coordf_t)PI)
theta = 0.0;
m_angle_z = (float)theta;
}
void GLGizmoRotate::on_render(const BoundingBoxf3& box) const
{
::glDisable(GL_LIGHTING);
::glDisable(GL_DEPTH_TEST);
const Pointf3& size = box.size();
m_center = box.center();
m_radius = Offset + ::sqrt(sqr(0.5f * size.x) + sqr(0.5f * size.y));
::glLineWidth(2.0f);
::glColor3fv(BaseColor);
_render_circle();
_render_scale();
_render_snap_radii();
_render_reference_radius();
::glColor3fv(HighlightColor);
_render_angle_z();
_render_grabber();
}
void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const
{
::glDisable(GL_LIGHTING);
::glDisable(GL_DEPTH_TEST);
m_grabbers[0].color[0] = 1.0f;
m_grabbers[0].color[1] = 1.0f;
m_grabbers[0].color[2] = 254.0f / 255.0f;
render_grabbers();
}
void GLGizmoRotate::_render_circle() const
{
::glBegin(GL_LINE_LOOP);
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
{
float angle = (float)i * ScaleStepRad;
float x = m_center.x + ::cos(angle) * m_radius;
float y = m_center.y + ::sin(angle) * m_radius;
::glVertex3f((GLfloat)x, (GLfloat)y, 0.0f);
}
::glEnd();
}
void GLGizmoRotate::_render_scale() const
{
float out_radius_long = m_radius + ScaleLongTooth;
float out_radius_short = m_radius + ScaleShortTooth;
::glBegin(GL_LINES);
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
{
float angle = (float)i * ScaleStepRad;
float cosa = ::cos(angle);
float sina = ::sin(angle);
float in_x = m_center.x + cosa * m_radius;
float in_y = m_center.y + sina * m_radius;
float out_x = (i % ScaleLongEvery == 0) ? m_center.x + cosa * out_radius_long : m_center.x + cosa * out_radius_short;
float out_y = (i % ScaleLongEvery == 0) ? m_center.y + sina * out_radius_long : m_center.y + sina * out_radius_short;
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, 0.0f);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, 0.0f);
}
::glEnd();
}
void GLGizmoRotate::_render_snap_radii() const
{
float step = 2.0f * (float)PI / (float)SnapRegionsCount;
float in_radius = m_radius / 3.0f;
float out_radius = 2.0f * in_radius;
::glBegin(GL_LINES);
for (unsigned int i = 0; i < SnapRegionsCount; ++i)
{
float angle = (float)i * step;
float cosa = ::cos(angle);
float sina = ::sin(angle);
float in_x = m_center.x + cosa * in_radius;
float in_y = m_center.y + sina * in_radius;
float out_x = m_center.x + cosa * out_radius;
float out_y = m_center.y + sina * out_radius;
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, 0.0f);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, 0.0f);
}
::glEnd();
}
void GLGizmoRotate::_render_reference_radius() const
{
::glBegin(GL_LINES);
::glVertex3f((GLfloat)m_center.x, (GLfloat)m_center.y, 0.0f);
::glVertex3f((GLfloat)m_center.x + m_radius + GrabberOffset, (GLfloat)m_center.y, 0.0f);
::glEnd();
}
void GLGizmoRotate::_render_angle_z() const
{
float step_angle = m_angle_z / AngleResolution;
float ex_radius = m_radius + GrabberOffset;
::glBegin(GL_LINE_STRIP);
for (unsigned int i = 0; i <= AngleResolution; ++i)
{
float angle = (float)i * step_angle;
float x = m_center.x + ::cos(angle) * ex_radius;
float y = m_center.y + ::sin(angle) * ex_radius;
::glVertex3f((GLfloat)x, (GLfloat)y, 0.0f);
}
::glEnd();
}
void GLGizmoRotate::_render_grabber() const
{
float grabber_radius = m_radius + GrabberOffset;
m_grabbers[0].center.x = m_center.x + ::cos(m_angle_z) * grabber_radius;
m_grabbers[0].center.y = m_center.y + ::sin(m_angle_z) * grabber_radius;
m_grabbers[0].angle_z = m_angle_z;
::glColor3fv(BaseColor);
::glBegin(GL_LINES);
::glVertex3f((GLfloat)m_center.x, (GLfloat)m_center.y, 0.0f);
::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, 3 * sizeof(float));
render_grabbers();
}
const float GLGizmoScale::Offset = 5.0f;
GLGizmoScale::GLGizmoScale()
: GLGizmoBase()
, 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/";
std::string filename = path + "scale_off.png";
if (!m_textures[Off].load_from_file(filename, false))
return false;
filename = path + "scale_hover.png";
if (!m_textures[Hover].load_from_file(filename, false))
return false;
filename = path + "scale_on.png";
if (!m_textures[On].load_from_file(filename, false))
return false;
for (unsigned int i = 0; i < 4; ++i)
{
m_grabbers.push_back(Grabber());
}
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_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 = m_starting_scale * (float)ratio;
}
void GLGizmoScale::on_render(const BoundingBoxf3& box) const
{
::glDisable(GL_LIGHTING);
::glDisable(GL_DEPTH_TEST);
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;
m_grabbers[1].center.x = max_x;
m_grabbers[1].center.y = min_y;
m_grabbers[2].center.x = max_x;
m_grabbers[2].center.y = max_y;
m_grabbers[3].center.x = min_x;
m_grabbers[3].center.y = max_y;
::glLineWidth(2.0f);
::glColor3fv(BaseColor);
// draw outline
::glBegin(GL_LINE_LOOP);
for (unsigned int i = 0; i < 4; ++i)
{
::glVertex3f((GLfloat)m_grabbers[i].center.x, (GLfloat)m_grabbers[i].center.y, 0.0f);
}
::glEnd();
// draw grabbers
for (unsigned int i = 0; i < 4; ++i)
{
::memcpy((void*)m_grabbers[i].color, (const void*)HighlightColor, 3 * sizeof(float));
}
render_grabbers();
}
void GLGizmoScale::on_render_for_picking(const BoundingBoxf3& box) const
{
static const GLfloat INV_255 = 1.0f / 255.0f;
::glDisable(GL_LIGHTING);
::glDisable(GL_DEPTH_TEST);
for (unsigned int i = 0; i < 4; ++i)
{
m_grabbers[i].color[0] = 1.0f;
m_grabbers[i].color[1] = 1.0f;
m_grabbers[i].color[2] = (254.0f - (float)i) * INV_255;
}
render_grabbers();
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,145 @@
#ifndef slic3r_GLGizmo_hpp_
#define slic3r_GLGizmo_hpp_
#include "../../slic3r/GUI/GLTexture.hpp"
#include "../../libslic3r/Point.hpp"
#include <vector>
namespace Slic3r {
class BoundingBoxf3;
class Pointf3;
namespace GUI {
class GLGizmoBase
{
protected:
static const float BaseColor[3];
static const float HighlightColor[3];
struct Grabber
{
static const float HalfSize;
static const float HoverOffset;
Pointf center;
float angle_z;
float color[3];
Grabber();
void render(bool hover) const;
};
public:
enum EState
{
Off,
Hover,
On,
Num_States
};
protected:
EState m_state;
// textures are assumed to be square and all with the same size in pixels, no internal check is done
GLTexture m_textures[Num_States];
int m_hover_id;
mutable std::vector<Grabber> m_grabbers;
public:
GLGizmoBase();
virtual ~GLGizmoBase();
bool init();
EState get_state() const;
void set_state(EState state);
unsigned int get_textures_id() const;
int get_textures_size() const;
int get_hover_id() const;
void set_hover_id(int id);
void start_dragging();
void update(const Pointf& mouse_pos);
void render(const BoundingBoxf3& box) const;
void render_for_picking(const BoundingBoxf3& box) const;
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;
void render_grabbers() const;
};
class GLGizmoRotate : public GLGizmoBase
{
static const float Offset;
static const unsigned int CircleResolution;
static const unsigned int AngleResolution;
static const unsigned int ScaleStepsCount;
static const float ScaleStepRad;
static const unsigned int ScaleLongEvery;
static const float ScaleLongTooth;
static const float ScaleShortTooth;
static const unsigned int SnapRegionsCount;
static const float GrabberOffset;
float m_angle_z;
mutable Pointf m_center;
mutable float m_radius;
public:
GLGizmoRotate();
protected:
virtual bool on_init();
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;
private:
void _render_circle() const;
void _render_scale() const;
void _render_snap_radii() const;
void _render_reference_radius() const;
void _render_angle_z() const;
void _render_grabber() const;
};
class GLGizmoScale : public GLGizmoBase
{
static const float Offset;
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;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmo_hpp_

View File

@ -2,6 +2,9 @@
#include "GLShader.hpp" #include "GLShader.hpp"
#include "../../libslic3r/Utils.hpp"
#include <boost/nowide/fstream.hpp>
#include <string> #include <string>
#include <utility> #include <utility>
#include <assert.h> #include <assert.h>
@ -22,7 +25,7 @@ inline std::string gl_get_string_safe(GLenum param)
return std::string(value ? value : "N/A"); return std::string(value ? value : "N/A");
} }
bool GLShader::load(const char *fragment_shader, const char *vertex_shader) bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_shader)
{ {
std::string gl_version = gl_get_string_safe(GL_VERSION); std::string gl_version = gl_get_string_safe(GL_VERSION);
int major = atoi(gl_version.c_str()); int major = atoi(gl_version.c_str());
@ -123,6 +126,41 @@ bool GLShader::load(const char *fragment_shader, const char *vertex_shader)
return true; return true;
} }
bool GLShader::load_from_file(const char* fragment_shader_filename, const char* vertex_shader_filename)
{
const std::string& path = resources_dir() + "/shaders/";
boost::nowide::ifstream vs(path + std::string(vertex_shader_filename), boost::nowide::ifstream::binary);
if (!vs.good())
return false;
vs.seekg(0, vs.end);
int file_length = vs.tellg();
vs.seekg(0, vs.beg);
std::string vertex_shader(file_length, '\0');
vs.read(const_cast<char*>(vertex_shader.data()), file_length);
if (!vs.good())
return false;
vs.close();
boost::nowide::ifstream fs(path + std::string(fragment_shader_filename), boost::nowide::ifstream::binary);
if (!fs.good())
return false;
fs.seekg(0, fs.end);
file_length = fs.tellg();
fs.seekg(0, fs.beg);
std::string fragment_shader(file_length, '\0');
fs.read(const_cast<char*>(fragment_shader.data()), file_length);
if (!fs.good())
return false;
fs.close();
return load_from_text(fragment_shader.c_str(), vertex_shader.c_str());
}
void GLShader::release() void GLShader::release()
{ {
if (this->shader_program_id) { if (this->shader_program_id) {

View File

@ -16,7 +16,9 @@ public:
{} {}
~GLShader(); ~GLShader();
bool load(const char *fragment_shader, const char *vertex_shader); bool load_from_text(const char *fragment_shader, const char *vertex_shader);
bool load_from_file(const char* fragment_shader_filename, const char* vertex_shader_filename);
void release(); void release();
int get_attrib_location(const char *name) const; int get_attrib_location(const char *name) const;

View File

@ -0,0 +1,185 @@
#include "GLTexture.hpp"
#include <GL/glew.h>
#include <wx/image.h>
#include <vector>
#include <algorithm>
namespace Slic3r {
namespace GUI {
GLTexture::GLTexture()
: m_id(0)
, m_width(0)
, m_height(0)
, m_source("")
{
}
GLTexture::~GLTexture()
{
reset();
}
bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmaps)
{
reset();
// Load a PNG with an alpha channel.
wxImage image;
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
{
reset();
return false;
}
m_width = image.GetWidth();
m_height = image.GetHeight();
int n_pixels = m_width * m_height;
if (n_pixels <= 0)
{
reset();
return false;
}
// Get RGB & alpha raw data from wxImage, pack them into an array.
unsigned char* img_rgb = image.GetData();
if (img_rgb == nullptr)
{
reset();
return false;
}
unsigned char* img_alpha = image.GetAlpha();
std::vector<unsigned char> data(n_pixels * 4, 0);
for (int i = 0; i < n_pixels; ++i)
{
int data_id = i * 4;
int img_id = i * 3;
data[data_id + 0] = img_rgb[img_id + 0];
data[data_id + 1] = img_rgb[img_id + 1];
data[data_id + 2] = img_rgb[img_id + 2];
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
}
// sends data to gpu
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
if (generate_mipmaps)
{
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
_generate_mipmaps(image);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
}
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glBindTexture(GL_TEXTURE_2D, 0);
m_source = filename;
return true;
}
void GLTexture::reset()
{
if (m_id != 0)
::glDeleteTextures(1, &m_id);
m_id = 0;
m_width = 0;
m_height = 0;
m_source = "";
}
unsigned int GLTexture::get_id() const
{
return m_id;
}
int GLTexture::get_width() const
{
return m_width;
}
int GLTexture::get_height() const
{
return m_height;
}
const std::string& GLTexture::get_source() const
{
return m_source;
}
void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top)
{
::glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
::glDisable(GL_LIGHTING);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
::glEnable(GL_TEXTURE_2D);
::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id);
::glBegin(GL_QUADS);
::glTexCoord2d(0.0f, 1.0f); ::glVertex3f(left, bottom, 0.0f);
::glTexCoord2d(1.0f, 1.0f); ::glVertex3f(right, bottom, 0.0f);
::glTexCoord2d(1.0f, 0.0f); ::glVertex3f(right, top, 0.0f);
::glTexCoord2d(0.0f, 0.0f); ::glVertex3f(left, top, 0.0f);
::glEnd();
::glBindTexture(GL_TEXTURE_2D, 0);
::glDisable(GL_TEXTURE_2D);
::glDisable(GL_BLEND);
::glEnable(GL_LIGHTING);
}
void GLTexture::_generate_mipmaps(wxImage& image)
{
int w = image.GetWidth();
int h = image.GetHeight();
GLint level = 0;
std::vector<unsigned char> data(w * h * 4, 0);
while ((w > 1) && (h > 1))
{
++level;
w = std::max(w / 2, 1);
h = std::max(h / 2, 1);
int n_pixels = w * h;
image = image.ResampleBicubic(w, h);
unsigned char* img_rgb = image.GetData();
unsigned char* img_alpha = image.GetAlpha();
data.resize(n_pixels * 4);
for (int i = 0; i < n_pixels; ++i)
{
int data_id = i * 4;
int img_id = i * 3;
data[data_id + 0] = img_rgb[img_id + 0];
data[data_id + 1] = img_rgb[img_id + 1];
data[data_id + 2] = img_rgb[img_id + 2];
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
}
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
}
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,41 @@
#ifndef slic3r_GLTexture_hpp_
#define slic3r_GLTexture_hpp_
#include <string>
class wxImage;
namespace Slic3r {
namespace GUI {
class GLTexture
{
private:
unsigned int m_id;
int m_width;
int m_height;
std::string m_source;
public:
GLTexture();
~GLTexture();
bool load_from_file(const std::string& filename, bool generate_mipmaps);
void reset();
unsigned int get_id() const;
int get_width() const;
int get_height() const;
const std::string& get_source() const;
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
private:
void _generate_mipmaps(wxImage& image);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLTexture_hpp_

View File

@ -8,7 +8,8 @@
GLShader(); GLShader();
~GLShader(); ~GLShader();
bool load(const char *fragment_shader, const char *vertex_shader); bool load_from_text(const char *fragment_shader, const char *vertex_shader);
bool load_from_file(const char *fragment_shader, const char *vertex_shader);
void release(); void release();
int get_attrib_location(const char *name) const; int get_attrib_location(const char *name) const;
@ -92,9 +93,6 @@
int count() int count()
%code{% RETVAL = THIS->volumes.size(); %}; %code{% RETVAL = THIS->volumes.size(); %};
std::vector<double> get_current_print_zs(bool active_only)
%code{% RETVAL = THIS->get_current_print_zs(active_only); %};
void set_range(double low, double high); void set_range(double low, double high);
void render_VBOs() const; void render_VBOs() const;
@ -155,11 +153,457 @@ GLVolumeCollection::arrayref()
%package{Slic3r::GUI::_3DScene}; %package{Slic3r::GUI::_3DScene};
%{ %{
std::string
get_gl_info(format_as_html, extensions)
bool format_as_html;
bool extensions;
CODE:
RETVAL = _3DScene::get_gl_info(format_as_html, extensions);
OUTPUT:
RETVAL
bool
use_VBOs()
CODE:
RETVAL = _3DScene::use_VBOs();
OUTPUT:
RETVAL
bool
add_canvas(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::add_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
bool
remove_canvas(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::remove_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
void void
_glew_init() remove_all_canvases()
CODE: CODE:
_3DScene::_glew_init(); _3DScene::remove_all_canvases();
void
set_active(canvas, active)
SV *canvas;
bool active;
CODE:
_3DScene::set_active((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active);
unsigned int
get_volumes_count(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::get_volumes_count((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
void
reset_volumes(canvas)
SV *canvas;
CODE:
_3DScene::reset_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void
deselect_volumes(canvas)
SV *canvas;
CODE:
_3DScene::deselect_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void
select_volume(canvas, id)
SV *canvas;
unsigned int id;
CODE:
_3DScene::select_volume((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
void
update_volumes_selection(canvas, selections)
SV *canvas;
std::vector<int> selections;
CODE:
_3DScene::update_volumes_selection((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections);
bool
check_volumes_outside_state(canvas, config)
SV *canvas;
DynamicPrintConfig *config;
CODE:
RETVAL = _3DScene::check_volumes_outside_state((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), config);
OUTPUT:
RETVAL
bool
move_volume_up(canvas, id)
SV *canvas;
unsigned int id;
CODE:
RETVAL = _3DScene::move_volume_up((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
OUTPUT:
RETVAL
bool
move_volume_down(canvas, id)
SV *canvas;
unsigned int id;
CODE:
RETVAL = _3DScene::move_volume_down((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
OUTPUT:
RETVAL
void
set_objects_selections(canvas, selections)
SV *canvas;
std::vector<int> selections;
CODE:
_3DScene::set_objects_selections((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections);
void
set_config(canvas, config)
SV *canvas;
DynamicPrintConfig *config;
CODE:
_3DScene::set_config((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), config);
void
set_print(canvas, print)
SV *canvas;
Print *print;
CODE:
_3DScene::set_print((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print);
void
set_model(canvas, model)
SV *canvas;
Model *model;
CODE:
_3DScene::set_model((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model);
void
set_bed_shape(canvas, shape)
SV *canvas;
Pointfs shape;
CODE:
_3DScene::set_bed_shape((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), shape);
void
set_auto_bed_shape(canvas)
SV *canvas;
CODE:
_3DScene::set_auto_bed_shape((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
Clone<BoundingBoxf3>
get_volumes_bounding_box(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::get_volumes_bounding_box((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
void
set_axes_length(canvas, length)
SV *canvas;
float length;
CODE:
_3DScene::set_axes_length((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), length);
void
set_cutting_plane(canvas, z, polygons)
SV *canvas;
float z;
ExPolygons polygons;
CODE:
_3DScene::set_cutting_plane((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), z, polygons);
void
set_color_by(canvas, value)
SV *canvas;
std::string value;
CODE:
_3DScene::set_color_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
void
set_select_by(canvas, value)
SV *canvas;
std::string value;
CODE:
_3DScene::set_select_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
void
set_drag_by(canvas, value)
SV *canvas;
std::string value;
CODE:
_3DScene::set_drag_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
bool
is_layers_editing_enabled(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::is_layers_editing_enabled((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
bool
is_layers_editing_allowed(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::is_layers_editing_allowed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
bool
is_shader_enabled(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::is_shader_enabled((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
bool
is_reload_delayed(canvas)
SV *canvas;
CODE:
RETVAL = _3DScene::is_reload_delayed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
OUTPUT:
RETVAL
void
enable_layers_editing(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_layers_editing((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_warning_texture(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_warning_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_legend_texture(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_legend_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_picking(canvas, enable)
SV *canvas;
bool enable;
CODE:
_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
enable_gizmos(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_gizmos((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_shader(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_shader((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_force_zoom_to_bed(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_force_zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
allow_multisample(canvas, allow)
SV *canvas;
bool allow;
CODE:
_3DScene::allow_multisample((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), allow);
void
zoom_to_bed(canvas)
SV *canvas;
CODE:
_3DScene::zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void
zoom_to_volumes(canvas)
SV *canvas;
CODE:
_3DScene::zoom_to_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void
select_view(canvas, direction)
SV *canvas;
std::string direction;
CODE:
_3DScene::select_view((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), direction);
void
set_viewport_from_scene(canvas, other)
SV *canvas;
SV *other;
CODE:
_3DScene::set_viewport_from_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (wxGLCanvas*)wxPli_sv_2_object(aTHX_ other, "Wx::GLCanvas"));
void
update_volumes_colors_by_extruder(canvas)
SV *canvas;
CODE:
_3DScene::update_volumes_colors_by_extruder((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void
render(canvas)
SV *canvas;
CODE:
_3DScene::render((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
std::vector<double>
get_current_print_zs(canvas, active_only)
SV *canvas;
bool active_only;
CODE:
RETVAL = _3DScene::get_current_print_zs((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active_only);
OUTPUT:
RETVAL
void
set_toolpaths_range(canvas, low, high)
SV *canvas;
double low;
double high;
CODE:
_3DScene::set_toolpaths_range((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), low, high);
void
register_on_viewport_changed_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_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_object_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_select_object_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_model_update_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_model_update_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_remove_object_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_remove_object_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_arrange_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_arrange_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_rotate_object_left_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_rotate_object_left_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_rotate_object_right_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_rotate_object_right_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_scale_object_uniformly_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_scale_object_uniformly_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_increase_objects_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_increase_objects_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_decrease_objects_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_decrease_objects_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_instance_moved_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_instance_moved_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_wipe_tower_moved_callback(canvas, callback)
SV *canvas;
SV *callback;
CODE:
_3DScene::register_on_wipe_tower_moved_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
void
register_on_enable_action_buttons_callback(canvas, callback)
SV *canvas;
SV *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 unsigned int
finalize_legend_texture() finalize_legend_texture()
@ -218,41 +662,61 @@ reset_warning_texture()
CODE: CODE:
_3DScene::reset_warning_texture(); _3DScene::reset_warning_texture();
void std::vector<int>
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs) load_model_object(canvas, model_object, obj_idx, instance_idxs)
Print *print; SV *canvas;
GLVolumeCollection *volumes; ModelObject *model_object;
std::vector<std::string> tool_colors; int obj_idx;
int use_VBOs; std::vector<int> instance_idxs;
CODE: CODE:
_3DScene::_load_print_toolpaths(print, volumes, tool_colors, use_VBOs != 0); RETVAL = _3DScene::load_object((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model_object, obj_idx, instance_idxs);
OUTPUT:
RETVAL
std::vector<int>
load_model(canvas, model, obj_idx)
SV *canvas;
Model *model;
int obj_idx;
CODE:
RETVAL = _3DScene::load_object((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model, obj_idx);
OUTPUT:
RETVAL
void void
_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs) reload_scene(canvas, force)
PrintObject *print_object; SV *canvas;
GLVolumeCollection *volumes; bool force;
std::vector<std::string> tool_colors;
int use_VBOs;
CODE: CODE:
_3DScene::_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs != 0); _3DScene::reload_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), force);
void void
_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs) load_print_toolpaths(canvas)
Print *print; SV *canvas;
GLVolumeCollection *volumes;
std::vector<std::string> tool_colors;
int use_VBOs;
CODE: CODE:
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0); _3DScene::load_print_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
void void
load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs) load_print_object_toolpaths(canvas, print_object, tool_colors)
Print *print; SV *canvas;
PrintObject *print_object;
std::vector<std::string> tool_colors;
CODE:
_3DScene::load_print_object_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object, tool_colors);
void
load_wipe_tower_toolpaths(canvas, tool_colors)
SV *canvas;
std::vector<std::string> tool_colors;
CODE:
_3DScene::load_wipe_tower_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), tool_colors);
void
load_gcode_preview(canvas, preview_data, str_tool_colors)
SV *canvas;
GCodePreviewData *preview_data; GCodePreviewData *preview_data;
GLVolumeCollection *volumes;
std::vector<std::string> str_tool_colors; std::vector<std::string> str_tool_colors;
int use_VBOs;
CODE: CODE:
_3DScene::load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs != 0); _3DScene::load_gcode_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), preview_data, str_tool_colors);
%} %}

View File

@ -52,6 +52,9 @@ _constant()
int region_count() int region_count()
%code%{ RETVAL = THIS->print()->regions.size(); %}; %code%{ RETVAL = THIS->print()->regions.size(); %};
int region_volumes_count()
%code%{ RETVAL = THIS->region_volumes.size(); %};
Ref<Print> print(); Ref<Print> print();
Ref<ModelObject> model_object(); Ref<ModelObject> model_object();
Ref<StaticPrintConfig> config() Ref<StaticPrintConfig> config()
@ -119,15 +122,6 @@ _constant()
RETVAL.push_back(slicing_params.layer_height); RETVAL.push_back(slicing_params.layer_height);
%}; %};
void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
%code%{
THIS->update_layer_height_profile(THIS->model_object()->layer_height_profile);
adjust_layer_height_profile(
THIS->slicing_parameters(), THIS->model_object()->layer_height_profile, z, layer_thickness_delta, band_width, LayerHeightEditActionType(action));
THIS->model_object()->layer_height_profile_valid = true;
THIS->layer_height_profile_valid = false;
%};
void reset_layer_height_profile(); void reset_layer_height_profile();
int ptr() int ptr()