mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/updating' into new_main_page_ui
This commit is contained in:
		
						commit
						2cab573a02
					
				
					 95 changed files with 7513 additions and 1736 deletions
				
			
		|  | @ -70,6 +70,7 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init | |||
|                               _legend_enabled | ||||
|                               _warning_enabled | ||||
|                               _apply_zoom_to_volumes_filter | ||||
|                               _mouse_dragging | ||||
|                                                              | ||||
|                               ) ); | ||||
|                                | ||||
|  | @ -146,6 +147,7 @@ sub new { | |||
|     $self->_warning_enabled(0); | ||||
|     $self->use_plain_shader(0); | ||||
|     $self->_apply_zoom_to_volumes_filter(0); | ||||
|     $self->_mouse_dragging(0); | ||||
| 
 | ||||
|     # Collection of GLVolume objects | ||||
|     $self->volumes(Slic3r::GUI::_3DScene::GLVolume::Collection->new); | ||||
|  | @ -199,6 +201,10 @@ sub new { | |||
|                 $self->select_view('left'); | ||||
|             } elsif ($key == ord('6')) { | ||||
|                 $self->select_view('right'); | ||||
|             } elsif ($key == ord('z')) { | ||||
|                 $self->zoom_to_volumes; | ||||
|             } elsif ($key == ord('b')) { | ||||
|                 $self->zoom_to_bed; | ||||
|             } else { | ||||
|                 $event->Skip; | ||||
|             } | ||||
|  | @ -381,7 +387,9 @@ sub mouse_event { | |||
|     my $pos = Slic3r::Pointf->new($e->GetPositionXY); | ||||
|     my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id_for_variable_layer_height_editing : -1; | ||||
| 
 | ||||
|     if ($e->Entering && &Wx::wxMSW) { | ||||
|     $self->_mouse_dragging($e->Dragging); | ||||
|      | ||||
|     if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) { | ||||
|         # wxMSW needs focus in order to catch mouse wheel events | ||||
|         $self->SetFocus; | ||||
|         $self->_drag_start_xy(undef);         | ||||
|  | @ -595,22 +603,23 @@ sub mouse_wheel_event { | |||
|     $zoom = $zoom_min if defined $zoom_min && $zoom < $zoom_min; | ||||
|     $self->_zoom($zoom); | ||||
|      | ||||
|     # In order to zoom around the mouse point we need to translate | ||||
|     # the camera target | ||||
|     my $size = Slic3r::Pointf->new($self->GetSizeWH); | ||||
|     my $pos = Slic3r::Pointf->new($e->GetX, $size->y - $e->GetY); #- | ||||
|     $self->_camera_target->translate( | ||||
|         # ($pos - $size/2) represents the vector from the viewport center | ||||
|         # to the mouse point. By multiplying it by $zoom we get the new, | ||||
|         # transformed, length of such vector. | ||||
|         # Since we want that point to stay fixed, we move our camera target | ||||
|         # in the opposite direction by the delta of the length of such vector | ||||
|         # ($zoom - 1). We then scale everything by 1/$self->_zoom since  | ||||
|         # $self->_camera_target is expressed in terms of model units. | ||||
|         -($pos->x - $size->x/2) * ($zoom) / $self->_zoom, | ||||
|         -($pos->y - $size->y/2) * ($zoom) / $self->_zoom, | ||||
|         0, | ||||
|     ) if 0; | ||||
| #    # In order to zoom around the mouse point we need to translate | ||||
| #    # the camera target | ||||
| #    my $size = Slic3r::Pointf->new($self->GetSizeWH); | ||||
| #    my $pos = Slic3r::Pointf->new($e->GetX, $size->y - $e->GetY); #- | ||||
| #    $self->_camera_target->translate( | ||||
| #        # ($pos - $size/2) represents the vector from the viewport center | ||||
| #        # to the mouse point. By multiplying it by $zoom we get the new, | ||||
| #        # transformed, length of such vector. | ||||
| #        # Since we want that point to stay fixed, we move our camera target | ||||
| #        # in the opposite direction by the delta of the length of such vector | ||||
| #        # ($zoom - 1). We then scale everything by 1/$self->_zoom since  | ||||
| #        # $self->_camera_target is expressed in terms of model units. | ||||
| #        -($pos->x - $size->x/2) * ($zoom) / $self->_zoom, | ||||
| #        -($pos->y - $size->y/2) * ($zoom) / $self->_zoom, | ||||
| #        0, | ||||
| #    ) if 0; | ||||
| 
 | ||||
|     $self->on_viewport_changed->() if $self->on_viewport_changed; | ||||
|     $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | ||||
|     $self->Refresh; | ||||
|  | @ -678,10 +687,85 @@ sub select_view { | |||
| } | ||||
| 
 | ||||
| sub get_zoom_to_bounding_box_factor { | ||||
|     my ($self, $bb) = @_; | ||||
|     return undef if ($bb->empty); | ||||
|     my $max_size = max(@{$bb->size}) * 2; | ||||
|     return ($max_size == 0) ? undef : min($self->GetSizeWH) / $max_size; | ||||
|     my ($self, $bb) = @_;     | ||||
|     my $max_bb_size = max(@{ $bb->size }); | ||||
|     return undef if ($max_bb_size == 0); | ||||
|          | ||||
|     # project the bbox vertices on a plane perpendicular to the camera forward axis | ||||
|     # then calculates the vertices coordinate on this plane along the camera xy axes | ||||
|      | ||||
|     # we need the view matrix, we let opengl calculate it (same as done in render sub) | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
|     glLoadIdentity(); | ||||
| 
 | ||||
|     if (!TURNTABLE_MODE) { | ||||
|         # Shift the perspective camera. | ||||
|         my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); | ||||
|         glTranslatef(@$camera_pos); | ||||
|     } | ||||
|      | ||||
|     if (TURNTABLE_MODE) { | ||||
|         # Turntable mode is enabled by default. | ||||
|         glRotatef(-$self->_stheta, 1, 0, 0); # pitch | ||||
|         glRotatef($self->_sphi, 0, 0, 1);    # yaw | ||||
|     } else { | ||||
|         # Shift the perspective camera. | ||||
|         my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); | ||||
|         glTranslatef(@$camera_pos); | ||||
|         my @rotmat = quat_to_rotmatrix($self->quat); | ||||
|         glMultMatrixd_p(@rotmat[0..15]); | ||||
|     }     | ||||
|     glTranslatef(@{ $self->_camera_target->negative }); | ||||
|      | ||||
|     # get the view matrix back from opengl | ||||
|     my @matrix = glGetFloatv_p(GL_MODELVIEW_MATRIX); | ||||
| 
 | ||||
|     # camera axes | ||||
|     my $right = Slic3r::Pointf3->new($matrix[0], $matrix[4], $matrix[8]); | ||||
|     my $up = Slic3r::Pointf3->new($matrix[1], $matrix[5], $matrix[9]); | ||||
|     my $forward = Slic3r::Pointf3->new($matrix[2], $matrix[6], $matrix[10]); | ||||
|      | ||||
|     my $bb_min = $bb->min_point(); | ||||
|     my $bb_max = $bb->max_point(); | ||||
|     my $bb_center = $bb->center(); | ||||
|      | ||||
|     # bbox vertices in world space | ||||
|     my @vertices = ();     | ||||
|     push(@vertices, $bb_min); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_min->y(), $bb_min->z())); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_max->y(), $bb_min->z())); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_max->y(), $bb_min->z())); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_min->y(), $bb_max->z())); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_min->y(), $bb_max->z())); | ||||
|     push(@vertices, $bb_max); | ||||
|     push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_max->y(), $bb_max->z())); | ||||
|      | ||||
|     my $max_x = 0.0; | ||||
|     my $max_y = 0.0; | ||||
| 
 | ||||
|     # margin factor to give some empty space around the bbox | ||||
|     my $margin_factor = 1.25; | ||||
|      | ||||
|     foreach my $v (@vertices) { | ||||
|         # project vertex on the plane perpendicular to camera forward axis | ||||
|         my $pos = Slic3r::Pointf3->new($v->x() - $bb_center->x(), $v->y() - $bb_center->y(), $v->z() - $bb_center->z()); | ||||
|         my $proj_on_normal = $pos->x() * $forward->x() + $pos->y() * $forward->y() + $pos->z() * $forward->z(); | ||||
|         my $proj_on_plane = Slic3r::Pointf3->new($pos->x() - $proj_on_normal * $forward->x(), $pos->y() - $proj_on_normal * $forward->y(), $pos->z() - $proj_on_normal * $forward->z()); | ||||
|          | ||||
|         # calculates vertex coordinate along camera xy axes | ||||
|         my $x_on_plane = $proj_on_plane->x() * $right->x() + $proj_on_plane->y() * $right->y() + $proj_on_plane->z() * $right->z(); | ||||
|         my $y_on_plane = $proj_on_plane->x() * $up->x() + $proj_on_plane->y() * $up->y() + $proj_on_plane->z() * $up->z(); | ||||
|      | ||||
|         $max_x = max($max_x, $margin_factor * 2 * abs($x_on_plane)); | ||||
|         $max_y = max($max_y, $margin_factor * 2 * abs($y_on_plane)); | ||||
|     } | ||||
|      | ||||
|     return undef if (($max_x == 0) || ($max_y == 0)); | ||||
|      | ||||
|     my ($cw, $ch) = $self->GetSizeWH; | ||||
|     my $min_ratio = min($cw / $max_x, $ch / $max_y); | ||||
| 
 | ||||
|     return $min_ratio; | ||||
| } | ||||
| 
 | ||||
| sub zoom_to_bounding_box { | ||||
|  | @ -693,6 +777,8 @@ sub zoom_to_bounding_box { | |||
|         # center view around bounding box center | ||||
|         $self->_camera_target($bb->center); | ||||
|         $self->on_viewport_changed->() if $self->on_viewport_changed; | ||||
|         $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; | ||||
|         $self->Refresh; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1027,8 +1113,8 @@ sub Resize { | |||
|         #FIXME setting the size of the box 10x larger than necessary | ||||
|         # is only a workaround for an incorrectly set camera. | ||||
|         # This workaround harms Z-buffer accuracy! | ||||
| #        my $depth = 1.05 * $self->max_bounding_box->radius();  | ||||
|        my $depth = 10.0 * $self->max_bounding_box->radius(); | ||||
| #        my $depth = 1.05 * $self->max_bounding_box->radius(); | ||||
|        my $depth = 5.0 * max(@{ $self->max_bounding_box->size }); | ||||
|         glOrtho( | ||||
|             -$x/2, $x/2, -$y/2, $y/2, | ||||
|             -$depth, $depth, | ||||
|  | @ -1066,6 +1152,8 @@ sub InitGL { | |||
|     $self->volumes->finalize_geometry(1)  | ||||
|         if ($^O eq 'linux' && $self->UseVBOs); | ||||
| 
 | ||||
|     $self->zoom_to_bed; | ||||
|          | ||||
|     glClearColor(0, 0, 0, 1); | ||||
|     glColor3f(1, 0, 0); | ||||
|     glEnable(GL_DEPTH_TEST); | ||||
|  | @ -1158,7 +1246,7 @@ sub Render { | |||
|     glMatrixMode(GL_MODELVIEW); | ||||
|     glLoadIdentity(); | ||||
| 
 | ||||
|     { | ||||
|     if (!TURNTABLE_MODE) { | ||||
|         # Shift the perspective camera. | ||||
|         my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); | ||||
|         glTranslatef(@$camera_pos); | ||||
|  | @ -1182,7 +1270,7 @@ sub Render { | |||
|     # Head light | ||||
|     glLightfv_p(GL_LIGHT1, GL_POSITION, 1, 0, 1, 0); | ||||
|      | ||||
|     if ($self->enable_picking) { | ||||
|     if ($self->enable_picking && !$self->_mouse_dragging) { | ||||
|         if (my $pos = $self->_mouse_pos) { | ||||
|             # Render the object for picking. | ||||
|             # FIXME This cannot possibly work in a multi-sampled context as the color gets mangled by the anti-aliasing. | ||||
|  | @ -1281,10 +1369,7 @@ sub Render { | |||
|         # disable depth testing so that axes are not covered by ground | ||||
|         glDisable(GL_DEPTH_TEST); | ||||
|         my $origin = $self->origin; | ||||
|         my $axis_len = max( | ||||
|             0.3 * max(@{ $self->bed_bounding_box->size }), | ||||
|               2 * max(@{ $volumes_bb->size }), | ||||
|         ); | ||||
|         my $axis_len = $self->use_plain_shader ? 0.3 * max(@{ $self->bed_bounding_box->size }) : 2 * max(@{ $volumes_bb->size }); | ||||
|         glLineWidth(2); | ||||
|         glBegin(GL_LINES); | ||||
|         # draw line for x axis | ||||
|  | @ -1330,8 +1415,8 @@ sub Render { | |||
|         glEnable(GL_CULL_FACE) if ($self->enable_picking); | ||||
|     } | ||||
| 
 | ||||
|     # draw cutting plane | ||||
|     if (defined $self->cutting_plane_z) { | ||||
|         # draw cutting plane | ||||
|         my $plane_z = $self->cutting_plane_z; | ||||
|         my $bb = $volumes_bb; | ||||
|         glDisable(GL_CULL_FACE); | ||||
|  | @ -1347,6 +1432,15 @@ sub Render { | |||
|         glEnd(); | ||||
|         glEnable(GL_CULL_FACE); | ||||
|         glDisable(GL_BLEND); | ||||
|          | ||||
|         # draw cutting contours | ||||
|         glEnableClientState(GL_VERTEX_ARRAY); | ||||
|         glLineWidth(2); | ||||
|         glColor3f(0, 0, 0); | ||||
|         glVertexPointer_c(3, GL_FLOAT, 0, $self->cut_lines_vertices->ptr()); | ||||
|         glDrawArrays(GL_LINES, 0, $self->cut_lines_vertices->elements / 3); | ||||
|         glVertexPointer_c(3, GL_FLOAT, 0, 0); | ||||
|         glDisableClientState(GL_VERTEX_ARRAY); | ||||
|     } | ||||
| 
 | ||||
|     # draw warning message | ||||
|  | @ -1393,18 +1487,10 @@ sub draw_volumes { | |||
|         $volume->render; | ||||
|     } | ||||
|     glDisableClientState(GL_NORMAL_ARRAY); | ||||
|     glDisable(GL_BLEND); | ||||
| 
 | ||||
|     glEnable(GL_CULL_FACE); | ||||
|      | ||||
|     if (defined $self->cutting_plane_z) { | ||||
|         glLineWidth(2); | ||||
|         glColor3f(0, 0, 0); | ||||
|         glVertexPointer_c(3, GL_FLOAT, 0, $self->cut_lines_vertices->ptr()); | ||||
|         glDrawArrays(GL_LINES, 0, $self->cut_lines_vertices->elements / 3); | ||||
|         glVertexPointer_c(3, GL_FLOAT, 0, 0); | ||||
|     } | ||||
|     glDisableClientState(GL_VERTEX_ARRAY); | ||||
|      | ||||
|     glDisable(GL_BLEND); | ||||
|     glEnable(GL_CULL_FACE);     | ||||
| } | ||||
| 
 | ||||
| sub mark_volumes_for_layer_height { | ||||
|  | @ -1753,8 +1839,8 @@ sub _vertex_shader_Gouraud { | |||
| // normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) | ||||
| const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); | ||||
| #define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SPECULAR   (0.25 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SHININESS  200.0 | ||||
| #define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SHININESS  20.0 | ||||
| 
 | ||||
| // normalized values for (1./1.43, 0.2/1.43, 1./1.43) | ||||
| const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); | ||||
|  | @ -1784,15 +1870,9 @@ varying vec3 delta_box_max; | |||
| 
 | ||||
| void main() | ||||
| { | ||||
|     vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz); | ||||
| 
 | ||||
|     // First transform the normal into camera space and normalize the result. | ||||
|     vec3 normal = normalize(gl_NormalMatrix * gl_Normal); | ||||
|      | ||||
|     // Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space.  | ||||
|     // Also since we're talking about a directional light, the position field is actually direction. | ||||
|     vec3 halfVector = normalize(LIGHT_TOP_DIR + eye); | ||||
|      | ||||
|     // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. | ||||
|     // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. | ||||
|     float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); | ||||
|  | @ -1801,7 +1881,7 @@ void main() | |||
|     intensity.y = 0.0; | ||||
| 
 | ||||
|     if (NdotL > 0.0) | ||||
|         intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS); | ||||
|         intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); | ||||
| 
 | ||||
|     // Perform the same lighting calculation for the 2nd light source (no specular applied). | ||||
|     NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); | ||||
|  | @ -1926,8 +2006,8 @@ sub _vertex_shader_variable_layer_height { | |||
| 
 | ||||
| const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); | ||||
| #define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SPECULAR   (0.25 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SHININESS  200.0 | ||||
| #define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION) | ||||
| #define LIGHT_TOP_SHININESS  20.0 | ||||
| 
 | ||||
| const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); | ||||
| #define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION) | ||||
|  | @ -1943,15 +2023,9 @@ varying float object_z; | |||
| 
 | ||||
| void main() | ||||
| { | ||||
|     vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz); | ||||
| 
 | ||||
|     // First transform the normal into camera space and normalize the result. | ||||
|     vec3 normal = normalize(gl_NormalMatrix * gl_Normal); | ||||
|      | ||||
|     // Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space.  | ||||
|     // Also since we're talking about a directional light, the position field is actually direction. | ||||
|     vec3 halfVector = normalize(LIGHT_TOP_DIR + eye); | ||||
|      | ||||
|     // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. | ||||
|     // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. | ||||
|     float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); | ||||
|  | @ -1960,7 +2034,7 @@ void main() | |||
|     intensity.y = 0.0; | ||||
| 
 | ||||
|     if (NdotL > 0.0) | ||||
|         intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS); | ||||
|         intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); | ||||
| 
 | ||||
|     // Perform the same lighting calculation for the 2nd light source (no specular) | ||||
|     NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); | ||||
|  |  | |||
|  | @ -1,122 +0,0 @@ | |||
| package Slic3r::GUI::AboutDialog; | ||||
| use strict; | ||||
| use warnings; | ||||
| use utf8; | ||||
| 
 | ||||
| use Wx qw(:font :html :misc :dialog :sizer :systemsettings :frame :id); | ||||
| use Wx::Event qw(EVT_HTML_LINK_CLICKED EVT_LEFT_DOWN EVT_BUTTON); | ||||
| use Wx::Print; | ||||
| use Wx::Html; | ||||
| use base 'Wx::Dialog'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, -1, 'About Slic3r', wxDefaultPosition, [600, 340], wxCAPTION); | ||||
| 
 | ||||
|     $self->SetBackgroundColour(Wx::wxWHITE); | ||||
|     my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); | ||||
|     $self->SetSizer($hsizer); | ||||
| 
 | ||||
|     # logo | ||||
|     my $logo = Slic3r::GUI::AboutDialog::Logo->new($self, -1, wxDefaultPosition, wxDefaultSize); | ||||
|     $logo->SetBackgroundColour(Wx::wxWHITE); | ||||
|     $hsizer->Add($logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30); | ||||
| 
 | ||||
|     my $vsizer = Wx::BoxSizer->new(wxVERTICAL); | ||||
|     $hsizer->Add($vsizer, 1, wxEXPAND, 0); | ||||
| 
 | ||||
|     # title | ||||
|     my $title = Wx::StaticText->new($self, -1, $Slic3r::FORK_NAME, wxDefaultPosition, wxDefaultSize); | ||||
|     my $title_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); | ||||
|     $title_font->SetWeight(wxFONTWEIGHT_BOLD); | ||||
|     $title_font->SetFamily(wxFONTFAMILY_ROMAN); | ||||
|     $title_font->SetPointSize(24); | ||||
|     $title->SetFont($title_font); | ||||
|     $vsizer->Add($title, 0, wxALIGN_LEFT | wxTOP, 30); | ||||
| 
 | ||||
|     # version | ||||
|     my $version = Wx::StaticText->new($self, -1, "Version $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize); | ||||
|     my $version_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); | ||||
|     $version_font->SetPointSize(&Wx::wxMSW ? 9 : 11); | ||||
|     $version->SetFont($version_font); | ||||
|     $vsizer->Add($version, 0, wxALIGN_LEFT | wxBOTTOM, 10); | ||||
| 
 | ||||
|     # text | ||||
|     my $text = | ||||
|         '<html>' . | ||||
|         '<body bgcolor="#ffffff" link="#808080">' . | ||||
|         '<font color="#808080">' . | ||||
|         'Copyright © 2016 Vojtech Bubnik, Prusa Research. <br />' . | ||||
|         'Copyright © 2011-2016 Alessandro Ranellucci. <br />' . | ||||
|         '<a href="http://slic3r.org/">Slic3r</a> is licensed under the ' . | ||||
|         '<a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License, version 3</a>.' . | ||||
|         '<br /><br /><br />' . | ||||
|         'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake and numerous others. ' . | ||||
|         'Manual by Gary Hodgson. Inspired by the RepRap community. <br />' . | ||||
|         'Slic3r logo designed by Corey Daniels, <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon Set</a> designed by Mark James. ' . | ||||
|         '</font>' . | ||||
|         '</body>' . | ||||
|         '</html>'; | ||||
|     my $html = Wx::HtmlWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); | ||||
|     my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); | ||||
|     my $size = &Wx::wxMSW ? 8 : 10; | ||||
|     $html->SetFonts($font->GetFaceName, $font->GetFaceName, [$size, $size, $size, $size, $size, $size, $size]); | ||||
|     $html->SetBorders(2); | ||||
|     $html->SetPage($text); | ||||
|     $vsizer->Add($html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20); | ||||
|     EVT_HTML_LINK_CLICKED($self, $html, \&link_clicked); | ||||
|      | ||||
|     my $buttons = $self->CreateStdDialogButtonSizer(wxOK); | ||||
|     $self->SetEscapeId(wxID_CLOSE); | ||||
|     EVT_BUTTON($self, wxID_CLOSE, sub { | ||||
|         $self->EndModal(wxID_CLOSE); | ||||
|         $self->Close; | ||||
|     }); | ||||
|     $vsizer->Add($buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); | ||||
|      | ||||
|     EVT_LEFT_DOWN($self, sub { $self->Close }); | ||||
|     EVT_LEFT_DOWN($logo, sub { $self->Close }); | ||||
|      | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub link_clicked { | ||||
|     my ($self, $event) = @_; | ||||
| 
 | ||||
|     Wx::LaunchDefaultBrowser($event->GetLinkInfo->GetHref); | ||||
|     $event->Skip(0); | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::AboutDialog::Logo; | ||||
| use Wx qw(:bitmap :dc); | ||||
| use Wx::Event qw(EVT_PAINT); | ||||
| use base 'Wx::Panel'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my $self = $class->SUPER::new(@_); | ||||
| 
 | ||||
|     $self->{logo} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px.png"), wxBITMAP_TYPE_PNG); | ||||
|     $self->SetMinSize(Wx::Size->new($self->{logo}->GetWidth, $self->{logo}->GetHeight)); | ||||
| 
 | ||||
|     EVT_PAINT($self, \&repaint); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub repaint { | ||||
|     my ($self, $event) = @_; | ||||
| 
 | ||||
|     my $dc = Wx::PaintDC->new($self); | ||||
|     $dc->SetBackgroundMode(wxTRANSPARENT); | ||||
| 
 | ||||
|     my $size = $self->GetSize; | ||||
|     my $logo_w = $self->{logo}->GetWidth; | ||||
|     my $logo_h = $self->{logo}->GetHeight; | ||||
|     $dc->DrawBitmap($self->{logo}, ($size->GetWidth - $logo_w) / 2, ($size->GetHeight - $logo_h) / 2, 1); | ||||
| 
 | ||||
|     $event->Skip; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  | @ -1,458 +0,0 @@ | |||
| # The config wizard is executed when the Slic3r is first started. | ||||
| # The wizard helps the user to specify the 3D printer properties. | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard; | ||||
| use strict; | ||||
| use warnings; | ||||
| use utf8; | ||||
| 
 | ||||
| use Wx; | ||||
| use base 'Wx::Wizard'; | ||||
| 
 | ||||
| # adhere to various human interface guidelines | ||||
| our $wizard = 'Wizard'; | ||||
| $wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK; | ||||
| 
 | ||||
| sub new { | ||||
|     my ($class, $parent, $presets, $fresh_start) = @_; | ||||
|     my $self = $class->SUPER::new($parent, -1, "Configuration $wizard"); | ||||
| 
 | ||||
|     # initialize an empty repository | ||||
|     $self->{config} = Slic3r::Config->new; | ||||
| 
 | ||||
|     my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self, $fresh_start); | ||||
|     $self->add_page($welcome_page); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); | ||||
|     $self->add_page(Slic3r::GUI::ConfigWizard::Page::Finished->new($self)); | ||||
| 
 | ||||
|     $_->build_index for @{$self->{pages}}; | ||||
| 
 | ||||
|     $welcome_page->set_selection_presets([@{$presets}, 'Other']); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub add_page { | ||||
|     my ($self, $page) = @_; | ||||
| 
 | ||||
|     my $n = push @{$self->{pages}}, $page; | ||||
|     # add first page to the page area sizer | ||||
|     $self->GetPageAreaSizer->Add($page) if $n == 1; | ||||
|     # link pages | ||||
|     $self->{pages}[$n-2]->set_next_page($page) if $n >= 2; | ||||
|     $page->set_previous_page($self->{pages}[$n-2]) if $n >= 2; | ||||
| } | ||||
| 
 | ||||
| sub run { | ||||
|     my ($self) = @_; | ||||
|     my $result; | ||||
|     if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) { | ||||
|         my $preset_name = $self->{pages}[0]->{preset_name}; | ||||
|         $result = {  | ||||
|             preset_name         => $preset_name, | ||||
|             reset_user_profile  => $self->{pages}[0]->{reset_user_profile} | ||||
|         }; | ||||
|         if ($preset_name eq 'Other') { | ||||
|             # it would be cleaner to have these defined inside each page class, | ||||
|             # in some event getting called before leaving the page | ||||
|             # set first_layer_height + layer_height based on nozzle_diameter | ||||
|             my $nozzle = $self->{config}->nozzle_diameter; | ||||
|             $self->{config}->set('first_layer_height', $nozzle->[0]); | ||||
|             $self->{config}->set('layer_height', $nozzle->[0] - 0.1); | ||||
|              | ||||
|             # set first_layer_temperature to temperature + 5 | ||||
|             $self->{config}->set('first_layer_temperature', [$self->{config}->temperature->[0] + 5]); | ||||
|              | ||||
|             # set first_layer_bed_temperature to temperature + 5 | ||||
|             $self->{config}->set('first_layer_bed_temperature', | ||||
|                 [ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]); | ||||
|             $result->{config} = $self->{config}; | ||||
|         } | ||||
|     } | ||||
|     $self->Destroy; | ||||
|     return $result; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Index; | ||||
| use Wx qw(:bitmap :dc :font :misc :sizer :systemsettings :window); | ||||
| use Wx::Event qw(EVT_ERASE_BACKGROUND EVT_PAINT); | ||||
| use base 'Wx::Panel'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent, $title) = @_; | ||||
|     my $self = $class->SUPER::new($parent); | ||||
| 
 | ||||
|     push @{$self->{titles}}, $title; | ||||
|     $self->{own_index} = 0; | ||||
| 
 | ||||
|     $self->{bullets}->{before} = Wx::Bitmap->new(Slic3r::var("bullet_black.png"), wxBITMAP_TYPE_PNG); | ||||
|     $self->{bullets}->{own}    = Wx::Bitmap->new(Slic3r::var("bullet_blue.png"),  wxBITMAP_TYPE_PNG); | ||||
|     $self->{bullets}->{after}  = Wx::Bitmap->new(Slic3r::var("bullet_white.png"), wxBITMAP_TYPE_PNG); | ||||
| 
 | ||||
|     $self->{background} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px_transparent.png"), wxBITMAP_TYPE_PNG); | ||||
|     $self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight)); | ||||
| 
 | ||||
|     EVT_PAINT($self, \&repaint); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub repaint { | ||||
|     my ($self, $event) = @_; | ||||
|     my $size = $self->GetClientSize; | ||||
|     my $gap = 5; | ||||
| 
 | ||||
|     my $dc = Wx::PaintDC->new($self); | ||||
|     $dc->SetBackgroundMode(wxTRANSPARENT); | ||||
|     $dc->SetFont($self->GetFont); | ||||
|     $dc->SetTextForeground($self->GetForegroundColour); | ||||
| 
 | ||||
|     my $background_h = $self->{background}->GetHeight; | ||||
|     my $background_w = $self->{background}->GetWidth; | ||||
|     $dc->DrawBitmap($self->{background}, ($size->GetWidth - $background_w) / 2, ($size->GetHeight - $background_h) / 2, 1); | ||||
| 
 | ||||
|     my $label_h = $self->{bullets}->{own}->GetHeight; | ||||
|     $label_h = $dc->GetCharHeight if $dc->GetCharHeight > $label_h; | ||||
|     my $label_w = $size->GetWidth; | ||||
| 
 | ||||
|     my $i = 0; | ||||
|     foreach (@{$self->{titles}}) { | ||||
|         my $bullet = $self->{bullets}->{own}; | ||||
|         $bullet = $self->{bullets}->{before} if $i < $self->{own_index}; | ||||
|         $bullet = $self->{bullets}->{after} if $i > $self->{own_index}; | ||||
| 
 | ||||
|         $dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index}; | ||||
|         $dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gap), $label_w, $label_h)); | ||||
|         # Only show the first bullet if this is the only wizard page to be displayed. | ||||
|         last if $i == 0 && $self->{just_welcome}; | ||||
|         $i++; | ||||
|     } | ||||
| 
 | ||||
|     $event->Skip; | ||||
| } | ||||
| 
 | ||||
| sub prepend_title { | ||||
|     my $self = shift; | ||||
|     my ($title) = @_; | ||||
| 
 | ||||
|     unshift @{$self->{titles}}, $title; | ||||
|     $self->{own_index}++; | ||||
|     $self->Refresh; | ||||
| } | ||||
| 
 | ||||
| sub append_title { | ||||
|     my $self = shift; | ||||
|     my ($title) = @_; | ||||
| 
 | ||||
|     push @{$self->{titles}}, $title; | ||||
|     $self->Refresh; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page; | ||||
| use Wx qw(:font :misc :sizer :staticline :systemsettings); | ||||
| use base 'Wx::WizardPage'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent, $title, $short_title) = @_; | ||||
|     my $self = $class->SUPER::new($parent); | ||||
| 
 | ||||
|     my $sizer = Wx::FlexGridSizer->new(0, 2, 10, 10); | ||||
|     $sizer->AddGrowableCol(1, 1); | ||||
|     $sizer->AddGrowableRow(1, 1); | ||||
|     $sizer->AddStretchSpacer(0); | ||||
|     $self->SetSizer($sizer); | ||||
| 
 | ||||
|     # title | ||||
|     my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); | ||||
|     my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); | ||||
|     $bold_font->SetWeight(wxFONTWEIGHT_BOLD); | ||||
|     $bold_font->SetPointSize(14); | ||||
|     $text->SetFont($bold_font); | ||||
|     $sizer->Add($text, 0, wxALIGN_LEFT, 0); | ||||
| 
 | ||||
|     # index | ||||
|     $self->{short_title} = $short_title ? $short_title : $title; | ||||
|     $self->{index} = Slic3r::GUI::ConfigWizard::Index->new($self, $self->{short_title}); | ||||
|     $sizer->Add($self->{index}, 1, wxEXPAND | wxTOP | wxRIGHT, 10); | ||||
| 
 | ||||
|     # contents | ||||
|     $self->{width} = 430; | ||||
|     $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); | ||||
|     $sizer->Add($self->{vsizer}, 1); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub append_text { | ||||
|     my $self = shift; | ||||
|     my ($text) = @_; | ||||
| 
 | ||||
|     my $para = Wx::StaticText->new($self, -1, $text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); | ||||
|     $para->Wrap($self->{width}); | ||||
|     $para->SetMinSize([$self->{width}, -1]); | ||||
|     $self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxTOP | wxBOTTOM, 10); | ||||
| } | ||||
| 
 | ||||
| sub append_option { | ||||
|     my $self = shift; | ||||
|     my ($full_key) = @_; | ||||
|      | ||||
|     # populate repository with the factory default | ||||
|     my ($opt_key, $opt_index) = split /#/, $full_key, 2; | ||||
|     $self->config->apply(Slic3r::Config::new_from_defaults_keys([$opt_key])); | ||||
|      | ||||
|     # draw the control | ||||
|     my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new( | ||||
|         parent      => $self, | ||||
|         title       => '', | ||||
|         config      => $self->config, | ||||
|         full_labels => 1, | ||||
|     ); | ||||
|     $optgroup->append_single_option_line($opt_key, $opt_index); | ||||
|     $self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); | ||||
| } | ||||
| 
 | ||||
| sub append_panel { | ||||
|     my ($self, $panel) = @_; | ||||
|     $self->{vsizer}->Add($panel, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); | ||||
| } | ||||
| 
 | ||||
| sub set_previous_page { | ||||
|     my $self = shift; | ||||
|     my ($previous_page) = @_; | ||||
|     $self->{previous_page} = $previous_page; | ||||
| } | ||||
| 
 | ||||
| sub GetPrev { | ||||
|     my $self = shift; | ||||
|     return $self->{previous_page}; | ||||
| } | ||||
| 
 | ||||
| sub set_next_page { | ||||
|     my $self = shift; | ||||
|     my ($next_page) = @_; | ||||
|     $self->{next_page} = $next_page; | ||||
| } | ||||
| 
 | ||||
| sub GetNext { | ||||
|     my $self = shift; | ||||
|     return $self->{next_page}; | ||||
| } | ||||
| 
 | ||||
| sub get_short_title { | ||||
|     my $self = shift; | ||||
|     return $self->{short_title}; | ||||
| } | ||||
| 
 | ||||
| sub build_index { | ||||
|     my $self = shift; | ||||
| 
 | ||||
|     my $page = $self; | ||||
|     $self->{index}->prepend_title($page->get_short_title) while ($page = $page->GetPrev); | ||||
|     $page = $self; | ||||
|     $self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext); | ||||
| } | ||||
| 
 | ||||
| sub config { | ||||
|     my ($self) = @_; | ||||
|     return $self->GetParent->{config}; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Welcome; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| use Wx qw(:misc :sizer wxID_FORWARD); | ||||
| use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE EVT_CHECKBOX); | ||||
| 
 | ||||
| sub new { | ||||
|     my ($class, $parent, $fresh_start) = @_; | ||||
|     my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); | ||||
|     $self->{full_wizard_workflow} = 1; | ||||
|     $self->{reset_user_profile} = 0; | ||||
| 
 | ||||
|     # Test for the existence of the old config path. | ||||
|     my $message_has_legacy; | ||||
|     { | ||||
|         my $datadir = Slic3r::data_dir; | ||||
|         if ($datadir =~ /Slic3rPE/) { | ||||
|             # Check for existence of the legacy Slic3r directory. | ||||
|             my $datadir_legacy = substr $datadir, 0, -2; | ||||
|             my $dir_enc = Slic3r::encode_path($datadir_legacy); | ||||
|             if (-e $dir_enc && -d $dir_enc &&  | ||||
|                 -e ($dir_enc . '/print')    && -d ($dir_enc . '/print')    && | ||||
|                 -e ($dir_enc . '/filament') && -d ($dir_enc . '/filament') && | ||||
|                 -e ($dir_enc . '/printer')  && -d ($dir_enc . '/printer')  && | ||||
|                 -e ($dir_enc . '/slic3r.ini')) { | ||||
|                 $message_has_legacy = "Starting with Slic3r 1.38.4, the user profile directory has been renamed to $datadir. You may consider closing Slic3r and renaming $datadir_legacy to $datadir."; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     $self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); | ||||
|     $self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.'); | ||||
|     $self->append_text($message_has_legacy) if defined $message_has_legacy; | ||||
|         # To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); | ||||
|     $self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.'); | ||||
| 
 | ||||
|     $self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); | ||||
|     $self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); | ||||
|     if (! $fresh_start) { | ||||
|         $self->{reset_checkbox} = Wx::CheckBox->new($self, -1, "Reset user profile, install from scratch"); | ||||
|         $self->{vsizer}->Add($self->{reset_checkbox}, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); | ||||
|     } | ||||
| 
 | ||||
|     EVT_CHOICE($parent, $choice, sub { | ||||
|         my $sel = $self->{choice}->GetStringSelection; | ||||
|         $self->{preset_name} = $sel; | ||||
|         $self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq '')); | ||||
|     }); | ||||
| 
 | ||||
|     if (! $fresh_start) { | ||||
|         EVT_CHECKBOX($self, $self->{reset_checkbox}, sub { | ||||
|             $self->{reset_user_profile} = $self->{reset_checkbox}->GetValue(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     EVT_ACTIVATE($parent, sub { | ||||
|         $self->set_full_wizard_workflow($self->{preset_name} eq 'Other'); | ||||
|     }); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub set_full_wizard_workflow { | ||||
|     my ($self, $full_workflow) = @_; | ||||
|     $self->{full_wizard_workflow} = $full_workflow; | ||||
|     $self->{index}->{just_welcome} = !$full_workflow; | ||||
|     $self->{index}->Refresh; | ||||
|     my $next_button = $self->GetParent->FindWindow(wxID_FORWARD); | ||||
|     $next_button->SetLabel($full_workflow ? "&Next >" : "&Finish"); | ||||
| } | ||||
| 
 | ||||
| # Set the preset names, select the first item. | ||||
| sub set_selection_presets { | ||||
|     my ($self, $names) = @_; | ||||
|     $self->{choice}->Append($names); | ||||
|     $self->{choice}->SetSelection(0); | ||||
|     $self->{preset_name} = $names->[0]; | ||||
| } | ||||
| 
 | ||||
| sub GetNext { | ||||
|     my $self = shift; | ||||
|     return $self->{full_wizard_workflow} ? $self->{next_page} : undef; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Firmware; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Firmware Type'); | ||||
| 
 | ||||
|     $self->append_text('Choose the type of firmware used by your printer, then click Next.'); | ||||
|     $self->append_option('gcode_flavor'); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Bed; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Bed Size'); | ||||
| 
 | ||||
|     $self->append_text('Set the shape of your printer\'s bed, then click Next.'); | ||||
|      | ||||
|     $self->config->apply(Slic3r::Config::new_from_defaults_keys(['bed_shape'])); | ||||
|     $self->{bed_shape_panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $self->config->bed_shape); | ||||
|     $self->{bed_shape_panel}->on_change(sub { | ||||
|         $self->config->set('bed_shape', $self->{bed_shape_panel}->GetValue); | ||||
|     }); | ||||
|     $self->append_panel($self->{bed_shape_panel}); | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Nozzle; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Nozzle Diameter'); | ||||
| 
 | ||||
|     $self->append_text('Enter the diameter of your printer\'s hot end nozzle, then click Next.'); | ||||
|     $self->append_option('nozzle_diameter#0'); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Filament; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Filament Diameter'); | ||||
| 
 | ||||
|     $self->append_text('Enter the diameter of your filament, then click Next.'); | ||||
|     $self->append_text('Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.'); | ||||
|     $self->append_option('filament_diameter#0'); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Temperature; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Extrusion Temperature'); | ||||
| 
 | ||||
|     $self->append_text('Enter the temperature needed for extruding your filament, then click Next.'); | ||||
|     $self->append_text('A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS.'); | ||||
|     $self->append_option('temperature#0'); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::BedTemperature; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Bed Temperature'); | ||||
| 
 | ||||
|     $self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed, then click Next.'); | ||||
|     $self->append_text('A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed.'); | ||||
|     $self->append_option('bed_temperature#0'); | ||||
|      | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::GUI::ConfigWizard::Page::Finished; | ||||
| use base 'Slic3r::GUI::ConfigWizard::Page'; | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|     my ($parent) = @_; | ||||
|     my $self = $class->SUPER::new($parent, 'Congratulations!', 'Finish'); | ||||
| 
 | ||||
|     $self->append_text("You have successfully completed the Slic3r Configuration $wizard. " . | ||||
|                        'Slic3r is now configured for your printer and filament.'); | ||||
|     $self->append_text('To close this '.lc($wizard).' and apply the newly created configuration, click Finish.'); | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  | @ -7,7 +7,7 @@ use strict; | |||
| use warnings; | ||||
| use utf8; | ||||
| 
 | ||||
| use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog); | ||||
| use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog wxBORDER_NONE); | ||||
| use Wx::Event qw(EVT_CLOSE EVT_LEFT_DOWN EVT_MENU); | ||||
| use base qw(Wx::ScrolledWindow Class::Accessor); | ||||
| use List::Util qw(first); | ||||
|  | @ -34,7 +34,7 @@ sub new { | |||
|     # button for adding new printer panels | ||||
|     { | ||||
|         my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), | ||||
|             wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE); | ||||
|             wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); | ||||
|         $btn->SetToolTipString("Add printer…") | ||||
|             if $btn->can('SetToolTipString'); | ||||
|          | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ sub new { | |||
|     # declare events | ||||
|     EVT_CLOSE($self, sub { | ||||
|         my (undef, $event) = @_; | ||||
|         if ($event->CanVeto && !$self->check_unsaved_changes) { | ||||
|         if ($event->CanVeto && !Slic3r::GUI::check_unsaved_changes) { | ||||
|             $event->Veto; | ||||
|             return; | ||||
|         } | ||||
|  | @ -95,7 +95,7 @@ sub new { | |||
|     }); | ||||
| 
 | ||||
|     $self->update_ui_from_settings; | ||||
|      | ||||
| 
 | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
|  | @ -238,12 +238,6 @@ sub _init_menubar { | |||
|             $self->repair_stl; | ||||
|         }, undef, 'wrench.png'); | ||||
|         $fileMenu->AppendSeparator(); | ||||
|         # Cmd+, is standard on OS X - what about other operating systems? | ||||
|         $self->_append_menu_item($fileMenu, L("Preferences…\tCtrl+,"), L('Application preferences'), sub { | ||||
|             # Opening the C++ preferences dialog. | ||||
|             Slic3r::GUI::open_preferences_dialog($self->{preferences_event}); | ||||
|         }, wxID_PREFERENCES); | ||||
|         $fileMenu->AppendSeparator(); | ||||
|         $self->_append_menu_item($fileMenu, L("&Quit"), L('Quit Slic3r'), sub { | ||||
|             $self->Close(0); | ||||
|         }, wxID_EXIT); | ||||
|  | @ -320,11 +314,6 @@ sub _init_menubar { | |||
|     # Help menu | ||||
|     my $helpMenu = Wx::Menu->new; | ||||
|     { | ||||
|         $self->_append_menu_item($helpMenu, L("&Configuration ").$Slic3r::GUI::ConfigWizard::wizard."…", L("Run Configuration ").$Slic3r::GUI::ConfigWizard::wizard, sub { | ||||
|             # Run the config wizard, offer the "reset user profile" checkbox. | ||||
|             $self->config_wizard(0); | ||||
|         }); | ||||
|         $helpMenu->AppendSeparator(); | ||||
|         $self->_append_menu_item($helpMenu, L("Prusa 3D Drivers"), L('Open the Prusa3D drivers download page in your browser'), sub { | ||||
|             Wx::LaunchDefaultBrowser('http://www.prusa3d.com/drivers/'); | ||||
|         }); | ||||
|  | @ -349,7 +338,7 @@ sub _init_menubar { | |||
|             Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/issues/new'); | ||||
|         }); | ||||
|         $self->_append_menu_item($helpMenu, L("&About Slic3r"), L('Show about dialog'), sub { | ||||
|             wxTheApp->about; | ||||
|             Slic3r::GUI::about; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|  | @ -363,11 +352,9 @@ sub _init_menubar { | |||
|         $menubar->Append($self->{object_menu}, L("&Object")) if $self->{object_menu}; | ||||
|         $menubar->Append($windowMenu, L("&Window")); | ||||
|         $menubar->Append($self->{viewMenu}, L("&View")) if $self->{viewMenu}; | ||||
|         # Add an optional debug menu  | ||||
|         # (Select application language from the list of installed languages) | ||||
|         Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event}); | ||||
|         # Add a configuration  menu. | ||||
|         Slic3r::GUI::add_config_menu($menubar, $self->{preferences_event}, $self->{lang_ch_event}); | ||||
|         $menubar->Append($helpMenu, L("&Help")); | ||||
|         # Add an optional debug menu. In production code, the add_debug_menu() call should do nothing. | ||||
|         $self->SetMenuBar($menubar); | ||||
|     } | ||||
| } | ||||
|  | @ -563,7 +550,7 @@ sub export_config { | |||
| sub load_config_file { | ||||
|     my ($self, $file) = @_; | ||||
|     if (!$file) { | ||||
|         return unless $self->check_unsaved_changes; | ||||
|         return unless Slic3r::GUI::check_unsaved_changes; | ||||
|         my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),  | ||||
|             $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, | ||||
|             "config.ini", | ||||
|  | @ -582,7 +569,7 @@ sub load_config_file { | |||
| 
 | ||||
| sub export_configbundle { | ||||
|     my ($self) = @_; | ||||
|     return unless $self->check_unsaved_changes; | ||||
|     return unless Slic3r::GUI::check_unsaved_changes; | ||||
|     # validate current configuration in case it's dirty | ||||
|     eval { wxTheApp->{preset_bundle}->full_config->validate; }; | ||||
|     Slic3r::GUI::catch_error($self) and return; | ||||
|  | @ -606,7 +593,7 @@ sub export_configbundle { | |||
| # but that behavior was not documented and likely buggy. | ||||
| sub load_configbundle { | ||||
|     my ($self, $file, $reset_user_profile) = @_; | ||||
|     return unless $self->check_unsaved_changes; | ||||
|     return unless Slic3r::GUI::check_unsaved_changes; | ||||
|     if (!$file) { | ||||
|         my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),  | ||||
|             $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, | ||||
|  | @ -640,70 +627,6 @@ sub load_config { | |||
|     $self->{plater}->on_config_change($config) if $self->{plater}; | ||||
| } | ||||
| 
 | ||||
| sub config_wizard { | ||||
|     my ($self, $fresh_start) = @_; | ||||
|     # Exit wizard if there are unsaved changes and the user cancels the action. | ||||
|     return unless $self->check_unsaved_changes; | ||||
|     # Enumerate the profiles bundled with the Slic3r installation under resources/profiles. | ||||
|     my $directory = Slic3r::resources_dir() . "/profiles"; | ||||
|     my @profiles = (); | ||||
|     if (opendir(DIR, Slic3r::encode_path($directory))) { | ||||
|         while (my $file = readdir(DIR)) { | ||||
|             if ($file =~ /\.ini$/) { | ||||
|                 $file =~ s/\.ini$//; | ||||
|                 push @profiles, Slic3r::decode_path($file); | ||||
|             } | ||||
|         } | ||||
|         closedir(DIR); | ||||
|     } | ||||
|     # Open the wizard. | ||||
|     if (my $result = Slic3r::GUI::ConfigWizard->new($self, \@profiles, $fresh_start)->run) { | ||||
|         eval { | ||||
|             if ($result->{reset_user_profile}) { | ||||
|                 wxTheApp->{preset_bundle}->reset(1); | ||||
|             } | ||||
|             if (defined $result->{config}) { | ||||
|                 # Load and save the settings into print, filament and printer presets. | ||||
|                 wxTheApp->{preset_bundle}->load_config('My Settings', $result->{config}); | ||||
|             } else { | ||||
|                 # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. | ||||
|                 wxTheApp->{preset_bundle}->install_vendor_configbundle($directory . '/' . $result->{preset_name} . '.ini'); | ||||
|                 # Reset the print / filament / printer selections, so that following line will select some sensible defaults. | ||||
|                 if ($fresh_start) { | ||||
|                     wxTheApp->{app_config}->reset_selections; | ||||
|                 } | ||||
|                 # Reload all presets after the vendor config bundle has been installed. | ||||
|                 wxTheApp->{preset_bundle}->load_presets(wxTheApp->{app_config}); | ||||
|             } | ||||
|         }; | ||||
|         Slic3r::GUI::catch_error($self) and return; | ||||
|         # Load the currently selected preset into the GUI, update the preset selection box. | ||||
|         foreach my $tab (values %{$self->{options_tabs}}) { | ||||
|             $tab->load_current_preset; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| # This is called when closing the application, when loading a config file or when starting the config wizard | ||||
| # to notify the user whether he is aware that some preset changes will be lost. | ||||
| sub check_unsaved_changes { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my @dirty = (); | ||||
|     foreach my $tab (values %{$self->{options_tabs}}) { | ||||
|         push @dirty, $tab->title if $tab->current_preset_is_dirty; | ||||
|     } | ||||
|      | ||||
|     if (@dirty) { | ||||
|         my $titles = join ', ', @dirty; | ||||
|         my $confirm = Wx::MessageDialog->new($self, L("You have unsaved changes ").($titles).L(". Discard changes and continue anyway?"), | ||||
|                                              L('Unsaved Presets'), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); | ||||
|         return $confirm->ShowModal == wxID_YES; | ||||
|     } | ||||
|      | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| sub select_tab { | ||||
|     my ($self, $tab) = @_; | ||||
|     $self->{tabpanel}->SetSelection($tab); | ||||
|  |  | |||
|  | @ -682,6 +682,9 @@ sub load_files { | |||
|             Slic3r::GUI::show_error($self, $@) if $@; | ||||
|             $_->load_current_preset for (values %{$self->GetFrame->{options_tabs}}); | ||||
|             wxTheApp->{app_config}->update_config_dir(dirname($input_file)); | ||||
|             # forces the update of the config here, or it will invalidate the imported layer heights profile if done using the timer | ||||
|             # and if the config contains a "layer_height" different from the current defined one | ||||
|             $self->async_apply_config; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | @ -1696,6 +1699,7 @@ sub update { | |||
| 
 | ||||
|     $self->{canvas}->reload_scene if $self->{canvas}; | ||||
|     $self->{canvas3D}->reload_scene if $self->{canvas3D}; | ||||
|     $self->{preview3D}->reset_gcode_preview_data if $self->{preview3D}; | ||||
|     $self->{preview3D}->reload_print if $self->{preview3D}; | ||||
| } | ||||
| 
 | ||||
|  | @ -1801,22 +1805,26 @@ sub on_config_change { | |||
| sub list_item_deselected { | ||||
|     my ($self, $event) = @_; | ||||
|     return if $PreventListEvents; | ||||
|     $self->{_lecursor} = Wx::BusyCursor->new(); | ||||
|     if ($self->{list}->GetFirstSelected == -1) { | ||||
|         $self->select_object(undef); | ||||
|         $self->{canvas}->Refresh; | ||||
|         #FIXME VBOs are being refreshed just to change a selection color? | ||||
|         $self->{canvas3D}->reload_scene if $self->{canvas3D}; | ||||
|     } | ||||
|     undef $self->{_lecursor}; | ||||
| } | ||||
| 
 | ||||
| sub list_item_selected { | ||||
|     my ($self, $event) = @_; | ||||
|     return if $PreventListEvents; | ||||
|     $self->{_lecursor} = Wx::BusyCursor->new(); | ||||
|     my $obj_idx = $event->GetIndex; | ||||
|     $self->select_object($obj_idx); | ||||
|     $self->{canvas}->Refresh; | ||||
|     #FIXME VBOs are being refreshed just to change a selection color? | ||||
|     $self->{canvas3D}->reload_scene if $self->{canvas3D}; | ||||
|     undef $self->{_lecursor}; | ||||
| } | ||||
| 
 | ||||
| sub list_item_activated { | ||||
|  | @ -1875,6 +1883,7 @@ sub object_cut_dialog { | |||
| 	    $self->remove($obj_idx); | ||||
| 	    $self->load_model_objects(grep defined($_), @new_objects); | ||||
| 	    $self->arrange; | ||||
|         $self->{canvas3D}->zoom_to_volumes if $self->{canvas3D}; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1949,7 +1958,8 @@ sub selection_changed { | |||
|     my ($self) = @_; | ||||
|     my ($obj_idx, $object) = $self->selected_object; | ||||
|     my $have_sel = defined $obj_idx; | ||||
|      | ||||
| 
 | ||||
|     $self->Freeze; | ||||
|     if ($self->{htoolbar}) { | ||||
|         # On OSX or Linux | ||||
|         $self->{htoolbar}->EnableTool($_, $have_sel) | ||||
|  | @ -2000,6 +2010,7 @@ sub selection_changed { | |||
|      | ||||
|     # prepagate the event to the frame (a custom Wx event would be cleaner) | ||||
|     $self->GetFrame->on_plater_selection_changed($have_sel); | ||||
|     $self->Thaw; | ||||
| } | ||||
| 
 | ||||
| sub select_object { | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ use base qw(Wx::Panel Class::Accessor); | |||
| 
 | ||||
| use Wx::Locale gettext => 'L'; | ||||
| 
 | ||||
| __PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer auto_zoom)); | ||||
| __PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer)); | ||||
| 
 | ||||
| sub new { | ||||
|     my $class = shift; | ||||
|  | @ -21,7 +21,6 @@ sub new { | |||
|     $self->{number_extruders} = 1; | ||||
|     # Show by feature type by default. | ||||
|     $self->{preferred_color_mode} = 'feature'; | ||||
|     $self->auto_zoom(1); | ||||
| 
 | ||||
|     # init GUI elements | ||||
|     my $canvas = Slic3r::GUI::3DScene->new($self); | ||||
|  | @ -73,6 +72,9 @@ sub new { | |||
|     $choice_view_type->Append(L("Tool")); | ||||
|     $choice_view_type->SetSelection(0); | ||||
| 
 | ||||
|     # the following value needs to be changed if new items are added into $choice_view_type before "Tool" | ||||
|     $self->{tool_idx} = 5; | ||||
|      | ||||
|     my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, L("Show")); | ||||
|      | ||||
|     my $combochecklist_features = $self->{combochecklist_features} = Wx::ComboCtrl->new(); | ||||
|  | @ -205,43 +207,31 @@ sub new { | |||
|     }); | ||||
|     EVT_CHOICE($self, $choice_view_type, sub { | ||||
|         my $selection = $choice_view_type->GetCurrentSelection(); | ||||
|         $self->{preferred_color_mode} = ($selection == 4) ? 'tool' : 'feature'; | ||||
|         $self->{preferred_color_mode} = ($selection == $self->{tool_idx}) ? 'tool' : 'feature'; | ||||
|         $self->gcode_preview_data->set_type($selection); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->reload_print; | ||||
|         $self->auto_zoom(1); | ||||
|     }); | ||||
|     EVT_CHECKLISTBOX($self, $combochecklist_features, sub { | ||||
|         my $flags = Slic3r::GUI::combochecklist_get_flags($combochecklist_features); | ||||
|          | ||||
|         $self->gcode_preview_data->set_extrusion_flags($flags); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->refresh_print; | ||||
|         $self->auto_zoom(1); | ||||
|     });     | ||||
|     EVT_CHECKBOX($self, $checkbox_travel, sub { | ||||
|         $self->gcode_preview_data->set_travel_visible($checkbox_travel->IsChecked()); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->refresh_print; | ||||
|         $self->auto_zoom(1); | ||||
|     });     | ||||
|     EVT_CHECKBOX($self, $checkbox_retractions, sub { | ||||
|         $self->gcode_preview_data->set_retractions_visible($checkbox_retractions->IsChecked()); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->refresh_print; | ||||
|         $self->auto_zoom(1); | ||||
|     }); | ||||
|     EVT_CHECKBOX($self, $checkbox_unretractions, sub { | ||||
|         $self->gcode_preview_data->set_unretractions_visible($checkbox_unretractions->IsChecked()); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->refresh_print; | ||||
|         $self->auto_zoom(1); | ||||
|     }); | ||||
|     EVT_CHECKBOX($self, $checkbox_shells, sub { | ||||
|         $self->gcode_preview_data->set_shells_visible($checkbox_shells->IsChecked()); | ||||
|         $self->auto_zoom(0); | ||||
|         $self->refresh_print; | ||||
|         $self->auto_zoom(1); | ||||
|     }); | ||||
|      | ||||
|     $self->SetSizer($main_sizer); | ||||
|  | @ -302,6 +292,12 @@ sub refresh_print { | |||
|     $self->load_print; | ||||
| } | ||||
| 
 | ||||
| sub reset_gcode_preview_data { | ||||
|     my ($self) = @_; | ||||
|     $self->gcode_preview_data->reset; | ||||
|     $self->canvas->reset_legend_texture(); | ||||
| } | ||||
| 
 | ||||
| sub load_print { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|  | @ -341,7 +337,7 @@ sub load_print { | |||
|         # It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature. | ||||
|         # Color by feature if it is a single extruder print. | ||||
|         my $extruders = $self->{print}->extruders; | ||||
|         my $type = (scalar(@{$extruders}) > 1) ? 4 : 0; | ||||
|         my $type = (scalar(@{$extruders}) > 1) ? $self->{tool_idx} : 0; | ||||
|         $self->gcode_preview_data->set_type($type); | ||||
|         $self->{choice_view_type}->SetSelection($type); | ||||
|         # If the ->SetSelection changed the following line, revert it to "decide yourself". | ||||
|  | @ -350,7 +346,7 @@ sub load_print { | |||
| 
 | ||||
|     # Collect colors per extruder. | ||||
|     my @colors = (); | ||||
|     if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == 4) { | ||||
|     if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == $self->{tool_idx}) { | ||||
|         my @extruder_colors = @{$self->{config}->extruder_colour}; | ||||
|         my @filament_colors = @{$self->{config}->filament_colour}; | ||||
|         for (my $i = 0; $i <= $#extruder_colors; $i += 1) { | ||||
|  | @ -374,7 +370,7 @@ sub load_print { | |||
|             } | ||||
|             $self->show_hide_ui_elements('simple'); | ||||
|         } else { | ||||
|             $self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0) && $self->auto_zoom; | ||||
|             $self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0); | ||||
|             $self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors); | ||||
|             $self->show_hide_ui_elements('full'); | ||||
| 
 | ||||
|  | @ -384,10 +380,6 @@ sub load_print { | |||
|         } | ||||
| 
 | ||||
|         $self->update_sliders($n_layers); | ||||
|                  | ||||
|         if ($self->auto_zoom) { | ||||
|             $self->canvas->zoom_to_volumes; | ||||
|         } | ||||
|         $self->_loaded(1); | ||||
|     } | ||||
| } | ||||
|  | @ -475,11 +467,11 @@ sub set_number_extruders { | |||
|     if ($self->{number_extruders} != $number_extruders) { | ||||
|         $self->{number_extruders} = $number_extruders; | ||||
|         my $type = ($number_extruders > 1) ? | ||||
|               4  # color by a tool number | ||||
|               $self->{tool_idx}  # color by a tool number | ||||
|             : 0; # color by a feature type | ||||
|         $self->{choice_view_type}->SetSelection($type); | ||||
|         $self->gcode_preview_data->set_type($type); | ||||
|         $self->{preferred_color_mode} = ($type == 4) ? 'tool_or_feature' : 'feature'; | ||||
|         $self->{preferred_color_mode} = ($type == $self->{tool_idx}) ? 'tool_or_feature' : 'feature'; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -227,12 +227,14 @@ sub _update { | |||
|                 push @objects, $self->{model_object}; | ||||
|             } | ||||
|          | ||||
|             my $z_cut = $z + $self->{model_object}->bounding_box->z_min;         | ||||
|          | ||||
|             # get section contour | ||||
|             my @expolygons = (); | ||||
|             foreach my $volume (@{$self->{model_object}->volumes}) { | ||||
|                 next if !$volume->mesh; | ||||
|                 next if $volume->modifier; | ||||
|                 my $expp = $volume->mesh->slice([ $z + $volume->mesh->bounding_box->z_min ])->[0]; | ||||
|                 my $expp = $volume->mesh->slice([ $z_cut ])->[0]; | ||||
|                 push @expolygons, @$expp; | ||||
|             } | ||||
|             foreach my $expolygon (@expolygons) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka