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