Merge branch 'master' of https://github.com/prusa3d/Slic3r into svg_icons
This commit is contained in:
commit
3c7ec5f7c6
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
|
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
|
||||||
remove_definitions(-D_UNICODE -DUNICODE)
|
remove_definitions(-D_UNICODE -DUNICODE)
|
||||||
@ -68,18 +70,31 @@ set(AVRDUDE_SOURCES
|
|||||||
)
|
)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
||||||
|
windows/utf8.c
|
||||||
windows/unistd.cpp
|
windows/unistd.cpp
|
||||||
windows/getopt.c
|
windows/getopt.c
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
|
||||||
|
|
||||||
set(STANDALONE_SOURCES
|
add_executable(avrdude-conf-gen conf-generate.cpp)
|
||||||
main-standalone.c
|
|
||||||
|
# Config file embedding
|
||||||
|
add_custom_command(
|
||||||
|
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
|
||||||
|
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||||
|
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf > avrdude-slic3r.conf.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
add_executable(avrdude-slic3r ${STANDALONE_SOURCES})
|
|
||||||
|
add_custom_target(gen_conf_h
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||||
|
add_dependencies(avrdude gen_conf_h)
|
||||||
|
|
||||||
|
add_executable(avrdude-slic3r main-standalone.cpp)
|
||||||
target_link_libraries(avrdude-slic3r avrdude)
|
target_link_libraries(avrdude-slic3r avrdude)
|
||||||
set_target_properties(avrdude-slic3r PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
|
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
|
||||||
|
@ -158,8 +158,10 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stk500_getsync(pgm) < 0)
|
if (stk500_getsync(pgm) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
424
src/avrdude/avrdude-slic3r.conf
Normal file
424
src/avrdude/avrdude-slic3r.conf
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# This is a basic minimal config file embedded into the avrdude-slic3r binary
|
||||||
|
# so that it can work in a standalone manner.
|
||||||
|
#
|
||||||
|
# Only the bits useful for Prusa3D devices were copied over from avrdude.conf
|
||||||
|
# If needed, more configuration can still be loaded into avrdude-slic3r
|
||||||
|
# via the -C command-line option.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "wiring";
|
||||||
|
desc = "Wiring";
|
||||||
|
type = "wiring";
|
||||||
|
connection_type = serial;
|
||||||
|
;
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "arduino";
|
||||||
|
desc = "Arduino";
|
||||||
|
type = "arduino";
|
||||||
|
connection_type = serial;
|
||||||
|
;
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "avr109";
|
||||||
|
desc = "Atmel AppNote AVR109 Boot Loader";
|
||||||
|
type = "butterfly";
|
||||||
|
connection_type = serial;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
# ATmega2560
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
part
|
||||||
|
id = "m2560";
|
||||||
|
desc = "ATmega2560";
|
||||||
|
signature = 0x1e 0x98 0x01;
|
||||||
|
has_jtag = yes;
|
||||||
|
stk500_devcode = 0xB2;
|
||||||
|
# avr910_devcode = 0x43;
|
||||||
|
chip_erase_delay = 9000;
|
||||||
|
pagel = 0xD7;
|
||||||
|
bs2 = 0xA0;
|
||||||
|
reset = dedicated;
|
||||||
|
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
|
||||||
|
"x x x x x x x x x x x x x x x x";
|
||||||
|
|
||||||
|
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x x x x x x x x x";
|
||||||
|
|
||||||
|
timeout = 200;
|
||||||
|
stabdelay = 100;
|
||||||
|
cmdexedelay = 25;
|
||||||
|
synchloops = 32;
|
||||||
|
bytedelay = 0;
|
||||||
|
pollindex = 3;
|
||||||
|
pollvalue = 0x53;
|
||||||
|
predelay = 1;
|
||||||
|
postdelay = 1;
|
||||||
|
pollmethod = 1;
|
||||||
|
|
||||||
|
pp_controlstack =
|
||||||
|
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
|
||||||
|
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
|
||||||
|
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
|
||||||
|
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02;
|
||||||
|
hventerstabdelay = 100;
|
||||||
|
progmodedelay = 0;
|
||||||
|
latchcycles = 5;
|
||||||
|
togglevtg = 1;
|
||||||
|
poweroffdelay = 15;
|
||||||
|
resetdelayms = 1;
|
||||||
|
resetdelayus = 0;
|
||||||
|
hvleavestabdelay = 15;
|
||||||
|
chiperasepulsewidth = 0;
|
||||||
|
chiperasepolltimeout = 10;
|
||||||
|
programfusepulsewidth = 0;
|
||||||
|
programfusepolltimeout = 5;
|
||||||
|
programlockpulsewidth = 0;
|
||||||
|
programlockpolltimeout = 5;
|
||||||
|
|
||||||
|
idr = 0x31;
|
||||||
|
spmcr = 0x57;
|
||||||
|
rampz = 0x3b;
|
||||||
|
allowfullpagebitstream = no;
|
||||||
|
|
||||||
|
ocdrev = 4;
|
||||||
|
|
||||||
|
memory "eeprom"
|
||||||
|
paged = no; /* leave this "no" */
|
||||||
|
page_size = 8; /* for parallel programming */
|
||||||
|
size = 4096;
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
readback_p1 = 0x00;
|
||||||
|
readback_p2 = 0x00;
|
||||||
|
read = " 1 0 1 0 0 0 0 0",
|
||||||
|
" x x x x a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
write = " 1 1 0 0 0 0 0 0",
|
||||||
|
" x x x x a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
loadpage_lo = " 1 1 0 0 0 0 0 1",
|
||||||
|
" 0 0 0 0 0 0 0 0",
|
||||||
|
" 0 0 0 0 0 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
writepage = " 1 1 0 0 0 0 1 0",
|
||||||
|
" 0 0 x x a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 0 0 0",
|
||||||
|
" x x x x x x x x";
|
||||||
|
|
||||||
|
mode = 0x41;
|
||||||
|
delay = 10;
|
||||||
|
blocksize = 8;
|
||||||
|
readsize = 256;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "flash"
|
||||||
|
paged = yes;
|
||||||
|
size = 262144;
|
||||||
|
page_size = 256;
|
||||||
|
num_pages = 1024;
|
||||||
|
min_write_delay = 4500;
|
||||||
|
max_write_delay = 4500;
|
||||||
|
readback_p1 = 0x00;
|
||||||
|
readback_p2 = 0x00;
|
||||||
|
read_lo = " 0 0 1 0 0 0 0 0",
|
||||||
|
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
read_hi = " 0 0 1 0 1 0 0 0",
|
||||||
|
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
loadpage_lo = " 0 1 0 0 0 0 0 0",
|
||||||
|
" x x x x x x x x",
|
||||||
|
" x a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
loadpage_hi = " 0 1 0 0 1 0 0 0",
|
||||||
|
" x x x x x x x x",
|
||||||
|
" x a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
writepage = " 0 1 0 0 1 1 0 0",
|
||||||
|
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 x x x x x x x",
|
||||||
|
" x x x x x x x x";
|
||||||
|
|
||||||
|
load_ext_addr = " 0 1 0 0 1 1 0 1",
|
||||||
|
" 0 0 0 0 0 0 0 0",
|
||||||
|
" 0 0 0 0 0 0 0 a16",
|
||||||
|
" 0 0 0 0 0 0 0 0";
|
||||||
|
|
||||||
|
mode = 0x41;
|
||||||
|
delay = 10;
|
||||||
|
blocksize = 256;
|
||||||
|
readsize = 256;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "lfuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
|
||||||
|
"x x x x x x x x i i i i i i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "hfuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
|
||||||
|
"x x x x x x x x i i i i i i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "efuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
|
||||||
|
"x x x x x x x x x x x x x i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "lock"
|
||||||
|
size = 1;
|
||||||
|
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x x x o o o o o o";
|
||||||
|
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
|
||||||
|
"x x x x x x x x 1 1 i i i i i i";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "calibration"
|
||||||
|
size = 1;
|
||||||
|
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
|
||||||
|
"0 0 0 0 0 0 0 0 o o o o o o o o";
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "signature"
|
||||||
|
size = 3;
|
||||||
|
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
|
||||||
|
"x x x x x x a1 a0 o o o o o o o o";
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
# ATmega32u4
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
part
|
||||||
|
id = "m32u4";
|
||||||
|
desc = "ATmega32U4";
|
||||||
|
signature = 0x1e 0x95 0x87;
|
||||||
|
usbpid = 0x2ff4;
|
||||||
|
has_jtag = yes;
|
||||||
|
# stk500_devcode = 0xB2;
|
||||||
|
# avr910_devcode = 0x43;
|
||||||
|
chip_erase_delay = 9000;
|
||||||
|
pagel = 0xD7;
|
||||||
|
bs2 = 0xA0;
|
||||||
|
reset = dedicated;
|
||||||
|
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
|
||||||
|
"x x x x x x x x x x x x x x x x";
|
||||||
|
|
||||||
|
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x x x x x x x x x";
|
||||||
|
|
||||||
|
timeout = 200;
|
||||||
|
stabdelay = 100;
|
||||||
|
cmdexedelay = 25;
|
||||||
|
synchloops = 32;
|
||||||
|
bytedelay = 0;
|
||||||
|
pollindex = 3;
|
||||||
|
pollvalue = 0x53;
|
||||||
|
predelay = 1;
|
||||||
|
postdelay = 1;
|
||||||
|
pollmethod = 1;
|
||||||
|
|
||||||
|
pp_controlstack =
|
||||||
|
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
|
||||||
|
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
|
||||||
|
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
|
||||||
|
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
|
||||||
|
hventerstabdelay = 100;
|
||||||
|
progmodedelay = 0;
|
||||||
|
latchcycles = 5;
|
||||||
|
togglevtg = 1;
|
||||||
|
poweroffdelay = 15;
|
||||||
|
resetdelayms = 1;
|
||||||
|
resetdelayus = 0;
|
||||||
|
hvleavestabdelay = 15;
|
||||||
|
chiperasepulsewidth = 0;
|
||||||
|
chiperasepolltimeout = 10;
|
||||||
|
programfusepulsewidth = 0;
|
||||||
|
programfusepolltimeout = 5;
|
||||||
|
programlockpulsewidth = 0;
|
||||||
|
programlockpolltimeout = 5;
|
||||||
|
|
||||||
|
idr = 0x31;
|
||||||
|
spmcr = 0x57;
|
||||||
|
rampz = 0x3b;
|
||||||
|
allowfullpagebitstream = no;
|
||||||
|
|
||||||
|
ocdrev = 3;
|
||||||
|
|
||||||
|
memory "eeprom"
|
||||||
|
paged = no; /* leave this "no" */
|
||||||
|
page_size = 4; /* for parallel programming */
|
||||||
|
size = 1024;
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
readback_p1 = 0x00;
|
||||||
|
readback_p2 = 0x00;
|
||||||
|
read = " 1 0 1 0 0 0 0 0",
|
||||||
|
" x x x x x a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
write = " 1 1 0 0 0 0 0 0",
|
||||||
|
" x x x x x a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
loadpage_lo = " 1 1 0 0 0 0 0 1",
|
||||||
|
" 0 0 0 0 0 0 0 0",
|
||||||
|
" 0 0 0 0 0 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
writepage = " 1 1 0 0 0 0 1 0",
|
||||||
|
" 0 0 x x x a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 0 0 0",
|
||||||
|
" x x x x x x x x";
|
||||||
|
|
||||||
|
mode = 0x41;
|
||||||
|
delay = 20;
|
||||||
|
blocksize = 4;
|
||||||
|
readsize = 256;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "flash"
|
||||||
|
paged = yes;
|
||||||
|
size = 32768;
|
||||||
|
page_size = 128;
|
||||||
|
num_pages = 256;
|
||||||
|
min_write_delay = 4500;
|
||||||
|
max_write_delay = 4500;
|
||||||
|
readback_p1 = 0x00;
|
||||||
|
readback_p2 = 0x00;
|
||||||
|
read_lo = " 0 0 1 0 0 0 0 0",
|
||||||
|
" 0 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
read_hi = " 0 0 1 0 1 0 0 0",
|
||||||
|
" 0 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||||
|
" o o o o o o o o";
|
||||||
|
|
||||||
|
loadpage_lo = " 0 1 0 0 0 0 0 0",
|
||||||
|
" x x x x x x x x",
|
||||||
|
" x x a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
loadpage_hi = " 0 1 0 0 1 0 0 0",
|
||||||
|
" x x x x x x x x",
|
||||||
|
" x x a5 a4 a3 a2 a1 a0",
|
||||||
|
" i i i i i i i i";
|
||||||
|
|
||||||
|
writepage = " 0 1 0 0 1 1 0 0",
|
||||||
|
" a15 a14 a13 a12 a11 a10 a9 a8",
|
||||||
|
" a7 a6 x x x x x x",
|
||||||
|
" x x x x x x x x";
|
||||||
|
|
||||||
|
mode = 0x41;
|
||||||
|
delay = 6;
|
||||||
|
blocksize = 128;
|
||||||
|
readsize = 256;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "lfuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
|
||||||
|
"x x x x x x x x i i i i i i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "hfuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
|
||||||
|
"x x x x x x x x i i i i i i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "efuse"
|
||||||
|
size = 1;
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
|
||||||
|
"x x x x x x x x x x x x i i i i";
|
||||||
|
|
||||||
|
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
|
||||||
|
"x x x x x x x x o o o o o o o o";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "lock"
|
||||||
|
size = 1;
|
||||||
|
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
|
||||||
|
"x x x x x x x x x x o o o o o o";
|
||||||
|
|
||||||
|
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
|
||||||
|
"x x x x x x x x 1 1 i i i i i i";
|
||||||
|
min_write_delay = 9000;
|
||||||
|
max_write_delay = 9000;
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "calibration"
|
||||||
|
size = 1;
|
||||||
|
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
|
||||||
|
"0 0 0 0 0 0 0 0 o o o o o o o o";
|
||||||
|
;
|
||||||
|
|
||||||
|
memory "signature"
|
||||||
|
size = 3;
|
||||||
|
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
|
||||||
|
"x x x x x x a1 a0 o o o o o o o o";
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
1188
src/avrdude/avrdude-slic3r.conf.h
Normal file
1188
src/avrdude/avrdude-slic3r.conf.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -42,7 +42,6 @@ static void avrdude_oom_handler(const char *context, void *user_p)
|
|||||||
|
|
||||||
struct AvrDude::priv
|
struct AvrDude::priv
|
||||||
{
|
{
|
||||||
std::string sys_config;
|
|
||||||
std::deque<std::vector<std::string>> args;
|
std::deque<std::vector<std::string>> args;
|
||||||
bool cancelled = false;
|
bool cancelled = false;
|
||||||
int exit_code = 0;
|
int exit_code = 0;
|
||||||
@ -54,8 +53,6 @@ struct AvrDude::priv
|
|||||||
|
|
||||||
std::thread avrdude_thread;
|
std::thread avrdude_thread;
|
||||||
|
|
||||||
priv(std::string &&sys_config) : sys_config(sys_config) {}
|
|
||||||
|
|
||||||
void set_handlers();
|
void set_handlers();
|
||||||
void unset_handlers();
|
void unset_handlers();
|
||||||
int run_one(const std::vector<std::string> &args);
|
int run_one(const std::vector<std::string> &args);
|
||||||
@ -110,7 +107,7 @@ int AvrDude::priv::run_one(const std::vector<std::string> &args) {
|
|||||||
|
|
||||||
message_fn(command_line.c_str(), command_line.size());
|
message_fn(command_line.c_str(), command_line.size());
|
||||||
|
|
||||||
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), sys_config.c_str());
|
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -130,7 +127,7 @@ int AvrDude::priv::run() {
|
|||||||
|
|
||||||
// Public
|
// Public
|
||||||
|
|
||||||
AvrDude::AvrDude(std::string sys_config) : p(new priv(std::move(sys_config))) {}
|
AvrDude::AvrDude() : p(new priv()) {}
|
||||||
|
|
||||||
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}
|
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ public:
|
|||||||
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
|
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
|
||||||
typedef std::function<void()> CompleteFn;
|
typedef std::function<void()> CompleteFn;
|
||||||
|
|
||||||
// Main c-tor, sys_config is the location of avrdude's main configuration file
|
AvrDude();
|
||||||
AvrDude(std::string sys_config);
|
|
||||||
AvrDude(AvrDude &&);
|
AvrDude(AvrDude &&);
|
||||||
AvrDude(const AvrDude &) = delete;
|
AvrDude(const AvrDude &) = delete;
|
||||||
AvrDude &operator=(AvrDude &&) = delete;
|
AvrDude &operator=(AvrDude &&) = delete;
|
||||||
|
@ -55,7 +55,7 @@ void avrdude_cancel();
|
|||||||
#define MSG_TRACE (4) /* displayed with -vvvv, show trace commuication */
|
#define MSG_TRACE (4) /* displayed with -vvvv, show trace commuication */
|
||||||
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
|
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
|
||||||
|
|
||||||
int avrdude_main(int argc, char * argv [], const char *sys_config);
|
int avrdude_main(int argc, char * argv []);
|
||||||
|
|
||||||
#if defined(WIN32NATIVE)
|
#if defined(WIN32NATIVE)
|
||||||
|
|
||||||
|
41
src/avrdude/conf-generate.cpp
Normal file
41
src/avrdude/conf-generate.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ios>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* filename = argv[1];
|
||||||
|
const char* symbol = argv[2];
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
std::fstream file(filename);
|
||||||
|
if (!file.good()) {
|
||||||
|
std::cerr << "Cannot read file: " << filename << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl;
|
||||||
|
std::cout << "unsigned char " << symbol << "[] = {";
|
||||||
|
|
||||||
|
char c;
|
||||||
|
std::cout << std::hex;
|
||||||
|
std::cout.fill('0');
|
||||||
|
for (file.get(c); !file.eof(); size++, file.get(c)) {
|
||||||
|
if (size % 12 == 0) { std::cout << "\n "; }
|
||||||
|
std::cout << "0x" << std::setw(2) << (unsigned)c << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n 0, 0\n};\n";
|
||||||
|
|
||||||
|
std::cout << std::dec;
|
||||||
|
std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl;
|
||||||
|
std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "config_gram.h"
|
#include "config_gram.h"
|
||||||
|
|
||||||
|
#include "avrdude-slic3r.conf.h" // Embedded config file
|
||||||
|
|
||||||
char default_programmer[MAX_STR_CONST];
|
char default_programmer[MAX_STR_CONST];
|
||||||
char default_parallel[PATH_MAX];
|
char default_parallel[PATH_MAX];
|
||||||
char default_serial[PATH_MAX];
|
char default_serial[PATH_MAX];
|
||||||
@ -325,7 +327,7 @@ int read_config(const char * file)
|
|||||||
FILE * f;
|
FILE * f;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
f = fopen(file, "r");
|
f = fopen_utf8(file, "r");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
|
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
|
||||||
progname, file, strerror(errno));
|
progname, file, strerror(errno));
|
||||||
@ -347,3 +349,33 @@ int read_config(const char * file)
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||||
|
extern YY_BUFFER_STATE yy_scan_bytes(char *base, size_t size);
|
||||||
|
extern void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||||
|
|
||||||
|
int read_config_builtin()
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
lineno = 1;
|
||||||
|
infile = "(builtin)";
|
||||||
|
|
||||||
|
// Note: Can't use yy_scan_buffer, it's buggy (?), leads to fread from a null FILE*
|
||||||
|
// and so unfortunatelly we have to use the copying variant here
|
||||||
|
YY_BUFFER_STATE buffer = yy_scan_bytes(avrdude_slic3r_conf, avrdude_slic3r_conf_size);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = yyparse();
|
||||||
|
yy_delete_buffer(buffer);
|
||||||
|
|
||||||
|
#ifdef HAVE_YYLEX_DESTROY
|
||||||
|
/* reset lexer and free any allocated memory */
|
||||||
|
yylex_destroy();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
|
||||||
|
#if defined(WIN32NATIVE)
|
||||||
|
#include "windows/utf8.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IHEX_MAXDATA 256
|
#define IHEX_MAXDATA 256
|
||||||
|
|
||||||
@ -102,21 +105,25 @@ static int fmt_autodetect(char * fname, unsigned section);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
|
FILE *fopen_utf8(const char *filename, const char *mode)
|
||||||
{
|
{
|
||||||
FILE *file;
|
|
||||||
// On Windows we need to convert the filename to UTF-16
|
// On Windows we need to convert the filename to UTF-16
|
||||||
#if defined(WIN32NATIVE)
|
#if defined(WIN32NATIVE)
|
||||||
static wchar_t fname_buffer[PATH_MAX];
|
static wchar_t fname_buffer[PATH_MAX];
|
||||||
static wchar_t mode_buffer[MAX_MODE_LEN];
|
static wchar_t mode_buffer[MAX_MODE_LEN];
|
||||||
|
|
||||||
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
|
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
|
||||||
if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
|
if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
|
||||||
|
|
||||||
file = _wfopen(fname_buffer, mode_buffer);
|
return _wfopen(fname_buffer, mode_buffer);
|
||||||
#else
|
#else
|
||||||
file = fopen(filename, mode);
|
return fopen(filename, mode);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
|
||||||
|
{
|
||||||
|
FILE *file = fopen_utf8(filename, mode);
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1527,8 +1527,10 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1579,8 +1581,10 @@ static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1631,8 +1635,10 @@ static int jtagmkII_open_pdi(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1684,8 +1690,10 @@ static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1737,8 +1745,10 @@ static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1790,8 +1800,10 @@ static int jtagmkII_dragon_open_pdi(PROGRAMMER * pgm, char * port)
|
|||||||
*/
|
*/
|
||||||
jtagmkII_drain(pgm, 0);
|
jtagmkII_drain(pgm, 0);
|
||||||
|
|
||||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
|
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3370,6 +3382,8 @@ static int jtagmkII_open32(PROGRAMMER * pgm, char * port)
|
|||||||
status = jtagmkII_getsync(pgm, -1);
|
status = jtagmkII_getsync(pgm, -1);
|
||||||
if(status < 0) return -1;
|
if(status < 0) return -1;
|
||||||
|
|
||||||
|
// FIXME: Error handling is bad here: memory leak in resp (?) and port not closed
|
||||||
|
|
||||||
// AVR32 "special"
|
// AVR32 "special"
|
||||||
buf[0] = CMND_SET_PARAMETER;
|
buf[0] = CMND_SET_PARAMETER;
|
||||||
buf[1] = 0x2D;
|
buf[1] = 0x2D;
|
||||||
|
@ -820,6 +820,8 @@ extern "C" {
|
|||||||
|
|
||||||
char * fmtstr(FILEFMT format);
|
char * fmtstr(FILEFMT format);
|
||||||
|
|
||||||
|
FILE *fopen_utf8(const char *filename, const char *mode);
|
||||||
|
|
||||||
int fileio(int op, char * filename, FILEFMT format,
|
int fileio(int op, char * filename, FILEFMT format,
|
||||||
struct avrpart * p, char * memtype, int size, unsigned section);
|
struct avrpart * p, char * memtype, int size, unsigned section);
|
||||||
|
|
||||||
@ -939,6 +941,7 @@ int init_config(void);
|
|||||||
void cleanup_config(void);
|
void cleanup_config(void);
|
||||||
|
|
||||||
int read_config(const char * file);
|
int read_config(const char * file);
|
||||||
|
int read_config_builtin();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#include "avrdude.h"
|
|
||||||
|
|
||||||
|
|
||||||
static const char* SYS_CONFIG = "/etc/avrdude-slic3r.conf";
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
return avrdude_main(argc, argv, SYS_CONFIG);
|
|
||||||
}
|
|
54
src/avrdude/main-standalone.cpp
Normal file
54
src/avrdude/main-standalone.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
extern "C" {
|
||||||
|
#include "avrdude.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "windows/utf8.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArgvUtf8 : std::vector<char*>
|
||||||
|
{
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
ArgvUtf8(int argc_w, wchar_t *argv_w[]) : std::vector<char*>(argc_w + 1, nullptr), argc(0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argc_w; i++) {
|
||||||
|
char *arg_utf8 = ::wstr_to_utf8(argv_w[i], -1);
|
||||||
|
if (arg_utf8 != nullptr) {
|
||||||
|
operator[](i) = arg_utf8;
|
||||||
|
argc = i + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ArgvUtf8()
|
||||||
|
{
|
||||||
|
for (char *arg : *this) {
|
||||||
|
if (arg != nullptr) {
|
||||||
|
::free(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int wmain(int argc_w, wchar_t *argv_w[])
|
||||||
|
{
|
||||||
|
ArgvUtf8 argv_utf8(argc_w, argv_w);
|
||||||
|
return ::avrdude_main(argv_utf8.argc, &argv_utf8[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return ::avrdude_main(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -426,7 +426,7 @@ static int cleanup_main(int status)
|
|||||||
/*
|
/*
|
||||||
* main routine
|
* main routine
|
||||||
*/
|
*/
|
||||||
int avrdude_main(int argc, char * argv [], const char *sys_config)
|
int avrdude_main(int argc, char * argv [])
|
||||||
{
|
{
|
||||||
int rc; /* general return code checking */
|
int rc; /* general return code checking */
|
||||||
int exitrc; /* exit code for main() */
|
int exitrc; /* exit code for main() */
|
||||||
@ -807,13 +807,15 @@ int avrdude_main(int argc, char * argv [], const char *sys_config)
|
|||||||
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
|
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
|
||||||
"%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
|
"%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
|
||||||
progname, version, __DATE__, __TIME__, progbuf, progbuf);
|
progname, version, __DATE__, __TIME__, progbuf, progbuf);
|
||||||
avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
|
// avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
|
||||||
progbuf, sys_config);
|
// progbuf, sys_config);
|
||||||
|
|
||||||
rc = read_config(sys_config);
|
// rc = read_config(sys_config);
|
||||||
|
rc = read_config_builtin();
|
||||||
if (rc) {
|
if (rc) {
|
||||||
avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
|
// avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
|
||||||
progname, sys_config);
|
// progname, sys_config);
|
||||||
|
avrdude_message(MSG_INFO, "%s: error reading built-in configuration file\n", progname);
|
||||||
return cleanup_main(1);
|
return cleanup_main(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
|
||||||
long serial_recv_timeout = 5000; /* ms */
|
long serial_recv_timeout = 4000; /* ms */
|
||||||
#define MAX_ZERO_READS 512
|
#define MAX_ZERO_READS 512
|
||||||
|
|
||||||
struct baud_mapping {
|
struct baud_mapping {
|
||||||
@ -150,6 +150,68 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Timeout read & write variants
|
||||||
|
// Additionally to the regular -1 on I/O error, they return -2 on timeout
|
||||||
|
ssize_t read_timeout(int fd, void *buf, size_t count, long timeout)
|
||||||
|
{
|
||||||
|
struct timeval tm, tm2;
|
||||||
|
fd_set rfds;
|
||||||
|
int nfds;
|
||||||
|
|
||||||
|
tm.tv_sec = timeout / 1000L;
|
||||||
|
tm.tv_usec = (timeout % 1000L) * 1000;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
tm2 = tm;
|
||||||
|
nfds = select(fd + 1, &rfds, NULL, NULL, &tm2);
|
||||||
|
|
||||||
|
if (nfds == 0) {
|
||||||
|
return -2;
|
||||||
|
} else if (nfds == -1) {
|
||||||
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return read(fd, buf, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t write_timeout(int fd, const void *buf, size_t count, long timeout)
|
||||||
|
{
|
||||||
|
struct timeval tm, tm2;
|
||||||
|
fd_set wfds;
|
||||||
|
int nfds;
|
||||||
|
|
||||||
|
tm.tv_sec = timeout / 1000L;
|
||||||
|
tm.tv_usec = (timeout % 1000L) * 1000;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(fd, &wfds);
|
||||||
|
tm2 = tm;
|
||||||
|
nfds = select(fd + 1, NULL, &wfds, NULL, &tm2);
|
||||||
|
|
||||||
|
if (nfds == 0) {
|
||||||
|
return -2;
|
||||||
|
} else if (nfds == -1) {
|
||||||
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return write(fd, buf, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a port description of the form <host>:<port>, open a TCP
|
* Given a port description of the form <host>:<port>, open a TCP
|
||||||
* connection to the specified destination, which is assumed to be a
|
* connection to the specified destination, which is assumed to be a
|
||||||
@ -314,6 +376,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
int rc;
|
int rc;
|
||||||
const unsigned char * p = buf;
|
const unsigned char * p = buf;
|
||||||
size_t len = buflen;
|
size_t len = buflen;
|
||||||
|
unsigned zero_writes = 0;
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
return 0;
|
return 0;
|
||||||
@ -341,14 +404,25 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
|
rc = write_timeout(fd->ifd, p, (len > 1024) ? 1024 : len, serial_recv_timeout);
|
||||||
if (rc < 0) {
|
if (rc == -2) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding\n", progname);
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (rc == -1) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
} else if (rc == 0) {
|
||||||
|
zero_writes++;
|
||||||
|
if (zero_writes > MAX_ZERO_READS) {
|
||||||
|
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding (too many zero writes)\n",
|
||||||
|
progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
zero_writes = 0;
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
}
|
}
|
||||||
p += rc;
|
|
||||||
len -= rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -357,51 +431,21 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
|
|
||||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct timeval timeout, to2;
|
|
||||||
fd_set rfds;
|
|
||||||
int nfds;
|
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char * p = buf;
|
unsigned char * p = buf;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
unsigned zero_reads = 0;
|
unsigned zero_reads = 0;
|
||||||
|
|
||||||
timeout.tv_sec = serial_recv_timeout / 1000L;
|
|
||||||
timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
|
|
||||||
to2 = timeout;
|
|
||||||
|
|
||||||
while (len < buflen) {
|
while (len < buflen) {
|
||||||
reselect:
|
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(fd->ifd, &rfds);
|
|
||||||
|
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
rc = read_timeout(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, serial_recv_timeout);
|
||||||
// FIXME: The timeout has different behaviour on Linux vs other Unices
|
|
||||||
// On Linux, the timeout is modified by subtracting the time spent,
|
if (rc == -2) {
|
||||||
// on OS X (for example), it is not modified.
|
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
|
||||||
// POSIX recommends re-initializing it before selecting.
|
|
||||||
if (nfds == 0) {
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
} else if (rc == -1) {
|
||||||
else if (nfds == -1) {
|
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, strerror(errno));
|
||||||
if (errno == EINTR || errno == EAGAIN) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): programmer is not responding,reselecting\n",
|
|
||||||
progname);
|
|
||||||
goto reselect;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n",
|
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
|
||||||
if (rc < 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (rc == 0) {
|
} else if (rc == 0) {
|
||||||
zero_reads++;
|
zero_reads++;
|
||||||
@ -445,49 +489,26 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
|||||||
|
|
||||||
static int ser_drain(union filedescriptor *fd, int display)
|
static int ser_drain(union filedescriptor *fd, int display)
|
||||||
{
|
{
|
||||||
struct timeval timeout;
|
|
||||||
fd_set rfds;
|
|
||||||
int nfds;
|
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char buf;
|
unsigned char buf;
|
||||||
unsigned zero_reads = 0;
|
unsigned zero_reads = 0;
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 250000;
|
|
||||||
|
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "drain>");
|
avrdude_message(MSG_INFO, "drain>");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(fd->ifd, &rfds);
|
|
||||||
|
|
||||||
reselect:
|
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
|
||||||
if (nfds == 0) {
|
rc = read_timeout(fd->ifd, &buf, 1, 250); // Note: timeout needs to be kept low to not timeout in programmers
|
||||||
|
if (rc == -2) {
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "<drain\n");
|
avrdude_message(MSG_INFO, "<drain\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (nfds == -1) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
goto reselect;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n",
|
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = read(fd->ifd, &buf, 1);
|
break;
|
||||||
if (rc < 0) {
|
} else if (rc == -1) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (rc == 0) {
|
} else if (rc == 0) {
|
||||||
zero_reads++;
|
zero_reads++;
|
||||||
|
@ -34,16 +34,63 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <ctype.h> /* for isprint */
|
#include <ctype.h> /* for isprint */
|
||||||
#include <errno.h> /* ENOTTY */
|
#include <errno.h> /* ENOTTY */
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
#include "windows/utf8.h"
|
||||||
|
|
||||||
long serial_recv_timeout = 5000; /* ms */
|
long serial_recv_timeout = 5000; /* ms */
|
||||||
|
|
||||||
#define W32SERBUFSIZE 1024
|
#define W32SERBUFSIZE 1024
|
||||||
|
|
||||||
|
|
||||||
|
// Get last error message string in UTF-8
|
||||||
|
// Always return a valid null-terminated string
|
||||||
|
// The returned string should be freed by the caller
|
||||||
|
char* last_error_string(int wsa)
|
||||||
|
{
|
||||||
|
LPWSTR wbuffer = NULL;
|
||||||
|
|
||||||
|
(void)wsa;
|
||||||
|
|
||||||
|
DWORD wbuffer_len = FormatMessageW(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
#ifdef HAVE_LIBWS2_32
|
||||||
|
wsa ? WSAGetLastError() : GetLastError(),
|
||||||
|
#else
|
||||||
|
GetLastError(),
|
||||||
|
#endif
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPWSTR)&wbuffer,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (wbuffer_len == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *res = wstr_to_utf8(wbuffer, wbuffer_len);
|
||||||
|
|
||||||
|
LocalFree(wbuffer);
|
||||||
|
|
||||||
|
if (res == NULL) {
|
||||||
|
// If we get here, conversion to UTF-8 failed
|
||||||
|
res = strdup("(could not get error message)");
|
||||||
|
if (res == NULL) {
|
||||||
|
avrdude_oom("last_error_string(): out of memory\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct baud_mapping {
|
struct baud_mapping {
|
||||||
long baud;
|
long baud;
|
||||||
DWORD speed;
|
DWORD speed;
|
||||||
@ -95,6 +142,7 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
|||||||
// ctmo.ReadIntervalTimeout = timeout;
|
// ctmo.ReadIntervalTimeout = timeout;
|
||||||
// ctmo.ReadTotalTimeoutMultiplier = timeout;
|
// ctmo.ReadTotalTimeoutMultiplier = timeout;
|
||||||
ctmo.ReadTotalTimeoutConstant = timeout;
|
ctmo.ReadTotalTimeoutConstant = timeout;
|
||||||
|
ctmo.WriteTotalTimeoutConstant = timeout;
|
||||||
|
|
||||||
return SetCommTimeouts(hComPort, &ctmo);
|
return SetCommTimeouts(hComPort, &ctmo);
|
||||||
}
|
}
|
||||||
@ -129,7 +177,6 @@ static int
|
|||||||
net_open(const char *port, union filedescriptor *fdp)
|
net_open(const char *port, union filedescriptor *fdp)
|
||||||
{
|
{
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
|
|
||||||
char *hstr, *pstr, *end;
|
char *hstr, *pstr, *end;
|
||||||
unsigned int pnum;
|
unsigned int pnum;
|
||||||
@ -175,18 +222,10 @@ net_open(const char *port, union filedescriptor *fdp)
|
|||||||
free(hstr);
|
free(hstr);
|
||||||
|
|
||||||
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
FormatMessage(
|
const char *error = last_error_string(1);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
WSAGetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, (char *)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,18 +235,9 @@ net_open(const char *port, union filedescriptor *fdp)
|
|||||||
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
|
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
||||||
FormatMessage(
|
const char *error = last_error_string(1);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
WSAGetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname, (char *)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +251,6 @@ net_open(const char *port, union filedescriptor *fdp)
|
|||||||
|
|
||||||
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
{
|
{
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
||||||
char *newname = 0;
|
char *newname = 0;
|
||||||
|
|
||||||
@ -261,19 +290,9 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
|||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
FormatMessage(
|
const char *error = last_error_string(0);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
|
|
||||||
progname, port, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,14 +365,13 @@ static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
|
|||||||
#ifdef HAVE_LIBWS2_32
|
#ifdef HAVE_LIBWS2_32
|
||||||
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
int rc;
|
int rc;
|
||||||
const unsigned char *p = buf;
|
const unsigned char *p = buf;
|
||||||
size_t len = buflen;
|
size_t len = buflen;
|
||||||
|
|
||||||
if (fd->ifd < 0) {
|
if (fd->ifd < 0) {
|
||||||
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
|
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
@ -382,19 +400,10 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
while (len) {
|
while (len) {
|
||||||
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
|
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FormatMessage(
|
const char *error = last_error_string(1);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
return -1;
|
||||||
NULL,
|
|
||||||
WSAGetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, (char *)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
p += rc;
|
p += rc;
|
||||||
len -= rc;
|
len -= rc;
|
||||||
@ -423,8 +432,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n",
|
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n", progname);
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,18 +457,18 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "\n");
|
avrdude_message(MSG_INFO, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_w32SetTimeOut(hComPort,500);
|
serial_w32SetTimeOut(hComPort,500);
|
||||||
|
|
||||||
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
|
if (!WriteFile(hComPort, buf, buflen, &written, NULL)) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
const char *error = last_error_string(0);
|
||||||
progname, "sorry no info avail"); // TODO
|
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
|
||||||
|
free(error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (written != buflen) {
|
if (written != buflen) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n",
|
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n", progname);
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +479,6 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
|||||||
#ifdef HAVE_LIBWS2_32
|
#ifdef HAVE_LIBWS2_32
|
||||||
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
struct timeval timeout, to2;
|
struct timeval timeout, to2;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
int nfds;
|
int nfds;
|
||||||
@ -481,7 +488,7 @@ static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
|||||||
|
|
||||||
if (fd->ifd < 0) {
|
if (fd->ifd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
|
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout.tv_sec = serial_recv_timeout / 1000L;
|
timeout.tv_sec = serial_recv_timeout / 1000L;
|
||||||
@ -504,37 +511,19 @@ reselect:
|
|||||||
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
|
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
|
||||||
goto reselect;
|
goto reselect;
|
||||||
} else {
|
} else {
|
||||||
FormatMessage(
|
const char *error = last_error_string(1);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
return -1;
|
||||||
NULL,
|
|
||||||
WSAGetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, (char *)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
|
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FormatMessage(
|
const char *error = last_error_string(1);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
free(error);
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
return -1;
|
||||||
NULL,
|
|
||||||
WSAGetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, (char *)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
p += rc;
|
p += rc;
|
||||||
len += rc;
|
len += rc;
|
||||||
@ -579,37 +568,24 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
|||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
|
|
||||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n",
|
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n", progname);
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
|
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
|
||||||
|
|
||||||
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
|
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
|
||||||
LPVOID lpMsgBuf;
|
const char *error = last_error_string(0);
|
||||||
FormatMessage(
|
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
free(error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL );
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
|
||||||
progname, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* time out detected */
|
/* time out detected */
|
||||||
if (read == 0) {
|
if (read == 0) {
|
||||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,20 +640,9 @@ static int ser_drain(union filedescriptor *fd, int display)
|
|||||||
|
|
||||||
readres=ReadFile(hComPort, buf, 1, &read, NULL);
|
readres=ReadFile(hComPort, buf, 1, &read, NULL);
|
||||||
if (!readres) {
|
if (!readres) {
|
||||||
LPVOID lpMsgBuf;
|
const char *error = last_error_string(0);
|
||||||
FormatMessage(
|
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
free(error);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL );
|
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
|
||||||
progname, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,11 +669,15 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
|
|||||||
|
|
||||||
// MIB510 init
|
// MIB510 init
|
||||||
if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 &&
|
if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 &&
|
||||||
mib510_isp(pgm, 1) != 0)
|
mib510_isp(pgm, 1) != 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (stk500_getsync(pgm) < 0)
|
if (stk500_getsync(pgm) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1695,8 +1695,10 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
|||||||
stk500v2_drain(pgm, 0);
|
stk500v2_drain(pgm, 0);
|
||||||
|
|
||||||
if (pgm->bitclock != 0.0) {
|
if (pgm->bitclock != 0.0) {
|
||||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1753,8 +1755,10 @@ static int stk600_open(PROGRAMMER * pgm, char * port)
|
|||||||
stk500v2_drain(pgm, 0);
|
stk500v2_drain(pgm, 0);
|
||||||
|
|
||||||
if (pgm->bitclock != 0.0) {
|
if (pgm->bitclock != 0.0) {
|
||||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
45
src/avrdude/windows/utf8.c
Normal file
45
src/avrdude/windows/utf8.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "utf8.h"
|
||||||
|
|
||||||
|
|
||||||
|
char* wstr_to_utf8(LPWSTR wstr, int len)
|
||||||
|
{
|
||||||
|
char *res = NULL;
|
||||||
|
|
||||||
|
int res_size = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
||||||
|
if (res_size > 0) {
|
||||||
|
// Note: WideCharToMultiByte doesn't null-terminate if real (ie. > 0) buffer length is passed
|
||||||
|
res = malloc(len != - 1 ? res_size + 1 : res_size);
|
||||||
|
if (res == NULL) { return NULL; }
|
||||||
|
|
||||||
|
if (WideCharToMultiByte(CP_UTF8, 0, wstr, len, res, res_size, NULL, NULL) == res_size) {
|
||||||
|
if (len != -1) { res[res_size] = '\0'; }
|
||||||
|
} else {
|
||||||
|
free(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWSTR utf8_to_wstr(const char *str, int len)
|
||||||
|
{
|
||||||
|
LPWSTR res = NULL;
|
||||||
|
|
||||||
|
int res_size = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
|
||||||
|
if (res_size > 0) {
|
||||||
|
// Note: MultiByteToWideChar doesn't null-terminate if real (ie. > 0) buffer length is passed
|
||||||
|
res = malloc(len != - 1 ? res_size + 1 : res_size);
|
||||||
|
|
||||||
|
if (res == NULL) { return NULL; }
|
||||||
|
|
||||||
|
if (MultiByteToWideChar(CP_UTF8, 0, str, len, res, res_size) == res_size) {
|
||||||
|
if (len != -1) { res[res_size] = L'\0'; }
|
||||||
|
} else {
|
||||||
|
free(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
10
src/avrdude/windows/utf8.h
Normal file
10
src/avrdude/windows/utf8.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef SLIC3R_AVRDUDE_UTF8_H
|
||||||
|
#define SLIC3R_AVRDUDE_UTF8_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
extern char* wstr_to_utf8(LPWSTR wstr, int len);
|
||||||
|
extern LPWSTR utf8_to_wstr(const char *str, int len);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SLIC3R_AVRDUDE_UTF8_H
|
@ -192,8 +192,10 @@ static int wiring_open(PROGRAMMER * pgm, char * port)
|
|||||||
/* drain any extraneous input */
|
/* drain any extraneous input */
|
||||||
stk500v2_drain(pgm, 0);
|
stk500v2_drain(pgm, 0);
|
||||||
|
|
||||||
if (stk500v2_getsync(pgm) < 0)
|
if (stk500v2_getsync(pgm) < 0) {
|
||||||
|
serial_close(&pgm->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2488,6 +2488,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||||||
// adds analyzer tags and updates analyzer's tracking data
|
// adds analyzer tags and updates analyzer's tracking data
|
||||||
if (m_enable_analyzer)
|
if (m_enable_analyzer)
|
||||||
{
|
{
|
||||||
|
// PrusaMultiMaterial::Writer may generate GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines without updating m_last_height and m_last_width
|
||||||
|
// so, if the last role was erWipeTower we force export of GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines
|
||||||
|
bool last_was_wipe_tower = (m_last_analyzer_extrusion_role == erWipeTower);
|
||||||
|
|
||||||
if (path.role() != m_last_analyzer_extrusion_role)
|
if (path.role() != m_last_analyzer_extrusion_role)
|
||||||
{
|
{
|
||||||
m_last_analyzer_extrusion_role = path.role();
|
m_last_analyzer_extrusion_role = path.role();
|
||||||
@ -2505,7 +2509,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||||||
gcode += buf;
|
gcode += buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_last_width != path.width)
|
if (last_was_wipe_tower || (m_last_width != path.width))
|
||||||
{
|
{
|
||||||
m_last_width = path.width;
|
m_last_width = path.width;
|
||||||
|
|
||||||
@ -2514,7 +2518,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||||||
gcode += buf;
|
gcode += buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_last_height != path.height)
|
if (last_was_wipe_tower || (m_last_height != path.height))
|
||||||
{
|
{
|
||||||
m_last_height = path.height;
|
m_last_height = path.height;
|
||||||
|
|
||||||
|
@ -59,6 +59,17 @@ void PrintConfigDef::init_common_params()
|
|||||||
def->cli = "max-print-height=f";
|
def->cli = "max-print-height=f";
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionFloat(200.0);
|
def->default_value = new ConfigOptionFloat(200.0);
|
||||||
|
|
||||||
|
def = this->add("slice_closing_radius", coFloat);
|
||||||
|
def->label = L("Slice gap closing radius");
|
||||||
|
def->category = L("Advanced");
|
||||||
|
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
|
||||||
|
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
|
||||||
|
def->sidetext = L("mm");
|
||||||
|
def->cli = "slice-closing-radius=f";
|
||||||
|
def->min = 0;
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->default_value = new ConfigOptionFloat(0.049);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintConfigDef::init_fff_params()
|
void PrintConfigDef::init_fff_params()
|
||||||
|
@ -384,6 +384,7 @@ public:
|
|||||||
ConfigOptionEnum<SeamPosition> seam_position;
|
ConfigOptionEnum<SeamPosition> seam_position;
|
||||||
// ConfigOptionFloat seam_preferred_direction;
|
// ConfigOptionFloat seam_preferred_direction;
|
||||||
// ConfigOptionFloat seam_preferred_direction_jitter;
|
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||||
|
ConfigOptionFloat slice_closing_radius;
|
||||||
ConfigOptionBool support_material;
|
ConfigOptionBool support_material;
|
||||||
// Automatic supports (generated based on support_material_threshold).
|
// Automatic supports (generated based on support_material_threshold).
|
||||||
ConfigOptionBool support_material_auto;
|
ConfigOptionBool support_material_auto;
|
||||||
@ -425,6 +426,7 @@ protected:
|
|||||||
OPT_PTR(layer_height);
|
OPT_PTR(layer_height);
|
||||||
OPT_PTR(raft_layers);
|
OPT_PTR(raft_layers);
|
||||||
OPT_PTR(seam_position);
|
OPT_PTR(seam_position);
|
||||||
|
OPT_PTR(slice_closing_radius);
|
||||||
// OPT_PTR(seam_preferred_direction);
|
// OPT_PTR(seam_preferred_direction);
|
||||||
// OPT_PTR(seam_preferred_direction_jitter);
|
// OPT_PTR(seam_preferred_direction_jitter);
|
||||||
OPT_PTR(support_material);
|
OPT_PTR(support_material);
|
||||||
@ -963,6 +965,8 @@ public:
|
|||||||
//Number of the layers needed for the exposure time fade [3;20]
|
//Number of the layers needed for the exposure time fade [3;20]
|
||||||
ConfigOptionInt faded_layers /*= 10*/;
|
ConfigOptionInt faded_layers /*= 10*/;
|
||||||
|
|
||||||
|
ConfigOptionFloat slice_closing_radius;
|
||||||
|
|
||||||
// Enabling or disabling support creation
|
// Enabling or disabling support creation
|
||||||
ConfigOptionBool supports_enable;
|
ConfigOptionBool supports_enable;
|
||||||
|
|
||||||
@ -1036,6 +1040,7 @@ protected:
|
|||||||
{
|
{
|
||||||
OPT_PTR(layer_height);
|
OPT_PTR(layer_height);
|
||||||
OPT_PTR(faded_layers);
|
OPT_PTR(faded_layers);
|
||||||
|
OPT_PTR(slice_closing_radius);
|
||||||
OPT_PTR(supports_enable);
|
OPT_PTR(supports_enable);
|
||||||
OPT_PTR(support_head_front_diameter);
|
OPT_PTR(support_head_front_diameter);
|
||||||
OPT_PTR(support_head_penetration);
|
OPT_PTR(support_head_penetration);
|
||||||
|
@ -157,8 +157,6 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
|||||||
"expTimeFirst = " + expt_first_str + "\n"
|
"expTimeFirst = " + expt_first_str + "\n"
|
||||||
"numFade = " + cnt_fade_layers + "\n"
|
"numFade = " + cnt_fade_layers + "\n"
|
||||||
"layerHeight = " + layerh_str + "\n"
|
"layerHeight = " + layerh_str + "\n"
|
||||||
"expTime = "+expt_str+" + resinType = generic+layerHeight = "
|
|
||||||
+layerh_str+" + printer = DWARF3\n"
|
|
||||||
"usedMaterial = " + used_material + "\n"
|
"usedMaterial = " + used_material + "\n"
|
||||||
"numSlow = " + cnt_slow_layers + "\n"
|
"numSlow = " + cnt_slow_layers + "\n"
|
||||||
"numFast = " + cnt_fast_layers + "\n";
|
"numFast = " + cnt_fast_layers + "\n";
|
||||||
|
@ -453,7 +453,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
|||||||
} else if (
|
} else if (
|
||||||
opt_key == "layer_height"
|
opt_key == "layer_height"
|
||||||
|| opt_key == "first_layer_height"
|
|| opt_key == "first_layer_height"
|
||||||
|| opt_key == "raft_layers") {
|
|| opt_key == "raft_layers"
|
||||||
|
|| opt_key == "slice_closing_radius") {
|
||||||
steps.emplace_back(posSlice);
|
steps.emplace_back(posSlice);
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
@ -1643,7 +1644,7 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
|||||||
const Print *print = this->print();
|
const Print *print = this->print();
|
||||||
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
||||||
mslicer.init(&mesh, callback);
|
mslicer.init(&mesh, callback);
|
||||||
mslicer.slice(z, &layers, callback);
|
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,7 +561,7 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
|||||||
heights.emplace_back(hi);
|
heights.emplace_back(hi);
|
||||||
|
|
||||||
std::vector<ExPolygons> out; out.reserve(size_t(std::ceil(h/layerh)));
|
std::vector<ExPolygons> out; out.reserve(size_t(std::ceil(h/layerh)));
|
||||||
slicer.slice(heights, &out, thrfn);
|
slicer.slice(heights, 0.f, &out, thrfn);
|
||||||
|
|
||||||
size_t count = 0; for(auto& o : out) count += o.size();
|
size_t count = 0; for(auto& o : out) count += o.size();
|
||||||
|
|
||||||
|
@ -2105,7 +2105,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
|
|||||||
fullmesh.merge(get_pad());
|
fullmesh.merge(get_pad());
|
||||||
TriangleMeshSlicer slicer(&fullmesh);
|
TriangleMeshSlicer slicer(&fullmesh);
|
||||||
SlicedSupports ret;
|
SlicedSupports ret;
|
||||||
slicer.slice(heights, &ret, get().ctl().cancelfn);
|
slicer.slice(heights, 0.f, &ret, get().ctl().cancelfn);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
/*if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
||||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||||
if (it_print_object_status != print_object_status.end())
|
if (it_print_object_status != print_object_status.end())
|
||||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||||
@ -351,6 +351,18 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||||||
if (it_print_object_status != print_object_status.end())
|
if (it_print_object_status != print_object_status.end())
|
||||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
bool old_user_modified = model_object.sla_points_status == sla::PointsStatus::UserModified;
|
||||||
|
bool new_user_modified = model_object_new.sla_points_status == sla::PointsStatus::UserModified;
|
||||||
|
if ((old_user_modified && ! new_user_modified) || // switching to automatic supports from manual supports
|
||||||
|
(! old_user_modified && new_user_modified) || // switching to manual supports from automatic supports
|
||||||
|
(new_user_modified && model_object.sla_support_points != model_object_new.sla_support_points)) {
|
||||||
|
if (it_print_object_status != print_object_status.end())
|
||||||
|
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||||
|
|
||||||
|
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||||
|
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||||
@ -625,7 +637,7 @@ void SLAPrint::process()
|
|||||||
ilh, float(lh));
|
ilh, float(lh));
|
||||||
|
|
||||||
auto& layers = po.m_model_slices; layers.clear();
|
auto& layers = po.m_model_slices; layers.clear();
|
||||||
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); });
|
||||||
};
|
};
|
||||||
|
|
||||||
// In this step we check the slices, identify island and cover them with
|
// In this step we check the slices, identify island and cover them with
|
||||||
@ -1358,7 +1370,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||||||
bool invalidated = false;
|
bool invalidated = false;
|
||||||
for (const t_config_option_key &opt_key : opt_keys) {
|
for (const t_config_option_key &opt_key : opt_keys) {
|
||||||
if ( opt_key == "layer_height"
|
if ( opt_key == "layer_height"
|
||||||
|| opt_key == "faded_layers") {
|
|| opt_key == "faded_layers"
|
||||||
|
|| opt_key == "slice_closing_radius") {
|
||||||
steps.emplace_back(slaposObjectSlice);
|
steps.emplace_back(slaposObjectSlice);
|
||||||
} else if (
|
} else if (
|
||||||
opt_key == "supports_enable"
|
opt_key == "supports_enable"
|
||||||
|
@ -852,7 +852,7 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const
|
void TriangleMeshSlicer::slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const
|
||||||
{
|
{
|
||||||
std::vector<Polygons> layers_p;
|
std::vector<Polygons> layers_p;
|
||||||
this->slice(z, &layers_p, throw_on_cancel);
|
this->slice(z, &layers_p, throw_on_cancel);
|
||||||
@ -861,13 +861,13 @@ void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygo
|
|||||||
layers->resize(z.size());
|
layers->resize(z.size());
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, z.size()),
|
tbb::blocked_range<size_t>(0, z.size()),
|
||||||
[&layers_p, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) {
|
[&layers_p, closing_radius, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
||||||
printf("Layer " PRINTF_ZU " (slice_z = %.2f):\n", layer_id, z[layer_id]);
|
printf("Layer " PRINTF_ZU " (slice_z = %.2f):\n", layer_id, z[layer_id]);
|
||||||
#endif
|
#endif
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
this->make_expolygons(layers_p[layer_id], &(*layers)[layer_id]);
|
this->make_expolygons(layers_p[layer_id], closing_radius, &(*layers)[layer_id]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::make_expolygons in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::make_expolygons in parallel - end";
|
||||||
@ -1600,7 +1600,7 @@ void TriangleMeshSlicer::make_expolygons_simple(std::vector<IntersectionLine> &l
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) const
|
void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Input loops are not suitable for evenodd nor nonzero fill types, as we might get
|
Input loops are not suitable for evenodd nor nonzero fill types, as we might get
|
||||||
@ -1655,7 +1655,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
|||||||
// 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959
|
// 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959
|
||||||
// double safety_offset = scale_(0.0499);
|
// double safety_offset = scale_(0.0499);
|
||||||
// 0.0001 is set to satisfy GH #520, #1029, #1364
|
// 0.0001 is set to satisfy GH #520, #1029, #1364
|
||||||
double safety_offset = scale_(0.0001);
|
double safety_offset = scale_(closing_radius);
|
||||||
|
|
||||||
/* The following line is commented out because it can generate wrong polygons,
|
/* The following line is commented out because it can generate wrong polygons,
|
||||||
see for example issue #661 */
|
see for example issue #661 */
|
||||||
@ -1670,17 +1670,17 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// append to the supplied collection
|
// append to the supplied collection
|
||||||
/* Fix for issue #661 { */
|
if (safety_offset > 0)
|
||||||
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
|
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
|
||||||
//expolygons_append(*slices, ex_slices);
|
else
|
||||||
/* } */
|
expolygons_append(*slices, union_ex(loops, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const
|
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const
|
||||||
{
|
{
|
||||||
Polygons pp;
|
Polygons pp;
|
||||||
this->make_loops(lines, &pp);
|
this->make_loops(lines, &pp);
|
||||||
this->make_expolygons(pp, slices);
|
this->make_expolygons(pp, closing_radius, slices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) const
|
void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) const
|
||||||
|
@ -165,7 +165,7 @@ public:
|
|||||||
TriangleMeshSlicer(TriangleMesh* mesh) { this->init(mesh, [](){}); }
|
TriangleMeshSlicer(TriangleMesh* mesh) { this->init(mesh, [](){}); }
|
||||||
void init(TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel);
|
void init(TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel);
|
||||||
void slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
void slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
||||||
void slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
void slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
||||||
enum FacetSliceType {
|
enum FacetSliceType {
|
||||||
NoSlice = 0,
|
NoSlice = 0,
|
||||||
Slicing = 1,
|
Slicing = 1,
|
||||||
@ -184,9 +184,9 @@ private:
|
|||||||
|
|
||||||
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
||||||
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;
|
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;
|
||||||
void make_expolygons(const Polygons &loops, ExPolygons* slices) const;
|
void make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const;
|
||||||
void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
||||||
void make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
void make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
TriangleMesh make_cube(double x, double y, double z);
|
TriangleMesh make_cube(double x, double y, double z);
|
||||||
|
@ -1004,7 +1004,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason)
|
|||||||
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
|
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
|
||||||
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
|
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
|
||||||
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
|
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
|
||||||
p->btn_cancel = new wxButton(this, wxID_CANCEL);
|
p->btn_cancel = new wxButton(this, wxID_CANCEL, _(L("Cancel"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||||
p->btnsizer->AddStretchSpacer();
|
p->btnsizer->AddStretchSpacer();
|
||||||
p->btnsizer->Add(p->btn_prev, 0, wxLEFT, BTN_SPACING);
|
p->btnsizer->Add(p->btn_prev, 0, wxLEFT, BTN_SPACING);
|
||||||
p->btnsizer->Add(p->btn_next, 0, wxLEFT, BTN_SPACING);
|
p->btnsizer->Add(p->btn_next, 0, wxLEFT, BTN_SPACING);
|
||||||
|
@ -122,7 +122,6 @@ struct FirmwareDialog::priv
|
|||||||
// This is a shared pointer holding the background AvrDude task
|
// This is a shared pointer holding the background AvrDude task
|
||||||
// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
|
// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
|
||||||
AvrDude::Ptr avrdude;
|
AvrDude::Ptr avrdude;
|
||||||
std::string avrdude_config;
|
|
||||||
unsigned progress_tasks_done;
|
unsigned progress_tasks_done;
|
||||||
unsigned progress_tasks_bar;
|
unsigned progress_tasks_bar;
|
||||||
bool user_cancelled;
|
bool user_cancelled;
|
||||||
@ -134,7 +133,6 @@ struct FirmwareDialog::priv
|
|||||||
btn_flash_label_flashing(_(L("Cancel"))),
|
btn_flash_label_flashing(_(L("Cancel"))),
|
||||||
label_status_flashing(_(L("Flashing in progress. Please do not disconnect the printer!"))),
|
label_status_flashing(_(L("Flashing in progress. Please do not disconnect the printer!"))),
|
||||||
timer_pulse(q),
|
timer_pulse(q),
|
||||||
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
|
|
||||||
progress_tasks_done(0),
|
progress_tasks_done(0),
|
||||||
progress_tasks_bar(0),
|
progress_tasks_bar(0),
|
||||||
user_cancelled(false),
|
user_cancelled(false),
|
||||||
@ -553,7 +551,7 @@ void FirmwareDialog::priv::perform_upload()
|
|||||||
flashing_start(hex_file.device == HexFile::DEV_MK3 ? 2 : 1);
|
flashing_start(hex_file.device == HexFile::DEV_MK3 ? 2 : 1);
|
||||||
|
|
||||||
// Init the avrdude object
|
// Init the avrdude object
|
||||||
AvrDude avrdude(avrdude_config);
|
AvrDude avrdude;
|
||||||
|
|
||||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||||
@ -722,7 +720,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
|||||||
panel->SetSizer(vsizer);
|
panel->SetSizer(vsizer);
|
||||||
|
|
||||||
auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
|
auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
|
||||||
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
|
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
|
||||||
"Hex files (*.hex)|*.hex|All files|*.*");
|
"Hex files (*.hex)|*.hex|All files|*.*");
|
||||||
|
|
||||||
auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
|
auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
|
||||||
@ -770,7 +768,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
|||||||
// Experience says it needs to be 1, otherwise things won't get sized properly.
|
// Experience says it needs to be 1, otherwise things won't get sized properly.
|
||||||
vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING);
|
vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING);
|
||||||
|
|
||||||
p->btn_close = new wxButton(panel, wxID_CLOSE);
|
p->btn_close = new wxButton(panel, wxID_CLOSE, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||||
p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
|
p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
|
||||||
p->btn_flash->Disable();
|
p->btn_flash->Disable();
|
||||||
auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
|
auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
@ -896,8 +896,7 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio
|
|||||||
if (needs_reset)
|
if (needs_reset)
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
if (volume->is_modifier)
|
m_mode = volume->is_modifier ? Volume : Instance;
|
||||||
m_mode = Volume;
|
|
||||||
|
|
||||||
switch (m_mode)
|
switch (m_mode)
|
||||||
{
|
{
|
||||||
@ -1261,17 +1260,22 @@ static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to
|
|||||||
return (axis.z() < 0) ? -angle : angle;
|
return (axis.z() < 0) ? -angle : angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
|
||||||
|
void GLCanvas3D::Selection::rotate(const Vec3d& rotation, GLCanvas3D::TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Only relative rotation values are allowed in the world coordinate system.
|
||||||
|
assert(! transformation_type.world() || transformation_type.relative());
|
||||||
|
|
||||||
int rot_axis_max;
|
int rot_axis_max;
|
||||||
|
//FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
|
||||||
rotation.cwiseAbs().maxCoeff(&rot_axis_max);
|
rotation.cwiseAbs().maxCoeff(&rot_axis_max);
|
||||||
|
|
||||||
// For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
|
// For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
|
||||||
std::vector<int> object_instance_first(m_model->objects.size(), -1);
|
std::vector<int> object_instance_first(m_model->objects.size(), -1);
|
||||||
auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, local](GLVolume &volume, int i) {
|
auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
|
||||||
int first_volume_idx = object_instance_first[volume.object_idx()];
|
int first_volume_idx = object_instance_first[volume.object_idx()];
|
||||||
if (rot_axis_max != 2 && first_volume_idx != -1) {
|
if (rot_axis_max != 2 && first_volume_idx != -1) {
|
||||||
// Generic rotation, but no rotation around the Z axis.
|
// Generic rotation, but no rotation around the Z axis.
|
||||||
@ -1283,11 +1287,14 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
|||||||
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
|
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
|
||||||
} else {
|
} else {
|
||||||
// extracts rotations from the composed transformation
|
// extracts rotations from the composed transformation
|
||||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
Vec3d new_rotation = transformation_type.world() ?
|
||||||
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix());
|
Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
|
||||||
if (rot_axis_max == 2 && !local)
|
transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
|
||||||
|
if (rot_axis_max == 2 && transformation_type.joint()) {
|
||||||
// Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
|
// Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
|
||||||
volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
double z_diff = rotation_diff_z(new_rotation, m_cache.volumes_data[i].get_instance_rotation());
|
||||||
|
volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||||
|
}
|
||||||
volume.set_instance_rotation(new_rotation);
|
volume.set_instance_rotation(new_rotation);
|
||||||
object_instance_first[volume.object_idx()] = i;
|
object_instance_first[volume.object_idx()] = i;
|
||||||
}
|
}
|
||||||
@ -1300,7 +1307,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
|||||||
rotate_instance(volume, i);
|
rotate_instance(volume, i);
|
||||||
else if (is_single_volume() || is_single_modifier())
|
else if (is_single_volume() || is_single_modifier())
|
||||||
{
|
{
|
||||||
if (local)
|
if (transformation_type.independent())
|
||||||
volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
|
volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1318,7 +1325,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
|||||||
// extracts rotations from the composed transformation
|
// extracts rotations from the composed transformation
|
||||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||||
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
||||||
if (!local)
|
if (transformation_type.joint())
|
||||||
{
|
{
|
||||||
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
||||||
volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
||||||
@ -5136,6 +5143,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
{
|
{
|
||||||
// to remove hover on objects when the mouse goes out of this canvas
|
// to remove hover on objects when the mouse goes out of this canvas
|
||||||
m_mouse.position = Vec2d(-1.0, -1.0);
|
m_mouse.position = Vec2d(-1.0, -1.0);
|
||||||
|
// ensure m_mouse.left_down is reset (it may happen when switching canvas)
|
||||||
|
m_mouse.left_down = false;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
|
else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
|
||||||
@ -5203,12 +5212,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
{
|
{
|
||||||
// event was taken care of by the SlaSupports gizmo
|
// event was taken care of by the SlaSupports gizmo
|
||||||
}
|
}
|
||||||
else if (view_toolbar_contains_mouse != -1)
|
else if (evt.LeftDown() && (view_toolbar_contains_mouse != -1))
|
||||||
{
|
{
|
||||||
if (m_view_toolbar != nullptr)
|
if (m_view_toolbar != nullptr)
|
||||||
m_view_toolbar->do_action((unsigned int)view_toolbar_contains_mouse, *this);
|
m_view_toolbar->do_action((unsigned int)view_toolbar_contains_mouse, *this);
|
||||||
}
|
}
|
||||||
else if (toolbar_contains_mouse != -1)
|
else if (evt.LeftDown() && (toolbar_contains_mouse != -1))
|
||||||
{
|
{
|
||||||
m_toolbar_action_running = true;
|
m_toolbar_action_running = true;
|
||||||
m_mouse.set_start_position_3D_as_invalid();
|
m_mouse.set_start_position_3D_as_invalid();
|
||||||
@ -5388,7 +5397,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
case Gizmos::Rotate:
|
case Gizmos::Rotate:
|
||||||
{
|
{
|
||||||
// Apply new temporary rotations
|
// Apply new temporary rotations
|
||||||
m_selection.rotate(m_gizmos.get_rotation(), evt.AltDown());
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
|
if (evt.AltDown())
|
||||||
|
transformation_type.set_independent();
|
||||||
|
m_selection.rotate(m_gizmos.get_rotation(), transformation_type);
|
||||||
wxGetApp().obj_manipul()->update_settings_value(m_selection);
|
wxGetApp().obj_manipul()->update_settings_value(m_selection);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5403,7 +5415,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
// the gizmo got the event and took some action, no need to do anything more here
|
// the gizmo got the event and took some action, no need to do anything more here
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
|
// do not process dragging if the mouse is into any of the HUD elements
|
||||||
|
else if (evt.Dragging() && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1) && (view_toolbar_contains_mouse == -1))
|
||||||
{
|
{
|
||||||
m_mouse.dragging = true;
|
m_mouse.dragging = true;
|
||||||
|
|
||||||
@ -5412,7 +5425,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
if (m_layers_editing.state == LayersEditing::Editing)
|
if (m_layers_editing.state == LayersEditing::Editing)
|
||||||
_perform_layer_editing_action(&evt);
|
_perform_layer_editing_action(&evt);
|
||||||
}
|
}
|
||||||
else if (evt.LeftIsDown())
|
// do not process the dragging if the left mouse was set down in another canvas
|
||||||
|
else if (m_mouse.left_down && evt.LeftIsDown())
|
||||||
{
|
{
|
||||||
// if dragging over blank area with left button, rotate
|
// if dragging over blank area with left button, rotate
|
||||||
#if ENABLE_MOVE_MIN_THRESHOLD
|
#if ENABLE_MOVE_MIN_THRESHOLD
|
||||||
|
@ -375,6 +375,59 @@ class GLCanvas3D
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
class TransformationType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Enum {
|
||||||
|
// Transforming in a world coordinate system
|
||||||
|
World = 0,
|
||||||
|
// Transforming in a local coordinate system
|
||||||
|
Local = 1,
|
||||||
|
// Absolute transformations, allowed in local coordinate system only.
|
||||||
|
Absolute = 0,
|
||||||
|
// Relative transformations, allowed in both local and world coordinate system.
|
||||||
|
Relative = 2,
|
||||||
|
// For group selection, the transformation is performed as if the group made a single solid body.
|
||||||
|
Joint = 0,
|
||||||
|
// For group selection, the transformation is performed on each object independently.
|
||||||
|
Independent = 4,
|
||||||
|
|
||||||
|
World_Relative_Joint = World | Relative | Joint,
|
||||||
|
World_Relative_Independent = World | Relative | Independent,
|
||||||
|
Local_Absolute_Joint = Local | Absolute | Joint,
|
||||||
|
Local_Absolute_Independent = Local | Absolute | Independent,
|
||||||
|
Local_Relative_Joint = Local | Relative | Joint,
|
||||||
|
Local_Relative_Independent = Local | Relative | Independent,
|
||||||
|
};
|
||||||
|
|
||||||
|
TransformationType() : m_value(World) {}
|
||||||
|
TransformationType(Enum value) : m_value(value) {}
|
||||||
|
TransformationType& operator=(Enum value) { m_value = value; return *this; }
|
||||||
|
|
||||||
|
Enum operator()() const { return m_value; }
|
||||||
|
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
|
||||||
|
|
||||||
|
void set_world() { this->remove(Local); }
|
||||||
|
void set_local() { this->add(Local); }
|
||||||
|
void set_absolute() { this->remove(Relative); }
|
||||||
|
void set_relative() { this->add(Relative); }
|
||||||
|
void set_joint() { this->remove(Independent); }
|
||||||
|
void set_independent() { this->add(Independent); }
|
||||||
|
|
||||||
|
bool world() const { return ! this->has(Local); }
|
||||||
|
bool local() const { return this->has(Local); }
|
||||||
|
bool absolute() const { return ! this->has(Relative); }
|
||||||
|
bool relative() const { return this->has(Relative); }
|
||||||
|
bool joint() const { return ! this->has(Independent); }
|
||||||
|
bool independent() const { return this->has(Independent); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
|
||||||
|
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
|
||||||
|
|
||||||
|
Enum m_value;
|
||||||
|
};
|
||||||
|
|
||||||
class Selection
|
class Selection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -553,7 +606,7 @@ public:
|
|||||||
void start_dragging();
|
void start_dragging();
|
||||||
|
|
||||||
void translate(const Vec3d& displacement, bool local = false);
|
void translate(const Vec3d& displacement, bool local = false);
|
||||||
void rotate(const Vec3d& rotation, bool local);
|
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||||
void flattening_rotate(const Vec3d& normal);
|
void flattening_rotate(const Vec3d& normal);
|
||||||
void scale(const Vec3d& scale, bool local);
|
void scale(const Vec3d& scale, bool local);
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "GUI_ObjectSettings.hpp"
|
||||||
|
#include "GUI_ObjectList.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "PresetBundle.hpp"
|
#include "PresetBundle.hpp"
|
||||||
|
|
||||||
@ -1922,7 +1924,7 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
|
|||||||
|
|
||||||
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
|
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
|
||||||
{
|
{
|
||||||
return (m_state == On) && (m_model_object != nullptr) && (m_model_object != m_old_model_object) && !m_model_object->instances.empty();
|
return (m_state == On) && (m_model_object != m_old_model_object) && (m_model_object != nullptr) && !m_model_object->instances.empty();
|
||||||
|
|
||||||
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
|
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
|
||||||
// return false;
|
// return false;
|
||||||
@ -2161,13 +2163,10 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSlaSupports::delete_selected_points()
|
void GLGizmoSlaSupports::delete_selected_points(bool force)
|
||||||
{
|
{
|
||||||
if (!m_editing_mode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
|
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
|
||||||
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands)) {
|
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands || force)) {
|
||||||
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
|
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
|
||||||
m_unsaved_changes = true;
|
m_unsaved_changes = true;
|
||||||
}
|
}
|
||||||
@ -2228,9 +2227,41 @@ void GLGizmoSlaSupports::render_tooltip_texture() const {
|
|||||||
#endif // not ENABLE_IMGUI
|
#endif // not ENABLE_IMGUI
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<ConfigOption*> GLGizmoSlaSupports::get_config_options(const std::vector<std::string>& keys) const
|
||||||
|
{
|
||||||
|
std::vector<ConfigOption*> out;
|
||||||
|
|
||||||
|
if (!m_model_object)
|
||||||
|
return out;
|
||||||
|
|
||||||
|
DynamicPrintConfig& object_cfg = m_model_object->config;
|
||||||
|
DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||||
|
std::unique_ptr<DynamicPrintConfig> default_cfg = nullptr;
|
||||||
|
|
||||||
|
for (const std::string& key : keys) {
|
||||||
|
if (object_cfg.has(key))
|
||||||
|
out.push_back(object_cfg.option(key));
|
||||||
|
else
|
||||||
|
if (print_cfg.has(key))
|
||||||
|
out.push_back(print_cfg.option(key));
|
||||||
|
else { // we must get it from defaults
|
||||||
|
if (default_cfg == nullptr)
|
||||||
|
default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys));
|
||||||
|
out.push_back(default_cfg->option(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_IMGUI
|
#if ENABLE_IMGUI
|
||||||
void GLGizmoSlaSupports::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
void GLGizmoSlaSupports::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||||
{
|
{
|
||||||
|
if (!m_model_object)
|
||||||
|
return;
|
||||||
|
|
||||||
bool first_run = true; // This is a hack to redraw the button when all points are removed,
|
bool first_run = true; // This is a hack to redraw the button when all points are removed,
|
||||||
// so it is not delayed until the background process finishes.
|
// so it is not delayed until the background process finishes.
|
||||||
RENDER_AGAIN:
|
RENDER_AGAIN:
|
||||||
@ -2242,6 +2273,7 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
bool force_refresh = false;
|
bool force_refresh = false;
|
||||||
bool remove_selected = false;
|
bool remove_selected = false;
|
||||||
|
bool remove_all = false;
|
||||||
|
|
||||||
if (m_editing_mode) {
|
if (m_editing_mode) {
|
||||||
m_imgui->text(_(L("Left mouse click - add point")));
|
m_imgui->text(_(L("Left mouse click - add point")));
|
||||||
@ -2255,7 +2287,8 @@ RENDER_AGAIN:
|
|||||||
wxString str = ss.str();
|
wxString str = ss.str();
|
||||||
|
|
||||||
bool old_combo_state = m_combo_box_open;
|
bool old_combo_state = m_combo_box_open;
|
||||||
m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options, str);
|
// The combo is commented out for now, until the feature is supported by backend.
|
||||||
|
// m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options, str);
|
||||||
force_refresh |= (old_combo_state != m_combo_box_open);
|
force_refresh |= (old_combo_state != m_combo_box_open);
|
||||||
|
|
||||||
float current_number = atof(str);
|
float current_number = atof(str);
|
||||||
@ -2279,6 +2312,10 @@ RENDER_AGAIN:
|
|||||||
remove_selected = m_imgui->button(_(L("Remove selected points")));
|
remove_selected = m_imgui->button(_(L("Remove selected points")));
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(m_editing_mode_cache.empty());
|
||||||
|
remove_all = m_imgui->button(_(L("Remove all points")));
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
m_imgui->text(" "); // vertical gap
|
m_imgui->text(" "); // vertical gap
|
||||||
|
|
||||||
if (m_imgui->button(_(L("Apply changes")))) {
|
if (m_imgui->button(_(L("Apply changes")))) {
|
||||||
@ -2293,13 +2330,29 @@ RENDER_AGAIN:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // not in editing mode:
|
else { // not in editing mode:
|
||||||
/*ImGui::PushItemWidth(100.0f);
|
ImGui::PushItemWidth(100.0f);
|
||||||
m_imgui->text(_(L("Minimal points distance: ")));
|
m_imgui->text(_(L("Minimal points distance: ")));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
bool value_changed = ImGui::SliderFloat("", &m_minimal_point_distance, 0.f, 20.f, "%.f mm");
|
|
||||||
|
std::vector<ConfigOption*> opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"});
|
||||||
|
float density = static_cast<ConfigOptionInt*>(opts[0])->value;
|
||||||
|
float minimal_point_distance = static_cast<ConfigOptionFloat*>(opts[1])->value;
|
||||||
|
|
||||||
|
bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
|
||||||
|
if (value_changed)
|
||||||
|
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
|
||||||
|
|
||||||
m_imgui->text(_(L("Support points density: ")));
|
m_imgui->text(_(L("Support points density: ")));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
value_changed |= ImGui::SliderFloat(" ", &m_density, 0.f, 200.f, "%.f %%");*/
|
if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) {
|
||||||
|
value_changed = true;
|
||||||
|
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value_changed) { // Update side panel
|
||||||
|
wxGetApp().obj_settings()->UpdateAndShow(true);
|
||||||
|
wxGetApp().obj_list()->update_settings_items();
|
||||||
|
}
|
||||||
|
|
||||||
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
|
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
|
||||||
|
|
||||||
@ -2310,6 +2363,12 @@ RENDER_AGAIN:
|
|||||||
if (m_imgui->button(_(L("Manual editing [M]"))))
|
if (m_imgui->button(_(L("Manual editing [M]"))))
|
||||||
switch_to_editing_mode();
|
switch_to_editing_mode();
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(m_editing_mode_cache.empty());
|
||||||
|
remove_all = m_imgui->button(_(L("Remove all points")));
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
m_imgui->text("");
|
||||||
|
|
||||||
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
|
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
|
||||||
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
|
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
|
||||||
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
|
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
|
||||||
@ -2324,10 +2383,14 @@ RENDER_AGAIN:
|
|||||||
}
|
}
|
||||||
m_old_editing_state = m_editing_mode;
|
m_old_editing_state = m_editing_mode;
|
||||||
|
|
||||||
if (remove_selected) {
|
if (remove_selected || remove_all) {
|
||||||
force_refresh = false;
|
force_refresh = false;
|
||||||
m_parent.reload_scene(true);
|
m_parent.reload_scene(true);
|
||||||
delete_selected_points();
|
if (remove_all)
|
||||||
|
select_point(AllPoints);
|
||||||
|
delete_selected_points(remove_all);
|
||||||
|
if (remove_all && !m_editing_mode)
|
||||||
|
editing_mode_apply_changes();
|
||||||
if (first_run) {
|
if (first_run) {
|
||||||
first_run = false;
|
first_run = false;
|
||||||
goto RENDER_AGAIN;
|
goto RENDER_AGAIN;
|
||||||
@ -2375,19 +2438,22 @@ void GLGizmoSlaSupports::on_set_state()
|
|||||||
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
||||||
}
|
}
|
||||||
if (m_state == Off) {
|
if (m_state == Off) {
|
||||||
if (m_old_state != Off && m_model_object) { // the gizmo was just turned Off
|
if (m_old_state != Off) { // the gizmo was just turned Off
|
||||||
|
|
||||||
if (m_unsaved_changes) {
|
if (m_model_object) {
|
||||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
|
if (m_unsaved_changes) {
|
||||||
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
|
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
|
||||||
if (dlg.ShowModal() == wxID_YES)
|
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
|
||||||
editing_mode_apply_changes();
|
if (dlg.ShowModal() == wxID_YES)
|
||||||
else
|
editing_mode_apply_changes();
|
||||||
editing_mode_discard_changes();
|
else
|
||||||
|
editing_mode_discard_changes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_parent.toggle_model_objects_visibility(true);
|
m_parent.toggle_model_objects_visibility(true);
|
||||||
m_editing_mode = false; // so it is not active next time the gizmo opens
|
m_editing_mode = false; // so it is not active next time the gizmo opens
|
||||||
|
m_editing_mode_cache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_old_state = m_state;
|
m_old_state = m_state;
|
||||||
@ -2492,7 +2558,7 @@ void GLGizmoSlaSupports::auto_generate()
|
|||||||
"Are you sure you want to do it?\n"
|
"Are you sure you want to do it?\n"
|
||||||
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
||||||
|
|
||||||
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || dlg.ShowModal() == wxID_YES) {
|
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) {
|
||||||
m_model_object->sla_support_points.clear();
|
m_model_object->sla_support_points.clear();
|
||||||
m_model_object->sla_points_status = sla::PointsStatus::Generating;
|
m_model_object->sla_points_status = sla::PointsStatus::Generating;
|
||||||
m_editing_mode_cache.clear();
|
m_editing_mode_cache.clear();
|
||||||
|
@ -498,7 +498,7 @@ public:
|
|||||||
virtual ~GLGizmoSlaSupports();
|
virtual ~GLGizmoSlaSupports();
|
||||||
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
|
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
|
||||||
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
|
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
|
||||||
void delete_selected_points();
|
void delete_selected_points(bool force = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool on_init();
|
bool on_init();
|
||||||
@ -536,6 +536,8 @@ private:
|
|||||||
int m_canvas_width;
|
int m_canvas_width;
|
||||||
int m_canvas_height;
|
int m_canvas_height;
|
||||||
|
|
||||||
|
std::vector<ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
|
||||||
|
|
||||||
// Methods that do the model_object and editing cache synchronization,
|
// Methods that do the model_object and editing cache synchronization,
|
||||||
// editing mode selection, etc:
|
// editing mode selection, etc:
|
||||||
enum {
|
enum {
|
||||||
|
@ -177,33 +177,40 @@ bool GUI_App::OnInit()
|
|||||||
|
|
||||||
if (this->plater() != nullptr)
|
if (this->plater() != nullptr)
|
||||||
this->obj_manipul()->update_if_dirty();
|
this->obj_manipul()->update_if_dirty();
|
||||||
});
|
|
||||||
|
|
||||||
// On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...)
|
// Preset updating & Configwizard are done after the above initializations,
|
||||||
// are shown before or in the same event callback with the main frame creation.
|
// and after MainFrame is created & shown.
|
||||||
// Therefore we schedule them for later using CallAfter.
|
// The extra CallAfter() is needed because of Mac, where this is the only way
|
||||||
CallAfter([this]() {
|
// to popup a modal dialog on start without screwing combo boxes.
|
||||||
try {
|
// This is ugly but I honestly found not better way to do it.
|
||||||
if (!preset_updater->config_update())
|
// Neither wxShowEvent nor wxWindowCreateEvent work reliably.
|
||||||
mainframe->Close();
|
static bool once = true;
|
||||||
} catch (const std::exception &ex) {
|
if (once) {
|
||||||
show_error(nullptr, ex.what());
|
once = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!preset_updater->config_update()) {
|
||||||
|
mainframe->Close();
|
||||||
|
}
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
show_error(nullptr, ex.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
CallAfter([this] {
|
||||||
|
if (!config_wizard_startup(app_conf_exists)) {
|
||||||
|
// Only notify if there was not wizard so as not to bother too much ...
|
||||||
|
preset_updater->slic3r_update_notify();
|
||||||
|
}
|
||||||
|
preset_updater->sync(preset_bundle);
|
||||||
|
});
|
||||||
|
|
||||||
|
load_current_presets();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CallAfter([this]() {
|
|
||||||
if (!config_wizard_startup(app_conf_exists)) {
|
|
||||||
// Only notify if there was not wizard so as not to bother too much ...
|
|
||||||
preset_updater->slic3r_update_notify();
|
|
||||||
}
|
|
||||||
preset_updater->sync(preset_bundle);
|
|
||||||
|
|
||||||
load_current_presets();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
mainframe->Show(true);
|
mainframe->Show(true);
|
||||||
return m_initialized = true;
|
m_initialized = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
||||||
|
@ -1180,25 +1180,29 @@ Geometry::Transformation volume_to_bed_transformation(const Geometry::Transforma
|
|||||||
{
|
{
|
||||||
Geometry::Transformation out;
|
Geometry::Transformation out;
|
||||||
|
|
||||||
|
// Is the angle close to a multiple of 90 degrees?
|
||||||
|
auto ninety_degrees = [](double a) {
|
||||||
|
a = fmod(std::abs(a), 0.5 * PI);
|
||||||
|
if (a > 0.25 * PI)
|
||||||
|
a = 0.5 * PI - a;
|
||||||
|
return a < 0.001;
|
||||||
|
};
|
||||||
if (instance_transformation.is_scaling_uniform()) {
|
if (instance_transformation.is_scaling_uniform()) {
|
||||||
// No need to run the non-linear least squares fitting for uniform scaling.
|
// No need to run the non-linear least squares fitting for uniform scaling.
|
||||||
// Just set the inverse.
|
// Just set the inverse.
|
||||||
out.set_from_transform(instance_transformation.get_matrix(true).inverse());
|
out.set_from_transform(instance_transformation.get_matrix(true).inverse());
|
||||||
}
|
}
|
||||||
else
|
else if (ninety_degrees(instance_transformation.get_rotation().x()) && ninety_degrees(instance_transformation.get_rotation().y()) && ninety_degrees(instance_transformation.get_rotation().z()))
|
||||||
{
|
{
|
||||||
|
// Anisotropic scaling, rotation by multiples of ninety degrees.
|
||||||
Eigen::Matrix3d instance_rotation_trafo =
|
Eigen::Matrix3d instance_rotation_trafo =
|
||||||
(Eigen::AngleAxisd(instance_transformation.get_rotation().z(), Vec3d::UnitZ()) *
|
(Eigen::AngleAxisd(instance_transformation.get_rotation().z(), Vec3d::UnitZ()) *
|
||||||
Eigen::AngleAxisd(instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
Eigen::AngleAxisd(instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
||||||
Eigen::AngleAxisd(instance_transformation.get_rotation().x(), Vec3d::UnitX())).toRotationMatrix();
|
Eigen::AngleAxisd(instance_transformation.get_rotation().x(), Vec3d::UnitX())).toRotationMatrix();
|
||||||
Eigen::Matrix3d instance_rotation_trafo_inv =
|
Eigen::Matrix3d volume_rotation_trafo =
|
||||||
(Eigen::AngleAxisd(- instance_transformation.get_rotation().x(), Vec3d::UnitX()) *
|
(Eigen::AngleAxisd(-instance_transformation.get_rotation().x(), Vec3d::UnitX()) *
|
||||||
Eigen::AngleAxisd(- instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
Eigen::AngleAxisd(-instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
||||||
Eigen::AngleAxisd(- instance_transformation.get_rotation().z(), Vec3d::UnitZ())).toRotationMatrix();
|
Eigen::AngleAxisd(-instance_transformation.get_rotation().z(), Vec3d::UnitZ())).toRotationMatrix();
|
||||||
Vec3d euler_angles_inv = Geometry::extract_euler_angles(instance_rotation_trafo_inv);
|
|
||||||
|
|
||||||
Eigen::Matrix3d instance_trafo = instance_rotation_trafo *
|
|
||||||
Eigen::Scaling(instance_transformation.get_scaling_factor().cwiseProduct(instance_transformation.get_mirror()));
|
|
||||||
|
|
||||||
// 8 corners of the bounding box.
|
// 8 corners of the bounding box.
|
||||||
auto pts = Eigen::MatrixXd(8, 3);
|
auto pts = Eigen::MatrixXd(8, 3);
|
||||||
@ -1211,101 +1215,27 @@ Geometry::Transformation volume_to_bed_transformation(const Geometry::Transforma
|
|||||||
pts(6, 0) = bbox.max.x(); pts(6, 1) = bbox.max.y(); pts(6, 2) = bbox.min.z();
|
pts(6, 0) = bbox.max.x(); pts(6, 1) = bbox.max.y(); pts(6, 2) = bbox.min.z();
|
||||||
pts(7, 0) = bbox.max.x(); pts(7, 1) = bbox.max.y(); pts(7, 2) = bbox.max.z();
|
pts(7, 0) = bbox.max.x(); pts(7, 1) = bbox.max.y(); pts(7, 2) = bbox.max.z();
|
||||||
|
|
||||||
// Current parameters: 3x scale, 3x rotation
|
// Corners of the bounding box transformed into the modifier mesh coordinate space, with inverse rotation applied to the modifier.
|
||||||
auto beta = Eigen::MatrixXd(3 + 3, 1);
|
auto qs = pts *
|
||||||
beta << 1., 1., 1., euler_angles_inv(0), euler_angles_inv(1), euler_angles_inv(2);
|
(instance_rotation_trafo *
|
||||||
|
Eigen::Scaling(instance_transformation.get_scaling_factor().cwiseProduct(instance_transformation.get_mirror())) *
|
||||||
|
volume_rotation_trafo).inverse().transpose();
|
||||||
|
// Fill in scaling based on least squares fitting of the bounding box corners.
|
||||||
|
Vec3d scale;
|
||||||
|
for (int i = 0; i < 3; ++ i)
|
||||||
|
scale(i) = pts.col(i).dot(qs.col(i)) / pts.col(i).dot(pts.col(i));
|
||||||
|
|
||||||
{
|
out.set_rotation(Geometry::extract_euler_angles(volume_rotation_trafo));
|
||||||
// Trafo from world to the coordinate system of the modifier mesh, with the inverse rotation applied to the modifier.
|
out.set_scaling_factor(Vec3d(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2))));
|
||||||
Eigen::Matrix3d A_scaling = instance_trafo * instance_rotation_trafo_inv;
|
out.set_mirror(Vec3d(scale(0) > 0 ? 1. : -1, scale(1) > 0 ? 1. : -1, scale(2) > 0 ? 1. : -1));
|
||||||
// Corners of the bounding box transformed into the modifier mesh coordinate space, with inverse rotation applied to the modifier.
|
|
||||||
auto qs = pts * A_scaling.inverse().transpose();
|
|
||||||
// Fill in scaling based on least squares fitting of the bounding box corners.
|
|
||||||
for (int i = 0; i < 3; ++i)
|
|
||||||
beta(i) = pts.col(i).dot(qs.col(i)) / pts.col(i).dot(pts.col(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jacobian
|
|
||||||
// rows: 8 corners of a cube times 3 dimensions,
|
|
||||||
// cols: 3x scale, 3x rotation
|
|
||||||
auto J = Eigen::MatrixXd(8 * 3, 3 + 3);
|
|
||||||
|
|
||||||
// Until convergence:
|
|
||||||
Eigen::Matrix3d s, dsx, dsy, dsz;
|
|
||||||
Eigen::Matrix3d rx, drx, ry, dry, rz, drz;
|
|
||||||
s.setIdentity();
|
|
||||||
rx.setIdentity(); ry.setIdentity(); rz.setIdentity();
|
|
||||||
dsx.setZero(); dsy.setZero(); dsz.setZero();
|
|
||||||
drx.setZero(); dry.setZero(); drz.setZero();
|
|
||||||
dsx(0, 0) = 1.; dsy(1, 1) = 1.; dsz(2, 2) = 1.;
|
|
||||||
|
|
||||||
// Solve the non-linear Least Squares problem by Levenberg–Marquardt algorithm (modified Gauss–Newton iteration)
|
|
||||||
const double eps = 1.e-7;
|
|
||||||
auto beta_best = beta;
|
|
||||||
double beta_best_error = 1e10;
|
|
||||||
for (size_t iter = 0; iter < 200; ++ iter) {
|
|
||||||
// Current rotation & scaling transformation.
|
|
||||||
auto trafo = instance_trafo *
|
|
||||||
Eigen::AngleAxisd(beta(5), Vec3d::UnitZ()) *
|
|
||||||
Eigen::AngleAxisd(beta(4), Vec3d::UnitY()) *
|
|
||||||
Eigen::AngleAxisd(beta(3), Vec3d::UnitX()) *
|
|
||||||
Eigen::Scaling(Vec3d(beta(0), beta(1), beta(2)));
|
|
||||||
// Current error after rotation & scaling.
|
|
||||||
auto dy = (pts - pts * trafo.transpose()).eval();
|
|
||||||
double err = 0;
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
err += dy.row(i).norm();
|
|
||||||
if (err < beta_best_error) {
|
|
||||||
beta_best = beta;
|
|
||||||
beta_best_error = err;
|
|
||||||
}
|
|
||||||
// Fill in the Jacobian at current beta.
|
|
||||||
double cos_rx = cos(beta(3));
|
|
||||||
double sin_rx = sin(beta(3));
|
|
||||||
double cos_ry = cos(beta(4));
|
|
||||||
double sin_ry = sin(beta(4));
|
|
||||||
double cos_rz = cos(beta(5));
|
|
||||||
double sin_rz = sin(beta(5));
|
|
||||||
rx << 1., 0., 0., 0., cos_rx, -sin_rx, 0., sin_rx, cos_rx;
|
|
||||||
drx << 0., 0., 0., 0., -sin_rx, -cos_rx, 0., cos_rx, -sin_rx;
|
|
||||||
ry << cos_ry, 0., sin_ry, 0., 1., 0., -sin_ry, 0., cos_ry;
|
|
||||||
dry << -sin_ry, 0., cos_ry, 0., 0., 0., -cos_ry, 0., -sin_ry;
|
|
||||||
rz << cos_rz, -sin_rz, 0., sin_rz, cos_rz, 0., 0., 0., 1.;
|
|
||||||
drz << -sin_rz, -cos_rz, 0., cos_rz, -sin_rz, 0., 0., 0., 0.;
|
|
||||||
s(0, 0) = beta(0);
|
|
||||||
s(1, 1) = beta(1);
|
|
||||||
s(2, 2) = beta(2);
|
|
||||||
auto rot = (instance_trafo * rz * ry * rx).eval();
|
|
||||||
auto jrx = pts * (instance_trafo * rz * ry * drx * s).transpose();
|
|
||||||
auto jry = pts * (instance_trafo * rz * dry * rx * s).transpose();
|
|
||||||
auto jrz = pts * (instance_trafo * drz * ry * rx * s).transpose();
|
|
||||||
for (int r = 0; r < 8; ++ r) {
|
|
||||||
for (int i = 0; i < 3; ++ i) {
|
|
||||||
J(r * 3 + i, 0) = rot(i, 0) * pts(r, 0);
|
|
||||||
J(r * 3 + i, 1) = rot(i, 1) * pts(r, 1);
|
|
||||||
J(r * 3 + i, 2) = rot(i, 2) * pts(r, 2);
|
|
||||||
J(r * 3 + i, 3) = jrx(r, i);
|
|
||||||
J(r * 3 + i, 4) = jry(r, i);
|
|
||||||
J(r * 3 + i, 5) = jrz(r, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Solving the normal equations for delta beta.
|
|
||||||
auto rhs = (J.transpose() * Eigen::Map<Eigen::VectorXd>(dy.data(), dy.size())).eval();
|
|
||||||
double lambda = 1.; // 0.01;
|
|
||||||
auto A = (J.transpose() * J + Eigen::Matrix<double, 6, 6>::Identity() * lambda).eval();
|
|
||||||
auto L = A.ldlt();
|
|
||||||
auto delta_beta = L.solve(rhs).eval();
|
|
||||||
// Check for convergence.
|
|
||||||
auto delta_beta_max = delta_beta.cwiseAbs().maxCoeff();
|
|
||||||
if (delta_beta_max < eps)
|
|
||||||
break;
|
|
||||||
beta = beta + delta_beta;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.set_rotation(Vec3d(beta_best(3), beta_best(4), beta_best(5)));
|
|
||||||
out.set_scaling_factor(Vec3d(std::abs(beta_best(0)), std::abs(beta_best(1)), std::abs(beta_best(2))));
|
|
||||||
out.set_mirror(Vec3d(beta_best(0) > 0 ? 1. : -1, beta_best(1) > 0 ? 1. : -1, beta_best(2) > 0 ? 1. : -1));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// General anisotropic scaling, general rotation.
|
||||||
|
// Keep the modifier mesh in the instance coordinate system, so the modifier mesh will not be aligned with the world.
|
||||||
|
// Scale it to get the required size.
|
||||||
|
out.set_scaling_factor(instance_transformation.get_scaling_factor().cwiseInverse());
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -361,16 +361,21 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
|||||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
const GLCanvas3D::Selection& selection = canvas->get_selection();
|
const GLCanvas3D::Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
Vec3d delta_rotation = rotation - m_cache.rotation;
|
GLCanvas3D::TransformationType transformation_type(GLCanvas3D::TransformationType::World_Relative_Joint);
|
||||||
|
if (selection.is_single_full_instance() || selection.requires_local_axes())
|
||||||
|
transformation_type.set_independent();
|
||||||
|
if (selection.is_single_full_instance()) {
|
||||||
|
//FIXME GLCanvas3D::Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
|
||||||
|
// transformation_type.set_absolute();
|
||||||
|
transformation_type.set_local();
|
||||||
|
}
|
||||||
|
|
||||||
Vec3d rad_rotation;
|
Vec3d rad_rotation;
|
||||||
for (size_t i = 0; i < 3; ++i)
|
for (size_t i = 0; i < 3; ++i)
|
||||||
{
|
rad_rotation(i) = Geometry::deg2rad((transformation_type.absolute()) ? rotation(i) : rotation(i) - m_cache.rotation(i));
|
||||||
rad_rotation(i) = Geometry::deg2rad(delta_rotation(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas->get_selection().start_dragging();
|
canvas->get_selection().start_dragging();
|
||||||
canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance() || selection.requires_local_axes());
|
canvas->get_selection().rotate(rad_rotation, transformation_type);
|
||||||
canvas->do_rotate();
|
canvas->do_rotate();
|
||||||
|
|
||||||
m_cache.rotation = rotation;
|
m_cache.rotation = rotation;
|
||||||
|
@ -416,11 +416,14 @@ void Preview::load_print()
|
|||||||
load_print_as_sla();
|
load_print_as_sla();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preview::reload_print(bool force)
|
void Preview::reload_print(bool force, bool keep_volumes)
|
||||||
{
|
{
|
||||||
m_canvas->reset_volumes();
|
if (!keep_volumes)
|
||||||
m_canvas->reset_legend_texture();
|
{
|
||||||
m_loaded = false;
|
m_canvas->reset_volumes();
|
||||||
|
m_canvas->reset_legend_texture();
|
||||||
|
m_loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsShown() && !force)
|
if (!IsShown() && !force)
|
||||||
return;
|
return;
|
||||||
@ -644,7 +647,7 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool for
|
|||||||
|
|
||||||
bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF);
|
bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF);
|
||||||
if (color_print_enable) {
|
if (color_print_enable) {
|
||||||
const auto& cfg = wxGetApp().preset_bundle->full_config();
|
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
if (cfg.opt<ConfigOptionFloats>("nozzle_diameter")->values.size() > 1)
|
if (cfg.opt<ConfigOptionFloats>("nozzle_diameter")->values.size() > 1)
|
||||||
color_print_enable = false;
|
color_print_enable = false;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ public:
|
|||||||
void set_drop_target(wxDropTarget* target);
|
void set_drop_target(wxDropTarget* target);
|
||||||
|
|
||||||
void load_print();
|
void load_print();
|
||||||
void reload_print(bool force = false);
|
void reload_print(bool force = false, bool keep_volumes = false);
|
||||||
void refresh_print();
|
void refresh_print();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -2001,6 +2001,9 @@ void Plater::priv::schedule_background_process()
|
|||||||
this->background_process_timer.Start(500, wxTIMER_ONE_SHOT);
|
this->background_process_timer.Start(500, wxTIMER_ONE_SHOT);
|
||||||
// Notify the Canvas3D that something has changed, so it may invalidate some of the layer editing stuff.
|
// Notify the Canvas3D that something has changed, so it may invalidate some of the layer editing stuff.
|
||||||
this->view3D->get_canvas3d()->set_config(this->config);
|
this->view3D->get_canvas3d()->set_config(this->config);
|
||||||
|
// Reset gcode preview
|
||||||
|
this->preview->get_canvas3d()->reset_volumes();
|
||||||
|
this->preview->get_canvas3d()->reset_legend_texture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::update_print_volume_state()
|
void Plater::priv::update_print_volume_state()
|
||||||
@ -2265,7 +2268,8 @@ void Plater::priv::set_current_panel(wxPanel* panel)
|
|||||||
else if (current_panel == preview)
|
else if (current_panel == preview)
|
||||||
{
|
{
|
||||||
this->q->reslice();
|
this->q->reslice();
|
||||||
preview->reload_print();
|
// keeps current gcode preview, if any
|
||||||
|
preview->reload_print(false, true);
|
||||||
preview->set_canvas_as_dirty();
|
preview->set_canvas_as_dirty();
|
||||||
view_toolbar.select_item("Preview");
|
view_toolbar.select_item("Preview");
|
||||||
}
|
}
|
||||||
@ -2984,7 +2988,7 @@ void Plater::export_gcode()
|
|||||||
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
||||||
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
|
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
|
||||||
|
|
||||||
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save Zip file as:")),
|
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
|
||||||
start_dir,
|
start_dir,
|
||||||
from_path(default_output_file.filename()),
|
from_path(default_output_file.filename()),
|
||||||
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
|
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
|
||||||
|
@ -354,7 +354,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
|||||||
const std::vector<std::string>& Preset::print_options()
|
const std::vector<std::string>& Preset::print_options()
|
||||||
{
|
{
|
||||||
static std::vector<std::string> s_opts {
|
static std::vector<std::string> s_opts {
|
||||||
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "top_solid_layers", "bottom_solid_layers",
|
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "top_solid_layers", "bottom_solid_layers",
|
||||||
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
||||||
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
|
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
|
||||||
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
|
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
|
||||||
@ -460,6 +460,7 @@ const std::vector<std::string>& Preset::sla_print_options()
|
|||||||
"support_object_elevation",
|
"support_object_elevation",
|
||||||
"support_points_density_relative",
|
"support_points_density_relative",
|
||||||
"support_points_minimal_distance",
|
"support_points_minimal_distance",
|
||||||
|
"slice_closing_radius",
|
||||||
"pad_enable",
|
"pad_enable",
|
||||||
"pad_wall_thickness",
|
"pad_wall_thickness",
|
||||||
"pad_wall_height",
|
"pad_wall_height",
|
||||||
|
@ -157,7 +157,7 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent)
|
|||||||
btn_cancel->Disable();
|
btn_cancel->Disable();
|
||||||
btn_error = new wxButton(this, wxID_ANY, _(L("Show error message")));
|
btn_error = new wxButton(this, wxID_ANY, _(L("Show error message")));
|
||||||
btn_error->Disable();
|
btn_error->Disable();
|
||||||
auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close")));
|
auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||||
btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING);
|
btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING);
|
||||||
btnsizer->Add(btn_error, 0);
|
btnsizer->Add(btn_error, 0);
|
||||||
btnsizer->AddStretchSpacer();
|
btnsizer->AddStretchSpacer();
|
||||||
|
@ -1108,12 +1108,14 @@ void TabPrint::build()
|
|||||||
optgroup = page->new_optgroup(_(L("Flow")));
|
optgroup = page->new_optgroup(_(L("Flow")));
|
||||||
optgroup->append_single_option_line("bridge_flow_ratio");
|
optgroup->append_single_option_line("bridge_flow_ratio");
|
||||||
|
|
||||||
|
optgroup = page->new_optgroup(_(L("Slicing")));
|
||||||
|
optgroup->append_single_option_line("slice_closing_radius");
|
||||||
|
optgroup->append_single_option_line("resolution");
|
||||||
|
optgroup->append_single_option_line("xy_size_compensation");
|
||||||
|
optgroup->append_single_option_line("elefant_foot_compensation");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Other")));
|
optgroup = page->new_optgroup(_(L("Other")));
|
||||||
optgroup->append_single_option_line("clip_multipart_objects");
|
optgroup->append_single_option_line("clip_multipart_objects");
|
||||||
optgroup->append_single_option_line("elefant_foot_compensation");
|
|
||||||
optgroup->append_single_option_line("xy_size_compensation");
|
|
||||||
// # optgroup->append_single_option_line("threads");
|
|
||||||
optgroup->append_single_option_line("resolution");
|
|
||||||
|
|
||||||
page = add_options_page(_(L("Output options")), "page_white_go.png");
|
page = add_options_page(_(L("Output options")), "page_white_go.png");
|
||||||
optgroup = page->new_optgroup(_(L("Sequential printing")));
|
optgroup = page->new_optgroup(_(L("Sequential printing")));
|
||||||
@ -3292,6 +3294,10 @@ void TabSLAPrint::build()
|
|||||||
// optgroup->append_single_option_line("pad_edge_radius");
|
// optgroup->append_single_option_line("pad_edge_radius");
|
||||||
optgroup->append_single_option_line("pad_wall_slope");
|
optgroup->append_single_option_line("pad_wall_slope");
|
||||||
|
|
||||||
|
page = add_options_page(_(L("Advanced")), "wrench.png");
|
||||||
|
optgroup = page->new_optgroup(_(L("Slicing")));
|
||||||
|
optgroup->append_single_option_line("slice_closing_radius");
|
||||||
|
|
||||||
page = add_options_page(_(L("Output options")), "page_white_go.png");
|
page = add_options_page(_(L("Output options")), "page_white_go.png");
|
||||||
optgroup = page->new_optgroup(_(L("Output file")));
|
optgroup = page->new_optgroup(_(L("Output file")));
|
||||||
Option option = optgroup->get_option("output_filename_format");
|
Option option = optgroup->get_option("output_filename_format");
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# (the version numbers are generated by the build script from the git current label)
|
# (the version numbers are generated by the build script from the git current label)
|
||||||
|
|
||||||
set(SLIC3R_FORK_NAME "Slic3r Prusa Edition")
|
set(SLIC3R_FORK_NAME "Slic3r Prusa Edition")
|
||||||
set(SLIC3R_VERSION "1.42.0-alpha6")
|
set(SLIC3R_VERSION "1.42.0-alpha7")
|
||||||
set(SLIC3R_BUILD "${SLIC3R_VERSION}+UNKNOWN")
|
set(SLIC3R_BUILD "${SLIC3R_VERSION}+UNKNOWN")
|
||||||
set(SLIC3R_BUILD_ID "${SLIC3R_BUILD_ID}")
|
set(SLIC3R_BUILD_ID "${SLIC3R_BUILD_ID}")
|
||||||
set(SLIC3R_RC_VERSION "1,42,0,0")
|
set(SLIC3R_RC_VERSION "1,42,0,0")
|
||||||
|
@ -185,7 +185,7 @@ TriangleMesh::slice(z)
|
|||||||
|
|
||||||
std::vector<ExPolygons> layers;
|
std::vector<ExPolygons> layers;
|
||||||
TriangleMeshSlicer mslicer(THIS);
|
TriangleMeshSlicer mslicer(THIS);
|
||||||
mslicer.slice(z_f, &layers, [](){});
|
mslicer.slice(z_f, 0.049f, &layers, [](){});
|
||||||
|
|
||||||
AV* layers_av = newAV();
|
AV* layers_av = newAV();
|
||||||
size_t len = layers.size();
|
size_t len = layers.size();
|
||||||
|
Loading…
Reference in New Issue
Block a user