mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
Merge branch 'master' into amf_activate_existing_presets
This commit is contained in:
commit
68e82a7348
30 changed files with 931 additions and 543 deletions
|
@ -49,6 +49,7 @@ my \$defines = ' ' . Alien::wxWidgets->defines;
|
||||||
my \$cflags = Alien::wxWidgets->c_flags;
|
my \$cflags = Alien::wxWidgets->c_flags;
|
||||||
my \$linkflags = Alien::wxWidgets->link_flags;
|
my \$linkflags = Alien::wxWidgets->link_flags;
|
||||||
my \$libraries = ' ' . Alien::wxWidgets->libraries(@components);
|
my \$libraries = ' ' . Alien::wxWidgets->libraries(@components);
|
||||||
|
my \$gui_toolkit = Alien::wxWidgets->config->{toolkit};
|
||||||
#my @libraries = Alien::wxWidgets->link_libraries(@components);
|
#my @libraries = Alien::wxWidgets->link_libraries(@components);
|
||||||
#my @implib = Alien::wxWidgets->import_libraries(@components);
|
#my @implib = Alien::wxWidgets->import_libraries(@components);
|
||||||
#my @shrlib = Alien::wxWidgets->shared_libraries(@components);
|
#my @shrlib = Alien::wxWidgets->shared_libraries(@components);
|
||||||
|
@ -82,6 +83,7 @@ cmake_set_var('LIBRARIES', \$libraries);
|
||||||
cmake_set_var('DEFINITIONS', \$defines);
|
cmake_set_var('DEFINITIONS', \$defines);
|
||||||
#cmake_set_var('DEFINITIONS_DEBUG', );
|
#cmake_set_var('DEFINITIONS_DEBUG', );
|
||||||
cmake_set_var('CXX_FLAGS', \$cflags);
|
cmake_set_var('CXX_FLAGS', \$cflags);
|
||||||
|
cmake_set_var('GUI_TOOLKIT', \$gui_toolkit);
|
||||||
close \$fh;
|
close \$fh;
|
||||||
")
|
")
|
||||||
include(${AlienWx_TEMP_INCLUDE})
|
include(${AlienWx_TEMP_INCLUDE})
|
||||||
|
@ -96,6 +98,7 @@ if (AlienWx_DEBUG)
|
||||||
message(STATUS " AlienWx_DEFINITIONS = ${AlienWx_DEFINITIONS}")
|
message(STATUS " AlienWx_DEFINITIONS = ${AlienWx_DEFINITIONS}")
|
||||||
message(STATUS " AlienWx_DEFINITIONS_DEBUG = ${AlienWx_DEFINITIONS_DEBUG}")
|
message(STATUS " AlienWx_DEFINITIONS_DEBUG = ${AlienWx_DEFINITIONS_DEBUG}")
|
||||||
message(STATUS " AlienWx_CXX_FLAGS = ${AlienWx_CXX_FLAGS}")
|
message(STATUS " AlienWx_CXX_FLAGS = ${AlienWx_CXX_FLAGS}")
|
||||||
|
message(STATUS " AlienWx_GUI_TOOLKIT = ${AlienWx_GUI_TOOLKIT}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
|
@ -53,7 +53,7 @@ sub new {
|
||||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||||
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
||||||
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
||||||
wipe_tower_rotation_angle extruder_colour filament_colour max_print_height
|
wipe_tower_rotation_angle extruder_colour filament_colour max_print_height printer_model
|
||||||
)]);
|
)]);
|
||||||
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
||||||
$self->{model} = Slic3r::Model->new;
|
$self->{model} = Slic3r::Model->new;
|
||||||
|
@ -187,6 +187,7 @@ sub new {
|
||||||
if ($Slic3r::GUI::have_OpenGL) {
|
if ($Slic3r::GUI::have_OpenGL) {
|
||||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
|
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
|
||||||
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
|
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
|
||||||
|
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
|
||||||
Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
|
Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
|
||||||
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
|
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
|
||||||
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
|
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
|
||||||
|
@ -200,17 +201,18 @@ sub new {
|
||||||
|
|
||||||
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
|
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
|
||||||
my $preview = $self->{preview_notebook}->GetCurrentPage;
|
my $preview = $self->{preview_notebook}->GetCurrentPage;
|
||||||
if ($preview == $self->{preview3D})
|
if (($preview != $self->{preview3D}) && ($preview != $self->{canvas3D})) {
|
||||||
{
|
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
|
||||||
|
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
|
||||||
|
Slic3r::GUI::_3DScene::reset_current_canvas();
|
||||||
|
$preview->OnActivate if $preview->can('OnActivate');
|
||||||
|
} elsif ($preview == $self->{preview3D}) {
|
||||||
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 1);
|
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 1);
|
||||||
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
|
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
|
||||||
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
|
$self->{preview3D}->load_print;
|
||||||
$self->{preview3D}->load_print(1);
|
# sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
|
||||||
} else {
|
Slic3r::GUI::_3DScene::set_as_dirty($self->{preview3D}->canvas);
|
||||||
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 0);
|
} elsif ($preview == $self->{canvas3D}) {
|
||||||
}
|
|
||||||
|
|
||||||
if ($preview == $self->{canvas3D}) {
|
|
||||||
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 1);
|
Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 1);
|
||||||
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
|
Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
|
||||||
if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) {
|
if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) {
|
||||||
|
@ -218,8 +220,8 @@ sub new {
|
||||||
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
|
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
|
||||||
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
|
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
|
||||||
}
|
}
|
||||||
} else {
|
# sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
|
||||||
$preview->OnActivate if $preview->can('OnActivate');
|
Slic3r::GUI::_3DScene::set_as_dirty($self->{canvas3D});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1886,6 +1888,11 @@ sub on_config_change {
|
||||||
$self->{preview3D}->set_number_extruders(scalar(@{$extruder_colors}));
|
$self->{preview3D}->set_number_extruders(scalar(@{$extruder_colors}));
|
||||||
} elsif ($opt_key eq 'max_print_height') {
|
} elsif ($opt_key eq 'max_print_height') {
|
||||||
$update_scheduled = 1;
|
$update_scheduled = 1;
|
||||||
|
} elsif ($opt_key eq 'printer_model') {
|
||||||
|
# update to force bed selection (for texturing)
|
||||||
|
Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape) if $self->{canvas3D};
|
||||||
|
Slic3r::GUI::_3DScene::set_bed_shape($self->{preview3D}->canvas, $self->{config}->bed_shape) if $self->{preview3D};
|
||||||
|
$update_scheduled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,8 +231,9 @@ sub mouse_event {
|
||||||
}
|
}
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
} elsif ($event->LeftUp) {
|
} elsif ($event->LeftUp) {
|
||||||
$self->{on_instances_moved}->()
|
if ($self->{drag_object}) {
|
||||||
if $self->{drag_object};
|
$self->{on_instances_moved}->();
|
||||||
|
}
|
||||||
$self->{drag_start_pos} = undef;
|
$self->{drag_start_pos} = undef;
|
||||||
$self->{drag_object} = undef;
|
$self->{drag_object} = undef;
|
||||||
$self->SetCursor(wxSTANDARD_CURSOR);
|
$self->SetCursor(wxSTANDARD_CURSOR);
|
||||||
|
|
|
@ -199,11 +199,11 @@ sub new {
|
||||||
my $old_zoom = $self->_zoom;
|
my $old_zoom = $self->_zoom;
|
||||||
|
|
||||||
# Calculate the zoom delta and apply it to the current zoom factor
|
# Calculate the zoom delta and apply it to the current zoom factor
|
||||||
my $zoom = $e->GetWheelRotation() / $e->GetWheelDelta();
|
my $zoom = -$e->GetWheelRotation() / $e->GetWheelDelta();
|
||||||
$zoom = max(min($zoom, 4), -4);
|
$zoom = max(min($zoom, 4), -4);
|
||||||
$zoom /= 10;
|
$zoom /= 10;
|
||||||
$self->_zoom($self->_zoom / (1-$zoom));
|
$self->_zoom($self->_zoom / (1-$zoom));
|
||||||
$self->_zoom(1) if $self->_zoom > 1; # prevent from zooming out too much
|
$self->_zoom(1.25) if $self->_zoom > 1.25; # prevent from zooming out too much
|
||||||
|
|
||||||
{
|
{
|
||||||
# In order to zoom around the mouse point we need to translate
|
# In order to zoom around the mouse point we need to translate
|
||||||
|
@ -227,7 +227,6 @@ sub new {
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->_dirty(1);
|
$self->_dirty(1);
|
||||||
$self->Refresh;
|
|
||||||
});
|
});
|
||||||
EVT_MOUSE_EVENTS($self, \&mouse_event);
|
EVT_MOUSE_EVENTS($self, \&mouse_event);
|
||||||
|
|
||||||
|
@ -255,8 +254,8 @@ sub mouse_event {
|
||||||
return if !$self->GetParent->enabled;
|
return if !$self->GetParent->enabled;
|
||||||
|
|
||||||
my $pos = Slic3r::Pointf->new($e->GetPositionXY);
|
my $pos = Slic3r::Pointf->new($e->GetPositionXY);
|
||||||
if ($e->Entering && &Wx::wxMSW) {
|
if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) {
|
||||||
# wxMSW needs focus in order to catch mouse wheel events
|
# wxMSW and Linux needs focus in order to catch key events
|
||||||
$self->SetFocus;
|
$self->SetFocus;
|
||||||
} elsif ($e->Dragging) {
|
} elsif ($e->Dragging) {
|
||||||
if ($e->LeftIsDown || $e->MiddleIsDown || $e->RightIsDown) {
|
if ($e->LeftIsDown || $e->MiddleIsDown || $e->RightIsDown) {
|
||||||
|
@ -276,7 +275,6 @@ sub mouse_event {
|
||||||
);
|
);
|
||||||
|
|
||||||
$self->_dirty(1);
|
$self->_dirty(1);
|
||||||
$self->Refresh;
|
|
||||||
}
|
}
|
||||||
$self->_drag_start_xy($pos);
|
$self->_drag_start_xy($pos);
|
||||||
}
|
}
|
||||||
|
@ -632,6 +630,27 @@ sub Resize {
|
||||||
|
|
||||||
my $bb = $self->bb->clone;
|
my $bb = $self->bb->clone;
|
||||||
|
|
||||||
|
# rescale in dependence of window aspect ratio
|
||||||
|
my $bb_size = $bb->size;
|
||||||
|
my $ratio_x = ($x != 0.0) ? $bb_size->x / $x : 1.0;
|
||||||
|
my $ratio_y = ($y != 0.0) ? $bb_size->y / $y : 1.0;
|
||||||
|
|
||||||
|
if ($ratio_y < $ratio_x) {
|
||||||
|
if ($ratio_y != 0.0) {
|
||||||
|
my $new_size_y = $bb_size->y * $ratio_x / $ratio_y;
|
||||||
|
my $half_delta_size_y = 0.5 * ($new_size_y - $bb_size->y);
|
||||||
|
$bb->set_y_min($bb->y_min - $half_delta_size_y);
|
||||||
|
$bb->set_y_max($bb->y_max + $half_delta_size_y);
|
||||||
|
}
|
||||||
|
} elsif ($ratio_x < $ratio_y) {
|
||||||
|
if ($ratio_x != 0.0) {
|
||||||
|
my $new_size_x = $bb_size->x * $ratio_y / $ratio_x;
|
||||||
|
my $half_delta_size_x = 0.5 * ($new_size_x - $bb_size->x);
|
||||||
|
$bb->set_x_min($bb->x_min - $half_delta_size_x);
|
||||||
|
$bb->set_x_max($bb->x_max + $half_delta_size_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# center bounding box around origin before scaling it
|
# center bounding box around origin before scaling it
|
||||||
my $bb_center = $bb->center;
|
my $bb_center = $bb->center;
|
||||||
$bb->translate(@{$bb_center->negative});
|
$bb->translate(@{$bb_center->negative});
|
||||||
|
@ -645,25 +664,25 @@ sub Resize {
|
||||||
# translate camera
|
# translate camera
|
||||||
$bb->translate(@{$self->_camera_target});
|
$bb->translate(@{$self->_camera_target});
|
||||||
|
|
||||||
# keep camera_bb within total bb
|
# # keep camera_bb within total bb
|
||||||
# (i.e. prevent user from panning outside the bounding box)
|
# # (i.e. prevent user from panning outside the bounding box)
|
||||||
{
|
# {
|
||||||
my @translate = (0,0);
|
# my @translate = (0,0);
|
||||||
if ($bb->x_min < $self->bb->x_min) {
|
# if ($bb->x_min < $self->bb->x_min) {
|
||||||
$translate[X] += $self->bb->x_min - $bb->x_min;
|
# $translate[X] += $self->bb->x_min - $bb->x_min;
|
||||||
}
|
# }
|
||||||
if ($bb->y_min < $self->bb->y_min) {
|
# if ($bb->y_min < $self->bb->y_min) {
|
||||||
$translate[Y] += $self->bb->y_min - $bb->y_min;
|
# $translate[Y] += $self->bb->y_min - $bb->y_min;
|
||||||
}
|
# }
|
||||||
if ($bb->x_max > $self->bb->x_max) {
|
# if ($bb->x_max > $self->bb->x_max) {
|
||||||
$translate[X] -= $bb->x_max - $self->bb->x_max;
|
# $translate[X] -= $bb->x_max - $self->bb->x_max;
|
||||||
}
|
# }
|
||||||
if ($bb->y_max > $self->bb->y_max) {
|
# if ($bb->y_max > $self->bb->y_max) {
|
||||||
$translate[Y] -= $bb->y_max - $self->bb->y_max;
|
# $translate[Y] -= $bb->y_max - $self->bb->y_max;
|
||||||
}
|
# }
|
||||||
$self->_camera_target->translate(@translate);
|
# $self->_camera_target->translate(@translate);
|
||||||
$bb->translate(@translate);
|
# $bb->translate(@translate);
|
||||||
}
|
# }
|
||||||
|
|
||||||
# save camera
|
# save camera
|
||||||
$self->_camera_bb($bb);
|
$self->_camera_bb($bb);
|
||||||
|
|
|
@ -279,6 +279,7 @@ sub reload_print {
|
||||||
my ($self, $force) = @_;
|
my ($self, $force) = @_;
|
||||||
|
|
||||||
Slic3r::GUI::_3DScene::reset_volumes($self->canvas);
|
Slic3r::GUI::_3DScene::reset_volumes($self->canvas);
|
||||||
|
Slic3r::GUI::_3DScene::reset_current_canvas();
|
||||||
$self->_loaded(0);
|
$self->_loaded(0);
|
||||||
|
|
||||||
if (! $self->IsShown && ! $force) {
|
if (! $self->IsShown && ! $force) {
|
||||||
|
|
|
@ -101,7 +101,12 @@ sub export_gcode {
|
||||||
die "The configured post-processing script is not executable: check permissions. ($script)\n";
|
die "The configured post-processing script is not executable: check permissions. ($script)\n";
|
||||||
}
|
}
|
||||||
if ($^O eq 'MSWin32' && $script =~ /\.[pP][lL]/) {
|
if ($^O eq 'MSWin32' && $script =~ /\.[pP][lL]/) {
|
||||||
system($^X, $script, $output_file);
|
# The current process (^X) may be slic3r.exe or slic3r-console.exe.
|
||||||
|
# Replace it with the current perl interpreter.
|
||||||
|
my($filename, $directories, $suffix) = fileparse($^X);
|
||||||
|
$filename =~ s/^slic3r.*$/perl5\.24\.0\.exe/;
|
||||||
|
my $interpreter = $directories . $filename;
|
||||||
|
system($interpreter, $script, $output_file);
|
||||||
} else {
|
} else {
|
||||||
system($script, $output_file);
|
system($script, $output_file);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,6 +6,7 @@ xs/src/slic3r/GUI/ButtonsDescription.cpp
|
||||||
xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp
|
xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp
|
||||||
xs/src/slic3r/GUI/ConfigWizard.cpp
|
xs/src/slic3r/GUI/ConfigWizard.cpp
|
||||||
xs/src/slic3r/GUI/FirmwareDialog.cpp
|
xs/src/slic3r/GUI/FirmwareDialog.cpp
|
||||||
|
xs/src/slic3r/GUI/GLCanvas3D.cpp
|
||||||
xs/src/slic3r/GUI/GUI.cpp
|
xs/src/slic3r/GUI/GUI.cpp
|
||||||
xs/src/slic3r/GUI/MsgDialog.cpp
|
xs/src/slic3r/GUI/MsgDialog.cpp
|
||||||
xs/src/slic3r/GUI/Tab.cpp
|
xs/src/slic3r/GUI/Tab.cpp
|
||||||
|
|
|
@ -8,6 +8,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/)
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
# Workaround for an old CMake, which does not understand CMAKE_CXX_STANDARD.
|
# Workaround for an old CMake, which does not understand CMAKE_CXX_STANDARD.
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall" )
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
|
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
|
||||||
|
@ -579,6 +580,15 @@ if (SLIC3R_PRUSACONTROL)
|
||||||
#add_compile_options(${AlienWx_CXX_FLAGS})
|
#add_compile_options(${AlienWx_CXX_FLAGS})
|
||||||
add_definitions(${AlienWx_DEFINITIONS})
|
add_definitions(${AlienWx_DEFINITIONS})
|
||||||
set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES})
|
set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES})
|
||||||
|
# On Linux / gtk, we need to have a direct access to gtk+ for some workarounds.
|
||||||
|
if (AlienWx_GUI_TOOLKIT STREQUAL "gtk2")
|
||||||
|
pkg_check_modules(GTK2 gtk+-2.0)
|
||||||
|
include_directories(${GTK2_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
if (AlienWx_GUI_TOOLKIT STREQUAL "gtk3")
|
||||||
|
pkg_check_modules(GTK3 gtk+-3.0)
|
||||||
|
include_directories(${GTK3_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
else ()
|
else ()
|
||||||
find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl)
|
find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl)
|
||||||
include(${wxWidgets_USE_FILE})
|
include(${wxWidgets_USE_FILE})
|
||||||
|
|
|
@ -99,7 +99,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (strncmp(buffer, entry_magic_send, recv_size) != 0) {
|
} else if (strncmp(buffer, entry_magic_send, recv_size) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname);
|
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code: `%*s`\n", progname, recv_size, buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (strncmp(buffer, entry_magic_cfm, recv_size) != 0) {
|
} else if (strncmp(buffer, entry_magic_cfm, recv_size) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname);
|
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect cfm code: `%*s`\n", progname, recv_size, buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,13 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
|
||||||
serial_set_dtr_rts(&pgm->fd, 1);
|
serial_set_dtr_rts(&pgm->fd, 1);
|
||||||
usleep(50*1000);
|
usleep(50*1000);
|
||||||
|
|
||||||
|
// Sometimes there may be line noise generating input on the printer's USB-to-serial IC
|
||||||
|
// Here we try to clean its input buffer with a sequence of newlines (a minimum of 9 is needed):
|
||||||
|
const char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n";
|
||||||
|
if (serial_send(&pgm->fd, cleanup_newlines, sizeof(cleanup_newlines) - 1) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* drain any extraneous input
|
* drain any extraneous input
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -142,14 +142,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gcode += "G1";
|
m_gcode += "G1";
|
||||||
if (rot.x != rotated_current_pos.x) {
|
if (std::abs(dx) > EPSILON)
|
||||||
m_gcode += set_format_X(rot.x); // Transform current position back to wipe tower coordinates (was updated by set_format_X)
|
m_gcode += set_format_X(rot.x);
|
||||||
m_current_pos.x = x;
|
|
||||||
}
|
if (std::abs(dy) > EPSILON)
|
||||||
if (rot.y != rotated_current_pos.y) {
|
|
||||||
m_gcode += set_format_Y(rot.y);
|
m_gcode += set_format_Y(rot.y);
|
||||||
m_current_pos.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e != 0.f)
|
if (e != 0.f)
|
||||||
m_gcode += set_format_E(e);
|
m_gcode += set_format_E(e);
|
||||||
|
@ -157,8 +154,8 @@ public:
|
||||||
if (f != 0.f && f != m_current_feedrate)
|
if (f != 0.f && f != m_current_feedrate)
|
||||||
m_gcode += set_format_F(f);
|
m_gcode += set_format_F(f);
|
||||||
|
|
||||||
|
m_current_pos.x = x;
|
||||||
|
m_current_pos.y = y;
|
||||||
|
|
||||||
// Update the elapsed time with a rough estimate.
|
// Update the elapsed time with a rough estimate.
|
||||||
m_elapsed_time += ((len == 0) ? std::abs(e) : len) / m_current_feedrate * 60.f;
|
m_elapsed_time += ((len == 0) ? std::abs(e) : len) / m_current_feedrate * 60.f;
|
||||||
|
|
|
@ -433,6 +433,7 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||||
v.extruder_id = extruder_id;
|
v.extruder_id = extruder_id;
|
||||||
}
|
}
|
||||||
v.is_modifier = model_volume->modifier;
|
v.is_modifier = model_volume->modifier;
|
||||||
|
v.outside_printer_detection_enabled = !model_volume->modifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +664,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
|
||||||
bool contained = true;
|
bool contained = true;
|
||||||
for (GLVolume* volume : this->volumes)
|
for (GLVolume* volume : this->volumes)
|
||||||
{
|
{
|
||||||
if (volume != nullptr)
|
if ((volume != nullptr) && !volume->is_modifier)
|
||||||
{
|
{
|
||||||
bool state = print_volume.contains(volume->transformed_bounding_box());
|
bool state = print_volume.contains(volume->transformed_bounding_box());
|
||||||
contained &= state;
|
contained &= state;
|
||||||
|
@ -1753,11 +1754,26 @@ bool _3DScene::init(wxGLCanvas* canvas)
|
||||||
return s_canvas_mgr.init(canvas);
|
return s_canvas_mgr.init(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _3DScene::set_current(wxGLCanvas* canvas, bool force)
|
||||||
|
{
|
||||||
|
return s_canvas_mgr.set_current(canvas, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _3DScene::reset_current_canvas()
|
||||||
|
{
|
||||||
|
s_canvas_mgr.set_current(nullptr, false);
|
||||||
|
}
|
||||||
|
|
||||||
void _3DScene::set_active(wxGLCanvas* canvas, bool active)
|
void _3DScene::set_active(wxGLCanvas* canvas, bool active)
|
||||||
{
|
{
|
||||||
s_canvas_mgr.set_active(canvas, active);
|
s_canvas_mgr.set_active(canvas, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _3DScene::set_as_dirty(wxGLCanvas* canvas)
|
||||||
|
{
|
||||||
|
s_canvas_mgr.set_as_dirty(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int _3DScene::get_volumes_count(wxGLCanvas* canvas)
|
unsigned int _3DScene::get_volumes_count(wxGLCanvas* canvas)
|
||||||
{
|
{
|
||||||
return s_canvas_mgr.get_volumes_count(canvas);
|
return s_canvas_mgr.get_volumes_count(canvas);
|
||||||
|
|
|
@ -516,7 +516,11 @@ public:
|
||||||
|
|
||||||
static bool init(wxGLCanvas* canvas);
|
static bool init(wxGLCanvas* canvas);
|
||||||
|
|
||||||
|
static bool set_current(wxGLCanvas* canvas, bool force);
|
||||||
|
static void reset_current_canvas();
|
||||||
|
|
||||||
static void set_active(wxGLCanvas* canvas, bool active);
|
static void set_active(wxGLCanvas* canvas, bool active);
|
||||||
|
static void set_as_dirty(wxGLCanvas* canvas);
|
||||||
|
|
||||||
static unsigned int get_volumes_count(wxGLCanvas* canvas);
|
static unsigned int get_volumes_count(wxGLCanvas* canvas);
|
||||||
static void reset_volumes(wxGLCanvas* canvas);
|
static void reset_volumes(wxGLCanvas* canvas);
|
||||||
|
|
|
@ -12,10 +12,20 @@ namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
wxString double_to_string(double const value)
|
wxString double_to_string(double const value)
|
||||||
{
|
{
|
||||||
int precision = 10 * value - int(10 * value) == 0 ? 1 : 2;
|
if (value - int(value) == 0)
|
||||||
return value - int(value) == 0 ?
|
return wxString::Format(_T("%i"), int(value));
|
||||||
wxString::Format(_T("%i"), int(value)) :
|
else {
|
||||||
wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
|
int precision = 4;
|
||||||
|
for (size_t p = 1; p < 4; p++)
|
||||||
|
{
|
||||||
|
double cur_val = pow(10, p)*value;
|
||||||
|
if (cur_val - int(cur_val) == 0) {
|
||||||
|
precision = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field::PostInitialize(){
|
void Field::PostInitialize(){
|
||||||
|
|
|
@ -405,16 +405,27 @@ GLCanvas3D::Bed::EType GLCanvas3D::Bed::_detect_type() const
|
||||||
const PresetBundle* bundle = get_preset_bundle();
|
const PresetBundle* bundle = get_preset_bundle();
|
||||||
if (bundle != nullptr)
|
if (bundle != nullptr)
|
||||||
{
|
{
|
||||||
const Preset& curr = bundle->printers.get_selected_preset();
|
const Preset* curr = &bundle->printers.get_selected_preset();
|
||||||
if (curr.config.has("bed_shape") && _are_equal(m_shape, dynamic_cast<const ConfigOptionPoints*>(curr.config.option("bed_shape"))->values))
|
while (curr != nullptr)
|
||||||
{
|
{
|
||||||
if ((curr.vendor != nullptr) && (curr.vendor->name == "Prusa Research"))
|
if (curr->config.has("bed_shape") && _are_equal(m_shape, dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
|
||||||
|
{
|
||||||
|
if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research"))
|
||||||
|
{
|
||||||
|
if (boost::contains(curr->name, "MK2"))
|
||||||
{
|
{
|
||||||
if (boost::contains(curr.name, "MK2"))
|
|
||||||
type = MK2;
|
type = MK2;
|
||||||
else if (boost::contains(curr.name, "MK3"))
|
break;
|
||||||
type = MK3;
|
|
||||||
}
|
}
|
||||||
|
else if (boost::contains(curr->name, "MK3"))
|
||||||
|
{
|
||||||
|
type = MK3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curr = bundle->printers.get_preset_parent(*curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1509,13 +1520,10 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::set_current()
|
bool GLCanvas3D::set_current(bool force)
|
||||||
{
|
{
|
||||||
if ((m_canvas != nullptr) && (m_context != nullptr))
|
if ((force || m_active) && (m_canvas != nullptr) && (m_context != nullptr))
|
||||||
{
|
return m_canvas->SetCurrent(*m_context);
|
||||||
m_canvas->SetCurrent(*m_context);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1525,6 +1533,11 @@ void GLCanvas3D::set_active(bool active)
|
||||||
m_active = active;
|
m_active = active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::set_as_dirty()
|
||||||
|
{
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GLCanvas3D::get_volumes_count() const
|
unsigned int GLCanvas3D::get_volumes_count() const
|
||||||
{
|
{
|
||||||
return (unsigned int)m_volumes.volumes.size();
|
return (unsigned int)m_volumes.volumes.size();
|
||||||
|
@ -1532,8 +1545,13 @@ unsigned int GLCanvas3D::get_volumes_count() const
|
||||||
|
|
||||||
void GLCanvas3D::reset_volumes()
|
void GLCanvas3D::reset_volumes()
|
||||||
{
|
{
|
||||||
if (set_current())
|
|
||||||
|
if (!m_volumes.empty())
|
||||||
{
|
{
|
||||||
|
// ensures this canvas is current
|
||||||
|
if ((m_canvas == nullptr) || !_3DScene::set_current(m_canvas, true))
|
||||||
|
return;
|
||||||
|
|
||||||
m_volumes.release_geometry();
|
m_volumes.release_geometry();
|
||||||
m_volumes.clear();
|
m_volumes.clear();
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
|
@ -1831,8 +1849,8 @@ void GLCanvas3D::render()
|
||||||
if (!_is_shown_on_screen())
|
if (!_is_shown_on_screen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// ensures that the proper context is selected and that this canvas is initialized
|
// ensures this canvas is current and initialized
|
||||||
if (!set_current() || !_3DScene::init(m_canvas))
|
if (!_3DScene::set_current(m_canvas, false) || !_3DScene::init(m_canvas))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_force_zoom_to_bed_enabled)
|
if (m_force_zoom_to_bed_enabled)
|
||||||
|
@ -1913,6 +1931,11 @@ void GLCanvas3D::reload_scene(bool force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
reset_volumes();
|
reset_volumes();
|
||||||
|
|
||||||
|
// ensures this canvas is current
|
||||||
|
if (!_3DScene::set_current(m_canvas, true))
|
||||||
|
return;
|
||||||
|
|
||||||
set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
|
set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
|
||||||
|
|
||||||
if (!m_canvas->IsShown() && !force)
|
if (!m_canvas->IsShown() && !force)
|
||||||
|
@ -1984,6 +2007,10 @@ void GLCanvas3D::reload_scene(bool force)
|
||||||
|
|
||||||
void GLCanvas3D::load_print_toolpaths()
|
void GLCanvas3D::load_print_toolpaths()
|
||||||
{
|
{
|
||||||
|
// ensures this canvas is current
|
||||||
|
if (!_3DScene::set_current(m_canvas, true))
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_print == nullptr)
|
if (m_print == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2348,8 +2375,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
|
||||||
{
|
{
|
||||||
if ((m_canvas != nullptr) && (m_print != nullptr))
|
if ((m_canvas != nullptr) && (m_print != nullptr))
|
||||||
{
|
{
|
||||||
// ensures that the proper context is selected
|
// ensures that this canvas is current
|
||||||
if (!set_current())
|
if (!_3DScene::set_current(m_canvas, true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_volumes.empty())
|
if (m_volumes.empty())
|
||||||
|
@ -2666,7 +2693,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (evt.LeftDClick() && (m_hover_volume_id != -1))
|
else if (evt.LeftDClick() && (m_hover_volume_id != -1))
|
||||||
|
{
|
||||||
|
m_active = false;
|
||||||
m_on_double_click_callback.call();
|
m_on_double_click_callback.call();
|
||||||
|
m_active = true;
|
||||||
|
}
|
||||||
else if (evt.LeftDown() || evt.RightDown())
|
else if (evt.LeftDown() || evt.RightDown())
|
||||||
{
|
{
|
||||||
// If user pressed left or right button we first check whether this happened
|
// If user pressed left or right button we first check whether this happened
|
||||||
|
@ -2762,7 +2793,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
{
|
{
|
||||||
// if right clicking on volume, propagate event through callback
|
// if right clicking on volume, propagate event through callback
|
||||||
if (m_volumes.volumes[volume_idx]->hover)
|
if (m_volumes.volumes[volume_idx]->hover)
|
||||||
|
{
|
||||||
|
m_active = false;
|
||||||
m_on_right_click_callback.call(pos.x, pos.y);
|
m_on_right_click_callback.call(pos.x, pos.y);
|
||||||
|
m_active = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2980,10 +3015,11 @@ void GLCanvas3D::_force_zoom_to_bed()
|
||||||
|
|
||||||
void GLCanvas3D::_resize(unsigned int w, unsigned int h)
|
void GLCanvas3D::_resize(unsigned int w, unsigned int h)
|
||||||
{
|
{
|
||||||
if (m_context == nullptr)
|
if ((m_canvas == nullptr) && (m_context == nullptr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_current();
|
// ensures that this canvas is current
|
||||||
|
_3DScene::set_current(m_canvas, false);
|
||||||
::glViewport(0, 0, w, h);
|
::glViewport(0, 0, w, h);
|
||||||
|
|
||||||
::glMatrixMode(GL_PROJECTION);
|
::glMatrixMode(GL_PROJECTION);
|
||||||
|
@ -3569,9 +3605,11 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
|
||||||
|
|
||||||
Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z)
|
Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z)
|
||||||
{
|
{
|
||||||
if (!set_current())
|
if (m_canvas == nullptr)
|
||||||
return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX);
|
return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||||
|
|
||||||
|
_camera_tranform();
|
||||||
|
|
||||||
GLint viewport[4];
|
GLint viewport[4];
|
||||||
::glGetIntegerv(GL_VIEWPORT, viewport);
|
::glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
GLdouble modelview_matrix[16];
|
GLdouble modelview_matrix[16];
|
||||||
|
|
|
@ -449,9 +449,10 @@ public:
|
||||||
|
|
||||||
bool init(bool useVBOs, bool use_legacy_opengl);
|
bool init(bool useVBOs, bool use_legacy_opengl);
|
||||||
|
|
||||||
bool set_current();
|
bool set_current(bool force);
|
||||||
|
|
||||||
void set_active(bool active);
|
void set_active(bool active);
|
||||||
|
void set_as_dirty();
|
||||||
|
|
||||||
unsigned int get_volumes_count() const;
|
unsigned int get_volumes_count() const;
|
||||||
void reset_volumes();
|
void reset_volumes();
|
||||||
|
|
|
@ -26,33 +26,23 @@ GLCanvas3DManager::GLInfo::GLInfo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3DManager::GLInfo::detect()
|
void GLCanvas3DManager::GLInfo::detect()
|
||||||
{
|
{
|
||||||
const char* data = (const char*)::glGetString(GL_VERSION);
|
const char* data = (const char*)::glGetString(GL_VERSION);
|
||||||
if (data == nullptr)
|
if (data != nullptr)
|
||||||
return false;
|
|
||||||
|
|
||||||
version = data;
|
version = data;
|
||||||
|
|
||||||
data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
|
data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||||
if (data == nullptr)
|
if (data != nullptr)
|
||||||
return false;
|
|
||||||
|
|
||||||
glsl_version = data;
|
glsl_version = data;
|
||||||
|
|
||||||
data = (const char*)::glGetString(GL_VENDOR);
|
data = (const char*)::glGetString(GL_VENDOR);
|
||||||
if (data == nullptr)
|
if (data != nullptr)
|
||||||
return false;
|
|
||||||
|
|
||||||
vendor = data;
|
vendor = data;
|
||||||
|
|
||||||
data = (const char*)::glGetString(GL_RENDERER);
|
data = (const char*)::glGetString(GL_RENDERER);
|
||||||
if (data == nullptr)
|
if (data != nullptr)
|
||||||
return false;
|
|
||||||
|
|
||||||
renderer = data;
|
renderer = data;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
||||||
|
@ -94,10 +84,10 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
|
||||||
std::string line_end = format_as_html ? "<br>" : "\n";
|
std::string line_end = format_as_html ? "<br>" : "\n";
|
||||||
|
|
||||||
out << h2_start << "OpenGL installation" << h2_end << line_end;
|
out << h2_start << "OpenGL installation" << h2_end << line_end;
|
||||||
out << b_start << "GL version: " << b_end << version << line_end;
|
out << b_start << "GL version: " << b_end << (version.empty() ? "N/A" : version) << line_end;
|
||||||
out << b_start << "Vendor: " << b_end << vendor << line_end;
|
out << b_start << "Vendor: " << b_end << (vendor.empty() ? "N/A" : vendor) << line_end;
|
||||||
out << b_start << "Renderer: " << b_end << renderer << line_end;
|
out << b_start << "Renderer: " << b_end << (renderer.empty() ? "N/A" : renderer) << line_end;
|
||||||
out << b_start << "GLSL version: " << b_end << glsl_version << line_end;
|
out << b_start << "GLSL version: " << b_end << (glsl_version.empty() ? "N/A" : glsl_version) << line_end;
|
||||||
|
|
||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
|
@ -125,6 +115,7 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
|
||||||
|
|
||||||
GLCanvas3DManager::GLCanvas3DManager()
|
GLCanvas3DManager::GLCanvas3DManager()
|
||||||
: m_context(nullptr)
|
: m_context(nullptr)
|
||||||
|
, m_current(nullptr)
|
||||||
, m_gl_initialized(false)
|
, m_gl_initialized(false)
|
||||||
, m_use_legacy_opengl(false)
|
, m_use_legacy_opengl(false)
|
||||||
, m_use_VBOs(false)
|
, m_use_VBOs(false)
|
||||||
|
@ -195,16 +186,12 @@ void GLCanvas3DManager::init_gl()
|
||||||
if (!m_gl_initialized)
|
if (!m_gl_initialized)
|
||||||
{
|
{
|
||||||
glewInit();
|
glewInit();
|
||||||
if (m_gl_info.detect())
|
m_gl_info.detect();
|
||||||
{
|
|
||||||
const AppConfig* config = GUI::get_app_config();
|
const AppConfig* config = GUI::get_app_config();
|
||||||
m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1");
|
m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1");
|
||||||
m_use_VBOs = !m_use_legacy_opengl && m_gl_info.is_version_greater_or_equal_to(2, 0);
|
m_use_VBOs = !m_use_legacy_opengl && m_gl_info.is_version_greater_or_equal_to(2, 0);
|
||||||
m_gl_initialized = true;
|
m_gl_initialized = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
throw std::runtime_error(std::string("Unable to initialize OpenGL driver\n"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLCanvas3DManager::get_gl_info(bool format_as_html, bool extensions) const
|
std::string GLCanvas3DManager::get_gl_info(bool format_as_html, bool extensions) const
|
||||||
|
@ -226,6 +213,34 @@ bool GLCanvas3DManager::init(wxGLCanvas* canvas)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3DManager::set_current(wxGLCanvas* canvas, bool force)
|
||||||
|
{
|
||||||
|
// given canvas is already current, return
|
||||||
|
if (m_current == canvas)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (canvas == nullptr)
|
||||||
|
{
|
||||||
|
m_current = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set given canvas as current
|
||||||
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
if (it != m_canvases.end())
|
||||||
|
{
|
||||||
|
bool res = it->second->set_current(force);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
m_current = canvas;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_current = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
|
void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
|
||||||
{
|
{
|
||||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
@ -233,6 +248,13 @@ void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
|
||||||
it->second->set_active(active);
|
it->second->set_active(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3DManager::set_as_dirty(wxGLCanvas* canvas)
|
||||||
|
{
|
||||||
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
if (it != m_canvases.end())
|
||||||
|
it->second->set_as_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GLCanvas3DManager::get_volumes_count(wxGLCanvas* canvas) const
|
unsigned int GLCanvas3DManager::get_volumes_count(wxGLCanvas* canvas) const
|
||||||
{
|
{
|
||||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||||
|
|
|
@ -35,7 +35,7 @@ class GLCanvas3DManager
|
||||||
|
|
||||||
GLInfo();
|
GLInfo();
|
||||||
|
|
||||||
bool detect();
|
void detect();
|
||||||
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
|
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
|
||||||
|
|
||||||
std::string to_string(bool format_as_html, bool extensions) const;
|
std::string to_string(bool format_as_html, bool extensions) const;
|
||||||
|
@ -45,6 +45,7 @@ class GLCanvas3DManager
|
||||||
|
|
||||||
wxGLContext* m_context;
|
wxGLContext* m_context;
|
||||||
CanvasesMap m_canvases;
|
CanvasesMap m_canvases;
|
||||||
|
wxGLCanvas* m_current;
|
||||||
GLInfo m_gl_info;
|
GLInfo m_gl_info;
|
||||||
bool m_gl_initialized;
|
bool m_gl_initialized;
|
||||||
bool m_use_legacy_opengl;
|
bool m_use_legacy_opengl;
|
||||||
|
@ -69,7 +70,9 @@ public:
|
||||||
|
|
||||||
bool init(wxGLCanvas* canvas);
|
bool init(wxGLCanvas* canvas);
|
||||||
|
|
||||||
|
bool set_current(wxGLCanvas* canvas, bool force);
|
||||||
void set_active(wxGLCanvas* canvas, bool active);
|
void set_active(wxGLCanvas* canvas, bool active);
|
||||||
|
void set_as_dirty(wxGLCanvas* canvas);
|
||||||
|
|
||||||
unsigned int get_volumes_count(wxGLCanvas* canvas) const;
|
unsigned int get_volumes_count(wxGLCanvas* canvas) const;
|
||||||
void reset_volumes(wxGLCanvas* canvas);
|
void reset_volumes(wxGLCanvas* canvas);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -27,6 +29,9 @@ bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmap
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(filename))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Load a PNG with an alpha channel.
|
// Load a PNG with an alpha channel.
|
||||||
wxImage image;
|
wxImage image;
|
||||||
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
|
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "../Utils/PresetUpdater.hpp"
|
#include "../Utils/PresetUpdater.hpp"
|
||||||
#include "../Config/Snapshot.hpp"
|
#include "../Config/Snapshot.hpp"
|
||||||
#include "libslic3r/I18N.hpp"
|
#include "libslic3r/I18N.hpp"
|
||||||
|
#include "3DScene.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
@ -382,6 +383,7 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
|
||||||
save_language();
|
save_language();
|
||||||
show_info(g_wxTabPanel, _(L("Application will be restarted")), _(L("Attention!")));
|
show_info(g_wxTabPanel, _(L("Application will be restarted")), _(L("Attention!")));
|
||||||
if (event_language_change > 0) {
|
if (event_language_change > 0) {
|
||||||
|
_3DScene::remove_all_canvases();// remove all canvas before recreate GUI
|
||||||
wxCommandEvent event(event_language_change);
|
wxCommandEvent event(event_language_change);
|
||||||
g_wxApp->ProcessEvent(event);
|
g_wxApp->ProcessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ struct MsgDialog : wxDialog
|
||||||
MsgDialog &operator=(const MsgDialog &) = delete;
|
MsgDialog &operator=(const MsgDialog &) = delete;
|
||||||
virtual ~MsgDialog();
|
virtual ~MsgDialog();
|
||||||
|
|
||||||
|
// TODO: refactor with CreateStdDialogButtonSizer usage
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum {
|
||||||
CONTENT_WIDTH = 500,
|
CONTENT_WIDTH = 500,
|
||||||
|
|
|
@ -150,8 +150,15 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
|
||||||
// Build a label if we have it
|
// Build a label if we have it
|
||||||
wxStaticText* label=nullptr;
|
wxStaticText* label=nullptr;
|
||||||
if (label_width != 0) {
|
if (label_width != 0) {
|
||||||
|
long label_style = staticbox ? 0 : wxALIGN_RIGHT;
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
// workaround for correct text align of the StaticBox on Linux
|
||||||
|
// flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given.
|
||||||
|
// Text is properly aligned only when Ellipsize is checked.
|
||||||
|
label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END;
|
||||||
|
#endif /* __WXGTK__ */
|
||||||
label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ":"),
|
label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ":"),
|
||||||
wxDefaultPosition, wxSize(label_width, -1), staticbox ? 0 : wxALIGN_RIGHT);
|
wxDefaultPosition, wxSize(label_width, -1), label_style);
|
||||||
label->SetFont(label_font);
|
label->SetFont(label_font);
|
||||||
label->Wrap(label_width); // avoid a Linux/GTK bug
|
label->Wrap(label_width); // avoid a Linux/GTK bug
|
||||||
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
|
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
|
|
@ -2619,14 +2619,24 @@ void SavePresetWindow::accept()
|
||||||
if (!m_chosen_name.empty()) {
|
if (!m_chosen_name.empty()) {
|
||||||
const char* unusable_symbols = "<>:/\\|?*\"";
|
const char* unusable_symbols = "<>:/\\|?*\"";
|
||||||
bool is_unusable_symbol = false;
|
bool is_unusable_symbol = false;
|
||||||
|
bool is_unusable_postfix = false;
|
||||||
|
const std::string unusable_postfix = "(modified)";
|
||||||
for (size_t i = 0; i < std::strlen(unusable_symbols); i++){
|
for (size_t i = 0; i < std::strlen(unusable_symbols); i++){
|
||||||
if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos){
|
if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos){
|
||||||
is_unusable_symbol = true;
|
is_unusable_symbol = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_chosen_name.find(unusable_postfix) != std::string::npos)
|
||||||
|
is_unusable_postfix = true;
|
||||||
|
|
||||||
if (is_unusable_symbol) {
|
if (is_unusable_symbol) {
|
||||||
show_error(this, _(L("The supplied name is not valid; the following characters are not allowed:"))+" <>:/\\|?*\"");
|
show_error(this,_(L("The supplied name is not valid;")) + "\n" +
|
||||||
|
_(L("the following characters are not allowed:")) + " <>:/\\|?*\"");
|
||||||
|
}
|
||||||
|
else if (is_unusable_postfix){
|
||||||
|
show_error(this, _(L("The supplied name is not valid;")) + "\n" +
|
||||||
|
_(L("the following postfix are not allowed:")) + "\n\t" + unusable_postfix);
|
||||||
}
|
}
|
||||||
else if (m_chosen_name.compare("- default -") == 0) {
|
else if (m_chosen_name.compare("- default -") == 0) {
|
||||||
show_error(this, _(L("The supplied name is not available.")));
|
show_error(this, _(L("The supplied name is not available.")));
|
||||||
|
|
|
@ -3,13 +3,16 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <tuple>
|
#include <deque>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "../../libslic3r/libslic3r.h"
|
#include "../../libslic3r/libslic3r.h"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
@ -34,7 +37,11 @@ struct Http::priv
|
||||||
::curl_httppost *form;
|
::curl_httppost *form;
|
||||||
::curl_httppost *form_end;
|
::curl_httppost *form_end;
|
||||||
::curl_slist *headerlist;
|
::curl_slist *headerlist;
|
||||||
|
// Used for reading the body
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
// Used for storing file streams added as multipart form parts
|
||||||
|
// Using a deque here because unlike vector it doesn't ivalidate pointers on insertion
|
||||||
|
std::deque<fs::ifstream> form_files;
|
||||||
size_t limit;
|
size_t limit;
|
||||||
bool cancel;
|
bool cancel;
|
||||||
|
|
||||||
|
@ -50,6 +57,10 @@ struct Http::priv
|
||||||
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
|
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
|
||||||
static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
|
static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
|
||||||
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
|
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
|
||||||
|
static size_t form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp);
|
||||||
|
|
||||||
|
void form_add_file(const char *name, const fs::path &path, const char* filename);
|
||||||
|
|
||||||
std::string curl_error(CURLcode curlcode);
|
std::string curl_error(CURLcode curlcode);
|
||||||
std::string body_size_error();
|
std::string body_size_error();
|
||||||
void http_perform();
|
void http_perform();
|
||||||
|
@ -135,6 +146,46 @@ int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double
|
||||||
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
|
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Http::priv::form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp)
|
||||||
|
{
|
||||||
|
auto stream = reinterpret_cast<fs::ifstream*>(userp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
stream->read(buffer, size * nitems);
|
||||||
|
} catch (...) {
|
||||||
|
return CURL_READFUNC_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream->gcount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Http::priv::form_add_file(const char *name, const fs::path &path, const char* filename)
|
||||||
|
{
|
||||||
|
// We can't use CURLFORM_FILECONTENT, because curl doesn't support Unicode filenames on Windows
|
||||||
|
// and so we use CURLFORM_STREAM with boost ifstream to read the file.
|
||||||
|
|
||||||
|
if (filename == nullptr) {
|
||||||
|
filename = path.string().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
form_files.emplace_back(path, std::ios::in | std::ios::binary);
|
||||||
|
auto &stream = form_files.back();
|
||||||
|
stream.seekg(0, std::ios::end);
|
||||||
|
size_t size = stream.tellg();
|
||||||
|
stream.seekg(0);
|
||||||
|
|
||||||
|
if (filename != nullptr) {
|
||||||
|
::curl_formadd(&form, &form_end,
|
||||||
|
CURLFORM_COPYNAME, name,
|
||||||
|
CURLFORM_FILENAME, filename,
|
||||||
|
CURLFORM_CONTENTTYPE, "application/octet-stream",
|
||||||
|
CURLFORM_STREAM, static_cast<void*>(&stream),
|
||||||
|
CURLFORM_CONTENTSLENGTH, static_cast<long>(size),
|
||||||
|
CURLFORM_END
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string Http::priv::curl_error(CURLcode curlcode)
|
std::string Http::priv::curl_error(CURLcode curlcode)
|
||||||
{
|
{
|
||||||
return (boost::format("%1% (%2%)")
|
return (boost::format("%1% (%2%)")
|
||||||
|
@ -154,6 +205,7 @@ void Http::priv::http_perform()
|
||||||
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
|
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
|
||||||
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
|
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
|
||||||
|
::curl_easy_setopt(curl, CURLOPT_READFUNCTION, form_file_read_cb);
|
||||||
|
|
||||||
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||||
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
|
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
|
||||||
|
@ -183,14 +235,20 @@ void Http::priv::http_perform()
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
if (res == CURLE_ABORTED_BY_CALLBACK) {
|
if (res == CURLE_ABORTED_BY_CALLBACK) {
|
||||||
|
if (cancel) {
|
||||||
|
// The abort comes from the request being cancelled programatically
|
||||||
Progress dummyprogress(0, 0, 0, 0);
|
Progress dummyprogress(0, 0, 0, 0);
|
||||||
bool cancel = true;
|
bool cancel = true;
|
||||||
if (progressfn) { progressfn(dummyprogress, cancel); }
|
if (progressfn) { progressfn(dummyprogress, cancel); }
|
||||||
|
} else {
|
||||||
|
// The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed
|
||||||
|
if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", http_status); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (res == CURLE_WRITE_ERROR) {
|
else if (res == CURLE_WRITE_ERROR) {
|
||||||
if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
|
if (errorfn) { errorfn(std::move(buffer), body_size_error(), http_status); }
|
||||||
} else {
|
} else {
|
||||||
if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
|
if (errorfn) { errorfn(std::move(buffer), curl_error(res), http_status); }
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (completefn) {
|
if (completefn) {
|
||||||
|
@ -265,17 +323,15 @@ Http& Http::form_add(const std::string &name, const std::string &contents)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Http& Http::form_add_file(const std::string &name, const std::string &filename)
|
Http& Http::form_add_file(const std::string &name, const fs::path &path)
|
||||||
{
|
{
|
||||||
if (p) {
|
if (p) { p->form_add_file(name.c_str(), path.c_str(), nullptr); }
|
||||||
::curl_formadd(&p->form, &p->form_end,
|
return *this;
|
||||||
CURLFORM_COPYNAME, name.c_str(),
|
|
||||||
CURLFORM_FILE, filename.c_str(),
|
|
||||||
CURLFORM_CONTENTTYPE, "application/octet-stream",
|
|
||||||
CURLFORM_END
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Http& Http::form_add_file(const std::string &name, const fs::path &path, const std::string &filename)
|
||||||
|
{
|
||||||
|
if (p) { p->form_add_file(name.c_str(), path.c_str(), filename.c_str()); }
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -16,10 +17,10 @@ private:
|
||||||
public:
|
public:
|
||||||
struct Progress
|
struct Progress
|
||||||
{
|
{
|
||||||
size_t dltotal;
|
size_t dltotal; // Total bytes to download
|
||||||
size_t dlnow;
|
size_t dlnow; // Bytes downloaded so far
|
||||||
size_t ultotal;
|
size_t ultotal; // Total bytes to upload
|
||||||
size_t ulnow;
|
size_t ulnow; // Bytes uploaded so far
|
||||||
|
|
||||||
Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
|
Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
|
||||||
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
|
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
|
||||||
|
@ -33,6 +34,10 @@ public:
|
||||||
|
|
||||||
Http(Http &&other);
|
Http(Http &&other);
|
||||||
|
|
||||||
|
// Note: strings are expected to be UTF-8-encoded
|
||||||
|
|
||||||
|
// These are the primary constructors that create a HTTP object
|
||||||
|
// for a GET and a POST request respectively.
|
||||||
static Http get(std::string url);
|
static Http get(std::string url);
|
||||||
static Http post(std::string url);
|
static Http post(std::string url);
|
||||||
~Http();
|
~Http();
|
||||||
|
@ -41,21 +46,42 @@ public:
|
||||||
Http& operator=(const Http &) = delete;
|
Http& operator=(const Http &) = delete;
|
||||||
Http& operator=(Http &&) = delete;
|
Http& operator=(Http &&) = delete;
|
||||||
|
|
||||||
|
// Sets a maximum size of the data that can be received. The default is 5MB.
|
||||||
Http& size_limit(size_t sizeLimit);
|
Http& size_limit(size_t sizeLimit);
|
||||||
|
// Sets a HTTP header field.
|
||||||
Http& header(std::string name, const std::string &value);
|
Http& header(std::string name, const std::string &value);
|
||||||
|
// Removes a header field.
|
||||||
Http& remove_header(std::string name);
|
Http& remove_header(std::string name);
|
||||||
|
// Sets a CA certificate file for usage with HTTPS. This is only supported on some backends,
|
||||||
|
// specifically, this is supported with OpenSSL and NOT supported with Windows and OS X native certificate store.
|
||||||
|
// See also ca_file_supported().
|
||||||
Http& ca_file(const std::string &filename);
|
Http& ca_file(const std::string &filename);
|
||||||
|
// Add a HTTP multipart form field
|
||||||
Http& form_add(const std::string &name, const std::string &contents);
|
Http& form_add(const std::string &name, const std::string &contents);
|
||||||
Http& form_add_file(const std::string &name, const std::string &filename);
|
// Add a HTTP multipart form file data contents, `name` is the name of the part
|
||||||
|
Http& form_add_file(const std::string &name, const boost::filesystem::path &path);
|
||||||
|
// Same as above except also override the file's filename with a custom one
|
||||||
|
Http& form_add_file(const std::string &name, const boost::filesystem::path &path, const std::string &filename);
|
||||||
|
|
||||||
|
// Callback called on HTTP request complete
|
||||||
Http& on_complete(CompleteFn fn);
|
Http& on_complete(CompleteFn fn);
|
||||||
|
// Callback called on an error occuring at any stage of the requests: Url parsing, DNS lookup,
|
||||||
|
// TCP connection, HTTP transfer, and finally also when the response indicates an error (status >= 400).
|
||||||
|
// Therefore, a response body may or may not be present.
|
||||||
Http& on_error(ErrorFn fn);
|
Http& on_error(ErrorFn fn);
|
||||||
|
// Callback called on data download/upload prorgess (called fairly frequently).
|
||||||
|
// See the `Progress` structure for description of the data passed.
|
||||||
|
// Writing a true-ish value into the cancel reference parameter cancels the request.
|
||||||
Http& on_progress(ProgressFn fn);
|
Http& on_progress(ProgressFn fn);
|
||||||
|
|
||||||
|
// Starts performing the request in a background thread
|
||||||
Ptr perform();
|
Ptr perform();
|
||||||
|
// Starts performing the request on the current thread
|
||||||
void perform_sync();
|
void perform_sync();
|
||||||
|
// Cancels a request in progress
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
|
// Tells whether current backend supports seting up a CA file using ca_file()
|
||||||
static bool ca_file_supported();
|
static bool ca_file_supported();
|
||||||
private:
|
private:
|
||||||
Http(const std::string &url);
|
Http(const std::string &url);
|
||||||
|
|
|
@ -1,20 +1,65 @@
|
||||||
#include "OctoPrint.hpp"
|
#include "OctoPrint.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include <wx/frame.h>
|
#include <wx/frame.h>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
#include "Http.hpp"
|
#include "Http.hpp"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
|
||||||
|
struct SendDialog : public GUI::MsgDialog
|
||||||
|
{
|
||||||
|
wxTextCtrl *txt_filename;
|
||||||
|
wxCheckBox *box_print;
|
||||||
|
|
||||||
|
SendDialog(const fs::path &path) :
|
||||||
|
MsgDialog(nullptr, _(L("Send G-Code to printer")), _(L("Upload to OctoPrint with the following filename:")), wxID_NONE),
|
||||||
|
txt_filename(new wxTextCtrl(this, wxID_ANY, path.filename().wstring())),
|
||||||
|
box_print(new wxCheckBox(this, wxID_ANY, _(L("Start printing after upload"))))
|
||||||
|
{
|
||||||
|
auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _(L("Use forward slashes ( / ) as a directory separator if needed.")));
|
||||||
|
label_dir_hint->Wrap(CONTENT_WIDTH);
|
||||||
|
|
||||||
|
content_sizer->Add(txt_filename, 0, wxEXPAND);
|
||||||
|
content_sizer->Add(label_dir_hint);
|
||||||
|
content_sizer->AddSpacer(VERT_SPACING);
|
||||||
|
content_sizer->Add(box_print, 0, wxBOTTOM, 2*VERT_SPACING);
|
||||||
|
|
||||||
|
btn_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL));
|
||||||
|
|
||||||
|
txt_filename->SetFocus();
|
||||||
|
wxString stem(path.stem().wstring());
|
||||||
|
txt_filename->SetSelection(0, stem.Length());
|
||||||
|
|
||||||
|
Fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path filename() const {
|
||||||
|
return fs::path(txt_filename->GetValue().wx_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool print() const { return box_print->GetValue(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OctoPrint::OctoPrint(DynamicPrintConfig *config) :
|
OctoPrint::OctoPrint(DynamicPrintConfig *config) :
|
||||||
host(config->opt_string("octoprint_host")),
|
host(config->opt_string("octoprint_host")),
|
||||||
apikey(config->opt_string("octoprint_apikey")),
|
apikey(config->opt_string("octoprint_apikey")),
|
||||||
|
@ -27,24 +72,39 @@ bool OctoPrint::test(wxString &msg) const
|
||||||
// it is ok to refer to `msg` from within the closure
|
// it is ok to refer to `msg` from within the closure
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
auto url = make_url("api/version");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Get version at: %1%") % url;
|
||||||
|
|
||||||
auto url = std::move(make_url("api/version"));
|
|
||||||
auto http = Http::get(std::move(url));
|
auto http = Http::get(std::move(url));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.on_error([&](std::string, std::string error, unsigned status) {
|
http.on_error([&](std::string, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1% (HTTP %2%)") % error % status;
|
||||||
res = false;
|
res = false;
|
||||||
msg = format_error(error, status);
|
msg = format_error(error, status);
|
||||||
})
|
})
|
||||||
|
.on_complete([&](std::string body, unsigned) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
|
||||||
|
})
|
||||||
.perform_sync();
|
.perform_sync();
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OctoPrint::send_gcode(const std::string &filename, bool print) const
|
bool OctoPrint::send_gcode(const std::string &filename) const
|
||||||
{
|
{
|
||||||
enum { PROGRESS_RANGE = 1000 };
|
enum { PROGRESS_RANGE = 1000 };
|
||||||
|
|
||||||
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
|
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
|
||||||
|
fs::path filepath(filename);
|
||||||
|
|
||||||
|
SendDialog send_dialog(filepath.filename());
|
||||||
|
if (send_dialog.ShowModal() != wxID_OK) { return false; }
|
||||||
|
|
||||||
|
const bool print = send_dialog.print();
|
||||||
|
const auto upload_filepath = send_dialog.filename();
|
||||||
|
const auto upload_filename = upload_filepath.filename();
|
||||||
|
const auto upload_parent_path = upload_filepath.parent_path();
|
||||||
|
|
||||||
wxProgressDialog progress_dialog(
|
wxProgressDialog progress_dialog(
|
||||||
_(L("OctoPrint upload")),
|
_(L("OctoPrint upload")),
|
||||||
|
@ -61,14 +121,26 @@ bool OctoPrint::send_gcode(const std::string &filename, bool print) const
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
|
||||||
auto http = Http::post(std::move(make_url("api/files/local")));
|
auto url = make_url("api/files/local");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Uploading file %1% at %2%, filename: %3%, path: %4%, print: %5%")
|
||||||
|
% filepath.string()
|
||||||
|
% url
|
||||||
|
% upload_filename.string()
|
||||||
|
% upload_parent_path.string()
|
||||||
|
% print;
|
||||||
|
|
||||||
|
auto http = Http::post(std::move(url));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.form_add("print", print ? "true" : "false")
|
http.form_add("print", print ? "true" : "false")
|
||||||
.form_add_file("file", filename)
|
.form_add("path", upload_parent_path.string())
|
||||||
|
.form_add_file("file", filename, upload_filename.string())
|
||||||
.on_complete([&](std::string body, unsigned status) {
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: File uploaded: HTTP %1%: %2%") % status % body;
|
||||||
progress_dialog.Update(PROGRESS_RANGE);
|
progress_dialog.Update(PROGRESS_RANGE);
|
||||||
})
|
})
|
||||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1% (HTTP %2%)") % error % status;
|
||||||
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
|
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
|
||||||
GUI::show_error(&progress_dialog, std::move(errormsg));
|
GUI::show_error(&progress_dialog, std::move(errormsg));
|
||||||
res = false;
|
res = false;
|
||||||
|
@ -102,24 +174,24 @@ std::string OctoPrint::make_url(const std::string &path) const
|
||||||
{
|
{
|
||||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||||
if (host.back() == '/') {
|
if (host.back() == '/') {
|
||||||
return std::move((boost::format("%1%%2%") % host % path).str());
|
return (boost::format("%1%%2%") % host % path).str();
|
||||||
} else {
|
} else {
|
||||||
return std::move((boost::format("%1%/%2%") % host % path).str());
|
return (boost::format("%1%/%2%") % host % path).str();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return std::move((boost::format("http://%1%/%2%") % host % path).str());
|
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString OctoPrint::format_error(std::string error, unsigned status)
|
wxString OctoPrint::format_error(const std::string &error, unsigned status)
|
||||||
{
|
{
|
||||||
const wxString wxerror = error;
|
auto wxerror = wxString::FromUTF8(error.data());
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
return wxString::Format("HTTP %u: %s", status,
|
return wxString::Format("HTTP %u: %s", status,
|
||||||
(status == 401 ? _(L("Invalid API key")) : wxerror));
|
(status == 401 ? _(L("Invalid API key")) : wxerror));
|
||||||
} else {
|
} else {
|
||||||
return std::move(wxerror);
|
return wxerror;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ public:
|
||||||
OctoPrint(DynamicPrintConfig *config);
|
OctoPrint(DynamicPrintConfig *config);
|
||||||
|
|
||||||
bool test(wxString &curl_msg) const;
|
bool test(wxString &curl_msg) const;
|
||||||
bool send_gcode(const std::string &filename, bool print = false) const;
|
// Send gcode file to octoprint, filename is expected to be in UTF-8
|
||||||
|
bool send_gcode(const std::string &filename) const;
|
||||||
private:
|
private:
|
||||||
std::string host;
|
std::string host;
|
||||||
std::string apikey;
|
std::string apikey;
|
||||||
|
@ -25,7 +26,7 @@ private:
|
||||||
|
|
||||||
void set_auth(Http &http) const;
|
void set_auth(Http &http) const;
|
||||||
std::string make_url(const std::string &path) const;
|
std::string make_url(const std::string &path) const;
|
||||||
static wxString format_error(std::string error, unsigned status);
|
static wxString format_error(const std::string &error, unsigned status);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
int x_max() %code{% RETVAL = THIS->max.x; %};
|
int x_max() %code{% RETVAL = THIS->max.x; %};
|
||||||
int y_min() %code{% RETVAL = THIS->min.y; %};
|
int y_min() %code{% RETVAL = THIS->min.y; %};
|
||||||
int y_max() %code{% RETVAL = THIS->max.y; %};
|
int y_max() %code{% RETVAL = THIS->max.y; %};
|
||||||
|
void set_x_min(double val) %code{% THIS->min.x = val; %};
|
||||||
|
void set_x_max(double val) %code{% THIS->max.x = val; %};
|
||||||
|
void set_y_min(double val) %code{% THIS->min.y = val; %};
|
||||||
|
void set_y_max(double val) %code{% THIS->max.y = val; %};
|
||||||
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
|
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %};
|
||||||
bool defined() %code{% RETVAL = THIS->defined; %};
|
bool defined() %code{% RETVAL = THIS->defined; %};
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,11 @@ remove_all_canvases()
|
||||||
CODE:
|
CODE:
|
||||||
_3DScene::remove_all_canvases();
|
_3DScene::remove_all_canvases();
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_current_canvas()
|
||||||
|
CODE:
|
||||||
|
_3DScene::reset_current_canvas();
|
||||||
|
|
||||||
void
|
void
|
||||||
set_active(canvas, active)
|
set_active(canvas, active)
|
||||||
SV *canvas;
|
SV *canvas;
|
||||||
|
@ -197,6 +202,12 @@ set_active(canvas, active)
|
||||||
CODE:
|
CODE:
|
||||||
_3DScene::set_active((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active);
|
_3DScene::set_active((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active);
|
||||||
|
|
||||||
|
void
|
||||||
|
set_as_dirty(canvas)
|
||||||
|
SV *canvas;
|
||||||
|
CODE:
|
||||||
|
_3DScene::set_as_dirty((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
get_volumes_count(canvas)
|
get_volumes_count(canvas)
|
||||||
SV *canvas;
|
SV *canvas;
|
||||||
|
|
|
@ -9,5 +9,5 @@
|
||||||
OctoPrint(DynamicPrintConfig *config);
|
OctoPrint(DynamicPrintConfig *config);
|
||||||
~OctoPrint();
|
~OctoPrint();
|
||||||
|
|
||||||
bool send_gcode(std::string filename, bool print = false) const;
|
bool send_gcode(std::string filename) const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue