Distinct dialogs for 3D preview and object settings
This commit is contained in:
parent
b55d4a4e4b
commit
ae21a45886
3
MANIFEST
3
MANIFEST
@ -37,7 +37,8 @@ lib/Slic3r/GUI/AboutDialog.pm
|
||||
lib/Slic3r/GUI/ConfigWizard.pm
|
||||
lib/Slic3r/GUI/OptionsGroup.pm
|
||||
lib/Slic3r/GUI/Plater.pm
|
||||
lib/Slic3r/GUI/Plater/ObjectDialog.pm
|
||||
lib/Slic3r/GUI/Plater/ObjectPreviewDialog.pm
|
||||
lib/Slic3r/GUI/Plater/ObjectSettingsDialog.pm
|
||||
lib/Slic3r/GUI/Preferences.pm
|
||||
lib/Slic3r/GUI/PreviewCanvas.pm
|
||||
lib/Slic3r/GUI/SkeinPanel.pm
|
||||
|
@ -7,7 +7,8 @@ use FindBin;
|
||||
use Slic3r::GUI::AboutDialog;
|
||||
use Slic3r::GUI::ConfigWizard;
|
||||
use Slic3r::GUI::Plater;
|
||||
use Slic3r::GUI::Plater::ObjectDialog;
|
||||
use Slic3r::GUI::Plater::ObjectPreviewDialog;
|
||||
use Slic3r::GUI::Plater::ObjectSettingsDialog;
|
||||
use Slic3r::GUI::Preferences;
|
||||
use Slic3r::GUI::OptionsGroup;
|
||||
use Slic3r::GUI::SkeinPanel;
|
||||
@ -56,6 +57,7 @@ our $Settings = {
|
||||
},
|
||||
};
|
||||
|
||||
our $have_button_icons = &Wx::wxVERSION_STRING =~ / 2\.9\.[1-9]/;
|
||||
our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
$small_font->SetPointSize(11) if !&Wx::wxMSW;
|
||||
our $medium_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
|
@ -21,12 +21,13 @@ use constant TB_EXPORT_GCODE => &Wx::NewId;
|
||||
use constant TB_EXPORT_STL => &Wx::NewId;
|
||||
use constant TB_MORE => &Wx::NewId;
|
||||
use constant TB_FEWER => &Wx::NewId;
|
||||
use constant TB_INFO => &Wx::NewId;
|
||||
use constant TB_45CW => &Wx::NewId;
|
||||
use constant TB_45CCW => &Wx::NewId;
|
||||
use constant TB_ROTATE => &Wx::NewId;
|
||||
use constant TB_SCALE => &Wx::NewId;
|
||||
use constant TB_SPLIT => &Wx::NewId;
|
||||
use constant TB_VIEW => &Wx::NewId;
|
||||
use constant TB_SETTINGS => &Wx::NewId;
|
||||
|
||||
my $THUMBNAIL_DONE_EVENT : shared = Wx::NewEventType;
|
||||
my $PROGRESS_BAR_EVENT : shared = Wx::NewEventType;
|
||||
@ -73,7 +74,6 @@ sub new {
|
||||
$self->{htoolbar}->AddTool(TB_RESET, "Delete All", Wx::Bitmap->new("$Slic3r::var/cross.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ARRANGE, "Arrange", Wx::Bitmap->new("$Slic3r::var/bricks.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_INFO, "Open", Wx::Bitmap->new("$Slic3r::var/package.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_FEWER, "Fewer", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
@ -81,15 +81,16 @@ sub new {
|
||||
$self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ROTATE, "Rotate…", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new("$Slic3r::var/arrow_out.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new("$Slic3r::var/shape_ungroup.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_VIEW, "View", Wx::Bitmap->new("$Slic3r::var/package.png", wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new("$Slic3r::var/cog.png", wxBITMAP_TYPE_PNG), '');
|
||||
} else {
|
||||
my %tbar_buttons = (
|
||||
load => "Add…",
|
||||
remove => "Delete",
|
||||
reset => "Delete All",
|
||||
arrange => "Arrange",
|
||||
info => "Open",
|
||||
increase => "",
|
||||
decrease => "",
|
||||
rotate45ccw => "",
|
||||
@ -97,9 +98,11 @@ sub new {
|
||||
rotate => "Rotate…",
|
||||
changescale => "Scale…",
|
||||
split => "Split",
|
||||
view => "View",
|
||||
settings => "Settings…",
|
||||
);
|
||||
$self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
for (qw(load remove reset arrange info increase decrease rotate45ccw rotate45cw rotate changescale split)) {
|
||||
for (qw(load remove reset arrange increase decrease rotate45ccw rotate45cw rotate changescale split view settings)) {
|
||||
$self->{"btn_$_"} = Wx::Button->new($self, -1, $tbar_buttons{$_}, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
$self->{btoolbar}->Add($self->{"btn_$_"});
|
||||
}
|
||||
@ -127,7 +130,7 @@ sub new {
|
||||
$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font);
|
||||
$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font);
|
||||
|
||||
if (&Wx::wxVERSION_STRING =~ / 2\.9\.[1-9]/) {
|
||||
if ($Slic3r::GUI::have_button_icons) {
|
||||
my %icons = qw(
|
||||
load brick_add.png
|
||||
remove brick_delete.png
|
||||
@ -159,7 +162,6 @@ sub new {
|
||||
EVT_TOOL($self, TB_REMOVE, sub { $self->remove() }); # explicitly pass no argument to remove
|
||||
EVT_TOOL($self, TB_RESET, \&reset);
|
||||
EVT_TOOL($self, TB_ARRANGE, \&arrange);
|
||||
EVT_TOOL($self, TB_INFO, sub { $_[0]->object_dialog });
|
||||
EVT_TOOL($self, TB_MORE, \&increase);
|
||||
EVT_TOOL($self, TB_FEWER, \&decrease);
|
||||
EVT_TOOL($self, TB_45CW, sub { $_[0]->rotate(-45) });
|
||||
@ -167,12 +169,13 @@ sub new {
|
||||
EVT_TOOL($self, TB_ROTATE, sub { $_[0]->rotate(undef) });
|
||||
EVT_TOOL($self, TB_SCALE, \&changescale);
|
||||
EVT_TOOL($self, TB_SPLIT, \&split_object);
|
||||
EVT_TOOL($self, TB_VIEW, sub { $_[0]->object_preview_dialog });
|
||||
EVT_TOOL($self, TB_SETTINGS, sub { $_[0]->object_settings_dialog });
|
||||
} else {
|
||||
EVT_BUTTON($self, $self->{btn_load}, \&load);
|
||||
EVT_BUTTON($self, $self->{btn_remove}, sub { $self->remove() }); # explicitly pass no argument to remove
|
||||
EVT_BUTTON($self, $self->{btn_reset}, \&reset);
|
||||
EVT_BUTTON($self, $self->{btn_arrange}, \&arrange);
|
||||
EVT_BUTTON($self, $self->{btn_info}, sub { $_[0]->object_dialog });
|
||||
EVT_BUTTON($self, $self->{btn_increase}, \&increase);
|
||||
EVT_BUTTON($self, $self->{btn_decrease}, \&decrease);
|
||||
EVT_BUTTON($self, $self->{btn_rotate45cw}, sub { $_[0]->rotate(-45) });
|
||||
@ -180,6 +183,8 @@ sub new {
|
||||
EVT_BUTTON($self, $self->{btn_changescale}, \&changescale);
|
||||
EVT_BUTTON($self, $self->{btn_rotate}, sub { $_[0]->rotate(undef) });
|
||||
EVT_BUTTON($self, $self->{btn_split}, \&split_object);
|
||||
EVT_BUTTON($self, $self->{btn_view}, sub { $_[0]->object_preview_dialog });
|
||||
EVT_BUTTON($self, $self->{btn_settings}, sub { $_[0]->object_settings_dialog });
|
||||
}
|
||||
|
||||
$_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self))
|
||||
@ -402,7 +407,7 @@ sub load_file {
|
||||
}
|
||||
|
||||
$process_dialog->Destroy;
|
||||
$self->statusbar->SetStatusText("Loaded $basename - Double click object for more info");
|
||||
$self->statusbar->SetStatusText("Loaded $basename");
|
||||
}
|
||||
|
||||
sub object_loaded {
|
||||
@ -1014,7 +1019,7 @@ sub mouse_event {
|
||||
$self->{drag_object} = undef;
|
||||
$self->SetCursor(wxSTANDARD_CURSOR);
|
||||
} elsif ($event->ButtonDClick) {
|
||||
$parent->object_dialog if @{$parent->{selected_objects}};
|
||||
$parent->object_preview_dialog if @{$parent->{selected_objects}};
|
||||
} elsif ($event->Dragging) {
|
||||
return if !$self->{drag_start_pos}; # concurrency problems
|
||||
for my $preview ($self->{drag_object}) {
|
||||
@ -1058,10 +1063,10 @@ sub list_item_activated {
|
||||
my ($self, $event, $obj_idx) = @_;
|
||||
|
||||
$obj_idx //= $event->GetIndex;
|
||||
$self->object_dialog($obj_idx);
|
||||
$self->object_preview_dialog($obj_idx);
|
||||
}
|
||||
|
||||
sub object_dialog {
|
||||
sub object_preview_dialog {
|
||||
my $self = shift;
|
||||
my ($obj_idx) = @_;
|
||||
|
||||
@ -1069,7 +1074,21 @@ sub object_dialog {
|
||||
($obj_idx, undef) = $self->selected_object;
|
||||
}
|
||||
|
||||
my $dlg = Slic3r::GUI::Plater::ObjectDialog->new($self,
|
||||
my $dlg = Slic3r::GUI::Plater::ObjectPreviewDialog->new($self,
|
||||
object => $self->{objects}[$obj_idx],
|
||||
);
|
||||
$dlg->ShowModal;
|
||||
}
|
||||
|
||||
sub object_settings_dialog {
|
||||
my $self = shift;
|
||||
my ($obj_idx) = @_;
|
||||
|
||||
if (!defined $obj_idx) {
|
||||
($obj_idx, undef) = $self->selected_object;
|
||||
}
|
||||
|
||||
my $dlg = Slic3r::GUI::Plater::ObjectSettingsDialog->new($self,
|
||||
object => $self->{objects}[$obj_idx],
|
||||
);
|
||||
$dlg->ShowModal;
|
||||
@ -1078,9 +1097,15 @@ sub object_dialog {
|
||||
sub object_list_changed {
|
||||
my $self = shift;
|
||||
|
||||
my $method = @{$self->{objects}} ? 'Enable' : 'Disable';
|
||||
my $have_objects = @{$self->{objects}} ? 1 : 0;
|
||||
my $method = $have_objects ? 'Enable' : 'Disable';
|
||||
$self->{"btn_$_"}->$method
|
||||
for grep $self->{"btn_$_"}, qw(reset arrange export_gcode export_stl);
|
||||
|
||||
if ($self->{htoolbar}) {
|
||||
$self->{htoolbar}->EnableTool($_, $have_objects)
|
||||
for (TB_RESET, TB_ARRANGE);
|
||||
}
|
||||
}
|
||||
|
||||
sub selection_changed {
|
||||
@ -1089,11 +1114,11 @@ sub selection_changed {
|
||||
|
||||
my $method = $have_sel ? 'Enable' : 'Disable';
|
||||
$self->{"btn_$_"}->$method
|
||||
for grep $self->{"btn_$_"}, qw(remove info increase decrease rotate45cw rotate45ccw rotate changescale split);
|
||||
for grep $self->{"btn_$_"}, qw(remove increase decrease rotate45cw rotate45ccw rotate changescale split view settings);
|
||||
|
||||
if ($self->{htoolbar}) {
|
||||
$self->{htoolbar}->EnableTool($_, $have_sel)
|
||||
for (TB_REMOVE, TB_INFO, TB_MORE, TB_FEWER, TB_45CW, TB_45CCW, TB_ROTATE, TB_SCALE, TB_SPLIT);
|
||||
for (TB_REMOVE, TB_MORE, TB_FEWER, TB_45CW, TB_45CCW, TB_ROTATE, TB_SCALE, TB_SPLIT, TB_VIEW, TB_SETTINGS);
|
||||
}
|
||||
|
||||
if ($self->{object_info_size}) { # have we already loaded the info pane?
|
||||
@ -1109,6 +1134,8 @@ sub selection_changed {
|
||||
$self->{object_info_manifold}->SetLabel(sprintf("Auto-repaired (%d errors)", $errors));
|
||||
$self->{object_info_manifold_warning_icon}->Show;
|
||||
|
||||
# we don't show normals_fixed because we never provide normals
|
||||
# to admesh, so it generates normals for all facets
|
||||
my $message = sprintf '%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);
|
||||
|
24
lib/Slic3r/GUI/Plater/ObjectPreviewDialog.pm
Normal file
24
lib/Slic3r/GUI/Plater/ObjectPreviewDialog.pm
Normal file
@ -0,0 +1,24 @@
|
||||
package Slic3r::GUI::Plater::ObjectPreviewDialog;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use Wx qw(:dialog :id :misc :sizer :systemsettings :notebook wxTAB_TRAVERSAL);
|
||||
use Wx::Event qw(EVT_BUTTON);
|
||||
use base 'Wx::Dialog';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, %params) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||
$self->{object} = $params{object};
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object), 1, wxEXPAND, 0);
|
||||
$self->SetSizer($sizer);
|
||||
$self->SetMinSize($self->GetSize);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
@ -1,4 +1,4 @@
|
||||
package Slic3r::GUI::Plater::ObjectDialog;
|
||||
package Slic3r::GUI::Plater::ObjectSettingsDialog;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
@ -10,13 +10,10 @@ use base 'Wx::Dialog';
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, %params) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, "Object", wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||
my $self = $class->SUPER::new($parent, -1, "Settings for " . $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||
$self->{object} = $params{object};
|
||||
|
||||
$self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
||||
$self->{tabpanel}->AddPage($self->{preview} = Slic3r::GUI::Plater::ObjectDialog::PreviewTab->new($self->{tabpanel}, object => $self->{object}), "Preview")
|
||||
if $Slic3r::GUI::have_OpenGL;
|
||||
$self->{tabpanel}->AddPage($self->{info} = Slic3r::GUI::Plater::ObjectDialog::InfoTab->new($self->{tabpanel}, object => $self->{object}), "Info");
|
||||
$self->{tabpanel}->AddPage($self->{settings} = Slic3r::GUI::Plater::ObjectDialog::SettingsTab->new($self->{tabpanel}, object => $self->{object}), "Settings");
|
||||
$self->{tabpanel}->AddPage($self->{layers} = Slic3r::GUI::Plater::ObjectDialog::LayersTab->new($self->{tabpanel}, object => $self->{object}), "Layers");
|
||||
|
||||
@ -42,90 +39,6 @@ sub new {
|
||||
return $self;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::Plater::ObjectDialog::InfoTab;
|
||||
use Wx qw(:dialog :id :misc :sizer :systemsettings);
|
||||
use base 'Wx::Panel';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, %params) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
|
||||
$self->{object} = $params{object};
|
||||
|
||||
my $grid_sizer = Wx::FlexGridSizer->new(3, 2, 5, 5);
|
||||
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
||||
$grid_sizer->AddGrowableCol(1);
|
||||
|
||||
my $label_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
$label_font->SetPointSize(10);
|
||||
|
||||
my $properties = $self->get_properties;
|
||||
foreach my $property (@$properties) {
|
||||
my $label = Wx::StaticText->new($self, -1, $property->[0] . ":");
|
||||
my $value = Wx::StaticText->new($self, -1, $property->[1]);
|
||||
$label->SetFont($label_font);
|
||||
$grid_sizer->Add($label, 1, wxALIGN_BOTTOM);
|
||||
$grid_sizer->Add($value, 0);
|
||||
}
|
||||
|
||||
$self->SetSizer($grid_sizer);
|
||||
$grid_sizer->SetSizeHints($self);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_properties {
|
||||
my $self = shift;
|
||||
|
||||
my $object = $self->{object};
|
||||
my $properties = [
|
||||
['Name' => $object->name],
|
||||
['Size' => sprintf "%.2f x %.2f x %.2f", @{$object->transformed_size}],
|
||||
['Facets' => $object->facets],
|
||||
['Vertices' => $object->vertices],
|
||||
['Materials' => $object->materials],
|
||||
];
|
||||
|
||||
if (my $stats = $object->mesh_stats) {
|
||||
push @$properties,
|
||||
[ 'Shells' => $stats->{number_of_parts} ],
|
||||
[ 'Volume' => sprintf('%.2f', $stats->{volume} * ($object->scale**3)) ],
|
||||
[ 'Degenerate facets' => $stats->{degenerate_facets} ],
|
||||
[ 'Edges fixed' => $stats->{edges_fixed} ],
|
||||
[ 'Facets removed' => $stats->{facets_removed} ],
|
||||
[ 'Facets added' => $stats->{facets_added} ],
|
||||
[ 'Facets reversed' => $stats->{facets_reversed} ],
|
||||
[ 'Backwards edges' => $stats->{backwards_edges} ],
|
||||
# we don't show normals_fixed because we never provide normals
|
||||
# to admesh, so it generates normals for all facets
|
||||
;
|
||||
} else {
|
||||
push @$properties,
|
||||
['Two-Manifold' => $object->is_manifold ? 'Yes' : 'No'],
|
||||
;
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::Plater::ObjectDialog::PreviewTab;
|
||||
use Wx qw(:dialog :id :misc :sizer :systemsettings);
|
||||
use base 'Wx::Panel';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, %params) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
|
||||
$self->{object} = $params{object};
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object), 1, wxEXPAND, 0);
|
||||
$self->SetSizer($sizer);
|
||||
$sizer->SetSizeHints($self);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::Plater::ObjectDialog::SettingsTab;
|
||||
use Wx qw(:dialog :id :misc :sizer :systemsettings :button :icon);
|
||||
use Wx::Grid;
|
@ -295,7 +295,7 @@ package Slic3r::Model::Object;
|
||||
use Moo;
|
||||
|
||||
use File::Basename qw(basename);
|
||||
use List::Util qw(first);
|
||||
use List::Util qw(first sum);
|
||||
use Slic3r::Geometry qw(X Y Z MIN MAX move_points move_points_3D);
|
||||
use Storable qw(dclone);
|
||||
|
||||
@ -430,6 +430,11 @@ sub materials_count {
|
||||
return scalar keys %materials;
|
||||
}
|
||||
|
||||
sub facets_count {
|
||||
my $self = shift;
|
||||
return sum(map $_->facets_count, @{$self->volumes});
|
||||
}
|
||||
|
||||
sub check_manifoldness {
|
||||
my $self = shift;
|
||||
return (first { !$_->mesh->check_manifoldness } @{$self->volumes}) ? 0 : 1;
|
||||
@ -485,6 +490,11 @@ sub mesh {
|
||||
);
|
||||
}
|
||||
|
||||
sub facets_count {
|
||||
my $self = shift;
|
||||
return scalar(@{$self->facets}); # TODO: optimize in XS
|
||||
}
|
||||
|
||||
package Slic3r::Model::Instance;
|
||||
use Moo;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user