mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-10 07:15:08 -06:00
Merge branch 'master' of https://github.com/prusa3d/Slic3r into time_estimate
This commit is contained in:
commit
fa9014fc8e
72 changed files with 11533 additions and 4117 deletions
|
@ -27,6 +27,13 @@ if(WIN32)
|
|||
# BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
|
||||
add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB)
|
||||
# -D_ITERATOR_DEBUG_LEVEL)
|
||||
if(WIN10SDK_PATH)
|
||||
message("Building with Win10 Netfabb STL fixing service support")
|
||||
add_definitions(-DHAS_WIN10SDK)
|
||||
include_directories("${WIN10SDK_PATH}/Include")
|
||||
else()
|
||||
message("Building without Win10 Netfabb STL fixing service support")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO)
|
||||
|
@ -181,7 +188,15 @@ add_library(libslic3r_gui STATIC
|
|||
${LIBDIR}/slic3r/GUI/3DScene.cpp
|
||||
${LIBDIR}/slic3r/GUI/3DScene.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLShader.cpp
|
||||
${LIBDIR}/slic3r/GUI/GLShader.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLShader.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLCanvas3D.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLCanvas3D.cpp
|
||||
${LIBDIR}/slic3r/GUI/GLCanvas3DManager.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLCanvas3DManager.cpp
|
||||
${LIBDIR}/slic3r/GUI/GLGizmo.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLGizmo.cpp
|
||||
${LIBDIR}/slic3r/GUI/GLTexture.hpp
|
||||
${LIBDIR}/slic3r/GUI/GLTexture.cpp
|
||||
${LIBDIR}/slic3r/GUI/Preferences.cpp
|
||||
${LIBDIR}/slic3r/GUI/Preferences.hpp
|
||||
${LIBDIR}/slic3r/GUI/Preset.cpp
|
||||
|
@ -232,6 +247,8 @@ add_library(libslic3r_gui STATIC
|
|||
${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp
|
||||
${LIBDIR}/slic3r/Utils/Http.cpp
|
||||
${LIBDIR}/slic3r/Utils/Http.hpp
|
||||
${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp
|
||||
${LIBDIR}/slic3r/Utils/FixModelByWin10.hpp
|
||||
${LIBDIR}/slic3r/Utils/OctoPrint.cpp
|
||||
${LIBDIR}/slic3r/Utils/OctoPrint.hpp
|
||||
${LIBDIR}/slic3r/Utils/Bonjour.cpp
|
||||
|
@ -336,8 +353,6 @@ add_library(semver STATIC
|
|||
)
|
||||
|
||||
|
||||
add_subdirectory(src/avrdude)
|
||||
|
||||
# Generate the Slic3r Perl module (XS) typemap file.
|
||||
set(MyTypemap ${CMAKE_CURRENT_BINARY_DIR}/typemap)
|
||||
add_custom_command(
|
||||
|
@ -500,12 +515,12 @@ if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;")
|
|||
message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG")
|
||||
set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32")
|
||||
set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG /DWIN32")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG /DWIN32")
|
||||
set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32")
|
||||
set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32")
|
||||
endif()
|
||||
# The following line will add -fPIC on Linux to make the XS.so rellocable.
|
||||
add_definitions(${PerlEmbed_CCCDLFLAGS})
|
||||
|
@ -513,6 +528,8 @@ if (WIN32)
|
|||
target_link_libraries(XS ${PERL_LIBRARY})
|
||||
endif()
|
||||
|
||||
add_subdirectory(src/avrdude)
|
||||
|
||||
## REQUIRED packages
|
||||
|
||||
# Find and configure boost
|
||||
|
@ -557,13 +574,13 @@ if (SLIC3R_PRUSACONTROL)
|
|||
set(wxWidgets_UseAlienWx 1)
|
||||
if (wxWidgets_UseAlienWx)
|
||||
set(AlienWx_DEBUG 1)
|
||||
find_package(AlienWx REQUIRED COMPONENTS base core adv html)
|
||||
find_package(AlienWx REQUIRED COMPONENTS base core adv html gl)
|
||||
include_directories(${AlienWx_INCLUDE_DIRS})
|
||||
#add_compile_options(${AlienWx_CXX_FLAGS})
|
||||
add_definitions(${AlienWx_DEFINITIONS})
|
||||
set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES})
|
||||
else ()
|
||||
find_package(wxWidgets REQUIRED COMPONENTS base core adv html)
|
||||
find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl)
|
||||
include(${wxWidgets_USE_FILE})
|
||||
endif ()
|
||||
add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS)
|
||||
|
|
|
@ -12,6 +12,8 @@ our $VERSION = '0.01';
|
|||
BEGIN {
|
||||
if ($^O eq 'MSWin32') {
|
||||
eval "use Wx";
|
||||
eval "use Wx::GLCanvas";
|
||||
eval "use Wx::GLContext";
|
||||
eval "use Wx::Html";
|
||||
eval "use Wx::Print"; # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code)
|
||||
}
|
||||
|
@ -280,6 +282,7 @@ for my $class (qw(
|
|||
Slic3r::Geometry::BoundingBox
|
||||
Slic3r::Geometry::BoundingBoxf
|
||||
Slic3r::Geometry::BoundingBoxf3
|
||||
Slic3r::GUI::_3DScene::GLShader
|
||||
Slic3r::GUI::_3DScene::GLVolume
|
||||
Slic3r::GUI::Preset
|
||||
Slic3r::GUI::PresetCollection
|
||||
|
|
|
@ -80,6 +80,49 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
|||
return 3;
|
||||
}
|
||||
|
||||
static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||
{
|
||||
// Note: send/receive as in _the firmare_ send & receives
|
||||
const char entry_magic_send [] = "start\n";
|
||||
const char entry_magic_receive[] = "w25x20cl_enter\n";
|
||||
const char entry_magic_cfm [] = "w25x20cl_cfm\n";
|
||||
const size_t buffer_len = 32; // Should be large enough for the above messages
|
||||
|
||||
int res;
|
||||
size_t recv_size;
|
||||
char *buffer = alloca(buffer_len);
|
||||
|
||||
// 1. receive the "start" command
|
||||
recv_size = sizeof(entry_magic_send) - 1;
|
||||
res = serial_recv(&pgm->fd, buffer, recv_size);
|
||||
if (res < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
||||
return -1;
|
||||
} else if (strncmp(buffer, entry_magic_send, recv_size) != 0) {
|
||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 2. Send the external flash programmer enter command
|
||||
if (serial_send(&pgm->fd, entry_magic_receive, sizeof(entry_magic_receive) - 1) < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): Failed to send command to the printer\n",progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 3. Receive the entry confirmation command
|
||||
recv_size = sizeof(entry_magic_cfm) - 1;
|
||||
res = serial_recv(&pgm->fd, buffer, recv_size);
|
||||
if (res < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
|
||||
return -1;
|
||||
} else if (strncmp(buffer, entry_magic_cfm, recv_size) != 0) {
|
||||
avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arduino_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
union pinfo pinfo;
|
||||
|
@ -102,6 +145,12 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
|
|||
*/
|
||||
stk500_drain(pgm, 0);
|
||||
|
||||
// Initialization sequence for programming the external FLASH on the Prusa MK3
|
||||
if (prusa_init_external_flash(pgm) < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: arduino_open(): Failed to initialize MK3 external flash programming mode\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "avrdude-slic3r.hpp"
|
||||
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
|
||||
extern "C" {
|
||||
|
@ -33,17 +34,22 @@ static void avrdude_progress_handler_closure(const char *task, unsigned progress
|
|||
struct AvrDude::priv
|
||||
{
|
||||
std::string sys_config;
|
||||
std::vector<std::string> args;
|
||||
std::deque<std::vector<std::string>> args;
|
||||
size_t current_args_set = 0;
|
||||
RunFn run_fn;
|
||||
MessageFn message_fn;
|
||||
ProgressFn progress_fn;
|
||||
CompleteFn complete_fn;
|
||||
|
||||
std::thread avrdude_thread;
|
||||
|
||||
priv(std::string &&sys_config) : sys_config(sys_config) {}
|
||||
|
||||
int run_one(const std::vector<std::string> &args);
|
||||
int run();
|
||||
};
|
||||
|
||||
int AvrDude::priv::run() {
|
||||
int AvrDude::priv::run_one(const std::vector<std::string> &args) {
|
||||
std::vector<char*> c_args {{ const_cast<char*>(PACKAGE_NAME) }};
|
||||
for (const auto &arg : args) {
|
||||
c_args.push_back(const_cast<char*>(arg.data()));
|
||||
|
@ -68,10 +74,22 @@ int AvrDude::priv::run() {
|
|||
return res;
|
||||
}
|
||||
|
||||
int AvrDude::priv::run() {
|
||||
for (; args.size() > 0; current_args_set++) {
|
||||
int res = run_one(args.front());
|
||||
args.pop_front();
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
AvrDude::AvrDude() : p(new priv()) {}
|
||||
AvrDude::AvrDude(std::string sys_config) : p(new priv(std::move(sys_config))) {}
|
||||
|
||||
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}
|
||||
|
||||
|
@ -82,15 +100,15 @@ AvrDude::~AvrDude()
|
|||
}
|
||||
}
|
||||
|
||||
AvrDude& AvrDude::sys_config(std::string sys_config)
|
||||
AvrDude& AvrDude::push_args(std::vector<std::string> args)
|
||||
{
|
||||
if (p) { p->sys_config = std::move(sys_config); }
|
||||
if (p) { p->args.push_back(std::move(args)); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
AvrDude& AvrDude::args(std::vector<std::string> args)
|
||||
AvrDude& AvrDude::on_run(RunFn fn)
|
||||
{
|
||||
if (p) { p->args = std::move(args); }
|
||||
if (p) { p->run_fn = std::move(fn); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -123,11 +141,17 @@ AvrDude::Ptr AvrDude::run()
|
|||
|
||||
if (self->p) {
|
||||
auto avrdude_thread = std::thread([self]() {
|
||||
auto res = self->p->run();
|
||||
if (self->p->complete_fn) {
|
||||
self->p->complete_fn(res);
|
||||
}
|
||||
});
|
||||
if (self->p->run_fn) {
|
||||
self->p->run_fn();
|
||||
}
|
||||
|
||||
auto res = self->p->run();
|
||||
|
||||
if (self->p->complete_fn) {
|
||||
self->p->complete_fn(res, self->p->current_args_set);
|
||||
}
|
||||
});
|
||||
|
||||
self->p->avrdude_thread = std::move(avrdude_thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,22 +12,28 @@ class AvrDude
|
|||
{
|
||||
public:
|
||||
typedef std::shared_ptr<AvrDude> Ptr;
|
||||
typedef std::function<void()> RunFn;
|
||||
typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn;
|
||||
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
|
||||
typedef std::function<void(int /* exit status */)> CompleteFn;
|
||||
typedef std::function<void(int /* exit status */, size_t /* args_id */)> CompleteFn;
|
||||
|
||||
AvrDude();
|
||||
// Main c-tor, sys_config is the location of avrdude's main configuration file
|
||||
AvrDude(std::string sys_config);
|
||||
AvrDude(AvrDude &&);
|
||||
AvrDude(const AvrDude &) = delete;
|
||||
AvrDude &operator=(AvrDude &&) = delete;
|
||||
AvrDude &operator=(const AvrDude &) = delete;
|
||||
~AvrDude();
|
||||
|
||||
// Set location of avrdude's main configuration file
|
||||
AvrDude& sys_config(std::string sys_config);
|
||||
// Push a set of avrdude cli arguments
|
||||
// Each set makes one avrdude invocation - use this method multiple times to push
|
||||
// more than one avrdude invocations.
|
||||
AvrDude& push_args(std::vector<std::string> args);
|
||||
|
||||
// Set avrdude cli arguments
|
||||
AvrDude& args(std::vector<std::string> args);
|
||||
// Set a callback to be called just after run() before avrdude is ran
|
||||
// This can be used to perform any needed setup tasks from the background thread.
|
||||
// This has no effect when using run_sync().
|
||||
AvrDude& on_run(RunFn fn);
|
||||
|
||||
// Set message output callback
|
||||
AvrDude& on_message(MessageFn fn);
|
||||
|
@ -36,7 +42,10 @@ public:
|
|||
// Progress is reported per each task (reading / writing) in percents.
|
||||
AvrDude& on_progress(ProgressFn fn);
|
||||
|
||||
// Called when avrdude's main function finishes
|
||||
// Called when the last avrdude invocation finishes with the exit status of zero,
|
||||
// or earlier, if one of the invocations return a non-zero status.
|
||||
// The second argument contains the sequential id of the last avrdude invocation argument set.
|
||||
// This has no effect when using run_sync().
|
||||
AvrDude& on_complete(CompleteFn fn);
|
||||
|
||||
int run_sync();
|
||||
|
|
|
@ -378,7 +378,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
|
|||
char * optr;
|
||||
|
||||
if (m == NULL) {
|
||||
fprintf(f,
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s Block Poll Page Polled\n"
|
||||
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
|
@ -386,13 +386,13 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
|
|||
}
|
||||
else {
|
||||
if (verbose > 2) {
|
||||
fprintf(f,
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s Block Poll Page Polled\n"
|
||||
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
fprintf(f,
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s%-11s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
||||
prefix, m->desc, m->mode, m->delay, m->blocksize, m->pollindex,
|
||||
m->paged ? "yes" : "no",
|
||||
|
@ -415,7 +415,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
|
|||
optr = avr_op_str(i);
|
||||
else
|
||||
optr = " ";
|
||||
fprintf(f,
|
||||
avrdude_message(MSG_INFO,
|
||||
"%s %-11s %8d %8s %5d %5d\n",
|
||||
prefix, optr, j,
|
||||
bittype(m->op[i]->bit[j].type),
|
||||
|
@ -620,7 +620,7 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
|
|||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
|
||||
fprintf(f,
|
||||
avrdude_message(MSG_INFO,
|
||||
"%sAVR Part : %s\n"
|
||||
"%sChip Erase delay : %d us\n"
|
||||
"%sPAGEL : P%02X\n"
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */
|
||||
|
||||
#define MAX_MODE_LEN 32 // For fopen_and_seek()
|
||||
|
||||
|
||||
struct ihexrec {
|
||||
unsigned char reclen;
|
||||
|
@ -96,10 +98,42 @@ static int fileio_num(struct fioparms * fio,
|
|||
char * filename, FILE * f, AVRMEM * mem, int size,
|
||||
FILEFMT fmt);
|
||||
|
||||
static int fmt_autodetect(char * fname);
|
||||
static int fmt_autodetect(char * fname, size_t offset);
|
||||
|
||||
|
||||
|
||||
static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset)
|
||||
{
|
||||
FILE *file;
|
||||
// On Windows we need to convert the filename to UTF-16
|
||||
#if defined(WIN32NATIVE)
|
||||
static wchar_t fname_buffer[PATH_MAX];
|
||||
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_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
|
||||
|
||||
file = _wfopen(fname_buffer, mode_buffer);
|
||||
#else
|
||||
file = fopen(filename, mode);
|
||||
#endif
|
||||
|
||||
if (file != NULL) {
|
||||
// Some systems allow seeking past the end of file, so we need check for that first and disallow
|
||||
if (fseek(file, 0, SEEK_END) != 0
|
||||
|| offset >= ftell(file)
|
||||
|| fseek(file, offset, SEEK_SET) != 0
|
||||
) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
errno = EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
char * fmtstr(FILEFMT format)
|
||||
{
|
||||
switch (format) {
|
||||
|
@ -1358,7 +1392,7 @@ int fileio_setparms(int op, struct fioparms * fp,
|
|||
|
||||
|
||||
|
||||
static int fmt_autodetect(char * fname)
|
||||
static int fmt_autodetect(char * fname, size_t offset)
|
||||
{
|
||||
FILE * f;
|
||||
unsigned char buf[MAX_LINE_LEN];
|
||||
|
@ -1368,10 +1402,11 @@ static int fmt_autodetect(char * fname)
|
|||
int first = 1;
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
f = fopen(fname, "r");
|
||||
f = fopen_and_seek(fname, "r", offset);
|
||||
#else
|
||||
f = fopen(fname, "rb");
|
||||
f = fopen_and_seek(fname, "rb", offset);
|
||||
#endif
|
||||
|
||||
if (f == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: error opening %s: %s\n",
|
||||
progname, fname, strerror(errno));
|
||||
|
@ -1445,7 +1480,7 @@ static int fmt_autodetect(char * fname)
|
|||
|
||||
|
||||
int fileio(int op, char * filename, FILEFMT format,
|
||||
struct avrpart * p, char * memtype, int size)
|
||||
struct avrpart * p, char * memtype, int size, size_t offset)
|
||||
{
|
||||
int rc;
|
||||
FILE * f;
|
||||
|
@ -1477,15 +1512,17 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
using_stdio = 0;
|
||||
|
||||
if (strcmp(filename, "-")==0) {
|
||||
if (fio.op == FIO_READ) {
|
||||
fname = "<stdin>";
|
||||
f = stdin;
|
||||
}
|
||||
else {
|
||||
fname = "<stdout>";
|
||||
f = stdout;
|
||||
}
|
||||
using_stdio = 1;
|
||||
return -1;
|
||||
// Note: we don't want to read stdin or write to stdout as part of Slic3r
|
||||
// if (fio.op == FIO_READ) {
|
||||
// fname = "<stdin>";
|
||||
// f = stdin;
|
||||
// }
|
||||
// else {
|
||||
// fname = "<stdout>";
|
||||
// f = stdout;
|
||||
// }
|
||||
// using_stdio = 1;
|
||||
}
|
||||
else {
|
||||
fname = filename;
|
||||
|
@ -1502,7 +1539,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
return -1;
|
||||
}
|
||||
|
||||
format_detect = fmt_autodetect(fname);
|
||||
format_detect = fmt_autodetect(fname, offset);
|
||||
if (format_detect < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
|
||||
progname, fname);
|
||||
|
@ -1533,7 +1570,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
|
||||
if (format != FMT_IMM) {
|
||||
if (!using_stdio) {
|
||||
f = fopen(fname, fio.mode);
|
||||
f = fopen_and_seek(fname, fio.mode, offset);
|
||||
if (f == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
|
||||
progname, fio.iodesc, fname, strerror(errno));
|
||||
|
|
|
@ -737,7 +737,7 @@ extern bool cancel_flag;
|
|||
#define RETURN_IF_CANCEL() \
|
||||
do { \
|
||||
if (cancel_flag) { \
|
||||
avrdude_message(MSG_INFO, "%s(): Cancelled, exiting...\n", __func__); \
|
||||
avrdude_message(MSG_INFO, "avrdude: %s(): Cancelled, exiting...\n", __func__); \
|
||||
return -99; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -821,7 +821,7 @@ extern "C" {
|
|||
char * fmtstr(FILEFMT format);
|
||||
|
||||
int fileio(int op, char * filename, FILEFMT format,
|
||||
struct avrpart * p, char * memtype, int size);
|
||||
struct avrpart * p, char * memtype, int size, size_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -870,6 +870,7 @@ enum updateflags {
|
|||
typedef struct update_t {
|
||||
char * memtype;
|
||||
int op;
|
||||
size_t offset;
|
||||
char * filename;
|
||||
int format;
|
||||
} UPDATE;
|
||||
|
@ -881,7 +882,7 @@ extern "C" {
|
|||
extern UPDATE * parse_op(char * s);
|
||||
extern UPDATE * dup_update(UPDATE * upd);
|
||||
extern UPDATE * new_update(int op, char * memtype, int filefmt,
|
||||
char * filename);
|
||||
char * filename, size_t offset);
|
||||
extern void free_update(UPDATE * upd);
|
||||
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
||||
enum updateflags flags);
|
||||
|
|
|
@ -194,7 +194,7 @@ static void usage(void)
|
|||
" -F Override invalid signature check.\n"
|
||||
" -e Perform a chip erase.\n"
|
||||
" -O Perform RC oscillator calibration (see AVR053). \n"
|
||||
" -U <memtype>:r|w|v:<filename>[:format]\n"
|
||||
" -U <memtype>:r|w|v:<offset>:<filename>[:format]\n"
|
||||
" Memory operation specification.\n"
|
||||
" Multiple -U options are allowed, each request\n"
|
||||
" is performed in the order specified.\n"
|
||||
|
@ -374,7 +374,7 @@ static void list_parts(FILE * f, const char *prefix, LISTID avrparts)
|
|||
|
||||
static int cleanup_main(int status)
|
||||
{
|
||||
if (pgm_setup && pgm->teardown) {
|
||||
if (pgm_setup && pgm != NULL && pgm->teardown) {
|
||||
pgm->teardown(pgm);
|
||||
}
|
||||
|
||||
|
|
|
@ -376,6 +376,10 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
|||
FD_SET(fd->ifd, &rfds);
|
||||
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||
// FIXME: The timeout has different behaviour on Linux vs other Unices
|
||||
// On Linux, the timeout is modified by subtracting the time spent,
|
||||
// on OS X (for example), it is not modified.
|
||||
// POSIX recommends re-initializing it before selecting.
|
||||
if (nfds == 0) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
|
|
|
@ -716,11 +716,14 @@ static int stk500_loadaddr(PROGRAMMER * pgm, AVRMEM * mem, unsigned int addr)
|
|||
}
|
||||
|
||||
buf[0] = Cmnd_STK_LOAD_ADDRESS;
|
||||
buf[1] = addr & 0xff;
|
||||
buf[2] = (addr >> 8) & 0xff;
|
||||
buf[3] = Sync_CRC_EOP;
|
||||
|
||||
stk500_send(pgm, buf, 4);
|
||||
// Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
|
||||
// Send the binary data by nibbles to avoid transmitting the ';' character.
|
||||
buf[1] = addr & 0x0f;
|
||||
buf[2] = addr & 0xf0;
|
||||
buf[3] = (addr >> 8) & 0x0f;
|
||||
buf[4] = (addr >> 8) & 0xf0;
|
||||
buf[5] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 6);
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
|
@ -765,7 +768,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
int block_size;
|
||||
int tries;
|
||||
unsigned int n;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
unsigned int prusa3d_semicolon_workaround_round = 0;
|
||||
bool has_semicolon = false;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
memtype = 'F';
|
||||
|
@ -806,44 +811,64 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
tries++;
|
||||
stk500_loadaddr(pgm, m, addr/a_div);
|
||||
|
||||
/* build command block and avoid multiple send commands as it leads to a crash
|
||||
of the silabs usb serial driver on mac os x */
|
||||
i = 0;
|
||||
buf[i++] = Cmnd_STK_PROG_PAGE;
|
||||
buf[i++] = (block_size >> 8) & 0xff;
|
||||
buf[i++] = block_size & 0xff;
|
||||
buf[i++] = memtype;
|
||||
memcpy(&buf[i], &m->buf[addr], block_size);
|
||||
i += block_size;
|
||||
buf[i++] = Sync_CRC_EOP;
|
||||
stk500_send( pgm, buf, i);
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): can't get into sync\n",
|
||||
progname);
|
||||
return -3;
|
||||
for (i = 0; i < n_bytes; ++ i)
|
||||
if (m->buf[addr + i] == ';') {
|
||||
has_semicolon = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2 : 1); ++ prusa3d_semicolon_workaround_round) {
|
||||
/* build command block and avoid multiple send commands as it leads to a crash
|
||||
of the silabs usb serial driver on mac os x */
|
||||
i = 0;
|
||||
buf[i++] = Cmnd_STK_PROG_PAGE;
|
||||
// Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
|
||||
// Send the binary data by nibbles to avoid transmitting the ';' character.
|
||||
buf[i++] = (block_size >> 8) & 0xf0;
|
||||
buf[i++] = (block_size >> 8) & 0x0f;
|
||||
buf[i++] = block_size & 0xf0;
|
||||
buf[i++] = block_size & 0x0f;
|
||||
buf[i++] = memtype;
|
||||
if (has_semicolon) {
|
||||
for (j = 0; j < block_size; ++i, ++ j) {
|
||||
buf[i] = m->buf[addr + j];
|
||||
if (buf[i] == ';')
|
||||
buf[i] |= (prusa3d_semicolon_workaround_round ? 0xf0 : 0x0f);
|
||||
}
|
||||
} else {
|
||||
memcpy(&buf[i], &m->buf[addr], block_size);
|
||||
i += block_size;
|
||||
}
|
||||
buf[i++] = Sync_CRC_EOP;
|
||||
stk500_send( pgm, buf, i);
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): can't get into sync\n",
|
||||
progname);
|
||||
return -3;
|
||||
}
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, "
|
||||
"expect=0x%02x, resp=0x%02x\n",
|
||||
progname, Resp_STK_INSYNC, buf[0]);
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, "
|
||||
"expect=0x%02x, resp=0x%02x\n",
|
||||
progname, Resp_STK_INSYNC, buf[0]);
|
||||
return -5;
|
||||
}
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, "
|
||||
"expect=0x%02x, resp=0x%02x\n",
|
||||
progname, Resp_STK_INSYNC, buf[0]);
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, "
|
||||
"expect=0x%02x, resp=0x%02x\n",
|
||||
progname, Resp_STK_INSYNC, buf[0]);
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -893,11 +918,15 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
tries++;
|
||||
stk500_loadaddr(pgm, m, addr/a_div);
|
||||
buf[0] = Cmnd_STK_READ_PAGE;
|
||||
buf[1] = (block_size >> 8) & 0xff;
|
||||
buf[2] = block_size & 0xff;
|
||||
buf[3] = memtype;
|
||||
buf[4] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 5);
|
||||
// Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
|
||||
// Send the binary data by nibbles to avoid transmitting the ';' character.
|
||||
buf[1] = (block_size >> 8) & 0xf0;
|
||||
buf[2] = (block_size >> 8) & 0x0f;
|
||||
buf[3] = block_size & 0xf0;
|
||||
buf[4] = block_size & 0x0f;
|
||||
buf[5] = memtype;
|
||||
buf[6] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 7);
|
||||
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
return -1;
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
#define SERIAL_TIMEOUT 2
|
||||
|
||||
// Retry count
|
||||
#define RETRIES 5
|
||||
#define RETRIES 0
|
||||
|
||||
#if 0
|
||||
#define DEBUG(...) avrdude_message(MSG_INFO, __VA_ARGS__)
|
||||
|
@ -745,7 +745,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char *msg, size_t maxsize) {
|
|||
|
||||
|
||||
|
||||
static int stk500v2_getsync_internal(PROGRAMMER * pgm, int retries) {
|
||||
int stk500v2_getsync(PROGRAMMER * pgm) {
|
||||
int tries = 0;
|
||||
unsigned char buf[1], resp[32];
|
||||
int status;
|
||||
|
@ -804,7 +804,7 @@ retry:
|
|||
progname, pgmname[PDATA(pgm)->pgmtype]);
|
||||
return 0;
|
||||
} else {
|
||||
if (tries > retries) {
|
||||
if (tries > RETRIES) {
|
||||
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
|
||||
progname, resp[0]);
|
||||
return -6;
|
||||
|
@ -814,7 +814,7 @@ retry:
|
|||
|
||||
// or if we got a timeout
|
||||
} else if (status == -1) {
|
||||
if (tries > retries) {
|
||||
if (tries > RETRIES) {
|
||||
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): timeout communicating with programmer\n",
|
||||
progname);
|
||||
return -1;
|
||||
|
@ -823,7 +823,7 @@ retry:
|
|||
|
||||
// or any other error
|
||||
} else {
|
||||
if (tries > retries) {
|
||||
if (tries > RETRIES) {
|
||||
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
|
||||
progname,status);
|
||||
} else
|
||||
|
@ -833,11 +833,6 @@ retry:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int stk500v2_getsync(PROGRAMMER * pgm) {
|
||||
// This is to avoid applying RETRIES exponentially
|
||||
return stk500v2_getsync_internal(pgm, RETRIES);
|
||||
}
|
||||
|
||||
static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf,
|
||||
size_t len, size_t maxlen) {
|
||||
int i;
|
||||
|
@ -947,7 +942,7 @@ retry:
|
|||
}
|
||||
|
||||
// otherwise try to sync up again
|
||||
status = stk500v2_getsync_internal(pgm, 1);
|
||||
status = stk500v2_getsync(pgm);
|
||||
if (status != 0) {
|
||||
if (tries > RETRIES) {
|
||||
avrdude_message(MSG_INFO, "%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
|
||||
|
|
|
@ -101,6 +101,24 @@ UPDATE * parse_op(char * s)
|
|||
|
||||
p++;
|
||||
|
||||
// Extension: Parse file contents offset
|
||||
size_t offset = 0;
|
||||
|
||||
for (; *p != ':'; p++) {
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
offset *= 10;
|
||||
offset += *p - 0x30;
|
||||
} else {
|
||||
avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname);
|
||||
free(upd->memtype);
|
||||
free(upd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
upd->offset = offset;
|
||||
p++;
|
||||
|
||||
/*
|
||||
* Now, parse the filename component. Instead of looking for the
|
||||
* leftmost possible colon delimiter, we look for the rightmost one.
|
||||
|
@ -176,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd)
|
|||
return u;
|
||||
}
|
||||
|
||||
UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
|
||||
UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset)
|
||||
{
|
||||
UPDATE * u;
|
||||
|
||||
|
@ -190,6 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
|
|||
u->filename = strdup(filename);
|
||||
u->op = op;
|
||||
u->format = filefmt;
|
||||
u->offset = offset;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
@ -250,7 +269,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
progname,
|
||||
strcmp(upd->filename, "-")==0 ? "<stdout>" : upd->filename);
|
||||
}
|
||||
rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size);
|
||||
rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size, 0);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: write to file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
@ -267,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
progname,
|
||||
strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
|
||||
}
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
@ -296,11 +315,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
report_progress(1,1,NULL);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* test mode, don't actually write to the chip, output the buffer
|
||||
* to stdout in intel hex instead
|
||||
*/
|
||||
rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size);
|
||||
// /*
|
||||
// * test mode, don't actually write to the chip, output the buffer
|
||||
// * to stdout in intel hex instead
|
||||
// */
|
||||
// rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size, 0);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
|
@ -332,7 +351,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
progname, mem->desc, upd->filename);
|
||||
}
|
||||
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
|
|
@ -222,6 +222,14 @@ BoundingBox3Base<PointClass>::center() const
|
|||
}
|
||||
template Pointf3 BoundingBox3Base<Pointf3>::center() const;
|
||||
|
||||
template <class PointClass> coordf_t
|
||||
BoundingBox3Base<PointClass>::max_size() const
|
||||
{
|
||||
PointClass s = size();
|
||||
return std::max(s.x, std::max(s.y, s.z));
|
||||
}
|
||||
template coordf_t BoundingBox3Base<Pointf3>::max_size() const;
|
||||
|
||||
// Align a coordinate to a grid. The coordinate may be negative,
|
||||
// the aligned value will never be bigger than the original one.
|
||||
static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); }
|
||||
void offset(coordf_t delta);
|
||||
PointClass center() const;
|
||||
coordf_t max_size() const;
|
||||
|
||||
bool contains(const PointClass &point) const {
|
||||
return BoundingBoxBase<PointClass>::contains(point) && point.z >= this->min.z && point.z <= this->max.z;
|
||||
|
|
|
@ -1271,6 +1271,7 @@ namespace Slic3r {
|
|||
if ((std::abs(sx - sy) > 0.00001) || (std::abs(sx - sz) > 0.00001))
|
||||
return;
|
||||
|
||||
#if 0 // use quaternions
|
||||
// rotations (extracted using quaternion)
|
||||
double inv_sx = 1.0 / sx;
|
||||
double inv_sy = 1.0 / sy;
|
||||
|
@ -1331,6 +1332,25 @@ namespace Slic3r {
|
|||
if (angle_z < 0.0)
|
||||
angle_z += 2.0 * PI;
|
||||
}
|
||||
#else // use eigen library
|
||||
double inv_sx = 1.0 / sx;
|
||||
double inv_sy = 1.0 / sy;
|
||||
double inv_sz = 1.0 / sz;
|
||||
|
||||
Eigen::Matrix3d m3x3;
|
||||
m3x3 << (double)matrix(0, 0) * inv_sx, (double)matrix(0, 1) * inv_sy, (double)matrix(0, 2) * inv_sz,
|
||||
(double)matrix(1, 0) * inv_sx, (double)matrix(1, 1) * inv_sy, (double)matrix(1, 2) * inv_sz,
|
||||
(double)matrix(2, 0) * inv_sx, (double)matrix(2, 1) * inv_sy, (double)matrix(2, 2) * inv_sz;
|
||||
|
||||
Eigen::AngleAxisd rotation;
|
||||
rotation.fromRotationMatrix(m3x3);
|
||||
|
||||
// invalid rotation axis, we currently handle only rotations around Z axis
|
||||
if ((rotation.angle() != 0.0) && (rotation.axis() != Eigen::Vector3d::UnitZ()) && (rotation.axis() != -Eigen::Vector3d::UnitZ()))
|
||||
return;
|
||||
|
||||
double angle_z = (rotation.axis() == Eigen::Vector3d::UnitZ()) ? rotation.angle() : -rotation.angle();
|
||||
#endif
|
||||
|
||||
instance.offset.x = offset_x;
|
||||
instance.offset.y = offset_y;
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
//############################################################################################################################################
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
//############################################################################################################################################
|
||||
#include <miniz/miniz_zip.h>
|
||||
|
||||
#if 0
|
||||
|
@ -666,10 +669,21 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
|
|||
// If bundle is not a null pointer, updates it if the amf file/archive contains config data
|
||||
bool load_amf(const char *path, PresetBundle* bundle, Model *model)
|
||||
{
|
||||
if (boost::iends_with(path, ".zip.amf"))
|
||||
return load_amf_archive(path, bundle, model);
|
||||
else if (boost::iends_with(path, ".amf") || boost::iends_with(path, ".amf.xml"))
|
||||
if (boost::iends_with(path, ".amf.xml"))
|
||||
// backward compatibility with older slic3r output
|
||||
return load_amf_file(path, bundle, model);
|
||||
else if (boost::iends_with(path, ".amf"))
|
||||
{
|
||||
boost::nowide::ifstream file(path, boost::nowide::ifstream::binary);
|
||||
if (!file.good())
|
||||
return false;
|
||||
|
||||
std::string zip_mask(2, '\0');
|
||||
file.read(const_cast<char*>(zip_mask.data()), 2);
|
||||
file.close();
|
||||
|
||||
return (zip_mask == "PK") ? load_amf_archive(path, bundle, model) : load_amf_file(path, bundle, model);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -603,7 +603,10 @@ void ModelObject::clear_instances()
|
|||
|
||||
// Returns the bounding box of the transformed instances.
|
||||
// This bounding box is approximate and not snug.
|
||||
const BoundingBoxf3& ModelObject::bounding_box()
|
||||
//========================================================================================================
|
||||
const BoundingBoxf3& ModelObject::bounding_box() const
|
||||
//const BoundingBoxf3& ModelObject::bounding_box()
|
||||
//========================================================================================================
|
||||
{
|
||||
if (! m_bounding_box_valid) {
|
||||
BoundingBoxf3 raw_bbox;
|
||||
|
|
|
@ -103,7 +103,10 @@ public:
|
|||
// Returns the bounding box of the transformed instances.
|
||||
// This bounding box is approximate and not snug.
|
||||
// This bounding box is being cached.
|
||||
const BoundingBoxf3& bounding_box();
|
||||
//========================================================================================================
|
||||
const BoundingBoxf3& bounding_box() const;
|
||||
// const BoundingBoxf3& bounding_box();
|
||||
//========================================================================================================
|
||||
void invalidate_bounding_box() { m_bounding_box_valid = false; }
|
||||
// Returns a snug bounding box of the transformed instances.
|
||||
// This bounding box is not being cached.
|
||||
|
@ -145,8 +148,10 @@ private:
|
|||
// Parent object, owning this ModelObject.
|
||||
Model *m_model;
|
||||
// Bounding box, cached.
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
bool m_bounding_box_valid;
|
||||
//========================================================================================================
|
||||
mutable BoundingBoxf3 m_bounding_box;
|
||||
mutable bool m_bounding_box_valid;
|
||||
//========================================================================================================
|
||||
};
|
||||
|
||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||
|
|
|
@ -238,6 +238,11 @@ inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x * v2.x + v
|
|||
inline coordf_t dot(const Pointf &v) { return v.x * v.x + v.y * v.y; }
|
||||
inline double length(const Vectorf &v) { return sqrt(dot(v)); }
|
||||
inline double l2(const Vectorf &v) { return dot(v); }
|
||||
inline Vectorf normalize(const Vectorf& v)
|
||||
{
|
||||
coordf_t len = ::sqrt(sqr(v.x) + sqr(v.y));
|
||||
return (len != 0.0) ? 1.0 / len * v : Vectorf(0.0, 0.0);
|
||||
}
|
||||
|
||||
class Pointf3 : public Pointf
|
||||
{
|
||||
|
|
|
@ -103,7 +103,7 @@ double Polygon::area() const
|
|||
|
||||
double a = 0.;
|
||||
for (size_t i = 0, j = n - 1; i < n; ++i) {
|
||||
a += double(points[j].x + points[i].x) * double(points[i].y - points[j].y);
|
||||
a += ((double)points[j].x + (double)points[i].x) * ((double)points[i].y - (double)points[j].y);
|
||||
j = i;
|
||||
}
|
||||
return 0.5 * a;
|
||||
|
|
|
@ -184,6 +184,8 @@ public:
|
|||
|
||||
void reset_layer_height_profile();
|
||||
|
||||
void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action);
|
||||
|
||||
// Collect the slicing parameters, to be used by variable layer thickness algorithm,
|
||||
// by the interactive layer height editor and by the printing process itself.
|
||||
// The slicing parameters are dependent on various configuration values
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Geometry.hpp"
|
||||
#include "SupportMaterial.hpp"
|
||||
#include "Surface.hpp"
|
||||
#include "Slicing.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
@ -1961,4 +1962,12 @@ void PrintObject::reset_layer_height_profile()
|
|||
this->model_object()->layer_height_profile_valid = false;
|
||||
}
|
||||
|
||||
void PrintObject::adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
|
||||
{
|
||||
update_layer_height_profile(_model_object->layer_height_profile);
|
||||
Slic3r::adjust_layer_height_profile(slicing_parameters(), _model_object->layer_height_profile, z, layer_thickness_delta, band_width, LayerHeightEditActionType(action));
|
||||
_model_object->layer_height_profile_valid = true;
|
||||
layer_height_profile_valid = false;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -91,10 +91,13 @@ public:
|
|||
~PerlCallback() { this->deregister_callback(); }
|
||||
void register_callback(void *sv);
|
||||
void deregister_callback();
|
||||
void call();
|
||||
void call(int i);
|
||||
void call(int i, int j);
|
||||
// void call(const std::vector<int> &ints);
|
||||
void call() const;
|
||||
void call(int i) const;
|
||||
void call(int i, int j) const;
|
||||
void call(const std::vector<int>& ints) const;
|
||||
void call(double d) const;
|
||||
void call(double x, double y) const;
|
||||
void call(bool b) const;
|
||||
private:
|
||||
void *m_callback;
|
||||
};
|
||||
|
|
|
@ -184,7 +184,7 @@ void PerlCallback::deregister_callback()
|
|||
}
|
||||
}
|
||||
|
||||
void PerlCallback::call()
|
||||
void PerlCallback::call() const
|
||||
{
|
||||
if (! m_callback)
|
||||
return;
|
||||
|
@ -198,7 +198,7 @@ void PerlCallback::call()
|
|||
LEAVE;
|
||||
}
|
||||
|
||||
void PerlCallback::call(int i)
|
||||
void PerlCallback::call(int i) const
|
||||
{
|
||||
if (! m_callback)
|
||||
return;
|
||||
|
@ -213,7 +213,7 @@ void PerlCallback::call(int i)
|
|||
LEAVE;
|
||||
}
|
||||
|
||||
void PerlCallback::call(int i, int j)
|
||||
void PerlCallback::call(int i, int j) const
|
||||
{
|
||||
if (! m_callback)
|
||||
return;
|
||||
|
@ -229,8 +229,7 @@ void PerlCallback::call(int i, int j)
|
|||
LEAVE;
|
||||
}
|
||||
|
||||
/*
|
||||
void PerlCallback::call(const std::vector<int> &ints)
|
||||
void PerlCallback::call(const std::vector<int>& ints) const
|
||||
{
|
||||
if (! m_callback)
|
||||
return;
|
||||
|
@ -238,16 +237,51 @@ void PerlCallback::call(const std::vector<int> &ints)
|
|||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
AV* av = newAV();
|
||||
for (int i : ints)
|
||||
av_push(av, newSViv(i));
|
||||
XPUSHs(av);
|
||||
{
|
||||
XPUSHs(sv_2mortal(newSViv(i)));
|
||||
}
|
||||
PUTBACK;
|
||||
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
}
|
||||
*/
|
||||
|
||||
void PerlCallback::call(double d) const
|
||||
{
|
||||
if (!m_callback)
|
||||
return;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(sv_2mortal(newSVnv(d)));
|
||||
PUTBACK;
|
||||
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
void PerlCallback::call(double x, double y) const
|
||||
{
|
||||
if (!m_callback)
|
||||
return;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(sv_2mortal(newSVnv(x)));
|
||||
XPUSHs(sv_2mortal(newSVnv(y)));
|
||||
PUTBACK;
|
||||
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
void PerlCallback::call(bool b) const
|
||||
{
|
||||
call(b ? 1 : 0);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef NOMINMAX
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,8 +6,10 @@
|
|||
#include "../../libslic3r/Line.hpp"
|
||||
#include "../../libslic3r/TriangleMesh.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
||||
|
||||
class wxBitmap;
|
||||
class wxWindow;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -17,6 +19,11 @@ class Model;
|
|||
class ModelObject;
|
||||
class GCodePreviewData;
|
||||
class DynamicPrintConfig;
|
||||
class ExtrusionPath;
|
||||
class ExtrusionMultiPath;
|
||||
class ExtrusionLoop;
|
||||
class ExtrusionEntity;
|
||||
class ExtrusionEntityCollection;
|
||||
|
||||
// A container for interleaved arrays of 3D vertices and normals,
|
||||
// possibly indexed by triangles and / or quads.
|
||||
|
@ -305,9 +312,9 @@ public:
|
|||
// Boolean: Is mouse over this object?
|
||||
bool hover;
|
||||
// Wheter or not this volume has been generated from a modifier
|
||||
bool is_modifier;
|
||||
bool is_modifier;
|
||||
// Wheter or not this volume has been generated from the wipe tower
|
||||
bool is_wipe_tower;
|
||||
bool is_wipe_tower;
|
||||
|
||||
// Interleaved triangles & normals with indexed triangles & quads.
|
||||
GLIndexedVertexArray indexed_vertex_array;
|
||||
|
@ -437,35 +444,6 @@ private:
|
|||
|
||||
class _3DScene
|
||||
{
|
||||
struct GCodePreviewVolumeIndex
|
||||
{
|
||||
enum EType
|
||||
{
|
||||
Extrusion,
|
||||
Travel,
|
||||
Retraction,
|
||||
Unretraction,
|
||||
Shell,
|
||||
Num_Geometry_Types
|
||||
};
|
||||
|
||||
struct FirstVolume
|
||||
{
|
||||
EType type;
|
||||
unsigned int flag;
|
||||
// Index of the first volume in a GLVolumeCollection.
|
||||
unsigned int id;
|
||||
|
||||
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
|
||||
};
|
||||
|
||||
std::vector<FirstVolume> first_volumes;
|
||||
|
||||
void reset() { first_volumes.clear(); }
|
||||
};
|
||||
|
||||
static GCodePreviewVolumeIndex s_gcode_preview_volume_index;
|
||||
|
||||
class TextureBase
|
||||
{
|
||||
protected:
|
||||
|
@ -525,12 +503,106 @@ class _3DScene
|
|||
|
||||
static LegendTexture s_legend_texture;
|
||||
static WarningTexture s_warning_texture;
|
||||
static GUI::GLCanvas3DManager s_canvas_mgr;
|
||||
|
||||
public:
|
||||
static void _glew_init();
|
||||
static void init_gl();
|
||||
static std::string get_gl_info(bool format_as_html, bool extensions);
|
||||
static bool use_VBOs();
|
||||
|
||||
static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs);
|
||||
static bool add_canvas(wxGLCanvas* canvas);
|
||||
static bool remove_canvas(wxGLCanvas* canvas);
|
||||
static void remove_all_canvases();
|
||||
|
||||
static bool init(wxGLCanvas* canvas);
|
||||
|
||||
static void set_active(wxGLCanvas* canvas, bool active);
|
||||
|
||||
static unsigned int get_volumes_count(wxGLCanvas* canvas);
|
||||
static void reset_volumes(wxGLCanvas* canvas);
|
||||
static void deselect_volumes(wxGLCanvas* canvas);
|
||||
static void select_volume(wxGLCanvas* canvas, unsigned int id);
|
||||
static void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
static bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config);
|
||||
static bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
|
||||
static bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
|
||||
|
||||
static void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
|
||||
static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config);
|
||||
static void set_print(wxGLCanvas* canvas, Print* print);
|
||||
static void set_model(wxGLCanvas* canvas, Model* model);
|
||||
|
||||
static void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
|
||||
static void set_auto_bed_shape(wxGLCanvas* canvas);
|
||||
|
||||
static BoundingBoxf3 get_volumes_bounding_box(wxGLCanvas* canvas);
|
||||
|
||||
static void set_axes_length(wxGLCanvas* canvas, float length);
|
||||
|
||||
static void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
|
||||
|
||||
static void set_color_by(wxGLCanvas* canvas, const std::string& value);
|
||||
static void set_select_by(wxGLCanvas* canvas, const std::string& value);
|
||||
static void set_drag_by(wxGLCanvas* canvas, const std::string& value);
|
||||
|
||||
static bool is_layers_editing_enabled(wxGLCanvas* canvas);
|
||||
static bool is_layers_editing_allowed(wxGLCanvas* canvas);
|
||||
static bool is_shader_enabled(wxGLCanvas* canvas);
|
||||
|
||||
static bool is_reload_delayed(wxGLCanvas* canvas);
|
||||
|
||||
static void enable_layers_editing(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_warning_texture(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_legend_texture(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_picking(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_moving(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_gizmos(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_shader(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
|
||||
static void allow_multisample(wxGLCanvas* canvas, bool allow);
|
||||
|
||||
static void zoom_to_bed(wxGLCanvas* canvas);
|
||||
static void zoom_to_volumes(wxGLCanvas* canvas);
|
||||
static void select_view(wxGLCanvas* canvas, const std::string& direction);
|
||||
static void set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other);
|
||||
|
||||
static void update_volumes_colors_by_extruder(wxGLCanvas* canvas);
|
||||
|
||||
static void render(wxGLCanvas* canvas);
|
||||
|
||||
static std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only);
|
||||
static void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
|
||||
|
||||
static void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_select_object_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
static std::vector<int> load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs);
|
||||
static std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
|
||||
|
||||
static void reload_scene(wxGLCanvas* canvas, bool force);
|
||||
|
||||
static void load_print_toolpaths(wxGLCanvas* canvas);
|
||||
static void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
// generates the legend texture in dependence of the current shown view type
|
||||
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
static unsigned int get_legend_texture_width();
|
||||
static unsigned int get_legend_texture_height();
|
||||
|
||||
|
@ -545,42 +617,16 @@ public:
|
|||
static void reset_warning_texture();
|
||||
static unsigned int finalize_warning_texture();
|
||||
|
||||
static void _load_print_toolpaths(
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors,
|
||||
bool use_VBOs);
|
||||
|
||||
static void _load_print_object_toolpaths(
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors,
|
||||
bool use_VBOs);
|
||||
|
||||
static void _load_wipe_tower_toolpaths(
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors_str,
|
||||
bool use_VBOs);
|
||||
|
||||
private:
|
||||
// generates gcode extrusion paths geometry
|
||||
static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
|
||||
// generates gcode travel paths geometry
|
||||
static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
|
||||
static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
|
||||
static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
|
||||
static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors);
|
||||
// generates gcode retractions geometry
|
||||
static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
|
||||
// generates gcode unretractions geometry
|
||||
static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
|
||||
// sets gcode geometry visibility according to user selection
|
||||
static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
|
||||
// generates the legend texture in dependence of the current shown view type
|
||||
static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
// generates objects and wipe tower geometry
|
||||
static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
|
||||
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
||||
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GLVolume& volume);
|
||||
static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume);
|
||||
static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -113,6 +113,11 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
|
|||
sizer->Add(all_none_sizer, 0, wxEXPAND);
|
||||
|
||||
SetSizer(sizer);
|
||||
|
||||
if (cboxes.size() > 0) {
|
||||
cboxes[0]->SetValue(true);
|
||||
on_checkbox(cboxes[0], true);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinterPicker::select_all(bool select)
|
||||
|
@ -598,10 +603,10 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
|
|||
|
||||
static const std::unordered_map<std::string, std::pair<std::string, std::string>> legacy_preset_map {{
|
||||
{ "Original Prusa i3 MK2.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode.ini", std::make_pair("MK2SMM", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini", std::make_pair("MK2SMM", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial.ini", std::make_pair("MK2SMM", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini", std::make_pair("MK2SMM", "0.6") },
|
||||
{ "Original Prusa i3 MK2 0.25 nozzle.ini", std::make_pair("MK2S", "0.25") },
|
||||
{ "Original Prusa i3 MK2 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK3.ini", std::make_pair("MK3", "0.4") },
|
||||
|
@ -809,8 +814,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
|
|||
topsizer->AddSpacer(INDEX_MARGIN);
|
||||
topsizer->Add(p->hscroll, 1, wxEXPAND);
|
||||
|
||||
p->btn_prev = new wxButton(this, wxID_BACKWARD);
|
||||
p->btn_next = new wxButton(this, wxID_FORWARD);
|
||||
p->btn_prev = new wxButton(this, wxID_NONE, _(L("< &Back")));
|
||||
p->btn_next = new wxButton(this, wxID_NONE, _(L("&Next >")));
|
||||
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
|
||||
p->btn_cancel = new wxButton(this, wxID_CANCEL);
|
||||
p->btnsizer->AddStretchSpacer();
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
#include <algorithm>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/filepicker.h>
|
||||
|
@ -36,7 +38,7 @@ namespace Slic3r {
|
|||
enum AvrdudeEvent
|
||||
{
|
||||
AE_MESSAGE,
|
||||
AE_PRORGESS,
|
||||
AE_PROGRESS,
|
||||
AE_EXIT,
|
||||
};
|
||||
|
||||
|
@ -62,7 +64,6 @@ struct FirmwareDialog::priv
|
|||
std::vector<Utils::SerialPortInfo> ports;
|
||||
wxFilePickerCtrl *hex_picker;
|
||||
wxStaticText *txt_status;
|
||||
wxStaticText *txt_progress;
|
||||
wxGauge *progressbar;
|
||||
wxCollapsiblePane *spoiler;
|
||||
wxTextCtrl *txt_stdout;
|
||||
|
@ -72,6 +73,8 @@ struct FirmwareDialog::priv
|
|||
wxString btn_flash_label_ready;
|
||||
wxString btn_flash_label_flashing;
|
||||
|
||||
wxTimer timer_pulse;
|
||||
|
||||
// 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).
|
||||
AvrDude::Ptr avrdude;
|
||||
|
@ -83,13 +86,16 @@ struct FirmwareDialog::priv
|
|||
q(q),
|
||||
btn_flash_label_ready(_(L("Flash!"))),
|
||||
btn_flash_label_flashing(_(L("Cancel"))),
|
||||
timer_pulse(q),
|
||||
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
|
||||
progress_tasks_done(0),
|
||||
cancelled(false)
|
||||
{}
|
||||
|
||||
void find_serial_ports();
|
||||
void flashing_status(bool flashing, AvrDudeComplete complete = AC_NONE);
|
||||
void flashing_start(bool flashing_l10n);
|
||||
void flashing_done(AvrDudeComplete complete);
|
||||
size_t hex_lang_offset(const wxString &path);
|
||||
void perform_upload();
|
||||
void cancel();
|
||||
void on_avrdude(const wxCommandEvent &evt);
|
||||
|
@ -116,42 +122,76 @@ void FirmwareDialog::priv::find_serial_ports()
|
|||
}
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::flashing_status(bool value, AvrDudeComplete complete)
|
||||
void FirmwareDialog::priv::flashing_start(bool flashing_l10n)
|
||||
{
|
||||
if (value) {
|
||||
txt_stdout->Clear();
|
||||
txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
txt_status->SetForegroundColour(GUI::get_label_clr_modified());
|
||||
port_picker->Disable();
|
||||
btn_rescan->Disable();
|
||||
hex_picker->Disable();
|
||||
btn_close->Disable();
|
||||
btn_flash->SetLabel(btn_flash_label_flashing);
|
||||
progressbar->SetRange(200); // See progress callback below
|
||||
progressbar->SetValue(0);
|
||||
progress_tasks_done = 0;
|
||||
cancelled = false;
|
||||
} else {
|
||||
auto text_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
port_picker->Enable();
|
||||
btn_rescan->Enable();
|
||||
hex_picker->Enable();
|
||||
btn_close->Enable();
|
||||
btn_flash->SetLabel(btn_flash_label_ready);
|
||||
txt_status->SetForegroundColour(text_color);
|
||||
progressbar->SetValue(200);
|
||||
txt_stdout->Clear();
|
||||
txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
txt_status->SetForegroundColour(GUI::get_label_clr_modified());
|
||||
port_picker->Disable();
|
||||
btn_rescan->Disable();
|
||||
hex_picker->Disable();
|
||||
btn_close->Disable();
|
||||
btn_flash->SetLabel(btn_flash_label_flashing);
|
||||
progressbar->SetRange(flashing_l10n ? 500 : 200); // See progress callback below
|
||||
progressbar->SetValue(0);
|
||||
progress_tasks_done = 0;
|
||||
cancelled = false;
|
||||
timer_pulse.Start(50);
|
||||
}
|
||||
|
||||
switch (complete) {
|
||||
case AC_SUCCESS: txt_status->SetLabel(_(L("Flashing succeeded!"))); break;
|
||||
case AC_FAILURE: txt_status->SetLabel(_(L("Flashing failed. Please see the avrdude log below."))); break;
|
||||
case AC_CANCEL: txt_status->SetLabel(_(L("Flashing cancelled."))); break;
|
||||
void FirmwareDialog::priv::flashing_done(AvrDudeComplete complete)
|
||||
{
|
||||
auto text_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
port_picker->Enable();
|
||||
btn_rescan->Enable();
|
||||
hex_picker->Enable();
|
||||
btn_close->Enable();
|
||||
btn_flash->SetLabel(btn_flash_label_ready);
|
||||
txt_status->SetForegroundColour(text_color);
|
||||
timer_pulse.Stop();
|
||||
progressbar->SetValue(progressbar->GetRange());
|
||||
|
||||
switch (complete) {
|
||||
case AC_SUCCESS: txt_status->SetLabel(_(L("Flashing succeeded!"))); break;
|
||||
case AC_FAILURE: txt_status->SetLabel(_(L("Flashing failed. Please see the avrdude log below."))); break;
|
||||
case AC_CANCEL: txt_status->SetLabel(_(L("Flashing cancelled."))); break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path)
|
||||
{
|
||||
fs::ifstream file(fs::path(path.wx_str()));
|
||||
if (! file.good()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *hex_terminator = ":00000001FF\r";
|
||||
size_t res = 0;
|
||||
std::string line;
|
||||
while (getline(file, line, '\n').good()) {
|
||||
// Account for LF vs CRLF
|
||||
if (!line.empty() && line.back() != '\r') {
|
||||
line.push_back('\r');
|
||||
}
|
||||
|
||||
if (line == hex_terminator) {
|
||||
if (res == 0) {
|
||||
// This is the first terminator seen, save the position
|
||||
res = file.tellg();
|
||||
} else {
|
||||
// We've found another terminator, return the offset just after the first one
|
||||
// which is the start of the second 'section'.
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::perform_upload()
|
||||
{
|
||||
auto filename = hex_picker->GetPath();
|
||||
auto filename = hex_picker->GetPath();
|
||||
std::string port = port_picker->GetValue().ToStdString();
|
||||
int selection = port_picker->GetSelection();
|
||||
if (selection != -1) {
|
||||
|
@ -161,16 +201,32 @@ void FirmwareDialog::priv::perform_upload()
|
|||
}
|
||||
if (filename.IsEmpty() || port.empty()) { return; }
|
||||
|
||||
flashing_status(true);
|
||||
const bool extra_verbose = false; // For debugging
|
||||
const auto lang_offset = hex_lang_offset(filename);
|
||||
const auto filename_utf8 = filename.utf8_str();
|
||||
|
||||
flashing_start(lang_offset > 0);
|
||||
|
||||
// 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.
|
||||
auto q = this->q;
|
||||
|
||||
// Init the avrdude object
|
||||
AvrDude avrdude(avrdude_config);
|
||||
|
||||
// Build argument list(s)
|
||||
std::vector<std::string> args {{
|
||||
"-v",
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Wiring" mode to program Rambo or Einsy, using the STK500v2 protocol (not the STK500).
|
||||
// The Prusa's avrdude is patched to never send semicolons inside the data packets, as the USB to serial chip
|
||||
// is flashed with a buggy firmware.
|
||||
"-c", "wiring",
|
||||
"-P", port,
|
||||
"-b", "115200", // XXX: is this ok to hardcode?
|
||||
"-b", "115200", // TODO: Allow other rates? Ditto below.
|
||||
"-D",
|
||||
"-U", (boost::format("flash:w:%1%:i") % filename.ToStdString()).str()
|
||||
// XXX: Safe mode?
|
||||
"-U", (boost::format("flash:w:0:%1%:i") % filename_utf8.data()).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
|
||||
|
@ -178,26 +234,51 @@ void FirmwareDialog::priv::perform_upload()
|
|||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
// 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.
|
||||
auto q = this->q;
|
||||
avrdude.push_args(std::move(args));
|
||||
|
||||
if (lang_offset > 0) {
|
||||
// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
|
||||
// This is done via another avrdude invocation, here we build arg list for that:
|
||||
std::vector<std::string> args_l10n {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
|
||||
// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
|
||||
"-c", "arduino",
|
||||
"-P", port,
|
||||
"-b", "115200",
|
||||
"-D",
|
||||
"-u", // disable safe mode
|
||||
"-U", (boost::format("flash:w:%1%:%2%:i") % lang_offset % filename_utf8.data()).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
|
||||
<< std::accumulate(std::next(args_l10n.begin()), args_l10n.end(), args_l10n[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
avrdude.push_args(std::move(args_l10n));
|
||||
}
|
||||
|
||||
this->avrdude = avrdude
|
||||
.on_message(std::move([q, extra_verbose](const char *msg, unsigned /* size */) {
|
||||
if (extra_verbose) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "avrdude: " << msg;
|
||||
}
|
||||
|
||||
avrdude = AvrDude()
|
||||
.sys_config(avrdude_config)
|
||||
.args(args)
|
||||
.on_message(std::move([q](const char *msg, unsigned /* size */) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
auto wxmsg = wxString::FromUTF8(msg);
|
||||
evt->SetExtraLong(AE_MESSAGE);
|
||||
evt->SetString(msg);
|
||||
evt->SetString(std::move(wxmsg));
|
||||
wxQueueEvent(q, evt);
|
||||
}))
|
||||
.on_progress(std::move([q](const char * /* task */, unsigned progress) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
evt->SetExtraLong(AE_PRORGESS);
|
||||
evt->SetExtraLong(AE_PROGRESS);
|
||||
evt->SetInt(progress);
|
||||
wxQueueEvent(q, evt);
|
||||
}))
|
||||
.on_complete(std::move([q](int status) {
|
||||
.on_complete(std::move([q](int status, size_t /* args_id */) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
evt->SetExtraLong(AE_EXIT);
|
||||
evt->SetInt(status);
|
||||
|
@ -224,19 +305,19 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
txt_stdout->AppendText(evt.GetString());
|
||||
break;
|
||||
|
||||
case AE_PRORGESS:
|
||||
case AE_PROGRESS:
|
||||
// We try to track overall progress here.
|
||||
// When uploading the firmware, avrdude first reads a littlebit of status data,
|
||||
// then performs write, then reading (verification).
|
||||
// We Pulse() during the first read and combine progress of the latter two tasks.
|
||||
// Avrdude performs 3 tasks per one memory operation ("-U" arg),
|
||||
// first of which is reading of status data (very short).
|
||||
// We use the timer_pulse during the very first task to indicate intialization
|
||||
// and then display overall progress during the latter tasks.
|
||||
|
||||
if (progress_tasks_done == 0) {
|
||||
progressbar->Pulse();
|
||||
} else {
|
||||
if (progress_tasks_done > 0) {
|
||||
progressbar->SetValue(progress_tasks_done - 100 + evt.GetInt());
|
||||
}
|
||||
|
||||
if (evt.GetInt() == 100) {
|
||||
timer_pulse.Stop();
|
||||
progress_tasks_done += 100;
|
||||
}
|
||||
|
||||
|
@ -246,7 +327,7 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
BOOST_LOG_TRIVIAL(info) << "avrdude exit code: " << evt.GetInt();
|
||||
|
||||
complete_kind = cancelled ? AC_CANCEL : (evt.GetInt() == 0 ? AC_SUCCESS : AC_FAILURE);
|
||||
flashing_status(false, complete_kind);
|
||||
flashing_done(complete_kind);
|
||||
|
||||
// Make sure the background thread is collected and the AvrDude object reset
|
||||
if (avrdude) { avrdude->join(); }
|
||||
|
@ -374,6 +455,8 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
|||
}
|
||||
});
|
||||
|
||||
Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->p->progressbar->Pulse(); });
|
||||
|
||||
Bind(EVT_AVRDUDE, [this](wxCommandEvent &evt) { this->p->on_avrdude(evt); });
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &evt) {
|
||||
|
|
4308
xs/src/slic3r/GUI/GLCanvas3D.cpp
Normal file
4308
xs/src/slic3r/GUI/GLCanvas3D.cpp
Normal file
File diff suppressed because it is too large
Load diff
639
xs/src/slic3r/GUI/GLCanvas3D.hpp
Normal file
639
xs/src/slic3r/GUI/GLCanvas3D.hpp
Normal file
|
@ -0,0 +1,639 @@
|
|||
#ifndef slic3r_GLCanvas3D_hpp_
|
||||
#define slic3r_GLCanvas3D_hpp_
|
||||
|
||||
#include "../../slic3r/GUI/3DScene.hpp"
|
||||
#include "../../slic3r/GUI/GLTexture.hpp"
|
||||
|
||||
class wxTimer;
|
||||
class wxSizeEvent;
|
||||
class wxIdleEvent;
|
||||
class wxKeyEvent;
|
||||
class wxMouseEvent;
|
||||
class wxTimerEvent;
|
||||
class wxPaintEvent;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class GLShader;
|
||||
class ExPolygon;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class GLGizmoBase;
|
||||
|
||||
class GeometryBuffer
|
||||
{
|
||||
std::vector<float> m_vertices;
|
||||
std::vector<float> m_tex_coords;
|
||||
|
||||
public:
|
||||
bool set_from_triangles(const Polygons& triangles, float z, bool generate_tex_coords);
|
||||
bool set_from_lines(const Lines& lines, float z);
|
||||
|
||||
const float* get_vertices() const;
|
||||
const float* get_tex_coords() const;
|
||||
|
||||
unsigned int get_vertices_count() const;
|
||||
};
|
||||
|
||||
class Size
|
||||
{
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
public:
|
||||
Size();
|
||||
Size(int width, int height);
|
||||
|
||||
int get_width() const;
|
||||
void set_width(int width);
|
||||
|
||||
int get_height() const;
|
||||
void set_height(int height);
|
||||
};
|
||||
|
||||
class Rect
|
||||
{
|
||||
float m_left;
|
||||
float m_top;
|
||||
float m_right;
|
||||
float m_bottom;
|
||||
|
||||
public:
|
||||
Rect();
|
||||
Rect(float left, float top, float right, float bottom);
|
||||
|
||||
float get_left() const;
|
||||
void set_left(float left);
|
||||
|
||||
float get_top() const;
|
||||
void set_top(float top);
|
||||
|
||||
float get_right() const;
|
||||
void set_right(float right);
|
||||
|
||||
float get_bottom() const;
|
||||
void set_bottom(float bottom);
|
||||
};
|
||||
|
||||
class GLCanvas3D
|
||||
{
|
||||
struct GCodePreviewVolumeIndex
|
||||
{
|
||||
enum EType
|
||||
{
|
||||
Extrusion,
|
||||
Travel,
|
||||
Retraction,
|
||||
Unretraction,
|
||||
Shell,
|
||||
Num_Geometry_Types
|
||||
};
|
||||
|
||||
struct FirstVolume
|
||||
{
|
||||
EType type;
|
||||
unsigned int flag;
|
||||
// Index of the first volume in a GLVolumeCollection.
|
||||
unsigned int id;
|
||||
|
||||
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
|
||||
};
|
||||
|
||||
std::vector<FirstVolume> first_volumes;
|
||||
|
||||
void reset() { first_volumes.clear(); }
|
||||
};
|
||||
|
||||
public:
|
||||
struct Camera
|
||||
{
|
||||
enum EType : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
// Perspective,
|
||||
Ortho,
|
||||
Num_types
|
||||
};
|
||||
|
||||
EType type;
|
||||
float zoom;
|
||||
float phi;
|
||||
// float distance;
|
||||
Pointf3 target;
|
||||
|
||||
private:
|
||||
float m_theta;
|
||||
|
||||
public:
|
||||
Camera();
|
||||
|
||||
std::string get_type_as_string() const;
|
||||
|
||||
float get_theta() const;
|
||||
void set_theta(float theta);
|
||||
};
|
||||
|
||||
class Bed
|
||||
{
|
||||
public:
|
||||
enum EType : unsigned char
|
||||
{
|
||||
MK2,
|
||||
MK3,
|
||||
Custom,
|
||||
Num_Types
|
||||
};
|
||||
|
||||
private:
|
||||
EType m_type;
|
||||
Pointfs m_shape;
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
Polygon m_polygon;
|
||||
GeometryBuffer m_triangles;
|
||||
GeometryBuffer m_gridlines;
|
||||
mutable GLTexture m_top_texture;
|
||||
mutable GLTexture m_bottom_texture;
|
||||
|
||||
public:
|
||||
Bed();
|
||||
|
||||
bool is_prusa() const;
|
||||
bool is_custom() const;
|
||||
|
||||
const Pointfs& get_shape() const;
|
||||
void set_shape(const Pointfs& shape);
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const;
|
||||
bool contains(const Point& point) const;
|
||||
Point point_projection(const Point& point) const;
|
||||
|
||||
void render(float theta) const;
|
||||
|
||||
private:
|
||||
void _calc_bounding_box();
|
||||
void _calc_triangles(const ExPolygon& poly);
|
||||
void _calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
|
||||
EType _detect_type() const;
|
||||
void _render_mk2(float theta) const;
|
||||
void _render_mk3(float theta) const;
|
||||
void _render_prusa(float theta) const;
|
||||
void _render_custom() const;
|
||||
static bool _are_equal(const Pointfs& bed_1, const Pointfs& bed_2);
|
||||
};
|
||||
|
||||
struct Axes
|
||||
{
|
||||
Pointf3 origin;
|
||||
float length;
|
||||
|
||||
Axes();
|
||||
|
||||
void render(bool depth_test) const;
|
||||
};
|
||||
|
||||
class CuttingPlane
|
||||
{
|
||||
float m_z;
|
||||
GeometryBuffer m_lines;
|
||||
|
||||
public:
|
||||
CuttingPlane();
|
||||
|
||||
bool set(float z, const ExPolygons& polygons);
|
||||
|
||||
void render(const BoundingBoxf3& bb) const;
|
||||
|
||||
private:
|
||||
void _render_plane(const BoundingBoxf3& bb) const;
|
||||
void _render_contour() const;
|
||||
};
|
||||
|
||||
class Shader
|
||||
{
|
||||
GLShader* m_shader;
|
||||
|
||||
public:
|
||||
Shader();
|
||||
~Shader();
|
||||
|
||||
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
|
||||
|
||||
bool is_initialized() const;
|
||||
|
||||
bool start_using() const;
|
||||
void stop_using() const;
|
||||
|
||||
void set_uniform(const std::string& name, float value) const;
|
||||
|
||||
const GLShader* get_shader() const;
|
||||
|
||||
private:
|
||||
void _reset();
|
||||
};
|
||||
|
||||
class LayersEditing
|
||||
{
|
||||
public:
|
||||
enum EState : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Editing,
|
||||
Completed,
|
||||
Num_States
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_use_legacy_opengl;
|
||||
bool m_enabled;
|
||||
Shader m_shader;
|
||||
unsigned int m_z_texture_id;
|
||||
mutable GLTexture m_tooltip_texture;
|
||||
mutable GLTexture m_reset_texture;
|
||||
|
||||
public:
|
||||
EState state;
|
||||
float band_width;
|
||||
float strength;
|
||||
int last_object_id;
|
||||
float last_z;
|
||||
unsigned int last_action;
|
||||
|
||||
LayersEditing();
|
||||
~LayersEditing();
|
||||
|
||||
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
|
||||
|
||||
bool is_allowed() const;
|
||||
void set_use_legacy_opengl(bool use_legacy_opengl);
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool enabled);
|
||||
|
||||
unsigned int get_z_texture_id() const;
|
||||
|
||||
void render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const;
|
||||
|
||||
int get_shader_program_id() const;
|
||||
|
||||
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
||||
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
||||
static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
||||
static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
|
||||
static Rect get_reset_rect_screen(const GLCanvas3D& canvas);
|
||||
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
|
||||
static Rect get_reset_rect_viewport(const GLCanvas3D& canvas);
|
||||
|
||||
private:
|
||||
bool _is_initialized() const;
|
||||
void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
|
||||
void _render_reset_texture(const Rect& reset_rect) const;
|
||||
void _render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const;
|
||||
void _render_profile(const PrintObject& print_object, const Rect& bar_rect) const;
|
||||
};
|
||||
|
||||
struct Mouse
|
||||
{
|
||||
struct Drag
|
||||
{
|
||||
static const Point Invalid_2D_Point;
|
||||
static const Pointf3 Invalid_3D_Point;
|
||||
|
||||
Point start_position_2D;
|
||||
Pointf3 start_position_3D;
|
||||
Vectorf3 volume_center_offset;
|
||||
int volume_idx;
|
||||
|
||||
public:
|
||||
Drag();
|
||||
};
|
||||
|
||||
bool dragging;
|
||||
Pointf position;
|
||||
Drag drag;
|
||||
|
||||
Mouse();
|
||||
|
||||
void set_start_position_2D_as_invalid();
|
||||
void set_start_position_3D_as_invalid();
|
||||
|
||||
bool is_start_position_2D_defined() const;
|
||||
bool is_start_position_3D_defined() const;
|
||||
};
|
||||
|
||||
class Gizmos
|
||||
{
|
||||
static const float OverlayOffsetX;
|
||||
static const float OverlayGapY;
|
||||
|
||||
public:
|
||||
enum EType : unsigned char
|
||||
{
|
||||
Undefined,
|
||||
Scale,
|
||||
Rotate,
|
||||
Num_Types
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_enabled;
|
||||
typedef std::map<EType, GLGizmoBase*> GizmosMap;
|
||||
GizmosMap m_gizmos;
|
||||
EType m_current;
|
||||
bool m_dragging;
|
||||
|
||||
public:
|
||||
Gizmos();
|
||||
~Gizmos();
|
||||
|
||||
bool init();
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool enable);
|
||||
|
||||
void update_hover_state(const GLCanvas3D& canvas, const Pointf& mouse_pos);
|
||||
void update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos);
|
||||
void reset_all_states();
|
||||
|
||||
void set_hover_id(int id);
|
||||
|
||||
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const;
|
||||
bool grabber_contains_mouse() const;
|
||||
void update(const Pointf& mouse_pos);
|
||||
void update_data(float scale);
|
||||
|
||||
bool is_running() const;
|
||||
bool is_dragging() const;
|
||||
void start_dragging();
|
||||
void stop_dragging();
|
||||
|
||||
float get_scale() const;
|
||||
|
||||
void render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const;
|
||||
void render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const;
|
||||
|
||||
private:
|
||||
void _reset();
|
||||
|
||||
void _render_overlay(const GLCanvas3D& canvas) const;
|
||||
void _render_current_gizmo(const BoundingBoxf3& box) const;
|
||||
|
||||
float _get_total_overlay_height() const;
|
||||
GLGizmoBase* _get_current() const;
|
||||
};
|
||||
|
||||
private:
|
||||
wxGLCanvas* m_canvas;
|
||||
wxGLContext* m_context;
|
||||
wxTimer* m_timer;
|
||||
Camera m_camera;
|
||||
Bed m_bed;
|
||||
Axes m_axes;
|
||||
CuttingPlane m_cutting_plane;
|
||||
LayersEditing m_layers_editing;
|
||||
Shader m_shader;
|
||||
Mouse m_mouse;
|
||||
mutable Gizmos m_gizmos;
|
||||
|
||||
mutable GLVolumeCollection m_volumes;
|
||||
DynamicPrintConfig* m_config;
|
||||
Print* m_print;
|
||||
Model* m_model;
|
||||
|
||||
bool m_dirty;
|
||||
// the active member has been introduced to overcome a bug in wxWidgets method IsShownOnScreen() which always return true
|
||||
// when a window is inside a wxNotebook
|
||||
bool m_active;
|
||||
bool m_initialized;
|
||||
bool m_use_VBOs;
|
||||
bool m_force_zoom_to_bed_enabled;
|
||||
bool m_apply_zoom_to_volumes_filter;
|
||||
mutable int m_hover_volume_id;
|
||||
bool m_warning_texture_enabled;
|
||||
bool m_legend_texture_enabled;
|
||||
bool m_picking_enabled;
|
||||
bool m_moving_enabled;
|
||||
bool m_shader_enabled;
|
||||
bool m_multisample_allowed;
|
||||
|
||||
std::string m_color_by;
|
||||
std::string m_select_by;
|
||||
std::string m_drag_by;
|
||||
|
||||
bool m_reload_delayed;
|
||||
std::vector<std::vector<int>> m_objects_volumes_idxs;
|
||||
std::vector<int> m_objects_selections;
|
||||
|
||||
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
|
||||
|
||||
PerlCallback m_on_viewport_changed_callback;
|
||||
PerlCallback m_on_double_click_callback;
|
||||
PerlCallback m_on_right_click_callback;
|
||||
PerlCallback m_on_select_object_callback;
|
||||
PerlCallback m_on_model_update_callback;
|
||||
PerlCallback m_on_remove_object_callback;
|
||||
PerlCallback m_on_arrange_callback;
|
||||
PerlCallback m_on_rotate_object_left_callback;
|
||||
PerlCallback m_on_rotate_object_right_callback;
|
||||
PerlCallback m_on_scale_object_uniformly_callback;
|
||||
PerlCallback m_on_increase_objects_callback;
|
||||
PerlCallback m_on_decrease_objects_callback;
|
||||
PerlCallback m_on_instance_moved_callback;
|
||||
PerlCallback m_on_wipe_tower_moved_callback;
|
||||
PerlCallback m_on_enable_action_buttons_callback;
|
||||
PerlCallback m_on_gizmo_scale_uniformly_callback;
|
||||
|
||||
public:
|
||||
GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context);
|
||||
~GLCanvas3D();
|
||||
|
||||
bool init(bool useVBOs, bool use_legacy_opengl);
|
||||
|
||||
bool set_current();
|
||||
|
||||
void set_active(bool active);
|
||||
|
||||
unsigned int get_volumes_count() const;
|
||||
void reset_volumes();
|
||||
void deselect_volumes();
|
||||
void select_volume(unsigned int id);
|
||||
void update_volumes_selection(const std::vector<int>& selections);
|
||||
bool check_volumes_outside_state(const DynamicPrintConfig* config) const;
|
||||
bool move_volume_up(unsigned int id);
|
||||
bool move_volume_down(unsigned int id);
|
||||
|
||||
void set_objects_selections(const std::vector<int>& selections);
|
||||
|
||||
void set_config(DynamicPrintConfig* config);
|
||||
void set_print(Print* print);
|
||||
void set_model(Model* model);
|
||||
|
||||
// Set the bed shape to a single closed 2D polygon(array of two element arrays),
|
||||
// triangulate the bed and store the triangles into m_bed.m_triangles,
|
||||
// fills the m_bed.m_grid_lines and sets m_bed.m_origin.
|
||||
// Sets m_bed.m_polygon to limit the object placement.
|
||||
void set_bed_shape(const Pointfs& shape);
|
||||
// Used by ObjectCutDialog and ObjectPartsPanel to generate a rectangular ground plane to support the scene objects.
|
||||
void set_auto_bed_shape();
|
||||
|
||||
void set_axes_length(float length);
|
||||
|
||||
void set_cutting_plane(float z, const ExPolygons& polygons);
|
||||
|
||||
void set_color_by(const std::string& value);
|
||||
void set_select_by(const std::string& value);
|
||||
void set_drag_by(const std::string& value);
|
||||
|
||||
float get_camera_zoom() const;
|
||||
|
||||
BoundingBoxf3 volumes_bounding_box() const;
|
||||
|
||||
bool is_layers_editing_enabled() const;
|
||||
bool is_layers_editing_allowed() const;
|
||||
bool is_shader_enabled() const;
|
||||
|
||||
bool is_reload_delayed() const;
|
||||
|
||||
void enable_layers_editing(bool enable);
|
||||
void enable_warning_texture(bool enable);
|
||||
void enable_legend_texture(bool enable);
|
||||
void enable_picking(bool enable);
|
||||
void enable_moving(bool enable);
|
||||
void enable_gizmos(bool enable);
|
||||
void enable_shader(bool enable);
|
||||
void enable_force_zoom_to_bed(bool enable);
|
||||
void allow_multisample(bool allow);
|
||||
|
||||
void zoom_to_bed();
|
||||
void zoom_to_volumes();
|
||||
void select_view(const std::string& direction);
|
||||
void set_viewport_from_scene(const GLCanvas3D& other);
|
||||
|
||||
void update_volumes_colors_by_extruder();
|
||||
|
||||
void render();
|
||||
|
||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||
void set_toolpaths_range(double low, double high);
|
||||
|
||||
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
|
||||
std::vector<int> load_object(const Model& model, int obj_idx);
|
||||
|
||||
void reload_scene(bool force);
|
||||
|
||||
// Create 3D thick extrusion lines for a skirt and brim.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||
void load_print_toolpaths();
|
||||
// Create 3D thick extrusion lines for object forming extrusions.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
// one for perimeters, one for infill and one for supports.
|
||||
void load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
|
||||
// Create 3D thick extrusion lines for wipe tower extrusions
|
||||
void load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
||||
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
void register_on_viewport_changed_callback(void* callback);
|
||||
void register_on_double_click_callback(void* callback);
|
||||
void register_on_right_click_callback(void* callback);
|
||||
void register_on_select_object_callback(void* callback);
|
||||
void register_on_model_update_callback(void* callback);
|
||||
void register_on_remove_object_callback(void* callback);
|
||||
void register_on_arrange_callback(void* callback);
|
||||
void register_on_rotate_object_left_callback(void* callback);
|
||||
void register_on_rotate_object_right_callback(void* callback);
|
||||
void register_on_scale_object_uniformly_callback(void* callback);
|
||||
void register_on_increase_objects_callback(void* callback);
|
||||
void register_on_decrease_objects_callback(void* callback);
|
||||
void register_on_instance_moved_callback(void* callback);
|
||||
void register_on_wipe_tower_moved_callback(void* callback);
|
||||
void register_on_enable_action_buttons_callback(void* callback);
|
||||
void register_on_gizmo_scale_uniformly_callback(void* callback);
|
||||
|
||||
void bind_event_handlers();
|
||||
void unbind_event_handlers();
|
||||
|
||||
void on_size(wxSizeEvent& evt);
|
||||
void on_idle(wxIdleEvent& evt);
|
||||
void on_char(wxKeyEvent& evt);
|
||||
void on_mouse_wheel(wxMouseEvent& evt);
|
||||
void on_timer(wxTimerEvent& evt);
|
||||
void on_mouse(wxMouseEvent& evt);
|
||||
void on_paint(wxPaintEvent& evt);
|
||||
void on_key_down(wxKeyEvent& evt);
|
||||
|
||||
Size get_canvas_size() const;
|
||||
Point get_local_mouse_position() const;
|
||||
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
void _force_zoom_to_bed();
|
||||
|
||||
void _resize(unsigned int w, unsigned int h);
|
||||
|
||||
BoundingBoxf3 _max_bounding_box() const;
|
||||
BoundingBoxf3 _selected_volumes_bounding_box() const;
|
||||
|
||||
void _zoom_to_bounding_box(const BoundingBoxf3& bbox);
|
||||
float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const;
|
||||
|
||||
void _deregister_callbacks();
|
||||
|
||||
void _mark_volumes_for_layer_height() const;
|
||||
void _refresh_if_shown_on_screen();
|
||||
|
||||
void _camera_tranform() const;
|
||||
void _picking_pass() const;
|
||||
void _render_background() const;
|
||||
void _render_bed(float theta) const;
|
||||
void _render_axes(bool depth_test) const;
|
||||
void _render_objects() const;
|
||||
void _render_cutting_plane() const;
|
||||
void _render_warning_texture() const;
|
||||
void _render_legend_texture() const;
|
||||
void _render_layer_editing_overlay() const;
|
||||
void _render_volumes(bool fake_colors) const;
|
||||
void _render_gizmo() const;
|
||||
|
||||
float _get_layers_editing_cursor_z_relative() const;
|
||||
void _perform_layer_editing_action(wxMouseEvent* evt = nullptr);
|
||||
|
||||
// Convert the screen space coordinate to an object space coordinate.
|
||||
// If the Z screen space coordinate is not provided, a depth buffer value is substituted.
|
||||
Pointf3 _mouse_to_3d(const Point& mouse_pos, float* z = nullptr);
|
||||
|
||||
// Convert the screen space coordinate to world coordinate on the bed.
|
||||
Pointf3 _mouse_to_bed_3d(const Point& mouse_pos);
|
||||
|
||||
void _start_timer();
|
||||
void _stop_timer();
|
||||
|
||||
int _get_first_selected_object_id() const;
|
||||
|
||||
// generates gcode extrusion paths geometry
|
||||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
// generates gcode travel paths geometry
|
||||
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
bool _travel_paths_by_type(const GCodePreviewData& preview_data);
|
||||
bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data);
|
||||
bool _travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
// generates gcode retractions geometry
|
||||
void _load_gcode_retractions(const GCodePreviewData& preview_data);
|
||||
// generates gcode unretractions geometry
|
||||
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
|
||||
// generates objects and wipe tower geometry
|
||||
void _load_shells();
|
||||
// sets gcode geometry visibility according to user selection
|
||||
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
||||
|
||||
void _on_move(const std::vector<int>& volume_idxs);
|
||||
void _on_select(int volume_idx);
|
||||
|
||||
void _update_gizmos_data();
|
||||
|
||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLCanvas3D_hpp_
|
707
xs/src/slic3r/GUI/GLCanvas3DManager.cpp
Normal file
707
xs/src/slic3r/GUI/GLCanvas3DManager.cpp
Normal file
|
@ -0,0 +1,707 @@
|
|||
#include "GLCanvas3DManager.hpp"
|
||||
#include "../../slic3r/GUI/GUI.hpp"
|
||||
#include "../../slic3r/GUI/AppConfig.hpp"
|
||||
#include "../../slic3r/GUI/GLCanvas3D.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
GLCanvas3DManager::GLInfo::GLInfo()
|
||||
: version("")
|
||||
, glsl_version("")
|
||||
, vendor("")
|
||||
, renderer("")
|
||||
{
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::GLInfo::detect()
|
||||
{
|
||||
const char* data = (const char*)::glGetString(GL_VERSION);
|
||||
if (data == nullptr)
|
||||
return false;
|
||||
|
||||
version = data;
|
||||
|
||||
data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
if (data == nullptr)
|
||||
return false;
|
||||
|
||||
glsl_version = data;
|
||||
|
||||
data = (const char*)::glGetString(GL_VENDOR);
|
||||
if (data == nullptr)
|
||||
return false;
|
||||
|
||||
vendor = data;
|
||||
|
||||
data = (const char*)::glGetString(GL_RENDERER);
|
||||
if (data == nullptr)
|
||||
return false;
|
||||
|
||||
renderer = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on);
|
||||
|
||||
if (tokens.empty())
|
||||
return false;
|
||||
|
||||
std::vector<std::string> numbers;
|
||||
boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
|
||||
|
||||
unsigned int gl_major = 0;
|
||||
unsigned int gl_minor = 0;
|
||||
|
||||
if (numbers.size() > 0)
|
||||
gl_major = ::atoi(numbers[0].c_str());
|
||||
|
||||
if (numbers.size() > 1)
|
||||
gl_minor = ::atoi(numbers[1].c_str());
|
||||
|
||||
if (gl_major < major)
|
||||
return false;
|
||||
else if (gl_major > major)
|
||||
return true;
|
||||
else
|
||||
return gl_minor >= minor;
|
||||
}
|
||||
|
||||
std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
std::string h2_start = format_as_html ? "<b>" : "";
|
||||
std::string h2_end = format_as_html ? "</b>" : "";
|
||||
std::string b_start = format_as_html ? "<b>" : "";
|
||||
std::string b_end = format_as_html ? "</b>" : "";
|
||||
std::string line_end = format_as_html ? "<br>" : "\n";
|
||||
|
||||
out << h2_start << "OpenGL installation" << h2_end << line_end;
|
||||
out << b_start << "GL version: " << b_end << version << line_end;
|
||||
out << b_start << "Vendor: " << b_end << vendor << line_end;
|
||||
out << b_start << "Renderer: " << b_end << renderer << line_end;
|
||||
out << b_start << "GLSL version: " << b_end << glsl_version << line_end;
|
||||
|
||||
if (extensions)
|
||||
{
|
||||
out << h2_start << "Installed extensions:" << h2_end << line_end;
|
||||
|
||||
std::vector<std::string> extensions_list;
|
||||
GLint num_extensions;
|
||||
::glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
|
||||
|
||||
for (GLint i = 0; i < num_extensions; ++i)
|
||||
{
|
||||
const char* e = (const char*)::glGetStringi(GL_EXTENSIONS, i);
|
||||
extensions_list.push_back(e);
|
||||
}
|
||||
|
||||
std::sort(extensions_list.begin(), extensions_list.end());
|
||||
for (const std::string& ext : extensions_list)
|
||||
{
|
||||
out << ext << line_end;
|
||||
}
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
GLCanvas3DManager::GLCanvas3DManager()
|
||||
: m_context(nullptr)
|
||||
, m_gl_initialized(false)
|
||||
, m_use_legacy_opengl(false)
|
||||
, m_use_VBOs(false)
|
||||
{
|
||||
}
|
||||
|
||||
GLCanvas3DManager::~GLCanvas3DManager()
|
||||
{
|
||||
if (m_context != nullptr)
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::add(wxGLCanvas* canvas)
|
||||
{
|
||||
if (canvas == nullptr)
|
||||
return false;
|
||||
|
||||
if (_get_canvas(canvas) != m_canvases.end())
|
||||
return false;
|
||||
|
||||
if (m_context == nullptr)
|
||||
{
|
||||
m_context = new wxGLContext(canvas);
|
||||
if (m_context == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
GLCanvas3D* canvas3D = new GLCanvas3D(canvas, m_context);
|
||||
if (canvas3D == nullptr)
|
||||
return false;
|
||||
|
||||
canvas3D->bind_event_handlers();
|
||||
m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::remove(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it == m_canvases.end())
|
||||
return false;
|
||||
|
||||
it->second->unbind_event_handlers();
|
||||
delete it->second;
|
||||
m_canvases.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::remove_all()
|
||||
{
|
||||
for (CanvasesMap::value_type& item : m_canvases)
|
||||
{
|
||||
item.second->unbind_event_handlers();
|
||||
delete item.second;
|
||||
}
|
||||
m_canvases.clear();
|
||||
}
|
||||
|
||||
unsigned int GLCanvas3DManager::count() const
|
||||
{
|
||||
return (unsigned int)m_canvases.size();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::init_gl()
|
||||
{
|
||||
if (!m_gl_initialized)
|
||||
{
|
||||
glewInit();
|
||||
if (m_gl_info.detect())
|
||||
{
|
||||
const AppConfig* config = GUI::get_app_config();
|
||||
m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1");
|
||||
m_use_VBOs = !m_use_legacy_opengl && m_gl_info.is_version_greater_or_equal_to(2, 0);
|
||||
m_gl_initialized = true;
|
||||
}
|
||||
else
|
||||
throw std::runtime_error(std::string("Unable to initialize OpenGL driver\n"));
|
||||
}
|
||||
}
|
||||
|
||||
std::string GLCanvas3DManager::get_gl_info(bool format_as_html, bool extensions) const
|
||||
{
|
||||
return m_gl_info.to_string(format_as_html, extensions);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::use_VBOs() const
|
||||
{
|
||||
return m_use_VBOs;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::init(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
return (it->second != nullptr) ? _init(*it->second) : false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_active(active);
|
||||
}
|
||||
|
||||
unsigned int GLCanvas3DManager::get_volumes_count(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->get_volumes_count() : 0;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::reset_volumes(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->reset_volumes();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::deselect_volumes(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->deselect_volumes();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::select_volume(wxGLCanvas* canvas, unsigned int id)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->select_volume(id);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->update_volumes_selection(selections);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->check_volumes_outside_state(config) : false;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::move_volume_up(wxGLCanvas* canvas, unsigned int id)
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->move_volume_up(id) : false;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::move_volume_down(wxGLCanvas* canvas, unsigned int id)
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->move_volume_down(id) : false;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_objects_selections(selections);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_config(config);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_print(wxGLCanvas* canvas, Print* print)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_print(print);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_model(wxGLCanvas* canvas, Model* model)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_model(model);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_bed_shape(shape);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_auto_bed_shape(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_auto_bed_shape();
|
||||
}
|
||||
|
||||
BoundingBoxf3 GLCanvas3DManager::get_volumes_bounding_box(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->volumes_bounding_box() : BoundingBoxf3();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_axes_length(wxGLCanvas* canvas, float length)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_axes_length(length);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_cutting_plane(z, polygons);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_color_by(wxGLCanvas* canvas, const std::string& value)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_color_by(value);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_select_by(wxGLCanvas* canvas, const std::string& value)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_select_by(value);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_drag_by(wxGLCanvas* canvas, const std::string& value)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_drag_by(value);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::is_layers_editing_enabled(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->is_layers_editing_enabled() : false;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::is_layers_editing_allowed(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->is_layers_editing_allowed() : false;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::is_shader_enabled(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->is_shader_enabled() : false;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::is_reload_delayed(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->is_reload_delayed() : false;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_layers_editing(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_layers_editing(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_warning_texture(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_warning_texture(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_legend_texture(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_legend_texture(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_picking(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_picking(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_moving(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_moving(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_gizmos(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_gizmos(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_shader(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_force_zoom_to_bed(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->allow_multisample(allow);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::zoom_to_bed(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->zoom_to_bed();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::zoom_to_volumes(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->zoom_to_volumes();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::select_view(wxGLCanvas* canvas, const std::string& direction)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->select_view(direction);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
{
|
||||
CanvasesMap::iterator other_it = _get_canvas(other);
|
||||
if (other_it != m_canvases.end())
|
||||
it->second->set_viewport_from_scene(*other_it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::update_volumes_colors_by_extruder(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->update_volumes_colors_by_extruder();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::render(wxGLCanvas* canvas) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->render();
|
||||
}
|
||||
|
||||
std::vector<double> GLCanvas3DManager::get_current_print_zs(wxGLCanvas* canvas, bool active_only) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->get_current_print_zs(active_only) : std::vector<double>();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::set_toolpaths_range(wxGLCanvas* canvas, double low, double high)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->set_toolpaths_range(low, high);
|
||||
}
|
||||
|
||||
std::vector<int> GLCanvas3DManager::load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs)
|
||||
{
|
||||
if (model_object == nullptr)
|
||||
return std::vector<int>();
|
||||
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->load_object(*model_object, obj_idx, instance_idxs) : std::vector<int>();
|
||||
}
|
||||
|
||||
std::vector<int> GLCanvas3DManager::load_object(wxGLCanvas* canvas, const Model* model, int obj_idx)
|
||||
{
|
||||
if (model == nullptr)
|
||||
return std::vector<int>();
|
||||
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->load_object(*model, obj_idx) : std::vector<int>();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->reload_scene(force);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_print_toolpaths(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_print_toolpaths();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors)
|
||||
{
|
||||
if (print_object == nullptr)
|
||||
return;
|
||||
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_print_object_toolpaths(*print_object, tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_wipe_tower_toolpaths(str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
if (preview_data == nullptr)
|
||||
return;
|
||||
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_gcode_preview(*preview_data, str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_viewport_changed_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_double_click_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_double_click_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_right_click_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_right_click_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_select_object_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_select_object_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_model_update_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_model_update_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_remove_object_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_arrange_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_arrange_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_rotate_object_left_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_rotate_object_right_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_scale_object_uniformly_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_increase_objects_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_decrease_objects_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_instance_moved_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_wipe_tower_moved_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_enable_action_buttons_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_gizmo_scale_uniformly_callback(callback);
|
||||
}
|
||||
|
||||
GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
|
||||
}
|
||||
|
||||
GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) const
|
||||
{
|
||||
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::_init(GLCanvas3D& canvas)
|
||||
{
|
||||
if (!m_gl_initialized)
|
||||
init_gl();
|
||||
|
||||
return canvas.init(m_use_VBOs, m_use_legacy_opengl);
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
167
xs/src/slic3r/GUI/GLCanvas3DManager.hpp
Normal file
167
xs/src/slic3r/GUI/GLCanvas3DManager.hpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
#ifndef slic3r_GLCanvas3DManager_hpp_
|
||||
#define slic3r_GLCanvas3DManager_hpp_
|
||||
|
||||
#include "../../libslic3r/BoundingBox.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class wxGLCanvas;
|
||||
class wxGLContext;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Print;
|
||||
class Model;
|
||||
class ExPolygon;
|
||||
typedef std::vector<ExPolygon> ExPolygons;
|
||||
class ModelObject;
|
||||
class PrintObject;
|
||||
class GCodePreviewData;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class GLCanvas3D;
|
||||
|
||||
class GLCanvas3DManager
|
||||
{
|
||||
struct GLInfo
|
||||
{
|
||||
std::string version;
|
||||
std::string glsl_version;
|
||||
std::string vendor;
|
||||
std::string renderer;
|
||||
|
||||
GLInfo();
|
||||
|
||||
bool detect();
|
||||
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
|
||||
|
||||
std::string to_string(bool format_as_html, bool extensions) const;
|
||||
};
|
||||
|
||||
typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap;
|
||||
|
||||
wxGLContext* m_context;
|
||||
CanvasesMap m_canvases;
|
||||
GLInfo m_gl_info;
|
||||
bool m_gl_initialized;
|
||||
bool m_use_legacy_opengl;
|
||||
bool m_use_VBOs;
|
||||
|
||||
public:
|
||||
GLCanvas3DManager();
|
||||
~GLCanvas3DManager();
|
||||
|
||||
bool add(wxGLCanvas* canvas);
|
||||
bool remove(wxGLCanvas* canvas);
|
||||
|
||||
void remove_all();
|
||||
|
||||
unsigned int count() const;
|
||||
|
||||
void init_gl();
|
||||
std::string get_gl_info(bool format_as_html, bool extensions) const;
|
||||
|
||||
bool use_VBOs() const;
|
||||
bool layer_editing_allowed() const;
|
||||
|
||||
bool init(wxGLCanvas* canvas);
|
||||
|
||||
void set_active(wxGLCanvas* canvas, bool active);
|
||||
|
||||
unsigned int get_volumes_count(wxGLCanvas* canvas) const;
|
||||
void reset_volumes(wxGLCanvas* canvas);
|
||||
void deselect_volumes(wxGLCanvas* canvas);
|
||||
void select_volume(wxGLCanvas* canvas, unsigned int id);
|
||||
void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const;
|
||||
bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
|
||||
bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
|
||||
|
||||
void set_objects_selections(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
|
||||
void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config);
|
||||
void set_print(wxGLCanvas* canvas, Print* print);
|
||||
void set_model(wxGLCanvas* canvas, Model* model);
|
||||
|
||||
void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape);
|
||||
void set_auto_bed_shape(wxGLCanvas* canvas);
|
||||
|
||||
BoundingBoxf3 get_volumes_bounding_box(wxGLCanvas* canvas);
|
||||
|
||||
void set_axes_length(wxGLCanvas* canvas, float length);
|
||||
|
||||
void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons);
|
||||
|
||||
void set_color_by(wxGLCanvas* canvas, const std::string& value);
|
||||
void set_select_by(wxGLCanvas* canvas, const std::string& value);
|
||||
void set_drag_by(wxGLCanvas* canvas, const std::string& value);
|
||||
|
||||
bool is_layers_editing_enabled(wxGLCanvas* canvas) const;
|
||||
bool is_layers_editing_allowed(wxGLCanvas* canvas) const;
|
||||
bool is_shader_enabled(wxGLCanvas* canvas) const;
|
||||
|
||||
bool is_reload_delayed(wxGLCanvas* canvas) const;
|
||||
|
||||
void enable_layers_editing(wxGLCanvas* canvas, bool enable);
|
||||
void enable_warning_texture(wxGLCanvas* canvas, bool enable);
|
||||
void enable_legend_texture(wxGLCanvas* canvas, bool enable);
|
||||
void enable_picking(wxGLCanvas* canvas, bool enable);
|
||||
void enable_moving(wxGLCanvas* canvas, bool enable);
|
||||
void enable_gizmos(wxGLCanvas* canvas, bool enable);
|
||||
void enable_shader(wxGLCanvas* canvas, bool enable);
|
||||
void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
|
||||
void allow_multisample(wxGLCanvas* canvas, bool allow);
|
||||
|
||||
void zoom_to_bed(wxGLCanvas* canvas);
|
||||
void zoom_to_volumes(wxGLCanvas* canvas);
|
||||
void select_view(wxGLCanvas* canvas, const std::string& direction);
|
||||
void set_viewport_from_scene(wxGLCanvas* canvas, wxGLCanvas* other);
|
||||
|
||||
void update_volumes_colors_by_extruder(wxGLCanvas* canvas);
|
||||
|
||||
void render(wxGLCanvas* canvas) const;
|
||||
|
||||
std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const;
|
||||
void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
|
||||
|
||||
std::vector<int> load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs);
|
||||
std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
|
||||
|
||||
void reload_scene(wxGLCanvas* canvas, bool force);
|
||||
|
||||
void load_print_toolpaths(wxGLCanvas* canvas);
|
||||
void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors);
|
||||
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_select_object_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
private:
|
||||
CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas);
|
||||
CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const;
|
||||
|
||||
bool _init(GLCanvas3D& canvas);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLCanvas3DManager_hpp_
|
454
xs/src/slic3r/GUI/GLGizmo.cpp
Normal file
454
xs/src/slic3r/GUI/GLGizmo.cpp
Normal file
|
@ -0,0 +1,454 @@
|
|||
#include "GLGizmo.hpp"
|
||||
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../libslic3r/BoundingBox.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
const float GLGizmoBase::Grabber::HalfSize = 2.0f;
|
||||
const float GLGizmoBase::Grabber::HoverOffset = 0.5f;
|
||||
const float GLGizmoBase::BaseColor[3] = { 1.0f, 1.0f, 1.0f };
|
||||
const float GLGizmoBase::HighlightColor[3] = { 1.0f, 0.38f, 0.0f };
|
||||
|
||||
GLGizmoBase::Grabber::Grabber()
|
||||
: center(Pointf(0.0, 0.0))
|
||||
, angle_z(0.0f)
|
||||
{
|
||||
color[0] = 1.0f;
|
||||
color[1] = 1.0f;
|
||||
color[2] = 1.0f;
|
||||
}
|
||||
|
||||
void GLGizmoBase::Grabber::render(bool hover) const
|
||||
{
|
||||
float min_x = -HalfSize;
|
||||
float max_x = +HalfSize;
|
||||
float min_y = -HalfSize;
|
||||
float max_y = +HalfSize;
|
||||
|
||||
::glColor3f((GLfloat)color[0], (GLfloat)color[1], (GLfloat)color[2]);
|
||||
|
||||
float angle_z_in_deg = angle_z * 180.0f / (float)PI;
|
||||
::glPushMatrix();
|
||||
::glTranslatef((GLfloat)center.x, (GLfloat)center.y, 0.0f);
|
||||
::glRotatef((GLfloat)angle_z_in_deg, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
::glDisable(GL_CULL_FACE);
|
||||
::glBegin(GL_TRIANGLES);
|
||||
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
|
||||
::glVertex3f((GLfloat)max_x, (GLfloat)min_y, 0.0f);
|
||||
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
|
||||
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
|
||||
::glVertex3f((GLfloat)min_x, (GLfloat)max_y, 0.0f);
|
||||
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
|
||||
::glEnd();
|
||||
::glEnable(GL_CULL_FACE);
|
||||
|
||||
if (hover)
|
||||
{
|
||||
min_x -= HoverOffset;
|
||||
max_x += HoverOffset;
|
||||
min_y -= HoverOffset;
|
||||
max_y += HoverOffset;
|
||||
|
||||
::glBegin(GL_LINE_LOOP);
|
||||
::glVertex3f((GLfloat)min_x, (GLfloat)min_y, 0.0f);
|
||||
::glVertex3f((GLfloat)max_x, (GLfloat)min_y, 0.0f);
|
||||
::glVertex3f((GLfloat)max_x, (GLfloat)max_y, 0.0f);
|
||||
::glVertex3f((GLfloat)min_x, (GLfloat)max_y, 0.0f);
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase()
|
||||
: m_state(Off)
|
||||
, m_hover_id(-1)
|
||||
{
|
||||
}
|
||||
|
||||
GLGizmoBase::~GLGizmoBase()
|
||||
{
|
||||
}
|
||||
|
||||
bool GLGizmoBase::init()
|
||||
{
|
||||
return on_init();
|
||||
}
|
||||
|
||||
GLGizmoBase::EState GLGizmoBase::get_state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void GLGizmoBase::set_state(GLGizmoBase::EState state)
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
unsigned int GLGizmoBase::get_textures_id() const
|
||||
{
|
||||
return m_textures[m_state].get_id();
|
||||
}
|
||||
|
||||
int GLGizmoBase::get_textures_size() const
|
||||
{
|
||||
return m_textures[Off].get_width();
|
||||
}
|
||||
|
||||
int GLGizmoBase::get_hover_id() const
|
||||
{
|
||||
return m_hover_id;
|
||||
}
|
||||
|
||||
void GLGizmoBase::set_hover_id(int id)
|
||||
{
|
||||
if (id < (int)m_grabbers.size())
|
||||
m_hover_id = id;
|
||||
}
|
||||
|
||||
void GLGizmoBase::start_dragging()
|
||||
{
|
||||
on_start_dragging();
|
||||
}
|
||||
|
||||
void GLGizmoBase::update(const Pointf& mouse_pos)
|
||||
{
|
||||
if (m_hover_id != -1)
|
||||
on_update(mouse_pos);
|
||||
}
|
||||
|
||||
void GLGizmoBase::render(const BoundingBoxf3& box) const
|
||||
{
|
||||
on_render(box);
|
||||
}
|
||||
|
||||
void GLGizmoBase::render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
on_render_for_picking(box);
|
||||
}
|
||||
|
||||
void GLGizmoBase::on_start_dragging()
|
||||
{
|
||||
}
|
||||
|
||||
void GLGizmoBase::render_grabbers() const
|
||||
{
|
||||
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i)
|
||||
{
|
||||
m_grabbers[i].render(m_hover_id == i);
|
||||
}
|
||||
}
|
||||
|
||||
const float GLGizmoRotate::Offset = 5.0f;
|
||||
const unsigned int GLGizmoRotate::CircleResolution = 64;
|
||||
const unsigned int GLGizmoRotate::AngleResolution = 64;
|
||||
const unsigned int GLGizmoRotate::ScaleStepsCount = 60;
|
||||
const float GLGizmoRotate::ScaleStepRad = 2.0f * (float)PI / GLGizmoRotate::ScaleStepsCount;
|
||||
const unsigned int GLGizmoRotate::ScaleLongEvery = 5;
|
||||
const float GLGizmoRotate::ScaleLongTooth = 2.0f;
|
||||
const float GLGizmoRotate::ScaleShortTooth = 1.0f;
|
||||
const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
|
||||
const float GLGizmoRotate::GrabberOffset = 5.0f;
|
||||
|
||||
GLGizmoRotate::GLGizmoRotate()
|
||||
: GLGizmoBase()
|
||||
, m_angle_z(0.0f)
|
||||
, m_center(Pointf(0.0, 0.0))
|
||||
, m_radius(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
bool GLGizmoRotate::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
std::string filename = path + "rotate_off.png";
|
||||
if (!m_textures[Off].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
filename = path + "rotate_hover.png";
|
||||
if (!m_textures[Hover].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
filename = path + "rotate_on.png";
|
||||
if (!m_textures[On].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
m_grabbers.push_back(Grabber());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLGizmoRotate::on_update(const Pointf& mouse_pos)
|
||||
{
|
||||
Vectorf orig_dir(1.0, 0.0);
|
||||
Vectorf new_dir = normalize(mouse_pos - m_center);
|
||||
coordf_t theta = ::acos(clamp(-1.0, 1.0, dot(new_dir, orig_dir)));
|
||||
if (cross(orig_dir, new_dir) < 0.0)
|
||||
theta = 2.0 * (coordf_t)PI - theta;
|
||||
|
||||
if (length(m_center.vector_to(mouse_pos)) < 2.0 * (double)m_radius / 3.0)
|
||||
{
|
||||
coordf_t step = 2.0 * (coordf_t)PI / (coordf_t)SnapRegionsCount;
|
||||
theta = step * (coordf_t)std::round(theta / step);
|
||||
}
|
||||
|
||||
if (theta == 2.0 * (coordf_t)PI)
|
||||
theta = 0.0;
|
||||
|
||||
m_angle_z = (float)theta;
|
||||
}
|
||||
|
||||
void GLGizmoRotate::on_render(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
const Pointf3& size = box.size();
|
||||
m_center = box.center();
|
||||
m_radius = Offset + ::sqrt(sqr(0.5f * size.x) + sqr(0.5f * size.y));
|
||||
|
||||
::glLineWidth(2.0f);
|
||||
::glColor3fv(BaseColor);
|
||||
|
||||
_render_circle();
|
||||
_render_scale();
|
||||
_render_snap_radii();
|
||||
_render_reference_radius();
|
||||
|
||||
::glColor3fv(HighlightColor);
|
||||
_render_angle_z();
|
||||
_render_grabber();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
m_grabbers[0].color[0] = 1.0f;
|
||||
m_grabbers[0].color[1] = 1.0f;
|
||||
m_grabbers[0].color[2] = 254.0f / 255.0f;
|
||||
render_grabbers();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_circle() const
|
||||
{
|
||||
::glBegin(GL_LINE_LOOP);
|
||||
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
|
||||
{
|
||||
float angle = (float)i * ScaleStepRad;
|
||||
float x = m_center.x + ::cos(angle) * m_radius;
|
||||
float y = m_center.y + ::sin(angle) * m_radius;
|
||||
::glVertex3f((GLfloat)x, (GLfloat)y, 0.0f);
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_scale() const
|
||||
{
|
||||
float out_radius_long = m_radius + ScaleLongTooth;
|
||||
float out_radius_short = m_radius + ScaleShortTooth;
|
||||
|
||||
::glBegin(GL_LINES);
|
||||
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
|
||||
{
|
||||
float angle = (float)i * ScaleStepRad;
|
||||
float cosa = ::cos(angle);
|
||||
float sina = ::sin(angle);
|
||||
float in_x = m_center.x + cosa * m_radius;
|
||||
float in_y = m_center.y + sina * m_radius;
|
||||
float out_x = (i % ScaleLongEvery == 0) ? m_center.x + cosa * out_radius_long : m_center.x + cosa * out_radius_short;
|
||||
float out_y = (i % ScaleLongEvery == 0) ? m_center.y + sina * out_radius_long : m_center.y + sina * out_radius_short;
|
||||
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, 0.0f);
|
||||
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, 0.0f);
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_snap_radii() const
|
||||
{
|
||||
float step = 2.0f * (float)PI / (float)SnapRegionsCount;
|
||||
|
||||
float in_radius = m_radius / 3.0f;
|
||||
float out_radius = 2.0f * in_radius;
|
||||
|
||||
::glBegin(GL_LINES);
|
||||
for (unsigned int i = 0; i < SnapRegionsCount; ++i)
|
||||
{
|
||||
float angle = (float)i * step;
|
||||
float cosa = ::cos(angle);
|
||||
float sina = ::sin(angle);
|
||||
float in_x = m_center.x + cosa * in_radius;
|
||||
float in_y = m_center.y + sina * in_radius;
|
||||
float out_x = m_center.x + cosa * out_radius;
|
||||
float out_y = m_center.y + sina * out_radius;
|
||||
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, 0.0f);
|
||||
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, 0.0f);
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_reference_radius() const
|
||||
{
|
||||
::glBegin(GL_LINES);
|
||||
::glVertex3f((GLfloat)m_center.x, (GLfloat)m_center.y, 0.0f);
|
||||
::glVertex3f((GLfloat)m_center.x + m_radius + GrabberOffset, (GLfloat)m_center.y, 0.0f);
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_angle_z() const
|
||||
{
|
||||
float step_angle = m_angle_z / AngleResolution;
|
||||
float ex_radius = m_radius + GrabberOffset;
|
||||
|
||||
::glBegin(GL_LINE_STRIP);
|
||||
for (unsigned int i = 0; i <= AngleResolution; ++i)
|
||||
{
|
||||
float angle = (float)i * step_angle;
|
||||
float x = m_center.x + ::cos(angle) * ex_radius;
|
||||
float y = m_center.y + ::sin(angle) * ex_radius;
|
||||
::glVertex3f((GLfloat)x, (GLfloat)y, 0.0f);
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::_render_grabber() const
|
||||
{
|
||||
float grabber_radius = m_radius + GrabberOffset;
|
||||
m_grabbers[0].center.x = m_center.x + ::cos(m_angle_z) * grabber_radius;
|
||||
m_grabbers[0].center.y = m_center.y + ::sin(m_angle_z) * grabber_radius;
|
||||
m_grabbers[0].angle_z = m_angle_z;
|
||||
|
||||
::glColor3fv(BaseColor);
|
||||
::glBegin(GL_LINES);
|
||||
::glVertex3f((GLfloat)m_center.x, (GLfloat)m_center.y, 0.0f);
|
||||
::glVertex3f((GLfloat)m_grabbers[0].center.x, (GLfloat)m_grabbers[0].center.y, 0.0f);
|
||||
::glEnd();
|
||||
|
||||
::memcpy((void*)m_grabbers[0].color, (const void*)HighlightColor, 3 * sizeof(float));
|
||||
render_grabbers();
|
||||
}
|
||||
|
||||
const float GLGizmoScale::Offset = 5.0f;
|
||||
|
||||
GLGizmoScale::GLGizmoScale()
|
||||
: GLGizmoBase()
|
||||
, m_scale(1.0f)
|
||||
, m_starting_scale(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
float GLGizmoScale::get_scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
void GLGizmoScale::set_scale(float scale)
|
||||
{
|
||||
m_starting_scale = scale;
|
||||
}
|
||||
|
||||
bool GLGizmoScale::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
std::string filename = path + "scale_off.png";
|
||||
if (!m_textures[Off].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
filename = path + "scale_hover.png";
|
||||
if (!m_textures[Hover].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
filename = path + "scale_on.png";
|
||||
if (!m_textures[On].load_from_file(filename, false))
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
m_grabbers.push_back(Grabber());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLGizmoScale::on_start_dragging()
|
||||
{
|
||||
if (m_hover_id != -1)
|
||||
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
||||
}
|
||||
|
||||
void GLGizmoScale::on_update(const Pointf& mouse_pos)
|
||||
{
|
||||
Pointf center(0.5 * (m_grabbers[1].center.x + m_grabbers[0].center.x), 0.5 * (m_grabbers[3].center.y + m_grabbers[0].center.y));
|
||||
|
||||
coordf_t orig_len = length(m_starting_drag_position - center);
|
||||
coordf_t new_len = length(mouse_pos - center);
|
||||
coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0;
|
||||
|
||||
m_scale = m_starting_scale * (float)ratio;
|
||||
}
|
||||
|
||||
void GLGizmoScale::on_render(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
coordf_t min_x = box.min.x - (coordf_t)Offset;
|
||||
coordf_t max_x = box.max.x + (coordf_t)Offset;
|
||||
coordf_t min_y = box.min.y - (coordf_t)Offset;
|
||||
coordf_t max_y = box.max.y + (coordf_t)Offset;
|
||||
|
||||
m_grabbers[0].center.x = min_x;
|
||||
m_grabbers[0].center.y = min_y;
|
||||
m_grabbers[1].center.x = max_x;
|
||||
m_grabbers[1].center.y = min_y;
|
||||
m_grabbers[2].center.x = max_x;
|
||||
m_grabbers[2].center.y = max_y;
|
||||
m_grabbers[3].center.x = min_x;
|
||||
m_grabbers[3].center.y = max_y;
|
||||
|
||||
::glLineWidth(2.0f);
|
||||
::glColor3fv(BaseColor);
|
||||
// draw outline
|
||||
::glBegin(GL_LINE_LOOP);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
::glVertex3f((GLfloat)m_grabbers[i].center.x, (GLfloat)m_grabbers[i].center.y, 0.0f);
|
||||
}
|
||||
::glEnd();
|
||||
|
||||
// draw grabbers
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
::memcpy((void*)m_grabbers[i].color, (const void*)HighlightColor, 3 * sizeof(float));
|
||||
}
|
||||
render_grabbers();
|
||||
}
|
||||
|
||||
void GLGizmoScale::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
static const GLfloat INV_255 = 1.0f / 255.0f;
|
||||
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
m_grabbers[i].color[0] = 1.0f;
|
||||
m_grabbers[i].color[1] = 1.0f;
|
||||
m_grabbers[i].color[2] = (254.0f - (float)i) * INV_255;
|
||||
}
|
||||
render_grabbers();
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
145
xs/src/slic3r/GUI/GLGizmo.hpp
Normal file
145
xs/src/slic3r/GUI/GLGizmo.hpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#ifndef slic3r_GLGizmo_hpp_
|
||||
#define slic3r_GLGizmo_hpp_
|
||||
|
||||
#include "../../slic3r/GUI/GLTexture.hpp"
|
||||
#include "../../libslic3r/Point.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class BoundingBoxf3;
|
||||
class Pointf3;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class GLGizmoBase
|
||||
{
|
||||
protected:
|
||||
static const float BaseColor[3];
|
||||
static const float HighlightColor[3];
|
||||
|
||||
struct Grabber
|
||||
{
|
||||
static const float HalfSize;
|
||||
static const float HoverOffset;
|
||||
|
||||
Pointf center;
|
||||
float angle_z;
|
||||
float color[3];
|
||||
|
||||
Grabber();
|
||||
void render(bool hover) const;
|
||||
};
|
||||
|
||||
public:
|
||||
enum EState
|
||||
{
|
||||
Off,
|
||||
Hover,
|
||||
On,
|
||||
Num_States
|
||||
};
|
||||
|
||||
protected:
|
||||
EState m_state;
|
||||
// textures are assumed to be square and all with the same size in pixels, no internal check is done
|
||||
GLTexture m_textures[Num_States];
|
||||
int m_hover_id;
|
||||
mutable std::vector<Grabber> m_grabbers;
|
||||
|
||||
public:
|
||||
GLGizmoBase();
|
||||
virtual ~GLGizmoBase();
|
||||
|
||||
bool init();
|
||||
|
||||
EState get_state() const;
|
||||
void set_state(EState state);
|
||||
|
||||
unsigned int get_textures_id() const;
|
||||
int get_textures_size() const;
|
||||
|
||||
int get_hover_id() const;
|
||||
void set_hover_id(int id);
|
||||
|
||||
void start_dragging();
|
||||
void update(const Pointf& mouse_pos);
|
||||
|
||||
void render(const BoundingBoxf3& box) const;
|
||||
void render_for_picking(const BoundingBoxf3& box) const;
|
||||
|
||||
protected:
|
||||
virtual bool on_init() = 0;
|
||||
virtual void on_start_dragging();
|
||||
virtual void on_update(const Pointf& mouse_pos) = 0;
|
||||
virtual void on_render(const BoundingBoxf3& box) const = 0;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0;
|
||||
|
||||
void render_grabbers() const;
|
||||
};
|
||||
|
||||
class GLGizmoRotate : public GLGizmoBase
|
||||
{
|
||||
static const float Offset;
|
||||
static const unsigned int CircleResolution;
|
||||
static const unsigned int AngleResolution;
|
||||
static const unsigned int ScaleStepsCount;
|
||||
static const float ScaleStepRad;
|
||||
static const unsigned int ScaleLongEvery;
|
||||
static const float ScaleLongTooth;
|
||||
static const float ScaleShortTooth;
|
||||
static const unsigned int SnapRegionsCount;
|
||||
static const float GrabberOffset;
|
||||
|
||||
float m_angle_z;
|
||||
|
||||
mutable Pointf m_center;
|
||||
mutable float m_radius;
|
||||
|
||||
public:
|
||||
GLGizmoRotate();
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
virtual void on_update(const Pointf& mouse_pos);
|
||||
virtual void on_render(const BoundingBoxf3& box) const;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||
|
||||
private:
|
||||
void _render_circle() const;
|
||||
void _render_scale() const;
|
||||
void _render_snap_radii() const;
|
||||
void _render_reference_radius() const;
|
||||
void _render_angle_z() const;
|
||||
void _render_grabber() const;
|
||||
};
|
||||
|
||||
class GLGizmoScale : public GLGizmoBase
|
||||
{
|
||||
static const float Offset;
|
||||
|
||||
float m_scale;
|
||||
|
||||
Pointf m_starting_drag_position;
|
||||
float m_starting_scale;
|
||||
|
||||
public:
|
||||
GLGizmoScale();
|
||||
|
||||
float get_scale() const;
|
||||
void set_scale(float scale);
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
virtual void on_start_dragging();
|
||||
virtual void on_update(const Pointf& mouse_pos);
|
||||
virtual void on_render(const BoundingBoxf3& box) const;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLGizmo_hpp_
|
||||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include "GLShader.hpp"
|
||||
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <assert.h>
|
||||
|
@ -22,7 +25,7 @@ inline std::string gl_get_string_safe(GLenum param)
|
|||
return std::string(value ? value : "N/A");
|
||||
}
|
||||
|
||||
bool GLShader::load(const char *fragment_shader, const char *vertex_shader)
|
||||
bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_shader)
|
||||
{
|
||||
std::string gl_version = gl_get_string_safe(GL_VERSION);
|
||||
int major = atoi(gl_version.c_str());
|
||||
|
@ -123,6 +126,41 @@ bool GLShader::load(const char *fragment_shader, const char *vertex_shader)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GLShader::load_from_file(const char* fragment_shader_filename, const char* vertex_shader_filename)
|
||||
{
|
||||
const std::string& path = resources_dir() + "/shaders/";
|
||||
|
||||
boost::nowide::ifstream vs(path + std::string(vertex_shader_filename), boost::nowide::ifstream::binary);
|
||||
if (!vs.good())
|
||||
return false;
|
||||
|
||||
vs.seekg(0, vs.end);
|
||||
int file_length = vs.tellg();
|
||||
vs.seekg(0, vs.beg);
|
||||
std::string vertex_shader(file_length, '\0');
|
||||
vs.read(const_cast<char*>(vertex_shader.data()), file_length);
|
||||
if (!vs.good())
|
||||
return false;
|
||||
|
||||
vs.close();
|
||||
|
||||
boost::nowide::ifstream fs(path + std::string(fragment_shader_filename), boost::nowide::ifstream::binary);
|
||||
if (!fs.good())
|
||||
return false;
|
||||
|
||||
fs.seekg(0, fs.end);
|
||||
file_length = fs.tellg();
|
||||
fs.seekg(0, fs.beg);
|
||||
std::string fragment_shader(file_length, '\0');
|
||||
fs.read(const_cast<char*>(fragment_shader.data()), file_length);
|
||||
if (!fs.good())
|
||||
return false;
|
||||
|
||||
fs.close();
|
||||
|
||||
return load_from_text(fragment_shader.c_str(), vertex_shader.c_str());
|
||||
}
|
||||
|
||||
void GLShader::release()
|
||||
{
|
||||
if (this->shader_program_id) {
|
||||
|
|
|
@ -16,7 +16,9 @@ public:
|
|||
{}
|
||||
~GLShader();
|
||||
|
||||
bool load(const char *fragment_shader, const char *vertex_shader);
|
||||
bool load_from_text(const char *fragment_shader, const char *vertex_shader);
|
||||
bool load_from_file(const char* fragment_shader_filename, const char* vertex_shader_filename);
|
||||
|
||||
void release();
|
||||
|
||||
int get_attrib_location(const char *name) const;
|
||||
|
|
185
xs/src/slic3r/GUI/GLTexture.cpp
Normal file
185
xs/src/slic3r/GUI/GLTexture.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include "GLTexture.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <wx/image.h>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
GLTexture::GLTexture()
|
||||
: m_id(0)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_source("")
|
||||
{
|
||||
}
|
||||
|
||||
GLTexture::~GLTexture()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmaps)
|
||||
{
|
||||
reset();
|
||||
|
||||
// Load a PNG with an alpha channel.
|
||||
wxImage image;
|
||||
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_width = image.GetWidth();
|
||||
m_height = image.GetHeight();
|
||||
int n_pixels = m_width * m_height;
|
||||
|
||||
if (n_pixels <= 0)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get RGB & alpha raw data from wxImage, pack them into an array.
|
||||
unsigned char* img_rgb = image.GetData();
|
||||
if (img_rgb == nullptr)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char* img_alpha = image.GetAlpha();
|
||||
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
for (int i = 0; i < n_pixels; ++i)
|
||||
{
|
||||
int data_id = i * 4;
|
||||
int img_id = i * 3;
|
||||
data[data_id + 0] = img_rgb[img_id + 0];
|
||||
data[data_id + 1] = img_rgb[img_id + 1];
|
||||
data[data_id + 2] = img_rgb[img_id + 2];
|
||||
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
|
||||
}
|
||||
|
||||
// sends data to gpu
|
||||
::glGenTextures(1, &m_id);
|
||||
::glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
if (generate_mipmaps)
|
||||
{
|
||||
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
|
||||
_generate_mipmaps(image);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
}
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
m_source = filename;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLTexture::reset()
|
||||
{
|
||||
if (m_id != 0)
|
||||
::glDeleteTextures(1, &m_id);
|
||||
|
||||
m_id = 0;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_source = "";
|
||||
}
|
||||
|
||||
unsigned int GLTexture::get_id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
int GLTexture::get_width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
int GLTexture::get_height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
const std::string& GLTexture::get_source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top)
|
||||
{
|
||||
::glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glEnable(GL_BLEND);
|
||||
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
::glEnable(GL_TEXTURE_2D);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id);
|
||||
|
||||
::glBegin(GL_QUADS);
|
||||
::glTexCoord2d(0.0f, 1.0f); ::glVertex3f(left, bottom, 0.0f);
|
||||
::glTexCoord2d(1.0f, 1.0f); ::glVertex3f(right, bottom, 0.0f);
|
||||
::glTexCoord2d(1.0f, 0.0f); ::glVertex3f(right, top, 0.0f);
|
||||
::glTexCoord2d(0.0f, 0.0f); ::glVertex3f(left, top, 0.0f);
|
||||
::glEnd();
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
::glDisable(GL_TEXTURE_2D);
|
||||
::glDisable(GL_BLEND);
|
||||
::glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void GLTexture::_generate_mipmaps(wxImage& image)
|
||||
{
|
||||
int w = image.GetWidth();
|
||||
int h = image.GetHeight();
|
||||
GLint level = 0;
|
||||
std::vector<unsigned char> data(w * h * 4, 0);
|
||||
|
||||
while ((w > 1) && (h > 1))
|
||||
{
|
||||
++level;
|
||||
|
||||
w = std::max(w / 2, 1);
|
||||
h = std::max(h / 2, 1);
|
||||
|
||||
int n_pixels = w * h;
|
||||
|
||||
image = image.ResampleBicubic(w, h);
|
||||
|
||||
unsigned char* img_rgb = image.GetData();
|
||||
unsigned char* img_alpha = image.GetAlpha();
|
||||
|
||||
data.resize(n_pixels * 4);
|
||||
for (int i = 0; i < n_pixels; ++i)
|
||||
{
|
||||
int data_id = i * 4;
|
||||
int img_id = i * 3;
|
||||
data[data_id + 0] = img_rgb[img_id + 0];
|
||||
data[data_id + 1] = img_rgb[img_id + 1];
|
||||
data[data_id + 2] = img_rgb[img_id + 2];
|
||||
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
|
||||
}
|
||||
|
||||
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
41
xs/src/slic3r/GUI/GLTexture.hpp
Normal file
41
xs/src/slic3r/GUI/GLTexture.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef slic3r_GLTexture_hpp_
|
||||
#define slic3r_GLTexture_hpp_
|
||||
|
||||
#include <string>
|
||||
|
||||
class wxImage;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class GLTexture
|
||||
{
|
||||
private:
|
||||
unsigned int m_id;
|
||||
int m_width;
|
||||
int m_height;
|
||||
std::string m_source;
|
||||
|
||||
public:
|
||||
GLTexture();
|
||||
~GLTexture();
|
||||
|
||||
bool load_from_file(const std::string& filename, bool generate_mipmaps);
|
||||
void reset();
|
||||
|
||||
unsigned int get_id() const;
|
||||
int get_width() const;
|
||||
int get_height() const;
|
||||
const std::string& get_source() const;
|
||||
|
||||
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
|
||||
|
||||
private:
|
||||
void _generate_mipmaps(wxImage& image);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLTexture_hpp_
|
||||
|
|
@ -423,7 +423,7 @@ bool check_unsaved_changes()
|
|||
|
||||
bool config_wizard_startup(bool app_config_exists)
|
||||
{
|
||||
if (! app_config_exists || g_PresetBundle->has_defauls_only()) {
|
||||
if (! app_config_exists || g_PresetBundle->printers.size() <= 1) {
|
||||
config_wizard(ConfigWizard::RR_DATA_EMPTY);
|
||||
return true;
|
||||
} else if (g_AppConfig->legacy_datadir()) {
|
||||
|
|
402
xs/src/slic3r/Utils/FixModelByWin10.cpp
Normal file
402
xs/src/slic3r/Utils/FixModelByWin10.cpp
Normal file
|
@ -0,0 +1,402 @@
|
|||
#ifdef HAS_WIN10SDK
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "FixModelByWin10.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include <roapi.h>
|
||||
// for ComPtr
|
||||
#include <wrl/client.h>
|
||||
// from C:/Program Files (x86)/Windows Kits/10/Include/10.0.17134.0/
|
||||
#include <winrt/robuffer.h>
|
||||
#include <winrt/windows.storage.provider.h>
|
||||
#include <winrt/windows.graphics.printing3d.h>
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
#include "../GUI/GUI.hpp"
|
||||
#include "../GUI/PresetBundle.hpp"
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/progdlg.h>
|
||||
|
||||
extern "C"{
|
||||
// from rapi.h
|
||||
typedef HRESULT (__stdcall* FunctionRoInitialize)(int);
|
||||
typedef HRESULT (__stdcall* FunctionRoUninitialize)();
|
||||
typedef HRESULT (__stdcall* FunctionRoActivateInstance)(HSTRING activatableClassId, IInspectable **instance);
|
||||
typedef HRESULT (__stdcall* FunctionRoGetActivationFactory)(HSTRING activatableClassId, REFIID iid, void **factory);
|
||||
// from winstring.h
|
||||
typedef HRESULT (__stdcall* FunctionWindowsCreateString)(LPCWSTR sourceString, UINT32 length, HSTRING *string);
|
||||
typedef HRESULT (__stdcall* FunctionWindowsDelteString)(HSTRING string);
|
||||
}
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
HMODULE s_hRuntimeObjectLibrary = nullptr;
|
||||
FunctionRoInitialize s_RoInitialize = nullptr;
|
||||
FunctionRoUninitialize s_RoUninitialize = nullptr;
|
||||
FunctionRoActivateInstance s_RoActivateInstance = nullptr;
|
||||
FunctionRoGetActivationFactory s_RoGetActivationFactory = nullptr;
|
||||
FunctionWindowsCreateString s_WindowsCreateString = nullptr;
|
||||
FunctionWindowsDelteString s_WindowsDeleteString = nullptr;
|
||||
|
||||
bool winrt_load_runtime_object_library()
|
||||
{
|
||||
if (s_hRuntimeObjectLibrary == nullptr)
|
||||
s_hRuntimeObjectLibrary = LoadLibrary(L"ComBase.dll");
|
||||
if (s_hRuntimeObjectLibrary != nullptr) {
|
||||
s_RoInitialize = (FunctionRoInitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoInitialize");
|
||||
s_RoUninitialize = (FunctionRoUninitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoUninitialize");
|
||||
s_RoActivateInstance = (FunctionRoActivateInstance) GetProcAddress(s_hRuntimeObjectLibrary, "RoActivateInstance");
|
||||
s_RoGetActivationFactory = (FunctionRoGetActivationFactory) GetProcAddress(s_hRuntimeObjectLibrary, "RoGetActivationFactory");
|
||||
s_WindowsCreateString = (FunctionWindowsCreateString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsCreateString");
|
||||
s_WindowsDeleteString = (FunctionWindowsDelteString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsDeleteString");
|
||||
}
|
||||
return s_RoInitialize && s_RoUninitialize && s_RoActivateInstance && s_WindowsCreateString && s_WindowsDeleteString;
|
||||
}
|
||||
|
||||
static HRESULT winrt_activate_instance(const std::wstring &class_name, IInspectable **pinst)
|
||||
{
|
||||
HSTRING hClassName;
|
||||
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
||||
if (S_OK != hr)
|
||||
return hr;
|
||||
hr = (*s_RoActivateInstance)(hClassName, pinst);
|
||||
(*s_WindowsDeleteString)(hClassName);
|
||||
return hr;
|
||||
}
|
||||
|
||||
template<typename TYPE>
|
||||
static HRESULT winrt_activate_instance(const std::wstring &class_name, TYPE **pinst)
|
||||
{
|
||||
IInspectable *pinspectable = nullptr;
|
||||
HRESULT hr = winrt_activate_instance(class_name, &pinspectable);
|
||||
if (S_OK != hr)
|
||||
return hr;
|
||||
hr = pinspectable->QueryInterface(__uuidof(TYPE), (void**)pinst);
|
||||
pinspectable->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, REFIID iid, void **pinst)
|
||||
{
|
||||
HSTRING hClassName;
|
||||
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
||||
if (S_OK != hr)
|
||||
return hr;
|
||||
hr = (*s_RoGetActivationFactory)(hClassName, iid, pinst);
|
||||
(*s_WindowsDeleteString)(hClassName);
|
||||
return hr;
|
||||
}
|
||||
|
||||
template<typename TYPE>
|
||||
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, TYPE **pinst)
|
||||
{
|
||||
return winrt_get_activation_factory(class_name, __uuidof(TYPE), reinterpret_cast<void**>(pinst));
|
||||
}
|
||||
|
||||
// To be called often to test whether to cancel the operation.
|
||||
typedef std::function<void ()> ThrowOnCancelFn;
|
||||
|
||||
template<typename T>
|
||||
static AsyncStatus winrt_async_await(const Microsoft::WRL::ComPtr<T> &asyncAction, ThrowOnCancelFn throw_on_cancel, int blocking_tick_ms = 100)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
asyncAction.As(&asyncInfo);
|
||||
AsyncStatus status;
|
||||
// Ugly blocking loop until the RepairAsync call finishes.
|
||||
//FIXME replace with a callback.
|
||||
// https://social.msdn.microsoft.com/Forums/en-US/a5038fb4-b7b7-4504-969d-c102faa389fb/trying-to-block-an-async-operation-and-wait-for-a-particular-time?forum=vclanguage
|
||||
for (;;) {
|
||||
asyncInfo->get_Status(&status);
|
||||
if (status != AsyncStatus::Started)
|
||||
return status;
|
||||
throw_on_cancel();
|
||||
::Sleep(blocking_tick_ms);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT winrt_open_file_stream(
|
||||
const std::wstring &path,
|
||||
ABI::Windows::Storage::FileAccessMode mode,
|
||||
ABI::Windows::Storage::Streams::IRandomAccessStream **fileStream,
|
||||
ThrowOnCancelFn throw_on_cancel)
|
||||
{
|
||||
// Get the file factory.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFileStatics> fileFactory;
|
||||
HRESULT hr = winrt_get_activation_factory(L"Windows.Storage.StorageFile", fileFactory.GetAddressOf());
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
// Open the file asynchronously.
|
||||
HSTRING hstr_path;
|
||||
hr = (*s_WindowsCreateString)(path.c_str(), path.size(), &hstr_path);
|
||||
if (FAILED(hr)) return hr;
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFile*>> fileOpenAsync;
|
||||
hr = fileFactory->GetFileFromPathAsync(hstr_path, fileOpenAsync.GetAddressOf());
|
||||
if (FAILED(hr)) return hr;
|
||||
(*s_WindowsDeleteString)(hstr_path);
|
||||
|
||||
// Wait until the file gets open, get the actual file.
|
||||
AsyncStatus status = winrt_async_await(fileOpenAsync, throw_on_cancel);
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFile> storageFile;
|
||||
if (status == AsyncStatus::Completed) {
|
||||
hr = fileOpenAsync->GetResults(storageFile.GetAddressOf());
|
||||
} else {
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
hr = fileOpenAsync.As(&asyncInfo);
|
||||
if (FAILED(hr)) return hr;
|
||||
HRESULT err;
|
||||
hr = asyncInfo->get_ErrorCode(&err);
|
||||
return FAILED(hr) ? hr : err;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> fileStreamAsync;
|
||||
hr = storageFile->OpenAsync(mode, fileStreamAsync.GetAddressOf());
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
status = winrt_async_await(fileStreamAsync, throw_on_cancel);
|
||||
if (status == AsyncStatus::Completed) {
|
||||
hr = fileStreamAsync->GetResults(fileStream);
|
||||
} else {
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
hr = fileStreamAsync.As(&asyncInfo);
|
||||
if (FAILED(hr)) return hr;
|
||||
HRESULT err;
|
||||
hr = asyncInfo->get_ErrorCode(&err);
|
||||
if (!FAILED(hr))
|
||||
hr = err;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool is_windows10()
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
|
||||
if (lRes == ERROR_SUCCESS) {
|
||||
WCHAR szBuffer[512];
|
||||
DWORD dwBufferSize = sizeof(szBuffer);
|
||||
lRes = RegQueryValueExW(hKey, L"ProductName", 0, nullptr, (LPBYTE)szBuffer, &dwBufferSize);
|
||||
if (lRes == ERROR_SUCCESS)
|
||||
return wcsncmp(szBuffer, L"Windows 10", 10) == 0;
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Progress function, to be called regularly to update the progress.
|
||||
typedef std::function<void (const char * /* message */, unsigned /* progress */)> ProgressFn;
|
||||
|
||||
void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path_dst, ProgressFn on_progress, ThrowOnCancelFn throw_on_cancel)
|
||||
{
|
||||
if (! is_windows10())
|
||||
throw std::runtime_error("fix_model_by_win10_sdk called on non Windows 10 system");
|
||||
|
||||
if (! winrt_load_runtime_object_library())
|
||||
throw std::runtime_error("Failed to initialize the WinRT library.");
|
||||
|
||||
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
|
||||
{
|
||||
on_progress(L("Exporting the source model"), 20);
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> fileStream;
|
||||
hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel);
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3D3MFPackage> printing3d3mfpackage;
|
||||
hr = winrt_activate_instance(L"Windows.Graphics.Printing3D.Printing3D3MFPackage", printing3d3mfpackage.GetAddressOf());
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Graphics::Printing3D::Printing3DModel*>> modelAsync;
|
||||
hr = printing3d3mfpackage->LoadModelFromPackageAsync(fileStream.Get(), modelAsync.GetAddressOf());
|
||||
|
||||
AsyncStatus status = winrt_async_await(modelAsync, throw_on_cancel);
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3DModel> model;
|
||||
if (status == AsyncStatus::Completed)
|
||||
hr = modelAsync->GetResults(model.GetAddressOf());
|
||||
else
|
||||
throw std::runtime_error(L("Failed loading the input model."));
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::Graphics::Printing3D::Printing3DMesh*>> meshes;
|
||||
hr = model->get_Meshes(meshes.GetAddressOf());
|
||||
unsigned num_meshes = 0;
|
||||
hr = meshes->get_Size(&num_meshes);
|
||||
|
||||
on_progress(L("Repairing the model by the Netfabb service"), 40);
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> repairAsync;
|
||||
hr = model->RepairAsync(repairAsync.GetAddressOf());
|
||||
status = winrt_async_await(repairAsync, throw_on_cancel);
|
||||
if (status != AsyncStatus::Completed)
|
||||
throw std::runtime_error(L("Mesh repair failed."));
|
||||
repairAsync->GetResults();
|
||||
|
||||
on_progress(L("Loading the repaired model"), 60);
|
||||
|
||||
// Verify the number of meshes returned after the repair action.
|
||||
meshes.Reset();
|
||||
hr = model->get_Meshes(meshes.GetAddressOf());
|
||||
hr = meshes->get_Size(&num_meshes);
|
||||
|
||||
// Save model to this class' Printing3D3MFPackage.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> saveToPackageAsync;
|
||||
hr = printing3d3mfpackage->SaveModelToPackageAsync(model.Get(), saveToPackageAsync.GetAddressOf());
|
||||
status = winrt_async_await(saveToPackageAsync, throw_on_cancel);
|
||||
if (status != AsyncStatus::Completed)
|
||||
throw std::runtime_error(L("Saving mesh into the 3MF container failed."));
|
||||
hr = saveToPackageAsync->GetResults();
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> generatorStreamAsync;
|
||||
hr = printing3d3mfpackage->SaveAsync(generatorStreamAsync.GetAddressOf());
|
||||
status = winrt_async_await(generatorStreamAsync, throw_on_cancel);
|
||||
if (status != AsyncStatus::Completed)
|
||||
throw std::runtime_error(L("Saving mesh into the 3MF container failed."));
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> generatorStream;
|
||||
hr = generatorStreamAsync->GetResults(generatorStream.GetAddressOf());
|
||||
|
||||
// Go to the beginning of the stream.
|
||||
generatorStream->Seek(0);
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IInputStream> inputStream;
|
||||
hr = generatorStream.As(&inputStream);
|
||||
|
||||
// Get the buffer factory.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBufferFactory> bufferFactory;
|
||||
hr = winrt_get_activation_factory(L"Windows.Storage.Streams.Buffer", bufferFactory.GetAddressOf());
|
||||
|
||||
// Open the destination file.
|
||||
FILE *fout = boost::nowide::fopen(path_dst.c_str(), "wb");
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
|
||||
byte *buffer_ptr;
|
||||
bufferFactory->Create(65536 * 2048, buffer.GetAddressOf());
|
||||
{
|
||||
Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
|
||||
buffer.As(&bufferByteAccess);
|
||||
hr = bufferByteAccess->Buffer(&buffer_ptr);
|
||||
}
|
||||
uint32_t length;
|
||||
hr = buffer->get_Length(&length);
|
||||
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer*, UINT32>> asyncRead;
|
||||
for (;;) {
|
||||
hr = inputStream->ReadAsync(buffer.Get(), 65536 * 2048, ABI::Windows::Storage::Streams::InputStreamOptions_ReadAhead, asyncRead.GetAddressOf());
|
||||
status = winrt_async_await(asyncRead, throw_on_cancel);
|
||||
if (status != AsyncStatus::Completed)
|
||||
throw std::runtime_error(L("Saving mesh into the 3MF container failed."));
|
||||
hr = buffer->get_Length(&length);
|
||||
if (length == 0)
|
||||
break;
|
||||
fwrite(buffer_ptr, length, 1, fout);
|
||||
}
|
||||
fclose(fout);
|
||||
// Here all the COM objects will be released through the ComPtr destructors.
|
||||
}
|
||||
(*s_RoUninitialize)();
|
||||
}
|
||||
|
||||
class RepairCanceledException : public std::exception {
|
||||
public:
|
||||
const char* what() const throw() { return "Model repair has been canceled"; }
|
||||
};
|
||||
|
||||
void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result)
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
struct Progress {
|
||||
std::string message;
|
||||
int percent = 0;
|
||||
bool updated = false;
|
||||
} progress;
|
||||
std::atomic<bool> canceled = false;
|
||||
std::atomic<bool> finished = false;
|
||||
|
||||
// Open a progress dialog.
|
||||
wxProgressDialog progress_dialog(
|
||||
_(L("Model fixing")),
|
||||
_(L("Exporting model...")),
|
||||
100, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
|
||||
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
|
||||
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
|
||||
bool success = false;
|
||||
auto on_progress = [&mutex, &condition, &progress](const char *msg, unsigned prcnt) {
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
progress.message = msg;
|
||||
progress.percent = prcnt;
|
||||
progress.updated = true;
|
||||
condition.notify_all();
|
||||
};
|
||||
auto worker_thread = boost::thread([&model_object, &print, &result, on_progress, &success, &canceled, &finished]() {
|
||||
try {
|
||||
on_progress(L("Exporting the source model"), 0);
|
||||
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||
path_src += ".3mf";
|
||||
Model model;
|
||||
model.add_object(model_object);
|
||||
if (! Slic3r::store_3mf(path_src.string().c_str(), &model, const_cast<Print*>(&print), false)) {
|
||||
boost::filesystem::remove(path_src);
|
||||
throw std::runtime_error(L("Export of a temporary 3mf file failed"));
|
||||
}
|
||||
model.clear_objects();
|
||||
model.clear_materials();
|
||||
boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||
path_dst += ".3mf";
|
||||
fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress,
|
||||
[&canceled]() { if (canceled) throw RepairCanceledException(); });
|
||||
boost::filesystem::remove(path_src);
|
||||
PresetBundle bundle;
|
||||
on_progress(L("Loading the repaired model"), 80);
|
||||
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &bundle, &result);
|
||||
boost::filesystem::remove(path_dst);
|
||||
if (! loaded)
|
||||
throw std::runtime_error(L("Import of the repaired 3mf file failed"));
|
||||
success = true;
|
||||
finished = true;
|
||||
on_progress(L("Model repair finished"), 100);
|
||||
} catch (RepairCanceledException &ex) {
|
||||
canceled = true;
|
||||
finished = true;
|
||||
on_progress(L("Model repair canceled"), 100);
|
||||
} catch (std::exception &ex) {
|
||||
success = false;
|
||||
finished = true;
|
||||
on_progress(ex.what(), 100);
|
||||
}
|
||||
});
|
||||
while (! finished) {
|
||||
condition.wait_for(lock, std::chrono::milliseconds(500), [&progress]{ return progress.updated; });
|
||||
if (! progress_dialog.Update(progress.percent, _(progress.message)))
|
||||
canceled = true;
|
||||
progress.updated = false;
|
||||
}
|
||||
|
||||
if (canceled) {
|
||||
// Nothing to show.
|
||||
} else if (success) {
|
||||
wxMessageDialog dlg(nullptr, _(L("Model repaired successfully")), _(L("Model Repair by the Netfabb service")), wxICON_INFORMATION | wxOK_DEFAULT);
|
||||
dlg.ShowModal();
|
||||
} else {
|
||||
wxMessageDialog dlg(nullptr, _(L("Model repair failed: \n")) + _(progress.message), _(L("Model Repair by the Netfabb service")), wxICON_ERROR | wxOK_DEFAULT);
|
||||
dlg.ShowModal();
|
||||
}
|
||||
worker_thread.join();
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* HAS_WIN10SDK */
|
26
xs/src/slic3r/Utils/FixModelByWin10.hpp
Normal file
26
xs/src/slic3r/Utils/FixModelByWin10.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef slic3r_GUI_Utils_FixModelByWin10_hpp_
|
||||
#define slic3r_GUI_Utils_FixModelByWin10_hpp_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Model;
|
||||
class ModelObject;
|
||||
class Print;
|
||||
|
||||
#ifdef HAS_WIN10SDK
|
||||
|
||||
extern bool is_windows10();
|
||||
extern void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result);
|
||||
|
||||
#else /* HAS_WIN10SDK */
|
||||
|
||||
inline bool is_windows10() { return false; }
|
||||
inline void fix_model_by_win10_sdk_gui(const ModelObject &, const Print &, Model &) {}
|
||||
|
||||
#endif /* HAS_WIN10SDK */
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_GUI_Utils_FixModelByWin10_hpp_ */
|
|
@ -259,7 +259,7 @@ void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors) con
|
|||
}
|
||||
const auto recommended = recommended_it->config_version;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("New index for vendor: %1%: current version: %2%, recommended version: %3%")
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Got index for vendor: %1%: current version: %2%, recommended version: %3%")
|
||||
% vendor.name
|
||||
% vendor.config_version.to_string()
|
||||
% recommended.to_string();
|
||||
|
@ -352,20 +352,25 @@ Updates PresetUpdater::priv::get_config_updates() const
|
|||
continue;
|
||||
}
|
||||
|
||||
auto path_in_cache = cache_path / (idx.vendor() + ".ini");
|
||||
if (! fs::exists(path_in_cache)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Index indicates update, but new bundle not found in cache: " << path_in_cache.string();
|
||||
continue;
|
||||
auto path_src = cache_path / (idx.vendor() + ".ini");
|
||||
if (! fs::exists(path_src)) {
|
||||
auto path_in_rsrc = rsrc_path / (idx.vendor() + ".ini");
|
||||
if (! fs::exists(path_in_rsrc)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update, but bundle found in neither cache nor resources")
|
||||
% idx.vendor();;
|
||||
continue;
|
||||
} else {
|
||||
path_src = std::move(path_in_rsrc);
|
||||
}
|
||||
}
|
||||
|
||||
const auto cached_vp = VendorProfile::from_ini(path_in_cache, false);
|
||||
if (cached_vp.config_version == recommended->config_version) {
|
||||
updates.updates.emplace_back(std::move(path_in_cache), std::move(bundle_path), *recommended);
|
||||
const auto new_vp = VendorProfile::from_ini(path_src, false);
|
||||
if (new_vp.config_version == recommended->config_version) {
|
||||
updates.updates.emplace_back(std::move(path_src), std::move(bundle_path), *recommended);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Vendor: %1%: Index indicates update (%2%) but cached bundle has a different version: %3%")
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources")
|
||||
% idx.vendor()
|
||||
% recommended->config_version.to_string()
|
||||
% cached_vp.config_version.to_string();
|
||||
% recommended->config_version.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <xsinit.h>
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/Utils/ASCIIFolding.hpp"
|
||||
#include "slic3r/Utils/FixModelByWin10.hpp"
|
||||
#include "slic3r/Utils/Serial.hpp"
|
||||
%}
|
||||
|
||||
|
@ -28,6 +29,9 @@ bool debugged()
|
|||
void break_to_debugger()
|
||||
%code{% Slic3r::GUI::break_to_debugger(); %};
|
||||
|
||||
bool is_windows10()
|
||||
%code{% RETVAL=Slic3r::is_windows10(); %};
|
||||
|
||||
void set_wxapp(SV *ui)
|
||||
%code%{ Slic3r::GUI::set_wxapp((wxApp*)wxPli_sv_2_object(aTHX_ ui, "Wx::App")); %};
|
||||
|
||||
|
@ -94,3 +98,6 @@ int get_export_option(SV *ui)
|
|||
|
||||
void desktop_open_datadir_folder()
|
||||
%code%{ Slic3r::GUI::desktop_open_datadir_folder(); %};
|
||||
|
||||
void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst)
|
||||
%code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %};
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
GLShader();
|
||||
~GLShader();
|
||||
|
||||
bool load(const char *fragment_shader, const char *vertex_shader);
|
||||
bool load_from_text(const char *fragment_shader, const char *vertex_shader);
|
||||
bool load_from_file(const char *fragment_shader, const char *vertex_shader);
|
||||
void release();
|
||||
|
||||
int get_attrib_location(const char *name) const;
|
||||
|
@ -92,9 +93,6 @@
|
|||
int count()
|
||||
%code{% RETVAL = THIS->volumes.size(); %};
|
||||
|
||||
std::vector<double> get_current_print_zs(bool active_only)
|
||||
%code{% RETVAL = THIS->get_current_print_zs(active_only); %};
|
||||
|
||||
void set_range(double low, double high);
|
||||
|
||||
void render_VBOs() const;
|
||||
|
@ -155,11 +153,457 @@ GLVolumeCollection::arrayref()
|
|||
%package{Slic3r::GUI::_3DScene};
|
||||
%{
|
||||
|
||||
std::string
|
||||
get_gl_info(format_as_html, extensions)
|
||||
bool format_as_html;
|
||||
bool extensions;
|
||||
CODE:
|
||||
RETVAL = _3DScene::get_gl_info(format_as_html, extensions);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
use_VBOs()
|
||||
CODE:
|
||||
RETVAL = _3DScene::use_VBOs();
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
add_canvas(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::add_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
remove_canvas(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::remove_canvas((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
_glew_init()
|
||||
remove_all_canvases()
|
||||
CODE:
|
||||
_3DScene::_glew_init();
|
||||
_3DScene::remove_all_canvases();
|
||||
|
||||
void
|
||||
set_active(canvas, active)
|
||||
SV *canvas;
|
||||
bool active;
|
||||
CODE:
|
||||
_3DScene::set_active((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active);
|
||||
|
||||
unsigned int
|
||||
get_volumes_count(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::get_volumes_count((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
reset_volumes(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::reset_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
deselect_volumes(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::deselect_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
select_volume(canvas, id)
|
||||
SV *canvas;
|
||||
unsigned int id;
|
||||
CODE:
|
||||
_3DScene::select_volume((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
|
||||
|
||||
void
|
||||
update_volumes_selection(canvas, selections)
|
||||
SV *canvas;
|
||||
std::vector<int> selections;
|
||||
CODE:
|
||||
_3DScene::update_volumes_selection((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections);
|
||||
|
||||
bool
|
||||
check_volumes_outside_state(canvas, config)
|
||||
SV *canvas;
|
||||
DynamicPrintConfig *config;
|
||||
CODE:
|
||||
RETVAL = _3DScene::check_volumes_outside_state((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), config);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
move_volume_up(canvas, id)
|
||||
SV *canvas;
|
||||
unsigned int id;
|
||||
CODE:
|
||||
RETVAL = _3DScene::move_volume_up((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
move_volume_down(canvas, id)
|
||||
SV *canvas;
|
||||
unsigned int id;
|
||||
CODE:
|
||||
RETVAL = _3DScene::move_volume_down((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), id);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
set_objects_selections(canvas, selections)
|
||||
SV *canvas;
|
||||
std::vector<int> selections;
|
||||
CODE:
|
||||
_3DScene::set_objects_selections((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), selections);
|
||||
|
||||
void
|
||||
set_config(canvas, config)
|
||||
SV *canvas;
|
||||
DynamicPrintConfig *config;
|
||||
CODE:
|
||||
_3DScene::set_config((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), config);
|
||||
|
||||
void
|
||||
set_print(canvas, print)
|
||||
SV *canvas;
|
||||
Print *print;
|
||||
CODE:
|
||||
_3DScene::set_print((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print);
|
||||
|
||||
void
|
||||
set_model(canvas, model)
|
||||
SV *canvas;
|
||||
Model *model;
|
||||
CODE:
|
||||
_3DScene::set_model((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model);
|
||||
|
||||
void
|
||||
set_bed_shape(canvas, shape)
|
||||
SV *canvas;
|
||||
Pointfs shape;
|
||||
CODE:
|
||||
_3DScene::set_bed_shape((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), shape);
|
||||
|
||||
void
|
||||
set_auto_bed_shape(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::set_auto_bed_shape((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
Clone<BoundingBoxf3>
|
||||
get_volumes_bounding_box(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::get_volumes_bounding_box((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
set_axes_length(canvas, length)
|
||||
SV *canvas;
|
||||
float length;
|
||||
CODE:
|
||||
_3DScene::set_axes_length((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), length);
|
||||
|
||||
void
|
||||
set_cutting_plane(canvas, z, polygons)
|
||||
SV *canvas;
|
||||
float z;
|
||||
ExPolygons polygons;
|
||||
CODE:
|
||||
_3DScene::set_cutting_plane((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), z, polygons);
|
||||
|
||||
void
|
||||
set_color_by(canvas, value)
|
||||
SV *canvas;
|
||||
std::string value;
|
||||
CODE:
|
||||
_3DScene::set_color_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
|
||||
|
||||
void
|
||||
set_select_by(canvas, value)
|
||||
SV *canvas;
|
||||
std::string value;
|
||||
CODE:
|
||||
_3DScene::set_select_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
|
||||
|
||||
void
|
||||
set_drag_by(canvas, value)
|
||||
SV *canvas;
|
||||
std::string value;
|
||||
CODE:
|
||||
_3DScene::set_drag_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value);
|
||||
|
||||
bool
|
||||
is_layers_editing_enabled(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::is_layers_editing_enabled((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
is_layers_editing_allowed(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::is_layers_editing_allowed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
is_shader_enabled(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::is_shader_enabled((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
bool
|
||||
is_reload_delayed(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
RETVAL = _3DScene::is_reload_delayed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
enable_layers_editing(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_layers_editing((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_warning_texture(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_warning_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_legend_texture(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_legend_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_picking(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_picking((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_moving(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_moving((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_gizmos(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_gizmos((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_shader(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_shader((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_force_zoom_to_bed(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_force_zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
allow_multisample(canvas, allow)
|
||||
SV *canvas;
|
||||
bool allow;
|
||||
CODE:
|
||||
_3DScene::allow_multisample((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), allow);
|
||||
|
||||
void
|
||||
zoom_to_bed(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
zoom_to_volumes(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::zoom_to_volumes((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
select_view(canvas, direction)
|
||||
SV *canvas;
|
||||
std::string direction;
|
||||
CODE:
|
||||
_3DScene::select_view((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), direction);
|
||||
|
||||
void
|
||||
set_viewport_from_scene(canvas, other)
|
||||
SV *canvas;
|
||||
SV *other;
|
||||
CODE:
|
||||
_3DScene::set_viewport_from_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (wxGLCanvas*)wxPli_sv_2_object(aTHX_ other, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
update_volumes_colors_by_extruder(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::update_volumes_colors_by_extruder((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
render(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::render((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
std::vector<double>
|
||||
get_current_print_zs(canvas, active_only)
|
||||
SV *canvas;
|
||||
bool active_only;
|
||||
CODE:
|
||||
RETVAL = _3DScene::get_current_print_zs((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), active_only);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
set_toolpaths_range(canvas, low, high)
|
||||
SV *canvas;
|
||||
double low;
|
||||
double high;
|
||||
CODE:
|
||||
_3DScene::set_toolpaths_range((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), low, high);
|
||||
|
||||
void
|
||||
register_on_viewport_changed_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_viewport_changed_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_double_click_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_double_click_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_right_click_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_right_click_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_select_object_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_select_object_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_model_update_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_model_update_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_remove_object_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_remove_object_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_arrange_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_arrange_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_rotate_object_left_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_rotate_object_left_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_rotate_object_right_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_rotate_object_right_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_scale_object_uniformly_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_scale_object_uniformly_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_increase_objects_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_increase_objects_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_decrease_objects_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_decrease_objects_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_instance_moved_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_instance_moved_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_wipe_tower_moved_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_wipe_tower_moved_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_enable_action_buttons_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_enable_action_buttons_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
void
|
||||
register_on_gizmo_scale_uniformly_callback(canvas, callback)
|
||||
SV *canvas;
|
||||
SV *callback;
|
||||
CODE:
|
||||
_3DScene::register_on_gizmo_scale_uniformly_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
|
||||
|
||||
unsigned int
|
||||
finalize_legend_texture()
|
||||
|
@ -218,41 +662,61 @@ reset_warning_texture()
|
|||
CODE:
|
||||
_3DScene::reset_warning_texture();
|
||||
|
||||
void
|
||||
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
|
||||
Print *print;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> tool_colors;
|
||||
int use_VBOs;
|
||||
std::vector<int>
|
||||
load_model_object(canvas, model_object, obj_idx, instance_idxs)
|
||||
SV *canvas;
|
||||
ModelObject *model_object;
|
||||
int obj_idx;
|
||||
std::vector<int> instance_idxs;
|
||||
CODE:
|
||||
_3DScene::_load_print_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
||||
RETVAL = _3DScene::load_object((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model_object, obj_idx, instance_idxs);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs)
|
||||
PrintObject *print_object;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> tool_colors;
|
||||
int use_VBOs;
|
||||
std::vector<int>
|
||||
load_model(canvas, model, obj_idx)
|
||||
SV *canvas;
|
||||
Model *model;
|
||||
int obj_idx;
|
||||
CODE:
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs != 0);
|
||||
RETVAL = _3DScene::load_object((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), model, obj_idx);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs)
|
||||
Print *print;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> tool_colors;
|
||||
int use_VBOs;
|
||||
reload_scene(canvas, force)
|
||||
SV *canvas;
|
||||
bool force;
|
||||
CODE:
|
||||
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
||||
_3DScene::reload_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), force);
|
||||
|
||||
void
|
||||
load_print_toolpaths(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::load_print_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs)
|
||||
Print *print;
|
||||
load_print_object_toolpaths(canvas, print_object, tool_colors)
|
||||
SV *canvas;
|
||||
PrintObject *print_object;
|
||||
std::vector<std::string> tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_print_object_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object, tool_colors);
|
||||
|
||||
void
|
||||
load_wipe_tower_toolpaths(canvas, tool_colors)
|
||||
SV *canvas;
|
||||
std::vector<std::string> tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_wipe_tower_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), tool_colors);
|
||||
|
||||
void
|
||||
load_gcode_preview(canvas, preview_data, str_tool_colors)
|
||||
SV *canvas;
|
||||
GCodePreviewData *preview_data;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> str_tool_colors;
|
||||
int use_VBOs;
|
||||
CODE:
|
||||
_3DScene::load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs != 0);
|
||||
_3DScene::load_gcode_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), preview_data, str_tool_colors);
|
||||
|
||||
%}
|
||||
|
|
|
@ -52,6 +52,8 @@ _constant()
|
|||
int region_count()
|
||||
%code%{ RETVAL = THIS->print()->regions.size(); %};
|
||||
|
||||
int region_volumes_count()
|
||||
%code%{ RETVAL = THIS->region_volumes.size(); %};
|
||||
Ref<Print> print();
|
||||
Ref<ModelObject> model_object();
|
||||
Ref<StaticPrintConfig> config()
|
||||
|
@ -119,15 +121,6 @@ _constant()
|
|||
RETVAL.push_back(slicing_params.layer_height);
|
||||
%};
|
||||
|
||||
void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
|
||||
%code%{
|
||||
THIS->update_layer_height_profile(THIS->model_object()->layer_height_profile);
|
||||
adjust_layer_height_profile(
|
||||
THIS->slicing_parameters(), THIS->model_object()->layer_height_profile, z, layer_thickness_delta, band_width, LayerHeightEditActionType(action));
|
||||
THIS->model_object()->layer_height_profile_valid = true;
|
||||
THIS->layer_height_profile_valid = false;
|
||||
%};
|
||||
|
||||
void reset_layer_height_profile();
|
||||
|
||||
int ptr()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue