mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
Merge branch 'main' into dev/step-import-dialog
This commit is contained in:
@@ -4,8 +4,6 @@ project(OrcaSlicer-native)
|
||||
add_subdirectory(build-utils)
|
||||
add_subdirectory(admesh)
|
||||
# add_subdirectory(avrdude)
|
||||
# boost/nowide
|
||||
add_subdirectory(boost)
|
||||
add_subdirectory(clipper)
|
||||
add_subdirectory(clipper2)
|
||||
add_subdirectory(miniz)
|
||||
|
||||
+2
-2
@@ -36,10 +36,10 @@ using namespace nlohmann;
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/args.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
#include <boost/nowide/filesystem.hpp>
|
||||
#include <boost/dll/runtime_symbol_info.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(nowide)
|
||||
|
||||
add_library(nowide STATIC
|
||||
nowide/args.hpp
|
||||
nowide/cenv.hpp
|
||||
nowide/config.hpp
|
||||
nowide/convert.hpp
|
||||
nowide/cstdio.hpp
|
||||
nowide/cstdlib.hpp
|
||||
nowide/filebuf.hpp
|
||||
nowide/fstream.hpp
|
||||
nowide/integration/filesystem.hpp
|
||||
nowide/iostream.cpp
|
||||
nowide/iostream.hpp
|
||||
nowide/stackstring.hpp
|
||||
nowide/system.hpp
|
||||
nowide/utf8_codecvt.hpp
|
||||
nowide/windows.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(nowide PUBLIC boost_headeronly)
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_ARGS_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_ARGS_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
#ifdef BOOST_WINDOWS
|
||||
#include <boost/nowide/windows.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
class args {
|
||||
public:
|
||||
args(int &,char **&) {}
|
||||
args(int &,char **&,char **&){}
|
||||
~args() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under
|
||||
/// Microsoft Windows.
|
||||
///
|
||||
/// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW()
|
||||
/// in order to obtain the information. It does not relates to actual values of argc,argv and env
|
||||
/// under Windows.
|
||||
///
|
||||
/// It restores the original values in its destructor
|
||||
///
|
||||
/// \note the class owns the memory of the newly allocated strings
|
||||
///
|
||||
class args {
|
||||
public:
|
||||
|
||||
///
|
||||
/// Fix command line agruments
|
||||
///
|
||||
args(int &argc,char **&argv) :
|
||||
old_argc_(argc),
|
||||
old_argv_(argv),
|
||||
old_env_(0),
|
||||
old_argc_ptr_(&argc),
|
||||
old_argv_ptr_(&argv),
|
||||
old_env_ptr_(0)
|
||||
{
|
||||
fix_args(argc,argv);
|
||||
}
|
||||
///
|
||||
/// Fix command line agruments and environment
|
||||
///
|
||||
args(int &argc,char **&argv,char **&en) :
|
||||
old_argc_(argc),
|
||||
old_argv_(argv),
|
||||
old_env_(en),
|
||||
old_argc_ptr_(&argc),
|
||||
old_argv_ptr_(&argv),
|
||||
old_env_ptr_(&en)
|
||||
{
|
||||
fix_args(argc,argv);
|
||||
fix_env(en);
|
||||
}
|
||||
///
|
||||
/// Restore original argc,argv,env values, if changed
|
||||
///
|
||||
~args()
|
||||
{
|
||||
if(old_argc_ptr_)
|
||||
*old_argc_ptr_ = old_argc_;
|
||||
if(old_argv_ptr_)
|
||||
*old_argv_ptr_ = old_argv_;
|
||||
if(old_env_ptr_)
|
||||
*old_env_ptr_ = old_env_;
|
||||
}
|
||||
private:
|
||||
void fix_args(int &argc,char **&argv)
|
||||
{
|
||||
int wargc;
|
||||
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc);
|
||||
if(!wargv) {
|
||||
argc = 0;
|
||||
static char *dummy = 0;
|
||||
argv = &dummy;
|
||||
return;
|
||||
}
|
||||
try{
|
||||
args_.resize(wargc+1,0);
|
||||
arg_values_.resize(wargc);
|
||||
for(int i=0;i<wargc;i++) {
|
||||
if(!arg_values_[i].convert(wargv[i])) {
|
||||
wargc = i;
|
||||
break;
|
||||
}
|
||||
args_[i] = arg_values_[i].c_str();
|
||||
}
|
||||
argc = wargc;
|
||||
argv = &args_[0];
|
||||
}
|
||||
catch(...) {
|
||||
LocalFree(wargv);
|
||||
throw;
|
||||
}
|
||||
LocalFree(wargv);
|
||||
}
|
||||
void fix_env(char **&en)
|
||||
{
|
||||
static char *dummy = 0;
|
||||
en = &dummy;
|
||||
wchar_t *wstrings = GetEnvironmentStringsW();
|
||||
if(!wstrings)
|
||||
return;
|
||||
try {
|
||||
wchar_t *wstrings_end = 0;
|
||||
int count = 0;
|
||||
for(wstrings_end = wstrings;*wstrings_end;wstrings_end+=wcslen(wstrings_end)+1)
|
||||
count++;
|
||||
if(env_.convert(wstrings,wstrings_end)) {
|
||||
envp_.resize(count+1,0);
|
||||
char *p=env_.c_str();
|
||||
int pos = 0;
|
||||
for(int i=0;i<count;i++) {
|
||||
if(*p!='=')
|
||||
envp_[pos++] = p;
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
en = &envp_[0];
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
throw;
|
||||
}
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
|
||||
}
|
||||
|
||||
std::vector<char *> args_;
|
||||
std::vector<short_stackstring> arg_values_;
|
||||
stackstring env_;
|
||||
std::vector<char *> envp_;
|
||||
|
||||
int old_argc_;
|
||||
char **old_argv_;
|
||||
char **old_env_;
|
||||
|
||||
int *old_argc_ptr_;
|
||||
char ***old_argv_ptr_;
|
||||
char ***old_env_ptr_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,124 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CENV_H_INCLUDED
|
||||
#define BOOST_NOWIDE_CENV_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_WINDOWS
|
||||
#include <boost/nowide/windows.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
using ::getenv;
|
||||
using ::setenv;
|
||||
using ::unsetenv;
|
||||
using ::putenv;
|
||||
#else
|
||||
///
|
||||
/// \brief UTF-8 aware getenv. Returns 0 if the variable is not set.
|
||||
///
|
||||
/// This function is not thread safe or reenterable as defined by the standard library
|
||||
///
|
||||
inline char *getenv(char const *key)
|
||||
{
|
||||
static stackstring value;
|
||||
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return 0;
|
||||
|
||||
static const size_t buf_size = 64;
|
||||
wchar_t buf[buf_size];
|
||||
std::vector<wchar_t> tmp;
|
||||
wchar_t *ptr = buf;
|
||||
size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size);
|
||||
if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND
|
||||
return 0;
|
||||
if(n >= buf_size) {
|
||||
tmp.resize(n+1,L'\0');
|
||||
n = GetEnvironmentVariableW(name.c_str(),&tmp[0],static_cast<unsigned>(tmp.size() - 1));
|
||||
// The size may have changed
|
||||
if(n >= tmp.size() - 1)
|
||||
return 0;
|
||||
ptr = &tmp[0];
|
||||
}
|
||||
if(!value.convert(ptr))
|
||||
return 0;
|
||||
return value.c_str();
|
||||
}
|
||||
///
|
||||
/// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value,
|
||||
///
|
||||
/// if override is not 0, that the old value is always overridded, otherwise,
|
||||
/// if the variable exists it remains unchanged
|
||||
///
|
||||
inline int setenv(char const *key,char const *value,int override)
|
||||
{
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return -1;
|
||||
if(!override) {
|
||||
wchar_t unused[2];
|
||||
if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND
|
||||
return 0;
|
||||
}
|
||||
wstackstring wval;
|
||||
if(!wval.convert(value))
|
||||
return -1;
|
||||
if(SetEnvironmentVariableW(name.c_str(),wval.c_str()))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
///
|
||||
/// \brief Remove enviroment variable \a key
|
||||
///
|
||||
inline int unsetenv(char const *key)
|
||||
{
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return -1;
|
||||
if(SetEnvironmentVariableW(name.c_str(),0))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
///
|
||||
/// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE
|
||||
///
|
||||
inline int putenv(char *string)
|
||||
{
|
||||
char const *key = string;
|
||||
char const *key_end = string;
|
||||
while(*key_end != '=' && *key_end != 0)
|
||||
++ key_end;
|
||||
if(*key_end == 0)
|
||||
return -1;
|
||||
wshort_stackstring wkey;
|
||||
if(!wkey.convert(key,key_end))
|
||||
return -1;
|
||||
wstackstring wvalue;
|
||||
if(!wvalue.convert(key_end+1))
|
||||
return -1;
|
||||
if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str()))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CONFIG_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_SYMBOL_VISIBLE
|
||||
# define BOOST_SYMBOL_VISIBLE
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK)
|
||||
# ifdef BOOST_NOWIDE_SOURCE
|
||||
# define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT
|
||||
# else
|
||||
# define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT
|
||||
# endif // BOOST_NOWIDE_SOURCE
|
||||
# endif // DYN_LINK
|
||||
#endif // BOOST_HAS_DECLSPEC
|
||||
|
||||
#ifndef BOOST_NOWIDE_DECL
|
||||
# define BOOST_NOWIDE_DECL
|
||||
#endif
|
||||
|
||||
//
|
||||
// Automatically link to the correct build variant where possible.
|
||||
//
|
||||
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NOWIDE_NO_LIB) && !defined(BOOST_NOWIDE_SOURCE)
|
||||
//
|
||||
// Set the name of our library, this will get undef'ed by auto_link.hpp
|
||||
// once it's done with it:
|
||||
//
|
||||
#define BOOST_LIB_NAME boost_nowide
|
||||
//
|
||||
// If we're importing code from a dll, then tell auto_link.hpp about it:
|
||||
//
|
||||
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
#endif
|
||||
//
|
||||
// And include the header that does the work:
|
||||
//
|
||||
#include <boost/config/auto_link.hpp>
|
||||
#endif // auto-linking disabled
|
||||
|
||||
|
||||
#endif // boost/nowide/config.hpp
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,154 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CONVERT_H_INCLUDED
|
||||
#define BOOST_NOWIDE_CONVERT_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
///
|
||||
/// \brief Template function that converts a buffer of UTF sequences in range [source_begin,source_end)
|
||||
/// to the output \a buffer of size \a buffer_size.
|
||||
///
|
||||
/// In case of success a NULL terminated string is returned (buffer), otherwise 0 is returned.
|
||||
///
|
||||
/// If there is not enough room in the buffer or the source sequence contains invalid UTF,
|
||||
/// 0 is returned, and the contents of the buffer are undefined.
|
||||
///
|
||||
template<typename CharOut,typename CharIn>
|
||||
CharOut *basic_convert(CharOut *buffer,size_t buffer_size,CharIn const *source_begin,CharIn const *source_end)
|
||||
{
|
||||
CharOut *rv = buffer;
|
||||
if(buffer_size == 0)
|
||||
return 0;
|
||||
buffer_size --;
|
||||
while(source_begin!=source_end) {
|
||||
using namespace boost::locale::utf;
|
||||
code_point c = utf_traits<CharIn>::template decode<CharIn const *>(source_begin,source_end);
|
||||
if(c==illegal || c==incomplete) {
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
size_t width = utf_traits<CharOut>::width(c);
|
||||
if(buffer_size < width) {
|
||||
rv=0;
|
||||
break;
|
||||
}
|
||||
buffer = utf_traits<CharOut>::template encode<CharOut *>(c,buffer);
|
||||
buffer_size -= width;
|
||||
}
|
||||
*buffer++ = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/// \cond INTERNAL
|
||||
namespace details {
|
||||
//
|
||||
// wcslen defined only in C99... So we will not use it
|
||||
//
|
||||
template<typename Char>
|
||||
Char const *basic_strend(Char const *s)
|
||||
{
|
||||
while(*s)
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// Convert NULL terminated UTF source string to NULL terminated \a output string of size at
|
||||
/// most output_size (including NULL)
|
||||
///
|
||||
/// In case of success output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline char *narrow(char *output,size_t output_size,wchar_t const *source)
|
||||
{
|
||||
return basic_convert(output,output_size,source,details::basic_strend(source));
|
||||
}
|
||||
///
|
||||
/// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at
|
||||
/// most output_size (including NULL)
|
||||
///
|
||||
/// In case of success output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline char *narrow(char *output,size_t output_size,wchar_t const *begin,wchar_t const *end)
|
||||
{
|
||||
return basic_convert(output,output_size,begin,end);
|
||||
}
|
||||
///
|
||||
/// Convert NULL terminated UTF source string to NULL terminated \a output string of size at
|
||||
/// most output_size (including NULL)
|
||||
///
|
||||
/// In case of success output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline wchar_t *widen(wchar_t *output,size_t output_size,char const *source)
|
||||
{
|
||||
return basic_convert(output,output_size,source,details::basic_strend(source));
|
||||
}
|
||||
///
|
||||
/// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at
|
||||
/// most output_size (including NULL)
|
||||
///
|
||||
/// In case of success output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline wchar_t *widen(wchar_t *output,size_t output_size,char const *begin,char const *end)
|
||||
{
|
||||
return basic_convert(output,output_size,begin,end);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert between Wide - UTF-16/32 string and UTF-8 string.
|
||||
///
|
||||
/// boost::locale::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::string narrow(wchar_t const *s)
|
||||
{
|
||||
return boost::locale::conv::utf_to_utf<char>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform
|
||||
///
|
||||
/// boost::locale::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::wstring widen(char const *s)
|
||||
{
|
||||
return boost::locale::conv::utf_to_utf<wchar_t>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between Wide - UTF-16/32 string and UTF-8 string
|
||||
///
|
||||
/// boost::locale::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::string narrow(std::wstring const &s)
|
||||
{
|
||||
return boost::locale::conv::utf_to_utf<char>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform
|
||||
///
|
||||
/// boost::locale::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::wstring widen(std::string const &s)
|
||||
{
|
||||
return boost::locale::conv::utf_to_utf<wchar_t>(s);
|
||||
}
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,101 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CSTDIO_H_INCLUDED
|
||||
#define BOOST_NOWIDE_CSTDIO_H_INCLUDED
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
using std::fopen;
|
||||
using std::freopen;
|
||||
using std::remove;
|
||||
using std::rename;
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief Same as freopen but file_name and mode are UTF-8 strings
|
||||
///
|
||||
/// If invalid UTF-8 given, NULL is returned and errno is set to EINVAL
|
||||
///
|
||||
inline FILE *freopen(char const *file_name,char const *mode,FILE *stream)
|
||||
{
|
||||
wstackstring wname;
|
||||
wshort_stackstring wmode;
|
||||
if(!wname.convert(file_name) || !wmode.convert(mode)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
return _wfreopen(wname.c_str(),wmode.c_str(),stream);
|
||||
}
|
||||
///
|
||||
/// \brief Same as fopen but file_name and mode are UTF-8 strings
|
||||
///
|
||||
/// If invalid UTF-8 given, NULL is returned and errno is set to EINVAL
|
||||
///
|
||||
inline FILE *fopen(char const *file_name,char const *mode)
|
||||
{
|
||||
wstackstring wname;
|
||||
wshort_stackstring wmode;
|
||||
if(!wname.convert(file_name) || !wmode.convert(mode)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
return _wfopen(wname.c_str(),wmode.c_str());
|
||||
}
|
||||
///
|
||||
/// \brief Same as rename but old_name and new_name are UTF-8 strings
|
||||
///
|
||||
/// If invalid UTF-8 given, -1 is returned and errno is set to EINVAL
|
||||
///
|
||||
inline int rename(char const *old_name,char const *new_name)
|
||||
{
|
||||
wstackstring wold,wnew;
|
||||
if(!wold.convert(old_name) || !wnew.convert(new_name)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wrename(wold.c_str(),wnew.c_str());
|
||||
}
|
||||
///
|
||||
/// \brief Same as rename but name is UTF-8 string
|
||||
///
|
||||
/// If invalid UTF-8 given, -1 is returned and errno is set to EINVAL
|
||||
///
|
||||
inline int remove(char const *name)
|
||||
{
|
||||
wstackstring wname;
|
||||
if(!wname.convert(name)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wremove(wname.c_str());
|
||||
}
|
||||
#endif
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED
|
||||
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/system.hpp>
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,415 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_FILEBUF_HPP
|
||||
#define BOOST_NOWIDE_FILEBUF_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4996 4244 4800)
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
using std::basic_filebuf;
|
||||
using std::filebuf;
|
||||
#else // Windows
|
||||
|
||||
///
|
||||
/// \brief This forward declaration defined the basic_filebuf type.
|
||||
///
|
||||
/// it is implemented and specialized for CharType = char, it behaves
|
||||
/// implements std::filebuf over standard C I/O
|
||||
///
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_filebuf;
|
||||
|
||||
///
|
||||
/// \brief This is implementation of std::filebuf
|
||||
///
|
||||
/// it is implemented and specialized for CharType = char, it behaves
|
||||
/// implements std::filebuf over standard C I/O
|
||||
///
|
||||
template<>
|
||||
class basic_filebuf<char> : public std::basic_streambuf<char> {
|
||||
public:
|
||||
///
|
||||
/// Creates new filebuf
|
||||
///
|
||||
basic_filebuf() :
|
||||
buffer_size_(4),
|
||||
buffer_(0),
|
||||
file_(0),
|
||||
own_(true),
|
||||
mode_(std::ios::in | std::ios::out)
|
||||
{
|
||||
setg(0,0,0);
|
||||
setp(0,0);
|
||||
}
|
||||
|
||||
virtual ~basic_filebuf()
|
||||
{
|
||||
if(file_) {
|
||||
::fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
if(own_ && buffer_)
|
||||
delete [] buffer_;
|
||||
}
|
||||
|
||||
///
|
||||
/// Same as std::filebuf::open but s is UTF-8 string
|
||||
///
|
||||
basic_filebuf *open(std::string const &s,std::ios_base::openmode mode)
|
||||
{
|
||||
return open(s.c_str(),mode);
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::open but s is UTF-8 string
|
||||
///
|
||||
basic_filebuf *open(char const *s,std::ios_base::openmode mode)
|
||||
{
|
||||
if(file_) {
|
||||
sync();
|
||||
::fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
bool ate = bool(mode & std::ios_base::ate);
|
||||
if(ate)
|
||||
mode = mode ^ std::ios_base::ate;
|
||||
wchar_t const *smode = get_mode(mode);
|
||||
if(!smode)
|
||||
return 0;
|
||||
wstackstring name;
|
||||
if(!name.convert(s))
|
||||
return 0;
|
||||
#ifdef BOOST_NOWIDE_FSTREAM_TESTS
|
||||
FILE *f = ::fopen(s,boost::nowide::convert(smode).c_str());
|
||||
#else
|
||||
FILE *f = ::_wfopen(name.c_str(),smode);
|
||||
#endif
|
||||
if(!f)
|
||||
return 0;
|
||||
if(ate && fseek(f,0,SEEK_END)!=0) {
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
file_ = f;
|
||||
return this;
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::close()
|
||||
///
|
||||
basic_filebuf *close()
|
||||
{
|
||||
bool res = sync() == 0;
|
||||
if(file_) {
|
||||
if(::fclose(file_)!=0)
|
||||
res = false;
|
||||
file_ = 0;
|
||||
}
|
||||
return res ? this : 0;
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::is_open()
|
||||
///
|
||||
bool is_open() const
|
||||
{
|
||||
return file_ != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void make_buffer()
|
||||
{
|
||||
if(buffer_)
|
||||
return;
|
||||
if(buffer_size_ > 0) {
|
||||
buffer_ = new char [buffer_size_];
|
||||
own_ = true;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
|
||||
virtual std::streambuf *setbuf(char *s,std::streamsize n)
|
||||
{
|
||||
if(!buffer_ && n>=0) {
|
||||
buffer_ = s;
|
||||
buffer_size_ = n;
|
||||
own_ = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
||||
|
||||
void print_buf(char *b,char *p,char *e)
|
||||
{
|
||||
std::cerr << "-- Is Null: " << (b==0) << std::endl;;
|
||||
if(b==0)
|
||||
return;
|
||||
if(e != 0)
|
||||
std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl;
|
||||
else
|
||||
std::cerr << "-- Total: " << p - b << std::endl;
|
||||
|
||||
std::cerr << "-- [";
|
||||
for(char *ptr = b;ptr<p;ptr++)
|
||||
std::cerr << *ptr;
|
||||
if(e!=0) {
|
||||
std::cerr << "|";
|
||||
for(char *ptr = p;ptr<e;ptr++)
|
||||
std::cerr << *ptr;
|
||||
}
|
||||
std::cerr << "]" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void print_state()
|
||||
{
|
||||
std::cerr << "- Output:" << std::endl;
|
||||
print_buf(pbase(),pptr(),0);
|
||||
std::cerr << "- Input:" << std::endl;
|
||||
print_buf(eback(),gptr(),egptr());
|
||||
std::cerr << "- fpos: " << (file_ ? ftell(file_) : -1L) << std::endl;
|
||||
}
|
||||
|
||||
struct print_guard
|
||||
{
|
||||
print_guard(basic_filebuf *p,char const *func)
|
||||
{
|
||||
self = p;
|
||||
f=func;
|
||||
std::cerr << "In: " << f << std::endl;
|
||||
self->print_state();
|
||||
}
|
||||
~print_guard()
|
||||
{
|
||||
std::cerr << "Out: " << f << std::endl;
|
||||
self->print_state();
|
||||
}
|
||||
basic_filebuf *self;
|
||||
char const *f;
|
||||
};
|
||||
#else
|
||||
#endif
|
||||
|
||||
int overflow(int c)
|
||||
{
|
||||
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
|
||||
if(fixg() < 0)
|
||||
return EOF;
|
||||
|
||||
size_t n = pptr() - pbase();
|
||||
if(n > 0) {
|
||||
if(::fwrite(pbase(),1,n,file_) < n)
|
||||
return -1;
|
||||
fflush(file_);
|
||||
}
|
||||
|
||||
if(buffer_size_ > 0) {
|
||||
make_buffer();
|
||||
setp(buffer_,buffer_+buffer_size_);
|
||||
if(c!=EOF)
|
||||
sputc(c);
|
||||
}
|
||||
else if(c!=EOF) {
|
||||
if(::fputc(c,file_)==EOF)
|
||||
return EOF;
|
||||
fflush(file_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sync()
|
||||
{
|
||||
return overflow(EOF);
|
||||
}
|
||||
|
||||
int underflow()
|
||||
{
|
||||
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
if(fixp() < 0)
|
||||
return EOF;
|
||||
if(buffer_size_ == 0) {
|
||||
int c = ::fgetc(file_);
|
||||
if(c==EOF) {
|
||||
return EOF;
|
||||
}
|
||||
last_char_ = c;
|
||||
setg(&last_char_,&last_char_,&last_char_ + 1);
|
||||
return c;
|
||||
}
|
||||
make_buffer();
|
||||
size_t n = ::fread(buffer_,1,buffer_size_,file_);
|
||||
setg(buffer_,buffer_,buffer_+n);
|
||||
if(n == 0)
|
||||
return EOF;
|
||||
return std::char_traits<char>::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
int pbackfail(int)
|
||||
{
|
||||
return pubseekoff(-1,std::ios::cur);
|
||||
}
|
||||
|
||||
std::streampos seekoff(std::streamoff off,
|
||||
std::ios_base::seekdir seekdir,
|
||||
std::ios_base::openmode /*m*/)
|
||||
{
|
||||
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
if(fixp() < 0 || fixg() < 0)
|
||||
return EOF;
|
||||
if(seekdir == std::ios_base::cur) {
|
||||
if( ::fseek(file_,off,SEEK_CUR) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else if(seekdir == std::ios_base::beg) {
|
||||
if( ::fseek(file_,off,SEEK_SET) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else if(seekdir == std::ios_base::end) {
|
||||
if( ::fseek(file_,off,SEEK_END) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
return ftell(file_);
|
||||
}
|
||||
std::streampos seekpos(std::streampos off,std::ios_base::openmode m)
|
||||
{
|
||||
return seekoff(std::streamoff(off),std::ios_base::beg,m);
|
||||
}
|
||||
private:
|
||||
int fixg()
|
||||
{
|
||||
if(gptr()!=egptr()) {
|
||||
std::streamsize off = gptr() - egptr();
|
||||
setg(0,0,0);
|
||||
if(fseek(file_,off,SEEK_CUR) != 0)
|
||||
return -1;
|
||||
}
|
||||
setg(0,0,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fixp()
|
||||
{
|
||||
if(pptr()!=0) {
|
||||
int r = sync();
|
||||
setp(0,0);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset(FILE *f = 0)
|
||||
{
|
||||
sync();
|
||||
if(file_) {
|
||||
fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
file_ = f;
|
||||
}
|
||||
|
||||
|
||||
static wchar_t const *get_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
//
|
||||
// done according to n2914 table 106 27.9.1.4
|
||||
//
|
||||
|
||||
// note can't use switch case as overload operator can't be used
|
||||
// in constant expression
|
||||
if(mode == (std::ios_base::out))
|
||||
return L"w";
|
||||
if(mode == (std::ios_base::out | std::ios_base::app))
|
||||
return L"a";
|
||||
if(mode == (std::ios_base::app))
|
||||
return L"a";
|
||||
if(mode == (std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w";
|
||||
if(mode == (std::ios_base::in))
|
||||
return L"r";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out))
|
||||
return L"r+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
||||
return L"a+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::app))
|
||||
return L"a+";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out))
|
||||
return L"wb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
|
||||
return L"ab";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::app))
|
||||
return L"ab";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"wb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in))
|
||||
return L"rb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
|
||||
return L"r+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
||||
return L"a+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
|
||||
return L"a+b";
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t buffer_size_;
|
||||
char *buffer_;
|
||||
FILE *file_;
|
||||
bool own_;
|
||||
char last_char_;
|
||||
std::ios::openmode mode_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Convinience typedef
|
||||
///
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
|
||||
#endif // windows
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,283 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_FSTREAM_INCLUDED_HPP
|
||||
#define BOOST_NOWIDE_FSTREAM_INCLUDED_HPP
|
||||
|
||||
//#include <iosfwd>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <boost/nowide/filebuf.hpp>
|
||||
|
||||
namespace boost {
|
||||
///
|
||||
/// \brief This namespace includes implementation of the standard library functios
|
||||
/// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias
|
||||
/// of std namespace (i.e. not on Windows)
|
||||
///
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
|
||||
using std::basic_ifstream;
|
||||
using std::basic_ofstream;
|
||||
using std::basic_fstream;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::fstream;
|
||||
|
||||
#else
|
||||
///
|
||||
/// \brief Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ifstream : public std::basic_istream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_istream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_ifstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
|
||||
explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
|
||||
explicit basic_ifstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
|
||||
|
||||
void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
open(file_name.c_str(),mode);
|
||||
}
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
if(!buf_->open(file_name,mode | std::ios_base::in)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_ifstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ofstream : public std::basic_ostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_ostream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_ofstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
explicit basic_ofstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out)
|
||||
{
|
||||
open(file_name.c_str(),mode);
|
||||
}
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
|
||||
{
|
||||
if(!buf_->open(file_name,mode | std::ios_base::out)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_ofstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_fstream : public std::basic_iostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_iostream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_fstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
explicit basic_fstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
|
||||
{
|
||||
open(file_name.c_str(),mode);
|
||||
}
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
|
||||
{
|
||||
if(!buf_->open(file_name,mode)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_fstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Same as std::filebuf but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
///
|
||||
/// Same as std::ifstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ifstream<char> ifstream;
|
||||
///
|
||||
/// Same as std::ofstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ofstream<char> ofstream;
|
||||
///
|
||||
/// Same as std::fstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_fstream<char> fstream;
|
||||
|
||||
#endif
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/utf8_codecvt.hpp>
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
///
|
||||
/// Instal utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8 strings
|
||||
///
|
||||
inline void nowide_filesystem()
|
||||
{
|
||||
std::locale tmp = std::locale(std::locale(),new boost::nowide::utf8_codecvt<wchar_t>());
|
||||
boost::filesystem::path::imbue(tmp);
|
||||
}
|
||||
} // nowide
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,261 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#define BOOST_NOWIDE_SOURCE
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_WINDOWS
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
namespace details {
|
||||
class console_output_buffer : public std::streambuf {
|
||||
public:
|
||||
console_output_buffer(HANDLE h) :
|
||||
handle_(h),
|
||||
isatty_(false)
|
||||
{
|
||||
if(handle_) {
|
||||
DWORD dummy;
|
||||
isatty_ = GetConsoleMode(handle_,&dummy) == TRUE;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
int sync()
|
||||
{
|
||||
return overflow(EOF);
|
||||
}
|
||||
int overflow(int c)
|
||||
{
|
||||
if(!handle_)
|
||||
return -1;
|
||||
int n = pptr() - pbase();
|
||||
int r = 0;
|
||||
|
||||
if(n > 0 && (r=write(pbase(),n)) < 0)
|
||||
return -1;
|
||||
if(r < n) {
|
||||
memmove(pbase(),pbase() + r,n-r);
|
||||
}
|
||||
setp(buffer_, buffer_ + buffer_size);
|
||||
pbump(n-r);
|
||||
if(c!=EOF)
|
||||
sputc(c);
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
|
||||
int write(char const *p,int n)
|
||||
{
|
||||
namespace uf = boost::locale::utf;
|
||||
char const *b = p;
|
||||
char const *e = p+n;
|
||||
DWORD size=0;
|
||||
if(!isatty_) {
|
||||
if(!WriteFile(handle_,p,n,&size,0) || static_cast<int>(size) != n)
|
||||
return -1;
|
||||
return n;
|
||||
}
|
||||
if(n > buffer_size)
|
||||
return -1;
|
||||
wchar_t *out = wbuffer_;
|
||||
uf::code_point c;
|
||||
size_t decoded = 0;
|
||||
while(p < e && (c = uf::utf_traits<char>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
|
||||
out = uf::utf_traits<wchar_t>::encode(c,out);
|
||||
decoded = p-b;
|
||||
}
|
||||
if(c==uf::illegal)
|
||||
return -1;
|
||||
if(!WriteConsoleW(handle_,wbuffer_,out - wbuffer_,&size,0))
|
||||
return -1;
|
||||
return decoded;
|
||||
}
|
||||
|
||||
static const int buffer_size = 1024;
|
||||
char buffer_[buffer_size];
|
||||
wchar_t wbuffer_[buffer_size]; // for null
|
||||
HANDLE handle_;
|
||||
bool isatty_;
|
||||
};
|
||||
|
||||
class console_input_buffer: public std::streambuf {
|
||||
public:
|
||||
console_input_buffer(HANDLE h) :
|
||||
handle_(h),
|
||||
isatty_(false),
|
||||
wsize_(0)
|
||||
{
|
||||
if(handle_) {
|
||||
DWORD dummy;
|
||||
isatty_ = GetConsoleMode(handle_,&dummy) == TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int pbackfail(int c)
|
||||
{
|
||||
if(c==EOF)
|
||||
return EOF;
|
||||
|
||||
if(gptr()!=eback()) {
|
||||
gbump(-1);
|
||||
*gptr() = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pback_buffer_.empty()) {
|
||||
pback_buffer_.resize(4);
|
||||
char *b = &pback_buffer_[0];
|
||||
char *e = b + pback_buffer_.size();
|
||||
setg(b,e-1,e);
|
||||
*gptr() = c;
|
||||
}
|
||||
else {
|
||||
size_t n = pback_buffer_.size();
|
||||
std::vector<char> tmp;
|
||||
tmp.resize(n*2);
|
||||
memcpy(&tmp[n],&pback_buffer_[0],n);
|
||||
tmp.swap(pback_buffer_);
|
||||
char *b = &pback_buffer_[0];
|
||||
char *e = b + n * 2;
|
||||
char *p = b+n-1;
|
||||
*p = c;
|
||||
setg(b,p,e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int underflow()
|
||||
{
|
||||
if(!handle_)
|
||||
return -1;
|
||||
if(!pback_buffer_.empty())
|
||||
pback_buffer_.clear();
|
||||
|
||||
size_t n = read();
|
||||
setg(buffer_,buffer_,buffer_+n);
|
||||
if(n == 0)
|
||||
return EOF;
|
||||
return std::char_traits<char>::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
size_t read()
|
||||
{
|
||||
namespace uf = boost::locale::utf;
|
||||
if(!isatty_) {
|
||||
DWORD read_bytes = 0;
|
||||
if(!ReadFile(handle_,buffer_,buffer_size,&read_bytes,0))
|
||||
return 0;
|
||||
return read_bytes;
|
||||
}
|
||||
DWORD read_wchars = 0;
|
||||
size_t n = wbuffer_size - wsize_;
|
||||
if(!ReadConsoleW(handle_,wbuffer_,n,&read_wchars,0))
|
||||
return 0;
|
||||
wsize_ += read_wchars;
|
||||
char *out = buffer_;
|
||||
wchar_t *b = wbuffer_;
|
||||
wchar_t *e = b + wsize_;
|
||||
wchar_t *p = b;
|
||||
uf::code_point c;
|
||||
wsize_ = e-p;
|
||||
while(p < e && (c = uf::utf_traits<wchar_t>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
|
||||
out = uf::utf_traits<char>::encode(c,out);
|
||||
wsize_ = e-p;
|
||||
}
|
||||
|
||||
if(c==uf::illegal)
|
||||
return -1;
|
||||
|
||||
|
||||
if(c==uf::incomplete) {
|
||||
memmove(b,e-wsize_,sizeof(wchar_t)*wsize_);
|
||||
}
|
||||
|
||||
return out - buffer_;
|
||||
}
|
||||
|
||||
static const size_t buffer_size = 1024 * 3;
|
||||
static const size_t wbuffer_size = 1024;
|
||||
char buffer_[buffer_size];
|
||||
wchar_t wbuffer_[buffer_size]; // for null
|
||||
HANDLE handle_;
|
||||
bool isatty_;
|
||||
int wsize_;
|
||||
std::vector<char> pback_buffer_;
|
||||
};
|
||||
|
||||
winconsole_ostream::winconsole_ostream(int fd) : std::ostream(0)
|
||||
{
|
||||
HANDLE h = 0;
|
||||
switch(fd) {
|
||||
case 1:
|
||||
h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
break;
|
||||
case 2:
|
||||
h = GetStdHandle(STD_ERROR_HANDLE);
|
||||
break;
|
||||
}
|
||||
d.reset(new console_output_buffer(h));
|
||||
std::ostream::rdbuf(d.get());
|
||||
}
|
||||
|
||||
winconsole_ostream::~winconsole_ostream()
|
||||
{
|
||||
}
|
||||
|
||||
winconsole_istream::winconsole_istream() : std::istream(0)
|
||||
{
|
||||
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
|
||||
d.reset(new console_input_buffer(h));
|
||||
std::istream::rdbuf(d.get());
|
||||
}
|
||||
|
||||
winconsole_istream::~winconsole_istream()
|
||||
{
|
||||
}
|
||||
|
||||
} // details
|
||||
|
||||
BOOST_NOWIDE_DECL details::winconsole_istream cin;
|
||||
BOOST_NOWIDE_DECL details::winconsole_ostream cout(1);
|
||||
BOOST_NOWIDE_DECL details::winconsole_ostream cerr(2);
|
||||
BOOST_NOWIDE_DECL details::winconsole_ostream clog(2);
|
||||
|
||||
namespace {
|
||||
struct initialize {
|
||||
initialize()
|
||||
{
|
||||
boost::nowide::cin.tie(&boost::nowide::cout);
|
||||
boost::nowide::cerr.tie(&boost::nowide::cout);
|
||||
boost::nowide::clog.tie(&boost::nowide::cout);
|
||||
}
|
||||
} inst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,99 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED
|
||||
|
||||
#include <boost/nowide/config.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::cin;
|
||||
using std::clog;
|
||||
#else
|
||||
|
||||
/// \cond INTERNAL
|
||||
namespace details {
|
||||
class console_output_buffer;
|
||||
class console_input_buffer;
|
||||
|
||||
class BOOST_NOWIDE_DECL winconsole_ostream : public std::ostream {
|
||||
winconsole_ostream(winconsole_ostream const &);
|
||||
void operator=(winconsole_ostream const &);
|
||||
public:
|
||||
winconsole_ostream(int fd);
|
||||
~winconsole_ostream();
|
||||
private:
|
||||
boost::scoped_ptr<console_output_buffer> d;
|
||||
};
|
||||
|
||||
class BOOST_NOWIDE_DECL winconsole_istream : public std::istream {
|
||||
winconsole_istream(winconsole_istream const &);
|
||||
void operator=(winconsole_istream const &);
|
||||
public:
|
||||
|
||||
winconsole_istream();
|
||||
~winconsole_istream();
|
||||
private:
|
||||
struct data;
|
||||
boost::scoped_ptr<console_input_buffer> d;
|
||||
};
|
||||
} // details
|
||||
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// \brief Same as std::cin, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern BOOST_NOWIDE_DECL details::winconsole_istream cin;
|
||||
///
|
||||
/// \brief Same as std::cout, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern BOOST_NOWIDE_DECL details::winconsole_ostream cout;
|
||||
///
|
||||
/// \brief Same as std::cerr, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern BOOST_NOWIDE_DECL details::winconsole_ostream cerr;
|
||||
///
|
||||
/// \brief Same as std::clog, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern BOOST_NOWIDE_DECL details::winconsole_ostream clog;
|
||||
|
||||
#endif
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,154 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED
|
||||
#define BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
|
||||
///
|
||||
/// \brief A class that allows to create a temporary wide or narrow UTF strings from
|
||||
/// wide or narrow UTF source.
|
||||
///
|
||||
/// It uses on stack buffer of the string is short enough
|
||||
/// and allocated a buffer on the heap if the size of the buffer is too small
|
||||
///
|
||||
template<typename CharOut=wchar_t,typename CharIn = char,size_t BufferSize = 256>
|
||||
class basic_stackstring {
|
||||
public:
|
||||
|
||||
static const size_t buffer_size = BufferSize;
|
||||
typedef CharOut output_char;
|
||||
typedef CharIn input_char;
|
||||
|
||||
basic_stackstring(basic_stackstring const &other) :
|
||||
mem_buffer_(0)
|
||||
{
|
||||
clear();
|
||||
if(other.mem_buffer_) {
|
||||
size_t len = 0;
|
||||
while(other.mem_buffer_[len])
|
||||
len ++;
|
||||
mem_buffer_ = new output_char[len + 1];
|
||||
memcpy(mem_buffer_,other.mem_buffer_,sizeof(output_char) * (len+1));
|
||||
}
|
||||
else {
|
||||
memcpy(buffer_,other.buffer_,buffer_size * sizeof(output_char));
|
||||
}
|
||||
}
|
||||
|
||||
void swap(basic_stackstring &other)
|
||||
{
|
||||
std::swap(mem_buffer_,other.mem_buffer_);
|
||||
for(size_t i=0;i<buffer_size;i++)
|
||||
std::swap(buffer_[i],other.buffer_[i]);
|
||||
}
|
||||
basic_stackstring &operator=(basic_stackstring const &other)
|
||||
{
|
||||
if(this != &other) {
|
||||
basic_stackstring tmp(other);
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_stackstring() : mem_buffer_(0)
|
||||
{
|
||||
}
|
||||
bool convert(input_char const *input)
|
||||
{
|
||||
return convert(input,details::basic_strend(input));
|
||||
}
|
||||
bool convert(input_char const *begin,input_char const *end)
|
||||
{
|
||||
clear();
|
||||
|
||||
size_t space = get_space(sizeof(input_char),sizeof(output_char),end - begin) + 1;
|
||||
if(space <= buffer_size) {
|
||||
if(basic_convert(buffer_,buffer_size,begin,end))
|
||||
return true;
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
mem_buffer_ = new output_char[space];
|
||||
if(!basic_convert(mem_buffer_,space,begin,end)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
output_char *c_str()
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
output_char const *c_str() const
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
if(mem_buffer_) {
|
||||
delete [] mem_buffer_;
|
||||
mem_buffer_=0;
|
||||
}
|
||||
buffer_[0] = 0;
|
||||
}
|
||||
~basic_stackstring()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
private:
|
||||
static size_t get_space(size_t insize,size_t outsize,size_t in)
|
||||
{
|
||||
if(insize <= outsize)
|
||||
return in;
|
||||
else if(insize == 2 && outsize == 1)
|
||||
return 3 * in;
|
||||
else if(insize == 4 && outsize == 1)
|
||||
return 4 * in;
|
||||
else // if(insize == 4 && outsize == 2)
|
||||
return 2 * in;
|
||||
}
|
||||
output_char buffer_[buffer_size];
|
||||
output_char *mem_buffer_;
|
||||
}; //basic_stackstring
|
||||
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,256> wstackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,256> stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,16> wshort_stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,16> short_stackstring;
|
||||
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,46 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_CSTDLIB_HPP
|
||||
#define BOOST_NOWIDE_CSTDLIB_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
||||
|
||||
using ::system;
|
||||
|
||||
#else // Windows
|
||||
|
||||
///
|
||||
/// Same as std::system but cmd is UTF-8.
|
||||
///
|
||||
/// If the input is not valid UTF-8, -1 returned and errno set to EINVAL
|
||||
///
|
||||
inline int system(char const *cmd)
|
||||
{
|
||||
if(!cmd)
|
||||
return _wsystem(0);
|
||||
wstackstring wcmd;
|
||||
if(!wcmd.convert(cmd)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wsystem(wcmd.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,499 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2015 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_UTF8_CODECVT_HPP
|
||||
#define BOOST_NOWIDE_UTF8_CODECVT_HPP
|
||||
|
||||
#include <boost/locale/utf.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <locale>
|
||||
|
||||
namespace boost {
|
||||
namespace nowide {
|
||||
|
||||
//
|
||||
// Make sure that mbstate can keep 16 bit of UTF-16 sequence
|
||||
//
|
||||
BOOST_STATIC_ASSERT(sizeof(std::mbstate_t)>=2);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// MSVC do_length is non-standard it counts wide characters instead of narrow and does not change mbstate
|
||||
#define BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
#endif
|
||||
|
||||
template<typename CharType,int CharSize=sizeof(CharType)>
|
||||
class utf8_codecvt;
|
||||
|
||||
template<typename CharType>
|
||||
class utf8_codecvt<CharType,2> : public std::codecvt<CharType,char,std::mbstate_t>
|
||||
{
|
||||
public:
|
||||
utf8_codecvt(size_t refs = 0) : std::codecvt<CharType,char,std::mbstate_t>(refs)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
|
||||
typedef CharType uchar;
|
||||
|
||||
virtual std::codecvt_base::result do_unshift(std::mbstate_t &s,char *from,char * /*to*/,char *&next) const
|
||||
{
|
||||
boost::uint16_t &state = *reinterpret_cast<boost::uint16_t *>(&s);
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering unshift " << std::hex << state << std::dec << std::endl;
|
||||
#endif
|
||||
if(state != 0)
|
||||
return std::codecvt_base::error;
|
||||
next=from;
|
||||
return std::codecvt_base::ok;
|
||||
}
|
||||
virtual int do_encoding() const throw()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int do_max_length() const throw()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
virtual bool do_always_noconv() const throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int
|
||||
do_length( std::mbstate_t
|
||||
#ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
const
|
||||
#endif
|
||||
&std_state,
|
||||
char const *from,
|
||||
char const *from_end,
|
||||
size_t max) const
|
||||
{
|
||||
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
char const *save_from = from;
|
||||
boost::uint16_t &state = *reinterpret_cast<boost::uint16_t *>(&std_state);
|
||||
#else
|
||||
size_t save_max = max;
|
||||
boost::uint16_t state = *reinterpret_cast<boost::uint16_t const *>(&std_state);
|
||||
#endif
|
||||
while(max > 0 && from < from_end){
|
||||
char const *prev_from = from;
|
||||
boost::uint32_t ch=boost::locale::utf::utf_traits<char>::decode(from,from_end);
|
||||
if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) {
|
||||
from = prev_from;
|
||||
break;
|
||||
}
|
||||
max --;
|
||||
if(ch > 0xFFFF) {
|
||||
if(state == 0) {
|
||||
from = prev_from;
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
return from - save_from;
|
||||
#else
|
||||
return int(save_max - max);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_in( std::mbstate_t &std_state,
|
||||
char const *from,
|
||||
char const *from_end,
|
||||
char const *&from_next,
|
||||
uchar *to,
|
||||
uchar *to_end,
|
||||
uchar *&to_next) const
|
||||
{
|
||||
std::codecvt_base::result r=std::codecvt_base::ok;
|
||||
|
||||
// mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT())
|
||||
// according to standard. We use it to keep a flag 0/1 for surrogate pair writing
|
||||
//
|
||||
// if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd
|
||||
// and first pair is written, but no input consumed
|
||||
boost::uint16_t &state = *reinterpret_cast<boost::uint16_t *>(&std_state);
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering IN--------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
char const *from_saved = from;
|
||||
|
||||
uint32_t ch=boost::locale::utf::utf_traits<char>::decode(from,from_end);
|
||||
|
||||
if(ch==boost::locale::utf::illegal) {
|
||||
from = from_saved;
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
if(ch==boost::locale::utf::incomplete) {
|
||||
from = from_saved;
|
||||
r=std::codecvt_base::partial;
|
||||
break;
|
||||
}
|
||||
// Normal codepoints go direcly to stream
|
||||
if(ch <= 0xFFFF) {
|
||||
*to++=ch;
|
||||
}
|
||||
else {
|
||||
// for other codepoints we do following
|
||||
//
|
||||
// 1. We can't consume our input as we may find ourselfs
|
||||
// in state where all input consumed but not all output written,i.e. only
|
||||
// 1st pair is written
|
||||
// 2. We only write first pair and mark this in the state, we also revert back
|
||||
// the from pointer in order to make sure this codepoint would be read
|
||||
// once again and then we would consume our input together with writing
|
||||
// second surrogate pair
|
||||
ch-=0x10000;
|
||||
boost::uint16_t vh = ch >> 10;
|
||||
boost::uint16_t vl = ch & 0x3FF;
|
||||
boost::uint16_t w1 = vh + 0xD800;
|
||||
boost::uint16_t w2 = vl + 0xDC00;
|
||||
if(state == 0) {
|
||||
from = from_saved;
|
||||
*to++ = w1;
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
*to++ = w2;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
from_next=from;
|
||||
to_next=to;
|
||||
if(r == std::codecvt_base::ok && (from!=from_end || state!=0))
|
||||
r = std::codecvt_base::partial;
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Returning ";
|
||||
switch(r) {
|
||||
case std::codecvt_base::ok:
|
||||
std::cout << "ok" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::partial:
|
||||
std::cout << "partial" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "other" << std::endl;
|
||||
break;
|
||||
}
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_out( std::mbstate_t &std_state,
|
||||
uchar const *from,
|
||||
uchar const *from_end,
|
||||
uchar const *&from_next,
|
||||
char *to,
|
||||
char *to_end,
|
||||
char *&to_next) const
|
||||
{
|
||||
std::codecvt_base::result r=std::codecvt_base::ok;
|
||||
// mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT())
|
||||
// according to standard. We assume that sizeof(mbstate_t) >=2 in order
|
||||
// to be able to store first observerd surrogate pair
|
||||
//
|
||||
// State: state!=0 - a first surrogate pair was observerd (state = first pair),
|
||||
// we expect the second one to come and then zero the state
|
||||
///
|
||||
boost::uint16_t &state = *reinterpret_cast<boost::uint16_t *>(&std_state);
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering OUT --------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
boost::uint32_t ch=0;
|
||||
if(state != 0) {
|
||||
// if the state idecates that 1st surrogate pair was written
|
||||
// we should make sure that the second one that comes is actually
|
||||
// second surrogate
|
||||
boost::uint16_t w1 = state;
|
||||
boost::uint16_t w2 = *from;
|
||||
// we don't forward from as writing may fail to incomplete or
|
||||
// partial conversion
|
||||
if(0xDC00 <= w2 && w2<=0xDFFF) {
|
||||
boost::uint16_t vh = w1 - 0xD800;
|
||||
boost::uint16_t vl = w2 - 0xDC00;
|
||||
ch=((uint32_t(vh) << 10) | vl) + 0x10000;
|
||||
}
|
||||
else {
|
||||
// Invalid surrogate
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch = *from;
|
||||
if(0xD800 <= ch && ch<=0xDBFF) {
|
||||
// if this is a first surrogate pair we put
|
||||
// it into the state and consume it, note we don't
|
||||
// go forward as it should be illegal so we increase
|
||||
// the from pointer manually
|
||||
state = ch;
|
||||
from++;
|
||||
continue;
|
||||
}
|
||||
else if(0xDC00 <= ch && ch<=0xDFFF) {
|
||||
// if we observe second surrogate pair and
|
||||
// first only may be expected we should break from the loop with error
|
||||
// as it is illegal input
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!boost::locale::utf::is_valid_codepoint(ch)) {
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
int len = boost::locale::utf::utf_traits<char>::width(ch);
|
||||
if(to_end - to < len) {
|
||||
r=std::codecvt_base::partial;
|
||||
break;
|
||||
}
|
||||
to = boost::locale::utf::utf_traits<char>::encode(ch,to);
|
||||
state = 0;
|
||||
from++;
|
||||
}
|
||||
from_next=from;
|
||||
to_next=to;
|
||||
if(r==std::codecvt_base::ok && from!=from_end)
|
||||
r = std::codecvt_base::partial;
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Returning ";
|
||||
switch(r) {
|
||||
case std::codecvt_base::ok:
|
||||
std::cout << "ok" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::partial:
|
||||
std::cout << "partial" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "other" << std::endl;
|
||||
break;
|
||||
}
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class utf8_codecvt<CharType,4> : public std::codecvt<CharType,char,std::mbstate_t>
|
||||
{
|
||||
public:
|
||||
utf8_codecvt(size_t refs = 0) : std::codecvt<CharType,char,std::mbstate_t>(refs)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
|
||||
typedef CharType uchar;
|
||||
|
||||
virtual std::codecvt_base::result do_unshift(std::mbstate_t &/*s*/,char *from,char * /*to*/,char *&next) const
|
||||
{
|
||||
next=from;
|
||||
return std::codecvt_base::ok;
|
||||
}
|
||||
virtual int do_encoding() const throw()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int do_max_length() const throw()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
virtual bool do_always_noconv() const throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int
|
||||
do_length( std::mbstate_t
|
||||
#ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
const
|
||||
#endif
|
||||
&/*state*/,
|
||||
char const *from,
|
||||
char const *from_end,
|
||||
size_t max) const
|
||||
{
|
||||
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
char const *start_from = from;
|
||||
#else
|
||||
size_t save_max = max;
|
||||
#endif
|
||||
|
||||
while(max > 0 && from < from_end){
|
||||
char const *save_from = from;
|
||||
boost::uint32_t ch=boost::locale::utf::utf_traits<char>::decode(from,from_end);
|
||||
if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) {
|
||||
from = save_from;
|
||||
break;
|
||||
}
|
||||
max--;
|
||||
}
|
||||
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
return from - start_from;
|
||||
#else
|
||||
return save_max - max;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_in( std::mbstate_t &/*state*/,
|
||||
char const *from,
|
||||
char const *from_end,
|
||||
char const *&from_next,
|
||||
uchar *to,
|
||||
uchar *to_end,
|
||||
uchar *&to_next) const
|
||||
{
|
||||
std::codecvt_base::result r=std::codecvt_base::ok;
|
||||
|
||||
// mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT())
|
||||
// according to standard. We use it to keep a flag 0/1 for surrogate pair writing
|
||||
//
|
||||
// if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd
|
||||
// and first pair is written, but no input consumed
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering IN--------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
char const *from_saved = from;
|
||||
|
||||
uint32_t ch=boost::locale::utf::utf_traits<char>::decode(from,from_end);
|
||||
|
||||
if(ch==boost::locale::utf::illegal) {
|
||||
r=std::codecvt_base::error;
|
||||
from = from_saved;
|
||||
break;
|
||||
}
|
||||
if(ch==boost::locale::utf::incomplete) {
|
||||
r=std::codecvt_base::partial;
|
||||
from=from_saved;
|
||||
break;
|
||||
}
|
||||
*to++=ch;
|
||||
}
|
||||
from_next=from;
|
||||
to_next=to;
|
||||
if(r == std::codecvt_base::ok && from!=from_end)
|
||||
r = std::codecvt_base::partial;
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Returning ";
|
||||
switch(r) {
|
||||
case std::codecvt_base::ok:
|
||||
std::cout << "ok" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::partial:
|
||||
std::cout << "partial" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "other" << std::endl;
|
||||
break;
|
||||
}
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_out( std::mbstate_t &std_state,
|
||||
uchar const *from,
|
||||
uchar const *from_end,
|
||||
uchar const *&from_next,
|
||||
char *to,
|
||||
char *to_end,
|
||||
char *&to_next) const
|
||||
{
|
||||
std::codecvt_base::result r=std::codecvt_base::ok;
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering OUT --------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
boost::uint32_t ch=0;
|
||||
ch = *from;
|
||||
if(!boost::locale::utf::is_valid_codepoint(ch)) {
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
int len = boost::locale::utf::utf_traits<char>::width(ch);
|
||||
if(to_end - to < len) {
|
||||
r=std::codecvt_base::partial;
|
||||
break;
|
||||
}
|
||||
to = boost::locale::utf::utf_traits<char>::encode(ch,to);
|
||||
from++;
|
||||
}
|
||||
from_next=from;
|
||||
to_next=to;
|
||||
if(r==std::codecvt_base::ok && from!=from_end)
|
||||
r = std::codecvt_base::partial;
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Returning ";
|
||||
switch(r) {
|
||||
case std::codecvt_base::ok:
|
||||
std::cout << "ok" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::partial:
|
||||
std::cout << "partial" << std::endl;
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "other" << std::endl;
|
||||
break;
|
||||
}
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef BOOST_NOWIDE_WINDOWS_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_WINDOWS_HPP_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef BOOST_NOWIDE_USE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
//
|
||||
// These are function prototypes... Allow to to include windows.h
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
__declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void);
|
||||
__declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t *);
|
||||
__declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void);
|
||||
__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(wchar_t const *,int *);
|
||||
__declspec(dllimport) unsigned long __stdcall GetLastError();
|
||||
__declspec(dllimport) void* __stdcall LocalFree(void *);
|
||||
__declspec(dllimport) int __stdcall SetEnvironmentVariableW(wchar_t const *,wchar_t const *);
|
||||
__declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(wchar_t const *,wchar_t *,unsigned long);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
@@ -173,6 +173,9 @@ namespace ImGui
|
||||
const wchar_t SphereButtonIcon = 0x0816;
|
||||
const wchar_t GapFillIcon = 0x0817;
|
||||
const wchar_t ConfirmIcon = 0x0818;
|
||||
const wchar_t gCodeButtonIcon = 0x0819; // ORCA
|
||||
const wchar_t VisibleIcon = 0x0820; // ORCA
|
||||
const wchar_t HiddenIcon = 0x0821; // ORCA
|
||||
|
||||
const wchar_t MinimalizeDarkButton = 0x081C;
|
||||
const wchar_t MinimalizeHoverDarkButton = 0x081D;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
@@ -182,6 +181,9 @@ void AppConfig::set_defaults()
|
||||
if (get("reverse_mouse_wheel_zoom").empty())
|
||||
set_bool("reverse_mouse_wheel_zoom", false);
|
||||
|
||||
if (get("camera_orbit_mult").empty())
|
||||
set("camera_orbit_mult", "1.0");
|
||||
|
||||
if (get("zoom_to_mouse").empty())
|
||||
set_bool("zoom_to_mouse", false);
|
||||
|
||||
|
||||
@@ -560,7 +560,6 @@ target_link_libraries(libslic3r
|
||||
miniz
|
||||
boost_libs
|
||||
clipper
|
||||
nowide
|
||||
${EXPAT_LIBRARIES}
|
||||
glu-libtess
|
||||
qhull
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
@@ -153,6 +153,12 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||
out.push_back(eec = new ExtrusionEntityCollection());
|
||||
// Only concentric fills are not sorted.
|
||||
eec->no_sort = this->no_sort();
|
||||
// ORCA: special flag for flow rate calibration
|
||||
auto is_flow_calib = params.extrusion_role == erTopSolidInfill && this->print_object_config->has("calib_flowrate_topinfill_special_order") &&
|
||||
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool();
|
||||
if (is_flow_calib) {
|
||||
eec->no_sort = true;
|
||||
}
|
||||
size_t idx = eec->entities.size();
|
||||
if (params.use_arachne) {
|
||||
Flow new_flow = params.flow.with_spacing(float(this->spacing));
|
||||
@@ -165,11 +171,16 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||
params.extrusion_role,
|
||||
flow_mm3_per_mm, float(flow_width), params.flow.height());
|
||||
}
|
||||
if (!params.can_reverse) {
|
||||
|
||||
if (is_flow_calib) {
|
||||
for (size_t i = idx; i < eec->entities.size(); i++)
|
||||
eec->entities[i]->set_reverse();
|
||||
eec->entities[i]->reverse();
|
||||
} else {
|
||||
if (!params.can_reverse) {
|
||||
for (size_t i = idx; i < eec->entities.size(); i++)
|
||||
eec->entities[i]->set_reverse();
|
||||
}
|
||||
}
|
||||
|
||||
// Orca: run gap fill
|
||||
this->_create_gap_fill(surface, params, eec);
|
||||
}
|
||||
|
||||
+12
-6
@@ -4077,6 +4077,7 @@ LayerResult GCode::process_layer(
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
std::string gcode_toolchange;
|
||||
if (has_wipe_tower) {
|
||||
if (!m_wipe_tower->is_empty_wipe_tower_gcode(*this, extruder_id, extruder_id == layer_tools.extruders.back())) {
|
||||
if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
|
||||
@@ -4095,11 +4096,16 @@ LayerResult GCode::process_layer(
|
||||
}
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
|
||||
gcode_toolchange = m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
|
||||
}
|
||||
} else {
|
||||
gcode += this->set_extruder(extruder_id, print_z);
|
||||
gcode_toolchange = this->set_extruder(extruder_id, print_z);
|
||||
}
|
||||
if (!gcode_toolchange.empty()) {
|
||||
// Disable vase mode for layers that has toolchange
|
||||
result.spiral_vase_enable = false;
|
||||
}
|
||||
gcode += std::move(gcode_toolchange);
|
||||
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
@@ -5335,7 +5341,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
ref_speed = EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm;
|
||||
|
||||
if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||
ref_speed = std::min(ref_speed, EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm);
|
||||
ref_speed = std::min(ref_speed, EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm);
|
||||
}
|
||||
if (sloped) {
|
||||
ref_speed = std::min(ref_speed, m_config.scarf_joint_speed.get_abs_value(ref_speed));
|
||||
@@ -6064,7 +6070,8 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string
|
||||
|
||||
// use G1 because we rely on paths being straight (G0 may make round paths)
|
||||
if (travel.size() >= 2) {
|
||||
if (m_spiral_vase) {
|
||||
// Orca: use `travel_to_xyz` to ensure we start at the correct z, in case we moved z in custom/filament change gcode
|
||||
if (false/*m_spiral_vase*/) {
|
||||
// No lazy z lift for spiral vase mode
|
||||
for (size_t i = 1; i < travel.size(); ++i) {
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
|
||||
@@ -6292,8 +6299,7 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
||||
}
|
||||
|
||||
if (needs_lift && can_lift) {
|
||||
size_t extruder_id = m_writer.extruder()->id();
|
||||
gcode += m_writer.lift(!m_spiral_vase ? lift_type : LiftType::NormalLift);
|
||||
gcode += m_writer.lift(lift_type, m_spiral_vase != nullptr);
|
||||
}
|
||||
|
||||
return gcode;
|
||||
|
||||
@@ -442,6 +442,10 @@ public:
|
||||
};
|
||||
|
||||
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
||||
// ORCA: Clamp resulting speed to lowest of calculated speed based on the overhang values and the current speed
|
||||
// Fixes bug where resulting overhang speed is higher than the current speed due to (for example) volumetric flow limits.
|
||||
extrusion_speed = std::min(extrusion_speed, original_speed);
|
||||
|
||||
if(slowdown_for_curled_edges) {
|
||||
float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
|
||||
extrusion_speed = std::min(curled_speed, extrusion_speed); // adjust extrusion speed based on what is smallest - the calculated overhang speed or the artificial curled speed
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
// BBS
|
||||
|
||||
@@ -478,6 +478,16 @@ Transform3d Transformation::get_rotation_matrix() const
|
||||
return extract_rotation_matrix(m_matrix);
|
||||
}
|
||||
|
||||
Vec3d Transformation::get_rotation_by_quaternion() const
|
||||
{
|
||||
Matrix3d rotation_matrix = m_matrix.matrix().block(0, 0, 3, 3);
|
||||
Eigen::Quaterniond quaternion(rotation_matrix);
|
||||
quaternion.normalize();
|
||||
Vec3d temp_rotation = quaternion.matrix().eulerAngles(2, 1, 0);
|
||||
std::swap(temp_rotation(0), temp_rotation(2));
|
||||
return temp_rotation;
|
||||
}
|
||||
|
||||
void Transformation::set_rotation(const Vec3d& rotation)
|
||||
{
|
||||
const Vec3d offset = get_offset();
|
||||
@@ -839,6 +849,17 @@ TransformationSVD::TransformationSVD(const Transform3d& trafo)
|
||||
return curMat;
|
||||
}
|
||||
|
||||
Transformation generate_transform(const Vec3d& x_dir, const Vec3d& y_dir, const Vec3d& z_dir, const Vec3d& origin) {
|
||||
Matrix3d m;
|
||||
m.col(0) = x_dir.normalized();
|
||||
m.col(1) = y_dir.normalized();
|
||||
m.col(2) = z_dir.normalized();
|
||||
Transform3d mm(m);
|
||||
Transformation tran(mm);
|
||||
tran.set_offset(origin);
|
||||
return tran;
|
||||
}
|
||||
|
||||
bool is_point_inside_polygon_corner(const Point &a, const Point &b, const Point &c, const Point &query_point) {
|
||||
// Cast all input points into int64_t to prevent overflows when points are close to max values of coord_t.
|
||||
const Vec2i64 a_i64 = a.cast<int64_t>();
|
||||
|
||||
@@ -421,6 +421,7 @@ public:
|
||||
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
|
||||
|
||||
Vec3d get_rotation() const;
|
||||
Vec3d get_rotation_by_quaternion() const;
|
||||
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
|
||||
|
||||
Transform3d get_rotation_matrix() const;
|
||||
@@ -545,6 +546,7 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation)
|
||||
}
|
||||
|
||||
Transformation mat_around_a_point_rotate(const Transformation& innMat, const Vec3d &pt, const Vec3d &axis, float rotate_theta_radian);
|
||||
Transformation generate_transform(const Vec3d &x_dir, const Vec3d &y_dir, const Vec3d &z_dir, const Vec3d &origin);
|
||||
|
||||
/**
|
||||
* Checks if a given point is inside a corner of a polygon.
|
||||
|
||||
+51
-43
@@ -1216,23 +1216,27 @@ bool ModelObject::make_boolean(ModelObject *cut_object, const std::string &boole
|
||||
return true;
|
||||
}
|
||||
|
||||
ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh)
|
||||
ModelVolume *ModelObject::add_volume(const TriangleMesh &mesh, bool modify_to_center_geometry)
|
||||
{
|
||||
ModelVolume* v = new ModelVolume(this, mesh);
|
||||
this->volumes.push_back(v);
|
||||
v->center_geometry_after_creation();
|
||||
this->invalidate_bounding_box();
|
||||
if (modify_to_center_geometry) {
|
||||
v->center_geometry_after_creation();
|
||||
this->invalidate_bounding_box();
|
||||
}
|
||||
// BBS: backup
|
||||
Slic3r::save_object_mesh(*this);
|
||||
return v;
|
||||
}
|
||||
|
||||
ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh, ModelVolumeType type /*= ModelVolumeType::MODEL_PART*/)
|
||||
ModelVolume *ModelObject::add_volume(TriangleMesh &&mesh, ModelVolumeType type /*= ModelVolumeType::MODEL_PART*/, bool modify_to_center_geometry)
|
||||
{
|
||||
ModelVolume* v = new ModelVolume(this, std::move(mesh), type);
|
||||
this->volumes.push_back(v);
|
||||
v->center_geometry_after_creation();
|
||||
this->invalidate_bounding_box();
|
||||
if (modify_to_center_geometry) {
|
||||
v->center_geometry_after_creation();
|
||||
this->invalidate_bounding_box();
|
||||
}
|
||||
// BBS: backup
|
||||
Slic3r::save_object_mesh(*this);
|
||||
return v;
|
||||
@@ -2260,48 +2264,12 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
|
||||
unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume &build_volume)
|
||||
{
|
||||
unsigned int num_printable = 0;
|
||||
enum {
|
||||
INSIDE = 1,
|
||||
OUTSIDE = 2
|
||||
};
|
||||
|
||||
//BBS: add logs for build_volume
|
||||
//const BoundingBoxf3& print_volume = build_volume.bounding_volume();
|
||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", print_volume {%1%, %2%, %3%} to {%4%, %5%, %6%}")\
|
||||
// %print_volume.min.x() %print_volume.min.y() %print_volume.min.z()%print_volume.max.x() %print_volume.max.y() %print_volume.max.z();
|
||||
for (ModelInstance* model_instance : this->instances) {
|
||||
unsigned int inside_outside = 0;
|
||||
for (const ModelVolume *vol : this->volumes) {
|
||||
if (vol->is_model_part()) {
|
||||
//BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object)
|
||||
BoundingBoxf3 bb = vol->get_convex_hull().bounding_box();
|
||||
Vec3d size = bb.size();
|
||||
if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->name %vol->name\
|
||||
%bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z();
|
||||
continue;
|
||||
}
|
||||
|
||||
const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix();
|
||||
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
|
||||
if (state == BuildVolume::ObjectState::Inside)
|
||||
// Volume is completely inside.
|
||||
inside_outside |= INSIDE;
|
||||
else if (state == BuildVolume::ObjectState::Outside)
|
||||
// Volume is completely outside.
|
||||
inside_outside |= OUTSIDE;
|
||||
else if (state == BuildVolume::ObjectState::Below) {
|
||||
// Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable
|
||||
// if some of its volumes are still inside the build volume.
|
||||
} else
|
||||
// Volume colliding with the build volume.
|
||||
inside_outside |= INSIDE | OUTSIDE;
|
||||
}
|
||||
}
|
||||
model_instance->print_volume_state =
|
||||
inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
|
||||
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
|
||||
if (inside_outside == INSIDE) {
|
||||
if (model_instance->update_print_volume_state(build_volume) == ModelInstancePVS_Inside) {
|
||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s instance inside print volum")%this->name;
|
||||
++num_printable;
|
||||
}
|
||||
@@ -3329,6 +3297,46 @@ void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConf
|
||||
ret.extrude_ids.push_back(1);
|
||||
}
|
||||
|
||||
ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const BuildVolume& build_volume) const
|
||||
{
|
||||
enum {
|
||||
INSIDE = 1,
|
||||
OUTSIDE = 2
|
||||
};
|
||||
|
||||
unsigned int inside_outside = 0;
|
||||
for (const ModelVolume* vol : this->object->volumes) {
|
||||
if (vol->is_model_part()) {
|
||||
//BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object)
|
||||
BoundingBoxf3 bb = vol->get_convex_hull().bounding_box();
|
||||
Vec3d size = bb.size();
|
||||
if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->object->name %vol->name\
|
||||
%bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z();
|
||||
continue;
|
||||
}
|
||||
|
||||
const Transform3d matrix = this->get_matrix() * vol->get_matrix();
|
||||
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
|
||||
if (state == BuildVolume::ObjectState::Inside)
|
||||
// Volume is completely inside.
|
||||
inside_outside |= INSIDE;
|
||||
else if (state == BuildVolume::ObjectState::Outside)
|
||||
// Volume is completely outside.
|
||||
inside_outside |= OUTSIDE;
|
||||
else if (state == BuildVolume::ObjectState::Below) {
|
||||
// Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable
|
||||
// if some of its volumes are still inside the build volume.
|
||||
} else
|
||||
// Volume colliding with the build volume.
|
||||
inside_outside |= INSIDE | OUTSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
return inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
|
||||
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
|
||||
}
|
||||
|
||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
{
|
||||
TriangleSelector selector(mv.mesh());
|
||||
|
||||
+13
-3
@@ -411,8 +411,8 @@ public:
|
||||
return global_config.option<T>(config_option);
|
||||
}
|
||||
|
||||
ModelVolume* add_volume(const TriangleMesh &mesh);
|
||||
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
||||
ModelVolume* add_volume(const TriangleMesh &mesh, bool modify_to_center_geometry = true);
|
||||
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART, bool modify_to_center_geometry = true);
|
||||
ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID);
|
||||
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
||||
ModelVolume* add_volume_with_shared_mesh(const ModelVolume &other, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
||||
@@ -1245,11 +1245,13 @@ public:
|
||||
m_assemble_initialized = true;
|
||||
m_assemble_transformation = transformation;
|
||||
}
|
||||
void set_assemble_from_transform(Transform3d& transform) {
|
||||
void set_assemble_from_transform(const Transform3d& transform) {
|
||||
m_assemble_initialized = true;
|
||||
m_assemble_transformation.set_matrix(transform);
|
||||
}
|
||||
Vec3d get_assemble_offset() const {return m_assemble_transformation.get_offset(); }
|
||||
void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); }
|
||||
void set_assemble_rotation(const Vec3d &rotation) { m_assemble_transformation.set_rotation(rotation); }
|
||||
void rotate_assemble(double angle, const Vec3d& axis) {
|
||||
m_assemble_transformation.set_rotation(m_assemble_transformation.get_rotation() + Geometry::extract_euler_angles(Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)).toRotationMatrix()));
|
||||
}
|
||||
@@ -1326,6 +1328,8 @@ public:
|
||||
this->object->invalidate_bounding_box();
|
||||
}
|
||||
|
||||
ModelInstanceEPrintVolumeState calc_print_volume_state(const BuildVolume& build_volume) const;
|
||||
|
||||
protected:
|
||||
friend class Print;
|
||||
friend class SLAPrint;
|
||||
@@ -1335,6 +1339,12 @@ protected:
|
||||
explicit ModelInstance(const ModelInstance &rhs) = default;
|
||||
void set_model_object(ModelObject *model_object) { object = model_object; }
|
||||
|
||||
ModelInstanceEPrintVolumeState update_print_volume_state(const BuildVolume& build_volume)
|
||||
{
|
||||
print_volume_state = calc_print_volume_state(build_volume);
|
||||
return print_volume_state;
|
||||
}
|
||||
|
||||
private:
|
||||
// Parent object, owning this instance.
|
||||
ModelObject* object;
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
//BBS: add regex
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
@@ -836,7 +835,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth",
|
||||
"small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model",
|
||||
"seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold",
|
||||
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width",
|
||||
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_filament_options {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
@@ -3206,6 +3206,11 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(2));
|
||||
|
||||
// ORCA: special flag for flow rate calibration
|
||||
def = this->add("calib_flowrate_topinfill_special_order", coBool);
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("ironing_type", coEnum);
|
||||
def->label = L("Ironing Type");
|
||||
def->category = L("Quality");
|
||||
|
||||
@@ -907,6 +907,10 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionInt, interlocking_depth))
|
||||
((ConfigOptionInt, interlocking_boundary_avoidance))
|
||||
|
||||
// Orca: internal use only
|
||||
((ConfigOptionBool, calib_flowrate_topinfill_special_order)) // ORCA: special flag for flow rate calibration
|
||||
|
||||
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
||||
|
||||
@@ -733,8 +733,6 @@ void PrintObject::simplify_extrusion_path()
|
||||
}
|
||||
|
||||
if (this->set_started(posSimplifySupportPath)) {
|
||||
//BBS: disable circle simplification for support as it causes separation of support walls
|
||||
#if 0
|
||||
m_print->set_status(75, L("Optimizing toolpath"));
|
||||
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - start";
|
||||
tbb::parallel_for(
|
||||
@@ -748,7 +746,6 @@ void PrintObject::simplify_extrusion_path()
|
||||
);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - end";
|
||||
#endif
|
||||
this->set_done(posSimplifySupportPath);
|
||||
}
|
||||
}
|
||||
@@ -1312,7 +1309,8 @@ void PrintObject::detect_surfaces_type()
|
||||
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
|
||||
Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr;
|
||||
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||
const float offset_top = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||
const float offset_bottom = layerm->flow(frExternalPerimeter).scaled_width();
|
||||
|
||||
ExPolygons layerm_slices_surfaces = to_expolygons(layerm->slices.surfaces);
|
||||
// no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to slice, that's why we need to start from the result of PerimeterGenerator.
|
||||
@@ -1327,7 +1325,7 @@ void PrintObject::detect_surfaces_type()
|
||||
ExPolygons upper_slices = interface_shells ?
|
||||
diff_ex(layerm_slices_surfaces, upper_layer->m_regions[region_id]->slices.surfaces, ApplySafetyOffset::Yes) :
|
||||
diff_ex(layerm_slices_surfaces, upper_layer->lslices, ApplySafetyOffset::Yes);
|
||||
surfaces_append(top, opening_ex(upper_slices, offset), stTop);
|
||||
surfaces_append(top, opening_ex(upper_slices, offset_top), stTop);
|
||||
} else {
|
||||
// if no upper layer, all surfaces of this one are solid
|
||||
// we clone surfaces because we're going to clear the slices collection
|
||||
@@ -1353,7 +1351,7 @@ void PrintObject::detect_surfaces_type()
|
||||
bottom,
|
||||
opening_ex(
|
||||
diff_ex(layerm_slices_surfaces, lower_layer->lslices, ApplySafetyOffset::Yes),
|
||||
offset),
|
||||
offset_bottom),
|
||||
surface_type_bottom_other);
|
||||
// if user requested internal shells, we need to identify surfaces
|
||||
// lying on other slices not belonging to this region
|
||||
@@ -1367,7 +1365,7 @@ void PrintObject::detect_surfaces_type()
|
||||
intersection(layerm_slices_surfaces, lower_layer->lslices), // supported
|
||||
lower_layer->m_regions[region_id]->slices.surfaces,
|
||||
ApplySafetyOffset::Yes),
|
||||
offset),
|
||||
offset_bottom),
|
||||
stBottom);
|
||||
}
|
||||
#endif
|
||||
@@ -1383,12 +1381,25 @@ void PrintObject::detect_surfaces_type()
|
||||
// and top surfaces; let's do an intersection to discover them and consider them
|
||||
// as bottom surfaces (to allow for bridge detection)
|
||||
if (! top.empty() && ! bottom.empty()) {
|
||||
// Polygons overlapping = intersection(to_polygons(top), to_polygons(bottom));
|
||||
// Slic3r::debugf " layer %d contains %d membrane(s)\n", $layerm->layer->id, scalar(@$overlapping)
|
||||
// if $Slic3r::debug;
|
||||
Polygons top_polygons = to_polygons(std::move(top));
|
||||
top.clear();
|
||||
surfaces_append(top, diff_ex(top_polygons, bottom), stTop);
|
||||
const auto cracks = intersection_ex(top, bottom);
|
||||
if (!cracks.empty()) {
|
||||
const float small_crack_threshold = -offset_bottom;
|
||||
|
||||
for (const auto& crack : cracks) {
|
||||
if (offset_ex(crack, small_crack_threshold).empty()) {
|
||||
// Crack too small, leave it as part of the top surface, remove it from bottom surfaces
|
||||
Surfaces bot_tmp;
|
||||
for (auto& b : bottom) {
|
||||
surfaces_append(bot_tmp, diff_ex(b.expolygon, crack), b.surface_type);
|
||||
}
|
||||
bottom = std::move(bot_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
Polygons top_polygons = to_polygons(std::move(top));
|
||||
top.clear();
|
||||
surfaces_append(top, diff_ex(top_polygons, bottom), stTop);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
|
||||
@@ -490,6 +490,7 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
|
||||
double y_pos = start_y;
|
||||
|
||||
// prime line
|
||||
gcode << writer.set_pressure_advance(0.0);
|
||||
auto prime_x = start_x;
|
||||
gcode << move_to(Vec2d(prime_x, y_pos + (num) * m_space_y), writer);
|
||||
gcode << writer.set_speed(slow);
|
||||
@@ -505,6 +506,12 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
|
||||
gcode << writer.set_speed(slow);
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * m_space_y),
|
||||
e_per_mm * m_length_short);
|
||||
|
||||
if (i == 0) {
|
||||
// Print extra anchor line
|
||||
gcode << writer.set_pressure_advance(0.0);
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + (num) * m_space_y), e_per_mm * m_space_y * num * 1.2);
|
||||
}
|
||||
}
|
||||
gcode << writer.set_pressure_advance(0.0);
|
||||
|
||||
@@ -517,7 +524,7 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
|
||||
// gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7), writer);
|
||||
// gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7);
|
||||
|
||||
const auto box_start_x = start_x + m_length_short + m_length_long + m_length_short;
|
||||
const auto box_start_x = start_x + m_length_short + m_length_long + m_length_short + m_line_width;
|
||||
DrawBoxOptArgs default_box_opt_args(2, m_height_layer, m_line_width, fast);
|
||||
default_box_opt_args.is_filled = true;
|
||||
gcode << draw_box(writer, box_start_x, start_y - m_space_y,
|
||||
|
||||
@@ -75,7 +75,7 @@ static constexpr double RESOLUTION = 0.0125;
|
||||
static constexpr double SPARSE_INFILL_RESOLUTION = 0.04;
|
||||
#define SCALED_SPARSE_INFILL_RESOLUTION (SPARSE_INFILL_RESOLUTION / SCALING_FACTOR)
|
||||
|
||||
static constexpr double SUPPORT_RESOLUTION = 0.1;
|
||||
static constexpr double SUPPORT_RESOLUTION = 0.0375;
|
||||
#define SCALED_SUPPORT_RESOLUTION (SUPPORT_RESOLUTION / SCALING_FACTOR)
|
||||
// Maximum perimeter length for the loop to apply the small perimeter speed.
|
||||
#define SMALL_PERIMETER_LENGTH(LENGTH) (((LENGTH) / SCALING_FACTOR) * 2 * PI)
|
||||
|
||||
@@ -81,12 +81,11 @@
|
||||
#include <boost/log/expressions.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/multi_array.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
#include <boost/nowide/filesystem.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
|
||||
@@ -895,8 +895,13 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
|
||||
}
|
||||
|
||||
//BBS: add outline drawing logic
|
||||
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||
std::function<bool(const GLVolume&)> filter_func) const
|
||||
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||
bool disable_cullface,
|
||||
const Transform3d & view_matrix,
|
||||
const Transform3d& projection_matrix,
|
||||
const GUI::Size& cnv_size,
|
||||
std::function<bool(const GLVolume &)> filter_func,
|
||||
bool partly_inside_enable) const
|
||||
{
|
||||
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
||||
if (to_render.empty())
|
||||
@@ -964,7 +969,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
||||
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
|
||||
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
|
||||
|
||||
if (volume.first->partly_inside) {
|
||||
if (volume.first->partly_inside && partly_inside_enable) {
|
||||
//only partly inside volume need to be painted with boundary check
|
||||
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
|
||||
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
|
||||
@@ -1077,14 +1082,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||
{
|
||||
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
|
||||
BuildVolume::ObjectState state;
|
||||
const BoundingBoxf3& bb = volume_bbox(*volume);
|
||||
if (volume_below(*volume))
|
||||
state = BuildVolume::ObjectState::Below;
|
||||
else {
|
||||
switch (plate_build_volume.type()) {
|
||||
case BuildVolume_Type::Rectangle:
|
||||
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
|
||||
case BuildVolume_Type::Rectangle: {
|
||||
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
|
||||
const BoundingBoxf3& bb = volume_bbox(*volume);
|
||||
state = plate_build_volume.volume_state_bbox(bb);
|
||||
}
|
||||
break;
|
||||
case BuildVolume_Type::Circle:
|
||||
case BuildVolume_Type::Convex:
|
||||
|
||||
@@ -471,8 +471,14 @@ public:
|
||||
int get_selection_support_threshold_angle(bool&) const;
|
||||
// Render the volumes by OpenGL.
|
||||
//BBS: add outline drawing logic
|
||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>()) const;
|
||||
void render(ERenderType type,
|
||||
bool disable_cullface,
|
||||
const Transform3d & view_matrix,
|
||||
const Transform3d& projection_matrix,
|
||||
const GUI::Size& cnv_size,
|
||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
|
||||
bool partly_inside_enable =true
|
||||
) const;
|
||||
|
||||
// Clear the geometry
|
||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||
|
||||
@@ -90,7 +90,7 @@ void ConfigManipulation::check_nozzle_temperature_range(DynamicPrintConfig *conf
|
||||
if (config->opt_int("nozzle_temperature", 0) < temperature_range_low || config->opt_int("nozzle_temperature", 0) > temperature_range_high) {
|
||||
wxString msg_text = _(L("Nozzle may be blocked when the temperature is out of recommended range.\n"
|
||||
"Please make sure whether to use the temperature to print.\n\n"));
|
||||
msg_text += wxString::Format(_L("Recommended nozzle temperature of this filament type is [%d, %d] degree centigrade"), temperature_range_low, temperature_range_high);
|
||||
msg_text += wxString::Format(_L("The recommended nozzle temperature for this filament type is [%d, %d] degrees Celsius."), temperature_range_low, temperature_range_high);
|
||||
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog.ShowModal();
|
||||
@@ -113,7 +113,7 @@ void ConfigManipulation::check_nozzle_temperature_initial_layer_range(DynamicPri
|
||||
{
|
||||
wxString msg_text = _(L("Nozzle may be blocked when the temperature is out of recommended range.\n"
|
||||
"Please make sure whether to use the temperature to print.\n\n"));
|
||||
msg_text += wxString::Format(_L("Recommended nozzle temperature of this filament type is [%d, %d] degree centigrade"), temperature_range_low, temperature_range_high);
|
||||
msg_text += wxString::Format(_L("The recommended nozzle temperature for this filament type is [%d, %d] degrees Celsius."), temperature_range_low, temperature_range_high);
|
||||
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog.ShowModal();
|
||||
|
||||
@@ -117,7 +117,7 @@ void resolve_path_from_var(const std::string& var, std::vector<std::string>& pat
|
||||
wxString wxdirs;
|
||||
if (! wxGetEnv(boost::nowide::widen(var), &wxdirs) || wxdirs.empty() )
|
||||
return;
|
||||
std::string dirs = boost::nowide::narrow(wxdirs);
|
||||
std::string dirs = into_u8(wxdirs);
|
||||
for (size_t i = dirs.find(':'); i != std::string::npos; i = dirs.find(':'))
|
||||
{
|
||||
paths.push_back(dirs.substr(0, i));
|
||||
@@ -302,7 +302,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
// if all failed - try creating default home folder
|
||||
if (i == target_candidates.size() - 1) {
|
||||
// create $HOME/.local/share
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
|
||||
create_path(into_u8(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
|
||||
// copy icon
|
||||
target_dir_icons = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
|
||||
std::string icon_path = GUI::format("%1%/images/OrcaSlicer.png",resources_dir());
|
||||
@@ -354,7 +354,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
// if all failed - try creating default home folder
|
||||
if (i == target_candidates.size() - 1) {
|
||||
// create $HOME/.local/share
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
create_path(into_u8(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
// create desktop file
|
||||
target_dir_desktop = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
|
||||
std::string path = GUI::format("%1%/applications/OrcaSlicer%2%.desktop", target_dir_desktop, version_suffix);
|
||||
@@ -562,7 +562,7 @@ void DesktopIntegrationDialog::perform_downloader_desktop_integration(std::strin
|
||||
// if all failed - try creating default home folder
|
||||
if (!candidate_found) {
|
||||
// create $HOME/.local/share
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
create_path(into_u8(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
// create desktop file
|
||||
target_dir_desktop = GUI::format("%1%/.local/share", wxFileName::GetHomeDir());
|
||||
std::string path = GUI::format("%1%/applications/OrcaSlicerURLProtocol-%2%%3%.desktop", target_dir_desktop, url_prefix, version_suffix);
|
||||
|
||||
@@ -175,7 +175,7 @@ void Downloader::start_download(const std::string& full_url)
|
||||
void Downloader::on_progress(wxCommandEvent& event)
|
||||
{
|
||||
size_t id = event.GetInt();
|
||||
float percent = (float)std::stoi(boost::nowide::narrow(event.GetString())) / 100.f;
|
||||
float percent = (float)std::stoi(into_u8(event.GetString())) / 100.f;
|
||||
//BOOST_LOG_TRIVIAL(error) << "progress " << id << ": " << percent;
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
BOOST_LOG_TRIVIAL(trace) << "Download "<< id << ": " << percent;
|
||||
@@ -187,7 +187,7 @@ void Downloader::on_error(wxCommandEvent& event)
|
||||
set_download_state(event.GetInt(), DownloadState::DownloadError);
|
||||
BOOST_LOG_TRIVIAL(error) << "Download error: " << event.GetString();
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
ntf_mngr->set_download_URL_error(id, boost::nowide::narrow(event.GetString()));
|
||||
ntf_mngr->set_download_URL_error(id, into_u8(event.GetString()));
|
||||
show_error(nullptr, format_wxstr(L"%1%\n%2%", _L("The download has failed") + ":", event.GetString()));
|
||||
}
|
||||
void Downloader::on_complete(wxCommandEvent& event)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <thread>
|
||||
#include <curl/curl.h>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
@@ -228,7 +228,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
path = boost::filesystem::path(extra.substr(0, extra_size));
|
||||
} else {
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = boost::nowide::narrow(wname);
|
||||
std::string name = into_u8(wname);
|
||||
path = boost::filesystem::path(name);
|
||||
}
|
||||
assert(!path.empty());
|
||||
|
||||
@@ -596,9 +596,9 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f
|
||||
|
||||
//BBS: GUI refactor: move to right
|
||||
//imgui.set_next_window_pos(0.0f, top, ImGuiCond_Always, 0.0f, 0.0f);
|
||||
imgui.set_next_window_pos(right, top, ImGuiCond_Always, 1.0f, 0.0f);
|
||||
imgui.set_next_window_pos(right, top + 6 * m_scale, ImGuiCond_Always, 1.0f, 0.0f); // ORCA add a small gap between legend and code viewer
|
||||
imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * m_scale); // ORCA add window rounding to modernize / match style
|
||||
ImGui::SetNextWindowBgAlpha(0.8f);
|
||||
imgui.begin(std::string("G-code"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
|
||||
@@ -879,6 +879,7 @@ void GCodeViewer::set_scale(float scale)
|
||||
if (m_sequential_view.m_scale != scale) {
|
||||
m_sequential_view.m_scale = scale;
|
||||
m_sequential_view.marker.m_scale = scale;
|
||||
m_sequential_view.gcode_window.m_scale = scale; // ORCA
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4053,7 +4054,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
|
||||
}
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * m_scale); // ORCA add window rounding to modernize / match style
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0, 10.0 * m_scale));
|
||||
ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f, 1.0f, 1.0f, 0.6f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
|
||||
@@ -4363,8 +4364,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
|
||||
//BBS: GUI refactor: move to the right
|
||||
imgui.set_next_window_pos(float(canvas_width - right_margin * m_scale), 0.0f, ImGuiCond_Always, 1.0f, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
imgui.set_next_window_pos(float(canvas_width - right_margin * m_scale), 4.0f * m_scale, ImGuiCond_Always, 1.0f, 0.0f); // ORCA add a small gap to top to create seperation with main toolbar
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * m_scale); // ORCA add window rounding to modernize / match style
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0,0.0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f,1.0f,1.0f,0.6f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.59f, 0.53f, 1.0f));
|
||||
@@ -4403,9 +4404,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
ImVec2 pos_rect = ImGui::GetCursorScreenPos();
|
||||
float window_padding = 4.0f * m_scale;
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(pos_rect.x,pos_rect.y - ImGui::GetStyle().WindowPadding.y),
|
||||
ImVec2(pos_rect.x + ImGui::GetWindowWidth() + ImGui::GetFrameHeight(),pos_rect.y + ImGui::GetFrameHeight() + window_padding * 2.5),
|
||||
ImGui::GetColorU32(ImVec4(0,0,0,0.3)));
|
||||
// ORCA dont use background on top bar to give modern look
|
||||
//draw_list->AddRectFilled(ImVec2(pos_rect.x,pos_rect.y - ImGui::GetStyle().WindowPadding.y),
|
||||
//ImVec2(pos_rect.x + ImGui::GetWindowWidth() + ImGui::GetFrameHeight(),pos_rect.y + ImGui::GetFrameHeight() + window_padding * 2.5),
|
||||
//ImGui::GetColorU32(ImVec4(0,0,0,0.3)));
|
||||
|
||||
auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, this](
|
||||
EItemType type,
|
||||
@@ -4464,12 +4466,14 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
if (b_menu_item)
|
||||
callback();
|
||||
if (checkbox) {
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x / 2 - ImGui::GetFrameHeight() / 2 - 2 * window_padding);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0, 0.0));
|
||||
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
|
||||
ImGui::Checkbox(("##" + columns_offsets[0].first).c_str(), &visible);
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopStyleVar(1);
|
||||
//ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x / 2 - ImGui::GetFrameHeight() / 2 - 2 * window_padding);
|
||||
//ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0, 0.0));
|
||||
//ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
|
||||
//ImGui::Checkbox(("##" + columns_offsets[0].first).c_str(), &visible);
|
||||
//ImGui::PopStyleVar(1);
|
||||
// ORCA replace checkboxes with eye icon
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - (16.f + 0.f) * m_scale - window_padding * 2 - (ImGui::GetScrollMaxY() > 0.0f ? ImGui::GetStyle().ScrollbarSize : 0));
|
||||
ImGui::Text(into_u8(visible ? ImGui::VisibleIcon : ImGui::HiddenIcon).c_str(), ImVec2(16 * m_scale, 16 * m_scale));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4515,8 +4519,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
}
|
||||
};
|
||||
|
||||
auto append_headers = [&imgui, window_padding](const std::vector<std::pair<std::string, float>>& title_offsets) {
|
||||
auto append_headers = [&imgui, window_padding, this](const std::vector<std::pair<std::string, float>>& title_offsets) {
|
||||
for (size_t i = 0; i < title_offsets.size(); i++) {
|
||||
if (title_offsets[i].first == _u8L("Display")) { // ORCA Hide Display header
|
||||
ImGui::SameLine(title_offsets[i].second);
|
||||
ImGui::Dummy({(16.f - 6.f) * m_scale, 1}); // 16(icon) - 6(half of spacing)
|
||||
continue;
|
||||
}
|
||||
ImGui::SameLine(title_offsets[i].second);
|
||||
imgui.bold_text(title_offsets[i].first);
|
||||
}
|
||||
@@ -4534,14 +4543,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
return ret;
|
||||
};
|
||||
|
||||
auto calculate_offsets = [&imgui, max_width, window_padding](const std::vector<std::pair<std::string, std::vector<::string>>>& title_columns, float extra_size = 0.0f) {
|
||||
auto calculate_offsets = [&imgui, max_width, window_padding, this](const std::vector<std::pair<std::string, std::vector<::string>>>& title_columns, float extra_size = 0.0f) {
|
||||
const ImGuiStyle& style = ImGui::GetStyle();
|
||||
std::vector<float> offsets;
|
||||
offsets.push_back(max_width(title_columns[0].second, title_columns[0].first, extra_size) + 3.0f * style.ItemSpacing.x);
|
||||
// ORCA increase spacing for more readable format. Using direct number requires much less code change in here. GetTextLineHeight for additional spacing for icon_size
|
||||
offsets.push_back(max_width(title_columns[0].second, title_columns[0].first, extra_size) + 12.f * m_scale + ImGui::GetTextLineHeight());
|
||||
for (size_t i = 1; i < title_columns.size() - 1; i++)
|
||||
offsets.push_back(offsets.back() + max_width(title_columns[i].second, title_columns[i].first) + style.ItemSpacing.x);
|
||||
offsets.push_back(offsets.back() + max_width(title_columns[i].second, title_columns[i].first) + 12.f * m_scale); // ORCA increase spacing for more readable format. Using direct number requires much less code change in here
|
||||
if (title_columns.back().first == _u8L("Display")) {
|
||||
const auto preferred_offset = ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x - ImGui::GetFrameHeight() / 2 - 2 * window_padding - ImGui::GetStyle().ScrollbarSize;
|
||||
//const auto preferred_offset = ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x - ImGui::GetFrameHeight() / 2 - 2 * window_padding - ImGui::GetStyle().ScrollbarSize;
|
||||
const auto preferred_offset = ImGui::GetWindowWidth() - (16.f - 6.f) * m_scale - ImGui::GetFrameHeight() / 2 - 2 * window_padding - (ImGui::GetScrollMaxY() > 0.0f ? ImGui::GetStyle().ScrollbarSize : 0);
|
||||
if (preferred_offset > offsets.back()) {
|
||||
offsets.back() = preferred_offset;
|
||||
}
|
||||
@@ -4553,7 +4564,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
for (size_t i = 1; i < title_columns.size(); i++) {
|
||||
ret.push_back(std::max(offsets[i - 1], i * average_col_width));
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
@@ -4639,30 +4649,39 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
//BBS display Color Scheme
|
||||
ImGui::Dummy({ window_padding, window_padding });
|
||||
ImGui::Dummy({ window_padding, window_padding });
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine(window_padding * 2); // ORCA Ignores item spacing to get perfect window margins since since this part uses dummies for window padding
|
||||
std::wstring btn_name;
|
||||
if (m_fold)
|
||||
btn_name = ImGui::UnfoldButtonIcon;
|
||||
else
|
||||
btn_name = ImGui::FoldButtonIcon;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.59f, 0.53f, 1.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.0f, 0.59f, 0.53f, 0.78f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
//ImGui::PushItemWidth(
|
||||
float button_width = 34.0f;
|
||||
if (ImGui::Button(into_u8(btn_name).c_str(), ImVec2(button_width, 0))) {
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(84 / 255.f, 84 / 255.f, 90 / 255.f, 1.f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(84 / 255.f, 84 / 255.f, 90 / 255.f, 1.f));
|
||||
float calc_padding = (ImGui::GetFrameHeight() - 16 * m_scale) / 2; // ORCA calculated padding for 16x16 icon
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(calc_padding, calc_padding)); // ORCA Center icon with frame padding
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f * m_scale); // ORCA Match button style with combo box
|
||||
|
||||
float button_width = 16 * m_scale + calc_padding * 2; // ORCA match buttons height with combo box
|
||||
if (ImGui::Button(into_u8(btn_name).c_str(), ImVec2(button_width, button_width))) {
|
||||
m_fold = !m_fold;
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(1);
|
||||
|
||||
ImGui::SameLine();
|
||||
imgui.bold_text(_u8L("Color Scheme"));
|
||||
const wchar_t gCodeToggle = ImGui::gCodeButtonIcon;
|
||||
if (ImGui::Button(into_u8(gCodeToggle).c_str(), ImVec2(button_width, button_width))) {
|
||||
wxGetApp().toggle_show_gcode_window();
|
||||
wxGetApp().plater()->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
//imgui.bold_text(_u8L("Color Scheme"));
|
||||
push_combo_style();
|
||||
|
||||
ImGui::SameLine();
|
||||
const char* view_type_value = view_type_items_str[m_view_type_sel].c_str();
|
||||
ImGuiComboFlags flags = 0;
|
||||
ImGuiComboFlags flags = ImGuiComboFlags_HeightLargest; // ORCA allow to fit all items to prevent scrolling on reaching last elements
|
||||
if (ImGui::BBLBeginCombo("", view_type_value, flags)) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
|
||||
for (int i = 0; i < view_type_items_str.size(); i++) {
|
||||
@@ -4685,11 +4704,15 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
pop_combo_style();
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine(0, window_padding); // ORCA Without (0,window_padding) it adds unnecessary item spacing after combo box
|
||||
ImGui::Dummy({ window_padding, window_padding });
|
||||
ImGui::Dummy({ window_padding, window_padding }); // ORCA Matches top-bottom window paddings
|
||||
float window_width = ImGui::GetWindowWidth(); // ORCA Store window width
|
||||
|
||||
if (m_fold) {
|
||||
legend_height = ImGui::GetStyle().WindowPadding.y + ImGui::GetFrameHeight() + window_padding * 2.5;
|
||||
legend_height = ImGui::GetFrameHeight() + window_padding * 4; // ORCA using 4 instead 2 gives correct toolbar margins while its folded
|
||||
ImGui::SameLine(window_width); // ORCA use stored window width while folded. This prevents annoying position change on fold/expand button
|
||||
ImGui::Dummy({ 0, 0 });
|
||||
imgui.end();
|
||||
ImGui::PopStyleColor(6);
|
||||
ImGui::PopStyleVar(2);
|
||||
@@ -4813,16 +4836,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
labels.push_back(_u8L(ExtrusionEntity::role_to_string(role)));
|
||||
auto [time, percent] = role_time_and_percent(role);
|
||||
times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : "");
|
||||
if (percent == 0)
|
||||
::sprintf(buffer, "0%%");
|
||||
if (percent == 0) // ORCA remove % symbol from rows
|
||||
::sprintf(buffer, "0");
|
||||
else
|
||||
percent > 0.001 ? ::sprintf(buffer, "%.1f%%", percent * 100) : ::sprintf(buffer, "<0.1%%");
|
||||
percent > 0.001 ? ::sprintf(buffer, "%.1f", percent * 100) : ::sprintf(buffer, "<0.1");
|
||||
percents.push_back(buffer);
|
||||
|
||||
auto [model_used_filament_m, model_used_filament_g] = used_filament_per_role(role);
|
||||
::sprintf(buffer, imperial_units ? "%.2f in" : "%.2f m", model_used_filament_m);
|
||||
::sprintf(buffer, imperial_units ? "%.2fin" : "%.2fm", model_used_filament_m); // ORCA dont use spacing between value and unit
|
||||
used_filaments_length.push_back(buffer);
|
||||
::sprintf(buffer, imperial_units ? "%.2f oz" : "%.2f g", model_used_filament_g);
|
||||
::sprintf(buffer, imperial_units ? "%.2foz" : "%.2fg", model_used_filament_g); // ORCA dont use spacing between value and unit
|
||||
used_filaments_weight.push_back(buffer);
|
||||
}
|
||||
}
|
||||
@@ -4831,15 +4854,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
{
|
||||
auto [time, percent] = move_time_and_percent(EMoveType::Travel);
|
||||
travel_time = (time > 0.0f) ? short_time(get_time_dhms(time)) : "";
|
||||
if (percent == 0)
|
||||
::sprintf(buffer, "0%%");
|
||||
if (percent == 0) // ORCA remove % symbol from rows
|
||||
::sprintf(buffer, "0");
|
||||
else
|
||||
percent > 0.001 ? ::sprintf(buffer, "%.1f%%", percent * 100) : ::sprintf(buffer, "<0.1%%");
|
||||
percent > 0.001 ? ::sprintf(buffer, "%.1f", percent * 100) : ::sprintf(buffer, "<0.1");
|
||||
travel_percent = buffer;
|
||||
}
|
||||
|
||||
offsets = calculate_offsets({ {_u8L("Line Type"), labels}, {_u8L("Time"), times}, {_u8L("Percent"), percents}, {"", used_filaments_length}, {"", used_filaments_weight}, {_u8L("Display"), {""}}}, icon_size);
|
||||
append_headers({{_u8L("Line Type"), offsets[0]}, {_u8L("Time"), offsets[1]}, {_u8L("Percent"), offsets[2]}, {_u8L("Used filament"), offsets[3]}, {_u8L("Display"), offsets[5]}});
|
||||
// ORCA use % symbol for percentage and use "Usage" for "Used filaments"
|
||||
offsets = calculate_offsets({ {_u8L("Line Type"), labels}, {_u8L("Time"), times}, {_u8L("%"), percents}, {"", used_filaments_length}, {"", used_filaments_weight}, {_u8L("Display"), {""}}}, icon_size);
|
||||
append_headers({{_u8L("Line Type"), offsets[0]}, {_u8L("Time"), offsets[1]}, {_u8L("%"), offsets[2]}, {_u8L("Usage"), offsets[3]}, {_u8L("Display"), offsets[5]}});
|
||||
break;
|
||||
}
|
||||
case EViewType::Height: { imgui.title(_u8L("Layer Height (mm)")); break; }
|
||||
@@ -4870,7 +4894,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
}
|
||||
|
||||
offsets = calculate_offsets({ { "Extruder NNN", {""}}}, icon_size);
|
||||
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Used filament"), offsets[1]} });
|
||||
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Usage"), offsets[1]} });
|
||||
break;
|
||||
}
|
||||
case EViewType::ColorPrint:
|
||||
@@ -5699,8 +5723,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
|
||||
void GCodeViewer::push_combo_style()
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f * m_scale); // ORCA scale rounding
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * m_scale); // ORCA scale frame size
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0,8.0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));
|
||||
|
||||
@@ -660,6 +660,7 @@ public:
|
||||
std::vector<Line> m_lines;
|
||||
|
||||
public:
|
||||
float m_scale = 1.0f;
|
||||
GCodeWindow() = default;
|
||||
~GCodeWindow() { stop_mapping_file(); }
|
||||
void load_gcode(const std::string& filename, const std::vector<size_t> &lines_ends);
|
||||
|
||||
+198
-63
@@ -14,7 +14,6 @@
|
||||
#include "libslic3r/Technologies.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "3DBed.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "GLShader.hpp"
|
||||
@@ -1168,6 +1167,13 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
load_arrange_settings();
|
||||
|
||||
m_selection.set_volumes(&m_volumes.volumes);
|
||||
|
||||
m_assembly_view_desc["object_selection_caption"] = _L("Left mouse button");
|
||||
m_assembly_view_desc["object_selection"] = _L("object selection");
|
||||
m_assembly_view_desc["part_selection_caption"] = "Alt +" + _L("Left mouse button");
|
||||
m_assembly_view_desc["part_selection"] = _L("part selectiont");
|
||||
m_assembly_view_desc["number_key_caption"] = "1~16 " + _L("number keys");
|
||||
m_assembly_view_desc["number_key"] = _L("number keys can quickly change the color of objects");
|
||||
}
|
||||
|
||||
GLCanvas3D::~GLCanvas3D()
|
||||
@@ -1939,7 +1945,11 @@ void GLCanvas3D::render(bool only_init)
|
||||
/* assemble render*/
|
||||
else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
|
||||
//BBS: add outline logic
|
||||
if (m_show_world_axes) {
|
||||
m_axes.render();
|
||||
}
|
||||
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
|
||||
_render_selection();
|
||||
//_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
|
||||
_render_plane();
|
||||
//BBS: add outline logic insteadof selection under assemble view
|
||||
@@ -2147,6 +2157,9 @@ void GLCanvas3D::update_plate_thumbnails()
|
||||
|
||||
void GLCanvas3D::select_all()
|
||||
{
|
||||
if (!m_gizmos.is_allow_select_all()) {
|
||||
return;
|
||||
}
|
||||
m_selection.add_all();
|
||||
m_dirty = true;
|
||||
}
|
||||
@@ -2262,16 +2275,10 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
||||
void GLCanvas3D::mirror_selection(Axis axis)
|
||||
{
|
||||
TransformationType transformation_type;
|
||||
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
||||
transformation_type.set_local();
|
||||
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||
transformation_type.set_instance();
|
||||
|
||||
//transformation_type.set_world();
|
||||
transformation_type.set_relative();
|
||||
|
||||
m_selection.setup_cache();
|
||||
m_selection.mirror(axis, transformation_type);
|
||||
|
||||
do_mirror(L("Mirror Object"));
|
||||
// BBS
|
||||
//wxGetApp().obj_manipul()->set_dirty();
|
||||
@@ -4073,9 +4080,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
GLGizmosManager::EType c = m_gizmos.get_current_type();
|
||||
if (current_printer_technology() == ptFFF &&
|
||||
(fff_print()->config().print_sequence == PrintSequence::ByObject)) {
|
||||
if (c == GLGizmosManager::EType::Move ||
|
||||
c == GLGizmosManager::EType::Scale ||
|
||||
c == GLGizmosManager::EType::Rotate )
|
||||
if (can_sequential_clearance_show_in_gizmo())
|
||||
update_sequential_clearance();
|
||||
} else {
|
||||
if (c == GLGizmosManager::EType::Move ||
|
||||
@@ -4178,11 +4183,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
int volume_idx = get_first_hover_volume_idx();
|
||||
bool already_selected = m_selection.contains_volume(volume_idx);
|
||||
bool ctrl_down = evt.CmdDown();
|
||||
|
||||
bool alt_down = evt.AltDown();
|
||||
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
|
||||
|
||||
if (already_selected && ctrl_down)
|
||||
m_selection.remove(volume_idx);
|
||||
else if (alt_down) {
|
||||
Selection::EMode mode = Selection::Volume;
|
||||
if (already_selected) {
|
||||
std::vector<unsigned int> volume_idxs;
|
||||
for (auto idx : curr_idxs) { volume_idxs.emplace_back(idx); }
|
||||
m_selection.remove_volumes(mode, volume_idxs);
|
||||
}
|
||||
std::vector<unsigned int> add_volume_idxs;
|
||||
add_volume_idxs.emplace_back(volume_idx);
|
||||
m_selection.add_volumes(mode, add_volume_idxs, true);
|
||||
}
|
||||
else {
|
||||
m_selection.add(volume_idx, !ctrl_down, true);
|
||||
m_mouse.drag.move_requires_threshold = !already_selected;
|
||||
@@ -4299,7 +4315,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
// if dragging over blank area with left button, rotate
|
||||
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
|
||||
auto mult_pref = wxGetApp().app_config->get("camera_orbit_mult");
|
||||
const double mult = mult_pref.empty() ? 1.0 : std::stod(mult_pref);
|
||||
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.) * mult;
|
||||
if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports ||
|
||||
m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
|
||||
Vec3d rotate_target = Vec3d::Zero();
|
||||
@@ -4658,11 +4676,19 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
// Move instances/volumes
|
||||
ModelObject* model_object = m_model->objects[object_idx];
|
||||
if (model_object != nullptr) {
|
||||
if (selection_mode == Selection::Instance)
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
if (selection_mode == Selection::Instance) {
|
||||
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
if ((model_object->instances[instance_idx]->get_assemble_offset() - v->get_instance_offset()).norm() > 1e-2) {
|
||||
model_object->instances[instance_idx]->set_assemble_transformation(v->get_instance_transformation());
|
||||
}
|
||||
} else {
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
}
|
||||
}
|
||||
else if (selection_mode == Selection::Volume) {
|
||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||
auto cur_mv = model_object->volumes[volume_idx];
|
||||
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||
cur_mv->set_transformation(v->get_volume_transformation());
|
||||
// BBS: backup
|
||||
Slic3r::save_object_mesh(*model_object);
|
||||
}
|
||||
@@ -4769,11 +4795,17 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
// Rotate instances/volumes.
|
||||
ModelObject* model_object = m_model->objects[object_idx];
|
||||
if (model_object != nullptr) {
|
||||
if (selection_mode == Selection::Instance)
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
if (selection_mode == Selection::Instance) {
|
||||
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
model_object->instances[instance_idx]->set_assemble_from_transform(v->get_instance_transformation().get_matrix());
|
||||
} else {
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
}
|
||||
}
|
||||
else if (selection_mode == Selection::Volume) {
|
||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||
auto cur_mv = model_object->volumes[volume_idx];
|
||||
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||
cur_mv->set_transformation(v->get_volume_transformation());
|
||||
// BBS: backup
|
||||
Slic3r::save_object_mesh(*model_object);
|
||||
}
|
||||
@@ -4784,23 +4816,24 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
|
||||
//BBS: notify instance updates to part plater list
|
||||
m_selection.notify_instance_update(-1, -1);
|
||||
if (m_canvas_type != CanvasAssembleView) {
|
||||
// Fixes sinking/flying instances
|
||||
for (const std::pair<int, int> &i : done) {
|
||||
ModelObject *m = m_model->objects[i.first];
|
||||
|
||||
// Fixes sinking/flying instances
|
||||
for (const std::pair<int, int>& i : done) {
|
||||
ModelObject* m = m_model->objects[i.first];
|
||||
// BBS: don't call translate if the z is zero
|
||||
const double shift_z = m->get_instance_min_z(i.second);
|
||||
// leave sinking instances as sinking
|
||||
if ((min_zs.find({i.first, i.second})->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
// BBS: notify instance updates to part plater list
|
||||
m_selection.notify_instance_update(i.first, i.second);
|
||||
}
|
||||
|
||||
//BBS: don't call translate if the z is zero
|
||||
const double shift_z = m->get_instance_min_z(i.second);
|
||||
// leave sinking instances as sinking
|
||||
if ((min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
||||
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||
m_selection.translate(i.first, i.second, shift);
|
||||
m->translate_instance(i.second, shift);
|
||||
//BBS: notify instance updates to part plater list
|
||||
m_selection.notify_instance_update(i.first, i.second);
|
||||
wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
|
||||
}
|
||||
|
||||
wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
|
||||
}
|
||||
//BBS: nofity object list to update
|
||||
wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
|
||||
@@ -4850,12 +4883,14 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||
// Rotate instances/volumes
|
||||
ModelObject* model_object = m_model->objects[object_idx];
|
||||
if (model_object != nullptr) {
|
||||
if (selection_mode == Selection::Instance)
|
||||
if (selection_mode == Selection::Instance) {
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
}
|
||||
else if (selection_mode == Selection::Volume) {
|
||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
||||
auto cur_mv = model_object->volumes[volume_idx];
|
||||
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||
cur_mv->set_transformation(v->get_volume_transformation());
|
||||
// BBS: backup
|
||||
Slic3r::save_object_mesh(*model_object);
|
||||
}
|
||||
@@ -5211,6 +5246,17 @@ void GLCanvas3D::mouse_up_cleanup()
|
||||
m_canvas->ReleaseMouse();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::can_sequential_clearance_show_in_gizmo() {
|
||||
switch (m_gizmos.get_current_type()) {
|
||||
case GLGizmosManager::EType::Move:
|
||||
case GLGizmosManager::EType::Scale:
|
||||
case GLGizmosManager::EType::Rotate: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLCanvas3D::update_sequential_clearance()
|
||||
{
|
||||
if (current_printer_technology() != ptFFF || (fff_print()->config().print_sequence == PrintSequence::ByLayer))
|
||||
@@ -7267,6 +7313,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
|
||||
ECanvasType canvas_type = this->m_canvas_type;
|
||||
bool partly_inside_enable = canvas_type == ECanvasType::CanvasAssembleView ? false : true;
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
|
||||
@@ -7310,7 +7357,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||
else {
|
||||
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
partly_inside_enable);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -7344,7 +7392,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
partly_inside_enable);
|
||||
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
||||
const GLGizmosManager& gm = get_gizmos_manager();
|
||||
shader->stop_using();
|
||||
@@ -7412,19 +7461,11 @@ void GLCanvas3D::_render_sequential_clearance()
|
||||
{
|
||||
if (m_gizmos.is_dragging())
|
||||
return;
|
||||
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case GLGizmosManager::EType::Flatten:
|
||||
case GLGizmosManager::EType::Cut:
|
||||
// case GLGizmosManager::EType::Hollow:
|
||||
// case GLGizmosManager::EType::SlaSupports:
|
||||
case GLGizmosManager::EType::FdmSupports:
|
||||
case GLGizmosManager::EType::Seam: { return; }
|
||||
default: { break; }
|
||||
auto type = m_gizmos.get_current_type();
|
||||
if (type == GLGizmosManager::EType::Undefined
|
||||
|| can_sequential_clearance_show_in_gizmo()) {
|
||||
m_sequential_print_clearance.render();
|
||||
}
|
||||
|
||||
m_sequential_print_clearance.render();
|
||||
}
|
||||
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
@@ -8169,6 +8210,7 @@ void GLCanvas3D::_render_return_toolbar() const
|
||||
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
|
||||
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
|
||||
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
|
||||
wxGetApp().plater()->get_view3D_canvas3D()->reload_scene(true);
|
||||
}
|
||||
ImGui::PopStyleColor(5);
|
||||
ImGui::PopStyleVar(1);
|
||||
@@ -8368,8 +8410,45 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
float GLCanvas3D::_show_assembly_tooltip_information(float caption_max, float x, float y) const
|
||||
{
|
||||
ImGuiWrapper *imgui = wxGetApp().imgui();
|
||||
ImTextureID normal_id = m_gizmos.get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
|
||||
ImTextureID hover_id = m_gizmos.get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
|
||||
|
||||
caption_max += imgui->calc_text_size(": "sv).x + 35.f;
|
||||
|
||||
float scale = get_scale();
|
||||
ImVec2 button_size = ImVec2(25 * scale, 25 * scale); // ORCA: Use exact resolution will prevent blur on icon
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {0, ImGui::GetStyle().FramePadding.y});
|
||||
ImGui::ImageButton3(normal_id, hover_id, button_size);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip2(ImVec2(x, y));
|
||||
auto draw_text_with_caption = [this, &imgui, & caption_max](const wxString &caption, const wxString &text) {
|
||||
imgui->text_colored(ImGuiWrapper::COL_ACTIVE, caption);
|
||||
ImGui::SameLine(caption_max);
|
||||
imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
|
||||
};
|
||||
|
||||
for (const auto &t : std::array<std::string, 3>{"object_selection", "part_selection", "number_key"}) {
|
||||
draw_text_with_caption(m_assembly_view_desc.at(t + "_caption") + ": ", m_assembly_view_desc.at(t));
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
auto same_line_size = button_size.x * 1.8;//with an space size
|
||||
ImGui::SameLine(same_line_size);
|
||||
same_line_size = imgui->calc_text_size("|"sv).x + same_line_size + imgui->calc_text_size(" "sv).x;
|
||||
imgui->text_colored(ImGuiWrapper::COL_ACTIVE, "|");
|
||||
ImGui::SameLine(same_line_size);
|
||||
return same_line_size;
|
||||
}
|
||||
|
||||
//BBS
|
||||
void GLCanvas3D::_render_assemble_control() const
|
||||
void GLCanvas3D::_render_assemble_control()
|
||||
{
|
||||
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
|
||||
GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
|
||||
@@ -8390,8 +8469,8 @@ void GLCanvas3D::_render_assemble_control() const
|
||||
const float text_padding = 7.0f;
|
||||
const float text_size_x = std::max(imgui->calc_text_size(_L("Reset direction")).x + 2 * ImGui::GetStyle().FramePadding.x,
|
||||
std::max(imgui->calc_text_size(_L("Explosion Ratio")).x, imgui->calc_text_size(_L("Section View")).x));
|
||||
const float slider_width = 75.0f;
|
||||
const float value_size = imgui->calc_text_size(std::string_view{"3.00"}).x + text_padding * 2;
|
||||
const float slider_width = 60.0f;
|
||||
const float value_size = imgui->calc_text_size("3.00"sv).x + text_padding * 2;
|
||||
const float item_spacing = imgui->get_item_spacing().x;
|
||||
ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
|
||||
|
||||
@@ -8399,7 +8478,19 @@ void GLCanvas3D::_render_assemble_control() const
|
||||
imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
float tip_icon_size;
|
||||
{
|
||||
float caption_max = 0.f;
|
||||
for (const auto &t : std::array<std::string, 3>{"object_selection", "part_selection", "number_key"}) {
|
||||
caption_max = std::max(caption_max, imgui->calc_text_size(m_assembly_view_desc.at(t + "_caption")).x);
|
||||
}
|
||||
const ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
const float text_y =imgui->calc_text_size(_L("part selection")).y;
|
||||
float get_cur_x = pos.x;
|
||||
float get_cur_y = pos.y - ImGui::GetFrameHeight() - 4 * text_y;
|
||||
tip_icon_size =_show_assembly_tooltip_information(caption_max, get_cur_x, get_cur_y);
|
||||
}
|
||||
float same_line_width = tip_icon_size;
|
||||
{
|
||||
float clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position();
|
||||
if (clp_dist == 0.f) {
|
||||
@@ -8413,32 +8504,76 @@ void GLCanvas3D::_render_assemble_control() const
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine(window_padding.x + text_size_x + item_spacing);
|
||||
same_line_width += (text_size_x + item_spacing);
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(slider_width);
|
||||
bool view_slider_changed = imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||
|
||||
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 2);
|
||||
same_line_width += (slider_width + item_spacing);
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(value_size);
|
||||
bool view_input_changed = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (view_slider_changed || view_input_changed)
|
||||
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
|
||||
}
|
||||
|
||||
same_line_width += (value_size + item_spacing * 2);
|
||||
}
|
||||
{
|
||||
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 6 + value_size);
|
||||
auto temp_x = imgui->calc_text_size(_L("Explosion Ratio")).x;
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(temp_x);
|
||||
imgui->text(_L("Explosion Ratio"));
|
||||
|
||||
ImGui::SameLine(window_padding.x + 2 * text_size_x + slider_width + item_spacing * 7 + value_size);
|
||||
same_line_width += (temp_x + item_spacing);
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(slider_width);
|
||||
bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
|
||||
|
||||
ImGui::SameLine(window_padding.x + 2 * text_size_x + 2 * slider_width + item_spacing * 8 + value_size);
|
||||
same_line_width += (slider_width + item_spacing);
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(value_size);
|
||||
bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
|
||||
same_line_width += (value_size + item_spacing*2);
|
||||
}
|
||||
{
|
||||
ImGui::SameLine(same_line_width);
|
||||
// input
|
||||
std::vector<std::string> modes = {_u8L("Object"), _u8L("Part")};
|
||||
int selection_idx = m_selection.get_volume_selection_mode() == Selection::Instance ? 0 : 1;
|
||||
auto label = _u8L("Selection Mode") + ":" ;
|
||||
auto label_width = imgui->calc_text_size(label).x ;
|
||||
auto item_width = imgui->calc_text_size(_u8L("Object")).x * 2.5 + imgui->calc_text_size("xx"sv).x+ item_spacing;
|
||||
//render imgui
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::PushItemWidth(label_width);
|
||||
imgui->text(label);
|
||||
same_line_width += (label_width + item_spacing);
|
||||
ImGui::SameLine(same_line_width);
|
||||
ImGui::PushItemWidth(item_width);
|
||||
size_t selection_out = selection_idx;
|
||||
const char *selected_str = (selection_idx >= 0 && selection_idx < int(modes.size())) ? modes[selection_idx].c_str() : "";
|
||||
ImGuiWrapper::push_combo_style(get_scale());
|
||||
if (ImGui::BBLBeginCombo(("##" + label).c_str(), selected_str, 0)) {
|
||||
for (size_t line_idx = 0; line_idx < modes.size(); ++line_idx) {
|
||||
ImGui::PushID(int(line_idx));
|
||||
if (ImGui::Selectable("", line_idx == selection_idx))
|
||||
selection_out = line_idx;
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", modes[line_idx].c_str());
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGuiWrapper::pop_combo_style();
|
||||
if (selection_idx != selection_out) {//do
|
||||
if (selection_out == 0) { m_selection.unlock_volume_selection_mode(); }
|
||||
m_selection.set_volume_selection_mode(selection_out == 1 ? Selection::Volume : Selection::Instance);
|
||||
if (selection_out == 1) { m_selection.lock_volume_selection_mode(); }
|
||||
}
|
||||
same_line_width += (label_width + item_width);
|
||||
}
|
||||
imgui->end();
|
||||
|
||||
ImGuiWrapper::pop_toolbar_style();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "Camera.hpp"
|
||||
#include "SceneRaycaster.hpp"
|
||||
#include "IMToolbar.hpp"
|
||||
|
||||
#include "slic3r/GUI/3DBed.hpp"
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
|
||||
#include <float.h>
|
||||
@@ -512,6 +512,7 @@ private:
|
||||
wxGLContext* m_context;
|
||||
SceneRaycaster m_scene_raycaster;
|
||||
Bed3D &m_bed;
|
||||
std::map<std::string, wxString> m_assembly_view_desc;
|
||||
#if ENABLE_RETINA_GL
|
||||
std::unique_ptr<RetinaHelper> m_retina_helper;
|
||||
#endif
|
||||
@@ -611,8 +612,8 @@ private:
|
||||
|
||||
PrinterTechnology current_printer_technology() const;
|
||||
|
||||
|
||||
|
||||
bool m_show_world_axes{false};
|
||||
Bed3D::Axes m_axes;
|
||||
//BBS:record key botton frequency
|
||||
int auto_orient_count = 0;
|
||||
int auto_arrange_count = 0;
|
||||
@@ -807,6 +808,7 @@ public:
|
||||
void set_color_clip_plane(const Vec3d& cp_normal, double offset) { m_volumes.set_color_clip_plane(cp_normal, offset); }
|
||||
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_volumes.set_color_clip_plane_colors(colors); }
|
||||
|
||||
void set_show_world_axes(bool flag) { m_show_world_axes = flag; }
|
||||
void refresh_camera_scene_box();
|
||||
void set_color_by(const std::string& value);
|
||||
|
||||
@@ -1111,6 +1113,7 @@ public:
|
||||
m_sequential_print_clearance.set_polygons(polygons, height_polygons);
|
||||
}
|
||||
|
||||
bool can_sequential_clearance_show_in_gizmo();
|
||||
void update_sequential_clearance();
|
||||
|
||||
const Print* fff_print() const;
|
||||
@@ -1189,7 +1192,8 @@ private:
|
||||
// BBS
|
||||
//void _render_view_toolbar() const;
|
||||
void _render_paint_toolbar() const;
|
||||
void _render_assemble_control() const;
|
||||
float _show_assembly_tooltip_information(float caption_max, float x, float y) const;
|
||||
void _render_assemble_control();
|
||||
void _render_assemble_info() const;
|
||||
#if ENABLE_SHOW_CAMERA_TARGET
|
||||
void _render_camera_target();
|
||||
|
||||
+27
-26
@@ -1575,30 +1575,30 @@ void GUI_App::init_networking_callbacks()
|
||||
// GUI::wxGetApp().request_user_handle(online_login);
|
||||
// });
|
||||
|
||||
m_agent->set_server_callback([this](std::string url, int status) {
|
||||
|
||||
CallAfter([this]() {
|
||||
if (!m_server_error_dialog) {
|
||||
/*m_server_error_dialog->EndModal(wxCLOSE);
|
||||
m_server_error_dialog->Destroy();
|
||||
m_server_error_dialog = nullptr;*/
|
||||
m_server_error_dialog = new NetworkErrorDialog(mainframe);
|
||||
}
|
||||
|
||||
if(plater()->get_select_machine_dialog() && plater()->get_select_machine_dialog()->IsShown()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_server_error_dialog->m_show_again) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_server_error_dialog->IsShown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_server_error_dialog->ShowModal();
|
||||
});
|
||||
m_agent->set_server_callback([](std::string url, int status) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": server_callback, url=%1%, status=%2%") % url % status;
|
||||
//CallAfter([this]() {
|
||||
// if (!m_server_error_dialog) {
|
||||
// /*m_server_error_dialog->EndModal(wxCLOSE);
|
||||
// m_server_error_dialog->Destroy();
|
||||
// m_server_error_dialog = nullptr;*/
|
||||
// m_server_error_dialog = new NetworkErrorDialog(mainframe);
|
||||
// }
|
||||
//
|
||||
// if(plater()->get_select_machine_dialog() && plater()->get_select_machine_dialog()->IsShown()){
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (m_server_error_dialog->m_show_again) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (m_server_error_dialog->IsShown()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// m_server_error_dialog->ShowModal();
|
||||
//});
|
||||
});
|
||||
|
||||
|
||||
@@ -4789,6 +4789,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
[this, progressFn, cancelFn, finishFn, t = std::weak_ptr<int>(m_user_sync_token)] {
|
||||
// get setting list, update setting list
|
||||
std::string version = preset_bundle->get_vendor_profile_version(PresetBundle::ORCA_DEFAULT_BUNDLE).to_string();
|
||||
if(!m_agent) return;
|
||||
int ret = m_agent->get_setting_list2(version, [this](auto info) {
|
||||
auto type = info[BBL_JSON_KEY_TYPE];
|
||||
auto name = info[BBL_JSON_KEY_NAME];
|
||||
@@ -5923,7 +5924,7 @@ void GUI_App::MacOpenURL(const wxString& url)
|
||||
{
|
||||
if (url.empty())
|
||||
return;
|
||||
start_download(boost::nowide::narrow(url));
|
||||
start_download(into_u8(url));
|
||||
}
|
||||
|
||||
// wxWidgets override to get an event on open files.
|
||||
@@ -6685,7 +6686,7 @@ void GUI_App::associate_url(std::wstring url_prefix)
|
||||
}
|
||||
key_full = key_string;
|
||||
#elif defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
|
||||
DesktopIntegrationDialog::perform_downloader_desktop_integration(boost::nowide::narrow(url_prefix));
|
||||
DesktopIntegrationDialog::perform_downloader_desktop_integration(into_u8(url_prefix));
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace GUI {
|
||||
|
||||
enum class ECoordinatesType : unsigned char
|
||||
{
|
||||
World,
|
||||
World = 0,
|
||||
Instance,
|
||||
Local
|
||||
};
|
||||
|
||||
@@ -1192,6 +1192,8 @@ void ObjectList::OnContextMenu(wxDataViewEvent& evt)
|
||||
|
||||
void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_menu/* = false*/)
|
||||
{
|
||||
if (m_prevent_list_manipulation) return;
|
||||
|
||||
// Interesting fact: when mouse_pos.x < 0, HitTest(mouse_pos, item, col) returns item = null, but column = last column.
|
||||
// So, when mouse was moved to scene immediately after clicking in ObjectList, in the scene will be shown context menu for the Editing column.
|
||||
if (mouse_pos.x < 0)
|
||||
@@ -1289,7 +1291,7 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
|
||||
dynamic_cast<TabPrintPlate*>(wxGetApp().get_plate_tab())->reset_model_config();
|
||||
else if (m_objects_model->GetItemType(item) & itLayer)
|
||||
dynamic_cast<TabPrintLayer*>(wxGetApp().get_layer_tab())->reset_model_config();
|
||||
else
|
||||
else if (item.IsOk())
|
||||
dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config();
|
||||
}
|
||||
else if (col_num == colName)
|
||||
@@ -4668,6 +4670,7 @@ void ObjectList::select_item(std::function<wxDataViewItem()> get_item)
|
||||
return;
|
||||
|
||||
m_prevent_list_events = true;
|
||||
m_prevent_list_manipulation = true;
|
||||
|
||||
wxDataViewItem item = get_item();
|
||||
if (item.IsOk()) {
|
||||
@@ -4676,6 +4679,7 @@ void ObjectList::select_item(std::function<wxDataViewItem()> get_item)
|
||||
part_selection_changed();
|
||||
}
|
||||
|
||||
m_prevent_list_manipulation = false;
|
||||
m_prevent_list_events = false;
|
||||
}
|
||||
|
||||
@@ -4728,6 +4732,7 @@ void ObjectList::select_items(const std::vector<ObjectVolumeID>& ov_ids)
|
||||
void ObjectList::select_items(const wxDataViewItemArray& sels)
|
||||
{
|
||||
m_prevent_list_events = true;
|
||||
m_prevent_list_manipulation = true;
|
||||
m_last_selected_item = sels.empty() ? wxDataViewItem(nullptr) : sels.back();
|
||||
|
||||
UnselectAll();
|
||||
@@ -4742,6 +4747,7 @@ void ObjectList::select_items(const wxDataViewItemArray& sels)
|
||||
|
||||
part_selection_changed();
|
||||
|
||||
m_prevent_list_manipulation = false;
|
||||
m_prevent_list_events = false;
|
||||
}
|
||||
|
||||
@@ -4753,6 +4759,9 @@ void ObjectList::select_all()
|
||||
|
||||
void ObjectList::select_item_all_children()
|
||||
{
|
||||
if (wxGetApp().plater() && !wxGetApp().plater()->canvas3D()->get_gizmos_manager().is_allow_select_all()) {
|
||||
return;
|
||||
}
|
||||
wxDataViewItemArray sels;
|
||||
|
||||
// There is no selection before OR some object is selected => select all objects
|
||||
@@ -5418,7 +5427,7 @@ void ObjectList::fix_through_netfabb()
|
||||
}
|
||||
if (msg.IsEmpty())
|
||||
msg = _L("Repairing was canceled");
|
||||
plater->get_notification_manager()->push_notification(NotificationType::NetfabbFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, boost::nowide::narrow(msg));
|
||||
plater->get_notification_manager()->push_notification(NotificationType::NetfabbFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, into_u8(msg));
|
||||
}
|
||||
|
||||
void ObjectList::simplify()
|
||||
|
||||
@@ -175,6 +175,7 @@ private:
|
||||
bool m_prevent_list_events = false; // We use this flag to avoid circular event handling Select()
|
||||
// happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler
|
||||
// calls this method again and again and again
|
||||
bool m_prevent_list_manipulation = false;
|
||||
|
||||
bool m_prevent_update_filament_in_config = false; // We use this flag to avoid updating of the extruder value in config
|
||||
// during updating of the extruder count.
|
||||
|
||||
@@ -1890,6 +1890,7 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
|
||||
col->size = object_grid->GetTextExtent(L("Auto Brim")).x + 8; //add 8 for border
|
||||
col->choices.Add(_L("Auto"));
|
||||
col->choices.Add(_L("Mouse ear"));
|
||||
col->choices.Add(_L("Painted"));
|
||||
col->choices.Add(_L("Outer brim only"));
|
||||
col->choices.Add(_L("Inner brim only"));
|
||||
col->choices.Add(_L("Outer and inner brim"));
|
||||
|
||||
@@ -823,10 +823,10 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint
|
||||
m_canvas->enable_assemble_view_toolbar(false);
|
||||
m_canvas->enable_return_toolbar(true);
|
||||
m_canvas->enable_separator_toolbar(false);
|
||||
|
||||
//m_canvas->set_show_world_axes(true);//wait for GitHub users to see if they have this requirement
|
||||
// BBS: set volume_selection_mode to Volume
|
||||
m_canvas->get_selection().set_volume_selection_mode(Selection::Volume);
|
||||
m_canvas->get_selection().lock_volume_selection_mode();
|
||||
//same to 3d //m_canvas->get_selection().set_volume_selection_mode(Selection::Instance);
|
||||
//m_canvas->get_selection().lock_volume_selection_mode();
|
||||
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
||||
|
||||
@@ -227,7 +227,71 @@ bool GLGizmoBase::render_combo(const std::string &label, const std::vector<std::
|
||||
return is_changed;
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
void GLGizmoBase::render_cross_mark(const Vec3f &target, bool is_single)
|
||||
{
|
||||
const float half_length = 4.0f;
|
||||
|
||||
glsafe(::glLineWidth(2.0f));
|
||||
|
||||
auto render_line = [](const Vec3f& p1, const Vec3f& p2, const ColorRGBA& color) {
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = {GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
|
||||
init_data.color = color;
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(p1);
|
||||
init_data.add_vertex(p2);
|
||||
|
||||
// indices
|
||||
init_data.add_line(0, 1);
|
||||
|
||||
GLModel model;
|
||||
model.init_from(std::move(init_data));
|
||||
model.render();
|
||||
};
|
||||
|
||||
// draw line for x axis
|
||||
if (!is_single) {
|
||||
render_line(
|
||||
{target(0) - half_length, target(1), target(2)},
|
||||
{target(0) + half_length, target(1), target(2)},
|
||||
ColorRGBA::RED());
|
||||
}
|
||||
else {
|
||||
render_line(
|
||||
{target(0), target(1), target(2)},
|
||||
{target(0) + half_length, target(1), target(2)},
|
||||
ColorRGBA::RED());
|
||||
}
|
||||
// draw line for y axis
|
||||
if (!is_single) {
|
||||
render_line(
|
||||
{target(0), target(1) - half_length, target(2)},
|
||||
{target(0), target(1) + half_length, target(2)},
|
||||
ColorRGBA::GREEN());
|
||||
} else {
|
||||
render_line(
|
||||
{target(0), target(1), target(2)},
|
||||
{target(0), target(1) + half_length, target(2)},
|
||||
ColorRGBA::GREEN());
|
||||
}
|
||||
// draw line for z axis
|
||||
if (!is_single) {
|
||||
render_line(
|
||||
{target(0), target(1), target(2) - half_length},
|
||||
{target(0), target(1), target(2) + half_length},
|
||||
ColorRGBA::BLUE());
|
||||
} else {
|
||||
render_line(
|
||||
{target(0), target(1), target(2)},
|
||||
{target(0), target(1), target(2) + half_length},
|
||||
ColorRGBA::BLUE());
|
||||
}
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
|
||||
: m_parent(parent)
|
||||
, m_group_id(-1)
|
||||
, m_state(Off)
|
||||
|
||||
@@ -152,7 +152,7 @@ protected:
|
||||
|
||||
bool render_combo(const std::string &label, const std::vector<std::string> &lines,
|
||||
int &selection_idx, float label_width, float item_width);
|
||||
|
||||
void render_cross_mark(const Vec3f& target,bool is_single =false);
|
||||
public:
|
||||
GLGizmoBase(GLCanvas3D& parent,
|
||||
const std::string& icon_filename,
|
||||
|
||||
@@ -48,6 +48,7 @@ bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
|
||||
|
||||
void GLGizmoMove3D::data_changed(bool is_serializing) {
|
||||
m_grabbers[2].enabled = !m_parent.get_selection().is_wipe_tower();
|
||||
change_cs_by_selection();
|
||||
}
|
||||
|
||||
bool GLGizmoMove3D::on_init()
|
||||
@@ -67,7 +68,11 @@ bool GLGizmoMove3D::on_init()
|
||||
|
||||
std::string GLGizmoMove3D::on_get_name() const
|
||||
{
|
||||
return _u8L("Move");
|
||||
if (!on_is_activable() && m_state == EState::Off) {
|
||||
return _u8L("Move") + ":\n" + _u8L("Please select at least one object.");
|
||||
} else {
|
||||
return _u8L("Move");
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoMove3D::on_is_activable() const
|
||||
@@ -75,13 +80,21 @@ bool GLGizmoMove3D::on_is_activable() const
|
||||
return !m_parent.get_selection().is_empty();
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::on_set_state() {
|
||||
if (get_state() == On) {
|
||||
m_last_selected_obejct_idx = -1;
|
||||
m_last_selected_volume_idx = -1;
|
||||
change_cs_by_selection();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::on_start_dragging()
|
||||
{
|
||||
assert(m_hover_id != -1);
|
||||
|
||||
m_displacement = Vec3d::Zero();
|
||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
||||
m_starting_drag_position = m_grabbers[m_hover_id].matrix * m_grabbers[m_hover_id].center;
|
||||
m_starting_box_center = box.center();
|
||||
m_starting_box_bottom_center = box.center();
|
||||
m_starting_box_bottom_center(2) = box.min(2);
|
||||
@@ -121,42 +134,38 @@ void GLGizmoMove3D::on_render()
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
const Vec3d& center = box.center();
|
||||
const auto &[box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
|
||||
m_bounding_box = box;
|
||||
m_center = box_trafo.translation();
|
||||
if (m_object_manipulation) {
|
||||
m_object_manipulation->cs_center = box_trafo.translation();
|
||||
}
|
||||
const Transform3d base_matrix = box_trafo;
|
||||
float space_size = 20.f *INV_ZOOM;
|
||||
|
||||
#if ENABLE_FIXED_GRABBER
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
m_grabbers[i].matrix = base_matrix;
|
||||
}
|
||||
|
||||
const Vec3d zero = Vec3d::Zero();
|
||||
|
||||
// x axis
|
||||
m_grabbers[0].center = { box.max.x() + space_size, center.y(), center.z() };
|
||||
m_grabbers[0].center = {m_bounding_box.max.x() + space_size, 0, 0};
|
||||
// y axis
|
||||
m_grabbers[1].center = { center.x(), box.max.y() + space_size, center.z() };
|
||||
m_grabbers[1].center = {0, m_bounding_box.max.y() + space_size,0};
|
||||
// z axis
|
||||
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + space_size };
|
||||
m_grabbers[2].center = {0,0, m_bounding_box.max.z() + space_size};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
m_grabbers[i].color = AXES_COLOR[i];
|
||||
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i];
|
||||
}
|
||||
#else
|
||||
// x axis
|
||||
m_grabbers[0].center = { box.max.x() + Offset, center.y(), center.z() };
|
||||
m_grabbers[0].color = AXES_COLOR[0];
|
||||
|
||||
// y axis
|
||||
m_grabbers[1].center = { center.x(), box.max.y() + Offset, center.z() };
|
||||
m_grabbers[1].color = AXES_COLOR[1];
|
||||
|
||||
// z axis
|
||||
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
|
||||
m_grabbers[2].color = AXES_COLOR[2];
|
||||
#endif
|
||||
|
||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||
|
||||
auto render_grabber_connection = [this, ¢er](unsigned int id) {
|
||||
auto render_grabber_connection = [this, &zero](unsigned int id) {
|
||||
if (m_grabbers[id].enabled) {
|
||||
//if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
|
||||
m_grabber_connections[id].old_center = center;
|
||||
m_grabber_connections[id].old_center = m_grabbers[id].center;
|
||||
m_grabber_connections[id].model.reset();
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
@@ -166,7 +175,7 @@ void GLGizmoMove3D::on_render()
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex((Vec3f)center.cast<float>());
|
||||
init_data.add_vertex((Vec3f)zero.cast<float>());
|
||||
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
|
||||
|
||||
// indices
|
||||
@@ -186,7 +195,7 @@ void GLGizmoMove3D::on_render()
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
// draw axes
|
||||
@@ -199,6 +208,28 @@ void GLGizmoMove3D::on_render()
|
||||
|
||||
// draw grabbers
|
||||
render_grabbers(box);
|
||||
|
||||
if (m_object_manipulation->is_instance_coordinates()) {
|
||||
shader = wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
|
||||
Geometry::Transformation cur_tran;
|
||||
if (auto mi = m_parent.get_selection().get_selected_single_intance()) {
|
||||
cur_tran = mi->get_transformation();
|
||||
} else {
|
||||
cur_tran = selection.get_first_volume()->get_instance_transformation();
|
||||
}
|
||||
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * cur_tran.get_matrix());
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
render_cross_mark(Vec3f::Zero(), true);
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::on_register_raycasters_for_picking()
|
||||
@@ -245,5 +276,30 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
||||
|
||||
return projection;
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::change_cs_by_selection() {
|
||||
int obejct_idx, volume_idx;
|
||||
ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx);
|
||||
if (m_last_selected_obejct_idx == obejct_idx && m_last_selected_volume_idx == volume_idx) {
|
||||
return;
|
||||
}
|
||||
m_last_selected_obejct_idx = obejct_idx;
|
||||
m_last_selected_volume_idx = volume_idx;
|
||||
if (m_parent.get_selection().is_multiple_full_object()) {
|
||||
m_object_manipulation->set_use_object_cs(false);
|
||||
}
|
||||
else if (model_volume) {
|
||||
m_object_manipulation->set_use_object_cs(true);
|
||||
} else {
|
||||
m_object_manipulation->set_use_object_cs(false);
|
||||
}
|
||||
if (m_object_manipulation->get_use_object_cs()) {
|
||||
m_object_manipulation->set_coordinates_type(ECoordinatesType::Instance);
|
||||
} else {
|
||||
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -16,6 +16,8 @@ class GLGizmoMove3D : public GLGizmoBase
|
||||
static const double Offset;
|
||||
|
||||
Vec3d m_displacement{ Vec3d::Zero() };
|
||||
Vec3d m_center{ Vec3d::Zero() };
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
double m_snap_step{ 1.0 };
|
||||
Vec3d m_starting_drag_position{ Vec3d::Zero() };
|
||||
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
||||
@@ -57,6 +59,7 @@ protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override;
|
||||
bool on_is_activable() const override;
|
||||
virtual void on_set_state() override;
|
||||
void on_start_dragging() override;
|
||||
void on_stop_dragging() override;
|
||||
void on_dragging(const UpdateData& data) override;
|
||||
@@ -68,6 +71,9 @@ protected:
|
||||
|
||||
private:
|
||||
double calc_projection(const UpdateData& data) const;
|
||||
void change_cs_by_selection(); //cs mean Coordinate System
|
||||
private:
|
||||
int m_last_selected_obejct_idx, m_last_selected_volume_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -527,25 +527,6 @@ bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
|
||||
return use_grabbers(mouse_event);
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::data_changed(bool is_serializing) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
bool is_wipe_tower = selection.is_wipe_tower();
|
||||
if (is_wipe_tower) {
|
||||
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
float wipe_tower_rotation_angle =
|
||||
dynamic_cast<const ConfigOptionFloat *>(
|
||||
config.option("wipe_tower_rotation_angle"))
|
||||
->value;
|
||||
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
||||
m_gizmos[0].disable_grabber();
|
||||
m_gizmos[1].disable_grabber();
|
||||
} else {
|
||||
set_rotation(Vec3d::Zero());
|
||||
m_gizmos[0].enable_grabber();
|
||||
m_gizmos[1].enable_grabber();
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoRotate3D::on_init()
|
||||
{
|
||||
for (GLGizmoRotate& g : m_gizmos)
|
||||
@@ -561,7 +542,57 @@ bool GLGizmoRotate3D::on_init()
|
||||
|
||||
std::string GLGizmoRotate3D::on_get_name() const
|
||||
{
|
||||
return _u8L("Rotate");
|
||||
if (!on_is_activable() && m_state == EState::Off) {
|
||||
return _u8L("Rotate") + ":\n" + _u8L("Please select at least one object.");
|
||||
} else {
|
||||
return _u8L("Rotate");
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::on_set_state()
|
||||
{
|
||||
for (GLGizmoRotate &g : m_gizmos)
|
||||
g.set_state(m_state);
|
||||
if (get_state() == On) {
|
||||
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||
} else {
|
||||
m_last_volume = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::data_changed(bool is_serializing) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const GLVolume * volume = selection.get_first_volume();
|
||||
if (volume == nullptr) {
|
||||
m_last_volume = nullptr;
|
||||
return;
|
||||
}
|
||||
if (m_last_volume != volume) {
|
||||
m_last_volume = volume;
|
||||
Geometry::Transformation tran;
|
||||
if (selection.is_single_full_instance()) {
|
||||
tran = volume->get_instance_transformation();
|
||||
} else {
|
||||
tran = volume->get_volume_transformation();
|
||||
}
|
||||
m_object_manipulation->set_init_rotation(tran);
|
||||
}
|
||||
|
||||
bool is_wipe_tower = selection.is_wipe_tower();
|
||||
if (is_wipe_tower) {
|
||||
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
float wipe_tower_rotation_angle =
|
||||
dynamic_cast<const ConfigOptionFloat *>(
|
||||
config.option("wipe_tower_rotation_angle"))
|
||||
->value;
|
||||
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
||||
m_gizmos[0].disable_grabber();
|
||||
m_gizmos[1].disable_grabber();
|
||||
} else {
|
||||
set_rotation(Vec3d::Zero());
|
||||
m_gizmos[0].enable_grabber();
|
||||
m_gizmos[1].enable_grabber();
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoRotate3D::on_is_activable() const
|
||||
|
||||
@@ -151,11 +151,9 @@ public:
|
||||
protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override;
|
||||
void on_set_state() override {
|
||||
for (GLGizmoRotate& g : m_gizmos)
|
||||
g.set_state(m_state);
|
||||
}
|
||||
void on_set_hover_id() override {
|
||||
void on_set_state() override;
|
||||
void on_set_hover_id() override
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
|
||||
}
|
||||
@@ -179,7 +177,7 @@ protected:
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
private:
|
||||
|
||||
const GLVolume *m_last_volume;
|
||||
class RotoptimzeWindow
|
||||
{
|
||||
ImGuiWrapper *m_imgui = nullptr;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <wx/utils.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@@ -24,11 +24,11 @@ Vec3d GetIntersectionOfRayAndPlane(Vec3d ray_position, Vec3d ray_dir, Vec3d plan
|
||||
//BBS: GUI refactor: add obj manipulation
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
, m_scale(Vec3d::Ones())
|
||||
, m_offset(Vec3d::Zero())
|
||||
, m_snap_step(0.05)
|
||||
//BBS: GUI refactor: add obj manipulation
|
||||
, m_object_manipulation(obj_manipulation)
|
||||
, m_base_color(DEFAULT_BASE_COLOR)
|
||||
, m_drag_color(DEFAULT_DRAG_COLOR)
|
||||
, m_highlight_color(DEFAULT_HIGHLIGHT_COLOR)
|
||||
{
|
||||
m_grabber_connections[0].grabber_indices = { 0, 1 };
|
||||
m_grabber_connections[1].grabber_indices = { 2, 3 };
|
||||
@@ -39,6 +39,17 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filen
|
||||
m_grabber_connections[6].grabber_indices = { 9, 6 };
|
||||
}
|
||||
|
||||
const Vec3d &GLGizmoScale3D::get_scale()
|
||||
{
|
||||
if (m_object_manipulation) {
|
||||
Vec3d cache_scale = m_object_manipulation->get_cache().scale.cwiseQuotient(Vec3d(100,100,100));
|
||||
Vec3d temp_scale = cache_scale.cwiseProduct(m_scale);
|
||||
m_object_manipulation->limit_scaling_ratio(temp_scale);
|
||||
m_scale = temp_scale.cwiseQuotient(cache_scale);
|
||||
}
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
std::string GLGizmoScale3D::get_tooltip() const
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
@@ -70,77 +81,57 @@ std::string GLGizmoScale3D::get_tooltip() const
|
||||
return "";
|
||||
}
|
||||
|
||||
static int constraint_id(int grabber_id)
|
||||
{
|
||||
static const std::vector<int> id_map = { 1, 0, 3, 2, 5, 4, 8, 9, 6, 7 };
|
||||
return (0 <= grabber_id && grabber_id < (int)id_map.size()) ? id_map[grabber_id] : -1;
|
||||
}
|
||||
|
||||
bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
|
||||
{
|
||||
if (mouse_event.Dragging()) {
|
||||
if (m_dragging) {
|
||||
// Apply new temporary scale factors
|
||||
Selection& selection = m_parent.get_selection();
|
||||
TransformationType transformation_type;
|
||||
if (selection.is_single_full_instance()) {
|
||||
transformation_type.set_instance();
|
||||
} else if (selection.is_single_volume_or_modifier()) {
|
||||
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
||||
transformation_type.set_local();
|
||||
}
|
||||
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||
transformation_type.set_instance();
|
||||
|
||||
transformation_type.set_relative();
|
||||
|
||||
if (mouse_event.AltDown())
|
||||
transformation_type.set_independent();
|
||||
|
||||
selection.scale(m_scale, transformation_type);
|
||||
if (m_starting.ctrl_down && m_hover_id < 6) {
|
||||
// constrained scale:
|
||||
// uses the performed scale to calculate the new position of the constrained grabber
|
||||
// and from that calculates the offset (in world coordinates) to be applied to fullfill the constraint
|
||||
update_render_data();
|
||||
const Vec3d constraint_position = m_grabbers[constraint_id(m_hover_id)].center;
|
||||
// re-apply the scale because the selection always applies the transformations with respect to the initial state
|
||||
// set into on_start_dragging() with the call to selection.setup_cache()
|
||||
m_parent.get_selection().scale_and_translate(m_scale, m_starting.pivots[m_hover_id] - constraint_position, transformation_type);
|
||||
}
|
||||
Selection& selection = m_parent.get_selection();
|
||||
selection.scale_and_translate(get_scale(), get_offset(), transformation_type);
|
||||
}
|
||||
}
|
||||
return use_grabbers(mouse_event);
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::data_changed(bool is_serializing)
|
||||
{
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
||||
selection.is_single_volume_or_modifier();
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
m_grabbers[i].enabled = enable_scale_xyz;
|
||||
|
||||
set_scale(Vec3d::Ones());
|
||||
|
||||
change_cs_by_selection();
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
|
||||
{
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
m_grabbers[i].enabled = enable;
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::data_changed(bool is_serializing) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
||||
selection.is_single_volume_or_modifier();
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
m_grabbers[i].enabled = enable_scale_xyz;
|
||||
|
||||
set_scale(Vec3d::Ones());
|
||||
}
|
||||
|
||||
bool GLGizmoScale3D::on_init()
|
||||
{
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
m_grabbers.push_back(Grabber());
|
||||
}
|
||||
|
||||
double half_pi = 0.5 * (double)PI;
|
||||
|
||||
// x axis
|
||||
m_grabbers[0].angles(1) = half_pi;
|
||||
m_grabbers[1].angles(1) = half_pi;
|
||||
|
||||
// y axis
|
||||
m_grabbers[2].angles(0) = half_pi;
|
||||
m_grabbers[3].angles(0) = half_pi;
|
||||
|
||||
// BBS
|
||||
m_grabbers[4].enabled = false;
|
||||
@@ -151,7 +142,11 @@ bool GLGizmoScale3D::on_init()
|
||||
|
||||
std::string GLGizmoScale3D::on_get_name() const
|
||||
{
|
||||
return _u8L("Scale");
|
||||
if (!on_is_activable() && m_state == EState::Off) {
|
||||
return _u8L("Scale") + ":\n" + _u8L("Please select at least one object.");
|
||||
} else {
|
||||
return _u8L("Scale");
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoScale3D::on_is_activable() const
|
||||
@@ -160,21 +155,48 @@ bool GLGizmoScale3D::on_is_activable() const
|
||||
return !selection.is_empty() && !selection.is_wipe_tower();
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_set_state() {
|
||||
if (get_state() == On) {
|
||||
m_last_selected_obejct_idx = -1;
|
||||
m_last_selected_volume_idx = -1;
|
||||
change_cs_by_selection();
|
||||
}
|
||||
}
|
||||
|
||||
static int constraint_id(int grabber_id)
|
||||
{
|
||||
static const std::vector<int> id_map = {1, 0, 3, 2, 5, 4, 8, 9, 6, 7};
|
||||
return (0 <= grabber_id && grabber_id < (int) id_map.size()) ? id_map[grabber_id] : -1;
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_start_dragging()
|
||||
{
|
||||
assert(m_hover_id != -1);
|
||||
m_starting.drag_position = m_grabbers[m_hover_id].center;
|
||||
m_starting.plane_center = m_grabbers[4].center;
|
||||
m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].center;
|
||||
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||
m_starting.box = m_box;
|
||||
if (m_hover_id != -1) {
|
||||
auto grabbers_transform = m_grabbers_tran.get_matrix();
|
||||
m_starting.drag_position = grabbers_transform * m_grabbers[m_hover_id].center;
|
||||
m_starting.plane_center = grabbers_transform * m_grabbers[4].center; // plane_center = bottom center
|
||||
m_starting.plane_nromal = (grabbers_transform * m_grabbers[5].center - grabbers_transform * m_grabbers[4].center).normalized();
|
||||
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||
m_starting.box = m_bounding_box;
|
||||
|
||||
m_starting.pivots[0] = m_grabbers[1].center;
|
||||
m_starting.pivots[1] = m_grabbers[0].center;
|
||||
m_starting.pivots[2] = m_grabbers[3].center;
|
||||
m_starting.pivots[3] = m_grabbers[2].center;
|
||||
m_starting.pivots[4] = m_grabbers[5].center;
|
||||
m_starting.pivots[5] = m_grabbers[4].center;
|
||||
m_starting.center = m_center;
|
||||
m_starting.instance_center = m_instance_center;
|
||||
|
||||
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||
|
||||
m_starting.local_pivots[0] = Vec3d(box_half_size.x(), 0.0, -box_half_size.z());
|
||||
m_starting.local_pivots[1] = Vec3d(-box_half_size.x(), 0.0, -box_half_size.z());
|
||||
m_starting.local_pivots[2] = Vec3d(0.0, box_half_size.y(), -box_half_size.z());
|
||||
m_starting.local_pivots[3] = Vec3d(0.0, -box_half_size.y(), -box_half_size.z());
|
||||
m_starting.local_pivots[4] = Vec3d(0.0, 0.0, box_half_size.z());
|
||||
m_starting.local_pivots[5] = Vec3d(0.0, 0.0, -box_half_size.z());
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
m_starting.pivots[i] = grabbers_transform * m_starting.local_pivots[i]; // todo delete
|
||||
}
|
||||
m_starting.constraint_position = grabbers_transform * m_grabbers[constraint_id(m_hover_id)].center;
|
||||
m_scale = m_starting.scale = Vec3d::Ones() ;
|
||||
m_offset = Vec3d::Zero();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_stop_dragging()
|
||||
@@ -185,26 +207,95 @@ void GLGizmoScale3D::on_stop_dragging()
|
||||
|
||||
void GLGizmoScale3D::on_dragging(const UpdateData& data)
|
||||
{
|
||||
if (m_hover_id == 0 || m_hover_id == 1)
|
||||
if ((m_hover_id == 0) || (m_hover_id == 1))
|
||||
do_scale_along_axis(X, data);
|
||||
else if (m_hover_id == 2 || m_hover_id == 3)
|
||||
else if ((m_hover_id == 2) || (m_hover_id == 3))
|
||||
do_scale_along_axis(Y, data);
|
||||
else if (m_hover_id == 4 || m_hover_id == 5)
|
||||
else if ((m_hover_id == 4) || (m_hover_id == 5))
|
||||
do_scale_along_axis(Z, data);
|
||||
else if (m_hover_id >= 6)
|
||||
do_scale_uniform(data);
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::update_grabbers_data()
|
||||
{
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const auto &[box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
|
||||
m_bounding_box = box;
|
||||
m_center = box_trafo.translation();
|
||||
m_grabbers_tran.set_matrix(box_trafo);
|
||||
m_instance_center = (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) ? selection.get_first_volume()->get_instance_offset() : m_center;
|
||||
|
||||
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||
bool ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||
|
||||
|
||||
bool single_instance = selection.is_single_full_instance();
|
||||
bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
|
||||
|
||||
// x axis
|
||||
m_grabbers[0].center = Vec3d(-(box_half_size.x()), 0.0, -box_half_size.z());
|
||||
m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||
m_grabbers[1].center = Vec3d(box_half_size.x(), 0.0, -box_half_size.z());
|
||||
m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||
// y axis
|
||||
m_grabbers[2].center = Vec3d(0.0, -(box_half_size.y()), -box_half_size.z());
|
||||
m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||
m_grabbers[3].center = Vec3d(0.0, box_half_size.y(), -box_half_size.z());
|
||||
m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||
// z axis do not show 4
|
||||
m_grabbers[4].center = Vec3d(0.0, 0.0, -(box_half_size.z()));
|
||||
m_grabbers[4].enabled = false;
|
||||
|
||||
m_grabbers[5].center = Vec3d(0.0, 0.0, box_half_size.z());
|
||||
m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||
// uniform
|
||||
m_grabbers[6].center = Vec3d(-box_half_size.x(), -box_half_size.y(), -box_half_size.z());
|
||||
m_grabbers[6].color = (ctrl_down && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||
m_grabbers[7].center = Vec3d(box_half_size.x(), -box_half_size.y(), -box_half_size.z());
|
||||
m_grabbers[7].color = (ctrl_down && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||
m_grabbers[8].center = Vec3d(box_half_size.x(), box_half_size.y(), -box_half_size.z());
|
||||
m_grabbers[8].color = (ctrl_down && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||
m_grabbers[9].center = Vec3d(-box_half_size.x(), box_half_size.y(), -box_half_size.z());
|
||||
m_grabbers[9].color = (ctrl_down && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
//m_grabbers[i].color = AXES_COLOR[i / 2];
|
||||
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i / 2];
|
||||
}
|
||||
for (int i = 6; i < 10; ++i) {
|
||||
//m_grabbers[i].color = GRABBER_UNIFORM_COL;
|
||||
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
m_grabbers[i].matrix = m_grabbers_tran.get_matrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLGizmoScale3D::change_cs_by_selection() {
|
||||
int obejct_idx, volume_idx;
|
||||
ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx);
|
||||
if (m_last_selected_obejct_idx == obejct_idx && m_last_selected_volume_idx == volume_idx) { return; }
|
||||
m_last_selected_obejct_idx = obejct_idx;
|
||||
m_last_selected_volume_idx = volume_idx;
|
||||
if (m_parent.get_selection().is_multiple_full_object()) {
|
||||
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||
} else if (model_volume) {
|
||||
m_object_manipulation->set_coordinates_type(ECoordinatesType::Local);
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_render()
|
||||
{
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
update_render_data();
|
||||
update_grabbers_data();
|
||||
|
||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||
|
||||
const float grabber_mean_size = (float) ((m_box.size().x() + m_box.size().y() + m_box.size().z()) / 3.0);
|
||||
const float grabber_mean_size = (float)((m_bounding_box.size().x() + m_bounding_box.size().y() + m_bounding_box.size().z()) / 3.0);
|
||||
|
||||
//draw connections
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
@@ -213,7 +304,7 @@ void GLGizmoScale3D::on_render()
|
||||
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
|
||||
//if (single_instance || single_volume) {
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * m_grabbers_tran.get_matrix());
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
if (m_grabbers[4].enabled && m_grabbers[5].enabled)
|
||||
render_grabbers_connection(4, 5, m_grabbers[4].color);
|
||||
@@ -298,29 +389,53 @@ void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit
|
||||
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||
{
|
||||
double ratio = calc_ratio(data);
|
||||
if (ratio > 0.0) {
|
||||
Vec3d curr_scale = m_scale;
|
||||
curr_scale(axis) = m_starting.scale(axis) * ratio;
|
||||
m_scale = curr_scale;
|
||||
if (ratio > 0.0)
|
||||
{
|
||||
m_scale(axis) = m_starting.scale(axis) * ratio;
|
||||
if (m_starting.ctrl_down && abs(ratio-1.0f)>0.001) {
|
||||
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
|
||||
if (m_hover_id == 2 * axis) {
|
||||
local_offset *= -1.0;
|
||||
}
|
||||
Vec3d local_offset_vec;
|
||||
switch (axis)
|
||||
{
|
||||
case X: { local_offset_vec = local_offset * Vec3d::UnitX(); break; }
|
||||
case Y: { local_offset_vec = local_offset * Vec3d::UnitY(); break;}
|
||||
case Z: { local_offset_vec = local_offset * Vec3d::UnitZ(); break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
if (m_object_manipulation->is_world_coordinates()) {
|
||||
m_offset = local_offset_vec;
|
||||
} else {//if (m_object_manipulation->is_instance_coordinates())
|
||||
m_offset = m_grabbers_tran.get_matrix_no_offset() * local_offset_vec;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_offset = Vec3d::Zero();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::do_scale_uniform(const UpdateData & data)
|
||||
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
||||
{
|
||||
const double ratio = calc_ratio(data);
|
||||
double ratio = calc_ratio(data);
|
||||
if (ratio > 0.0)
|
||||
{
|
||||
m_scale = m_starting.scale * ratio;
|
||||
m_offset = Vec3d::Zero();
|
||||
}
|
||||
}
|
||||
|
||||
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||
{
|
||||
double ratio = 0.0;
|
||||
|
||||
Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.plane_center;
|
||||
|
||||
Vec3d pivot = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center
|
||||
Vec3d starting_vec = m_starting.drag_position - pivot;
|
||||
double len_starting_vec = starting_vec.norm();
|
||||
if (len_starting_vec != 0.0) {
|
||||
if (len_starting_vec != 0.0)
|
||||
{
|
||||
Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
||||
Vec3d plane_normal = m_starting.plane_nromal;
|
||||
if (m_hover_id == 5) {
|
||||
@@ -328,10 +443,16 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||
Vec3d plane_vec = mouse_dir.cross(m_starting.plane_nromal);
|
||||
plane_normal = plane_vec.cross(m_starting.plane_nromal);
|
||||
}
|
||||
|
||||
plane_normal = plane_normal.normalized();
|
||||
// finds the intersection of the mouse ray with the plane that the drag point moves
|
||||
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection
|
||||
Vec3d inters = GetIntersectionOfRayAndPlane(data.mouse_ray.a, mouse_dir, m_starting.drag_position, plane_normal.normalized());
|
||||
auto dot_value = (plane_normal.dot(mouse_dir));
|
||||
auto angle = Geometry::rad2deg(acos(dot_value));
|
||||
auto big_than_min_angle = abs(angle) < 95 && abs(angle) > 85;
|
||||
if (big_than_min_angle) {
|
||||
return 1;
|
||||
}
|
||||
Vec3d inters = GetIntersectionOfRayAndPlane(data.mouse_ray.a, mouse_dir, m_starting.drag_position, plane_normal);
|
||||
|
||||
Vec3d inters_vec = inters - m_starting.drag_position;
|
||||
|
||||
@@ -347,78 +468,5 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||
return ratio;
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::update_render_data()
|
||||
{
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
bool single_instance = selection.is_single_full_instance();
|
||||
bool single_volume = selection.is_single_volume_or_modifier();
|
||||
|
||||
m_box.reset();
|
||||
m_transform = Transform3d::Identity();
|
||||
Vec3d angles = Vec3d::Zero();
|
||||
|
||||
if (single_instance) {
|
||||
// calculate bounding box in instance local reference system
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
for (unsigned int idx : idxs) {
|
||||
const GLVolume* vol = selection.get_volume(idx);
|
||||
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
|
||||
}
|
||||
|
||||
// gets transform from first selected volume
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
m_transform = v->get_instance_transformation().get_matrix();
|
||||
// gets angles from first selected volume
|
||||
angles = v->get_instance_rotation();
|
||||
}
|
||||
else if (single_volume) {
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
m_box = v->bounding_box();
|
||||
m_transform = v->world_matrix();
|
||||
angles = Geometry::extract_euler_angles(m_transform);
|
||||
}
|
||||
else
|
||||
m_box = selection.get_bounding_box();
|
||||
|
||||
const Vec3d& center = m_box.center();
|
||||
|
||||
// x axis
|
||||
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z());
|
||||
m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), m_box.min.z());
|
||||
|
||||
// y axis
|
||||
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), m_box.min.z());
|
||||
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), m_box.min.z());
|
||||
|
||||
// z axis do not show 4
|
||||
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z());
|
||||
m_grabbers[4].enabled = false;
|
||||
|
||||
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z());
|
||||
|
||||
// uniform
|
||||
m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), m_box.min.z());
|
||||
m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), m_box.min.z());
|
||||
m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), m_box.min.z());
|
||||
m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), m_box.min.z());
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
m_grabbers[i].color = AXES_COLOR[i/2];
|
||||
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i/2];
|
||||
}
|
||||
|
||||
for (int i = 6; i < 10; ++i) {
|
||||
m_grabbers[i].color = GRABBER_UNIFORM_COL;
|
||||
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
|
||||
}
|
||||
|
||||
// sets grabbers orientation
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
m_grabbers[i].angles = angles;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -19,25 +19,28 @@ class GLGizmoScale3D : public GLGizmoBase
|
||||
{
|
||||
Vec3d scale;
|
||||
Vec3d drag_position;
|
||||
Vec3d constraint_position;
|
||||
Vec3d center{Vec3d::Zero()};//sphere bounding box center
|
||||
Vec3d instance_center{Vec3d::Zero()};
|
||||
Vec3d plane_center; // keep the relative center position for scale in the bottom plane
|
||||
Vec3d plane_nromal; // keep the bottom plane
|
||||
Vec3d plane_nromal; // keep the bottom plane
|
||||
BoundingBoxf3 box;
|
||||
Vec3d pivots[6];
|
||||
Vec3d pivots[6];// Vec3d constraint_position{Vec3d::Zero()};
|
||||
Vec3d local_pivots[6];
|
||||
bool ctrl_down;
|
||||
|
||||
StartingData() : scale(Vec3d::Ones()), drag_position(Vec3d::Zero()), ctrl_down(false) { for (int i = 0; i < 5; ++i) { pivots[i] = Vec3d::Zero(); } }
|
||||
};
|
||||
|
||||
BoundingBoxf3 m_box;
|
||||
Transform3d m_transform;
|
||||
Vec3d m_scale{ Vec3d::Ones() };
|
||||
double m_snap_step{ 0.05 };
|
||||
mutable BoundingBoxf3 m_bounding_box;
|
||||
Geometry::Transformation m_grabbers_tran;//m_grabbers_transform
|
||||
Vec3d m_center{Vec3d::Zero()};
|
||||
Vec3d m_instance_center{Vec3d::Zero()};
|
||||
Vec3d m_scale;
|
||||
Vec3d m_offset;
|
||||
double m_snap_step;
|
||||
StartingData m_starting;
|
||||
|
||||
ColorRGBA m_base_color;
|
||||
ColorRGBA m_drag_color;
|
||||
ColorRGBA m_highlight_color;
|
||||
|
||||
struct GrabberConnection
|
||||
{
|
||||
GLModel model;
|
||||
@@ -58,9 +61,11 @@ public:
|
||||
double get_snap_step(double step) const { return m_snap_step; }
|
||||
void set_snap_step(double step) { m_snap_step = step; }
|
||||
|
||||
const Vec3d& get_scale() const { return m_scale; }
|
||||
const Vec3d &get_scale();
|
||||
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
|
||||
|
||||
const Vec3d& get_offset() const { return m_offset; }
|
||||
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
/// <summary>
|
||||
@@ -76,6 +81,7 @@ protected:
|
||||
virtual bool on_init() override;
|
||||
virtual std::string on_get_name() const override;
|
||||
virtual bool on_is_activable() const override;
|
||||
virtual void on_set_state() override;
|
||||
virtual void on_start_dragging() override;
|
||||
virtual void on_stop_dragging() override;
|
||||
virtual void on_dragging(const UpdateData& data) override;
|
||||
@@ -92,7 +98,10 @@ private:
|
||||
void do_scale_uniform(const UpdateData& data);
|
||||
|
||||
double calc_ratio(const UpdateData& data) const;
|
||||
void update_render_data();
|
||||
void update_grabbers_data();
|
||||
void change_cs_by_selection(); // cs mean Coordinate System
|
||||
private:
|
||||
int m_last_selected_obejct_idx, m_last_selected_volume_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1024,20 +1024,6 @@ void GLGizmoText::show_tooltip_information(float x, float y)
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
ModelVolume *GLGizmoText::get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const
|
||||
{
|
||||
if (m_parent.get_selection().is_single_volume() || m_parent.get_selection().is_single_modifier()) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const GLVolume * gl_volume = selection.get_first_volume();
|
||||
out_object_idx = gl_volume->object_idx();
|
||||
ModelObject *model_object = selection.get_model()->objects[out_object_idx];
|
||||
out_volume_idx = gl_volume->volume_idx();
|
||||
if (out_volume_idx < model_object->volumes.size())
|
||||
return model_object->volumes[out_volume_idx];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GLGizmoText::reset_text_info()
|
||||
{
|
||||
m_font_name = "";
|
||||
|
||||
@@ -62,7 +62,9 @@ std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
|
||||
out.reserve(m_gizmos.size());
|
||||
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
for (size_t i = 0; i < m_gizmos.size(); ++i)
|
||||
if (m_gizmos[i]->get_sprite_id() == (unsigned int) Measure ||
|
||||
if (m_gizmos[i]->get_sprite_id() == (unsigned int) Move ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Rotate ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Measure ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Assembly ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) MmuSegmentation)
|
||||
out.push_back(i);
|
||||
@@ -247,6 +249,16 @@ bool GLGizmosManager::init_icon_textures()
|
||||
else
|
||||
return false;
|
||||
|
||||
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_reset_zero.svg", 14, 14, texture_id))
|
||||
icon_list.insert(std::make_pair((int) IC_TOOLBAR_RESET_ZERO, texture_id));
|
||||
else
|
||||
return false;
|
||||
|
||||
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_reset_zero_hover.svg", 14, 14, texture_id))
|
||||
icon_list.insert(std::make_pair((int) IC_TOOLBAR_RESET_ZERO_HOVER, texture_id));
|
||||
else
|
||||
return false;
|
||||
|
||||
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_tooltip.svg", 25, 25, texture_id)) // ORCA: Use same resolution with gizmos to prevent blur on icon
|
||||
icon_list.insert(std::make_pair((int)IC_TOOLBAR_TOOLTIP, texture_id));
|
||||
else
|
||||
@@ -371,6 +383,9 @@ void GLGizmosManager::update_assemble_view_data()
|
||||
void GLGizmosManager::update_data()
|
||||
{
|
||||
if (!m_enabled) return;
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
if (m_common_gizmos_data)
|
||||
m_common_gizmos_data->update(get_current()
|
||||
? get_current()->get_requirements()
|
||||
@@ -381,8 +396,10 @@ void GLGizmosManager::update_data()
|
||||
if (m_current != Flatten && !m_gizmos.empty()) m_gizmos[Flatten]->data_changed(m_serializing);
|
||||
|
||||
//BBS: GUI refactor: add object manipulation in gizmo
|
||||
m_object_manipulation.update_ui_from_settings();
|
||||
m_object_manipulation.UpdateAndShow(true);
|
||||
if (!selection.is_empty()) {
|
||||
m_object_manipulation.update_ui_from_settings();
|
||||
m_object_manipulation.UpdateAndShow(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmosManager::is_running() const
|
||||
@@ -461,6 +478,22 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLGizmosManager::is_paint_gizmo()
|
||||
{
|
||||
return m_current == EType::FdmSupports ||
|
||||
m_current == EType::MmuSegmentation ||
|
||||
m_current == EType::Seam;
|
||||
}
|
||||
|
||||
bool GLGizmosManager::is_allow_select_all() {
|
||||
if (m_current == Undefined || m_current == EType::Move||
|
||||
m_current == EType::Rotate ||
|
||||
m_current == EType::Scale) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ClippingPlane GLGizmosManager::get_clipping_plane() const
|
||||
{
|
||||
if (! m_common_gizmos_data
|
||||
|
||||
@@ -164,6 +164,8 @@ public:
|
||||
enum MENU_ICON_NAME {
|
||||
IC_TOOLBAR_RESET = 0,
|
||||
IC_TOOLBAR_RESET_HOVER,
|
||||
IC_TOOLBAR_RESET_ZERO,
|
||||
IC_TOOLBAR_RESET_ZERO_HOVER,
|
||||
IC_TOOLBAR_TOOLTIP,
|
||||
IC_TOOLBAR_TOOLTIP_HOVER,
|
||||
IC_NAME_COUNT,
|
||||
@@ -261,6 +263,8 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool is_paint_gizmo();
|
||||
bool is_allow_select_all();
|
||||
ClippingPlane get_clipping_plane() const;
|
||||
ClippingPlane get_assemble_view_clipping_plane() const;
|
||||
bool wants_reslice_supports_on_undo() const;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include <float.h>
|
||||
|
||||
#include "slic3r/GUI/GUI_Geometry.hpp"
|
||||
@@ -30,6 +31,8 @@ public:
|
||||
Vec3d position_rounded;
|
||||
Vec3d rotation;
|
||||
Vec3d rotation_rounded;
|
||||
Vec3d absolute_rotation;
|
||||
Vec3d absolute_rotation_rounded;
|
||||
Vec3d scale;
|
||||
Vec3d scale_rounded;
|
||||
Vec3d size;
|
||||
@@ -56,7 +59,7 @@ public:
|
||||
Cache m_cache;
|
||||
|
||||
bool m_imperial_units { false };
|
||||
|
||||
bool m_use_object_cs{false};
|
||||
// Mirroring buttons and their current state
|
||||
//enum MirrorButtonState {
|
||||
// mbHidden,
|
||||
@@ -75,19 +78,28 @@ public:
|
||||
std::string m_new_unit_string;
|
||||
Vec3d m_new_position;
|
||||
Vec3d m_new_rotation;
|
||||
Vec3d m_new_absolute_rotation;
|
||||
Vec3d m_new_scale;
|
||||
Vec3d m_new_size;
|
||||
Vec3d m_unscale_size;
|
||||
Vec3d m_buffered_position;
|
||||
Vec3d m_buffered_rotation;
|
||||
Vec3d m_buffered_absolute_rotation;
|
||||
Vec3d m_buffered_scale;
|
||||
Vec3d m_buffered_size;
|
||||
Vec3d cs_center;
|
||||
bool m_new_enabled {true};
|
||||
bool m_uniform_scale {true};
|
||||
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
ECoordinatesType m_coordinates_type{ECoordinatesType::World};
|
||||
|
||||
bool m_show_reset_0_rotation{false};
|
||||
bool m_show_clear_rotation { false };
|
||||
bool m_show_clear_scale { false };
|
||||
bool m_show_drop_to_bed { false };
|
||||
enum class RotateType { None, Relative, Absolute
|
||||
};
|
||||
RotateType m_last_rotate_type{RotateType::None}; // 0:no input 1:relative 2:absolute
|
||||
|
||||
protected:
|
||||
float last_move_input_window_width = 0.0f;
|
||||
@@ -108,21 +120,33 @@ public:
|
||||
|
||||
void set_uniform_scaling(const bool uniform_scale);
|
||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||
void set_use_object_cs(bool flag){ if (m_use_object_cs != flag) m_use_object_cs = flag; }
|
||||
bool get_use_object_cs() { return m_use_object_cs; }
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
void set_coordinates_type(ECoordinatesType type);
|
||||
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
|
||||
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
||||
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
||||
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
||||
|
||||
void set_coordinates_type(ECoordinatesType type);
|
||||
ECoordinatesType get_coordinates_type() const;
|
||||
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
||||
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
||||
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
||||
|
||||
const Cache& get_cache() {return m_cache; }
|
||||
void reset_cache() { m_cache.reset(); }
|
||||
|
||||
void limit_scaling_ratio(Vec3d &scaling_factor) const;
|
||||
void on_change(const std::string& opt_key, int axis, double new_value);
|
||||
bool render_combo(ImGuiWrapper *imgui_wrapper, const std::string &label, const std::vector<std::string> &lines, size_t &selection_idx, float label_width, float item_width);
|
||||
void do_render_move_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||
void do_render_rotate_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||
void do_render_scale_input_window(ImGuiWrapper* imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||
float max_unit_size(int number, Vec3d &vec1, Vec3d &vec2,std::string str);
|
||||
bool reset_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
|
||||
bool reset_zero_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
|
||||
bool bbl_checkbox(const wxString &label, bool &value);
|
||||
|
||||
void show_move_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||
void show_rotate_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||
void show_scale_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||
void set_init_rotation(const Geometry::Transformation &value);
|
||||
|
||||
private:
|
||||
void reset_settings_value();
|
||||
@@ -134,18 +158,24 @@ private:
|
||||
//Show or hide mirror buttons
|
||||
//void update_mirror_buttons_visibility();
|
||||
|
||||
// change values
|
||||
// change values
|
||||
void change_position_value(int axis, double value);
|
||||
void change_rotation_value(int axis, double value);
|
||||
void change_absolute_rotation_value(int axis, double value);
|
||||
void change_scale_value(int axis, double value);
|
||||
void change_size_value(int axis, double value);
|
||||
void do_scale(int axis, const Vec3d &scale) const;
|
||||
void reset_position_value();
|
||||
void reset_rotation_value();
|
||||
void reset_rotation_value(bool reset_relative);
|
||||
void reset_scale_value();
|
||||
|
||||
GLCanvas3D& m_glcanvas;
|
||||
unsigned int m_last_active_item { 0 };
|
||||
std::map<std::string, wxString> m_desc_move;
|
||||
std::map<std::string, wxString> m_desc_rotate;
|
||||
std::map<std::string, wxString> m_desc_scale;
|
||||
Vec3d m_init_rotation;
|
||||
Transform3d m_init_rotation_scale_tran;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -71,6 +71,9 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
||||
{ImGui::GapFillIcon , "gap_fill" },
|
||||
{ImGui::FoldButtonIcon , "im_fold" },
|
||||
{ImGui::UnfoldButtonIcon , "im_unfold" },
|
||||
{ImGui::gCodeButtonIcon , "im_code" }, //ORCA
|
||||
{ImGui::VisibleIcon , "im_visible" }, //ORCA
|
||||
{ImGui::HiddenIcon , "im_hidden" }, //ORCA
|
||||
{ImGui::SphereButtonIcon , "toolbar_modifier_sphere" },
|
||||
// dark mode icon
|
||||
{ImGui::MinimalizeDarkButton , "notification_minimalize_dark" },
|
||||
|
||||
@@ -2681,7 +2681,7 @@ void MainFrame::init_menubar_as_editor()
|
||||
viewMenu->Check(wxID_CAMERA_PERSPECTIVE + camera_id_base, true);
|
||||
else
|
||||
viewMenu->Check(wxID_CAMERA_ORTHOGONAL + camera_id_base, true);
|
||||
}, wxID_ANY);
|
||||
}, perspective_item->GetId());
|
||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Auto Perspective"), _L("Automatically switch between orthographic and perspective when changing from top/bottom/side views"),
|
||||
[this](wxCommandEvent&) {
|
||||
wxGetApp().app_config->set_bool("auto_perspective", !wxGetApp().app_config->get_bool("auto_perspective"));
|
||||
|
||||
@@ -1151,12 +1151,12 @@ bool Mouse3DController::connect_device()
|
||||
if (m_device != nullptr) {
|
||||
wchar_t buffer[1024];
|
||||
hid_get_manufacturer_string(m_device, buffer, 1024);
|
||||
m_device_str = boost::nowide::narrow(buffer);
|
||||
m_device_str = into_u8(buffer);
|
||||
// #3479 seems to show that sometimes an extra whitespace is added, so we remove it
|
||||
boost::algorithm::trim(m_device_str);
|
||||
|
||||
hid_get_product_string(m_device, buffer, 1024);
|
||||
m_device_str += "/" + boost::nowide::narrow(buffer);
|
||||
m_device_str += "/" + into_u8(buffer);
|
||||
// #3479 seems to show that sometimes an extra whitespace is added, so we remove it
|
||||
boost::algorithm::trim(m_device_str);
|
||||
|
||||
|
||||
@@ -1364,7 +1364,7 @@ void NotificationManager::URLDownloadNotification::render_pause_button_inner(ImG
|
||||
button_text = m_is_dark ? (m_download_paused ? ImGui::PlayHoverDarkButton : ImGui::PauseHoverDarkButton) : (m_download_paused ? ImGui::PlayHoverButton : ImGui::PauseHoverButton);
|
||||
}
|
||||
|
||||
ImVec2 button_pic_size = ImGui::CalcTextSize(boost::nowide::narrow(button_text).c_str());
|
||||
ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str());
|
||||
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f);
|
||||
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
|
||||
@@ -1405,7 +1405,7 @@ void NotificationManager::URLDownloadNotification::render_open_button_inner(ImGu
|
||||
button_text = m_is_dark ? ImGui::OpenHoverDarkButton : ImGui::OpenHoverButton;
|
||||
}
|
||||
|
||||
ImVec2 button_pic_size = ImGui::CalcTextSize(boost::nowide::narrow(button_text).c_str());
|
||||
ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str());
|
||||
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f);
|
||||
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
|
||||
|
||||
@@ -2074,6 +2074,16 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
||||
if (instance_box.max.z() > plate_box.min.z())
|
||||
plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking
|
||||
|
||||
if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
|
||||
// Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
|
||||
if (plate_box.intersects(instance_box)) {
|
||||
// TODO: FIXME: this does not take exclusion area into account
|
||||
const BuildVolume build_volume(get_shape(), m_plater->build_volume().printable_height());
|
||||
const auto state = instance->calc_print_volume_state(build_volume);
|
||||
outside = state == ModelInstancePVS_Partly_Outside;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (plate_box.contains(instance_box))
|
||||
{
|
||||
if (m_exclude_bounding_box.size() > 0)
|
||||
|
||||
@@ -9831,7 +9831,7 @@ void Plater::_calib_pa_select_added_objects() {
|
||||
// For linear mode, pass 1 means normal version while pass 2 mean "for perfectionists" version
|
||||
void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, int pass)
|
||||
{
|
||||
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto printerConfig = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
|
||||
|
||||
@@ -9889,7 +9889,7 @@ auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config
|
||||
_obj->config.set_key_value("sparse_infill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
_obj->config.set_key_value("top_surface_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
||||
_obj->config.set_key_value("internal_solid_infill_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
||||
_obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum<InfillPattern>(ipMonotonic));
|
||||
_obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum<InfillPattern>(ipArchimedeanChords));
|
||||
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
||||
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
||||
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
||||
@@ -9898,7 +9898,9 @@ auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config
|
||||
_obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloat(internal_solid_speed));
|
||||
_obj->config.set_key_value("top_surface_speed", new ConfigOptionFloat(top_surface_speed));
|
||||
_obj->config.set_key_value("seam_slope_type", new ConfigOptionEnum<SeamScarfType>(SeamScarfType::None));
|
||||
_obj->config.set_key_value("gap_fill_target", new ConfigOptionEnum<GapFillTarget>(GapFillTarget::gftNowhere));
|
||||
print_config->set_key_value("max_volumetric_extrusion_rate_slope", new ConfigOptionFloat(0));
|
||||
_obj->config.set_key_value("calib_flowrate_topinfill_special_order", new ConfigOptionBool(true));
|
||||
|
||||
// extract flowrate from name, filename format: flowrate_xxx
|
||||
std::string obj_name = _obj->name;
|
||||
@@ -10121,6 +10123,7 @@ void Plater::calib_retraction(const Calib_Params& params)
|
||||
if (max_lh->values[0] < layer_height)
|
||||
max_lh->values[0] = { layer_height };
|
||||
|
||||
printer_config->set_key_value("use_firmware_retraction", new ConfigOptionBool(false));
|
||||
obj->config.set_key_value("wall_loops", new ConfigOptionInt(2));
|
||||
obj->config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
|
||||
obj->config.set_key_value("bottom_shell_layers", new ConfigOptionInt(3));
|
||||
@@ -10427,7 +10430,7 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path)
|
||||
if (size != stat.m_uncomp_size) // size must fit
|
||||
continue;
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = boost::nowide::narrow(wname);
|
||||
std::string name = into_u8(wname);
|
||||
fs::path archive_path(name);
|
||||
|
||||
std::string extra(1024, 0);
|
||||
|
||||
@@ -512,6 +512,59 @@ wxBoxSizer *PreferencesDialog::create_item_input(wxString title, wxString title2
|
||||
return sizer_input;
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_camera_orbit_mult_input(wxString title, wxWindow *parent, wxString tooltip)
|
||||
{
|
||||
wxBoxSizer *sizer_input = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto input_title = new wxStaticText(parent, wxID_ANY, title);
|
||||
input_title->SetForegroundColour(DESIGN_GRAY900_COLOR);
|
||||
input_title->SetFont(::Label::Body_13);
|
||||
input_title->SetToolTip(tooltip);
|
||||
input_title->Wrap(-1);
|
||||
auto param = "camera_orbit_mult";
|
||||
|
||||
auto input = new ::TextInput(parent, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, DESIGN_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
StateColor input_bg(std::pair<wxColour, int>(wxColour("#F0F0F1"), StateColor::Disabled), std::pair<wxColour, int>(*wxWHITE, StateColor::Enabled));
|
||||
input->SetBackgroundColor(input_bg);
|
||||
input->GetTextCtrl()->SetValue(app_config->get(param));
|
||||
wxTextValidator validator(wxFILTER_NUMERIC);
|
||||
input->GetTextCtrl()->SetValidator(validator);
|
||||
|
||||
sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 23);
|
||||
sizer_input->Add(input_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
|
||||
sizer_input->Add(input, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 3);
|
||||
|
||||
const double min = 0.05;
|
||||
const double max = 2.0;
|
||||
|
||||
input->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, param, input, min, max](wxCommandEvent &e) {
|
||||
auto value = input->GetTextCtrl()->GetValue();
|
||||
double conv = 1.0;
|
||||
if (value.ToCDouble(&conv)) {
|
||||
conv = conv < min ? min : conv > max ? max : conv;
|
||||
auto strval = std::string(wxString::FromCDouble(conv, 2).mb_str());
|
||||
input->GetTextCtrl()->SetValue(strval);
|
||||
app_config->set(param, strval);
|
||||
app_config->save();
|
||||
}
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
input->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, param, input, min, max](wxFocusEvent &e) {
|
||||
auto value = input->GetTextCtrl()->GetValue();
|
||||
double conv = 1.0;
|
||||
if (value.ToCDouble(&conv)) {
|
||||
conv = conv < min ? min : conv > max ? max : conv;
|
||||
auto strval = std::string(wxString::FromCDouble(conv, 2).mb_str());
|
||||
input->GetTextCtrl()->SetValue(strval);
|
||||
app_config->set(param, strval);
|
||||
}
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
return sizer_input;
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param)
|
||||
{
|
||||
wxBoxSizer *m_sizer_input = new wxBoxSizer(wxHORIZONTAL);
|
||||
@@ -1164,6 +1217,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page, _L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50, "zoom_to_mouse");
|
||||
auto item_use_free_camera_settings = create_item_checkbox(_L("Use free camera"), page, _L("If enabled, use free camera. If not enabled, use constrained camera."), 50, "use_free_camera");
|
||||
auto reverse_mouse_zoom = create_item_checkbox(_L("Reverse mouse zoom"), page, _L("If enabled, reverses the direction of zoom with mouse wheel."), 50, "reverse_mouse_wheel_zoom");
|
||||
auto camera_orbit_mult = create_camera_orbit_mult_input(_L("Orbit speed multiplier"), page, _L("Multiplies the orbit speed for finer or coarser camera movement."));
|
||||
|
||||
auto item_show_splash_screen = create_item_checkbox(_L("Show splash screen"), page, _L("Show the splash screen during startup."), 50, "show_splash_screen");
|
||||
auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints");
|
||||
@@ -1247,6 +1301,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_use_free_camera_settings, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(reverse_mouse_zoom, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(camera_orbit_mult, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_show_splash_screen, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_calc_in_long_retract, 0, wxTOP, FromDIP(3));
|
||||
|
||||
@@ -115,6 +115,7 @@ public:
|
||||
wxBoxSizer *create_item_button(wxString title, wxString title2, wxWindow *parent, wxString tooltip, wxString tooltip2, std::function<void()> onclick, bool button_on_left = false);
|
||||
wxWindow* create_item_downloads(wxWindow* parent, int padding_left, std::string param);
|
||||
wxBoxSizer *create_item_input(wxString title, wxString title2, wxWindow *parent, wxString tooltip, std::string param, std::function<void(wxString)> onchange = {});
|
||||
wxBoxSizer *create_camera_orbit_mult_input(wxString title, wxWindow *parent, wxString tooltip);
|
||||
wxBoxSizer *create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param);
|
||||
wxBoxSizer *create_item_multiple_combobox(
|
||||
wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string parama, std::vector<wxString> vlista, std::vector<wxString> vlistb);
|
||||
|
||||
@@ -796,15 +796,6 @@ bool PlaterPresetComboBox::switch_to_tab()
|
||||
if (!tab)
|
||||
return false;
|
||||
|
||||
//BBS Select NoteBook Tab params
|
||||
if (tab->GetParent() == wxGetApp().params_panel())
|
||||
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
|
||||
else {
|
||||
wxGetApp().params_dialog()->Popup();
|
||||
tab->OnActivate();
|
||||
}
|
||||
tab->restore_last_select_item();
|
||||
|
||||
const Preset* selected_filament_preset = nullptr;
|
||||
if (m_type == Preset::TYPE_FILAMENT)
|
||||
{
|
||||
@@ -815,7 +806,6 @@ bool PlaterPresetComboBox::switch_to_tab()
|
||||
if (wxGetApp().get_tab(m_type)->select_preset(preset_name))
|
||||
wxGetApp().get_tab(m_type)->get_combo_box()->set_filament_idx(m_filament_idx);
|
||||
else {
|
||||
wxGetApp().params_dialog()->Hide();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -843,6 +833,15 @@ bool PlaterPresetComboBox::switch_to_tab()
|
||||
}
|
||||
*/
|
||||
|
||||
//BBS Select NoteBook Tab params
|
||||
if (tab->GetParent() == wxGetApp().params_panel())
|
||||
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
|
||||
else {
|
||||
wxGetApp().params_dialog()->Popup();
|
||||
tab->OnActivate();
|
||||
}
|
||||
tab->restore_last_select_item();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ std::string PrintHostSendDialog::storage() const
|
||||
return GUI::format("%1%", m_preselected_storage);
|
||||
if (combo_storage->GetSelection() < 0 || combo_storage->GetSelection() >= int(m_paths.size()))
|
||||
return {};
|
||||
return boost::nowide::narrow(m_paths[combo_storage->GetSelection()]);
|
||||
return into_u8(m_paths[combo_storage->GetSelection()]);
|
||||
}
|
||||
|
||||
void PrintHostSendDialog::EndModal(int ret)
|
||||
@@ -491,7 +491,7 @@ void PrintHostQueueDialog::on_progress(Event &evt)
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_percentage(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()), evt.progress / 100.f);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_percentage(evt.job_id + 1, into_u8(nm.GetString()), into_u8(hst.GetString()), evt.progress / 100.f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ void PrintHostQueueDialog::on_error(Event &evt)
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_error(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_error(evt.job_id + 1, into_u8(nm.GetString()), into_u8(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_cancel(Event &evt)
|
||||
@@ -527,7 +527,7 @@ void PrintHostQueueDialog::on_cancel(Event &evt)
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_canceled(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_canceled(evt.job_id + 1, into_u8(nm.GetString()), into_u8(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_info(Event& evt)
|
||||
@@ -538,17 +538,17 @@ void PrintHostQueueDialog::on_info(Event& evt)
|
||||
if (evt.tag == L"resolve") {
|
||||
wxVariant hst(evt.status);
|
||||
job_list->SetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_host(evt.job_id + 1, boost::nowide::narrow(evt.status));
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_host(evt.job_id + 1, into_u8(evt.status));
|
||||
} else if (evt.tag == L"complete") {
|
||||
wxVariant hst(evt.status);
|
||||
job_list->SetValue(hst, evt.job_id, COL_ERRORMSG);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_completed(evt.job_id + 1);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_status(evt.job_id + 1, boost::nowide::narrow(evt.status));
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_status(evt.job_id + 1, into_u8(evt.status));
|
||||
} else if(evt.tag == L"complete_with_warning"){
|
||||
wxVariant hst(evt.status);
|
||||
job_list->SetValue(hst, evt.job_id, COL_ERRORMSG);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_completed_with_warning(evt.job_id + 1);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_status(evt.job_id + 1, boost::nowide::narrow(evt.status));
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_status(evt.job_id + 1, into_u8(evt.status));
|
||||
} else if (evt.tag == L"set_complete_off") {
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_comp_on_100(evt.job_id + 1, false);
|
||||
}
|
||||
|
||||
@@ -77,12 +77,26 @@ void PrinterWebView::load_url(wxString& url, wxString apikey)
|
||||
return;
|
||||
m_apikey = apikey;
|
||||
m_apikey_sent = false;
|
||||
|
||||
m_browser->LoadURL(url);
|
||||
|
||||
if (this->IsShown()) {
|
||||
m_url_deferred = *wxEmptyString;
|
||||
m_browser->LoadURL(url);
|
||||
} else {
|
||||
m_url_deferred = url;
|
||||
}
|
||||
//m_browser->SetFocus();
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
bool PrinterWebView::Show(bool show)
|
||||
{
|
||||
if (show && !m_url_deferred.empty()) {
|
||||
m_browser->LoadURL(m_url_deferred);
|
||||
m_url_deferred = *wxEmptyString;
|
||||
}
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void PrinterWebView::reload()
|
||||
{
|
||||
m_browser->Reload();
|
||||
|
||||
@@ -43,6 +43,9 @@ public:
|
||||
void OnLoaded(wxWebViewEvent& evt);
|
||||
void reload();
|
||||
void update_mode();
|
||||
|
||||
bool Show(bool show = true) override;
|
||||
|
||||
private:
|
||||
void SendAPIKey();
|
||||
|
||||
@@ -51,6 +54,8 @@ private:
|
||||
wxString m_apikey;
|
||||
bool m_apikey_sent;
|
||||
|
||||
wxString m_url_deferred;
|
||||
|
||||
// DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ static char marker_by_type(Preset::Type type, PrinterTechnology pt)
|
||||
}
|
||||
}
|
||||
|
||||
std::string Option::opt_key() const { return boost::nowide::narrow(key).substr(2); }
|
||||
std::string Option::opt_key() const { return into_u8(key).substr(2); }
|
||||
|
||||
void FoundOption::get_marked_label_and_tooltip(const char **label_, const char **tooltip_) const
|
||||
{
|
||||
@@ -210,9 +210,9 @@ bool OptionsSearcher::search(const std::string &search, bool force /* = false*/,
|
||||
std::string label = into_u8(get_label(opt));
|
||||
//all
|
||||
if (type == Preset::TYPE_INVALID) {
|
||||
found.emplace_back(FoundOption{label, label, boost::nowide::narrow(get_tooltip(opt)), i, 0});
|
||||
found.emplace_back(FoundOption{label, label, into_u8(get_tooltip(opt)), i, 0});
|
||||
} else if (type == opt.type){
|
||||
found.emplace_back(FoundOption{label, label, boost::nowide::narrow(get_tooltip(opt)), i, 0});
|
||||
found.emplace_back(FoundOption{label, label, into_u8(get_tooltip(opt)), i, 0});
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -253,9 +253,9 @@ bool OptionsSearcher::search(const std::string &search, bool force /* = false*/,
|
||||
#endif
|
||||
|
||||
if (type == Preset::TYPE_INVALID) {
|
||||
found.emplace_back(FoundOption{label_plain, label_u8, boost::nowide::narrow(get_tooltip(opt)), i, score});
|
||||
found.emplace_back(FoundOption{label_plain, label_u8, into_u8(get_tooltip(opt)), i, score});
|
||||
} else if (type == opt.type) {
|
||||
found.emplace_back(FoundOption{label_plain, label_u8, boost::nowide::narrow(get_tooltip(opt)), i, score});
|
||||
found.emplace_back(FoundOption{label_plain, label_u8, into_u8(get_tooltip(opt)), i, score});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+195
-221
@@ -401,6 +401,39 @@ void Selection::remove_volumes(EMode mode, const std::vector<unsigned int>& volu
|
||||
this->set_bounding_boxes_dirty();
|
||||
}
|
||||
|
||||
ModelVolume *Selection::get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const
|
||||
{
|
||||
if (is_single_volume() || is_single_modifier()) {
|
||||
const GLVolume *gl_volume = get_first_volume();
|
||||
out_object_idx = gl_volume->object_idx();
|
||||
ModelObject *model_object = get_model()->objects[out_object_idx];
|
||||
out_volume_idx = gl_volume->volume_idx();
|
||||
if (out_volume_idx < model_object->volumes.size())
|
||||
return model_object->volumes[out_volume_idx];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ModelObject *Selection::get_selected_single_object(int &out_object_idx) const
|
||||
{
|
||||
if (is_single_volume() || is_single_modifier() || is_single_full_object()) {
|
||||
const GLVolume *gl_volume = get_first_volume();
|
||||
out_object_idx = gl_volume->object_idx();
|
||||
return get_model()->objects[out_object_idx];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ModelInstance *Selection::get_selected_single_intance() const
|
||||
{
|
||||
int object_idx;
|
||||
auto mo = get_selected_single_object(object_idx);
|
||||
if (mo) {
|
||||
return mo->instances[get_instance_idx()];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Selection::add_curr_plate()
|
||||
{
|
||||
if (!m_valid)
|
||||
@@ -910,17 +943,17 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
|
||||
return *m_scaled_instance_bounding_box;
|
||||
}
|
||||
|
||||
const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const
|
||||
const BoundingBoxf3 &Selection::get_full_unscaled_instance_bounding_box() const
|
||||
{
|
||||
assert(is_single_full_instance());
|
||||
|
||||
if (!m_full_unscaled_instance_bounding_box.has_value()) {
|
||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
if (m_valid) {
|
||||
for (unsigned int i : m_list) {
|
||||
const GLVolume& volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
|
||||
const GLVolume &volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
|
||||
trafo.translation().z() += volume.get_sla_shift_z();
|
||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||
}
|
||||
@@ -929,17 +962,17 @@ const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const
|
||||
return *m_full_unscaled_instance_bounding_box;
|
||||
}
|
||||
|
||||
const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const
|
||||
const BoundingBoxf3 &Selection::get_full_scaled_instance_bounding_box() const
|
||||
{
|
||||
assert(is_single_full_instance());
|
||||
|
||||
if (!m_full_scaled_instance_bounding_box.has_value()) {
|
||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_scaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_scaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
if (m_valid) {
|
||||
for (unsigned int i : m_list) {
|
||||
const GLVolume& volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
|
||||
const GLVolume &volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
|
||||
trafo.translation().z() += volume.get_sla_shift_z();
|
||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||
}
|
||||
@@ -948,17 +981,17 @@ const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const
|
||||
return *m_full_scaled_instance_bounding_box;
|
||||
}
|
||||
|
||||
const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box() const
|
||||
const BoundingBoxf3 &Selection::get_full_unscaled_instance_local_bounding_box() const
|
||||
{
|
||||
assert(is_single_full_instance());
|
||||
|
||||
if (!m_full_unscaled_instance_local_bounding_box.has_value()) {
|
||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_local_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_local_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
if (m_valid) {
|
||||
for (unsigned int i : m_list) {
|
||||
const GLVolume& volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_volume_transformation().get_matrix();
|
||||
const GLVolume &volume = *(*m_volumes)[i];
|
||||
Transform3d trafo = volume.get_volume_transformation().get_matrix();
|
||||
trafo.translation().z() += volume.get_sla_shift_z();
|
||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||
}
|
||||
@@ -967,22 +1000,20 @@ const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box()
|
||||
return *m_full_unscaled_instance_local_bounding_box;
|
||||
}
|
||||
|
||||
const std::pair<BoundingBoxf3, Transform3d>& Selection::get_bounding_box_in_current_reference_system() const
|
||||
const std::pair<BoundingBoxf3, Transform3d> &Selection::get_bounding_box_in_current_reference_system() const
|
||||
{
|
||||
static int last_coordinates_type = -1;
|
||||
|
||||
assert(!is_empty());
|
||||
|
||||
ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||
if (m_mode == Instance && coordinates_type == ECoordinatesType::Local)
|
||||
coordinates_type = ECoordinatesType::World;
|
||||
if (m_mode == Instance && coordinates_type == ECoordinatesType::Local) coordinates_type = ECoordinatesType::World;
|
||||
|
||||
if (last_coordinates_type != int(coordinates_type))
|
||||
const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>>*>(&m_bounding_box_in_current_reference_system)->reset();
|
||||
if (last_coordinates_type != int(coordinates_type)) const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system)->reset();
|
||||
|
||||
if (!m_bounding_box_in_current_reference_system.has_value()) {
|
||||
last_coordinates_type = int(coordinates_type);
|
||||
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>>*>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
|
||||
last_coordinates_type = int(coordinates_type);
|
||||
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
|
||||
}
|
||||
|
||||
return *m_bounding_box_in_current_reference_system;
|
||||
@@ -994,11 +1025,19 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
|
||||
// trafo to current reference system
|
||||
//
|
||||
Transform3d trafo;
|
||||
switch (type)
|
||||
{
|
||||
case ECoordinatesType::World: { trafo = Transform3d::Identity(); break; }
|
||||
case ECoordinatesType::Instance: { trafo = get_first_volume()->get_instance_transformation().get_matrix(); break; }
|
||||
case ECoordinatesType::Local: { trafo = get_first_volume()->world_matrix(); break; }
|
||||
switch (type) {
|
||||
case ECoordinatesType::World: {
|
||||
trafo = Transform3d::Identity();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Instance: {
|
||||
trafo = get_first_volume()->get_instance_transformation().get_matrix();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Local: {
|
||||
trafo = get_first_volume()->world_matrix();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1006,60 +1045,55 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
|
||||
//
|
||||
Geometry::Transformation t(trafo);
|
||||
t.reset_scaling_factor();
|
||||
const Transform3d basis_trafo = t.get_matrix_no_offset();
|
||||
std::vector<Vec3d> axes = { Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ() };
|
||||
for (size_t i = 0; i < axes.size(); ++i) {
|
||||
axes[i] = basis_trafo * axes[i];
|
||||
}
|
||||
const Transform3d basis_trafo = t.get_matrix_no_offset();
|
||||
std::vector<Vec3d> axes = {Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ()};
|
||||
for (size_t i = 0; i < axes.size(); ++i) { axes[i] = basis_trafo * axes[i]; }
|
||||
|
||||
//
|
||||
// calculate bounding box aligned to trafo basis
|
||||
//
|
||||
Vec3d min = { DBL_MAX, DBL_MAX, DBL_MAX };
|
||||
Vec3d max = { -DBL_MAX, -DBL_MAX, -DBL_MAX };
|
||||
Vec3d min = {DBL_MAX, DBL_MAX, DBL_MAX};
|
||||
Vec3d max = {-DBL_MAX, -DBL_MAX, -DBL_MAX};
|
||||
for (unsigned int id : m_list) {
|
||||
const GLVolume& vol = *get_volume(id);
|
||||
const Transform3d vol_world_rafo = vol.world_matrix();
|
||||
const TriangleMesh* mesh = vol.convex_hull();
|
||||
const GLVolume & vol = *get_volume(id);
|
||||
const Transform3d vol_world_rafo = vol.world_matrix();
|
||||
const TriangleMesh *mesh = vol.convex_hull();
|
||||
if (mesh == nullptr)
|
||||
mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
|
||||
assert(mesh != nullptr);
|
||||
for (const stl_vertex& v : mesh->its.vertices) {
|
||||
for (const stl_vertex &v : mesh->its.vertices) {
|
||||
const Vec3d world_v = vol_world_rafo * v.cast<double>();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const double i_comp = world_v.dot(axes[i]);
|
||||
min(i) = std::min(min(i), i_comp);
|
||||
max(i) = std::max(max(i), i_comp);
|
||||
min(i) = std::min(min(i), i_comp);
|
||||
max(i) = std::max(max(i), i_comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Vec3d box_size = max - min;
|
||||
Vec3d half_box_size = 0.5 * box_size;
|
||||
const Vec3d box_size = max - min;
|
||||
Vec3d half_box_size = 0.5 * box_size;
|
||||
Geometry::Transformation out_trafo(trafo);
|
||||
Vec3d center = 0.5 * (min + max);
|
||||
Vec3d center = 0.5 * (min + max);
|
||||
|
||||
// Fix for non centered volume
|
||||
// Fix for non centered volume
|
||||
// by move with calculated center(to volume center) and extend half box size
|
||||
// e.g. for right aligned embossed text
|
||||
if (m_list.size() == 1 &&
|
||||
type == ECoordinatesType::Local) {
|
||||
const GLVolume& vol = *get_volume(*m_list.begin());
|
||||
if (m_list.size() == 1 && type == ECoordinatesType::Local) {
|
||||
const GLVolume & vol = *get_volume(*m_list.begin());
|
||||
const Transform3d vol_world_trafo = vol.world_matrix();
|
||||
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
||||
for (size_t i = 0; i < 3; i++){
|
||||
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
// move center to local volume zero
|
||||
center[i] = world_zero.dot(axes[i]);
|
||||
// extend half size to bigger distance from center
|
||||
half_box_size[i] = std::max(
|
||||
abs(center[i] - min[i]),
|
||||
abs(center[i] - max[i]));
|
||||
half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const BoundingBoxf3 out_box(-half_box_size, half_box_size);
|
||||
out_trafo.set_offset(basis_trafo * center);
|
||||
return { out_box, out_trafo.get_matrix_no_scaling_factor() };
|
||||
return {out_box, out_trafo.get_matrix_no_scaling_factor()};
|
||||
}
|
||||
|
||||
const std::pair<Vec3d, double> Selection::get_bounding_sphere() const
|
||||
@@ -1138,34 +1172,52 @@ void Selection::move_to_center(const Vec3d& displacement, bool local)
|
||||
this->set_bounding_boxes_dirty();
|
||||
}
|
||||
|
||||
void Selection::translate(const Vec3d& displacement, TransformationType transformation_type)
|
||||
void Selection::translate(const Vec3d &displacement, TransformationType transformation_type)
|
||||
{
|
||||
if (!m_valid)
|
||||
return;
|
||||
|
||||
// Emboss use translate in local coordinate
|
||||
assert(transformation_type.relative() ||
|
||||
transformation_type.local());
|
||||
if (!m_valid) return;
|
||||
|
||||
for (unsigned int i : m_list) {
|
||||
GLVolume& v = *(*m_volumes)[i];
|
||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
||||
GLVolume & v = *(*m_volumes)[i];
|
||||
const VolumeCache &volume_data = m_cache.volumes_data[i];
|
||||
if (m_mode == Instance && !is_wipe_tower()) {
|
||||
assert(is_from_fully_selected_instance(i));
|
||||
if (transformation_type.instance()) {
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
|
||||
}
|
||||
else
|
||||
} else
|
||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
if (transformation_type.local() && transformation_type.absolute()) {
|
||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
|
||||
} else {
|
||||
if (v.is_wipe_tower) {//in world cs
|
||||
int plate_idx = v.object_idx() - 1000;
|
||||
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_bounding_box();
|
||||
Vec3d tower_size = v.bounding_box().size();
|
||||
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
|
||||
Vec3d actual_displacement = displacement;
|
||||
const double margin = WIPE_TOWER_MARGIN;
|
||||
|
||||
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() *
|
||||
m_cache.volumes_data[i].get_instance_mirror_matrix())
|
||||
.inverse() *
|
||||
displacement;
|
||||
if (tower_origin(0) + actual_displacement(0) - margin < plate_bbox.min(0)) {
|
||||
actual_displacement(0) = plate_bbox.min(0) - tower_origin(0) + margin;
|
||||
} else if (tower_origin(0) + actual_displacement(0) + tower_size(0) + margin > plate_bbox.max(0)) {
|
||||
actual_displacement(0) = plate_bbox.max(0) - tower_origin(0) - tower_size(0) - margin;
|
||||
}
|
||||
|
||||
if (tower_origin(1) + actual_displacement(1) - margin < plate_bbox.min(1)) {
|
||||
actual_displacement(1) = plate_bbox.min(1) - tower_origin(1) + margin;
|
||||
} else if (tower_origin(1) + actual_displacement(1) + tower_size(1) + margin > plate_bbox.max(1)) {
|
||||
actual_displacement(1) = plate_bbox.max(1) - tower_origin(1) - tower_size(1) - margin;
|
||||
}
|
||||
|
||||
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
|
||||
}
|
||||
else {
|
||||
else if (transformation_type.local() && transformation_type.absolute()) {
|
||||
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
|
||||
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
|
||||
} else {
|
||||
Vec3d relative_disp = displacement;
|
||||
if (transformation_type.world() && transformation_type.instance())
|
||||
relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
|
||||
@@ -1181,12 +1233,14 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor
|
||||
else if (m_mode == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
ensure_not_below_bed();
|
||||
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
ensure_not_below_bed();
|
||||
}
|
||||
set_bounding_boxes_dirty();
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
|
||||
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
|
||||
{
|
||||
@@ -1287,7 +1341,9 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
set_bounding_boxes_dirty();
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::flattening_rotate(const Vec3d& normal)
|
||||
@@ -1320,96 +1376,6 @@ void Selection::flattening_rotate(const Vec3d& normal)
|
||||
this->set_bounding_boxes_dirty();
|
||||
}
|
||||
|
||||
void Selection::scale_legacy(const Vec3d& scale, TransformationType transformation_type)
|
||||
{
|
||||
if (!m_valid)
|
||||
return;
|
||||
|
||||
for (unsigned int i : m_list) {
|
||||
GLVolume &v = *(*m_volumes)[i];
|
||||
if (is_single_full_instance()) {
|
||||
if (transformation_type.relative()) {
|
||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||
// extracts scaling factors from the composed transformation
|
||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||
if (transformation_type.joint())
|
||||
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||
|
||||
v.set_instance_scaling_factor(new_scale);
|
||||
// Restore mirror state
|
||||
v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror());
|
||||
}
|
||||
else {
|
||||
const auto mirror = v.get_instance_mirror();
|
||||
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
|
||||
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
|
||||
// This is only possible, if the instance rotation is mulitples of ninety degrees.
|
||||
assert(Geometry::is_rotation_ninety_degrees(v.get_instance_rotation()));
|
||||
v.set_instance_scaling_factor((v.get_instance_transformation().get_rotation_matrix().matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
|
||||
}
|
||||
else
|
||||
v.set_instance_scaling_factor(scale);
|
||||
// Restore mirror state
|
||||
v.set_instance_mirror(mirror);
|
||||
}
|
||||
|
||||
// update the instance assemble transform
|
||||
ModelObject* object = m_model->objects[v.object_idx()];
|
||||
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
|
||||
const auto mirror = assemble_transform.get_mirror();
|
||||
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
|
||||
assemble_transform.set_mirror(mirror);
|
||||
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
|
||||
}
|
||||
else if (is_single_volume() || is_single_modifier()) {
|
||||
const auto mirror = v.get_volume_transformation().get_mirror();
|
||||
v.set_volume_scaling_factor(scale);
|
||||
// Restore mirror state
|
||||
v.set_volume_mirror(mirror);
|
||||
}
|
||||
else {
|
||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
||||
if (m_mode == Instance) {
|
||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||
// extracts scaling factors from the composed transformation
|
||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||
if (transformation_type.joint())
|
||||
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||
|
||||
v.set_instance_scaling_factor(new_scale);
|
||||
// Restore mirror state
|
||||
v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror());
|
||||
}
|
||||
else if (m_mode == Volume) {
|
||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||
// extracts scaling factors from the composed transformation
|
||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||
if (transformation_type.joint()) {
|
||||
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
||||
v.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
||||
}
|
||||
v.set_volume_scaling_factor(new_scale);
|
||||
// Restore mirror state
|
||||
v.set_volume_mirror(m_cache.volumes_data[i].get_volume_transform().get_mirror());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
||||
// synchronize_unselected_instances() to apply the scale to the other instances
|
||||
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
||||
else if (m_mode == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
ensure_on_bed();
|
||||
set_bounding_boxes_dirty();
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
}
|
||||
|
||||
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
|
||||
{
|
||||
scale_and_translate(scale, Vec3d::Zero(), transformation_type);
|
||||
@@ -1552,16 +1518,9 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
|
||||
}
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
|
||||
void Selection::mirror(Axis axis, TransformationType transformation_type)
|
||||
void Selection::scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type)
|
||||
{
|
||||
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
|
||||
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
|
||||
}
|
||||
|
||||
void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_translation, TransformationType transformation_type)
|
||||
{
|
||||
if (!m_valid)
|
||||
return;
|
||||
if (!m_valid) return;
|
||||
|
||||
Vec3d relative_scale = scale;
|
||||
if (transformation_type.absolute()) {
|
||||
@@ -1582,45 +1541,52 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_trans
|
||||
}
|
||||
|
||||
for (unsigned int i : m_list) {
|
||||
GLVolume& v = *(*m_volumes)[i];
|
||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
GLVolume & v = *(*m_volumes)[i];
|
||||
const VolumeCache & volume_data = m_cache.volumes_data[i];
|
||||
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||
|
||||
if (m_mode == Instance) {
|
||||
if (transformation_type.instance()) {
|
||||
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
|
||||
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
|
||||
Matrix3d inst_rotation, inst_scale;
|
||||
Matrix3d inst_rotation, inst_scale;
|
||||
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
|
||||
const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + world_translation);
|
||||
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo * Geometry::translation_transform(-local_inst_pivot));
|
||||
}
|
||||
else
|
||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo *
|
||||
Geometry::translation_transform(-local_inst_pivot));
|
||||
} else
|
||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale),
|
||||
m_cache.dragging_center);
|
||||
// update the instance assemble transform
|
||||
ModelObject * object = m_model->objects[v.object_idx()];
|
||||
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
|
||||
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
|
||||
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
|
||||
} else {
|
||||
if (!is_single_volume_or_modifier()) {
|
||||
assert(transformation_type.world());
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale),
|
||||
m_cache.dragging_center);
|
||||
} else {
|
||||
transformation_type.set_independent();
|
||||
Vec3d translation;
|
||||
if (transformation_type.local())
|
||||
if (transformation_type.local()) {
|
||||
translation = volume_data.get_volume_transform().get_matrix_no_offset().inverse() * inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
||||
}
|
||||
else if (transformation_type.instance())
|
||||
translation = inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
||||
else
|
||||
translation = world_translation;
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale), m_cache.dragging_center);
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale),
|
||||
m_cache.dragging_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
||||
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
||||
// synchronize_unselected_instances() to apply the scale to the other instances
|
||||
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
||||
else if (m_mode == Volume)
|
||||
@@ -1629,7 +1595,16 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_trans
|
||||
|
||||
ensure_on_bed();
|
||||
set_bounding_boxes_dirty();
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::mirror(Axis axis, TransformationType transformation_type)
|
||||
{
|
||||
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
|
||||
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
|
||||
|
||||
}
|
||||
|
||||
void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
|
||||
@@ -1944,7 +1919,8 @@ void Selection::render(float scale_factor)
|
||||
m_scale_factor = scale_factor;
|
||||
// render cumulative bounding box of selected volumes
|
||||
const auto& [box, trafo] = get_bounding_box_in_current_reference_system();
|
||||
render_bounding_box(box, trafo, ColorRGB::WHITE());
|
||||
render_bounding_box(box, trafo,
|
||||
wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView ? ColorRGB::YELLOW(): ColorRGB::WHITE());
|
||||
render_synchronized_volumes();
|
||||
}
|
||||
|
||||
@@ -1992,40 +1968,33 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
const Transform3d base_matrix = Geometry::assemble_transform(get_bounding_box().center());
|
||||
Vec3d center = get_bounding_box().center();
|
||||
Transform3d orient_matrix = Transform3d::Identity();
|
||||
|
||||
if (!boost::starts_with(sidebar_field, "layer")) {
|
||||
shader->set_uniform("emission_factor", 0.05f);
|
||||
const auto &[box, box_trafo] = get_bounding_box_in_current_reference_system();
|
||||
// BBS
|
||||
if (is_single_full_instance()/* && !wxGetApp().obj_manipul()->get_world_coordinates()*/) {
|
||||
if (!boost::starts_with(sidebar_field, "position")) {
|
||||
if (boost::starts_with(sidebar_field, "scale"))
|
||||
if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
center = box_trafo.translation();
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
} else if (is_single_volume_or_modifier()) {
|
||||
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
if (wxGetApp().obj_manipul()->is_local_coordinates()) {
|
||||
orient_matrix = get_bounding_box_in_current_reference_system().second;
|
||||
orient_matrix.translation() = Vec3d::Zero();
|
||||
} else {
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
else if (boost::starts_with(sidebar_field, "rotation")) {
|
||||
if (boost::ends_with(sidebar_field, "x"))
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
else if (boost::ends_with(sidebar_field, "y")) {
|
||||
const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation();
|
||||
if (rotation.x() == 0.0)
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
else
|
||||
orient_matrix.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()));
|
||||
}
|
||||
center = box_trafo.translation();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_single_volume() || is_single_modifier()) {
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
if (!boost::starts_with(sidebar_field, "position"))
|
||||
orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_rotation_matrix();
|
||||
|
||||
}
|
||||
else {
|
||||
if (requires_local_axes())
|
||||
} else {
|
||||
if (requires_local_axes()) {
|
||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
const Transform3d base_matrix = Geometry::assemble_transform(center);
|
||||
|
||||
if (!boost::starts_with(sidebar_field, "layer"))
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
@@ -2033,6 +2002,8 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
|
||||
render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||
else if (boost::starts_with(sidebar_field, "rotation"))
|
||||
render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||
else if (boost::starts_with(sidebar_field, "absolute_rotation"))
|
||||
render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||
else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
|
||||
//BBS: GUI refactor: add uniform_scale from gizmo
|
||||
render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix);
|
||||
@@ -3052,6 +3023,9 @@ void Selection::ensure_not_below_bed()
|
||||
|
||||
bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
|
||||
{
|
||||
if (m_mode == Instance && wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||
return true;
|
||||
}
|
||||
struct SameInstance
|
||||
{
|
||||
int obj_idx;
|
||||
@@ -3180,14 +3154,14 @@ void Selection::paste_objects_from_clipboard()
|
||||
Vec3d displacement;
|
||||
bool in_current = plate->intersects(bbox);
|
||||
auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
|
||||
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
|
||||
if (shift_all(0) != 0 || shift_all(1) != 0) {
|
||||
// BBS: if multiple objects are selected, move them as a whole after copy
|
||||
if (i == 0) empty_cell_all = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1,bbox.size()(1)+1});
|
||||
auto instance_shift = src_object->instances.front()->get_offset() - src_objects[0]->instances.front()->get_offset();
|
||||
displacement = {shift_all.x() + empty_cell_all.x()+instance_shift.x(), shift_all.y() + empty_cell_all.y()+instance_shift.y(), start_point(2)};
|
||||
displacement = {shift_all.x() + empty_cell_all.x() + instance_shift.x(), shift_all.y() + empty_cell_all.y() + instance_shift.y(), start_offset(2)};
|
||||
} else {
|
||||
// BBS: if only one object is copied, find an empty cell to put it
|
||||
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
|
||||
auto point_offset = start_offset - start_point;
|
||||
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
|
||||
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
|
||||
|
||||
@@ -15,6 +15,7 @@ class Model;
|
||||
class ModelObject;
|
||||
class ModelVolume;
|
||||
class ObjectID;
|
||||
class ModelInstance;
|
||||
class GLVolume;
|
||||
class GLArrow;
|
||||
class GLCurvedArrow;
|
||||
@@ -225,6 +226,9 @@ public:
|
||||
void remove_volumes(EMode mode, const std::vector<unsigned int>& volume_idxs);
|
||||
|
||||
//BBS
|
||||
ModelVolume * get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const;
|
||||
ModelObject * get_selected_single_object(int &out_object_idx) const;
|
||||
const ModelInstance * get_selected_single_intance() const;
|
||||
void add_curr_plate();
|
||||
void add_object_from_idx(std::vector<int>& object_idxs);
|
||||
void remove_curr_plate();
|
||||
@@ -326,20 +330,17 @@ public:
|
||||
const std::pair<Vec3d, double> get_bounding_sphere() const;
|
||||
|
||||
void setup_cache();
|
||||
|
||||
void translate(const Vec3d& displacement, TransformationType transformation_type);
|
||||
void move_to_center(const Vec3d& displacement, bool local = false);
|
||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||
void flattening_rotate(const Vec3d& normal);
|
||||
[[deprecated("Only used by GizmoObjectManipulation")]]
|
||||
void scale_legacy(const Vec3d& scale, TransformationType transformation_type);
|
||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
void scale_to_fit_print_volume(const BuildVolume& volume);
|
||||
#else
|
||||
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
|
||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||
void scale_and_translate(const Vec3d& scale, const Vec3d& world_translation, TransformationType transformation_type);
|
||||
void scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type);
|
||||
void mirror(Axis axis, TransformationType transformation_type);
|
||||
|
||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||
@@ -351,6 +352,7 @@ public:
|
||||
//BBS: add partplate related logic
|
||||
void notify_instance_update(int object_idx, int instance_idx);
|
||||
// BBS
|
||||
EMode get_volume_selection_mode(){ return m_volume_selection_mode;}
|
||||
void set_volume_selection_mode(EMode mode) { if (!m_volume_selection_locked) m_volume_selection_mode = mode; }
|
||||
void lock_volume_selection_mode() { m_volume_selection_locked = true; }
|
||||
void unlock_volume_selection_mode() { m_volume_selection_locked = false; }
|
||||
@@ -358,11 +360,11 @@ public:
|
||||
void erase();
|
||||
|
||||
void render(float scale_factor = 1.0);
|
||||
//BBS: GUI refactor: add uniform scale from gizmo
|
||||
void render_sidebar_hints(const std::string& sidebar_field, bool uniform_scale);
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void render_center(bool gizmo_is_dragging);
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
//BBS: GUI refactor: add uniform scale from gizmo
|
||||
void render_sidebar_hints(const std::string& sidebar_field, bool uniform_scale);
|
||||
|
||||
bool requires_local_axes() const;
|
||||
|
||||
@@ -405,7 +407,8 @@ private:
|
||||
void set_bounding_boxes_dirty() {
|
||||
m_bounding_box.reset();
|
||||
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
||||
m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset();
|
||||
m_full_unscaled_instance_bounding_box.reset();
|
||||
m_full_scaled_instance_bounding_box.reset();
|
||||
m_full_unscaled_instance_local_bounding_box.reset();
|
||||
m_bounding_box_in_current_reference_system.reset();
|
||||
m_bounding_sphere.reset();
|
||||
|
||||
@@ -498,7 +498,7 @@ static std::string generate_system_info_json()
|
||||
std::vector<std::wstring> blacklisted_libraries;
|
||||
BlacklistedLibraryCheck::get_instance().get_blacklisted(blacklisted_libraries);
|
||||
for (const std::wstring& wstr : blacklisted_libraries) {
|
||||
std::string utf8 = boost::nowide::narrow(wstr);
|
||||
std::string utf8 = into_u8(wstr);
|
||||
if (size_t last_bs_pos = utf8.find_last_of("\\"); last_bs_pos < utf8.size() - 1) {
|
||||
// Remove anything before last backslash so we don't send the path to the DLL.
|
||||
utf8.erase(0, last_bs_pos + 1);
|
||||
|
||||
@@ -432,8 +432,8 @@ void Temp_Calibration_Dlg::on_filament_type_changed(wxCommandEvent& event) {
|
||||
end = 230;
|
||||
break;
|
||||
case tPCTG:
|
||||
start = 240;
|
||||
end = 280;
|
||||
start = 280;
|
||||
end = 240;
|
||||
break;
|
||||
case tTPU:
|
||||
start = 240;
|
||||
|
||||
@@ -1203,9 +1203,9 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
||||
auto machine_in_cache = (cache_profile_path / vendor_name / PRESET_PRINTER_NAME);
|
||||
|
||||
if (( fs::exists(path_in_vendor))
|
||||
&&( fs::exists(print_in_cache))
|
||||
&&( fs::exists(filament_in_cache))
|
||||
&&( fs::exists(machine_in_cache))) {
|
||||
|| fs::exists(print_in_cache)
|
||||
|| fs::exists(filament_in_cache)
|
||||
|| fs::exists(machine_in_cache)) {
|
||||
Semver vendor_ver = get_version_from_json(path_in_vendor.string());
|
||||
|
||||
std::map<std::string, std::string> key_values;
|
||||
@@ -1240,11 +1240,10 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
||||
Version version;
|
||||
version.config_version = cache_ver;
|
||||
version.comment = description;
|
||||
|
||||
updates.updates.emplace_back(std::move(file_path), std::move(path_in_vendor.string()), std::move(version), vendor_name, changelog, "", force_update, false);
|
||||
|
||||
//BBS: add directory support
|
||||
updates.updates.emplace_back(cache_path / vendor_name, vendor_path / vendor_name, Version(), vendor_name, "", "", force_update, true);
|
||||
// Orca: update vendor.json
|
||||
updates.updates.emplace_back(std::move(file_path), std::move(path_in_vendor.string()), std::move(version), vendor_name, changelog, "", force_update, false);
|
||||
//Orca: update vendor folder
|
||||
updates.updates.emplace_back(cache_profile_path / vendor_name, vendor_path / vendor_name, Version(), vendor_name, "", "", force_update, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdlib.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
Reference in New Issue
Block a user