mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/dev_native' into ys_dev_native
This commit is contained in:
		
						commit
						9f1613bffb
					
				
					 36 changed files with 1993 additions and 214 deletions
				
			
		|  | @ -41,6 +41,7 @@ our $PROCESS_COMPLETED_EVENT = Wx::NewEventType; | |||
| my $PreventListEvents = 0; | ||||
| our $appController; | ||||
| 
 | ||||
| # XXX: VK: done, except callback handling and timer | ||||
| sub new { | ||||
|     my ($class, $parent, %params) = @_; | ||||
|     my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); | ||||
|  | @ -813,12 +814,14 @@ sub new { | |||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: WIP | ||||
| # sets the callback | ||||
| sub on_select_preset { | ||||
|     my ($self, $cb) = @_; | ||||
|     $self->{on_select_preset} = $cb; | ||||
| } | ||||
| 
 | ||||
| # XXX: merged with on_select_preset | ||||
| # Called from the platter combo boxes selecting the active print, filament or printer. | ||||
| sub _on_select_preset { | ||||
| 	my ($self, $group, $choice, $idx) = @_; | ||||
|  | @ -855,6 +858,7 @@ sub _on_select_preset { | |||
| 	$self->on_config_change(wxTheApp->{preset_bundle}->full_config); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub on_layer_editing_toggled { | ||||
|     my ($self, $new_state) = @_; | ||||
|     Slic3r::GUI::_3DScene::enable_layers_editing($self->{canvas3D}, $new_state); | ||||
|  | @ -873,11 +877,13 @@ sub on_layer_editing_toggled { | |||
|     $self->{canvas3D}->Update; | ||||
| } | ||||
| 
 | ||||
| sub GetFrame {   # XXX: main_frame in C++ Plater | ||||
| # XXX: VK: done (Plater::priv::main_frame) | ||||
| sub GetFrame { | ||||
|     my ($self) = @_; | ||||
|     return &Wx::GetTopLevelParent($self); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Called after the Preferences dialog is closed and the program settings are saved. | ||||
| # Update the UI based on the current preferences. | ||||
| sub update_ui_from_settings | ||||
|  | @ -889,6 +895,7 @@ sub update_ui_from_settings | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| # Update preset combo boxes (Print settings, Filament, Material, Printer) from their respective tabs. | ||||
| # Called by  | ||||
| #       Slic3r::GUI::Tab::Print::_on_presets_changed | ||||
|  | @ -934,12 +941,14 @@ sub update_presets { | |||
|     wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done, in on_action_add() | ||||
| sub add { | ||||
|     my ($self) = @_; | ||||
|     my @input_files = wxTheApp->open_model($self); | ||||
|     $self->load_files(\@input_files); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub load_files { | ||||
|     my ($self, $input_files) = @_; | ||||
| 
 | ||||
|  | @ -1030,6 +1039,7 @@ sub load_files { | |||
|     return @obj_idx; | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done, except a few todos | ||||
| sub load_model_objects { | ||||
|     my ($self, @model_objects) = @_; | ||||
|      | ||||
|  | @ -1112,6 +1122,7 @@ sub load_model_objects { | |||
|     return @obj_idx; | ||||
| } | ||||
| 
 | ||||
| # XXX: Removed | ||||
| sub bed_centerf { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -1120,6 +1131,7 @@ sub bed_centerf { | |||
|     return Slic3r::Pointf->new(unscale($bed_center->x), unscale($bed_center->y)); #) | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub remove { | ||||
|     my ($self, $obj_idx) = @_; | ||||
|      | ||||
|  | @ -1146,6 +1158,7 @@ sub remove { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub reset { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -1166,6 +1179,7 @@ sub reset { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub increase { | ||||
|     my ($self, $copies) = @_; | ||||
|     $copies //= 1; | ||||
|  | @ -1197,6 +1211,7 @@ sub increase { | |||
|     $self->schedule_background_process; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub decrease { | ||||
|     my ($self, $copies_asked) = @_; | ||||
|     my $copies = $copies_asked // 1; | ||||
|  | @ -1224,6 +1239,7 @@ sub decrease { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub set_number_of_copies { | ||||
|     my ($self) = @_; | ||||
|     # get current number of copies | ||||
|  | @ -1242,6 +1258,7 @@ sub set_number_of_copies { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: not done (?) | ||||
| sub _get_number_from_user {     # XXX: Enrico | ||||
|     my ($self, $title, $prompt_message, $error_message, $default, $only_positive) = @_; | ||||
|     for (;;) { | ||||
|  | @ -1264,6 +1281,7 @@ sub _get_number_from_user {     # XXX: Enrico | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub rotate { | ||||
|     my ($self, $angle, $axis, $relative_key, $axis_x, $axis_y, $axis_z) = @_; | ||||
|     $relative_key //= 'absolute'; # relative or absolute coordinates | ||||
|  | @ -1334,6 +1352,7 @@ sub rotate { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub mirror { | ||||
|     my ($self, $axis) = @_; | ||||
|      | ||||
|  | @ -1363,6 +1382,7 @@ sub mirror { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub changescale { | ||||
|     my ($self, $axis, $tosize) = @_; | ||||
|      | ||||
|  | @ -1437,6 +1457,7 @@ sub changescale { | |||
|     $self->update; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub arrange { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -1454,6 +1475,7 @@ sub arrange { | |||
|     $self->update(0); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub split_object { | ||||
|     my $self = shift; | ||||
|      | ||||
|  | @ -1485,6 +1507,7 @@ sub split_object { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Trigger $self->async_apply_config() after 500ms. | ||||
| # The call is delayed to avoid restarting the background processing during typing into an edit field. | ||||
| sub schedule_background_process { | ||||
|  | @ -1492,6 +1515,7 @@ sub schedule_background_process { | |||
|     $self->{apply_config_timer}->Start(0.5 * 1000, 1);  # 1 = one shot, every half a second. | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Executed asynchronously by a timer every PROCESS_DELAY (0.5 second). | ||||
| # The timer is started by schedule_background_process(),  | ||||
| sub async_apply_config { | ||||
|  | @ -1526,6 +1550,7 @@ sub async_apply_config { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Background processing is started either by the "Slice now" button, by the "Export G-code button" or by async_apply_config(). | ||||
| sub start_background_process { | ||||
|     my ($self) = @_; | ||||
|  | @ -1546,6 +1571,7 @@ sub start_background_process { | |||
|     $self->{background_slicing_process}->start; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Stop the background processing | ||||
| sub stop_background_process { | ||||
|     my ($self) = @_; | ||||
|  | @ -1554,6 +1580,7 @@ sub stop_background_process { | |||
| #    $self->{preview3D}->reload_print if $self->{preview3D}; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Called by the "Slice now" button, which is visible only if the background processing is disabled. | ||||
| sub reslice { | ||||
|     # explicitly cancel a previous thread and start a new one. | ||||
|  | @ -1574,6 +1601,7 @@ sub reslice { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub export_gcode { | ||||
|     my ($self, $output_file) = @_; | ||||
|      | ||||
|  | @ -1654,6 +1682,7 @@ sub export_gcode { | |||
|     return $self->{export_gcode_output_file}; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # This message should be called by the background process synchronously. | ||||
| sub on_update_print_preview { | ||||
|     my ($self) = @_; | ||||
|  | @ -1666,6 +1695,7 @@ sub on_update_print_preview { | |||
|     Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # This gets called also if we have no threads. | ||||
| sub on_progress_event { | ||||
|     my ($self, $percent, $message) = @_; | ||||
|  | @ -1676,6 +1706,7 @@ sub on_progress_event { | |||
|     $self->statusbar->SetStatusText("$message..."); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Called when the G-code export finishes, either successfully or with an error. | ||||
| # This gets called also if we don't have threads. | ||||
| sub on_process_completed { | ||||
|  | @ -1743,6 +1774,7 @@ sub on_process_completed { | |||
| #    $self->{preview3D}->reload_print if $self->{preview3D}; | ||||
| } | ||||
| 
 | ||||
| # XXX: partially done in the Sidebar | ||||
| # Fill in the "Sliced info" box with the result of the G-code generator. | ||||
| sub print_info_box_show { | ||||
|     my ($self, $show) = @_; | ||||
|  | @ -1819,6 +1851,7 @@ sub print_info_box_show { | |||
|     $panel->Refresh; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done - to be removed | ||||
| sub do_print { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -1832,6 +1865,7 @@ sub do_print { | |||
|     $printer_panel->load_print_job($self->{print_file}, $filament_stats); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub export_stl { | ||||
|     my ($self) = @_; | ||||
|     return if !@{$self->{objects}}; | ||||
|  | @ -1842,6 +1876,7 @@ sub export_stl { | |||
|     $self->statusbar->SetStatusText(L("STL file exported to ").$output_file); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub reload_from_disk { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -1873,6 +1908,7 @@ sub reload_from_disk { | |||
|     $self->remove($obj_idx); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub export_object_stl { | ||||
|     my ($self) = @_; | ||||
|     my ($obj_idx, $object) = $self->selected_object; | ||||
|  | @ -1884,6 +1920,7 @@ sub export_object_stl { | |||
|     $self->statusbar->SetStatusText(L("STL file exported to ").$output_file); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub fix_through_netfabb { | ||||
|     my ($self) = @_; | ||||
|     my ($obj_idx, $object) = $self->selected_object; | ||||
|  | @ -1912,6 +1949,7 @@ sub fix_through_netfabb { | |||
|     $self->remove($obj_idx); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub export_amf { | ||||
|     my ($self) = @_; | ||||
|     return if !@{$self->{objects}}; | ||||
|  | @ -1928,6 +1966,7 @@ sub export_amf { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub export_3mf { | ||||
|     my ($self) = @_; | ||||
|     return if !@{$self->{objects}}; | ||||
|  | @ -1944,6 +1983,7 @@ sub export_3mf { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| # Ask user to select an output file for a given file format (STl, AMF, 3MF). | ||||
| # Propose a default file name based on the 'output_filename_format' configuration value. | ||||
| sub _get_export_file { | ||||
|  | @ -1993,6 +2033,7 @@ sub _get_export_file { | |||
| #    $self->{objects}[$obj_idx]->thumbnail(undef); | ||||
| #} | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| # this method gets called whenever print center is changed or the objects' bounding box changes | ||||
| # (i.e. when an object is added/removed/moved/rotated/scaled) | ||||
| sub update { | ||||
|  | @ -2016,6 +2057,7 @@ sub update { | |||
|     $self->Thaw; | ||||
| } | ||||
| 
 | ||||
| # XXX: done in sidebar? | ||||
| # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. | ||||
| sub show_preset_comboboxes{ | ||||
|     my ($self, $showSLA) = @_; #if showSLA is oposite value to "ptFFF" | ||||
|  | @ -2034,6 +2076,7 @@ sub show_preset_comboboxes{ | |||
|     $self->Layout; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. | ||||
| # Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly | ||||
| # and some reasonable default has to be selected for the additional extruders. | ||||
|  | @ -2078,6 +2121,7 @@ sub on_extruders_change { | |||
|     $self->Layout; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub on_config_change { | ||||
|     my ($self, $config) = @_; | ||||
|      | ||||
|  | @ -2144,6 +2188,7 @@ sub on_config_change { | |||
|     $self->schedule_background_process; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub item_changed_selection { | ||||
|     my ($self, $obj_idx) = @_; | ||||
| 
 | ||||
|  | @ -2159,6 +2204,7 @@ sub item_changed_selection { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub collect_selections { | ||||
|     my ($self) = @_; | ||||
|     my $selections = []; | ||||
|  | @ -2168,6 +2214,7 @@ sub collect_selections { | |||
|     return $selections; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Called when clicked on the filament preset combo box. | ||||
| # When clicked on the icon, show the color picker. | ||||
| sub filament_color_box_lmouse_down | ||||
|  | @ -2221,6 +2268,7 @@ sub filament_color_box_lmouse_down | |||
| #	} | ||||
| #} | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub changed_object_settings { | ||||
|     my ($self, $obj_idx, $parts_changed, $part_settings_changed) = @_; | ||||
|      | ||||
|  | @ -2246,6 +2294,7 @@ sub changed_object_settings { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| # Called to update various buttons depending on whether there are any objects or | ||||
| # whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active. | ||||
| sub object_list_changed { | ||||
|  | @ -2276,6 +2325,7 @@ sub object_list_changed { | |||
|         for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: WIP | ||||
| # Selection of an active 3D object changed. | ||||
| sub selection_changed { | ||||
|     my ($self) = @_; | ||||
|  | @ -2393,6 +2443,7 @@ sub selection_changed { | |||
|     $self->{right_panel}->Thaw; | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub select_object { | ||||
|     my ($self, $obj_idx, $child) = @_; | ||||
| 
 | ||||
|  | @ -2413,6 +2464,7 @@ sub select_object { | |||
|     $self->selection_changed(1); | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| sub select_object_from_cpp { | ||||
|     my ($self, $obj_idx, $vol_idx) = @_; | ||||
|      | ||||
|  | @ -2457,16 +2509,19 @@ sub select_object_from_cpp { | |||
|     $self->selection_changed(1); | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub selected_object { | ||||
|     my ($self) = @_; | ||||
|     my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} }; | ||||
|     return defined $obj_idx ? ($obj_idx, $self->{objects}[$obj_idx]) : undef; | ||||
| } | ||||
| 
 | ||||
| # XXX: VK: done | ||||
| sub statusbar { | ||||
|     return $_[0]->GetFrame->{statusbar}; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done, to be removed (?) | ||||
| sub object_menu { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -2577,6 +2632,7 @@ sub object_menu { | |||
|     return $menu; | ||||
| } | ||||
| 
 | ||||
| # XXX: not done | ||||
| # Set a camera direction, zoom to all objects. | ||||
| sub select_view { | ||||
|     my ($self, $direction) = @_; | ||||
|  | @ -2594,6 +2650,8 @@ sub select_view { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # XXX: VK: done, in PlaterDropTarget | ||||
| package Slic3r::GUI::Plater::DropTarget; | ||||
| use Wx::DND; | ||||
| use base 'Wx::FileDropTarget'; | ||||
|  |  | |||
|  | @ -1350,7 +1350,7 @@ namespace Slic3r { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         m_curr_config.volume_id = object->second.volumes.size(); | ||||
|         m_curr_config.volume_id = (int)object->second.volumes.size(); | ||||
| 
 | ||||
|         unsigned int first_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, FIRST_TRIANGLE_ID_ATTR); | ||||
|         unsigned int last_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, LAST_TRIANGLE_ID_ATTR); | ||||
|  | @ -1408,7 +1408,7 @@ namespace Slic3r { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         unsigned int geo_tri_count = geometry.triangles.size() / 3; | ||||
|         unsigned int geo_tri_count = (unsigned int)geometry.triangles.size() / 3; | ||||
| 
 | ||||
|         for (const ObjectMetadata::VolumeMetadata& volume_data : volumes) | ||||
|         { | ||||
|  | @ -1429,7 +1429,7 @@ namespace Slic3r { | |||
| 
 | ||||
|             unsigned int src_start_id = volume_data.first_triangle_id * 3; | ||||
| 
 | ||||
|             for (size_t i = 0; i < triangles_count; ++i) | ||||
|             for (unsigned int i = 0; i < triangles_count; ++i) | ||||
|             { | ||||
|                 unsigned int ii = i * 3; | ||||
|                 stl_facet& facet = stl.facet_start[i]; | ||||
|  |  | |||
|  | @ -911,7 +911,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c | |||
|             if (volume->is_modifier()) | ||||
|                 stream << "        <metadata type=\"slic3r.modifier\">1</metadata>\n"; | ||||
|             stream << "        <metadata type=\"slic3r.volume_type\">" << ModelVolume::type_to_string(volume->type()) << "</metadata>\n"; | ||||
|             for (int i = 0; i < volume->mesh.stl.stats.number_of_facets; ++i) { | ||||
|             for (int i = 0; i < (int)volume->mesh.stl.stats.number_of_facets; ++i) { | ||||
|                 stream << "        <triangle>\n"; | ||||
|                 for (int j = 0; j < 3; ++j) | ||||
|                 stream << "          <v" << j + 1 << ">" << volume->mesh.stl.v_indices[i].vertex[j] + vertices_offset << "</v" << j + 1 << ">\n"; | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ static_assert(sizeof(StlHeader) == 84, "StlHeader size not correct"); | |||
| class LineReader | ||||
| { | ||||
| public: | ||||
|     LineReader(std::vector<char> &data) : m_buffer(data), m_pos(0), m_len(data.size()) {} | ||||
|     LineReader(std::vector<char> &data) : m_buffer(data), m_pos(0), m_len((int)data.size()) {} | ||||
| 
 | ||||
|     const char* next_line() { | ||||
|         // Skip empty lines.
 | ||||
|  | @ -154,7 +154,7 @@ static void extract_model_from_archive( | |||
| #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM | ||||
|             instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2])); | ||||
|             // CHECK_ME -> Is the following correct ?
 | ||||
|             trafo[2][3] = position[2] / instance_scaling_factor(2); | ||||
|             trafo[2][3] = position[2] / (float)instance_scaling_factor(2); | ||||
| #else | ||||
|             instance_offset(0) = position[0] - zero[0]; | ||||
|             instance_offset(1) = position[1] - zero[1]; | ||||
|  | @ -291,8 +291,8 @@ static void extract_model_from_archive( | |||
|         if (! facets.empty() && solid_name.empty()) { | ||||
|             stl_file &stl = mesh.stl; | ||||
|             stl.stats.type = inmemory; | ||||
|             stl.stats.number_of_facets = facets.size(); | ||||
|             stl.stats.original_num_facets = facets.size(); | ||||
|             stl.stats.number_of_facets = (uint32_t)facets.size(); | ||||
|             stl.stats.original_num_facets = (int)facets.size(); | ||||
|             stl_allocate(&stl); | ||||
|             memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50); | ||||
|             stl_get_size(&stl); | ||||
|  |  | |||
|  | @ -698,7 +698,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ | |||
| 
 | ||||
|             // update current values
 | ||||
|             data = move.data; | ||||
|             z = move.start_position.z(); | ||||
|             z = (float)move.start_position.z(); | ||||
|             volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm; | ||||
|             height_range.update_from(move.data.height); | ||||
|             width_range.update_from(move.data.width); | ||||
|  |  | |||
|  | @ -484,14 +484,14 @@ namespace Slic3r { | |||
|     { | ||||
|         _state.filament_load_times.clear(); | ||||
|         for (double t : filament_load_times) | ||||
|             _state.filament_load_times.push_back(t); | ||||
|             _state.filament_load_times.push_back((float)t); | ||||
|     } | ||||
| 
 | ||||
|     void GCodeTimeEstimator::set_filament_unload_times(const std::vector<double> &filament_unload_times) | ||||
|     { | ||||
|         _state.filament_unload_times.clear(); | ||||
|         for (double t : filament_unload_times) | ||||
|             _state.filament_unload_times.push_back(t); | ||||
|             _state.filament_unload_times.push_back((float)t); | ||||
|     } | ||||
| 
 | ||||
|     float GCodeTimeEstimator::get_filament_load_time(unsigned int id_extruder) | ||||
|  | @ -731,7 +731,7 @@ namespace Slic3r { | |||
| #endif // ENABLE_MOVE_STATS
 | ||||
|         } | ||||
| 
 | ||||
|         _last_st_synchronized_block_id = _blocks.size() - 1; | ||||
|         _last_st_synchronized_block_id = (int)_blocks.size() - 1; | ||||
|         // The additional time has been consumed (added to the total time), reset it to zero.
 | ||||
|         set_additional_time(0.); | ||||
|     } | ||||
|  |  | |||
|  | @ -707,16 +707,23 @@ void ModelObject::center_around_origin() | |||
|         if (v->is_model_part()) | ||||
| 			bb.merge(v->mesh.bounding_box()); | ||||
|      | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     // Shift is the vector from the center of the bounding box to the origin
 | ||||
|     Vec3d shift = -bb.center(); | ||||
| #else | ||||
|     // Shift is the vector from the center of the bottom face of the bounding box to the origin
 | ||||
|     Vec3d shift = -bb.center(); | ||||
|     shift(2) = -bb.min(2); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     this->translate(shift); | ||||
|     this->origin_translation += shift; | ||||
| 
 | ||||
| #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     // set z to zero, translation in z has already been done within the mesh
 | ||||
|     shift(2) = 0.0; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
 | ||||
| 
 | ||||
|     if (!this->instances.empty()) { | ||||
|  |  | |||
|  | @ -56,10 +56,10 @@ inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); } | |||
| inline Vec2f   to_2d(const Vec3f   &pt3) { return Vec2f  (pt3(0), pt3(1)); } | ||||
| inline Vec2d   to_2d(const Vec3d   &pt3) { return Vec2d  (pt3(0), pt3(1)); } | ||||
| 
 | ||||
| // inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); }
 | ||||
| // inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); }
 | ||||
| // inline Vec3f   to_3d(const Vec2f   &pt2, float z)   { return Vec3f  (pt2(0), pt2(1), z); }
 | ||||
| // inline Vec3d   to_3d(const Vec2d   &pt2, double z)  { return Vec3d  (pt2(0), pt2(1), z); }
 | ||||
| inline Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); } | ||||
| inline Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); } | ||||
| inline Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); } | ||||
| inline Vec3crd to_3d(const Vec3crd &p, coord_t z) { return Vec3crd(p(0), p(1), z); } | ||||
| 
 | ||||
| inline Vec2d   unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); } | ||||
| inline Vec2d   unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); } | ||||
|  |  | |||
|  | @ -419,6 +419,7 @@ public: | |||
|     const PrintObject*          get_object(int idx) const { return m_objects[idx]; } | ||||
|     const PrintRegionPtrs&      regions() const { return m_regions; } | ||||
|     const PlaceholderParser&    placeholder_parser() const { return m_placeholder_parser; } | ||||
|     PlaceholderParser&          placeholder_parser() { return m_placeholder_parser; } | ||||
| 
 | ||||
|     // Returns extruder this eec should be printed with, according to PrintRegion config:
 | ||||
|     static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion); | ||||
|  |  | |||
|  | @ -5,13 +5,15 @@ | |||
| #define ENABLE_1_42_0 1 | ||||
| 
 | ||||
| // Add z coordinate to model instances' offset
 | ||||
| // Add x and y rotation components to model instances' offset
 | ||||
| // Add x and y rotation components to model instances' rotation
 | ||||
| // Add scaling factors for all the three axes to model instances
 | ||||
| #define ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM (1 && ENABLE_1_42_0) | ||||
| // Add double click on gizmo grabbers to reset transformation components to their default value
 | ||||
| #define ENABLE_GIZMOS_RESET (1 && ENABLE_1_42_0) | ||||
| // Uses a unique opengl context
 | ||||
| #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) | ||||
| // New selections
 | ||||
| #define ENABLE_EXTENDED_SELECTION (0 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM) | ||||
| 
 | ||||
| #endif // _technologies_h_
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,6 +39,8 @@ add_library(libslic3r_gui STATIC | |||
|     ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp | ||||
|     ${LIBDIR}/slic3r/GUI/GUI_App.cpp | ||||
|     ${LIBDIR}/slic3r/GUI/GUI_App.hpp | ||||
|     ${LIBDIR}/slic3r/GUI/GUI_Utils.cpp | ||||
|     ${LIBDIR}/slic3r/GUI/GUI_Utils.hpp | ||||
|     ${LIBDIR}/slic3r/GUI/MainFrame.cpp | ||||
|     ${LIBDIR}/slic3r/GUI/MainFrame.hpp | ||||
|     ${LIBDIR}/slic3r/GUI/Plater.cpp | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) | |||
| 
 | ||||
|     this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count()); | ||||
|      | ||||
|     for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) { | ||||
|     for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) { | ||||
|         const stl_facet &facet = mesh.stl.facet_start[i]; | ||||
|         for (int j = 0; j < 3; ++ j) | ||||
|             this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); | ||||
|  | @ -52,7 +52,7 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh) | |||
|     this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count()); | ||||
| 
 | ||||
|     unsigned int vertices_count = 0; | ||||
|     for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) { | ||||
|     for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) { | ||||
|         const stl_facet &facet = mesh.stl.facet_start[i]; | ||||
|         for (int j = 0; j < 3; ++j) | ||||
|             this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); | ||||
|  | @ -209,8 +209,10 @@ GLVolume::GLVolume(float r, float g, float b, float a) | |||
|     , m_transformed_convex_hull_bounding_box_dirty(true) | ||||
|     , m_convex_hull(nullptr) | ||||
|     , composite_id(-1) | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     , select_group_id(-1) | ||||
|     , drag_group_id(-1) | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     , extruder_id(0) | ||||
|     , selected(false) | ||||
|     , is_active(true) | ||||
|  | @ -242,7 +244,7 @@ void GLVolume::set_render_color(float r, float g, float b, float a) | |||
| void GLVolume::set_render_color(const float* rgba, unsigned int size) | ||||
| { | ||||
|     size = std::min((unsigned int)4, size); | ||||
|     for (int i = 0; i < size; ++i) | ||||
|     for (unsigned int i = 0; i < size; ++i) | ||||
|     { | ||||
|         render_color[i] = rgba[i]; | ||||
|     } | ||||
|  | @ -311,6 +313,13 @@ void GLVolume::set_offset(const Vec3d& offset) | |||
| } | ||||
| 
 | ||||
| #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| const Vec3d& GLVolume::get_scaling_factor() const | ||||
| { | ||||
|     return m_scaling_factor; | ||||
| } | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| void GLVolume::set_scaling_factor(const Vec3d& scaling_factor) | ||||
| { | ||||
|     if (m_scaling_factor != scaling_factor) | ||||
|  | @ -339,6 +348,7 @@ void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) | |||
|     m_convex_hull = &convex_hull; | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void GLVolume::set_select_group_id(const std::string& select_by) | ||||
| { | ||||
|     if (select_by == "object") | ||||
|  | @ -356,6 +366,7 @@ void GLVolume::set_drag_group_id(const std::string& drag_by) | |||
|     else if (drag_by == "instance") | ||||
|         drag_group_id = object_idx() * 1000 + instance_idx(); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| const Transform3f& GLVolume::world_matrix() const | ||||
| { | ||||
|  | @ -682,6 +693,14 @@ void GLVolume::generate_layer_height_texture(const PrintObject *print_object, bo | |||
| #define LAYER_HEIGHT_TEXTURE_WIDTH  1024 | ||||
| #define LAYER_HEIGHT_TEXTURE_HEIGHT 1024 | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| std::vector<int> GLVolumeCollection::load_object( | ||||
|     const ModelObject       *model_object, | ||||
|     int                      obj_idx, | ||||
|     const std::vector<int>  &instance_idxs, | ||||
|     const std::string       &color_by, | ||||
|     bool                     use_VBOs) | ||||
| #else | ||||
| std::vector<int> GLVolumeCollection::load_object( | ||||
|     const ModelObject       *model_object,  | ||||
|     int                      obj_idx, | ||||
|  | @ -690,6 +709,7 @@ std::vector<int> GLVolumeCollection::load_object( | |||
|     const std::string       &select_by, | ||||
|     const std::string       &drag_by, | ||||
|     bool                     use_VBOs) | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| { | ||||
|     static float colors[4][4] = { | ||||
|         { 1.0f, 1.0f, 0.0f, 1.f },  | ||||
|  | @ -740,8 +760,10 @@ std::vector<int> GLVolumeCollection::load_object( | |||
|             v.bounding_box = v.indexed_vertex_array.bounding_box(); | ||||
|             v.indexed_vertex_array.finalize_geometry(use_VBOs); | ||||
|             v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|             v.set_select_group_id(select_by); | ||||
|             v.set_drag_group_id(drag_by); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|             if (model_volume->is_model_part()) | ||||
|             { | ||||
|                 v.set_convex_hull(model_volume->get_convex_hull()); | ||||
|  | @ -789,9 +811,9 @@ int GLVolumeCollection::load_wipe_tower_preview( | |||
|         // edge has y=0 and centerline of the back edge has y=depth:
 | ||||
|         Pointf3s points; | ||||
|         std::vector<Vec3crd> facets; | ||||
|         float out_points_idx[][3] = {{0, -depth, 0}, {0, 0, 0}, {38.453, 0, 0}, {61.547, 0, 0}, {100, 0, 0}, {100, -depth, 0}, {55.7735, -10, 0}, {44.2265, 10, 0}, | ||||
|                                      {38.453, 0, 1}, {0, 0, 1}, {0, -depth, 1}, {100, -depth, 1}, {100, 0, 1}, {61.547, 0, 1}, {55.7735, -10, 1}, {44.2265, 10, 1}}; | ||||
|         int out_facets_idx[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 5, 0}, {3, 5, 6}, {6, 2, 7}, {6, 0, 2}, {8, 9, 10}, {11, 12, 13}, {10, 11, 14}, {14, 11, 13}, {15, 8, 14}, | ||||
|         float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 }, | ||||
|         { 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } }; | ||||
|         int out_facets_idx[][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 5, 0 }, { 3, 5, 6 }, { 6, 2, 7 }, { 6, 0, 2 }, { 8, 9, 10 }, { 11, 12, 13 }, { 10, 11, 14 }, { 14, 11, 13 }, { 15, 8, 14 }, | ||||
|                                    {8, 10, 14}, {3, 12, 4}, {3, 13, 12}, {6, 13, 3}, {6, 14, 13}, {7, 14, 6}, {7, 15, 14}, {2, 15, 7}, {2, 8, 15}, {1, 8, 2}, {1, 9, 8}, | ||||
|                                    {0, 9, 1}, {0, 10, 9}, {5, 10, 0}, {5, 11, 10}, {4, 11, 5}, {4, 12, 11}}; | ||||
|         for (int i=0;i<16;++i) | ||||
|  | @ -834,8 +856,10 @@ int GLVolumeCollection::load_wipe_tower_preview( | |||
|     v.bounding_box = v.indexed_vertex_array.bounding_box(); | ||||
|     v.indexed_vertex_array.finalize_geometry(use_VBOs); | ||||
|     v.composite_id = obj_idx * 1000000; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     v.select_group_id = obj_idx * 1000000; | ||||
|     v.drag_group_id = obj_idx * 1000; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     v.is_wipe_tower = true; | ||||
|     v.shader_outside_printer_detection_enabled = ! size_unknown; | ||||
|     return int(this->volumes.size() - 1); | ||||
|  | @ -1017,7 +1041,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con | |||
|             continue; | ||||
| 
 | ||||
|         int extruder_id = volume->extruder_id - 1; | ||||
|         if ((extruder_id < 0) || ((unsigned int)colors.size() <= extruder_id)) | ||||
|         if ((extruder_id < 0) || ((int)colors.size() <= extruder_id)) | ||||
|             extruder_id = 0; | ||||
| 
 | ||||
|         const Color& color = colors[extruder_id]; | ||||
|  | @ -1031,6 +1055,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con | |||
|     } | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void GLVolumeCollection::set_select_by(const std::string& select_by) | ||||
| { | ||||
|     for (GLVolume *vol : this->volumes) | ||||
|  | @ -1048,6 +1073,7 @@ void GLVolumeCollection::set_drag_by(const std::string& drag_by) | |||
|             vol->set_drag_group_id(drag_by); | ||||
|     } | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| std::vector<double> GLVolumeCollection::get_current_print_zs(bool active_only) const | ||||
| { | ||||
|  | @ -1820,6 +1846,7 @@ void _3DScene::reset_volumes(wxGLCanvas* canvas) | |||
|     s_canvas_mgr.reset_volumes(canvas); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void _3DScene::deselect_volumes(wxGLCanvas* canvas) | ||||
| { | ||||
|     s_canvas_mgr.deselect_volumes(canvas); | ||||
|  | @ -1834,6 +1861,7 @@ void _3DScene::update_volumes_selection(wxGLCanvas* canvas, const std::vector<in | |||
| { | ||||
|     s_canvas_mgr.update_volumes_selection(canvas, selections); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| int _3DScene::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) | ||||
| { | ||||
|  | @ -1850,10 +1878,12 @@ bool _3DScene::move_volume_down(wxGLCanvas* canvas, unsigned int id) | |||
|     return s_canvas_mgr.move_volume_down(canvas, id); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void _3DScene::set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections) | ||||
| { | ||||
|     s_canvas_mgr.set_objects_selections(canvas, selections); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| void _3DScene::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) | ||||
| { | ||||
|  | @ -1900,6 +1930,7 @@ void _3DScene::set_color_by(wxGLCanvas* canvas, const std::string& value) | |||
|     s_canvas_mgr.set_color_by(canvas, value); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void _3DScene::set_select_by(wxGLCanvas* canvas, const std::string& value) | ||||
| { | ||||
|     s_canvas_mgr.set_select_by(canvas, value); | ||||
|  | @ -1914,6 +1945,7 @@ std::string _3DScene::get_select_by(wxGLCanvas* canvas) | |||
| { | ||||
|     return s_canvas_mgr.get_select_by(canvas); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| bool _3DScene::is_layers_editing_enabled(wxGLCanvas* canvas) | ||||
| { | ||||
|  |  | |||
|  | @ -292,10 +292,12 @@ public: | |||
|     float               render_color[4]; | ||||
|     // An ID containing the object ID, volume ID and instance ID.
 | ||||
|     int                 composite_id; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     // An ID for group selection. It may be the same for all meshes of all object instances, or for just a single object instance.
 | ||||
|     int                 select_group_id; | ||||
|     // An ID for group dragging. It may be the same for all meshes of all object instances, or for just a single object instance.
 | ||||
|     int                 drag_group_id; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     // An ID containing the extruder ID (used to select color).
 | ||||
|     int                 extruder_id; | ||||
|     // Is this object selected?
 | ||||
|  | @ -338,6 +340,9 @@ public: | |||
|     const Vec3d& get_rotation() const; | ||||
|     void set_rotation(const Vec3d& rotation); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     const Vec3d& get_scaling_factor() const; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     void set_scaling_factor(const Vec3d& scaling_factor); | ||||
| #else | ||||
|     double get_rotation() const; | ||||
|  | @ -351,8 +356,10 @@ public: | |||
| 
 | ||||
|     void set_convex_hull(const TriangleMesh& convex_hull); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_select_group_id(const std::string& select_by); | ||||
|     void set_drag_group_id(const std::string& drag_by); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     int                 object_idx() const { return this->composite_id / 1000000; } | ||||
|     int                 volume_idx() const { return (this->composite_id / 1000) % 1000; } | ||||
|  | @ -410,6 +417,10 @@ public: | |||
|     void reset_layer_height_texture_data() { layer_height_texture_data.reset(); } | ||||
| }; | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| typedef std::vector<GLVolume*> GLVolumePtrs; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| class GLVolumeCollection | ||||
| { | ||||
|     // min and max vertex of the print box volume
 | ||||
|  | @ -417,11 +428,23 @@ class GLVolumeCollection | |||
|     float print_box_max[3]; | ||||
| 
 | ||||
| public: | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     GLVolumePtrs volumes; | ||||
| #else | ||||
|     std::vector<GLVolume*> volumes; | ||||
|      | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     GLVolumeCollection() {}; | ||||
|     ~GLVolumeCollection() { clear(); }; | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     std::vector<int> load_object( | ||||
|         const ModelObject       *model_object, | ||||
|         int                      obj_idx, | ||||
|         const std::vector<int>  &instance_idxs, | ||||
|         const std::string       &color_by, | ||||
|         bool                     use_VBOs); | ||||
| #else | ||||
|     std::vector<int> load_object( | ||||
|         const ModelObject       *model_object, | ||||
|         int                      obj_idx, | ||||
|  | @ -430,6 +453,7 @@ public: | |||
|         const std::string       &select_by, | ||||
|         const std::string       &drag_by, | ||||
|         bool                     use_VBOs); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     int load_wipe_tower_preview( | ||||
|         int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width); | ||||
|  | @ -463,8 +487,10 @@ public: | |||
| 
 | ||||
|     void update_colors_by_extruder(const DynamicPrintConfig* config); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_select_by(const std::string& select_by); | ||||
|     void set_drag_by(const std::string& drag_by); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
 | ||||
|     std::vector<double> get_current_print_zs(bool active_only) const; | ||||
|  | @ -493,14 +519,18 @@ public: | |||
| 
 | ||||
|     static unsigned int get_volumes_count(wxGLCanvas* canvas); | ||||
|     static void reset_volumes(wxGLCanvas* canvas); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     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); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     static int 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); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     static void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); | ||||
|     static void set_print(wxGLCanvas* canvas, Print* print); | ||||
|  | @ -516,10 +546,12 @@ public: | |||
|     static void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons); | ||||
| 
 | ||||
|     static void set_color_by(wxGLCanvas* canvas, const std::string& value); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     static void set_select_by(wxGLCanvas* canvas, const std::string& value); | ||||
|     static void set_drag_by(wxGLCanvas* canvas, const std::string& value); | ||||
| 
 | ||||
|     static std::string get_select_by(wxGLCanvas* canvas); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     static bool is_layers_editing_enabled(wxGLCanvas* canvas); | ||||
|     static bool is_layers_editing_allowed(wxGLCanvas* canvas); | ||||
|  |  | |||
|  | @ -292,7 +292,7 @@ void BedShapePanel::update_shape() | |||
| void BedShapePanel::load_stl() | ||||
| { | ||||
| 	auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "", | ||||
| 		MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
| 		file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
| 	if (dialog->ShowModal() != wxID_OK) { | ||||
| 		dialog->Destroy(); | ||||
| 		return; | ||||
|  |  | |||
|  | @ -611,8 +611,9 @@ void ColourPicker::BUILD() | |||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	wxString clr(static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx)); | ||||
| 	// FIXME: verify clr is valid, otherwise this causes an assert
 | ||||
| 	auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); | ||||
| 		 | ||||
| 
 | ||||
| 	// 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -346,11 +346,15 @@ class GLCanvas3D | |||
| 
 | ||||
|             Point start_position_2D; | ||||
|             Vec3d start_position_3D; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|             Vec3d volume_center_offset; | ||||
| 
 | ||||
|             bool move_with_shift; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|             int move_volume_idx; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|             int gizmo_volume_idx; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|         public: | ||||
|             Drag(); | ||||
|  | @ -372,6 +376,104 @@ class GLCanvas3D | |||
|         bool is_start_position_3D_defined() const; | ||||
|     }; | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| public: | ||||
|     class Selection | ||||
|     { | ||||
|     public: | ||||
|         typedef std::set<unsigned int> IndicesList; | ||||
| 
 | ||||
|         enum EMode : unsigned char | ||||
|         { | ||||
|             Volume, | ||||
|             Instance, | ||||
|             Object | ||||
|         }; | ||||
| 
 | ||||
|     private: | ||||
|         struct VolumeCache | ||||
|         { | ||||
|         private: | ||||
|             Transform3d m_rotation_matrix; | ||||
| 
 | ||||
|         public: | ||||
|             Vec3d position; | ||||
|             Vec3d rotation; | ||||
|             Vec3d scaling_factor; | ||||
| 
 | ||||
|             VolumeCache(); | ||||
|             VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor); | ||||
| 
 | ||||
|             const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; } | ||||
|         }; | ||||
| 
 | ||||
|         typedef std::map<unsigned int, VolumeCache> VolumesCache; | ||||
| 
 | ||||
|         struct Cache | ||||
|         { | ||||
|             VolumesCache volumes_data; | ||||
|             Vec3d dragging_center; | ||||
|         }; | ||||
| 
 | ||||
|         GLVolumePtrs* m_volumes; | ||||
|         Model* m_model; | ||||
| 
 | ||||
|         bool m_valid; | ||||
|         EMode m_mode; | ||||
|         IndicesList m_list; | ||||
|         Cache m_cache; | ||||
|         mutable BoundingBoxf3 m_bounding_box; | ||||
|         mutable bool m_bounding_box_dirty; | ||||
| 
 | ||||
|     public: | ||||
|         Selection(); | ||||
| 
 | ||||
|         void set_volumes(GLVolumePtrs* volumes); | ||||
|         void set_model(Model* model); | ||||
| 
 | ||||
|         EMode get_mode() const { return m_mode; } | ||||
|         void set_mode(EMode mode) { m_mode = mode; } | ||||
| 
 | ||||
|         void add(unsigned int volume_idx, bool as_single_selection = true); | ||||
|         void remove(unsigned int volume_idx); | ||||
|         void clear(); | ||||
| 
 | ||||
|         bool is_empty() const { return m_list.empty(); } | ||||
|         bool is_wipe_tower() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_wipe_tower; } | ||||
|         bool is_modifier() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_modifier; } | ||||
|         bool is_single_full_instance(int& object_idx_out, int& instance_idx_out) const; | ||||
|         bool is_single_full_object(int& object_idx_out) const; | ||||
|         bool is_from_single_instance(int& object_idx_out, int& instance_idx_out) const; | ||||
|         bool is_from_single_object(int& object_idx_out) const; | ||||
| 
 | ||||
|         const IndicesList& get_volume_idxs() const { return m_list; } | ||||
|         const GLVolume* get_volume(unsigned int volume_idx) const; | ||||
| 
 | ||||
|         unsigned int volumes_count() const { return (unsigned int)m_list.size(); } | ||||
|         const BoundingBoxf3& get_bounding_box() const; | ||||
| 
 | ||||
|         void start_dragging(); | ||||
| 
 | ||||
|         void translate(const Vec3d& displacement); | ||||
| 
 | ||||
|         void render() const; | ||||
| 
 | ||||
|     private: | ||||
|         void update_valid(); | ||||
|         void set_caches(); | ||||
|         void add_volume(unsigned int volume_idx); | ||||
|         void add_instance(unsigned int volume_idx); | ||||
|         void add_object(unsigned int volume_idx); | ||||
|         void remove_volume(unsigned int volume_idx); | ||||
|         void remove_instance(unsigned int volume_idx); | ||||
|         void remove_object(unsigned int volume_idx); | ||||
|         void calc_bounding_box() const; | ||||
|         void render_bounding_box(const BoundingBoxf3& box, float* color) const; | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     class Gizmos | ||||
|     { | ||||
|         static const float OverlayTexturesScale; | ||||
|  | @ -404,11 +506,20 @@ class GLCanvas3D | |||
|         bool is_enabled() const; | ||||
|         void set_enabled(bool enable); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|         void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); | ||||
|         void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); | ||||
| #else | ||||
|         void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); | ||||
|         void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|         void reset_all_states(); | ||||
| 
 | ||||
|         void set_hover_id(int id); | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|         void enable_grabber(EType type, unsigned int id); | ||||
|         void disable_grabber(EType type, unsigned int id); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|         bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; | ||||
|         bool grabber_contains_mouse() const; | ||||
|  | @ -425,8 +536,12 @@ class GLCanvas3D | |||
|         void start_dragging(const BoundingBoxf3& box); | ||||
|         void stop_dragging(); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|         Vec3d get_displacement() const; | ||||
| #else | ||||
|         Vec3d get_position() const; | ||||
|         void set_position(const Vec3d& position); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM | ||||
|         Vec3d get_scale() const; | ||||
|  | @ -517,6 +632,9 @@ class GLCanvas3D | |||
|     mutable GLToolbar m_toolbar; | ||||
| 
 | ||||
|     mutable GLVolumeCollection m_volumes; | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     Selection m_selection; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     DynamicPrintConfig* m_config; | ||||
|     Print* m_print; | ||||
|     Model* m_model; | ||||
|  | @ -535,14 +653,21 @@ class GLCanvas3D | |||
|     bool m_shader_enabled; | ||||
|     bool m_dynamic_background_enabled; | ||||
|     bool m_multisample_allowed; | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     bool m_regenerate_volumes; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     std::string m_color_by; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     std::string m_select_by; | ||||
|     std::string m_drag_by; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     bool m_reload_delayed; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     std::vector<std::vector<int>> m_objects_volumes_idxs; | ||||
|     std::vector<int> m_objects_selections; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     GCodePreviewVolumeIndex m_gcode_preview_volume_index; | ||||
| 
 | ||||
|  | @ -568,19 +693,27 @@ public: | |||
| 
 | ||||
|     unsigned int get_volumes_count() const; | ||||
|     void reset_volumes(); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void deselect_volumes(); | ||||
|     void select_volume(unsigned int id); | ||||
|     void update_volumes_selection(const std::vector<int>& selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     int check_volumes_outside_state(const DynamicPrintConfig* config) const; | ||||
|     bool move_volume_up(unsigned int id); | ||||
|     bool move_volume_down(unsigned int id); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_objects_selections(const std::vector<int>& selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     void set_config(DynamicPrintConfig* config); | ||||
|     void set_print(Print* print); | ||||
|     void set_model(Model* model); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     const Selection& get_selection() const { return m_selection; } | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     // 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.
 | ||||
|  | @ -594,11 +727,13 @@ public: | |||
|     void set_cutting_plane(float z, const ExPolygons& polygons); | ||||
| 
 | ||||
|     void set_color_by(const std::string& value); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_select_by(const std::string& value); | ||||
|     void set_drag_by(const std::string& value); | ||||
| 
 | ||||
|     const std::string& get_select_by() const; | ||||
|     const std::string& get_drag_by() const; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     float get_camera_zoom() const; | ||||
| 
 | ||||
|  | @ -680,7 +815,9 @@ private: | |||
|     void _resize(unsigned int w, unsigned int h); | ||||
| 
 | ||||
|     BoundingBoxf3 _max_bounding_box() const; | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     BoundingBoxf3 _selected_volumes_bounding_box() const; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     void _zoom_to_bounding_box(const BoundingBoxf3& bbox); | ||||
|     float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const; | ||||
|  | @ -694,6 +831,9 @@ private: | |||
|     void _render_bed(float theta) const; | ||||
|     void _render_axes(bool depth_test) const; | ||||
|     void _render_objects() const; | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     void _render_selection() const; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     void _render_cutting_plane() const; | ||||
|     void _render_warning_texture() const; | ||||
|     void _render_legend_texture() const; | ||||
|  | @ -703,6 +843,10 @@ private: | |||
|     void _render_gizmos_overlay() const; | ||||
|     void _render_toolbar() const; | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     void _update_volumes_hover_state() const; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     float _get_layers_editing_cursor_z_relative() const; | ||||
|     void _perform_layer_editing_action(wxMouseEvent* evt = nullptr); | ||||
| 
 | ||||
|  | @ -719,8 +863,10 @@ private: | |||
|     void _start_timer(); | ||||
|     void _stop_timer(); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     int _get_first_selected_object_id() const; | ||||
|     int _get_first_selected_volume_id(int object_id) const; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     // Create 3D thick extrusion lines for a skirt and brim.
 | ||||
|     // Adds a new Slic3r::GUI::3DScene::Volume to volumes.
 | ||||
|  | @ -750,7 +896,11 @@ private: | |||
|     void _update_toolpath_volumes_outside_state(); | ||||
|     void _show_warning_texture_if_needed(); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     void _on_move(); | ||||
| #else | ||||
|     void _on_move(const std::vector<int>& volume_idxs); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     void _on_select(int volume_idx, int object_idx); | ||||
| 
 | ||||
|     // generates the legend texture in dependence of the current shown view type
 | ||||
|  |  | |||
|  | @ -246,6 +246,7 @@ void GLCanvas3DManager::reset_volumes(wxGLCanvas* canvas) | |||
|         it->second->reset_volumes(); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void GLCanvas3DManager::deselect_volumes(wxGLCanvas* canvas) | ||||
| { | ||||
|     CanvasesMap::iterator it = _get_canvas(canvas); | ||||
|  | @ -266,6 +267,7 @@ void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std:: | |||
|     if (it != m_canvases.end()) | ||||
|         it->second->update_volumes_selection(selections); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| int GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const | ||||
| { | ||||
|  | @ -285,12 +287,14 @@ bool GLCanvas3DManager::move_volume_down(wxGLCanvas* canvas, unsigned int id) | |||
|     return (it != m_canvases.end()) ? it->second->move_volume_down(id) : false; | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| 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); | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| void GLCanvas3DManager::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) | ||||
| { | ||||
|  | @ -354,6 +358,7 @@ void GLCanvas3DManager::set_color_by(wxGLCanvas* canvas, const std::string& valu | |||
|         it->second->set_color_by(value); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| void GLCanvas3DManager::set_select_by(wxGLCanvas* canvas, const std::string& value) | ||||
| { | ||||
|     CanvasesMap::iterator it = _get_canvas(canvas); | ||||
|  | @ -373,6 +378,7 @@ std::string GLCanvas3DManager::get_select_by(wxGLCanvas* canvas) const | |||
|     CanvasesMap::const_iterator it = _get_canvas(canvas); | ||||
|     return (it != m_canvases.end()) ? it->second->get_select_by() : ""; | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| bool GLCanvas3DManager::is_layers_editing_enabled(wxGLCanvas* canvas) const | ||||
| { | ||||
|  |  | |||
|  | @ -87,14 +87,18 @@ public: | |||
| 
 | ||||
|     unsigned int get_volumes_count(wxGLCanvas* canvas) const; | ||||
|     void reset_volumes(wxGLCanvas* canvas); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void deselect_volumes(wxGLCanvas* canvas); | ||||
|     void select_volume(wxGLCanvas* canvas, unsigned int id); | ||||
|     void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     int 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); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); | ||||
|     void set_print(wxGLCanvas* canvas, Print* print); | ||||
|  | @ -110,10 +114,12 @@ public: | |||
|     void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons); | ||||
| 
 | ||||
|     void set_color_by(wxGLCanvas* canvas, const std::string& value); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     void set_select_by(wxGLCanvas* canvas, const std::string& value); | ||||
|     void set_drag_by(wxGLCanvas* canvas, const std::string& value); | ||||
| 
 | ||||
|     std::string get_select_by(wxGLCanvas* canvas) const; | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     bool is_layers_editing_enabled(wxGLCanvas* canvas) const; | ||||
|     bool is_layers_editing_allowed(wxGLCanvas* canvas) const; | ||||
|  |  | |||
|  | @ -216,6 +216,9 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent) | |||
|     : m_parent(parent) | ||||
|     , m_group_id(-1) | ||||
|     , m_state(Off) | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     , m_accept_wipe_tower(false) | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     , m_hover_id(-1) | ||||
|     , m_dragging(false) | ||||
| { | ||||
|  | @ -1050,7 +1053,11 @@ const double GLGizmoMove3D::Offset = 10.0; | |||
| 
 | ||||
| GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent) | ||||
|     : GLGizmoBase(parent) | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     , m_displacement(Vec3d::Zero()) | ||||
| #else | ||||
|     , m_position(Vec3d::Zero()) | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     , m_starting_drag_position(Vec3d::Zero()) | ||||
|     , m_starting_box_center(Vec3d::Zero()) | ||||
|     , m_starting_box_bottom_center(Vec3d::Zero()) | ||||
|  | @ -1078,6 +1085,10 @@ bool GLGizmoMove3D::on_init() | |||
|         m_grabbers.push_back(Grabber()); | ||||
|     } | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     m_accept_wipe_tower = true; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -1085,6 +1096,9 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) | |||
| { | ||||
|     if (m_hover_id != -1) | ||||
|     { | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|         m_displacement = Vec3d::Zero(); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|         m_starting_drag_position = m_grabbers[m_hover_id].center; | ||||
|         m_starting_box_center = box.center(); | ||||
|         m_starting_box_bottom_center = box.center(); | ||||
|  | @ -1094,22 +1108,40 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) | |||
| 
 | ||||
| void GLGizmoMove3D::on_update(const Linef3& mouse_ray) | ||||
| { | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     if (m_hover_id == 0) | ||||
|         m_displacement(0) = calc_projection(X, 1, mouse_ray) - (m_starting_drag_position(0) - m_starting_box_center(0)); | ||||
|     else if (m_hover_id == 1) | ||||
|         m_displacement(1) = calc_projection(Y, 2, mouse_ray) - (m_starting_drag_position(1) - m_starting_box_center(1)); | ||||
|     else if (m_hover_id == 2) | ||||
|         m_displacement(2) = calc_projection(Z, 1, mouse_ray) - (m_starting_drag_position(2) - m_starting_box_bottom_center(2)); | ||||
| #else | ||||
|     if (m_hover_id == 0) | ||||
|         m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0); | ||||
|     else if (m_hover_id == 1) | ||||
|         m_position(1) = 2.0 * m_starting_box_center(1) + calc_projection(Y, 2, mouse_ray) - m_starting_drag_position(1); | ||||
|     else if (m_hover_id == 2) | ||||
|         m_position(2) = 2.0 * m_starting_box_bottom_center(2) + calc_projection(Z, 1, mouse_ray) - m_starting_drag_position(2); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| } | ||||
| 
 | ||||
| void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const | ||||
| { | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     if (m_grabbers[0].dragging) | ||||
|         set_tooltip("X: " + format(m_displacement(0), 2)); | ||||
|     else if (m_grabbers[1].dragging) | ||||
|         set_tooltip("Y: " + format(m_displacement(1), 2)); | ||||
|     else if (m_grabbers[2].dragging) | ||||
|         set_tooltip("Z: " + format(m_displacement(2), 2)); | ||||
| #else | ||||
|     if (m_grabbers[0].dragging) | ||||
|         set_tooltip("X: " + format(m_position(0), 2)); | ||||
|     else if (m_grabbers[1].dragging) | ||||
|         set_tooltip("Y: " + format(m_position(1), 2)); | ||||
|     else if (m_grabbers[2].dragging) | ||||
|         set_tooltip("Z: " + format(m_position(2), 2)); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     ::glEnable(GL_DEPTH_TEST); | ||||
| 
 | ||||
|  |  | |||
|  | @ -56,6 +56,9 @@ protected: | |||
| 
 | ||||
|     int m_group_id; | ||||
|     EState m_state; | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     bool m_accept_wipe_tower; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     // 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; | ||||
|  | @ -77,6 +80,11 @@ public: | |||
|     EState get_state() const { return m_state; } | ||||
|     void set_state(EState state) { m_state = state; on_set_state(); } | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     bool get_accept_wipe_tower() { return m_accept_wipe_tower; } | ||||
|     void set_accept_wipe_tower(bool accept) { m_accept_wipe_tower = accept; } | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     unsigned int get_texture_id() const { return m_textures[m_state].get_id(); } | ||||
|     int get_textures_size() const { return m_textures[Off].get_width(); } | ||||
| 
 | ||||
|  | @ -318,7 +326,11 @@ class GLGizmoMove3D : public GLGizmoBase | |||
| { | ||||
|     static const double Offset; | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     Vec3d m_displacement; | ||||
| #else | ||||
|     Vec3d m_position; | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
|     Vec3d m_starting_drag_position; | ||||
|     Vec3d m_starting_box_center; | ||||
|     Vec3d m_starting_box_bottom_center; | ||||
|  | @ -326,8 +338,12 @@ class GLGizmoMove3D : public GLGizmoBase | |||
| public: | ||||
|     explicit GLGizmoMove3D(GLCanvas3D& parent); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     const Vec3d& get_displacement() const { return m_displacement; } | ||||
| #else | ||||
|     const Vec3d& get_position() const { return m_position; } | ||||
|     void set_position(const Vec3d& position) { m_position = position; } | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| protected: | ||||
|     virtual bool on_init(); | ||||
|  |  | |||
|  | @ -135,7 +135,7 @@ bool GLShader::load_from_file(const char* fragment_shader_filename, const char* | |||
|         return false; | ||||
| 
 | ||||
|     vs.seekg(0, vs.end); | ||||
|     int file_length = vs.tellg(); | ||||
|     int file_length = (int)vs.tellg(); | ||||
|     vs.seekg(0, vs.beg); | ||||
|     std::string vertex_shader(file_length, '\0'); | ||||
|     vs.read(const_cast<char*>(vertex_shader.data()), file_length); | ||||
|  | @ -149,7 +149,7 @@ bool GLShader::load_from_file(const char* fragment_shader_filename, const char* | |||
|         return false; | ||||
| 
 | ||||
|     fs.seekg(0, fs.end); | ||||
|     file_length = fs.tellg(); | ||||
|     file_length = (int)fs.tellg(); | ||||
|     fs.seekg(0, fs.beg); | ||||
|     std::string fragment_shader(file_length, '\0'); | ||||
|     fs.read(const_cast<char*>(fragment_shader.data()), file_length); | ||||
|  |  | |||
|  | @ -26,7 +26,9 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); | |||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| 
 | ||||
| GLToolbarItem::Data::Data() | ||||
|  |  | |||
|  | @ -26,7 +26,9 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); | |||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| class GLToolbarItem | ||||
| { | ||||
|  |  | |||
|  | @ -347,53 +347,6 @@ std::string into_u8(const wxString &str) | |||
| 	return std::string(buffer_utf8.data()); | ||||
| } | ||||
| 
 | ||||
| wxWindow* export_option_creator(wxWindow* parent) | ||||
| { | ||||
|     wxPanel* panel = new wxPanel(parent, -1); | ||||
|     wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
|     wxCheckBox* cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, L("Export print config")); | ||||
|     cbox->SetValue(true); | ||||
|     sizer->AddSpacer(5); | ||||
|     sizer->Add(cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); | ||||
|     panel->SetSizer(sizer); | ||||
|     sizer->SetSizeHints(panel); | ||||
|     return panel; | ||||
| } | ||||
| 
 | ||||
| void add_export_option(wxFileDialog* dlg, const std::string& format) | ||||
| { | ||||
|     if ((dlg != nullptr) && (format == "AMF") || (format == "3MF")) | ||||
|     { | ||||
|         if (dlg->SupportsExtraControl()) | ||||
|             dlg->SetExtraControlCreator(export_option_creator); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int get_export_option(wxFileDialog* dlg) | ||||
| { | ||||
|     if (dlg != nullptr) | ||||
|     { | ||||
|         wxWindow* wnd = dlg->GetExtraControl(); | ||||
|         if (wnd != nullptr) | ||||
|         { | ||||
|             wxPanel* panel = dynamic_cast<wxPanel*>(wnd); | ||||
|             if (panel != nullptr) | ||||
|             { | ||||
|                 wxWindow* child = panel->FindWindow(wxID_HIGHEST + 1); | ||||
|                 if (child != nullptr) | ||||
|                 { | ||||
|                     wxCheckBox* cbox = dynamic_cast<wxCheckBox*>(child); | ||||
|                     if (cbox != nullptr) | ||||
|                         return cbox->IsChecked() ? 1 : 0; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height) | ||||
| { | ||||
| 	const auto idx = wxDisplay::GetFromWindow(window); | ||||
|  |  | |||
|  | @ -102,9 +102,6 @@ std::string	into_u8(const wxString &str); | |||
| 
 | ||||
| // Callback to trigger a configuration update timer on the Plater.
 | ||||
| static PerlCallback g_on_request_update_callback; | ||||
|   | ||||
| void add_export_option(wxFileDialog* dlg, const std::string& format); | ||||
| int get_export_option(wxFileDialog* dlg); | ||||
| 
 | ||||
| // Returns the dimensions of the screen on which the main frame is displayed
 | ||||
| bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height); | ||||
|  |  | |||
|  | @ -34,6 +34,21 @@ | |||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| 
 | ||||
| const wxString file_wildcards[FT_SIZE] = { | ||||
|     /* FT_STL */   "STL files (*.stl)|*.stl;*.STL", | ||||
|     /* FT_OBJ */   "OBJ files (*.obj)|*.obj;*.OBJ", | ||||
|     /* FT_AMF */   "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML", | ||||
|     /* FT_3MF */   "3MF files (*.3mf)|*.3mf;*.3MF;", | ||||
|     /* FT_PRUSA */ "Prusa Control files (*.prusa)|*.prusa;*.PRUSA", | ||||
|     /* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC", | ||||
|     /* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA", | ||||
| 
 | ||||
|     /* FT_INI */   "INI files *.ini|*.ini;*.INI", | ||||
|     /* FT_SVG */   "SVG files *.svg|*.svg;*.SVG", | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } | ||||
| 
 | ||||
| IMPLEMENT_APP(GUI_App) | ||||
|  | @ -291,7 +306,7 @@ void GUI_App::open_model(wxWindow *parent, wxArrayString& input_files) | |||
|     auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(), | ||||
|         _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), | ||||
|         app_config->get_last_dir(), "", | ||||
|         MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); | ||||
|         file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); | ||||
|     if (dialog->ShowModal() != wxID_OK) { | ||||
|         dialog->Destroy(); | ||||
|         return; | ||||
|  |  | |||
|  | @ -25,26 +25,24 @@ class ModelObject; | |||
| 
 | ||||
| namespace GUI | ||||
| { | ||||
| // Map from an file_type name to full file wildcard name.
 | ||||
| const std::map<const std::string, const std::string> FILE_WILDCARDS{ | ||||
|     std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"), | ||||
|     std::make_pair("stl",   "STL files (*.stl)|*.stl;*.STL"), | ||||
|     std::make_pair("obj",   "OBJ files (*.obj)|*.obj;*.OBJ"), | ||||
|     std::make_pair("amf",   "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"), | ||||
|     std::make_pair("3mf",   "3MF files (*.3mf)|*.3mf;*.3MF;"), | ||||
|     std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"), | ||||
|     std::make_pair("ini",   "INI files *.ini|*.ini;*.INI"), | ||||
|     std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"), | ||||
|     std::make_pair("svg",   "SVG files *.svg|*.svg;*.SVG") | ||||
| 
 | ||||
| enum FileType | ||||
| { | ||||
|     FT_STL, | ||||
|     FT_OBJ, | ||||
|     FT_AMF, | ||||
|     FT_3MF, | ||||
|     FT_PRUSA, | ||||
|     FT_GCODE, | ||||
|     FT_MODEL, | ||||
| 
 | ||||
|     FT_INI, | ||||
|     FT_SVG, | ||||
| 
 | ||||
|     FT_SIZE, | ||||
| }; | ||||
| 
 | ||||
| const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") + | ||||
|     FILE_WILDCARDS.at("stl") + std::string("|") + | ||||
|     FILE_WILDCARDS.at("obj") + std::string("|") + | ||||
|     FILE_WILDCARDS.at("amf") + std::string("|") + | ||||
|     FILE_WILDCARDS.at("3mf") + std::string("|") + | ||||
|     FILE_WILDCARDS.at("prusa") }; | ||||
| 
 | ||||
| extern const wxString file_wildcards[FT_SIZE]; | ||||
| 
 | ||||
| enum ConfigMenuIDs { | ||||
|     ConfigMenuWizard, | ||||
|  |  | |||
|  | @ -510,7 +510,7 @@ void ObjectList::menu_item_add_generic(wxMenuItem* &menu, int id) { | |||
|         sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item))); | ||||
| 
 | ||||
| #ifndef __WXMSW__ | ||||
|     sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) { | ||||
|     sub_menu->Bind(wxEVT_MENU, [this, sub_menu](wxEvent &event) { | ||||
|         load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString()); | ||||
|     }); | ||||
| #endif //no __WXMSW__
 | ||||
|  | @ -632,7 +632,7 @@ wxMenu* ObjectList::create_add_settings_popupmenu(bool is_part) | |||
|         menu->Append(menu_item); | ||||
|     } | ||||
| #ifndef __WXMSW__ | ||||
|     menu->Bind(wxEVT_MENU, [menu, is_part](wxEvent &event) { | ||||
|     menu->Bind(wxEVT_MENU, [this, menu, is_part](wxEvent &event) { | ||||
|         get_settings_choice(menu, event.GetId(), is_part); | ||||
|     }); | ||||
| #endif //no __WXMSW__
 | ||||
|  | @ -1032,7 +1032,9 @@ void ObjectList::add_object_to_list(size_t obj_idx) | |||
|     auto model_object = (*m_objects)[obj_idx]; | ||||
|     wxString item_name = model_object->name; | ||||
|     auto item = m_objects_model->Add(item_name, model_object->instances.size()); | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     Select(item); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     // Add error icon if detected auto-repaire
 | ||||
|     auto stats = model_object->volumes[0]->mesh.stl.stats; | ||||
|  |  | |||
|  | @ -262,6 +262,51 @@ void ObjectManipulation::update_settings_list() | |||
|     parent->GetParent()->Layout(); | ||||
| } | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) | ||||
| { | ||||
|     int object_idx = -1; | ||||
|     int instance_idx = -1; | ||||
|     if (selection.is_single_full_instance(object_idx, instance_idx)) | ||||
|     { | ||||
|         // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
 | ||||
|         const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); | ||||
|         update_position_values(selection.get_volume(*idxs.begin())->get_offset()); | ||||
|         m_og->enable(); | ||||
|     } | ||||
|     else if (selection.is_wipe_tower()) | ||||
|     { | ||||
|         // the selection contains a single volume
 | ||||
|         const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); | ||||
|         update_position_values(selection.get_volume(*idxs.begin())->get_offset()); | ||||
|         m_og->enable(); | ||||
|     } | ||||
|     else if (selection.is_modifier()) | ||||
|     { | ||||
|         // the selection contains a single volume
 | ||||
|         const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); | ||||
|         update_position_values(selection.get_volume(*idxs.begin())->get_offset()); | ||||
|         m_og->enable(); | ||||
|     } | ||||
|     else | ||||
|         reset_settings_value(); | ||||
| } | ||||
| 
 | ||||
| void ObjectManipulation::reset_settings_value() | ||||
| { | ||||
|     m_og->set_value("position_x", 0); | ||||
|     m_og->set_value("position_y", 0); | ||||
|     m_og->set_value("position_z", 0); | ||||
|     m_og->set_value("scale_x", 0); | ||||
|     m_og->set_value("scale_y", 0); | ||||
|     m_og->set_value("scale_z", 0); | ||||
|     m_og->set_value("rotation_x", 0); | ||||
|     m_og->set_value("rotation_y", 0); | ||||
|     m_og->set_value("rotation_z", 0); | ||||
|     m_og->disable(); | ||||
| } | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| void ObjectManipulation::update_values() | ||||
| { | ||||
|     int selection = ol_selection(); | ||||
|  |  | |||
|  | @ -6,6 +6,9 @@ | |||
| #include <wx/panel.h> | ||||
| 
 | ||||
| #include "Preset.hpp" | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
| #include "GLCanvas3D.hpp" | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| class wxBoxSizer; | ||||
| 
 | ||||
|  | @ -44,6 +47,11 @@ public: | |||
|     int ol_selection(); | ||||
|     void update_settings_list(); | ||||
| 
 | ||||
| #if ENABLE_EXTENDED_SELECTION | ||||
|     void update_settings_value(const GLCanvas3D::Selection& selection); | ||||
|     void reset_settings_value(); | ||||
| #endif // ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
|     void update_values(); | ||||
|     // update position values displacements or "gizmos"
 | ||||
|     void update_position_values(); | ||||
|  |  | |||
							
								
								
									
										54
									
								
								src/slic3r/GUI/GUI_Utils.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/slic3r/GUI/GUI_Utils.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| #include "GUI_Utils.hpp" | ||||
| 
 | ||||
| #include <wx/sizer.h> | ||||
| #include <wx/panel.h> | ||||
| #include <wx/checkbox.h> | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| 
 | ||||
| CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, | ||||
| 	const wxString &checkbox_label, | ||||
|     bool checkbox_value, | ||||
|     const wxString &message, | ||||
|     const wxString &default_dir, | ||||
|     const wxString &default_file, | ||||
|     const wxString &wildcard, | ||||
|     long style, | ||||
|     const wxPoint &pos, | ||||
|     const wxSize &size, | ||||
|     const wxString &name | ||||
| ) | ||||
|     : wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name) | ||||
|     , cbox(nullptr) | ||||
| { | ||||
| 	if (checkbox_label.IsEmpty()) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* { | ||||
| 		wxPanel* panel = new wxPanel(parent, -1); | ||||
| 	    wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	    this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label); | ||||
| 	    this->cbox->SetValue(true); | ||||
| 	    sizer->AddSpacer(5); | ||||
| 	    sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); | ||||
| 	    panel->SetSizer(sizer); | ||||
| 	    sizer->SetSizeHints(panel); | ||||
| 
 | ||||
| 	    return panel; | ||||
| 	}; | ||||
| 
 | ||||
|     SetExtraControlCreator(*extra_control_creator.target<ExtraControlCreatorFunction>()); | ||||
| } | ||||
| 
 | ||||
| bool CheckboxFileDialog::get_checkbox_value() const | ||||
| { | ||||
| 	return this->cbox != nullptr ? cbox->IsChecked() : false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/slic3r/GUI/GUI_Utils.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/slic3r/GUI/GUI_Utils.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| #ifndef slic3r_GUI_Utils_hpp_ | ||||
| #define slic3r_GUI_Utils_hpp_ | ||||
| 
 | ||||
| #include <functional> | ||||
| 
 | ||||
| #include <wx/filedlg.h> | ||||
| 
 | ||||
| class wxCheckBox; | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| 
 | ||||
| class CheckboxFileDialog : public wxFileDialog | ||||
| { | ||||
| public: | ||||
|     CheckboxFileDialog(wxWindow *parent, | ||||
|         const wxString &checkbox_label, | ||||
|         bool checkbox_value, | ||||
|         const wxString &message = wxFileSelectorPromptStr, | ||||
|         const wxString &default_dir = wxEmptyString, | ||||
|         const wxString &default_file = wxEmptyString, | ||||
|         const wxString &wildcard = wxFileSelectorDefaultWildcardStr, | ||||
|         long style = wxFD_DEFAULT_STYLE, | ||||
|         const wxPoint &pos = wxDefaultPosition, | ||||
|         const wxSize &size = wxDefaultSize, | ||||
|         const wxString &name = wxFileDialogNameStr | ||||
|     ); | ||||
| 
 | ||||
|     bool get_checkbox_value() const; | ||||
| 
 | ||||
| private: | ||||
|     std::function<wxWindow*(wxWindow*)> extra_control_creator; | ||||
|     wxCheckBox *cbox; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| }} | ||||
| 
 | ||||
| #endif | ||||
|  | @ -441,7 +441,7 @@ void MainFrame::quick_slice(const int qs){ | |||
|     if (!(qs & qsReslice)) { | ||||
|         auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")), | ||||
|             wxGetApp().app_config->get_last_dir(), "", | ||||
|             MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|             file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|         if (dlg->ShowModal() != wxID_OK) { | ||||
|             dlg->Destroy(); | ||||
|             return; | ||||
|  | @ -500,7 +500,7 @@ void MainFrame::quick_slice(const int qs){ | |||
| //         output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /;
 | ||||
|         auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")), | ||||
|             wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file),  | ||||
|             qs & qsExportSVG ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"), | ||||
|             qs & qsExportSVG ? file_wildcards[FT_SVG] : file_wildcards[FT_GCODE], | ||||
|             wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|         if (dlg->ShowModal() != wxID_OK) { | ||||
|             dlg->Destroy(); | ||||
|  | @ -568,7 +568,7 @@ void MainFrame::repair_stl() | |||
|     { | ||||
|         auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")), | ||||
|             wxGetApp().app_config->get_last_dir(), "", | ||||
|             FILE_WILDCARDS.at("stl"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|             file_wildcards[FT_STL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|         if (dlg->ShowModal() != wxID_OK) { | ||||
|             dlg->Destroy(); | ||||
|             return; | ||||
|  | @ -582,7 +582,7 @@ void MainFrame::repair_stl() | |||
| //         output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ;
 | ||||
|         auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"),  | ||||
|                                         get_dir_name(output_file), get_base_name(output_file),  | ||||
|                                         FILE_WILDCARDS.at("obj"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|                                         file_wildcards[FT_OBJ], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|         if (dlg->ShowModal() != wxID_OK) { | ||||
|             dlg->Destroy(); | ||||
|             return /*undef*/; | ||||
|  | @ -612,7 +612,7 @@ void MainFrame::export_config() | |||
|     auto dlg = new wxFileDialog(this, _(L("Save configuration as:")), | ||||
|         !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), | ||||
|         !m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini", | ||||
|         FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|         file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|     wxString file; | ||||
|     if (dlg->ShowModal() == wxID_OK) | ||||
|         file = dlg->GetPath(); | ||||
|  | @ -664,7 +664,7 @@ void MainFrame::export_configbundle() | |||
|     auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")), | ||||
|         !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), | ||||
|         "Slic3r_config_bundle.ini", | ||||
|         FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|         file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|     wxString file; | ||||
|     if (dlg->ShowModal() == wxID_OK) | ||||
|         file = dlg->GetPath(); | ||||
|  | @ -688,7 +688,7 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re | |||
|     if (file.IsEmpty()) { | ||||
|         auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), | ||||
|             !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), | ||||
|             "config.ini", FILE_WILDCARDS.at("ini"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|             "config.ini", file_wildcards[FT_INI], wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|         if (dlg->ShowModal() != wxID_OK) | ||||
|             return; | ||||
|         file = dlg->GetPath(); | ||||
|  | @ -755,7 +755,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event) | |||
| 
 | ||||
|     // Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs.
 | ||||
|     auto presets = tab->get_presets(); | ||||
|     if (presets) { | ||||
|     if (m_plater != nullptr && presets != nullptr) { | ||||
|         auto reload_dependent_tabs = tab->get_dependent_tabs(); | ||||
| 
 | ||||
|         // FIXME: The preset type really should be a property of Tab instead
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <vector> | ||||
| #include <string> | ||||
| #include <regex> | ||||
| #include <boost/optional.hpp> | ||||
| #include <boost/filesystem/path.hpp> | ||||
| 
 | ||||
| #include <wx/sizer.h> | ||||
|  | @ -25,10 +26,14 @@ | |||
| #include "libslic3r/GCode/PreviewData.hpp" | ||||
| #include "libslic3r/Utils.hpp" | ||||
| #include "libslic3r/Polygon.hpp" | ||||
| #include "libslic3r/Format/STL.hpp" | ||||
| #include "libslic3r/Format/AMF.hpp" | ||||
| #include "libslic3r/Format/3mf.hpp" | ||||
| #include "GUI.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| #include "GUI_ObjectList.hpp" | ||||
| #include "GUI_ObjectManipulation.hpp" | ||||
| #include "GUI_Utils.hpp" | ||||
| #include "MainFrame.hpp" | ||||
| #include "3DScene.hpp" | ||||
| #include "GLCanvas3D.hpp" | ||||
|  | @ -43,6 +48,7 @@ | |||
| #include <wx/glcanvas.h>    // Needs to be last because reasons :-/
 | ||||
| #include "WipeTowerDialog.hpp" | ||||
| 
 | ||||
| using boost::optional; | ||||
| namespace fs = boost::filesystem; | ||||
| using Slic3r::_3DScene; | ||||
| using Slic3r::Preset; | ||||
|  | @ -340,7 +346,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : | |||
| 
 | ||||
| struct Sidebar::priv | ||||
| { | ||||
|     // Sidebar *q;      // PIMPL back pointer ("Q-Pointer")
 | ||||
|     Plater *plater; | ||||
| 
 | ||||
|     wxScrolledWindow *scrolled; | ||||
| 
 | ||||
|  | @ -363,6 +369,8 @@ struct Sidebar::priv | |||
|     // wxButton *btn_print;  // XXX: remove
 | ||||
|     wxButton *btn_send_gcode; | ||||
| 
 | ||||
|     priv(Plater *plater) : plater(plater) {} | ||||
| 
 | ||||
|     bool show_manifold_warning_icon = false; | ||||
|     bool show_print_info = false; | ||||
| }; | ||||
|  | @ -370,8 +378,8 @@ struct Sidebar::priv | |||
| 
 | ||||
| // Sidebar / public
 | ||||
| 
 | ||||
| Sidebar::Sidebar(wxWindow *parent) | ||||
|     : wxPanel(parent), p(new priv) | ||||
| Sidebar::Sidebar(Plater *parent) | ||||
|     : wxPanel(parent), p(new priv(parent)) | ||||
| { | ||||
|     p->scrolled = new wxScrolledWindow(this); | ||||
| 
 | ||||
|  | @ -460,6 +468,11 @@ Sidebar::Sidebar(wxWindow *parent) | |||
|     sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5); | ||||
|     sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20); | ||||
|     SetSizer(sizer); | ||||
| 
 | ||||
|     // Events
 | ||||
|     p->btn_export_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->export_gcode(); }); | ||||
|     p->btn_reslice->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->reslice(); }); | ||||
|     p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); }); | ||||
| } | ||||
| 
 | ||||
| Sidebar::~Sidebar() {} | ||||
|  | @ -558,6 +571,13 @@ void Sidebar::show_buttons(const bool show) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void Sidebar::enable_buttons(bool enable) | ||||
| { | ||||
|     p->btn_reslice->Enable(enable); | ||||
|     p->btn_export_gcode->Enable(enable); | ||||
|     p->btn_send_gcode->Enable(enable); | ||||
| } | ||||
| 
 | ||||
| // Plater::Object
 | ||||
| 
 | ||||
| struct PlaterObject | ||||
|  | @ -579,13 +599,28 @@ public: | |||
| 
 | ||||
| private: | ||||
|     Plater *plater; | ||||
| 
 | ||||
|     static const std::regex pattern_drop; | ||||
| }; | ||||
| 
 | ||||
| const std::regex PlaterDropTarget::pattern_drop("[.](stl|obj|amf|3mf|prusa)$", std::regex::icase); | ||||
| 
 | ||||
| bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) | ||||
| { | ||||
|     // TODO
 | ||||
|     // return false;
 | ||||
|     throw 0; | ||||
|     std::vector<fs::path> paths; | ||||
| 
 | ||||
|     for (const auto &filename : filenames) { | ||||
|         fs::path path(filename); | ||||
| 
 | ||||
|         if (std::regex_match(path.string(), pattern_drop)) { | ||||
|             paths.push_back(std::move(path)); | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     plater->load_files(paths); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| // Plater / private
 | ||||
|  | @ -603,8 +638,8 @@ struct Plater::priv | |||
|     Slic3r::GCodePreviewData gcode_preview_data; | ||||
|     std::vector<PlaterObject> objects; | ||||
| 
 | ||||
|     std::string export_gcode_output_file; | ||||
|     std::string send_gcode_file; | ||||
|     fs::path export_gcode_output_file; | ||||
|     fs::path send_gcode_file; | ||||
| 
 | ||||
|     // GUI elements
 | ||||
|     wxNotebook *notebook; | ||||
|  | @ -613,14 +648,15 @@ struct Plater::priv | |||
|     Preview *preview; | ||||
|     BackgroundSlicingProcess background_process; | ||||
| 
 | ||||
|     static const int gl_attrs[]; | ||||
|     static const std::regex pattern_bundle; | ||||
|     static const std::regex pattern_3mf; | ||||
|     static const std::regex pattern_zip_amf; | ||||
| 
 | ||||
|     priv(Plater *q, MainFrame *main_frame); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     std::vector<int> collect_selections(); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     void update(bool force_autocenter = false); | ||||
|     void update_ui_from_settings(); | ||||
|     ProgressStatusBar* statusbar(); | ||||
|  | @ -629,19 +665,47 @@ struct Plater::priv | |||
|     BoundingBox scaled_bed_shape_bb() const; | ||||
|     std::vector<size_t> load_files(const std::vector<fs::path> &input_files); | ||||
|     std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects); | ||||
|     std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type); | ||||
| 
 | ||||
|     void on_notebook_changed(wxBookCtrlEvent &); | ||||
|     void on_select_preset(wxCommandEvent &); | ||||
|     void on_update_print_preview(wxCommandEvent &); | ||||
|     void on_process_completed(wxCommandEvent &); | ||||
|     void select_object(optional<size_t> obj_idx); | ||||
|     optional<size_t> selected_object() const; | ||||
|     void selection_changed(); | ||||
|     void object_list_changed(); | ||||
| 
 | ||||
|     void remove(size_t obj_idx); | ||||
|     void reset(); | ||||
|     void increase(size_t num = 1); | ||||
|     void decrease(size_t num = 1); | ||||
| 
 | ||||
|     void on_notebook_changed(wxBookCtrlEvent&); | ||||
|     void on_select_preset(wxCommandEvent&); | ||||
|     void on_update_print_preview(wxCommandEvent&); | ||||
|     void on_process_completed(wxCommandEvent&); | ||||
|     void on_layer_editing_toggled(bool enable); | ||||
|     void on_action_add(SimpleEvent&); | ||||
| 
 | ||||
|     void on_viewport_changed(SimpleEvent& evt); | ||||
| 
 | ||||
|     void on_action_add(SimpleEvent&); | ||||
|     void on_action_arrange(SimpleEvent&); | ||||
|     void on_action_more(SimpleEvent&); | ||||
|     void on_action_fewer(SimpleEvent&); | ||||
|     void on_action_split(SimpleEvent&); | ||||
|     void on_action_cut(SimpleEvent&); | ||||
|     void on_action_settings(SimpleEvent&); | ||||
|     void on_action_layersediting(SimpleEvent&); | ||||
|     void on_action_selectbyparts(SimpleEvent&); | ||||
| 
 | ||||
|     void on_viewport_changed(SimpleEvent&); | ||||
|     void on_right_click(Vec2dEvent&); | ||||
|     void on_model_update(SimpleEvent&); | ||||
|     void on_remove_object(SimpleEvent&); | ||||
|     void on_arrange(SimpleEvent&); | ||||
|     void on_scale_uniformly(SimpleEvent&); | ||||
|     void on_instance_moves(SimpleEvent&); | ||||
|     void on_wipetower_moved(Vec3dEvent&); | ||||
|     void on_enable_action_buttons(Event<bool>&); | ||||
|     void on_update_geometry(Vec3dsEvent<2>&); | ||||
| }; | ||||
| 
 | ||||
| // TODO: multisample, see 3DScene.pm
 | ||||
| const int Plater::priv::gl_attrs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, 0}; | ||||
| const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); | ||||
| const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase); | ||||
| const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase); | ||||
|  | @ -674,8 +738,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : | |||
|     _3DScene::enable_picking(canvas3D, true); | ||||
|     _3DScene::enable_moving(canvas3D, true); | ||||
|     // XXX: more config from 3D.pm
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     _3DScene::set_select_by(canvas3D, "object"); | ||||
|     _3DScene::set_drag_by(canvas3D, "instance"); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     _3DScene::set_model(canvas3D, &model); | ||||
|     _3DScene::set_print(canvas3D, &print); | ||||
|     _3DScene::set_config(canvas3D, config); | ||||
|  | @ -714,18 +780,35 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : | |||
|     // Preset change event
 | ||||
|     sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); | ||||
| 
 | ||||
|     // Sidebar button events
 | ||||
|     sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(""); }); | ||||
|     sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); }); | ||||
|     sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { | ||||
|         this->send_gcode_file = this->q->export_gcode(""); | ||||
|     }); | ||||
| 
 | ||||
|     // 3DScene events:
 | ||||
|     // TODO: more
 | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, [](ObjectSelectEvent&) { /*TODO*/ }); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); | ||||
|     // canvas3D->Bind(EVT_GLCANVAS_DOUBLE_CLICK, [](SimpleEvent&) { });  // XXX: remove?
 | ||||
|     canvas3D->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, &priv::on_remove_object, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_ARRANGE, &priv::on_arrange, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event<int> &evt) { /*TODO: call rotate */ }); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, &priv::on_scale_uniformly, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [this](Event<int> &evt) { evt.data == 1 ? increase() : decrease(); }); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVES, &priv::on_instance_moves, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); | ||||
|     canvas3D->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this); | ||||
|     // 3DScene/Toolbar:
 | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, &priv::on_action_arrange, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_MORE, &priv::on_action_more, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_FEWER, &priv::on_action_fewer, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this); | ||||
|     canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this); | ||||
| 
 | ||||
|     // Preview events:
 | ||||
|     preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); | ||||
| 
 | ||||
|     q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); | ||||
|  | @ -738,6 +821,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : | |||
|     q->Layout(); | ||||
| } | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
| std::vector<int> Plater::priv::collect_selections() | ||||
| { | ||||
|     std::vector<int> res; | ||||
|  | @ -746,6 +830,7 @@ std::vector<int> Plater::priv::collect_selections() | |||
|     } | ||||
|     return res; | ||||
| } | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
| 
 | ||||
| void Plater::priv::update(bool force_autocenter) | ||||
| { | ||||
|  | @ -761,8 +846,10 @@ void Plater::priv::update(bool force_autocenter) | |||
|     // stop_background_process();   // TODO
 | ||||
|     print.reload_model_instances(); | ||||
| 
 | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|     const auto selections = collect_selections(); | ||||
|     _3DScene::set_objects_selections(canvas3D, selections); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|     _3DScene::reload_scene(canvas3D, false); | ||||
|     preview->reset_gcode_preview_data(); | ||||
|     preview->reload_print(); | ||||
|  | @ -805,7 +892,7 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const | |||
| 
 | ||||
| std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_files) | ||||
| { | ||||
|     if (input_files.size() < 1) { return std::vector<size_t>(); } | ||||
|     if (input_files.empty()) { return std::vector<size_t>(); } | ||||
| 
 | ||||
|     auto *nozzle_dmrs = config->opt<ConfigOptionFloats>("nozzle_diameter"); | ||||
| 
 | ||||
|  | @ -878,9 +965,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_ | |||
|         } | ||||
| 
 | ||||
|         if (one_by_one) { | ||||
|             // TODO:
 | ||||
|             // push @obj_idx, $self->load_model_objects(@{$model->objects});
 | ||||
|             // obj_idx.push_back(load_model_objects(model.objects);
 | ||||
|             auto loaded_idxs = load_model_objects(model.objects); | ||||
|             obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); | ||||
|         } else { | ||||
|  | @ -901,9 +985,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_ | |||
|             new_model->convert_multipart_object(nozzle_dmrs->values.size()); | ||||
|         } | ||||
| 
 | ||||
|         // TODO:
 | ||||
|         // push @obj_idx, $self->load_model_objects(@{$new_model->objects});
 | ||||
|         // obj_idx.push_back(load_model_objects(new_model->objects);
 | ||||
|         auto loaded_idxs = load_model_objects(model.objects); | ||||
|         obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); | ||||
|     } | ||||
|  | @ -914,18 +995,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_ | |||
|     return obj_idxs; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // TODO: move to Point.hpp
 | ||||
| Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); } | ||||
| Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); } | ||||
| Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); } | ||||
| Vec3crd to_3d(const Point &p, coord_t z) { return Vec3crd(p(0), p(1), z); } | ||||
| 
 | ||||
| std::vector<size_t>  Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) | ||||
| std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) | ||||
| { | ||||
|     const BoundingBoxf bed_shape = bed_shape_bb(); | ||||
|     const Vec3d bed_center = to_3d(bed_shape.center().cast<double>(), 0.0); | ||||
|     const Vec3d bed_size = to_3d(bed_shape.size().cast<double>(), 1.0); | ||||
|     const Vec3d bed_center = Slic3r::to_3d(bed_shape.center().cast<double>(), 0.0); | ||||
|     const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast<double>(), 1.0); | ||||
| 
 | ||||
|     bool need_arrange = false; | ||||
|     bool scaled_down = false; | ||||
|  | @ -937,7 +1011,7 @@ std::vector<size_t>  Plater::priv::load_model_objects(const ModelObjectPtrs &mod | |||
|         objects.emplace_back(std::move(object_name)); | ||||
|         obj_idxs.push_back(objects.size() - 1); | ||||
| 
 | ||||
|         if (model_object->instances.size() == 0) { | ||||
|         if (model_object->instances.empty()) { | ||||
|             // if object has no defined position(s) we need to rearrange everything after loading
 | ||||
|             need_arrange = true; | ||||
| 
 | ||||
|  | @ -993,12 +1067,229 @@ std::vector<size_t>  Plater::priv::load_model_objects(const ModelObjectPtrs &mod | |||
|     return obj_idxs; | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType file_type) | ||||
| { | ||||
|     wxString wildcard; | ||||
|     switch (file_type) { | ||||
|         case FT_STL: | ||||
|         case FT_AMF: | ||||
|         case FT_3MF: | ||||
|             wildcard = file_wildcards[FT_STL]; | ||||
|         break; | ||||
| 
 | ||||
|         default: | ||||
|             wildcard = file_wildcards[FT_MODEL]; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     fs::path output_file(print.output_filepath(std::string())); | ||||
| 
 | ||||
|     switch (file_type) { | ||||
|         case FT_STL: output_file.replace_extension("stl"); break; | ||||
|         case FT_AMF: output_file.replace_extension("zip.amf"); break;   // XXX: Problem on OS X with double extension?
 | ||||
|         case FT_3MF: output_file.replace_extension("3mf"); break; | ||||
|         default: break; | ||||
|     } | ||||
| 
 | ||||
|     wxGetApp().preset_bundle->export_selections(print.placeholder_parser()); | ||||
| 
 | ||||
|     auto dlg = Slic3r::make_unique<CheckboxFileDialog>(q, | ||||
|         _(L("Export print config")), | ||||
|         true, | ||||
|         _(L("Save file as:")), | ||||
|         output_file.parent_path().string(), | ||||
|         output_file.filename().string(), | ||||
|         wildcard, | ||||
|         wxFD_SAVE | wxFD_OVERWRITE_PROMPT | ||||
|     ); | ||||
| 
 | ||||
|     if (dlg->ShowModal() != wxID_OK) { | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     fs::path path(dlg->GetPath()); | ||||
|     wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); | ||||
|     export_gcode_output_file = path; | ||||
| 
 | ||||
|     return dlg; | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::select_object(optional<size_t> obj_idx) | ||||
| { | ||||
|     for (auto &obj : objects) { | ||||
|         obj.selected = false; | ||||
|     } | ||||
| 
 | ||||
|     if (obj_idx) { | ||||
|         objects[*obj_idx].selected = true; | ||||
|     } | ||||
| 
 | ||||
|     selection_changed(); | ||||
| } | ||||
| 
 | ||||
| optional<size_t> Plater::priv::selected_object() const | ||||
| { | ||||
|     for (size_t i = 0; i < objects.size(); i++) { | ||||
|         if (objects[i].selected) { return i; } | ||||
|     } | ||||
| 
 | ||||
|     return boost::none; | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::selection_changed() | ||||
| { | ||||
|     // TODO
 | ||||
| 
 | ||||
|     const auto obj_idx = selected_object(); | ||||
|     const bool have_sel = !!obj_idx; | ||||
|     const bool layers_height_allowed = config->opt<ConfigOptionBool>("variable_layer_height")->value; | ||||
| 
 | ||||
|     wxWindowUpdateLocker freeze_guard(sidebar); | ||||
| 
 | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "delete", have_sel); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "more", have_sel); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); | ||||
| 
 | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); | ||||
| 
 | ||||
|     bool can_select_by_parts = false; | ||||
| 
 | ||||
|     if (have_sel) { | ||||
|         const auto *model_object = model.objects[*obj_idx]; | ||||
|         // XXX: ?
 | ||||
|         can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1; | ||||
|         _3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1); | ||||
|     } | ||||
| 
 | ||||
|     if (can_select_by_parts) { | ||||
|         // first disable to let the item in the toolbar to switch to the unpressed state   // XXX: ?
 | ||||
|         _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); | ||||
|         _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", true); | ||||
|     } else { | ||||
|         _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); | ||||
|         _3DScene::set_select_by(canvas3D, "object"); | ||||
|     } | ||||
| 
 | ||||
|     if (have_sel) { | ||||
|         const auto *model_object = model.objects[*obj_idx]; | ||||
|         // FIXME print_info runs model fixing in two rounds, it is very slow, it should not be performed here!
 | ||||
|         // # $model_object->print_info;
 | ||||
| 
 | ||||
|         // my $model_instance = $model_object->instances->[0];
 | ||||
|         const auto *model_instance = model_object->instances[0]; | ||||
|         // TODO
 | ||||
|         // $self->{object_info_size}->SetLabel(sprintf("%.2f x %.2f x %.2f", @{$model_object->instance_bounding_box(0)->size}));
 | ||||
|         // $self->{object_info_materials}->SetLabel($model_object->materials_count);
 | ||||
| 
 | ||||
|         // if (my $stats = $model_object->mesh_stats) {
 | ||||
|         //     $self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3)));
 | ||||
|         //     $self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts}));
 | ||||
|         //     if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) {
 | ||||
|         //         $self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors));
 | ||||
|         //         #$self->{object_info_manifold_warning_icon}->Show;
 | ||||
|         //         $self->{"object_info_manifold_warning_icon_show"}->(1);
 | ||||
| 
 | ||||
|         //         # we don't show normals_fixed because we never provide normals
 | ||||
|         //         # to admesh, so it generates normals for all facets
 | ||||
|         //         my $message = sprintf L('%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges'),
 | ||||
|         //             @$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)};
 | ||||
|         //         $self->{object_info_manifold}->SetToolTipString($message);
 | ||||
|         //         $self->{object_info_manifold_warning_icon}->SetToolTipString($message);
 | ||||
|         //     } else {
 | ||||
|         //         $self->{object_info_manifold}->SetLabel(L("Yes"));
 | ||||
|         //         #$self->{object_info_manifold_warning_icon}->Hide;
 | ||||
|         //         $self->{"object_info_manifold_warning_icon_show"}->(0);
 | ||||
|         //         $self->{object_info_manifold}->SetToolTipString("");
 | ||||
|         //         $self->{object_info_manifold_warning_icon}->SetToolTipString("");
 | ||||
|         //     }
 | ||||
|         // } else {
 | ||||
|         //     $self->{object_info_facets}->SetLabel($object->facets);
 | ||||
|         // }
 | ||||
|     } else { | ||||
|         // $self->{"object_info_$_"}->SetLabel("") for qw(size volume facets materials manifold);
 | ||||
|         // $self->{"object_info_manifold_warning_icon_show"}->(0);
 | ||||
|         // $self->{object_info_manifold}->SetToolTipString("");
 | ||||
|         // $self->{object_info_manifold_warning_icon}->SetToolTipString("");
 | ||||
|     } | ||||
| 
 | ||||
|     q->Layout(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::object_list_changed() | ||||
| { | ||||
|     // Enable/disable buttons depending on whether there are any objects on the platter.
 | ||||
|     const bool have_objects = !objects.empty(); | ||||
| 
 | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "deleteall", have_objects); | ||||
|     _3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects); | ||||
| 
 | ||||
|     const bool export_in_progress = !(export_gcode_output_file.empty() && send_gcode_file.empty()); | ||||
|     // XXX: is this right?
 | ||||
|     const bool model_fits = _3DScene::check_volumes_outside_state(canvas3D, config) == ModelInstance::PVS_Inside; | ||||
| 
 | ||||
|     sidebar->enable_buttons(have_objects && !export_in_progress && model_fits); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::remove(size_t obj_idx) | ||||
| { | ||||
|     // $self->stop_background_process;   // TODO
 | ||||
| 
 | ||||
|     // Prevent toolpaths preview from rendering while we modify the Print object
 | ||||
|     preview->set_enabled(false); | ||||
| 
 | ||||
|     objects.erase(objects.begin() + obj_idx); | ||||
|     model.delete_object(obj_idx); | ||||
|     print.delete_object(obj_idx); | ||||
|     // Delete object from Sidebar list
 | ||||
|     sidebar->obj_list()->delete_object_from_list(); | ||||
| 
 | ||||
|     object_list_changed(); | ||||
| 
 | ||||
|     select_object(boost::none); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::reset() | ||||
| { | ||||
|     // $self->stop_background_process;   // TODO
 | ||||
| 
 | ||||
|     // Prevent toolpaths preview from rendering while we modify the Print object
 | ||||
|     preview->set_enabled(false); | ||||
| 
 | ||||
|     objects.clear(); | ||||
|     model.clear_objects(); | ||||
|     print.clear_objects(); | ||||
| 
 | ||||
|     // Delete all objects from list on c++ side
 | ||||
|     sidebar->obj_list()->delete_all_objects_from_list(); | ||||
|     object_list_changed(); | ||||
| 
 | ||||
|     select_object(boost::none); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::increase(size_t num) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::decrease(size_t num) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) | ||||
| { | ||||
|     const auto current_id = notebook->GetCurrentPage()->GetId(); | ||||
|     if (current_id == canvas3D->GetId()) { | ||||
|         if (_3DScene::is_reload_delayed(canvas3D)) { | ||||
| #if !ENABLE_EXTENDED_SELECTION | ||||
|             _3DScene::set_objects_selections(canvas3D, collect_selections()); | ||||
| #endif // !ENABLE_EXTENDED_SELECTION
 | ||||
|             _3DScene::reload_scene(canvas3D, true); | ||||
|         } | ||||
|         // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
 | ||||
|  | @ -1071,6 +1362,47 @@ void Plater::priv::on_action_add(SimpleEvent&) | |||
|     load_files(input_paths); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_arrange(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_more(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_fewer(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_split(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_cut(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_settings(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_layersediting(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_action_selectbyparts(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Plater::priv::on_viewport_changed(SimpleEvent& evt) | ||||
| { | ||||
|     wxObject* o = evt.GetEventObject(); | ||||
|  | @ -1080,6 +1412,53 @@ void Plater::priv::on_viewport_changed(SimpleEvent& evt) | |||
|         preview->set_viewport_from_scene(canvas3D); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_right_click(Vec2dEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_model_update(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_remove_object(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_arrange(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_scale_uniformly(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_instance_moves(SimpleEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_wipetower_moved(Vec3dEvent&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_enable_action_buttons(Event<bool>&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // Plater / Public
 | ||||
| 
 | ||||
| Plater::Plater(wxWindow *parent, MainFrame *main_frame) | ||||
|  | @ -1096,64 +1475,136 @@ Plater::~Plater() | |||
| Sidebar& Plater::sidebar() { return *p->sidebar; } | ||||
| Model&  Plater::model()  { return p->model; } | ||||
| 
 | ||||
| std::string Plater::export_gcode(const std::string &output_path) | ||||
| void Plater::update(bool force_autocenter) { p->update(force_autocenter); } | ||||
| void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } | ||||
| 
 | ||||
| void Plater::remove_selected() | ||||
| { | ||||
|     if (p->objects.size() == 0) { return ""; } | ||||
|     const auto selected = p->selected_object(); | ||||
|     if (selected) { | ||||
|         remove(*selected); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::load_files(const std::vector<fs::path> &input_files) { p->load_files(input_files); } | ||||
| 
 | ||||
| fs::path Plater::export_gcode(const fs::path &output_path) | ||||
| { | ||||
|     if (p->objects.empty()) { return ""; } | ||||
| 
 | ||||
|     if (! p->export_gcode_output_file.empty()) { | ||||
|         GUI::show_error(this, _(L("Another export job is currently running."))); | ||||
|         return ""; | ||||
|     } | ||||
| 
 | ||||
|     // wxTheApp->{preset_bundle}->full_config->validate;   // FIXME
 | ||||
|     const std::string err = p->print.validate(); | ||||
|     std::string err = wxGetApp().preset_bundle->full_config().validate(); | ||||
|     if (err.empty()) { | ||||
|         err = p->print.validate(); | ||||
|     } | ||||
|     if (! err.empty()) { | ||||
|         // The config is not valid
 | ||||
|         GUI::show_error(this, _(err)); | ||||
|         return ""; | ||||
|         return fs::path(); | ||||
|     } | ||||
| 
 | ||||
|     // Copy the names of active presets into the placeholder parser.
 | ||||
|     // wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser);   // FIXME
 | ||||
|     wxGetApp().preset_bundle->export_selections(p->print.placeholder_parser()); | ||||
| 
 | ||||
|     // select output file
 | ||||
|     if (! output_path.empty()) { | ||||
|         p->export_gcode_output_file = p->print.output_filepath(output_path); | ||||
|         p->export_gcode_output_file = fs::path(p->print.output_filepath(output_path.string())); | ||||
|         // FIXME: ^ errors to handle?
 | ||||
|     } else { | ||||
|         // FIXME:
 | ||||
|         std::string default_output_file;  // FIXME: tmp
 | ||||
|         // my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
 | ||||
|         // Slic3r::GUI::catch_error($self) and return;
 | ||||
| 
 | ||||
|         // XXX: take output path from CLI opts? Ancient Slic3r versions used to do that...
 | ||||
| 
 | ||||
|         // If possible, remove accents from accented latin characters.
 | ||||
|         // This function is useful for generating file names to be processed by legacy firmwares.
 | ||||
|         default_output_file = Slic3r::fold_utf8_to_ascii(default_output_file); | ||||
|         auto default_output_file = fs::path(Slic3r::fold_utf8_to_ascii( | ||||
|             p->print.output_filepath(output_path.string()) | ||||
|             // FIXME: ^ errors to handle?
 | ||||
|         )); | ||||
|         auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string()); | ||||
|         wxFileDialog dlg(this, _(L("Save G-code file as:")), | ||||
|             wxEmptyString, | ||||
|             wxEmptyString, | ||||
|             Slic3r::GUI::FILE_WILDCARDS.at("gcode"), | ||||
|             start_dir, | ||||
|             default_output_file.filename().string(), | ||||
|             GUI::file_wildcards[FT_GCODE], | ||||
|             wxFD_SAVE | wxFD_OVERWRITE_PROMPT | ||||
|         ); | ||||
|         // FIXME: ^ defaultDir:
 | ||||
|         // wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)),
 | ||||
|         // FIXME: ^ defaultFile:
 | ||||
|         // basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
 | ||||
| 
 | ||||
|         if (dlg.ShowModal() != wxID_OK) { return ""; } | ||||
|         auto path = dlg.GetPath(); | ||||
|         // wxTheApp->{app_config}->update_last_output_dir(dirname($path));   // FIXME
 | ||||
|         fs::path path(dlg.GetPath()); | ||||
|         wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); | ||||
|         p->export_gcode_output_file = path; | ||||
|     } | ||||
| 
 | ||||
|     return p->export_gcode_output_file; | ||||
| } | ||||
| 
 | ||||
| void Plater::export_stl() | ||||
| { | ||||
|     if (p->objects.empty()) { return; } | ||||
| 
 | ||||
|     auto dialog = p->get_export_file(FT_STL); | ||||
|     if (! dialog) { return; } | ||||
| 
 | ||||
|     // Store a binary STL
 | ||||
|     wxString path = dialog->GetPath(); | ||||
|     auto path_cstr = path.c_str(); | ||||
|     auto mesh = p->model.mesh(); | ||||
|     Slic3r::store_stl(path_cstr, &mesh, true); | ||||
|     p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path)); | ||||
| } | ||||
| 
 | ||||
| void Plater::export_amf() | ||||
| { | ||||
|     if (p->objects.empty()) { return; } | ||||
| 
 | ||||
|     auto dialog = p->get_export_file(FT_AMF); | ||||
|     if (! dialog) { return; } | ||||
| 
 | ||||
|     wxString path = dialog->GetPath(); | ||||
|     auto path_cstr = path.c_str(); | ||||
| 
 | ||||
|     if (Slic3r::store_amf(path_cstr, &p->model, &p->print, dialog->get_checkbox_value())) { | ||||
|         // Success
 | ||||
|         p->statusbar()->set_status_text(wxString::Format(_(L("AMF file exported to %s")), path)); | ||||
|     } else { | ||||
|         // Failure
 | ||||
|         p->statusbar()->set_status_text(wxString::Format(_(L("Error exporting AMF file %s")), path)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::export_3mf() | ||||
| { | ||||
|     if (p->objects.empty()) { return; } | ||||
| 
 | ||||
|     auto dialog = p->get_export_file(FT_3MF); | ||||
|     if (! dialog) { return; } | ||||
| 
 | ||||
|     wxString path = dialog->GetPath(); | ||||
|     auto path_cstr = path.c_str(); | ||||
| 
 | ||||
|     if (Slic3r::store_3mf(path_cstr, &p->model, &p->print, dialog->get_checkbox_value())) { | ||||
|         // Success
 | ||||
|         p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path)); | ||||
|     } else { | ||||
|         // Failure
 | ||||
|         p->statusbar()->set_status_text(wxString::Format(_(L("Error exporting 3MF file %s")), path)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Plater::reslice() | ||||
| { | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void Plater::send_gcode() | ||||
| { | ||||
|     p->send_gcode_file = export_gcode(); | ||||
| } | ||||
| 
 | ||||
| void Plater::changed_object_settings(int obj_idx) | ||||
| { | ||||
|     if (obj_idx < 0) | ||||
|  | @ -1163,7 +1614,6 @@ void Plater::changed_object_settings(int obj_idx) | |||
|     if (list == nullptr) | ||||
|         return; | ||||
| 
 | ||||
| 
 | ||||
|     if (list->is_parts_changed()) { | ||||
|         // recenter and re - align to Z = 0
 | ||||
|         auto model_object = p->model.objects[list->get_sel_obj_id()]; | ||||
|  |  | |||
|  | @ -2,11 +2,16 @@ | |||
| #define slic3r_Plater_hpp_ | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <boost/filesystem/path.hpp> | ||||
| 
 | ||||
| #include <wx/panel.h> | ||||
| 
 | ||||
| #include "Preset.hpp" | ||||
| 
 | ||||
| class wxButton; | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| class Model; | ||||
|  | @ -20,10 +25,12 @@ class ObjectList; | |||
| 
 | ||||
| using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>; | ||||
| 
 | ||||
| class Plater; | ||||
| 
 | ||||
| class Sidebar : public wxPanel | ||||
| { | ||||
| public: | ||||
|     Sidebar(wxWindow *parent); | ||||
|     Sidebar(Plater *parent); | ||||
|     Sidebar(Sidebar &&) = delete; | ||||
|     Sidebar(const Sidebar &) = delete; | ||||
|     Sidebar &operator=(Sidebar &&) = delete; | ||||
|  | @ -41,12 +48,11 @@ public: | |||
|     int                     get_ol_selection(); | ||||
|     void                    show_info_sizers(const bool show); | ||||
|     void                    show_buttons(const bool show); | ||||
|     void                    enable_buttons(bool enable); | ||||
| 
 | ||||
| private: | ||||
|     struct priv; | ||||
|     std::unique_ptr<priv> p; | ||||
| 
 | ||||
|     friend class Plater;    // XXX: better encapsulation?
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -63,11 +69,20 @@ public: | |||
|     Sidebar& sidebar(); | ||||
|     Model&  model(); | ||||
| 
 | ||||
|     // TODO: use fs::path
 | ||||
|     // Note: empty string means request default path
 | ||||
|     std::string export_gcode(const std::string &output_path); | ||||
|     void update(bool force_autocenter = false); | ||||
|     void remove(size_t obj_idx); | ||||
|     void remove_selected(); | ||||
| 
 | ||||
|     void load_files(const std::vector<boost::filesystem::path> &input_files); | ||||
| 
 | ||||
|     // Note: empty path means "use the default"
 | ||||
|     boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path()); | ||||
|     void export_stl(); | ||||
|     void export_amf(); | ||||
|     void export_3mf(); | ||||
|     void reslice(); | ||||
|     void changed_object_settings(int obj_idx); | ||||
|     void send_gcode(); | ||||
| private: | ||||
|     struct priv; | ||||
|     std::unique_ptr<priv> p; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka