Merge branch 'dev' of https://github.com/prusa3d/Slic3r into full_transform

This commit is contained in:
Enrico Turri 2018-09-14 08:51:06 +02:00
commit 7ef1eb306a
15 changed files with 1327 additions and 559 deletions

View File

@ -208,10 +208,12 @@ sub _init_tabpanel {
EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub {
my ($self, $event) = @_; my ($self, $event) = @_;
my $obj_idx = $event->GetId; my $obj_idx = $event->GetId;
my $child = $event->GetInt == 1 ? 1 : undef; # my $child = $event->GetInt == 1 ? 1 : undef;
# $self->{plater}->select_object($obj_idx < 0 ? undef: $obj_idx, $child);
# $self->{plater}->item_changed_selection($obj_idx);
$self->{plater}->select_object($obj_idx < 0 ? undef: $obj_idx, $child); my $vol_idx = $event->GetInt;
$self->{plater}->item_changed_selection($obj_idx); $self->{plater}->select_object_from_cpp($obj_idx < 0 ? undef: $obj_idx, $vol_idx<0 ? -1 : $vol_idx);
}); });
# The following event is emited by the C++ GUI implementation on object settings change. # The following event is emited by the C++ GUI implementation on object settings change.

View File

@ -113,10 +113,11 @@ sub new {
# callback to enable/disable action buttons # callback to enable/disable action buttons
my $enable_action_buttons = sub { my $enable_action_buttons = sub {
my ($enable) = @_; my ($enable) = @_;
$self->{btn_export_gcode}->Enable($enable); Slic3r::GUI::enable_action_buttons($enable);
$self->{btn_reslice}->Enable($enable); # $self->{btn_export_gcode}->Enable($enable);
$self->{btn_print}->Enable($enable); # $self->{btn_reslice}->Enable($enable);
$self->{btn_send_gcode}->Enable($enable); # $self->{btn_print}->Enable($enable);
# $self->{btn_send_gcode}->Enable($enable);
}; };
# callback to react to gizmo scale # callback to react to gizmo scale
@ -239,7 +240,14 @@ sub new {
my ($obj_idx, $object) = $self->selected_object; my ($obj_idx, $object) = $self->selected_object;
if (defined $obj_idx) { if (defined $obj_idx) {
my $vol_idx = Slic3r::GUI::_3DScene::get_first_volume_id($self->{canvas3D}, $obj_idx); my $vol_idx = Slic3r::GUI::_3DScene::get_first_volume_id($self->{canvas3D}, $obj_idx);
Slic3r::GUI::_3DScene::select_volume($self->{canvas3D}, $vol_idx) if ($vol_idx != -1); #Slic3r::GUI::_3DScene::select_volume($self->{canvas3D}, $vol_idx) if ($vol_idx != -1);
my $inst_cnt = $self->{model}->objects->[$obj_idx]->instances_count;
for (0..$inst_cnt-1){
Slic3r::GUI::_3DScene::select_volume($self->{canvas3D}, $_ + $vol_idx) if ($vol_idx != -1);
}
my $volume_idx = Slic3r::GUI::_3DScene::get_in_object_volume_id($self->{canvas3D}, $vol_idx);
Slic3r::GUI::select_current_volume($obj_idx, $volume_idx) if ($volume_idx != -1);
} }
} }
}; };
@ -391,26 +399,35 @@ sub new {
# } # }
### Panel for right column ### Panel for right column
# $self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); $self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{right_panel} = Wx::ScrolledWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); # $self->{right_panel} = Wx::ScrolledWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{right_panel}->SetScrollbars(0, 1, 1, 1); # $self->{right_panel}->SetScrollbars(0, 1, 1, 1);
### Scrolled Window for panel without "Export G-code" and "Slice now" buttons
my $scrolled_window_sizer = $self->{scrolled_window_sizer} = Wx::BoxSizer->new(wxVERTICAL);
$scrolled_window_sizer->SetMinSize([320, -1]);
my $scrolled_window_panel = $self->{scrolled_window_panel} = Wx::ScrolledWindow->new($self->{right_panel}, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$scrolled_window_panel->SetSizer($scrolled_window_sizer);
$scrolled_window_panel->SetScrollbars(0, 1, 1, 1);
# right pane buttons # right pane buttons
$self->{btn_export_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30], wxNO_BORDER);#, wxBU_LEFT); $self->{btn_export_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30],);# wxNO_BORDER);#, wxBU_LEFT);
$self->{btn_reslice} = Wx::Button->new($self->{right_panel}, -1, L("Slice now"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_reslice} = Wx::Button->new($self->{right_panel}, -1, L("Slice now"), wxDefaultPosition, [-1, 30]);#, wxNO_BORDER);#, wxBU_LEFT);
$self->{btn_print} = Wx::Button->new($self->{right_panel}, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT); # $self->{btn_print} = Wx::Button->new($self->{right_panel}, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_send_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT); # $self->{btn_send_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_export_stl} = Wx::Button->new($self->{right_panel}, -1, L("Export STL…"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_print} = Wx::Button->new($scrolled_window_panel, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_send_gcode} = Wx::Button->new($scrolled_window_panel, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
#$self->{btn_export_stl} = Wx::Button->new($self->{right_panel}, -1, L("Export STL…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
#$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font); #$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font);
#$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font); #$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font);
$self->{btn_print}->Hide; $self->{btn_print}->Hide;
$self->{btn_send_gcode}->Hide; $self->{btn_send_gcode}->Hide;
# export_gcode cog_go.png # export_gcode cog_go.png
#! reslice reslice.png
my %icons = qw( my %icons = qw(
print arrow_up.png print arrow_up.png
send_gcode arrow_up.png send_gcode arrow_up.png
reslice reslice.png
export_stl brick_go.png export_stl brick_go.png
); );
for (grep $self->{"btn_$_"}, keys %icons) { for (grep $self->{"btn_$_"}, keys %icons) {
@ -527,9 +544,11 @@ sub new {
# $self->{preset_choosers}{$group}[$idx] # $self->{preset_choosers}{$group}[$idx]
$self->{preset_choosers} = {}; $self->{preset_choosers} = {};
for my $group (qw(print filament sla_material printer)) { for my $group (qw(print filament sla_material printer)) {
my $text = Wx::StaticText->new($self->{right_panel}, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); # my $text = Wx::StaticText->new($self->{right_panel}, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
$text->SetFont($Slic3r::GUI::small_font); $text->SetFont($Slic3r::GUI::small_font);
my $choice = Wx::BitmapComboBox->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY); # my $choice = Wx::BitmapComboBox->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY);
my $choice = Wx::BitmapComboBox->new($scrolled_window_panel, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY);
if ($group eq 'filament') { if ($group eq 'filament') {
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down(0, @_); } ); EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down(0, @_); } );
} }
@ -548,26 +567,13 @@ sub new {
} }
my $frequently_changed_parameters_sizer = $self->{frequently_changed_parameters_sizer} = Wx::BoxSizer->new(wxVERTICAL); my $frequently_changed_parameters_sizer = $self->{frequently_changed_parameters_sizer} = Wx::BoxSizer->new(wxVERTICAL);
Slic3r::GUI::add_frequently_changed_parameters($self->{right_panel}, $frequently_changed_parameters_sizer, $presets); #! Slic3r::GUI::add_frequently_changed_parameters($self->{right_panel}, $frequently_changed_parameters_sizer, $presets);
Slic3r::GUI::add_frequently_changed_parameters($self->{scrolled_window_panel}, $frequently_changed_parameters_sizer, $presets);
my $expert_mode_part_sizer = Wx::BoxSizer->new(wxVERTICAL);
Slic3r::GUI::add_expert_mode_part( $self->{right_panel}, $expert_mode_part_sizer,
$self->{model},
$self->{event_object_selection_changed},
$self->{event_object_settings_changed},
$self->{event_remove_object},
$self->{event_update_scene});
# if ($expert_mode_part_sizer->IsShown(2)==1)
# {
# $expert_mode_part_sizer->Layout;
# $expert_mode_part_sizer->Show(2, 0); # ? Why doesn't work
# $self->{right_panel}->Layout;
# }
my $object_info_sizer; my $object_info_sizer;
{ {
# my $box = Wx::StaticBox->new($scrolled_window_panel, -1, L("Info")); my $box = Wx::StaticBox->new($scrolled_window_panel, -1, L("Info"));
my $box = Wx::StaticBox->new($self->{right_panel}, -1, L("Info")); # my $box = Wx::StaticBox->new($self->{right_panel}, -1, L("Info"));
$box->SetFont($Slic3r::GUI::small_bold_font); $box->SetFont($Slic3r::GUI::small_bold_font);
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL); $object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
$object_info_sizer->SetMinSize([300,-1]); $object_info_sizer->SetMinSize([300,-1]);
@ -587,17 +593,17 @@ sub new {
); );
while (my $field = shift @info) { while (my $field = shift @info) {
my $label = shift @info; my $label = shift @info;
# my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
my $text = Wx::StaticText->new($self->{right_panel}, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); # my $text = Wx::StaticText->new($self->{right_panel}, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$text->SetFont($Slic3r::GUI::small_font); $text->SetFont($Slic3r::GUI::small_font);
#!$grid_sizer->Add($text, 0); #!$grid_sizer->Add($text, 0);
# $self->{"object_info_$field"} = Wx::StaticText->new($scrolled_window_panel, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); $self->{"object_info_$field"} = Wx::StaticText->new($scrolled_window_panel, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$self->{"object_info_$field"} = Wx::StaticText->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); # $self->{"object_info_$field"} = Wx::StaticText->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font); $self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font);
if ($field eq 'manifold') { if ($field eq 'manifold') {
# $self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($scrolled_window_panel, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG)); $self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($scrolled_window_panel, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG));
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self->{right_panel}, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG)); # $self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self->{right_panel}, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG));
#$self->{object_info_manifold_warning_icon}->Hide; #$self->{object_info_manifold_warning_icon}->Hide;
$self->{"object_info_manifold_warning_icon_show"} = sub { $self->{"object_info_manifold_warning_icon_show"} = sub {
if ($self->{object_info_manifold_warning_icon}->IsShown() != $_[0]) { if ($self->{object_info_manifold_warning_icon}->IsShown() != $_[0]) {
@ -623,18 +629,19 @@ sub new {
} }
} }
my $print_info_sizer = $self->{print_info_sizer} = Wx::StaticBoxSizer->new( my $print_info_box = Wx::StaticBox->new($scrolled_window_panel, -1, L("Sliced Info"));
# Wx::StaticBox->new($scrolled_window_panel, -1, L("Sliced Info")), wxVERTICAL); $print_info_box->SetFont($Slic3r::GUI::small_bold_font);
Wx::StaticBox->new($self->{right_panel}, -1, L("Sliced Info")), wxVERTICAL); my $print_info_sizer = $self->{print_info_sizer} = Wx::StaticBoxSizer->new($print_info_box, wxVERTICAL);
# Wx::StaticBox->new($self->{right_panel}, -1, L("Sliced Info")), wxVERTICAL);
$print_info_sizer->SetMinSize([300,-1]); $print_info_sizer->SetMinSize([300,-1]);
my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$self->{buttons_sizer} = $buttons_sizer; $self->{buttons_sizer} = $buttons_sizer;
$buttons_sizer->AddStretchSpacer(1); $buttons_sizer->AddStretchSpacer(1);
$buttons_sizer->Add($self->{btn_export_stl}, 0, wxALIGN_RIGHT, 0); # $buttons_sizer->Add($self->{btn_export_stl}, 0, wxALIGN_RIGHT, 0);
$buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0); #! $buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0);
$buttons_sizer->Add($self->{btn_print}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_print}, 0, wxALIGN_RIGHT | wxBOTTOM | wxTOP, 5);
$buttons_sizer->Add($self->{btn_send_gcode}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_send_gcode}, 0, wxALIGN_RIGHT | wxBOTTOM | wxTOP, 5);
# $scrolled_window_sizer->Add($self->{list}, 1, wxEXPAND, 5); # $scrolled_window_sizer->Add($self->{list}, 1, wxEXPAND, 5);
# $scrolled_window_sizer->Add($object_info_sizer, 0, wxEXPAND, 0); # $scrolled_window_sizer->Add($object_info_sizer, 0, wxEXPAND, 0);
@ -644,24 +651,39 @@ sub new {
### Sizer for info boxes ### Sizer for info boxes
my $info_sizer = $self->{info_sizer} = Wx::BoxSizer->new(wxVERTICAL); my $info_sizer = $self->{info_sizer} = Wx::BoxSizer->new(wxVERTICAL);
$info_sizer->SetMinSize([318, -1]); $info_sizer->SetMinSize([318, -1]);
$info_sizer->Add($object_info_sizer, 0, wxEXPAND | wxBOTTOM, 5); $info_sizer->Add($object_info_sizer, 0, wxEXPAND | wxTOP, 20);
$info_sizer->Add($print_info_sizer, 0, wxEXPAND | wxBOTTOM, 5); $info_sizer->Add($print_info_sizer, 0, wxEXPAND | wxTOP, 20);
$scrolled_window_sizer->Add($presets, 0, wxEXPAND | wxLEFT, 2) if defined $presets;
$scrolled_window_sizer->Add($frequently_changed_parameters_sizer, 1, wxEXPAND | wxLEFT, 0) if defined $frequently_changed_parameters_sizer;
$scrolled_window_sizer->Add($buttons_sizer, 0, wxEXPAND, 0);
$scrolled_window_sizer->Add($info_sizer, 0, wxEXPAND | wxLEFT, 20);
# Show the box initially, let it be shown after the slicing is finished.
$self->print_info_box_show(0);
### Sizer for "Export G-code" & "Slice now" buttons
my $btns_sizer = Wx::BoxSizer->new(wxVERTICAL);
$btns_sizer->SetMinSize([318, -1]);
$btns_sizer->Add($self->{btn_reslice}, 0, wxEXPAND, 0);
$btns_sizer->Add($self->{btn_export_gcode}, 0, wxEXPAND | wxTOP, 5);
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL); my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
$self->{right_panel}->SetSizer($right_sizer); $self->{right_panel}->SetSizer($right_sizer);
$right_sizer->SetMinSize([320, -1]); $right_sizer->SetMinSize([320, -1]);
$right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets; #! $right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets;
$right_sizer->Add($frequently_changed_parameters_sizer, 1, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer; #! $right_sizer->Add($frequently_changed_parameters_sizer, 1, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer;
$right_sizer->Add($expert_mode_part_sizer, 0, wxEXPAND | wxTOP, 10) if defined $expert_mode_part_sizer; #! $right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM | wxTOP, 10);
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM | wxTOP, 10); #! $right_sizer->Add($info_sizer, 0, wxEXPAND | wxLEFT, 20);
$right_sizer->Add($info_sizer, 0, wxEXPAND | wxLEFT, 20);
# Show the box initially, let it be shown after the slicing is finished. # Show the box initially, let it be shown after the slicing is finished.
$self->print_info_box_show(0); #! $self->print_info_box_show(0);
$right_sizer->Add($self->{btn_export_gcode}, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 20); $right_sizer->Add($scrolled_window_panel, 1, wxEXPAND | wxTOP, 5);
# $right_sizer->Add($self->{btn_reslice}, 0, wxEXPAND | wxLEFT | wxTOP, 20);
# $right_sizer->Add($self->{btn_export_gcode}, 0, wxEXPAND | wxLEFT | wxTOP, 20);
$right_sizer->Add($btns_sizer, 0, wxEXPAND | wxLEFT | wxTOP, 20);
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
$hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1); $hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1);
$hsizer->Add($self->{right_panel}, 0, wxEXPAND | wxLEFT | wxRIGHT, 3); $hsizer->Add($self->{right_panel}, 0, wxEXPAND | wxLEFT | wxRIGHT, 0);#3);
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
# $sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar}; # $sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar};
@ -672,16 +694,21 @@ sub new {
$self->SetSizer($sizer); $self->SetSizer($sizer);
# Send sizers/buttons to C++ # Send sizers/buttons to C++
Slic3r::GUI::set_objects_from_perl( $self->{right_panel}, Slic3r::GUI::set_objects_from_perl( $self->{scrolled_window_panel},
$frequently_changed_parameters_sizer, $frequently_changed_parameters_sizer,
$expert_mode_part_sizer, $info_sizer,
$info_sizer, $self->{btn_export_gcode},
$self->{btn_export_gcode}, # $self->{btn_export_stl},
$self->{btn_export_stl}, $self->{btn_reslice},
$self->{btn_reslice}, $self->{btn_print},
$self->{btn_print}, $self->{btn_send_gcode},
$self->{btn_send_gcode}, $self->{object_info_manifold_warning_icon} );
$self->{object_info_manifold_warning_icon} );
Slic3r::GUI::set_model_events_from_perl( $self->{model},
$self->{event_object_selection_changed},
$self->{event_object_settings_changed},
$self->{event_remove_object},
$self->{event_update_scene});
} }
# Last correct selected item for each preset # Last correct selected item for each preset
@ -1758,14 +1785,16 @@ sub print_info_box_show {
# my $scrolled_window_panel = $self->{scrolled_window_panel}; # my $scrolled_window_panel = $self->{scrolled_window_panel};
# my $scrolled_window_sizer = $self->{scrolled_window_sizer}; # my $scrolled_window_sizer = $self->{scrolled_window_sizer};
# return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show)); # return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show));
my $panel = $self->{right_panel}; my $panel = $self->{scrolled_window_panel};#$self->{right_panel};
my $sizer = $self->{info_sizer}; my $sizer = $self->{info_sizer};
return if (!$sizer || !$show && ($sizer->IsShown(1) == $show)); # return if (!$sizer || !$show && ($sizer->IsShown(1) == $show));
return if (!$sizer);
Slic3r::GUI::set_show_print_info($show); Slic3r::GUI::set_show_print_info($show);
return if (wxTheApp->{app_config}->get("view_mode") eq "simple"); # return if (wxTheApp->{app_config}->get("view_mode") eq "simple");
if ($show) { # if ($show)
{
my $print_info_sizer = $self->{print_info_sizer}; my $print_info_sizer = $self->{print_info_sizer};
$print_info_sizer->Clear(1); $print_info_sizer->Clear(1);
my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5); my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5);
@ -1803,7 +1832,7 @@ sub print_info_box_show {
# $scrolled_window_sizer->Show(2, $show); # $scrolled_window_sizer->Show(2, $show);
# $scrolled_window_panel->Layout; # $scrolled_window_panel->Layout;
$sizer->Show(1, $show); $sizer->Show(1, $show && wxTheApp->{app_config}->get("view_mode") ne "simple");
$self->Layout; $self->Layout;
$panel->Refresh; $panel->Refresh;
@ -1987,7 +2016,7 @@ sub _get_export_file {
# (i.e. when an object is added/removed/moved/rotated/scaled) # (i.e. when an object is added/removed/moved/rotated/scaled)
sub update { sub update {
my ($self, $force_autocenter) = @_; my ($self, $force_autocenter) = @_;
$self->Freeze;
if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) { if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) {
$self->{model}->center_instances_around_point($self->bed_centerf); $self->{model}->center_instances_around_point($self->bed_centerf);
} }
@ -2013,6 +2042,7 @@ sub update {
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0); Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
$self->{preview3D}->reset_gcode_preview_data if $self->{preview3D}; $self->{preview3D}->reset_gcode_preview_data if $self->{preview3D};
$self->{preview3D}->reload_print if $self->{preview3D}; $self->{preview3D}->reload_print if $self->{preview3D};
$self->Thaw;
} }
# When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes.
@ -2045,7 +2075,8 @@ sub on_extruders_change {
my @presets = $choices->[0]->GetStrings; my @presets = $choices->[0]->GetStrings;
# initialize new choice # initialize new choice
my $choice = Wx::BitmapComboBox->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, [@presets], wxCB_READONLY); # my $choice = Wx::BitmapComboBox->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, [@presets], wxCB_READONLY);
my $choice = Wx::BitmapComboBox->new($self->{scrolled_window_panel}, -1, "", wxDefaultPosition, wxDefaultSize, [@presets], wxCB_READONLY);
my $extruder_idx = scalar @$choices; my $extruder_idx = scalar @$choices;
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down($extruder_idx, @_); } ); EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down($extruder_idx, @_); } );
push @$choices, $choice; push @$choices, $choice;
@ -2072,6 +2103,7 @@ sub on_extruders_change {
$choices->[-1]->Destroy; $choices->[-1]->Destroy;
pop @$choices; pop @$choices;
} }
$self->{right_panel}->Layout;
$self->Layout; $self->Layout;
} }
@ -2455,6 +2487,50 @@ sub select_object {
$self->selection_changed(1); $self->selection_changed(1);
} }
sub select_object_from_cpp {
my ($self, $obj_idx, $vol_idx) = @_;
# remove current selection
foreach my $o (0..$#{$self->{objects}}) {
$self->{objects}->[$o]->selected(0);
}
my $curr = Slic3r::GUI::_3DScene::get_select_by($self->{canvas3D});
if (defined $obj_idx) {
if ($vol_idx == -1){
if ($curr eq 'object') {
$self->{objects}->[$obj_idx]->selected(1);
}
elsif ($curr eq 'volume') {
Slic3r::GUI::_3DScene::set_select_by($self->{canvas3D}, 'object');
}
my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
}
else {
if ($curr eq 'object') {
Slic3r::GUI::_3DScene::set_select_by($self->{canvas3D}, 'volume');
}
my $selections = [];
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D});
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
my $volume_idx = Slic3r::GUI::_3DScene::get_first_volume_id($self->{canvas3D}, $obj_idx);
my $inst_cnt = $self->{model}->objects->[$obj_idx]->instances_count;
for (0..$inst_cnt-1){
Slic3r::GUI::_3DScene::select_volume($self->{canvas3D}, $vol_idx*$inst_cnt + $_ + $volume_idx) if ($volume_idx != -1);
}
}
}
$self->selection_changed(1);
}
sub selected_object { sub selected_object {
my ($self) = @_; my ($self) = @_;
my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} }; my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} };

View File

@ -5,12 +5,12 @@ use utf8;
use Slic3r::Print::State ':steps'; use Slic3r::Print::State ':steps';
use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE wxCB_READONLY); use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE wxCB_READONLY);
use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX EVT_CHOICE EVT_CHECKLISTBOX); use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX EVT_CHOICE EVT_CHECKLISTBOX EVT_SIZE);
use base qw(Wx::Panel Class::Accessor); use base qw(Wx::Panel Class::Accessor);
use Wx::Locale gettext => 'L'; use Wx::Locale gettext => 'L';
__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer)); __PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer double_slider_sizer));
sub new { sub new {
my $class = shift; my $class = shift;
@ -27,47 +27,47 @@ sub new {
Slic3r::GUI::_3DScene::enable_shader($canvas, 1); Slic3r::GUI::_3DScene::enable_shader($canvas, 1);
Slic3r::GUI::_3DScene::set_config($canvas, $config); Slic3r::GUI::_3DScene::set_config($canvas, $config);
$self->canvas($canvas); $self->canvas($canvas);
my $slider_low = Wx::Slider->new( # my $slider_low = Wx::Slider->new(
$self, -1, # $self, -1,
0, # default # 0, # default
0, # min # 0, # min
# we set max to a bogus non-zero value because the MSW implementation of wxSlider # we set max to a bogus non-zero value because the MSW implementation of wxSlider
# will skip drawing the slider if max <= min: # will skip drawing the slider if max <= min:
1, # max # 1, # max
wxDefaultPosition, # wxDefaultPosition,
wxDefaultSize, # wxDefaultSize,
wxVERTICAL | wxSL_INVERSE, # wxVERTICAL | wxSL_INVERSE,
); # );
$self->slider_low($slider_low); # $self->slider_low($slider_low);
my $slider_high = Wx::Slider->new( # my $slider_high = Wx::Slider->new(
$self, -1, # $self, -1,
0, # default # 0, # default
0, # min # 0, # min
# we set max to a bogus non-zero value because the MSW implementation of wxSlider # we set max to a bogus non-zero value because the MSW implementation of wxSlider
# will skip drawing the slider if max <= min: # will skip drawing the slider if max <= min:
1, # max # 1, # max
wxDefaultPosition, # wxDefaultPosition,
wxDefaultSize, # wxDefaultSize,
wxVERTICAL | wxSL_INVERSE, # wxVERTICAL | wxSL_INVERSE,
); # );
$self->slider_high($slider_high); # $self->slider_high($slider_high);
my $z_label_low = $self->{z_label_low} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, # my $z_label_low = $self->{z_label_low} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL); # [40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_low->SetFont($Slic3r::GUI::small_font); # $z_label_low->SetFont($Slic3r::GUI::small_font);
my $z_label_high = $self->{z_label_high} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, # my $z_label_high = $self->{z_label_high} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL); # [40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_high->SetFont($Slic3r::GUI::small_font); # $z_label_high->SetFont($Slic3r::GUI::small_font);
my $z_label_low_idx = $self->{z_label_low_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, # my $z_label_low_idx = $self->{z_label_low_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL); # [40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_low_idx->SetFont($Slic3r::GUI::small_font); # $z_label_low_idx->SetFont($Slic3r::GUI::small_font);
my $z_label_high_idx = $self->{z_label_high_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, # my $z_label_high_idx = $self->{z_label_high_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL); # [40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_high_idx->SetFont($Slic3r::GUI::small_font); # $z_label_high_idx->SetFont($Slic3r::GUI::small_font);
$self->single_layer(0); # $self->single_layer(0);
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, L("1 Layer")); # my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, L("1 Layer"));
my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, L("View")); my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, L("View"));
@ -102,26 +102,31 @@ sub new {
.L("Wipe tower")."|" .L("Wipe tower")."|"
.L("Custom"); .L("Custom");
Slic3r::GUI::create_combochecklist($combochecklist_features, $feature_text, $feature_items, 1); Slic3r::GUI::create_combochecklist($combochecklist_features, $feature_text, $feature_items, 1);
my $double_slider_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
Slic3r::GUI::create_double_slider($self, $double_slider_sizer, $self->canvas);
$self->double_slider_sizer($double_slider_sizer);
my $checkbox_travel = $self->{checkbox_travel} = Wx::CheckBox->new($self, -1, L("Travel")); my $checkbox_travel = $self->{checkbox_travel} = Wx::CheckBox->new($self, -1, L("Travel"));
my $checkbox_retractions = $self->{checkbox_retractions} = Wx::CheckBox->new($self, -1, L("Retractions")); my $checkbox_retractions = $self->{checkbox_retractions} = Wx::CheckBox->new($self, -1, L("Retractions"));
my $checkbox_unretractions = $self->{checkbox_unretractions} = Wx::CheckBox->new($self, -1, L("Unretractions")); my $checkbox_unretractions = $self->{checkbox_unretractions} = Wx::CheckBox->new($self, -1, L("Unretractions"));
my $checkbox_shells = $self->{checkbox_shells} = Wx::CheckBox->new($self, -1, L("Shells")); my $checkbox_shells = $self->{checkbox_shells} = Wx::CheckBox->new($self, -1, L("Shells"));
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); # my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
my $vsizer = Wx::BoxSizer->new(wxVERTICAL); # my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
my $vsizer_outer = Wx::BoxSizer->new(wxVERTICAL); # my $vsizer_outer = Wx::BoxSizer->new(wxVERTICAL);
$vsizer->Add($slider_low, 3, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer->Add($slider_low, 3, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_low_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer->Add($z_label_low_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_low, 0, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer->Add($z_label_low, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$hsizer->Add($vsizer, 0, wxEXPAND, 0); # $hsizer->Add($vsizer, 0, wxEXPAND, 0);
$vsizer = Wx::BoxSizer->new(wxVERTICAL); # $vsizer = Wx::BoxSizer->new(wxVERTICAL);
$vsizer->Add($slider_high, 3, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer->Add($slider_high, 3, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_high_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer->Add($z_label_high_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_high, 0, 0, 0); # $vsizer->Add($z_label_high, 0, 0, 0);
$hsizer->Add($vsizer, 0, wxEXPAND, 0); # $hsizer->Add($vsizer, 0, wxEXPAND, 0);
$vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0); # $vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5); # $vsizer_outer->Add($double_slider_sizer, 3, wxEXPAND, 0);
# $vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5);
my $bottom_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $bottom_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$bottom_sizer->Add($label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5); $bottom_sizer->Add($label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5);
@ -140,81 +145,83 @@ sub new {
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$sizer->Add($canvas, 1, wxALL | wxEXPAND, 0); $sizer->Add($canvas, 1, wxALL | wxEXPAND, 0);
$sizer->Add($vsizer_outer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5); # $sizer->Add($vsizer_outer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5);
$sizer->Add($double_slider_sizer, 0, wxEXPAND, 0);#wxTOP | wxBOTTOM | wxEXPAND, 5);
my $main_sizer = Wx::BoxSizer->new(wxVERTICAL); my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
$main_sizer->Add($sizer, 1, wxALL | wxEXPAND, 0); $main_sizer->Add($sizer, 1, wxALL | wxEXPAND, 0);
$main_sizer->Add($bottom_sizer, 0, wxALL | wxEXPAND, 0); $main_sizer->Add($bottom_sizer, 0, wxALL | wxEXPAND, 0);
EVT_SLIDER($self, $slider_low, sub { # EVT_SLIDER($self, $slider_low, sub {
$slider_high->SetValue($slider_low->GetValue) if $self->single_layer; # $slider_high->SetValue($slider_low->GetValue) if $self->single_layer;
$self->set_z_idx_low ($slider_low ->GetValue) # $self->set_z_idx_low ($slider_low ->GetValue)
}); # });
EVT_SLIDER($self, $slider_high, sub { # EVT_SLIDER($self, $slider_high, sub {
$slider_low->SetValue($slider_high->GetValue) if $self->single_layer; # $slider_low->SetValue($slider_high->GetValue) if $self->single_layer;
$self->set_z_idx_high($slider_high->GetValue) # $self->set_z_idx_high($slider_high->GetValue)
}); # });
EVT_KEY_DOWN($canvas, sub { # EVT_KEY_DOWN($canvas, sub {
my ($s, $event) = @_; # my ($s, $event) = @_;
my $key = $event->GetKeyCode; # Slic3r::GUI::update_double_slider_from_canvas($event);
if ($event->HasModifiers) { # my $key = $event->GetKeyCode;
$event->Skip; # if ($event->HasModifiers) {
} else { # $event->Skip;
if ($key == ord('U')) { # } else {
$slider_high->SetValue($slider_high->GetValue + 1); # if ($key == ord('U')) {
$slider_low->SetValue($slider_high->GetValue) if ($event->ShiftDown()); # $slider_high->SetValue($slider_high->GetValue + 1);
$self->set_z_idx_high($slider_high->GetValue); # $slider_low->SetValue($slider_high->GetValue) if ($event->ShiftDown());
} elsif ($key == ord('D')) { # $self->set_z_idx_high($slider_high->GetValue);
$slider_high->SetValue($slider_high->GetValue - 1); # } elsif ($key == ord('D')) {
$slider_low->SetValue($slider_high->GetValue) if ($event->ShiftDown()); # $slider_high->SetValue($slider_high->GetValue - 1);
$self->set_z_idx_high($slider_high->GetValue); # $slider_low->SetValue($slider_high->GetValue) if ($event->ShiftDown());
} elsif ($key == ord('S')) { # $self->set_z_idx_high($slider_high->GetValue);
$checkbox_singlelayer->SetValue(! $checkbox_singlelayer->GetValue()); # } elsif ($key == ord('S')) {
$self->single_layer($checkbox_singlelayer->GetValue()); # $checkbox_singlelayer->SetValue(! $checkbox_singlelayer->GetValue());
if ($self->single_layer) { # $self->single_layer($checkbox_singlelayer->GetValue());
$slider_low->SetValue($slider_high->GetValue); # if ($self->single_layer) {
$self->set_z_idx_high($slider_high->GetValue); # $slider_low->SetValue($slider_high->GetValue);
} # $self->set_z_idx_high($slider_high->GetValue);
} else { # }
$event->Skip; # } else {
} # $event->Skip;
} # }
}); # }
EVT_KEY_DOWN($slider_low, sub { # });
my ($s, $event) = @_; # EVT_KEY_DOWN($slider_low, sub {
my $key = $event->GetKeyCode; # my ($s, $event) = @_;
if ($event->HasModifiers) { # my $key = $event->GetKeyCode;
$event->Skip; # if ($event->HasModifiers) {
} else { # $event->Skip;
if ($key == WXK_LEFT) { # } else {
} elsif ($key == WXK_RIGHT) { # if ($key == WXK_LEFT) {
$slider_high->SetFocus; # } elsif ($key == WXK_RIGHT) {
} else { # $slider_high->SetFocus;
$event->Skip; # } else {
} # $event->Skip;
} # }
}); # }
EVT_KEY_DOWN($slider_high, sub { # });
my ($s, $event) = @_; # EVT_KEY_DOWN($slider_high, sub {
my $key = $event->GetKeyCode; # my ($s, $event) = @_;
if ($event->HasModifiers) { # my $key = $event->GetKeyCode;
$event->Skip; # if ($event->HasModifiers) {
} else { # $event->Skip;
if ($key == WXK_LEFT) { # } else {
$slider_low->SetFocus; # if ($key == WXK_LEFT) {
} elsif ($key == WXK_RIGHT) { # $slider_low->SetFocus;
} else { # } elsif ($key == WXK_RIGHT) {
$event->Skip; # } else {
} # $event->Skip;
} # }
}); # }
EVT_CHECKBOX($self, $checkbox_singlelayer, sub { # });
$self->single_layer($checkbox_singlelayer->GetValue()); # EVT_CHECKBOX($self, $checkbox_singlelayer, sub {
if ($self->single_layer) { # $self->single_layer($checkbox_singlelayer->GetValue());
$slider_low->SetValue($slider_high->GetValue); # if ($self->single_layer) {
$self->set_z_idx_high($slider_high->GetValue); # $slider_low->SetValue($slider_high->GetValue);
} # $self->set_z_idx_high($slider_high->GetValue);
}); # }
# });
EVT_CHOICE($self, $choice_view_type, sub { EVT_CHOICE($self, $choice_view_type, sub {
my $selection = $choice_view_type->GetCurrentSelection(); my $selection = $choice_view_type->GetCurrentSelection();
$self->{preferred_color_mode} = ($selection == $self->{tool_idx}) ? 'tool' : 'feature'; $self->{preferred_color_mode} = ($selection == $self->{tool_idx}) ? 'tool' : 'feature';
@ -243,6 +250,12 @@ sub new {
$self->gcode_preview_data->set_shells_visible($checkbox_shells->IsChecked()); $self->gcode_preview_data->set_shells_visible($checkbox_shells->IsChecked());
$self->refresh_print; $self->refresh_print;
}); });
EVT_SIZE($self, sub {
my ($s, $event) = @_;
$event->Skip;
$self->Refresh;
});
$self->SetSizer($main_sizer); $self->SetSizer($main_sizer);
$self->SetMinSize($self->GetSize); $self->SetMinSize($self->GetSize);
@ -392,62 +405,69 @@ sub load_print {
sub reset_sliders { sub reset_sliders {
my ($self) = @_; my ($self) = @_;
$self->enabled(0); $self->enabled(0);
$self->set_z_range(0,0); # $self->set_z_range(0,0);
$self->slider_low->Hide; # $self->slider_low->Hide;
$self->slider_high->Hide; # $self->slider_high->Hide;
$self->{z_label_low}->SetLabel(""); # $self->{z_label_low}->SetLabel("");
$self->{z_label_high}->SetLabel(""); # $self->{z_label_high}->SetLabel("");
$self->{z_label_low_idx}->SetLabel(""); # $self->{z_label_low_idx}->SetLabel("");
$self->{z_label_high_idx}->SetLabel(""); # $self->{z_label_high_idx}->SetLabel("");
Slic3r::GUI::reset_double_slider();
$self->double_slider_sizer->Hide(0);
} }
sub update_sliders sub update_sliders
{ {
my ($self, $n_layers) = @_; my ($self, $n_layers) = @_;
my $z_idx_low = $self->slider_low->GetValue; # my $z_idx_low = $self->slider_low->GetValue;
my $z_idx_high = $self->slider_high->GetValue; # my $z_idx_high = $self->slider_high->GetValue;
$self->enabled(1); $self->enabled(1);
$self->slider_low->SetRange(0, $n_layers - 1); # $self->slider_low->SetRange(0, $n_layers - 1);
$self->slider_high->SetRange(0, $n_layers - 1); # $self->slider_high->SetRange(0, $n_layers - 1);
if ($self->{force_sliders_full_range}) { # if ($self->{force_sliders_full_range}) {
$z_idx_low = 0; # $z_idx_low = 0;
$z_idx_high = $n_layers - 1; # $z_idx_high = $n_layers - 1;
} elsif ($z_idx_high < $n_layers && ($self->single_layer || $z_idx_high != 0)) { # } elsif ($z_idx_high < $n_layers && ($self->single_layer || $z_idx_high != 0)) {
# search new indices for nearest z (size of $self->{layers_z} may change in dependence of what is shown) # # search new indices for nearest z (size of $self->{layers_z} may change in dependence of what is shown)
if (defined($self->{z_low})) { # if (defined($self->{z_low})) {
for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) { # for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) {
if ($self->{layers_z}[$i] <= $self->{z_low}) { # if ($self->{layers_z}[$i] <= $self->{z_low}) {
$z_idx_low = $i; # $z_idx_low = $i;
last; # last;
} # }
} # }
} # }
if (defined($self->{z_high})) { # if (defined($self->{z_high})) {
for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) { # for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) {
if ($self->{layers_z}[$i] <= $self->{z_high}) { # if ($self->{layers_z}[$i] <= $self->{z_high}) {
$z_idx_high = $i; # $z_idx_high = $i;
last; # last;
} # }
} # }
} # }
} elsif ($z_idx_high >= $n_layers) { # } elsif ($z_idx_high >= $n_layers) {
# Out of range. Disable 'single layer' view. # # Out of range. Disable 'single layer' view.
$self->single_layer(0); # $self->single_layer(0);
$self->{checkbox_singlelayer}->SetValue(0); # $self->{checkbox_singlelayer}->SetValue(0);
$z_idx_low = 0; # $z_idx_low = 0;
$z_idx_high = $n_layers - 1; # $z_idx_high = $n_layers - 1;
} else { # } else {
$z_idx_low = 0; # $z_idx_low = 0;
$z_idx_high = $n_layers - 1; # $z_idx_high = $n_layers - 1;
} # }
$self->slider_low->SetValue($z_idx_low); # $self->slider_low->SetValue($z_idx_low);
$self->slider_high->SetValue($z_idx_high); # $self->slider_high->SetValue($z_idx_high);
$self->slider_low->Show; # $self->slider_low->Show;
$self->slider_high->Show; # $self->slider_high->Show;
$self->set_z_range($self->{layers_z}[$z_idx_low], $self->{layers_z}[$z_idx_high]); # $self->set_z_range($self->{layers_z}[$z_idx_low], $self->{layers_z}[$z_idx_high]);
Slic3r::GUI::update_double_slider($self->{force_sliders_full_range});
$self->double_slider_sizer->Show(0);
$self->Layout; $self->Layout;
} }

View File

@ -5418,6 +5418,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx)
} }
m_on_select_object_callback.call(obj_id, vol_id); m_on_select_object_callback.call(obj_id, vol_id);
Slic3r::GUI::select_current_volume(obj_id, vol_id);
} }
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors) std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)

View File

@ -116,7 +116,6 @@ wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr; AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr; PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr; PresetUpdater *g_PresetUpdater = nullptr;
_3DScene *g_3DScene = nullptr;
wxColour g_color_label_modified; wxColour g_color_label_modified;
wxColour g_color_label_sys; wxColour g_color_label_sys;
wxColour g_color_label_default; wxColour g_color_label_default;
@ -136,14 +135,9 @@ wxButton* g_wiping_dialog_button = nullptr;
//showed/hided controls according to the view mode //showed/hided controls according to the view mode
wxWindow *g_right_panel = nullptr; wxWindow *g_right_panel = nullptr;
wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr; wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr;
wxBoxSizer *g_expert_mode_part_sizer = nullptr; wxBoxSizer *g_info_sizer = nullptr;
wxBoxSizer *g_scrolled_window_sizer = nullptr;
wxBoxSizer *g_object_list_sizer = nullptr; wxBoxSizer *g_object_list_sizer = nullptr;
wxButton *g_btn_export_gcode = nullptr; std::vector<wxButton*> g_buttons;
wxButton *g_btn_export_stl = nullptr;
wxButton *g_btn_reslice = nullptr;
wxButton *g_btn_print = nullptr;
wxButton *g_btn_send_gcode = nullptr;
wxStaticBitmap *g_manifold_warning_icon = nullptr; wxStaticBitmap *g_manifold_warning_icon = nullptr;
bool g_show_print_info = false; bool g_show_print_info = false;
bool g_show_manifold_warning_icon = false; bool g_show_manifold_warning_icon = false;
@ -224,27 +218,36 @@ void set_preset_updater(PresetUpdater *updater)
g_PresetUpdater = updater; g_PresetUpdater = updater;
} }
void set_3DScene(_3DScene *scene) enum ActionButtons
{ {
g_3DScene = scene; abExportGCode,
} abReslice,
abPrint,
abSendGCode,
};
void set_objects_from_perl( wxWindow* parent, wxBoxSizer *frequently_changed_parameters_sizer, void set_objects_from_perl( wxWindow* parent,
wxBoxSizer *expert_mode_part_sizer, wxBoxSizer *scrolled_window_sizer, wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *info_sizer,
wxButton *btn_export_gcode, wxButton *btn_export_gcode,
wxButton *btn_export_stl, wxButton *btn_reslice, wxButton *btn_reslice,
wxButton *btn_print, wxButton *btn_send_gcode, wxButton *btn_print,
wxButton *btn_send_gcode,
wxStaticBitmap *manifold_warning_icon) wxStaticBitmap *manifold_warning_icon)
{ {
g_right_panel = parent; g_right_panel = parent->GetParent();
g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer; g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer;
g_expert_mode_part_sizer = expert_mode_part_sizer; g_info_sizer = info_sizer;
g_scrolled_window_sizer = scrolled_window_sizer;
g_btn_export_gcode = btn_export_gcode; g_buttons.push_back(btn_export_gcode);
g_btn_export_stl = btn_export_stl; g_buttons.push_back(btn_reslice);
g_btn_reslice = btn_reslice; g_buttons.push_back(btn_print);
g_btn_print = btn_print; g_buttons.push_back(btn_send_gcode);
g_btn_send_gcode = btn_send_gcode;
// Update font style for buttons
for (auto btn : g_buttons)
btn->SetFont(bold_font());
g_manifold_warning_icon = manifold_warning_icon; g_manifold_warning_icon = manifold_warning_icon;
} }
@ -934,12 +937,11 @@ wxString from_u8(const std::string &str)
return wxString::FromUTF8(str.c_str()); return wxString::FromUTF8(str.c_str());
} }
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer, void set_model_events_from_perl(Model &model,
Model &model, int event_object_selection_changed,
int event_object_selection_changed, int event_object_settings_changed,
int event_object_settings_changed, int event_remove_object,
int event_remove_object, int event_update_scene)
int event_update_scene)
{ {
set_event_object_selection_changed(event_object_selection_changed); set_event_object_selection_changed(event_object_selection_changed);
set_event_object_settings_changed(event_object_settings_changed); set_event_object_settings_changed(event_object_settings_changed);
@ -1076,7 +1078,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
}; };
optgroup->append_line(line); optgroup->append_line(line);
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 2); sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2);
m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters
@ -1103,25 +1105,24 @@ void show_frequently_changed_parameters(bool show)
void show_buttons(bool show) void show_buttons(bool show)
{ {
g_btn_export_stl->Show(show); g_buttons[abReslice]->Show(show);
g_btn_reslice->Show(show);
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) {
TabPrinter *tab = dynamic_cast<TabPrinter*>(g_wxTabPanel->GetPage(i)); TabPrinter *tab = dynamic_cast<TabPrinter*>(g_wxTabPanel->GetPage(i));
if (!tab) if (!tab)
continue; continue;
if (g_PresetBundle->printers.get_selected_preset().printer_technology() == ptFFF) { if (g_PresetBundle->printers.get_selected_preset().printer_technology() == ptFFF) {
g_btn_print->Show(show && !tab->m_config->opt_string("serial_port").empty()); g_buttons[abPrint]->Show(show && !tab->m_config->opt_string("serial_port").empty());
g_btn_send_gcode->Show(show && !tab->m_config->opt_string("print_host").empty()); g_buttons[abSendGCode]->Show(show && !tab->m_config->opt_string("print_host").empty());
} }
break; break;
} }
} }
void show_info_sizer(bool show) void show_info_sizer(const bool show, const bool is_update_settings/* = false*/)
{ {
g_scrolled_window_sizer->Show(static_cast<size_t>(0), show); g_info_sizer->Show(static_cast<size_t>(0), show);
g_scrolled_window_sizer->Show(1, show && g_show_print_info); g_info_sizer->Show(1, show && g_show_print_info);
g_manifold_warning_icon->Show(show && g_show_manifold_warning_icon); g_manifold_warning_icon->Show(show && (!is_update_settings && g_show_manifold_warning_icon));
} }
void show_object_name(bool show) void show_object_name(bool show)
@ -1133,20 +1134,10 @@ void show_object_name(bool show)
void update_mode() void update_mode()
{ {
wxWindowUpdateLocker noUpdates(g_right_panel); wxWindowUpdateLocker noUpdates(g_right_panel->GetParent());
// TODO There is a not the best place of it!
//*** Update style of the "Export G-code" button****
if (g_btn_export_gcode->GetFont() != bold_font()){
g_btn_export_gcode->SetBackgroundColour(wxColour(252, 77, 1));
g_btn_export_gcode->SetFont(bold_font());
}
// ***********************************
ConfigMenuIDs mode = get_view_mode(); ConfigMenuIDs mode = get_view_mode();
// show_frequently_changed_parameters(mode >= ConfigMenuModeRegular);
// g_expert_mode_part_sizer->Show(mode == ConfigMenuModeExpert);
g_object_list_sizer->Show(mode == ConfigMenuModeExpert); g_object_list_sizer->Show(mode == ConfigMenuModeExpert);
show_info_sizer(mode == ConfigMenuModeExpert); show_info_sizer(mode == ConfigMenuModeExpert);
show_buttons(mode == ConfigMenuModeExpert); show_buttons(mode == ConfigMenuModeExpert);
@ -1157,7 +1148,7 @@ void update_mode()
// show_collpane_settings(mode == ConfigMenuModeExpert); // show_collpane_settings(mode == ConfigMenuModeExpert);
// ************************* // *************************
g_right_panel->Layout(); g_right_panel->Layout();
g_right_panel->GetParent()->GetParent()->Layout(); g_right_panel->GetParent()->Layout();
} }
bool is_expert_mode(){ bool is_expert_mode(){
@ -1233,6 +1224,20 @@ void get_current_screen_size(unsigned &width, unsigned &height)
height = disp_size.GetHeight(); height = disp_size.GetHeight();
} }
void enable_action_buttons(bool enable)
{
if (g_buttons.empty())
return;
// Update background colour for buttons
const wxColour bgrd_color = enable ? wxColour(224, 224, 224/*255, 96, 0*/) : wxColour(204, 204, 204);
for (auto btn : g_buttons) {
btn->Enable(enable);
btn->SetBackgroundColour(bgrd_color);
}
}
void about() void about()
{ {
AboutDialog dlg; AboutDialog dlg;

View File

@ -35,7 +35,6 @@ class AppConfig;
class PresetUpdater; class PresetUpdater;
class DynamicPrintConfig; class DynamicPrintConfig;
class TabIface; class TabIface;
class _3DScene;
#define _(s) Slic3r::GUI::I18N::translate((s)) #define _(s) Slic3r::GUI::I18N::translate((s))
@ -101,13 +100,10 @@ void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config); void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle); void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater); void set_preset_updater(PresetUpdater *updater);
void set_3DScene(_3DScene *scene);
void set_objects_from_perl( wxWindow* parent, void set_objects_from_perl( wxWindow* parent,
wxBoxSizer *frequently_changed_parameters_sizer, wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *expert_mode_part_sizer, wxBoxSizer *info_sizer,
wxBoxSizer *scrolled_window_sizer,
wxButton *btn_export_gcode, wxButton *btn_export_gcode,
wxButton *btn_export_stl,
wxButton *btn_reslice, wxButton *btn_reslice,
wxButton *btn_print, wxButton *btn_print,
wxButton *btn_send_gcode, wxButton *btn_send_gcode,
@ -186,6 +182,8 @@ bool select_language(wxArrayString & names, wxArrayLong & identifiers);
// update right panel of the Plater according to view mode // update right panel of the Plater according to view mode
void update_mode(); void update_mode();
void show_info_sizer(const bool show, const bool is_update_settinfs = false);
std::vector<Tab *>& get_tabs_list(); std::vector<Tab *>& get_tabs_list();
bool checked_tab(Tab* tab); bool checked_tab(Tab* tab);
void delete_tab_from_list(Tab* tab); void delete_tab_from_list(Tab* tab);
@ -204,12 +202,11 @@ wxString L_str(const std::string &str);
// Return wxString from std::string in UTF8 // Return wxString from std::string in UTF8
wxString from_u8(const std::string &str); wxString from_u8(const std::string &str);
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer, void set_model_events_from_perl(Model &model,
Model &model, int event_object_selection_changed,
int event_object_selection_changed, int event_object_settings_changed,
int event_object_settings_changed, int event_remove_object,
int event_remove_object, int event_update_scene);
int event_update_scene);
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
// Update view mode according to selected menu // Update view mode according to selected menu
void update_mode(); void update_mode();
@ -228,6 +225,9 @@ int get_export_option(wxFileDialog* dlg);
// Returns the dimensions of the screen on which the main frame is displayed // Returns the dimensions of the screen on which the main frame is displayed
void get_current_screen_size(unsigned &width, unsigned &height); void get_current_screen_size(unsigned &width, unsigned &height);
// Update buttons view according to enable/disable
void enable_action_buttons(bool enable);
// Display an About dialog // Display an About dialog
extern void about(); extern void about();
// Ask the destop to open the datadir using the default file explorer. // Ask the destop to open the datadir using the default file explorer.

View File

@ -13,6 +13,9 @@
#include "Geometry.hpp" #include "Geometry.hpp"
#include "slic3r/Utils/FixModelByWin10.hpp" #include "slic3r/Utils/FixModelByWin10.hpp"
#include <wx/glcanvas.h>
#include "3DScene.hpp"
namespace Slic3r namespace Slic3r
{ {
namespace GUI namespace GUI
@ -23,10 +26,12 @@ wxSizer *m_sizer_object_movers = nullptr;
wxDataViewCtrl *m_objects_ctrl = nullptr; wxDataViewCtrl *m_objects_ctrl = nullptr;
PrusaObjectDataViewModel *m_objects_model = nullptr; PrusaObjectDataViewModel *m_objects_model = nullptr;
wxCollapsiblePane *m_collpane_settings = nullptr; wxCollapsiblePane *m_collpane_settings = nullptr;
PrusaDoubleSlider *m_slider = nullptr;
wxGLCanvas *m_preview_canvas = nullptr;
wxIcon m_icon_modifiermesh; wxBitmap m_icon_modifiermesh;
wxIcon m_icon_solidmesh; wxBitmap m_icon_solidmesh;
wxIcon m_icon_manifold_warning; wxBitmap m_icon_manifold_warning;
wxBitmap m_bmp_cog; wxBitmap m_bmp_cog;
wxBitmap m_bmp_split; wxBitmap m_bmp_split;
@ -64,8 +69,6 @@ bool m_part_settings_changed = false;
wxString g_selected_extruder = ""; wxString g_selected_extruder = "";
#endif //__WXOSX__ #endif //__WXOSX__
// typedef std::map<std::string, std::string> t_category_icon;
typedef std::map<std::string, wxBitmap> t_category_icon;
inline t_category_icon& get_category_icon() { inline t_category_icon& get_category_icon() {
static t_category_icon CATEGORY_ICON; static t_category_icon CATEGORY_ICON;
if (CATEGORY_ICON.empty()){ if (CATEGORY_ICON.empty()){
@ -138,11 +141,11 @@ void set_objects_from_model(Model &model) {
} }
void init_mesh_icons(){ void init_mesh_icons(){
m_icon_modifiermesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
m_icon_solidmesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
// init icon for manifold warning // init icon for manifold warning
m_icon_manifold_warning = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
// init bitmap for "Split to sub-objects" context menu // init bitmap for "Split to sub-objects" context menu
m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG); m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG);
@ -233,7 +236,7 @@ wxDataViewColumn* object_ctrl_create_extruder_column(int extruders_count)
void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz) void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
{ {
m_objects_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize); m_objects_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_objects_ctrl->SetInitialSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
objects_sz = new wxBoxSizer(wxVERTICAL); objects_sz = new wxBoxSizer(wxVERTICAL);
objects_sz->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20); objects_sz->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20);
@ -245,9 +248,10 @@ void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT); m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT);
#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE #endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
// column 0(Icon+Text) of the view control: // column 0(Icon+Text) of the view control:
m_objects_ctrl->AppendIconTextColumn(_(L("Name")), 0, wxDATAVIEW_CELL_INERT, 200, // And Icon can be consisting of several bitmaps
wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE); m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(),
0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
// column 1 of the view control: // column 1 of the view control:
m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45,
@ -278,7 +282,7 @@ wxBoxSizer* create_objects_list(wxWindow *win)
m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) { m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) {
object_ctrl_context_menu(); object_ctrl_context_menu();
event.Skip(); // event.Skip();
}); });
m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX
@ -316,15 +320,15 @@ wxBoxSizer* create_edit_object_buttons(wxWindow* win)
//*** button's functions //*** button's functions
btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) { btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win); // on_btn_load(win);
}); });
btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win, true); // on_btn_load(win, true);
}); });
btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win, true, true); // on_btn_load(win, true, true);
}); });
btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); }); btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); });
@ -663,7 +667,7 @@ void add_object_to_list(const std::string &name, ModelObject* model_object)
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges; stats.facets_added + stats.facets_reversed + stats.backwards_edges;
if (errors > 0) { if (errors > 0) {
const wxDataViewIconText data(item_name, m_icon_manifold_warning); const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning);
wxVariant variant; wxVariant variant;
variant << data; variant << data;
m_objects_model->SetValue(variant, item, 0); m_objects_model->SetValue(variant, item, 0);
@ -736,6 +740,24 @@ void select_current_object(int idx)
g_prevent_list_events = false; g_prevent_list_events = false;
} }
void select_current_volume(int idx, int vol_idx)
{
if (vol_idx < 0) {
select_current_object(idx);
return;
}
g_prevent_list_events = true;
m_objects_ctrl->UnselectAll();
if (idx < 0) {
g_prevent_list_events = false;
return;
}
m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx));
part_selection_changed();
g_prevent_list_events = false;
}
void remove() void remove()
{ {
auto item = m_objects_ctrl->GetSelection(); auto item = m_objects_ctrl->GetSelection();
@ -761,8 +783,17 @@ void object_ctrl_selection_changed()
if (m_event_object_selection_changed > 0) { if (m_event_object_selection_changed > 0) {
wxCommandEvent event(m_event_object_selection_changed); wxCommandEvent event(m_event_object_selection_changed);
event.SetInt(int(m_objects_model->GetParent(m_objects_ctrl->GetSelection()) != wxDataViewItem(0))); event.SetId(m_selected_object_id); // set $obj_idx
event.SetId(m_selected_object_id); const wxDataViewItem item = m_objects_ctrl->GetSelection();
if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0))
event.SetInt(-1); // set $vol_idx
else {
const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
if (vol_idx == -2) // is settings item
event.SetInt(m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item))); // set $vol_idx
else
event.SetInt(vol_idx);
}
get_main_frame()->ProcessWindowEvent(event); get_main_frame()->ProcessWindowEvent(event);
} }
@ -775,9 +806,9 @@ void object_ctrl_context_menu()
{ {
wxDataViewItem item; wxDataViewItem item;
wxDataViewColumn* col; wxDataViewColumn* col;
printf("object_ctrl_context_menu\n"); // printf("object_ctrl_context_menu\n");
const wxPoint pt = get_mouse_position_in_control(); const wxPoint pt = get_mouse_position_in_control();
printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y); // printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y);
m_objects_ctrl->HitTest(pt, item, col); m_objects_ctrl->HitTest(pt, item, col);
if (!item) if (!item)
#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX #ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX
@ -791,9 +822,9 @@ void object_ctrl_context_menu()
#else #else
return; return;
#endif // __WXOSX__ #endif // __WXOSX__
printf("item exists\n"); // printf("item exists\n");
const wxString title = col->GetTitle(); const wxString title = col->GetTitle();
printf("title = *%s*\n", title.data().AsChar()); // printf("title = *%s*\n", title.data().AsChar());
if (title == " ") if (title == " ")
show_context_menu(); show_context_menu();
@ -839,6 +870,15 @@ void object_ctrl_item_value_change(wxDataViewEvent& event)
} }
} }
void show_manipulation_og(const bool show)
{
wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer();
if (show == grid_sizer->IsShown(2))
return;
for (size_t id = 2; id < 12; id++)
grid_sizer->Show(id, show);
}
//update_optgroup //update_optgroup
void update_settings_list() void update_settings_list()
{ {
@ -859,14 +899,19 @@ void update_settings_list()
m_option_sizer->Clear(true); m_option_sizer->Clear(true);
if (m_config) bool show_manipulations = true;
const auto item = m_objects_ctrl->GetSelection();
if (m_config && m_objects_model->IsSettingsItem(item))
{ {
auto extra_column = [](wxWindow* parent, const Line& line) auto extra_column = [](wxWindow* parent, const Line& line)
{ {
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("erase.png")), wxBITMAP_TYPE_PNG), auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
#ifdef __WXMSW__
btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif // __WXMSW__
btn->Bind(wxEVT_BUTTON, [opt_key](wxEvent &event){ btn->Bind(wxEVT_BUTTON, [opt_key](wxEvent &event){
(*m_config)->erase(opt_key); (*m_config)->erase(opt_key);
wxTheApp->CallAfter([]() { update_settings_list(); }); wxTheApp->CallAfter([]() { update_settings_list(); });
@ -876,60 +921,75 @@ void update_settings_list()
std::map<std::string, std::vector<std::string>> cat_options; std::map<std::string, std::vector<std::string>> cat_options;
auto opt_keys = (*m_config)->keys(); auto opt_keys = (*m_config)->keys();
if (opt_keys.size() == 1 && opt_keys[0] == "extruder") m_og_settings.resize(0);
return; std::vector<std::string> categories;
if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return;
{
auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : for (auto& opt_key : opt_keys) {
get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size(); auto category = (*m_config)->def()->get(opt_key)->category;
if (category.empty() ||
(category == "Extruders" && extruders_cnt == 1)) continue;
for (auto& opt_key : opt_keys) { std::vector< std::string > new_category;
auto category = (*m_config)->def()->get(opt_key)->category;
if (category.empty() ||
(category == "Extruders" && extruders_cnt==1)) continue;
std::vector< std::string > new_category; auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category);
cat_opt.push_back(opt_key);
if (cat_opt.size() == 1)
cat_options[category] = cat_opt;
}
auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category); for (auto& cat : cat_options) {
cat_opt.push_back(opt_key); if (cat.second.size() == 1 && cat.second[0] == "extruder")
if (cat_opt.size() == 1) continue;
cat_options[category] = cat_opt;
}
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column);
optgroup->label_width = 150;
optgroup->sidetext_width = 70;
m_og_settings.resize(0); for (auto& opt : cat.second)
for (auto& cat : cat_options) { {
if (cat.second.size() == 1 && cat.second[0] == "extruder") if (opt == "extruder")
continue; continue;
Option option = optgroup->get_option(opt);
option.opt.width = 70;
optgroup->append_single_option_line(option);
}
optgroup->reload_config();
m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
m_og_settings.push_back(optgroup);
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column); categories.push_back(cat.first);
optgroup->label_width = 100; }
optgroup->sidetext_width = 70; }
for (auto& opt : cat.second) if (m_og_settings.empty()) {
{ m_objects_ctrl->Select(m_objects_model->Delete(item));
if (opt == "extruder") part_selection_changed();
continue; }
Option option = optgroup->get_option(opt); else {
option.opt.width = 70; if (!categories.empty())
optgroup->append_single_option_line(option); m_objects_model->UpdateSettingsDigest(item, categories);
} show_manipulations = false;
optgroup->reload_config(); }
m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
m_og_settings.push_back(optgroup);
}
} }
show_manipulation_og(show_manipulations);
show_info_sizer(show_manipulations && item && m_objects_model->GetParent(item) == wxDataViewItem(0));
#ifdef __linux__ #ifdef __linux__
no_updates.reset(nullptr); no_updates.reset(nullptr);
#endif #endif
/*get_right_panel()*/parent->Layout(); parent->Layout();
get_right_panel()->GetParent()->GetParent()->Layout(); get_right_panel()->GetParent()->Layout();
} }
void get_settings_choice(wxMenu *menu, int id, bool is_part) void get_settings_choice(wxMenu *menu, int id, bool is_part)
{ {
auto category_name = menu->GetLabel(id); const auto category_name = menu->GetLabel(id);
wxArrayString names; wxArrayString names;
wxArrayInt selections; wxArrayInt selections;
@ -977,15 +1037,35 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part)
(*m_config)->set_key_value(opt_key, m_default_config.get()->option(opt_key)->clone()); (*m_config)->set_key_value(opt_key, m_default_config.get()->option(opt_key)->clone());
} }
// Add settings item for object
const auto item = m_objects_ctrl->GetSelection();
if (item) {
const auto settings_item = m_objects_model->HasSettings(item);
m_objects_ctrl->Select(settings_item ? settings_item :
m_objects_model->AddSettingsChild(item));
#ifndef __WXOSX__
part_selection_changed();
#endif //no __WXOSX__
}
else
update_settings_list(); update_settings_list();
} }
bool cur_item_hase_children() void menu_item_add_generic(wxMenuItem* &menu, int id) {
{ auto sub_menu = new wxMenu;
wxDataViewItemArray children;
if (m_objects_model->GetChildren(m_objects_ctrl->GetSelection(), children) > 0) std::vector<std::string> menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") };
return true; for (auto& item : menu_items)
return false; sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item)));
#ifndef __WXMSW__
sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) {
load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString());
});
#endif //no __WXMSW__
menu->SetSubMenu(sub_menu);
} }
wxMenuItem* menu_item_split(wxMenu* menu, int id) { wxMenuItem* menu_item_split(wxMenu* menu, int id) {
@ -994,11 +1074,11 @@ wxMenuItem* menu_item_split(wxMenu* menu, int id) {
return menu_item; return menu_item;
} }
wxMenuItem* menu_item_settings(wxMenu* menu, int id) { wxMenuItem* menu_item_settings(wxMenu* menu, int id, const bool is_part) {
auto menu_item = new wxMenuItem(menu, id, _(L("Add settings"))); auto menu_item = new wxMenuItem(menu, id, _(L("Add settings")));
menu_item->SetBitmap(m_bmp_cog); menu_item->SetBitmap(m_bmp_cog);
auto sub_menu = create_add_settings_popupmenu(false); auto sub_menu = create_add_settings_popupmenu(is_part);
menu_item->SetSubMenu(sub_menu); menu_item->SetSubMenu(sub_menu);
return menu_item; return menu_item;
} }
@ -1008,44 +1088,54 @@ wxMenu *create_add_part_popupmenu()
wxMenu *menu = new wxMenu; wxMenu *menu = new wxMenu;
std::vector<std::string> menu_items = { L("Add part"), L("Add modifier"), L("Add generic") }; std::vector<std::string> menu_items = { L("Add part"), L("Add modifier"), L("Add generic") };
wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+2); wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+4+2);
int i = 0; int i = 0;
for (auto& item : menu_items) { for (auto& item : menu_items) {
auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item));
menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh);
menu->Append(menu_item); if (item == "Add generic")
menu_item_add_generic(menu_item, config_id_base + i);
menu->Append(menu_item);
i++; i++;
} }
menu->AppendSeparator(); menu->AppendSeparator();
auto menu_item = menu_item_split(menu, config_id_base + i); auto menu_item = menu_item_split(menu, config_id_base + i + 4);
menu->Append(menu_item); menu->Append(menu_item);
menu_item->Enable(!cur_item_hase_children()); menu_item->Enable(is_splittable_object(false));
menu->AppendSeparator(); menu->AppendSeparator();
// Append settings popupmenu // Append settings popupmenu
menu->Append(menu_item_settings(menu, config_id_base + i + 1)); menu->Append(menu_item_settings(menu, config_id_base + i + 5, false));
wxWindow* win = get_tab_panel()->GetPage(0); menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
menu->Bind(wxEVT_MENU, [config_id_base, win, menu](wxEvent &event){
switch (event.GetId() - config_id_base) { switch (event.GetId() - config_id_base) {
case 0: case 0:
on_btn_load(win); on_btn_load();
break; break;
case 1: case 1:
on_btn_load(win, true); on_btn_load(true);
break; break;
case 2: case 2:
on_btn_load(win, true, true); // on_btn_load(true, true);
break; break;
case 3: case 3:
case 4:
case 5:
case 6:
#ifdef __WXMSW__
load_lambda(menu->GetLabel(event.GetId()).ToStdString());
#endif // __WXMSW__
break;
case 7: //3:
on_btn_split(false); on_btn_split(false);
break; break;
default:{ default:
#ifdef __WXMSW__
get_settings_choice(menu, event.GetId(), false); get_settings_choice(menu, event.GetId(), false);
break;} #endif // __WXMSW__
break;
} }
}); });
@ -1057,11 +1147,13 @@ wxMenu *create_part_settings_popupmenu()
wxMenu *menu = new wxMenu; wxMenu *menu = new wxMenu;
wxWindowID config_id_base = wxWindow::NewControlId(2); wxWindowID config_id_base = wxWindow::NewControlId(2);
menu->Append(menu_item_split(menu, config_id_base)); auto menu_item = menu_item_split(menu, config_id_base);
menu->Append(menu_item);
menu_item->Enable(is_splittable_object(true));
menu->AppendSeparator(); menu->AppendSeparator();
// Append settings popupmenu // Append settings popupmenu
menu->Append(menu_item_settings(menu, config_id_base + 1)); menu->Append(menu_item_settings(menu, config_id_base + 1, true));
menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){ menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
switch (event.GetId() - config_id_base) { switch (event.GetId() - config_id_base) {
@ -1093,35 +1185,35 @@ wxMenu *create_add_settings_popupmenu(bool is_part)
wxNullBitmap : categories.at(cat.first)); wxNullBitmap : categories.at(cat.first));
menu->Append(menu_item); menu->Append(menu_item);
} }
#ifndef __WXMSW__
menu->Bind(wxEVT_MENU, [menu](wxEvent &event) { menu->Bind(wxEVT_MENU, [menu](wxEvent &event) {
get_settings_choice(menu, event.GetId(), true); get_settings_choice(menu, event.GetId(), true);
}); });
#endif //no __WXMSW__
return menu; return menu;
} }
void show_context_menu() void show_context_menu()
{ {
auto item = m_objects_ctrl->GetSelection(); const auto item = m_objects_ctrl->GetSelection();
if (item) if (item)
{ {
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { if (m_objects_model->IsSettingsItem(item))
auto menu = create_add_part_popupmenu(); return;
get_tab_panel()->GetPage(0)->PopupMenu(menu); const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ?
} create_add_part_popupmenu() :
else { create_part_settings_popupmenu();
auto menu = create_part_settings_popupmenu(); get_tab_panel()->GetPage(0)->PopupMenu(menu);
get_tab_panel()->GetPage(0)->PopupMenu(menu);
}
} }
} }
// ****** // ******
void load_part( wxWindow* parent, ModelObject* model_object, void load_part( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier) wxArrayString& part_names, const bool is_modifier)
{ {
wxWindow* parent = get_tab_panel()->GetPage(0);
wxArrayString input_files; wxArrayString input_files;
open_model(parent, input_files); open_model(parent, input_files);
for (int i = 0; i < input_files.size(); ++i) { for (int i = 0; i < input_files.size(); ++i) {
@ -1159,10 +1251,10 @@ void load_part( wxWindow* parent, ModelObject* model_object,
} }
} }
void load_lambda( wxWindow* parent, ModelObject* model_object, void load_lambda( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier) wxArrayString& part_names, const bool is_modifier)
{ {
auto dlg = new LambdaObjectDialog(parent); auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow());
if (dlg->ShowModal() == wxID_CANCEL) { if (dlg->ShowModal() == wxID_CANCEL) {
return; return;
} }
@ -1208,7 +1300,49 @@ void load_lambda( wxWindow* parent, ModelObject* model_object,
m_parts_changed = true; m_parts_changed = true;
} }
void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/* = false*/) void load_lambda(const std::string& type_name)
{
if (m_selected_object_id < 0) return;
auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name);
if (dlg->ShowModal() == wxID_CANCEL)
return;
const std::string name = "lambda-"+type_name;
TriangleMesh mesh;
const auto params = dlg->ObjectParameters();
if (type_name == _("Box"))
mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]);
else if (type_name == _("Cylinder"))
mesh = make_cylinder(params.cyl_r, params.cyl_h);
else if (type_name == _("Sphere"))
mesh = make_sphere(params.sph_rho);
else if (type_name == _("Slab")){
const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size();
mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h);
// box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z
mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z);
}
mesh.repair();
auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh);
new_volume->modifier = true;
new_volume->name = name;
// set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
m_parts_changed = true;
parts_changed(m_selected_object_id);
m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(),
name, m_icon_modifiermesh));
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
object_ctrl_selection_changed();
#endif //no __WXOSX__ //__WXMSW__
}
void on_btn_load(bool is_modifier /*= false*/, bool is_lambda/* = false*/)
{ {
auto item = m_objects_ctrl->GetSelection(); auto item = m_objects_ctrl->GetSelection();
if (!item) if (!item)
@ -1222,19 +1356,54 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/
if (obj_idx < 0) return; if (obj_idx < 0) return;
wxArrayString part_names; wxArrayString part_names;
if (is_lambda) if (is_lambda)
load_lambda(parent, (*m_objects)[obj_idx], part_names, is_modifier); load_lambda((*m_objects)[obj_idx], part_names, is_modifier);
else else
load_part(parent, (*m_objects)[obj_idx], part_names, is_modifier); load_part((*m_objects)[obj_idx], part_names, is_modifier);
parts_changed(obj_idx); parts_changed(obj_idx);
for (int i = 0; i < part_names.size(); ++i) for (int i = 0; i < part_names.size(); ++i)
m_objects_ctrl->Select( m_objects_model->AddChild(item, part_names.Item(i), m_objects_ctrl->Select( m_objects_model->AddChild(item, part_names.Item(i),
is_modifier ? m_icon_modifiermesh : m_icon_solidmesh)); is_modifier ? m_icon_modifiermesh : m_icon_solidmesh));
// part_selection_changed(); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
#ifdef __WXMSW__
object_ctrl_selection_changed(); object_ctrl_selection_changed();
#endif //__WXMSW__ #endif //no __WXOSX__//__WXMSW__
}
void remove_settings_from_config()
{
auto opt_keys = (*m_config)->keys();
if (opt_keys.size() == 1 && opt_keys[0] == "extruder")
return;
int extruder = -1;
if ((*m_config)->has("extruder"))
extruder = (*m_config)->option<ConfigOptionInt>("extruder")->value;
(*m_config)->clear();
if (extruder >=0 )
(*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder));
}
bool remove_subobject_from_object(const int volume_id)
{
const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
// if user is deleting the last solid part, throw error
int solid_cnt = 0;
for (auto vol : (*m_objects)[m_selected_object_id]->volumes)
if (!vol->modifier)
++solid_cnt;
if (!volume->modifier && solid_cnt == 1) {
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
return false;
}
(*m_objects)[m_selected_object_id]->delete_volume(volume_id);
m_parts_changed = true;
parts_changed(m_selected_object_id);
return true;
} }
void on_btn_del() void on_btn_del()
@ -1242,50 +1411,67 @@ void on_btn_del()
auto item = m_objects_ctrl->GetSelection(); auto item = m_objects_ctrl->GetSelection();
if (!item) return; if (!item) return;
auto volume_id = m_objects_model->GetVolumeIdByItem(item); const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
if (volume_id < 0) if (volume_id ==-1)
return; return;
auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
if (volume_id ==-2)
// if user is deleting the last solid part, throw error remove_settings_from_config();
int solid_cnt = 0; else if (!remove_subobject_from_object(volume_id))
for (auto vol : (*m_objects)[m_selected_object_id]->volumes) return;
if (!vol->modifier)
++solid_cnt;
if (!volume->modifier && solid_cnt == 1) {
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
return;
}
(*m_objects)[m_selected_object_id]->delete_volume(volume_id);
m_parts_changed = true;
parts_changed(m_selected_object_id);
m_objects_ctrl->Select(m_objects_model->Delete(item)); m_objects_ctrl->Select(m_objects_model->Delete(item));
part_selection_changed(); part_selection_changed();
// #ifdef __WXMSW__ }
// object_ctrl_selection_changed();
// #endif //__WXMSW__ bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume)
{
if (!item || m_selected_object_id < 0)
return false;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
if (volume_id < 0) {
if (split_part) return false;
volume = (*m_objects)[m_selected_object_id]->volumes[0];
}
else
volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
if (volume)
return true;
return false;
}
bool is_splittable_object(const bool split_part)
{
const wxDataViewItem item = m_objects_ctrl->GetSelection();
if (!item) return false;
wxDataViewItemArray children;
if (!split_part && m_objects_model->GetChildren(item, children) > 0)
return false;
ModelVolume* volume;
if (!get_volume_by_item(split_part, item, volume) || !volume)
return false;
TriangleMeshPtrs meshptrs = volume->mesh.split();
if (meshptrs.size() <= 1) {
delete meshptrs.front();
return false;
}
return true;
} }
void on_btn_split(const bool split_part) void on_btn_split(const bool split_part)
{ {
auto item = m_objects_ctrl->GetSelection(); const auto item = m_objects_ctrl->GetSelection();
if (!item || m_selected_object_id<0) if (!item || m_selected_object_id<0)
return; return;
auto volume_id = m_objects_model->GetVolumeIdByItem(item);
ModelVolume* volume; ModelVolume* volume;
if (volume_id < 0) { if (!get_volume_by_item(split_part, item, volume)) return;
if (split_part) return; DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
else const auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
volume = (*m_objects)[m_selected_object_id]->volumes[0]; } if (volume->split(nozzle_dmrs_cnt) == 1) {
else
volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
auto split_rez = volume->split(nozzle_dmrs_cnt);
if (split_rez == 1) {
wxMessageBox(_(L("The selected object couldn't be split because it contains only one part."))); wxMessageBox(_(L("The selected object couldn't be split because it contains only one part.")));
return; return;
} }
@ -1299,7 +1485,8 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++) for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(parent, model_object->volumes[id]->name, m_objects_model->AddChild(parent, model_object->volumes[id]->name,
model_object->volumes[id]->modifier ? m_icon_modifiermesh : m_icon_solidmesh, model_object->volumes[id]->modifier ? m_icon_modifiermesh : m_icon_solidmesh,
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value, model_object->volumes[id]->config.has("extruder") ?
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false); false);
m_objects_ctrl->Expand(parent); m_objects_ctrl->Expand(parent);
@ -1308,10 +1495,14 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++) for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(item, model_object->volumes[id]->name, m_objects_model->AddChild(item, model_object->volumes[id]->name,
m_icon_solidmesh, m_icon_solidmesh,
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value, model_object->volumes[id]->config.has("extruder") ?
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false); false);
m_objects_ctrl->Expand(item); m_objects_ctrl->Expand(item);
} }
m_parts_changed = true;
parts_changed(m_selected_object_id);
} }
void on_btn_move_up(){ void on_btn_move_up(){
@ -1392,33 +1583,49 @@ void part_selection_changed()
auto item = m_objects_ctrl->GetSelection(); auto item = m_objects_ctrl->GetSelection();
int obj_idx = -1; int obj_idx = -1;
auto og = get_optgroup(ogFrequentlyObjectSettings); auto og = get_optgroup(ogFrequentlyObjectSettings);
m_config = nullptr;
wxString object_name = wxEmptyString;
if (item) if (item)
{ {
const bool is_settings_item = m_objects_model->IsSettingsItem(item);
bool is_part = false; bool is_part = false;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { wxString og_name = wxEmptyString;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
obj_idx = m_objects_model->GetIdByItem(item); obj_idx = m_objects_model->GetIdByItem(item);
og->set_name(" " + _(L("Object Settings")) + " "); og_name = _(L("Object manipulation"));
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config); m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
} }
else { else {
auto parent = m_objects_model->GetParent(item); auto parent = m_objects_model->GetParent(item);
// Take ID of the parent object to "inform" perl-side which object have to be selected on the scene // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
obj_idx = m_objects_model->GetIdByItem(parent); obj_idx = m_objects_model->GetIdByItem(parent);
og->set_name(" " + _(L("Part Settings")) + " "); if (is_settings_item) {
is_part = true; if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) {
auto volume_id = m_objects_model->GetVolumeIdByItem(item); og_name = _(L("Object Settings to modify"));
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config); m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
}
else {
og_name = _(L("Part Settings to modify"));
is_part = true;
auto main_parent = m_objects_model->GetParent(parent);
obj_idx = m_objects_model->GetIdByItem(main_parent);
const auto volume_id = m_objects_model->GetVolumeIdByItem(parent);
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
}
}
else {
og_name = _(L("Part manipulation"));
is_part = true;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
}
} }
auto config = m_config; og->set_name(" " + og_name + " ");
og->set_value("object_name", m_objects_model->GetName(item)); object_name = m_objects_model->GetName(item);
m_default_config = std::make_shared<DynamicPrintConfig>(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part))); m_default_config = std::make_shared<DynamicPrintConfig>(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)));
} }
else { og->set_value("object_name", object_name);
wxString empty_str = wxEmptyString;
og->set_value("object_name", empty_str);
m_config = nullptr;
}
update_settings_list(); update_settings_list();
@ -1647,7 +1854,7 @@ void on_begin_drag(wxDataViewEvent &event)
wxDataViewItem item(event.GetItem()); wxDataViewItem item(event.GetItem());
// only allow drags for item, not containers // only allow drags for item, not containers
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) {
event.Veto(); event.Veto();
return; return;
} }
@ -1671,7 +1878,7 @@ void on_drop_possible(wxDataViewEvent &event)
// only allow drags for item or background, not containers // only allow drags for item or background, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
event.GetDataFormat() != wxDF_UNICODETEXT) event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item))
event.Veto(); event.Veto();
} }
@ -1681,7 +1888,7 @@ void on_drop(wxDataViewEvent &event)
// only allow drops for item, not containers // only allow drops for item, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
event.GetDataFormat() != wxDF_UNICODETEXT) { event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) {
event.Veto(); event.Veto();
return; return;
} }
@ -1709,6 +1916,9 @@ void on_drop(wxDataViewEvent &event)
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id+=delta, cnt++) for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id+=delta, cnt++)
std::swap(volumes[id], volumes[id +delta]); std::swap(volumes[id], volumes[id +delta]);
m_parts_changed = true;
parts_changed(m_selected_object_id);
g_prevent_list_events = false; g_prevent_list_events = false;
} }
@ -1725,5 +1935,103 @@ void update_objects_list_extruder_column(int extruders_count)
set_extruder_column_hidden(extruders_count <= 1); set_extruder_column_hidden(extruders_count <= 1);
} }
void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas)
{
m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100);
sizer->Add(m_slider, 0, wxEXPAND, 0);
m_preview_canvas = canvas;
m_preview_canvas->Bind(wxEVT_KEY_DOWN, update_double_slider_from_canvas);
m_slider->Bind(wxEVT_SCROLL_CHANGED, [parent](wxEvent& event) {
_3DScene::set_toolpaths_range(m_preview_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6);
if (parent->IsShown())
m_preview_canvas->Refresh();
});
}
void fill_slider_values(std::vector<std::pair<int, double>> &values,
const std::vector<double> &layers_z)
{
std::vector<double> layers_all_z = _3DScene::get_current_print_zs(m_preview_canvas, false);
if (layers_all_z.size() == layers_z.size())
for (int i = 0; i < layers_z.size(); i++)
values.push_back(std::pair<int, double>(i+1, layers_z[i]));
else if (layers_all_z.size() > layers_z.size()) {
int cur_id = 0;
for (int i = 0; i < layers_z.size(); i++)
for (int j = cur_id; j < layers_all_z.size(); j++)
if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) {
values.push_back(std::pair<int, double>(j+1, layers_z[i]));
cur_id = j;
break;
}
}
}
void set_double_slider_thumbs( const bool force_sliders_full_range,
const std::vector<double> &layers_z,
const double z_low, const double z_high)
{
// Force slider full range only when slider is created.
// Support selected diapason on the all next steps
if (/*force_sliders_full_range*/z_high == 0.0) {
m_slider->SetLowerValue(0);
m_slider->SetHigherValue(layers_z.size() - 1);
return;
}
for (int i = layers_z.size() - 1; i >= 0; i--)
if (z_low >= layers_z[i]) {
m_slider->SetLowerValue(i);
break;
}
for (int i = layers_z.size() - 1; i >= 0 ; i--)
if (z_high >= layers_z[i]) {
m_slider->SetHigherValue(i);
break;
}
}
void update_double_slider(bool force_sliders_full_range)
{
std::vector<std::pair<int, double>> values;
std::vector<double> layers_z = _3DScene::get_current_print_zs(m_preview_canvas, true);
fill_slider_values(values, layers_z);
const double z_low = m_slider->GetLowerValueD();
const double z_high = m_slider->GetHigherValueD();
m_slider->SetMaxValue(layers_z.size() - 1);
m_slider->SetSliderValues(values);
set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high);
}
void reset_double_slider()
{
m_slider->SetHigherValue(0);
m_slider->SetLowerValue(0);
}
void update_double_slider_from_canvas(wxKeyEvent& event)
{
if (event.HasModifiers()) {
event.Skip();
return;
}
const auto key = event.GetKeyCode();
if (key == 'U' || key == 'D') {
const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1;
m_slider->SetHigherValue(new_pos);
if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue());
}
else if (key == 'S')
m_slider->ChangeOneLayerLock();
else
event.Skip();
}
} //namespace GUI } //namespace GUI
} //namespace Slic3r } //namespace Slic3r

View File

@ -9,13 +9,15 @@ class wxArrayString;
class wxMenu; class wxMenu;
class wxDataViewEvent; class wxDataViewEvent;
class wxKeyEvent; class wxKeyEvent;
class wxControl; class wxGLCanvas;
class wxBitmap;
namespace Slic3r { namespace Slic3r {
class ModelObject; class ModelObject;
class Model; class Model;
namespace GUI { namespace GUI {
//class wxGLCanvas;
enum ogGroup{ enum ogGroup{
ogFrequentlyChangingParameters, ogFrequentlyChangingParameters,
@ -44,6 +46,9 @@ struct OBJECT_PARAMETERS
double slab_z = 0.0; double slab_z = 0.0;
}; };
typedef std::map<std::string, wxBitmap> t_category_icon;
inline t_category_icon& get_category_icon();
void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer); void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer);
void add_objects_list(wxWindow* parent, wxBoxSizer* sizer); void add_objects_list(wxWindow* parent, wxBoxSizer* sizer);
void add_object_settings(wxWindow* parent, wxBoxSizer* sizer); void add_object_settings(wxWindow* parent, wxBoxSizer* sizer);
@ -66,16 +71,17 @@ void set_object_count(int idx, int count);
void unselect_objects(); void unselect_objects();
// Select current object in the list on c++ side // Select current object in the list on c++ side
void select_current_object(int idx); void select_current_object(int idx);
// Select current volume in the list on c++ side
void select_current_volume(int idx, int vol_idx);
// Remove objects/sub-object from the list // Remove objects/sub-object from the list
void remove(); void remove();
//void create_double_slider(wxWindow* parent, wxControl* slider);
void object_ctrl_selection_changed(); void object_ctrl_selection_changed();
void object_ctrl_context_menu(); void object_ctrl_context_menu();
void object_ctrl_key_event(wxKeyEvent& event); void object_ctrl_key_event(wxKeyEvent& event);
void object_ctrl_item_value_change(wxDataViewEvent& event); void object_ctrl_item_value_change(wxDataViewEvent& event);
void show_context_menu(); void show_context_menu();
bool is_splittable_object(const bool split_part);
void init_mesh_icons(); void init_mesh_icons();
void set_event_object_selection_changed(const int& event); void set_event_object_selection_changed(const int& event);
@ -87,13 +93,14 @@ void set_objects_from_model(Model &model);
bool is_parts_changed(); bool is_parts_changed();
bool is_part_settings_changed(); bool is_part_settings_changed();
void load_part( wxWindow* parent, ModelObject* model_object, void load_part( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier); wxArrayString& part_names, const bool is_modifier);
void load_lambda(wxWindow* parent, ModelObject* model_object, void load_lambda( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier); wxArrayString& part_names, const bool is_modifier);
void load_lambda( const std::string& type_name);
void on_btn_load(wxWindow* parent, bool is_modifier = false, bool is_lambda = false); void on_btn_load(bool is_modifier = false, bool is_lambda = false);
void on_btn_del(); void on_btn_del();
void on_btn_split(const bool split_part); void on_btn_split(const bool split_part);
void on_btn_move_up(); void on_btn_move_up();
@ -126,6 +133,13 @@ void on_drop(wxDataViewEvent &event);
// update extruder column for objects_ctrl according to extruders count // update extruder column for objects_ctrl according to extruders count
void update_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count);
// Create/Update/Reset double slider on 3dPreview
void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas);
void update_double_slider(bool force_sliders_full_range);
void reset_double_slider();
// update DoubleSlider after keyDown in canvas
void update_double_slider_from_canvas(wxKeyEvent& event);
} //namespace GUI } //namespace GUI
} //namespace Slic3r } //namespace Slic3r
#endif //slic3r_GUI_ObjectParts_hpp_ #endif //slic3r_GUI_ObjectParts_hpp_

View File

@ -10,10 +10,12 @@ namespace GUI
{ {
static wxString dots("", wxConvUTF8); static wxString dots("", wxConvUTF8);
LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent,
const wxString type_name):
m_type_name(type_name)
{ {
Create(parent, wxID_ANY, _(L("Lambda Object")), Create(parent, wxID_ANY, _(L("Lambda Object")),
wxDefaultPosition, wxDefaultSize, parent->GetScreenPosition(), wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER); wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
// instead of double dim[3] = { 1.0, 1.0, 1.0 }; // instead of double dim[3] = { 1.0, 1.0, 1.0 };
@ -24,11 +26,20 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
sizer = new wxBoxSizer(wxVERTICAL); sizer = new wxBoxSizer(wxVERTICAL);
// modificator options // modificator options
m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition, if (m_type_name == wxEmptyString) {
wxDefaultSize, wxCHB_TOP); m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition,
sizer->Add(m_modificator_options_book, 1, wxEXPAND| wxALL, 10); wxDefaultSize, wxCHB_TOP);
sizer->Add(m_modificator_options_book, 1, wxEXPAND | wxALL, 10);
}
else {
m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
sizer->Add(m_panel, 1, wxEXPAND | wxALL, 10);
}
ConfigOptionDef def;
def.width = 70;
auto optgroup = init_modificator_options_page(_(L("Box"))); auto optgroup = init_modificator_options_page(_(L("Box")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int opt_id = opt_key == "l" ? 0 : int opt_id = opt_key == "l" ? 0 :
opt_key == "w" ? 1 : opt_key == "w" ? 1 :
@ -37,8 +48,6 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
object_parameters.dim[opt_id] = boost::any_cast<double>(value); object_parameters.dim[opt_id] = boost::any_cast<double>(value);
}; };
ConfigOptionDef def;
def.width = 70;
def.type = coFloat; def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 }; def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("L"); def.label = L("L");
@ -52,8 +61,10 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.label = L("H"); def.label = L("H");
option = Option(def, "h"); option = Option(def, "h");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Cylinder"))); optgroup = init_modificator_options_page(_(L("Cylinder")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int val = boost::any_cast<int>(value); int val = boost::any_cast<int>(value);
if (opt_key == "cyl_r") if (opt_key == "cyl_r")
@ -66,14 +77,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.type = coInt; def.type = coInt;
def.default_value = new ConfigOptionInt{ 1 }; def.default_value = new ConfigOptionInt{ 1 };
def.label = L("Radius"); def.label = L("Radius");
option = Option(def, "cyl_r"); auto option = Option(def, "cyl_r");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
def.label = L("Height"); def.label = L("Height");
option = Option(def, "cyl_h"); option = Option(def, "cyl_h");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Sphere"))); optgroup = init_modificator_options_page(_(L("Sphere")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
if (opt_key == "sph_rho") if (opt_key == "sph_rho")
object_parameters.sph_rho = boost::any_cast<double>(value); object_parameters.sph_rho = boost::any_cast<double>(value);
@ -83,10 +96,12 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.type = coFloat; def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 }; def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("Rho"); def.label = L("Rho");
option = Option(def, "sph_rho"); auto option = Option(def, "sph_rho");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Slab"))); optgroup = init_modificator_options_page(_(L("Slab")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
double val = boost::any_cast<double>(value); double val = boost::any_cast<double>(value);
if (opt_key == "slab_z") if (opt_key == "slab_z")
@ -96,13 +111,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
else return; else return;
}; };
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("H"); def.label = L("H");
option = Option(def, "slab_h"); auto option = Option(def, "slab_h");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
def.label = L("Initial Z"); def.label = L("Initial Z");
option = Option(def, "slab_z"); option = Option(def, "slab_z");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
}
Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e) Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e)
{ {
@ -127,8 +145,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
} }
})); }));
const auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxButton* btn_OK = static_cast<wxButton*>(FindWindowById(wxID_OK, this)); wxButton* btn_OK = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
@ -155,9 +172,11 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
// Called from the constructor. // Called from the constructor.
// Create a panel for a rectangular / circular / custom bed shape. // Create a panel for a rectangular / circular / custom bed shape.
ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString title){ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wxString& title){
if (!m_type_name.IsEmpty() && m_type_name != title)
return nullptr;
auto panel = new wxPanel(m_modificator_options_book); auto panel = m_type_name.IsEmpty() ? new wxPanel(m_modificator_options_book) : m_panel;
ConfigOptionsGroupShp optgroup; ConfigOptionsGroupShp optgroup;
optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Add")) + " " +title + " " +dots); optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Add")) + " " +title + " " +dots);
@ -165,8 +184,12 @@ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString
m_optgroups.push_back(optgroup); m_optgroups.push_back(optgroup);
panel->SetSizerAndFit(optgroup->sizer); if (m_type_name.IsEmpty()) {
m_modificator_options_book->AddPage(panel, title); panel->SetSizerAndFit(optgroup->sizer);
m_modificator_options_book->AddPage(panel, title);
}
else
panel->SetSizer(optgroup->sizer);
return optgroup; return optgroup;
} }

View File

@ -7,6 +7,8 @@
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/choicebk.h> #include <wx/choicebk.h>
class wxPanel;
namespace Slic3r namespace Slic3r
{ {
namespace GUI namespace GUI
@ -14,16 +16,19 @@ namespace GUI
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>; using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
class LambdaObjectDialog : public wxDialog class LambdaObjectDialog : public wxDialog
{ {
wxChoicebook* m_modificator_options_book; wxChoicebook* m_modificator_options_book = nullptr;
std::vector <ConfigOptionsGroupShp> m_optgroups; std::vector <ConfigOptionsGroupShp> m_optgroups;
wxString m_type_name;
wxPanel* m_panel = nullptr;
public: public:
LambdaObjectDialog(wxWindow* parent); LambdaObjectDialog(wxWindow* parent,
const wxString type_name = wxEmptyString);
~LambdaObjectDialog(){} ~LambdaObjectDialog(){}
bool CanClose() { return true; } // ??? bool CanClose() { return true; } // ???
OBJECT_PARAMETERS& ObjectParameters(){ return object_parameters; } OBJECT_PARAMETERS& ObjectParameters(){ return object_parameters; }
ConfigOptionsGroupShp init_modificator_options_page(wxString title); ConfigOptionsGroupShp init_modificator_options_page(const wxString& title);
// Note whether the window was already closed, so a pending update is not executed. // Note whether the window was already closed, so a pending update is not executed.
bool m_already_closed = false; bool m_already_closed = false;

View File

@ -158,7 +158,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// if we have an extra column, build it // if we have an extra column, build it
if (extra_column) { if (extra_column) {
if (extra_column) { if (extra_column) {
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL, 0); grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3);
} }
else { else {
// if the callback provides no sizer for the extra cell, put a spacer // if the callback provides no sizer for the extra cell, put a spacer

View File

@ -161,8 +161,10 @@ public:
ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) : ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt),
staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){ staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){
stb = new wxStaticBox(_parent, wxID_ANY, title); if (staticbox) {
stb->SetFont(bold_font()); stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(bold_font());
}
sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U; auto num_columns = 1U;
if (label_width != 0) num_columns++; if (label_width != 0) num_columns++;

View File

@ -2,6 +2,7 @@
#include "GUI.hpp" #include "GUI.hpp"
#include "../../libslic3r/Utils.hpp" #include "../../libslic3r/Utils.hpp"
#include "BitmapCache.hpp"
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/statline.h> #include <wx/statline.h>
@ -357,11 +358,53 @@ void PrusaObjectDataViewModelNode::set_part_action_icon() {
m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG); m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG);
} }
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories)
{
if (m_type != "settings" || m_opt_categories == categories)
return false;
m_opt_categories = categories;
m_name = wxEmptyString;
m_icon = m_empty_icon;
auto categories_icon = Slic3r::GUI::get_category_icon();
for (auto& cat : m_opt_categories)
m_name += cat + "; ";
wxBitmap *bmp = m_bitmap_cache->find(m_name.ToStdString());
if (bmp == nullptr) {
std::vector<wxBitmap> bmps;
for (auto& cat : m_opt_categories)
bmps.emplace_back(categories_icon.find(cat) == categories_icon.end() ?
wxNullBitmap : categories_icon.at(cat));
bmp = m_bitmap_cache->insert(m_name.ToStdString(), bmps);
}
m_bmp = *bmp;
return true;
}
// ***************************************************************************** // *****************************************************************************
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// PrusaObjectDataViewModel // PrusaObjectDataViewModel
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
PrusaObjectDataViewModel::PrusaObjectDataViewModel()
{
m_bitmap_cache = new Slic3r::GUI::BitmapCache;
}
PrusaObjectDataViewModel::~PrusaObjectDataViewModel()
{
for (auto object : m_objects)
delete object;
delete m_bitmap_cache;
m_bitmap_cache = nullptr;
}
wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name) wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name)
{ {
auto root = new PrusaObjectDataViewModelNode(name); auto root = new PrusaObjectDataViewModelNode(name);
@ -386,34 +429,50 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int ins
wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_item, wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_item,
const wxString &name, const wxString &name,
const wxIcon& icon, const wxBitmap& icon,
const int extruder/* = 0*/, const int extruder/* = 0*/,
const bool create_frst_child/* = true*/) const bool create_frst_child/* = true*/)
{ {
PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID();
if (!root) return wxDataViewItem(0); if (!root) return wxDataViewItem(0);
wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder);
if (root->GetChildren().Count() == 0 && create_frst_child) if (create_frst_child && (root->GetChildren().Count() == 0 ||
(root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == "settings")))
{ {
auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);
auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0);
root->Append(node); root->Append(node);
// notify control // notify control
wxDataViewItem child((void*)node); const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child); ItemAdded(parent_item, child);
} }
auto volume_id = root->GetChildCount(); const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == "settings" ?
auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); root->GetChildCount() - 1 : root->GetChildCount();
const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id);
root->Append(node); root->Append(node);
// notify control // notify control
wxDataViewItem child((void*)node); const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child); ItemAdded(parent_item, child);
return child; return child;
} }
wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem &parent_item)
{
PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID();
if (!root) return wxDataViewItem(0);
const auto node = new PrusaObjectDataViewModelNode(root);
root->Insert(node, 0);
// notify control
const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child);
return child;
}
wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
{ {
auto ret_item = wxDataViewItem(0); auto ret_item = wxDataViewItem(0);
@ -438,7 +497,7 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
//update volume_id value for remaining child-nodes //update volume_id value for remaining child-nodes
auto children = node_parent->GetChildren(); auto children = node_parent->GetChildren();
for (size_t i = 0; i < node_parent->GetChildCount(); i++) for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++)
{ {
auto volume_id = children[i]->GetVolumeId(); auto volume_id = children[i]->GetVolumeId();
if (volume_id > v_id) if (volume_id > v_id)
@ -460,9 +519,10 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
delete node; delete node;
// set m_containet to FALSE if parent has no child // set m_containet to FALSE if parent has no child
if (node_parent && node_parent->GetChildCount() == 0){ if (node_parent) {
#ifndef __WXGTK__ #ifndef __WXGTK__
node_parent->m_container = false; if (node_parent->GetChildCount() == 0)
node_parent->m_container = false;
#endif //__WXGTK__ #endif //__WXGTK__
ret_item = parent; ret_item = parent;
} }
@ -522,6 +582,26 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemById(int obj_idx)
} }
wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx)
{
if (obj_idx >= m_objects.size()) {
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
}
auto parent = m_objects[obj_idx];
if (parent->GetChildCount() == 0) {
printf("Error! Object has no one volume.\n");
return wxDataViewItem(0);
}
for (size_t i = 0; i < parent->GetChildCount(); i++)
if (parent->GetNthChild(i)->m_volume_id == volume_idx)
return wxDataViewItem(parent->GetNthChild(i));
return wxDataViewItem(0);
}
int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item) int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item)
{ {
wxASSERT(item.IsOk()); wxASSERT(item.IsOk());
@ -534,7 +614,7 @@ int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item)
return it - m_objects.begin(); return it - m_objects.begin();
} }
int PrusaObjectDataViewModel::GetVolumeIdByItem(wxDataViewItem& item) int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item)
{ {
wxASSERT(item.IsOk()); wxASSERT(item.IsOk());
@ -568,6 +648,12 @@ wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const
return node->m_icon; return node->m_icon;
} }
wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const
{
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
return node->m_bmp;
}
void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const
{ {
wxASSERT(item.IsOk()); wxASSERT(item.IsOk());
@ -576,8 +662,8 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem
switch (col) switch (col)
{ {
case 0:{ case 0:{
const wxDataViewIconText data(node->m_name, node->m_icon); const PrusaDataViewBitmapText data(node->m_name, node->m_bmp);
variant << data; variant << data;
break;} break;}
case 1: case 1:
variant = node->m_copy; variant = node->m_copy;
@ -667,26 +753,35 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i
if (!node_parent) // happens if item.IsOk()==false if (!node_parent) // happens if item.IsOk()==false
return ret_item; return ret_item;
PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id); const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0;
PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift);
node_parent->GetChildren().Remove(deleted_node); node_parent->GetChildren().Remove(deleted_node);
ItemDeleted(parent, wxDataViewItem(deleted_node)); ItemDeleted(parent, wxDataViewItem(deleted_node));
node_parent->Insert(deleted_node, new_volume_id); node_parent->Insert(deleted_node, new_volume_id+shift);
ItemAdded(parent, wxDataViewItem(deleted_node)); ItemAdded(parent, wxDataViewItem(deleted_node));
const auto settings_item = HasSettings(wxDataViewItem(deleted_node));
if (settings_item)
ItemAdded(wxDataViewItem(deleted_node), settings_item);
//update volume_id value for child-nodes //update volume_id value for child-nodes
auto children = node_parent->GetChildren(); auto children = node_parent->GetChildren();
int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id; int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id;
int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id; int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id;
for (int id = id_frst; id <= id_last; ++id) for (int id = id_frst; id <= id_last; ++id)
children[id]->SetVolumeId(id); children[id+shift]->SetVolumeId(id);
return wxDataViewItem(node_parent->GetNthChild(new_volume_id)); return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift));
} }
// bool MyObjectTreeModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const bool PrusaObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const
// { {
// wxASSERT(item.IsOk());
// } PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
// disable extruder selection for the "Settings" item
return !(col == 2 && node->m_extruder.IsEmpty());
}
wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) const wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) const
{ {
@ -738,6 +833,87 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent,
return count; return count;
} }
wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const
{
if (!item.IsOk())
return wxDataViewItem(0);
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
if (node->GetChildCount() == 0)
return wxDataViewItem(0);
auto& children = node->GetChildren();
if (children[0]->m_type == "settings")
return wxDataViewItem((void*)children[0]);;
return wxDataViewItem(0);
}
bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const
{
if (!item.IsOk())
return false;
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
return node->m_type == "settings";
}
void PrusaObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item,
const std::vector<std::string>& categories)
{
if (!item.IsOk()) return;
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
if (!node->update_settings_digest(categories))
return;
ItemChanged(item);
}
IMPLEMENT_VARIANT_OBJECT(PrusaDataViewBitmapText)
// ---------------------------------------------------------
// PrusaIconTextRenderer
// ---------------------------------------------------------
bool PrusaBitmapTextRenderer::SetValue(const wxVariant &value)
{
m_value << value;
return true;
}
bool PrusaBitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const
{
return false;
}
bool PrusaBitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state)
{
int xoffset = 0;
const wxBitmap& icon = m_value.GetBitmap();
if (icon.IsOk())
{
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon.GetHeight()) / 2);
xoffset = icon.GetWidth() + 4;
}
RenderText(m_value.GetText(), xoffset, rect, dc, state);
return true;
}
wxSize PrusaBitmapTextRenderer::GetSize() const
{
if (!m_value.GetText().empty())
{
wxSize size = GetTextExtent(m_value.GetText());
if (m_value.GetBitmap().IsOk())
size.x += m_value.GetBitmap().GetWidth() + 4;
return size;
}
return wxSize(80, 20);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// PrusaDoubleSlider // PrusaDoubleSlider
@ -829,16 +1005,28 @@ wxSize PrusaDoubleSlider::DoGetBestSize() const
void PrusaDoubleSlider::SetLowerValue(const int lower_val) void PrusaDoubleSlider::SetLowerValue(const int lower_val)
{ {
m_selection = ssLower;
m_lower_value = lower_val; m_lower_value = lower_val;
correct_lower_value();
Refresh(); Refresh();
Update(); Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
} }
void PrusaDoubleSlider::SetHigherValue(const int higher_val) void PrusaDoubleSlider::SetHigherValue(const int higher_val)
{ {
m_selection = ssHigher;
m_higher_value = higher_val; m_higher_value = higher_val;
correct_higher_value();
Refresh(); Refresh();
Update(); Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
} }
void PrusaDoubleSlider::SetMaxValue(const int max_value) void PrusaDoubleSlider::SetMaxValue(const int max_value)
@ -905,6 +1093,13 @@ void PrusaDoubleSlider::get_size(int *w, int *h)
is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim; is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim;
} }
double PrusaDoubleSlider::get_double_value(const SelectedSlider& selection) const
{
if (m_values.empty())
return 0.0;
return m_values[selection == ssLower ? m_lower_value : m_higher_value].second;
}
void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos) void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos)
{ {
const double step = get_scroll_step(); const double step = get_scroll_step();
@ -1010,7 +1205,7 @@ wxString PrusaDoubleSlider::get_label(const SelectedSlider& selection) const
void PrusaDoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const void PrusaDoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const
{ {
if (m_is_one_layer && selection != m_selection || !selection) if ((m_is_one_layer || m_higher_value==m_lower_value) && selection != m_selection || !selection)
return; return;
wxCoord text_width, text_height; wxCoord text_width, text_height;
const wxString label = get_label(selection); const wxString label = get_label(selection);
@ -1178,6 +1373,20 @@ bool PrusaDoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect)
return false; return false;
} }
void PrusaDoubleSlider::ChangeOneLayerLock()
{
m_is_one_layer = !m_is_one_layer;
m_selection == ssLower ? correct_lower_value() : correct_higher_value();
if (!m_selection) m_selection = ssHigher;
Refresh();
Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
}
void PrusaDoubleSlider::OnLeftDown(wxMouseEvent& event) void PrusaDoubleSlider::OnLeftDown(wxMouseEvent& event)
{ {
this->CaptureMouse(); this->CaptureMouse();
@ -1245,6 +1454,10 @@ void PrusaDoubleSlider::OnMotion(wxMouseEvent& event)
Refresh(); Refresh();
Update(); Update();
event.Skip(); event.Skip();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
} }
void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event) void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event)

View File

@ -144,6 +144,49 @@ public:
#endif //__WXMSW__ #endif //__WXMSW__
// ***************************************************************************** // *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaDataViewBitmapText: helper class used by PrusaBitmapTextRenderer
// ----------------------------------------------------------------------------
class PrusaDataViewBitmapText : public wxObject
{
public:
PrusaDataViewBitmapText(const wxString &text = wxEmptyString,
const wxBitmap& bmp = wxNullBitmap) :
m_text(text), m_bmp(bmp)
{ }
PrusaDataViewBitmapText(const PrusaDataViewBitmapText &other)
: wxObject(),
m_text(other.m_text),
m_bmp(other.m_bmp)
{ }
void SetText(const wxString &text) { m_text = text; }
wxString GetText() const { return m_text; }
void SetBitmap(const wxIcon &icon) { m_bmp = icon; }
const wxBitmap &GetBitmap() const { return m_bmp; }
bool IsSameAs(const PrusaDataViewBitmapText& other) const {
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
}
bool operator==(const PrusaDataViewBitmapText& other) const {
return IsSameAs(other);
}
bool operator!=(const PrusaDataViewBitmapText& other) const {
return !IsSameAs(other);
}
private:
wxString m_text;
wxBitmap m_bmp;
};
DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel // PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -155,7 +198,9 @@ class PrusaObjectDataViewModelNode
{ {
PrusaObjectDataViewModelNode* m_parent; PrusaObjectDataViewModelNode* m_parent;
MyObjectTreeModelNodePtrArray m_children; MyObjectTreeModelNodePtrArray m_children;
wxIcon m_empty_icon; wxIcon m_empty_icon;
wxBitmap m_empty_bmp;
std::vector< std::string > m_opt_categories;
public: public:
PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) { PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) {
m_parent = NULL; m_parent = NULL;
@ -174,18 +219,31 @@ public:
PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent,
const wxString& sub_obj_name, const wxString& sub_obj_name,
const wxIcon& icon, const wxBitmap& bmp,
const wxString& extruder, const wxString& extruder,
const int volume_id=-1) { const int volume_id=-1) {
m_parent = parent; m_parent = parent;
m_name = sub_obj_name; m_name = sub_obj_name;
m_copy = wxEmptyString; m_copy = wxEmptyString;
m_icon = icon; m_bmp = bmp;
m_type = "volume"; m_type = "volume";
m_volume_id = volume_id; m_volume_id = volume_id;
m_extruder = extruder; m_extruder = extruder;
#ifdef __WXGTK__
// it's necessary on GTK because of control have to know if this item will be container
// in another case you couldn't to add subitem for this item
// it will be produce "segmentation fault"
m_container = true;
#endif //__WXGTK__
set_part_action_icon(); set_part_action_icon();
} }
PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent) :
m_parent(parent),
m_name("Settings to modified"),
m_copy(wxEmptyString),
m_type("settings"),
m_extruder(wxEmptyString) {}
~PrusaObjectDataViewModelNode() ~PrusaObjectDataViewModelNode()
{ {
@ -200,9 +258,10 @@ public:
wxString m_name; wxString m_name;
wxIcon& m_icon = m_empty_icon; wxIcon& m_icon = m_empty_icon;
wxBitmap& m_bmp = m_empty_bmp;
wxString m_copy; wxString m_copy;
std::string m_type; std::string m_type;
int m_volume_id; int m_volume_id = -2;
bool m_container = false; bool m_container = false;
wxString m_extruder = "default"; wxString m_extruder = "default";
wxBitmap m_action_icon; wxBitmap m_action_icon;
@ -226,6 +285,8 @@ public:
} }
void Insert(PrusaObjectDataViewModelNode* child, unsigned int n) void Insert(PrusaObjectDataViewModelNode* child, unsigned int n)
{ {
if (!m_container)
m_container = true;
m_children.Insert(child, n); m_children.Insert(child, n);
} }
void Append(PrusaObjectDataViewModelNode* child) void Append(PrusaObjectDataViewModelNode* child)
@ -258,9 +319,9 @@ public:
switch (col) switch (col)
{ {
case 0:{ case 0:{
wxDataViewIconText data; PrusaDataViewBitmapText data;
data << variant; data << variant;
m_icon = data.GetIcon(); m_bmp = data.GetBitmap();
m_name = data.GetText(); m_name = data.GetText();
return true;} return true;}
case 1: case 1:
@ -281,6 +342,11 @@ public:
{ {
m_icon = icon; m_icon = icon;
} }
void SetBitmap(const wxBitmap &icon)
{
m_bmp = icon;
}
void SetType(const std::string& type){ void SetType(const std::string& type){
m_type = type; m_type = type;
@ -326,6 +392,7 @@ public:
// Set action icons for node // Set action icons for node
void set_object_action_icon(); void set_object_action_icon();
void set_part_action_icon(); void set_part_action_icon();
bool update_settings_digest(const std::vector<std::string>& categories);
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -336,26 +403,24 @@ class PrusaObjectDataViewModel :public wxDataViewModel
{ {
std::vector<PrusaObjectDataViewModelNode*> m_objects; std::vector<PrusaObjectDataViewModelNode*> m_objects;
public: public:
PrusaObjectDataViewModel(){} PrusaObjectDataViewModel();
~PrusaObjectDataViewModel() ~PrusaObjectDataViewModel();
{
for (auto object : m_objects)
delete object;
}
wxDataViewItem Add(const wxString &name); wxDataViewItem Add(const wxString &name);
wxDataViewItem Add(const wxString &name, const int instances_count); wxDataViewItem Add(const wxString &name, const int instances_count);
wxDataViewItem AddChild(const wxDataViewItem &parent_item, wxDataViewItem AddChild(const wxDataViewItem &parent_item,
const wxString &name, const wxString &name,
const wxIcon& icon, const wxBitmap& icon,
const int = 0, const int extruder = 0,
const bool create_frst_child = true); const bool create_frst_child = true);
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem Delete(const wxDataViewItem &item);
void DeleteAll(); void DeleteAll();
void DeleteChildren(wxDataViewItem& parent); void DeleteChildren(wxDataViewItem& parent);
wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemById(int obj_idx);
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
int GetIdByItem(wxDataViewItem& item); int GetIdByItem(wxDataViewItem& item);
int GetVolumeIdByItem(wxDataViewItem& item); int GetVolumeIdByItem(const wxDataViewItem& item);
bool IsEmpty() { return m_objects.empty(); } bool IsEmpty() { return m_objects.empty(); }
// helper method for wxLog // helper method for wxLog
@ -363,6 +428,7 @@ public:
wxString GetName(const wxDataViewItem &item) const; wxString GetName(const wxDataViewItem &item) const;
wxString GetCopy(const wxDataViewItem &item) const; wxString GetCopy(const wxDataViewItem &item) const;
wxIcon& GetIcon(const wxDataViewItem &item) const; wxIcon& GetIcon(const wxDataViewItem &item) const;
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
// helper methods to change the model // helper methods to change the model
@ -383,8 +449,7 @@ public:
int new_volume_id, int new_volume_id,
const wxDataViewItem &parent); const wxDataViewItem &parent);
// virtual bool IsEnabled(const wxDataViewItem &item, virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
// unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
virtual bool IsContainer(const wxDataViewItem &item) const override; virtual bool IsContainer(const wxDataViewItem &item) const override;
@ -394,8 +459,35 @@ public:
// Is the container just a header or an item with all columns // Is the container just a header or an item with all columns
// In our case it is an item with all columns // In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
wxDataViewItem HasSettings(const wxDataViewItem &item) const;
bool IsSettingsItem(const wxDataViewItem &item) const;
void UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories);
}; };
// ----------------------------------------------------------------------------
// PrusaBitmapTextRenderer
// ----------------------------------------------------------------------------
class PrusaBitmapTextRenderer : public wxDataViewCustomRenderer
{
public:
PrusaBitmapTextRenderer( wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT):
wxDataViewCustomRenderer(wxT("wxObject"), mode, align) {}
bool SetValue(const wxVariant &value);
bool GetValue(wxVariant &value) const;
virtual bool Render(wxRect cell, wxDC *dc, int state);
virtual wxSize GetSize() const;
virtual bool HasEditorCtrl() const { return false; }
private:
// wxDataViewIconText m_value;
PrusaDataViewBitmapText m_value;
};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -516,7 +608,7 @@ public:
int maxValue, int maxValue,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxSL_HORIZONTAL, long style = wxSL_VERTICAL,
const wxValidator& val = wxDefaultValidator, const wxValidator& val = wxDefaultValidator,
const wxString& name = wxEmptyString); const wxString& name = wxEmptyString);
~PrusaDoubleSlider(){} ~PrusaDoubleSlider(){}
@ -528,6 +620,8 @@ public:
return m_higher_value; return m_higher_value;
} }
int GetActiveValue() const; int GetActiveValue() const;
double GetLowerValueD() const { return get_double_value(ssLower); }
double GetHigherValueD() const { return get_double_value(ssHigher); }
wxSize DoGetBestSize() const override; wxSize DoGetBestSize() const override;
void SetLowerValue(const int lower_val); void SetLowerValue(const int lower_val);
void SetHigherValue(const int higher_val); void SetHigherValue(const int higher_val);
@ -538,6 +632,7 @@ public:
void SetSliderValues(const std::vector<std::pair<int, double>>& values) { void SetSliderValues(const std::vector<std::pair<int, double>>& values) {
m_values = values; m_values = values;
} }
void ChangeOneLayerLock();
void OnPaint(wxPaintEvent& ){ render();} void OnPaint(wxPaintEvent& ){ render();}
void OnLeftDown(wxMouseEvent& event); void OnLeftDown(wxMouseEvent& event);
@ -583,6 +678,7 @@ protected:
wxCoord get_position_from_value(const int value); wxCoord get_position_from_value(const int value);
wxSize get_size(); wxSize get_size();
void get_size(int *w, int *h); void get_size(int *w, int *h);
double get_double_value(const SelectedSlider& selection) const;
private: private:
int m_min_value; int m_min_value;

View File

@ -87,26 +87,21 @@ void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_siz
(wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"),
(wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %}; (wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %};
void add_expert_mode_part( SV *ui_parent, SV *ui_sizer, void set_model_events_from_perl(Model *model,
Model *model, int event_object_selection_changed,
int event_object_selection_changed, int event_object_settings_changed,
int event_object_settings_changed, int event_remove_object,
int event_remove_object, int event_update_scene)
int event_update_scene) %code%{ Slic3r::GUI::set_model_events_from_perl(*model,
%code%{ Slic3r::GUI::add_expert_mode_part( (wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), event_object_selection_changed,
(wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), event_object_settings_changed,
*model, event_remove_object,
event_object_selection_changed, event_update_scene); %};
event_object_settings_changed,
event_remove_object,
event_update_scene); %};
void set_objects_from_perl( SV *ui_parent, void set_objects_from_perl( SV *ui_parent,
SV *frequently_changed_parameters_sizer, SV *frequently_changed_parameters_sizer,
SV *expert_mode_part_sizer, SV *info_sizer,
SV *scrolled_window_sizer,
SV *btn_export_gcode, SV *btn_export_gcode,
SV *btn_export_stl,
SV *btn_reslice, SV *btn_reslice,
SV *btn_print, SV *btn_print,
SV *btn_send_gcode, SV *btn_send_gcode,
@ -114,10 +109,8 @@ void set_objects_from_perl( SV *ui_parent,
%code%{ Slic3r::GUI::set_objects_from_perl( %code%{ Slic3r::GUI::set_objects_from_perl(
(wxWindow *)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), (wxWindow *)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ frequently_changed_parameters_sizer, "Wx::BoxSizer"), (wxBoxSizer *)wxPli_sv_2_object(aTHX_ frequently_changed_parameters_sizer, "Wx::BoxSizer"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ expert_mode_part_sizer, "Wx::BoxSizer"), (wxBoxSizer *)wxPli_sv_2_object(aTHX_ info_sizer, "Wx::BoxSizer"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ scrolled_window_sizer, "Wx::BoxSizer"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_export_gcode, "Wx::Button"), (wxButton *)wxPli_sv_2_object(aTHX_ btn_export_gcode, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_export_stl, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_reslice, "Wx::Button"), (wxButton *)wxPli_sv_2_object(aTHX_ btn_reslice, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_print, "Wx::Button"), (wxButton *)wxPli_sv_2_object(aTHX_ btn_print, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_send_gcode, "Wx::Button"), (wxButton *)wxPli_sv_2_object(aTHX_ btn_send_gcode, "Wx::Button"),
@ -152,6 +145,9 @@ void unselect_objects()
void select_current_object(int idx) void select_current_object(int idx)
%code%{ Slic3r::GUI::select_current_object(idx); %}; %code%{ Slic3r::GUI::select_current_object(idx); %};
void select_current_volume(int idx, int vol_idx)
%code%{ Slic3r::GUI::select_current_volume(idx, vol_idx); %};
void remove_obj() void remove_obj()
%code%{ Slic3r::GUI::remove(); %}; %code%{ Slic3r::GUI::remove(); %};
@ -170,16 +166,23 @@ void desktop_open_datadir_folder()
void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst) void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst)
%code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %}; %code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %};
void set_3DScene(SV *scene)
%code%{ Slic3r::GUI::set_3DScene((_3DScene *)wxPli_sv_2_object(aTHX_ scene, "Slic3r::Model::3DScene") ); %};
void register_on_request_update_callback(SV* callback) void register_on_request_update_callback(SV* callback)
%code%{ Slic3r::GUI::g_on_request_update_callback.register_callback(callback); %}; %code%{ Slic3r::GUI::g_on_request_update_callback.register_callback(callback); %};
void deregister_on_request_update_callback() void deregister_on_request_update_callback()
%code%{ Slic3r::GUI::g_on_request_update_callback.deregister_callback(); %}; %code%{ Slic3r::GUI::g_on_request_update_callback.deregister_callback(); %};
//void create_double_slider(SV *ui_parent, SV *ui_ds) void create_double_slider(SV *ui_parent, SV *ui_sizer, SV *ui_canvas)
// %code%{ Slic3r::GUI::create_double_slider( (wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), %code%{ Slic3r::GUI::create_double_slider( (wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"),
// (wxControl*)wxPli_sv_2_object(aTHX_ ui_ds, "Wx::Control")); %}; (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"),
(wxGLCanvas*)wxPli_sv_2_object(aTHX_ ui_canvas, "Wx::GLCanvas")); %};
void update_double_slider(bool force_sliders_full_range)
%code%{ Slic3r::GUI::update_double_slider(force_sliders_full_range); %};
void reset_double_slider()
%code%{ Slic3r::GUI::reset_double_slider(); %};
void enable_action_buttons(bool enable)
%code%{ Slic3r::GUI::enable_action_buttons(enable); %};