Merge branch 'master' of https://github.com/Prusa-Development/PrusaSlicerPrivate into et_mirror
This commit is contained in:
commit
fd956ecc49
43 changed files with 4634 additions and 4163 deletions
|
@ -1,28 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="cut">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M118.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S118.95,65.5,118.12,65.5z M98.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S98.95,65.5,98.12,65.5z M78.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S78.95,65.5,78.12,65.5z M58.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S58.95,65.5,58.12,65.5z M38.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S38.95,65.5,38.12,65.5z M18.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S18.95,65.5,18.12,65.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M108.79,51.6H19.21c-1.93,0-3.5-1.57-3.5-3.5V10.12c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5V48.1C112.29,50.03,110.71,51.6,108.79,51.6z M19.21,9.62c-0.27,0-0.5,0.23-0.5,0.5V48.1
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V10.12c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M108.79,121.38H19.21c-1.93,0-3.5-1.57-3.5-3.5V79.4c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5v38.49C112.29,119.81,110.71,121.38,108.79,121.38z M19.21,78.9c-0.27,0-0.5,0.23-0.5,0.5v38.49
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V79.4c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<path fill="#ED6B21" d="M3.0597045,10.3634434H0.5884437C0.2628375,10.3634434,0,10.100606,0,9.7750006
|
||||
c0-0.3256063,0.2628375-0.5884438,0.5884437-0.5884438h2.4712608c0.3256061,0,0.5884435,0.2628374,0.5884435,0.5884438
|
||||
C3.6481481,10.100606,3.3853078,10.3634434,3.0597045,10.3634434z"/>
|
||||
<path fill="#ED6B21" d="M12.0967369,10.3634434h-2.471261c-0.3256063,0-0.5884438-0.2628374-0.5884438-0.5884428
|
||||
c0-0.3256063,0.2628374-0.5884438,0.5884438-0.5884438h2.471261c0.3256063,0,0.5884438,0.2628374,0.5884438,0.5884438
|
||||
C12.6851807,10.100606,12.4223404,10.3634434,12.0967369,10.3634434z"/>
|
||||
<path fill="#ED6B21" d="M7.5782208,10.3634434h-2.471261c-0.3256059,0-0.5884438-0.2628374-0.5884438-0.5884428
|
||||
c0-0.3256063,0.2628379-0.5884438,0.5884438-0.5884438h2.471261c0.3256059,0,0.5884433,0.2628374,0.5884433,0.5884438
|
||||
C8.1666641,10.100606,7.9038239,10.3634434,7.5782208,10.3634434z"/>
|
||||
<g>
|
||||
<path fill="#808080" d="M10.98001,11.9849854c-0.289978,0-0.5199585,0.2299805-0.5199585,0.5199585v0.5922852v0.3327637
|
||||
c0,0.289978-0.2300415,0.5200195-0.5200195,0.5200195H2.7452075c-0.289978,0-0.5200195-0.2300415-0.5200195-0.5200195V13.097229
|
||||
v-0.5922852c0-0.289978-0.2299803-0.5199585-0.5199584-0.5199585c-0.2900391,0-0.5200195,0.2299805-0.5200195,0.5199585v0.5922852
|
||||
v0.3327637C1.1852101,14.2999878,1.8952321,15,2.7552173,15h7.1748047c0.8599854,0,1.5700073-0.7000122,1.5700073-1.5700073
|
||||
V13.097229v-0.5922852C11.5000296,12.2149658,11.2700491,11.9849854,10.98001,11.9849854z"/>
|
||||
<path fill="#808080" d="M9.9300222,4.5499878H2.7552173c-0.8599852,0-1.5700072,0.7000122-1.5700072,1.5700073v0.3327637v0.5922852
|
||||
c0,0.289978,0.2299805,0.5199585,0.5200195,0.5199585c0.289978,0,0.5199584-0.2299805,0.5199584-0.5199585V6.4527588V6.1199951
|
||||
c0-0.289978,0.2300415-0.5200195,0.5200195-0.5200195H9.940032c0.289978,0,0.5200195,0.2300415,0.5200195,0.5200195v0.3327637
|
||||
v0.5922852c0,0.289978,0.2299805,0.5199585,0.5199585,0.5199585c0.2900391,0,0.5200195-0.2299805,0.5200195-0.5199585V6.4527588
|
||||
V6.1199951C11.5000296,5.25,10.7900076,4.5499878,9.9300222,4.5499878z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -1,26 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="add_x5F_part">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M14.62,4.37c-0.01-0.14,0.06-0.34,0.15-0.44l0.13-0.15c0.09-0.11,0.12-0.3,0.07-0.43l-0.2-0.49
|
||||
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.33-0.1-0.42-0.21c-0.09-0.1-0.37-0.46-0.38-0.6l-0.01-0.2
|
||||
c-0.01-0.14-0.12-0.3-0.25-0.35l-0.49-0.2C12.52,0.97,12.33,1,12.22,1.1l-0.15,0.13c-0.11,0.09-0.31,0.16-0.44,0.15
|
||||
c-0.14-0.01-0.59-0.06-0.69-0.15L10.78,1.1c-0.11-0.09-0.3-0.12-0.43-0.07l-0.49,0.2C9.73,1.28,9.61,1.44,9.6,1.58l-0.01,0.2
|
||||
C9.58,1.92,9.49,2.11,9.38,2.2c-0.1,0.09-0.46,0.37-0.6,0.38L8.58,2.6c-0.14,0.01-0.3,0.12-0.35,0.25l-0.2,0.49
|
||||
C7.97,3.48,8,3.67,8.1,3.78l0.13,0.15c0.09,0.11,0.16,0.31,0.15,0.44C8.37,4.52,8.32,4.96,8.23,5.07L8.1,5.22
|
||||
C8,5.33,7.97,5.52,8.03,5.65l0.2,0.49C8.28,6.27,8.44,6.39,8.58,6.4l0.2,0.01c0.14,0.01,0.33,0.1,0.42,0.21
|
||||
c0.09,0.1,0.37,0.46,0.38,0.6l0.01,0.2c0.01,0.14,0.12,0.3,0.25,0.35l0.49,0.2C10.48,8.03,10.67,8,10.78,7.9l0.15-0.13
|
||||
c0.11-0.09,0.31-0.16,0.44-0.15c0.14,0.01,0.59,0.06,0.69,0.15l0.15,0.13c0.11,0.09,0.3,0.12,0.43,0.07l0.49-0.2
|
||||
c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.33,0.21-0.42s0.46-0.37,0.6-0.38l0.2-0.01c0.14-0.01,0.3-0.12,0.35-0.25
|
||||
l0.2-0.49C15.03,5.52,15,5.33,14.9,5.22l-0.13-0.15C14.68,4.96,14.63,4.51,14.62,4.37z M11.5,6.6c-1.16,0-2.1-0.94-2.1-2.1
|
||||
s0.94-2.1,2.1-2.1s2.1,0.94,2.1,2.1S12.66,6.6,11.5,6.6z"/>
|
||||
</g>
|
||||
<path fill="#808080" d="M10.98,9.78c-0.29,0-0.52,0.23-0.52,0.52v2.09v1.04c0,0.29-0.23,0.52-0.52,0.52H2.62
|
||||
c-0.29,0-0.53-0.24-0.53-0.53L2.04,6.12c0-0.14,0.05-0.27,0.15-0.37c0.1-0.1,0.23-0.15,0.37-0.15l3.19,0v0
|
||||
c0.29,0,0.52-0.23,0.52-0.52S6.04,4.55,5.75,4.55H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81,0.16-1.11,0.46
|
||||
C1.16,5.31,1,5.71,1,6.13l0.04,7.31C1.05,14.3,1.75,15,2.62,15h7.31c0.86,0,1.57-0.7,1.57-1.57v-1.04V10.3
|
||||
C11.5,10.01,11.27,9.78,10.98,9.78z"/>
|
||||
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<path fill="#ED6B21" d="M7.2122064,10.8825388H5.473033c-0.6128426,0-1.1075444-0.4947023-1.1075444-1.1075449
|
||||
S4.8601904,8.667449,5.473033,8.667449h1.7391734c0.6128426,0,1.1075444,0.4947023,1.1075444,1.1075449
|
||||
S7.8250437,10.8825388,7.2122064,10.8825388z"/>
|
||||
<g>
|
||||
<path fill="#808080" d="M10.98001,15c-0.289978,0-0.5199585-0.2299805-0.5199585-0.5199585v-0.5922852v-0.3327637
|
||||
c0-0.289978-0.2300415-0.5200195-0.5200195-0.5200195H2.7452075c-0.289978,0-0.5200195,0.2300415-0.5200195,0.5200195v0.3327637
|
||||
v0.5922852C2.225188,14.7700195,1.9952077,15,1.7052296,15c-0.2900391,0-0.5200195-0.2299805-0.5200195-0.5199585v-0.5922852
|
||||
v-0.3327637c0-0.8699951,0.710022-1.5700073,1.5700072-1.5700073h7.1748047c0.8599854,0,1.5700073,0.7000122,1.5700073,1.5700073
|
||||
v0.3327637v0.5922852C11.5000296,14.7700195,11.2700491,15,10.98001,15z"/>
|
||||
<path fill="#808080" d="M9.9300222,7.5650024H2.7552173c-0.8599852,0-1.5700072-0.7000122-1.5700072-1.5700073V5.6622314V5.0699463
|
||||
c0-0.289978,0.2299805-0.5199585,0.5200195-0.5199585c0.289978,0,0.5199584,0.2299805,0.5199584,0.5199585v0.5922852v0.3327637
|
||||
c0,0.289978,0.2300415,0.5200195,0.5200195,0.5200195H9.940032c0.289978,0,0.5200195-0.2300415,0.5200195-0.5200195V5.6622314
|
||||
V5.0699463c0-0.289978,0.2299805-0.5199585,0.5199585-0.5199585c0.2900391,0,0.5200195,0.2299805,0.5200195,0.5199585v0.5922852
|
||||
v0.3327637C11.5000296,6.8649902,10.7900076,7.5650024,9.9300222,7.5650024z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
resources/profiles/Creality/ENDER5S1_thumbnail.png
Normal file
BIN
resources/profiles/Creality/ENDER5S1_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
resources/profiles/Creality/SERMOONV1_thumbnail.png
Normal file
BIN
resources/profiles/Creality/SERMOONV1_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -210,8 +210,9 @@ bool its_write_obj(const indexed_triangle_set &its, const char *file)
|
|||
bool its_write_obj(const indexed_triangle_set& its, const std::vector<obj_color> &color, const char* file)
|
||||
{
|
||||
Slic3r::CNumericLocalesSetter locales_setter;
|
||||
FILE* fp = fopen(file, "w");
|
||||
FILE* fp = boost::nowide::fopen(file, "w");
|
||||
if (fp == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,12 @@ imstb_truetype.h modification:
|
|||
|
||||
Hot fix for open symbolic fonts on windows
|
||||
62bdfe6f8d04b88e8bd511cd613be80c0baa7f55
|
||||
Add case STBTT_MS_EID_SYMBOL to swith in file imstb_truetype.h on line 1440.
|
||||
|
||||
Hot fix for open curved fonts mainly on MAC
|
||||
2148e49f75d82cb19dc6ec409fb7825296ed005c
|
||||
viz. https://github.com/nothings/stb/issues/1296
|
||||
In file imstb_truetype.h line 1667 change malloc size from:
|
||||
vertices = (stbtt_vertex *) STBTT_malloc((m + 1) * sizeof(vertices[0]), info->userdata);
|
||||
to:
|
||||
vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
|
|
@ -174,7 +174,6 @@ public:
|
|||
BoundingBox rotated(double angle, const Point ¢er) const;
|
||||
void rotate(double angle) { (*this) = this->rotated(angle); }
|
||||
void rotate(double angle, const Point ¢er) { (*this) = this->rotated(angle, center); }
|
||||
bool intersects(const BoundingBox &other) const { return this->min(0) <= other.max(0) && this->max(0) >= other.min(0) && this->min(1) <= other.max(1) && this->max(1) >= other.min(1); }
|
||||
// Align the min corner to a grid of cell_size x cell_size cells,
|
||||
// to encompass the original bounding box.
|
||||
void align_to_grid(const coord_t cell_size);
|
||||
|
|
|
@ -185,7 +185,6 @@ set(SLIC3R_SOURCES
|
|||
Model.hpp
|
||||
ModelArrange.hpp
|
||||
ModelArrange.cpp
|
||||
#ModelVolumeType.hpp
|
||||
MultiMaterialSegmentation.cpp
|
||||
MultiMaterialSegmentation.hpp
|
||||
MeshNormals.hpp
|
||||
|
|
|
@ -283,7 +283,7 @@ ExPolygons Emboss::heal_shape(const Polygons &shape) {
|
|||
|
||||
// Do not remove all duplicits but do it better way
|
||||
// Overlap all duplicit points by rectangle 3x3
|
||||
Points duplicits = collect_duplications(to_points(polygons));
|
||||
Points duplicits = collect_duplicates(to_points(polygons));
|
||||
if (!duplicits.empty()) {
|
||||
polygons.reserve(polygons.size() + duplicits.size());
|
||||
for (const Point &p : duplicits) {
|
||||
|
@ -310,7 +310,7 @@ bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
|
|||
priv::remove_same_neighbor(shape);
|
||||
|
||||
Pointfs intersections = intersection_points(shape);
|
||||
Points duplicits = collect_duplications(to_points(shape));
|
||||
Points duplicits = collect_duplicates(to_points(shape));
|
||||
//Points close = priv::collect_close_points(shape, 1.);
|
||||
if (intersections.empty() && duplicits.empty() /* && close.empty() */) break;
|
||||
|
||||
|
@ -353,7 +353,7 @@ bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
|
|||
svg.draw(shape, "green");
|
||||
|
||||
svg.draw(duplicits, "lightgray", 13 / Emboss::SHAPE_SCALE);
|
||||
Points duplicits3 = collect_duplications(to_points(shape));
|
||||
Points duplicits3 = collect_duplicates(to_points(shape));
|
||||
svg.draw(duplicits3, "black", 7 / Emboss::SHAPE_SCALE);
|
||||
|
||||
Pointfs pts2 = intersection_points(shape);
|
||||
|
@ -387,7 +387,7 @@ bool Emboss::heal_shape(ExPolygons &shape, unsigned max_iteration)
|
|||
}
|
||||
|
||||
assert(intersection_points(shape).empty());
|
||||
assert(collect_duplications(to_points(shape)).empty());
|
||||
assert(collect_duplicates(to_points(shape)).empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1186,7 @@ indexed_triangle_set Emboss::polygons2model(const ExPolygons &shape2d,
|
|||
const IProjection &projection)
|
||||
{
|
||||
Points points = to_points(shape2d);
|
||||
Points duplicits = collect_duplications(points);
|
||||
Points duplicits = collect_duplicates(points);
|
||||
return (duplicits.empty()) ?
|
||||
priv::polygons2model_unique(shape2d, projection, points) :
|
||||
priv::polygons2model_duplicit(shape2d, projection, points, duplicits);
|
||||
|
|
|
@ -148,7 +148,7 @@ static constexpr const char* MESH_STAT_FACETS_RESERVED = "facets_reversed";
|
|||
static constexpr const char* MESH_STAT_BACKWARDS_EDGES = "backwards_edges";
|
||||
|
||||
// Store / load of TextConfiguration
|
||||
static constexpr const char *TEXT_TAG = "emboss";
|
||||
static constexpr const char *TEXT_TAG = "slic3rpe:text";
|
||||
static constexpr const char *TEXT_DATA_ATTR = "text";
|
||||
// TextConfiguration::EmbossStyle
|
||||
static constexpr const char *STYLE_NAME_ATTR = "style_name";
|
||||
|
@ -3628,8 +3628,8 @@ std::optional<TextConfiguration> TextConfigurationSerialization::read(const char
|
|||
float distance = get_attribute_value_float(attributes, num_attributes, DISTANCE_ATTR);
|
||||
if (std::fabs(distance) > std::numeric_limits<float>::epsilon())
|
||||
fp.distance = distance;
|
||||
std::string use_surface = get_attribute_value_string(attributes, num_attributes, USE_SURFACE_ATTR);
|
||||
if (!use_surface.empty()) fp.use_surface = true;
|
||||
int use_surface = get_attribute_value_int(attributes, num_attributes, USE_SURFACE_ATTR);
|
||||
if (use_surface == 1) fp.use_surface = true;
|
||||
float angle = get_attribute_value_float(attributes, num_attributes, ANGLE_ATTR);
|
||||
if (std::fabs(angle) > std::numeric_limits<float>::epsilon())
|
||||
fp.angle = angle;
|
||||
|
|
|
@ -2327,7 +2327,7 @@ void GCode::process_layer_single_object(
|
|||
interface_extruder = dontcare_extruder;
|
||||
}
|
||||
bool extrude_support = has_support && support_extruder == extruder_id;
|
||||
bool extrude_interface = interface_extruder && interface_extruder == extruder_id;
|
||||
bool extrude_interface = has_interface && interface_extruder == extruder_id;
|
||||
if (extrude_support || extrude_interface) {
|
||||
init_layer_delayed();
|
||||
m_layer = layer_to_print.support_layer;
|
||||
|
|
|
@ -133,7 +133,7 @@ Slic3r::Pointfs compute_intersections(const Slic3r::Lines &lines)
|
|||
Point max_(std::max(a_.x(), b_.x()), std::max(a_.y(), b_.y()));
|
||||
BoundingBox bb_(min_, max_);
|
||||
// intersect of BB compare min max
|
||||
if (bb.intersects(bb_) &&
|
||||
if (bb.overlap(bb_) &&
|
||||
l.intersection(l_, &i))
|
||||
pts.push_back(i.cast<double>());
|
||||
}
|
||||
|
|
|
@ -317,13 +317,16 @@ void Layer::build_up_down_graph(Layer& below, Layer& above)
|
|||
coord_t* end = srcs + 4;
|
||||
std::sort(begin, end);
|
||||
end = std::unique(begin, end);
|
||||
assert(begin + 2 == end);
|
||||
if (begin + 1 == end)
|
||||
if (begin + 1 == end) {
|
||||
// Self intersection may happen on source contour. Just copy the Z value.
|
||||
pt.z() = *begin;
|
||||
else if (begin + 2 <= end) {
|
||||
// store a -1 based negative index into the "intersections" vector here.
|
||||
m_intersections.emplace_back(srcs[0], srcs[1]);
|
||||
pt.z() = -coord_t(m_intersections.size());
|
||||
} else {
|
||||
assert(begin + 2 == end);
|
||||
if (begin + 2 <= end) {
|
||||
// store a -1 based negative index into the "intersections" vector here.
|
||||
m_intersections.emplace_back(srcs[0], srcs[1]);
|
||||
pt.z() = -coord_t(m_intersections.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
const std::vector<std::pair<coord_t, coord_t>>& intersections() const { return m_intersections; }
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "Arrange.hpp"
|
||||
#include "CustomGCode.hpp"
|
||||
#include "enum_bitmask.hpp"
|
||||
//#include "ModelVolumeType.hpp"
|
||||
#include "TextConfiguration.hpp"
|
||||
|
||||
#include <map>
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef slic3r_ModelVolumeType_hpp_
|
||||
#define slic3r_ModelVolumeType_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class ModelVolumeType : int {
|
||||
INVALID = -1,
|
||||
MODEL_PART = 0,
|
||||
NEGATIVE_VOLUME,
|
||||
PARAMETER_MODIFIER,
|
||||
SUPPORT_BLOCKER,
|
||||
SUPPORT_ENFORCER,
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
#endif /* slic3r_ModelVolumeType_hpp_ */
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using namespace Slic3r;
|
||||
|
||||
// inspired by nanosvgrast.h function nsvgRasterize -> nsvg__flattenShape -> nsvg__flattenCubicBez
|
||||
// https://github.com/memononen/nanosvg/blob/f0a3e1034dd22e2e87e5db22401e44998383124e/src/nanosvgrast.h#L335
|
||||
void NSVGUtils::flatten_cubic_bez(Polygon &polygon,
|
||||
float tessTol,
|
||||
Vec2f p1,
|
||||
|
|
|
@ -397,22 +397,37 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, con
|
|||
ClipperLib_Z::Clipper clipper;
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot,
|
||||
const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
|
||||
// The clipping contour may be simplified by clipping it with a bounding box of "subject" path.
|
||||
// The clipping function used may produce self intersections outside of the "subject" bounding box. Such self intersections are
|
||||
// harmless to the result of the clipping operation,
|
||||
// Both ends of each edge belong to the same source: Either they are from subject or from clipping path.
|
||||
assert(e1bot.z() >= 0 && e1top.z() >= 0);
|
||||
assert(e2bot.z() >= 0 && e2top.z() >= 0);
|
||||
assert((e1bot.z() == 0) == (e1top.z() == 0));
|
||||
assert((e2bot.z() == 0) == (e2top.z() == 0));
|
||||
|
||||
// Start & end points of the clipped polyline (extrusion path with a non-zero width).
|
||||
ClipperLib_Z::IntPoint start = e1bot;
|
||||
ClipperLib_Z::IntPoint end = e1top;
|
||||
|
||||
if (start.z() <= 0 && end.z() <= 0) {
|
||||
start = e2bot;
|
||||
end = e2top;
|
||||
}
|
||||
|
||||
assert(start.z() > 0 && end.z() > 0);
|
||||
if (start.z() <= 0 && end.z() <= 0) {
|
||||
// Self intersection on the source contour.
|
||||
assert(start.z() == 0 && end.z() == 0);
|
||||
pt.z() = 0;
|
||||
} else {
|
||||
// Interpolate extrusion line width.
|
||||
assert(start.z() > 0 && end.z() > 0);
|
||||
|
||||
// Interpolate extrusion line width.
|
||||
double length_sqr = (end - start).cast<double>().squaredNorm();
|
||||
double dist_sqr = (pt - start).cast<double>().squaredNorm();
|
||||
double t = std::sqrt(dist_sqr / length_sqr);
|
||||
double length_sqr = (end - start).cast<double>().squaredNorm();
|
||||
double dist_sqr = (pt - start).cast<double>().squaredNorm();
|
||||
double t = std::sqrt(dist_sqr / length_sqr);
|
||||
|
||||
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
|
||||
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
|
||||
}
|
||||
});
|
||||
|
||||
clipper.AddPath(subject, ClipperLib_Z::ptSubject, false);
|
||||
|
|
|
@ -66,9 +66,9 @@ bool has_duplicate_points(std::vector<Point> &&pts)
|
|||
return false;
|
||||
}
|
||||
|
||||
Points collect_duplications(Points pts /* Copy */)
|
||||
Points collect_duplicates(Points pts /* Copy */)
|
||||
{
|
||||
std::stable_sort(pts.begin(), pts.end());
|
||||
std::sort(pts.begin(), pts.end());
|
||||
Points duplicits;
|
||||
const Point *prev = &pts.front();
|
||||
for (size_t i = 1; i < pts.size(); ++i) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -977,8 +977,10 @@ indexed_triangle_set its_make_cone(double r, double h, double fa)
|
|||
vertices.emplace_back(Vec3f(0., 0., h));
|
||||
|
||||
size_t i = 0;
|
||||
const auto vec = Eigen::Vector2f(0, float(r));
|
||||
for (double angle=0; angle<2*PI; angle+=fa) {
|
||||
vertices.emplace_back(r*std::cos(angle), r*std::sin(angle), 0.);
|
||||
Vec2f p = Eigen::Rotation2Df(angle) * vec;
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
|
||||
if (angle > 0.) {
|
||||
facets.emplace_back(0, i+2, i+1);
|
||||
facets.emplace_back(1, i+1, i+2);
|
||||
|
@ -1013,58 +1015,121 @@ indexed_triangle_set its_make_pyramid(float base, float height)
|
|||
// Generates mesh for a sphere centered about the origin, using the generated angle
|
||||
// to determine the granularity.
|
||||
// Default angle is 1 degree.
|
||||
//FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html
|
||||
indexed_triangle_set its_make_sphere(double radius, double fa)
|
||||
{
|
||||
int sectorCount = int(ceil(2. * M_PI / fa));
|
||||
int stackCount = int(ceil(M_PI / fa));
|
||||
float sectorStep = float(2. * M_PI / sectorCount);
|
||||
float stackStep = float(M_PI / stackCount);
|
||||
|
||||
// First build an icosahedron (taken from http://www.songho.ca/opengl/gl_sphere.html)
|
||||
indexed_triangle_set mesh;
|
||||
|
||||
const float PI = 3.1415926f;
|
||||
const float H_ANGLE = PI / 180 * 72; // 72 degree = 360 / 5
|
||||
const float V_ANGLE = atanf(1.0f / 2); // elevation = 26.565 degree
|
||||
|
||||
auto& vertices = mesh.vertices;
|
||||
vertices.reserve((stackCount - 1) * sectorCount + 2);
|
||||
for (int i = 0; i <= stackCount; ++ i) {
|
||||
// from pi/2 to -pi/2
|
||||
double stackAngle = 0.5 * M_PI - stackStep * i;
|
||||
double xy = radius * cos(stackAngle);
|
||||
double z = radius * sin(stackAngle);
|
||||
if (i == 0 || i == stackCount)
|
||||
vertices.emplace_back(Vec3f(float(xy), 0.f, float(z)));
|
||||
else
|
||||
for (int j = 0; j < sectorCount; ++ j) {
|
||||
// from 0 to 2pi
|
||||
double sectorAngle = sectorStep * j;
|
||||
vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast<float>());
|
||||
}
|
||||
}
|
||||
auto& indices = mesh.indices;
|
||||
vertices.resize(12);
|
||||
indices.reserve(20);
|
||||
|
||||
auto& facets = mesh.indices;
|
||||
facets.reserve(2 * (stackCount - 1) * sectorCount);
|
||||
for (int i = 0; i < stackCount; ++ i) {
|
||||
// Beginning of current stack.
|
||||
int k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount);
|
||||
int k1_first = k1;
|
||||
// Beginning of next stack.
|
||||
int k2 = (i == 0) ? 1 : (k1 + sectorCount);
|
||||
int k2_first = k2;
|
||||
for (int j = 0; j < sectorCount; ++ j) {
|
||||
// 2 triangles per sector excluding first and last stacks
|
||||
int k1_next = k1;
|
||||
int k2_next = k2;
|
||||
if (i != 0) {
|
||||
k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1);
|
||||
facets.emplace_back(k1, k2, k1_next);
|
||||
float z, xy;
|
||||
float hAngle1 = -PI / 2 - H_ANGLE / 2;
|
||||
|
||||
vertices[0] = stl_vertex(0, 0, radius); // the first top vertex at (0, 0, r)
|
||||
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
z = radius * sinf(V_ANGLE);
|
||||
xy = radius * cosf(V_ANGLE);
|
||||
vertices[i] = stl_vertex(xy * cosf(hAngle1), xy * sinf(hAngle1), z);
|
||||
vertices[i+5] = stl_vertex(xy * cosf(hAngle1 + H_ANGLE / 2), xy * sinf(hAngle1 + H_ANGLE / 2), -z);
|
||||
hAngle1 += H_ANGLE;
|
||||
|
||||
indices.emplace_back(stl_triangle_vertex_indices(i, i < 5 ? i+1 : 1, 0));
|
||||
indices.emplace_back(stl_triangle_vertex_indices(i, i+5, i < 5 ? i+1 : 1));
|
||||
indices.emplace_back(stl_triangle_vertex_indices(i+5, i+6 < 11 ? i+6 : 6, i+6 < 11 ? i+1 : 1));
|
||||
indices.emplace_back(stl_triangle_vertex_indices(i+5, 11, i+6 < 11 ? i+6 : 6));
|
||||
}
|
||||
vertices[11] = stl_vertex(0, 0, -radius); // the last bottom vertex at (0, 0, -r)
|
||||
|
||||
|
||||
// We have a beautiful icosahedron. Now subdivide the triangles.
|
||||
std::vector<Vec3i> neighbors = its_face_neighbors(mesh); // This is cheap, the mesh is small.
|
||||
|
||||
const double side_len_limit = radius * fa;
|
||||
const double side_len = (vertices[1] - vertices[0]).norm();
|
||||
const int iterations = std::ceil(std::log2(side_len / side_len_limit));
|
||||
|
||||
indices.reserve(indices.size() * std::pow(4, iterations));
|
||||
vertices.reserve(vertices.size() * std::pow(2, iterations));
|
||||
|
||||
struct DividedEdge {
|
||||
int neighbor = -1;
|
||||
int middle_vertex_idx;
|
||||
std::pair<int, int> children_idxs;
|
||||
};
|
||||
|
||||
for (int iter=0; iter<iterations; ++iter) {
|
||||
std::vector<std::array<DividedEdge, 3>> divided_triangles(indices.size());
|
||||
std::vector<Vec3i> new_neighbors(4*indices.size());
|
||||
|
||||
size_t orig_indices_size = indices.size();
|
||||
for (int i=0; i<orig_indices_size; ++i) { // iterate over all old triangles
|
||||
|
||||
// We are going to split this triangle. Let's foresee what will be the indices
|
||||
// of the new internal triangles along individual edges.
|
||||
int last_triangle_idx = indices.size()-1;
|
||||
std::array<std::pair<int, int>, 3> edge_children = { std::make_pair(i,last_triangle_idx + 2),
|
||||
std::make_pair(last_triangle_idx + 2,last_triangle_idx + 3),
|
||||
std::make_pair(last_triangle_idx + 3,i) };
|
||||
|
||||
std::array<int, 3> middle_vertices_idxs;
|
||||
std::array<std::pair<int, int>, 3> new_neighbors_per_edge;
|
||||
|
||||
for (int n=0; n<3; ++n) { // for all three edges
|
||||
const int edge_neighbor = neighbors[i][n];
|
||||
|
||||
if (divided_triangles[edge_neighbor][0].neighbor == -1) {
|
||||
// This n-th edge is not yet divided. Divide it now.
|
||||
vertices.emplace_back(0.5 * (vertices[indices[i][n]] + vertices[indices[i][n == 2 ? 0 : n+1]]));
|
||||
vertices.back() *= radius / vertices.back().norm();
|
||||
middle_vertices_idxs[n] = vertices.size()-1;
|
||||
|
||||
// Save information about what we did.
|
||||
int j = -1;
|
||||
while (divided_triangles[i][++j].neighbor != -1);
|
||||
|
||||
divided_triangles[i][j] = { edge_neighbor, int(vertices.size()-1), edge_children[n] };
|
||||
new_neighbors_per_edge[n] = std::make_pair(-1,-1);
|
||||
} else {
|
||||
// This edge is already divided. Get the index of the middle point.
|
||||
int j = -1;
|
||||
while (divided_triangles[edge_neighbor][++j].neighbor != i);
|
||||
middle_vertices_idxs[n] = divided_triangles[edge_neighbor][j].middle_vertex_idx;
|
||||
new_neighbors_per_edge[n] = divided_triangles[edge_neighbor][j].children_idxs;
|
||||
std::swap(new_neighbors_per_edge[n].first, new_neighbors_per_edge[n].second);
|
||||
|
||||
// We have saved the middle-point. We are looking for edges leading to/from it.
|
||||
int idx = -1; while (indices[new_neighbors_per_edge[n].first][++idx] != middle_vertices_idxs[n]);
|
||||
new_neighbors[new_neighbors_per_edge[n].first][idx] = edge_children[n].first;
|
||||
new_neighbors[new_neighbors_per_edge[n].second][idx] = edge_children[n].second;
|
||||
}
|
||||
}
|
||||
if (i + 1 != stackCount) {
|
||||
k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1);
|
||||
facets.emplace_back(k1_next, k2, k2_next);
|
||||
}
|
||||
k1 = k1_next;
|
||||
k2 = k2_next;
|
||||
|
||||
// Add three new triangles, reindex the old one.
|
||||
const int last_index = indices.size() - 1;
|
||||
indices.emplace_back(stl_triangle_vertex_indices(middle_vertices_idxs[0], middle_vertices_idxs[1], middle_vertices_idxs[2]));
|
||||
new_neighbors[indices.size()-1] = Vec3i(last_index+2, last_index+3, i);
|
||||
|
||||
indices.emplace_back(stl_triangle_vertex_indices(middle_vertices_idxs[0], indices[i][1], middle_vertices_idxs[1]));
|
||||
new_neighbors[indices.size()-1] = Vec3i(new_neighbors_per_edge[0].second, new_neighbors_per_edge[1].first, last_index+1);
|
||||
|
||||
indices.emplace_back(stl_triangle_vertex_indices(middle_vertices_idxs[2], middle_vertices_idxs[1], indices[i][2]));
|
||||
new_neighbors[indices.size()-1] = Vec3i(last_index+1, new_neighbors_per_edge[1].second, new_neighbors_per_edge[2].first);
|
||||
|
||||
indices[i][1] = middle_vertices_idxs[0];
|
||||
indices[i][2] = middle_vertices_idxs[2];
|
||||
new_neighbors[i] = Vec3i(new_neighbors_per_edge[0].first, last_index+1, new_neighbors_per_edge[2].second);
|
||||
|
||||
}
|
||||
neighbors = std::move(new_neighbors);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ Triangulation::Indices Triangulation::triangulate(const ExPolygon &expolygon){
|
|||
|
||||
Triangulation::Indices Triangulation::triangulate(const ExPolygons &expolygons){
|
||||
Points pts = to_points(expolygons);
|
||||
Points d_pts = collect_duplications(pts);
|
||||
Points d_pts = collect_duplicates(pts);
|
||||
if (d_pts.empty()) return triangulate(expolygons, pts);
|
||||
|
||||
Changes changes = create_changes(pts, d_pts);
|
||||
|
@ -262,7 +262,7 @@ Triangulation::Indices Triangulation::triangulate(const ExPolygons &expolygons,
|
|||
{
|
||||
assert(count_points(expolygons) == points.size());
|
||||
// when contain duplicit coordinate in points will not work properly
|
||||
assert(collect_duplications(points).empty());
|
||||
assert(collect_duplicates(points).empty());
|
||||
|
||||
HalfEdges edges;
|
||||
edges.reserve(points.size());
|
||||
|
|
|
@ -113,7 +113,6 @@ inline void append(std::vector<T>& dest, const std::vector<T>& src)
|
|||
dest = src; // copy
|
||||
else
|
||||
dest.insert(dest.end(), src.begin(), src.end());
|
||||
// NOTE: insert reserve space when needed
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -956,7 +956,8 @@ std::string xml_escape(std::string text, bool is_marked/* = false*/)
|
|||
}
|
||||
|
||||
// Definition of escape symbols https://www.w3.org/TR/REC-xml/#AVNormalize
|
||||
|
||||
// During the read of xml attribute normalization of white spaces is applied
|
||||
// Soo for not lose white space character it is escaped before store
|
||||
std::string xml_escape_double_quotes_attribute_value(std::string text)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
|
|
|
@ -437,9 +437,9 @@ std::vector<int> GLVolumeCollection::load_object(
|
|||
|
||||
int GLVolumeCollection::load_object_volume(
|
||||
const ModelObject* model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx)
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx)
|
||||
{
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
|
@ -448,12 +448,16 @@ int GLVolumeCollection::load_object_volume(
|
|||
this->volumes.emplace_back(new GLVolume());
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.set_color(color_from_model_volume(*model_volume));
|
||||
// apply printable value from the instance
|
||||
v.printable = instance->printable;
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
v.model.init_from(*mesh, true);
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
if (m_use_raycasters)
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
#else
|
||||
v.model.init_from(*mesh);
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
if (m_use_raycasters)
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
|
||||
if (model_volume->is_model_part()) {
|
||||
|
|
|
@ -397,6 +397,7 @@ private:
|
|||
Slope m_slope;
|
||||
bool m_show_sinking_contours{ false };
|
||||
bool m_show_non_manifold_edges{ true };
|
||||
bool m_use_raycasters{ true };
|
||||
|
||||
public:
|
||||
GLVolumePtrs volumes;
|
||||
|
@ -445,6 +446,7 @@ public:
|
|||
bool empty() const { return volumes.empty(); }
|
||||
void set_range(double low, double high) { for (GLVolume* vol : this->volumes) vol->set_range(low, high); }
|
||||
|
||||
void set_use_raycasters(bool value) { m_use_raycasters = value; }
|
||||
void set_print_volume(const PrintVolume& print_volume) { m_print_volume = print_volume; }
|
||||
|
||||
void set_z_range(float min_z, float max_z) { m_z_range[0] = min_z; m_z_range[1] = max_z; }
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -450,6 +450,14 @@ struct PageBedShape: ConfigWizardPage
|
|||
virtual void apply_custom_config(DynamicPrintConfig &config);
|
||||
};
|
||||
|
||||
struct PageBuildVolume : ConfigWizardPage
|
||||
{
|
||||
wxTextCtrl* build_volume;
|
||||
|
||||
PageBuildVolume(ConfigWizard* parent);
|
||||
virtual void apply_custom_config(DynamicPrintConfig& config);
|
||||
};
|
||||
|
||||
struct PageDiameters: ConfigWizardPage
|
||||
{
|
||||
wxTextCtrl *diam_nozzle;
|
||||
|
@ -584,6 +592,7 @@ struct ConfigWizard::priv
|
|||
PageBedShape *page_bed = nullptr;
|
||||
PageDiameters *page_diams = nullptr;
|
||||
PageTemperatures *page_temps = nullptr;
|
||||
PageBuildVolume* page_bvolume = nullptr;
|
||||
|
||||
// Pointers to all pages (regardless or whether currently part of the ConfigWizardIndex)
|
||||
std::vector<ConfigWizardPage*> all_pages;
|
||||
|
|
|
@ -643,7 +643,7 @@ const ColorRGBA GCodeViewer::Neutral_Color = ColorRGBA::DARK_GRAY();
|
|||
GCodeViewer::GCodeViewer()
|
||||
{
|
||||
m_extrusions.reset_role_visibility_flags();
|
||||
|
||||
m_shells.volumes.set_use_raycasters(false);
|
||||
// m_sequential_view.skip_invisible_moves = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,11 @@ static const Slic3r::ColorRGBA ERROR_BG_LIGHT_COLOR = { 0.753f, 0.192f, 0.039f
|
|||
// Number of floats
|
||||
static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
|
||||
|
||||
#define SHOW_IMGUI_DEMO_WINDOW
|
||||
#ifdef SHOW_IMGUI_DEMO_WINDOW
|
||||
static bool show_imgui_demo_window = false;
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
@ -1498,6 +1503,10 @@ void GLCanvas3D::render()
|
|||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
|
||||
#ifdef SHOW_IMGUI_DEMO_WINDOW
|
||||
if (show_imgui_demo_window) ImGui::ShowDemoWindow();
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
|
||||
const bool is_looking_downward = camera.is_looking_downward();
|
||||
|
||||
|
@ -2379,10 +2388,11 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
// see include/wx/defs.h enum wxKeyCode
|
||||
int keyCode = evt.GetKeyCode();
|
||||
int ctrlMask = wxMOD_CONTROL;
|
||||
int shiftMask = wxMOD_SHIFT;
|
||||
#ifdef SHOW_IMGUI_DEMO_WINDOW
|
||||
static int cur = 0;
|
||||
if (wxString("demo")[cur] == evt.GetUnicodeKey()) ++cur; else cur = 0;
|
||||
if (cur == 4) { show_imgui_demo_window = !show_imgui_demo_window; cur = 0;}
|
||||
#endif // SHOW_IMGUI_DEMO_WINDOW
|
||||
|
||||
auto imgui = wxGetApp().imgui();
|
||||
if (imgui->update_key_data(evt)) {
|
||||
|
@ -2390,6 +2400,10 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
return;
|
||||
}
|
||||
|
||||
// see include/wx/defs.h enum wxKeyCode
|
||||
int keyCode = evt.GetKeyCode();
|
||||
int ctrlMask = wxMOD_CONTROL;
|
||||
int shiftMask = wxMOD_SHIFT;
|
||||
if (keyCode == WXK_ESCAPE && (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item() || _deactivate_arrange_menu()))
|
||||
return;
|
||||
|
||||
|
@ -3447,20 +3461,27 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
evt.Skip();
|
||||
|
||||
// Detection of doubleclick on text to open emboss edit window
|
||||
if (evt.LeftDClick() && m_gizmos.get_current() == nullptr && !m_hover_volume_idxs.empty()) {
|
||||
auto type = m_gizmos.get_current_type();
|
||||
if (evt.LeftDClick() && !m_hover_volume_idxs.empty() &&
|
||||
(type == GLGizmosManager::EType::Undefined ||
|
||||
type == GLGizmosManager::EType::Move ||
|
||||
type == GLGizmosManager::EType::Rotate ||
|
||||
type == GLGizmosManager::EType::Scale ||
|
||||
type == GLGizmosManager::EType::Emboss) ) {
|
||||
for (int hover_volume_id : m_hover_volume_idxs) {
|
||||
const GLVolume &hover_gl_volume = *m_volumes.volumes[hover_volume_id];
|
||||
const ModelObject* hover_object = m_model->objects[hover_gl_volume.object_idx()];
|
||||
int object_idx = hover_gl_volume.object_idx();
|
||||
if (object_idx < 0 || object_idx >= m_model->objects.size()) continue;
|
||||
const ModelObject* hover_object = m_model->objects[object_idx];
|
||||
int hover_volume_idx = hover_gl_volume.volume_idx();
|
||||
if (hover_volume_idx < 0 || hover_volume_idx >= hover_object->volumes.size()) continue;
|
||||
const ModelVolume* hover_volume = hover_object->volumes[hover_volume_idx];
|
||||
if (hover_volume->text_configuration.has_value()) {
|
||||
//m_selection.set_mode(Selection::EMode::Volume);
|
||||
//m_selection.add(hover_volume_id); // add whole instance
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
if (!hover_volume->text_configuration.has_value()) continue;
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
if (type != GLGizmosManager::EType::Emboss)
|
||||
m_gizmos.open_gizmo(GLGizmosManager::EType::Emboss);
|
||||
wxGetApp().obj_list()->update_selections();
|
||||
return;
|
||||
}
|
||||
wxGetApp().obj_list()->update_selections();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -970,16 +970,19 @@ void MenuFactory::append_menu_item_edit_text(wxMenu *menu)
|
|||
wxString name = _L("Edit text");
|
||||
|
||||
auto can_edit_text = []() {
|
||||
const auto& sel = plater()->get_selection();
|
||||
if (sel.volumes_count() != 1) return false;
|
||||
auto cid = sel.get_volume(*sel.get_volume_idxs().begin());
|
||||
const ModelVolume* vol = plater()->canvas3D()->get_model()
|
||||
->objects[cid->object_idx()]->volumes[cid->volume_idx()];
|
||||
return vol->text_configuration.has_value();
|
||||
if (plater() != nullptr) {
|
||||
const Selection& sel = plater()->get_selection();
|
||||
if (sel.volumes_count() == 1) {
|
||||
const GLVolume* gl_vol = sel.get_first_volume();
|
||||
const ModelVolume* vol = plater()->model().objects[gl_vol->object_idx()]->volumes[gl_vol->volume_idx()];
|
||||
return vol->text_configuration.has_value();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (menu == &m_object_menu) {
|
||||
auto menu_item_id = menu->FindItem(name);
|
||||
if (menu != &m_text_part_menu) {
|
||||
const int menu_item_id = menu->FindItem(name);
|
||||
if (menu_item_id != wxNOT_FOUND)
|
||||
menu->Destroy(menu_item_id);
|
||||
if (!can_edit_text())
|
||||
|
|
|
@ -30,6 +30,7 @@ static const ColorRGBA SELECTED_PLAG_COLOR = ColorRGBA::GRAY();
|
|||
static const ColorRGBA SELECTED_DOWEL_COLOR = ColorRGBA::DARK_GRAY();
|
||||
static const ColorRGBA CONNECTOR_DEF_COLOR = ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
static const ColorRGBA CONNECTOR_ERR_COLOR = ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
|
||||
static const ColorRGBA HOVERED_ERR_COLOR = ColorRGBA(1.0f, 0.3f, 0.3f, 1.0f);
|
||||
|
||||
const unsigned int AngleResolution = 64;
|
||||
const unsigned int ScaleStepsCount = 72;
|
||||
|
@ -359,10 +360,19 @@ void GLGizmoCut3D::put_connectors_on_cut_plane(const Vec3d& cp_normal, double cp
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if the camera (forward) is pointing in the negative direction of the cut normal
|
||||
bool GLGizmoCut3D::is_looking_forward() const
|
||||
{
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const double dot = camera.get_dir_forward().dot(m_cut_normal);
|
||||
return dot < 0.05;
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::update_clipper()
|
||||
{
|
||||
BoundingBoxf3 box = bounding_box();
|
||||
|
||||
// update cut_normal
|
||||
Vec3d beg, end = beg = m_plane_center;
|
||||
beg[Z] = box.center().z() - m_radius;
|
||||
end[Z] = box.center().z() + m_radius;
|
||||
|
@ -370,12 +380,26 @@ void GLGizmoCut3D::update_clipper()
|
|||
rotate_vec3d_around_plane_center(beg);
|
||||
rotate_vec3d_around_plane_center(end);
|
||||
|
||||
double dist = (m_plane_center - beg).norm();
|
||||
// calculate normal for cut plane
|
||||
Vec3d normal = m_cut_normal = end - beg;
|
||||
m_cut_normal.normalize();
|
||||
|
||||
if (!is_looking_forward()) {
|
||||
end = beg = m_plane_center;
|
||||
beg[Z] = box.center().z() + m_radius;
|
||||
end[Z] = box.center().z() - m_radius;
|
||||
|
||||
rotate_vec3d_around_plane_center(beg);
|
||||
rotate_vec3d_around_plane_center(end);
|
||||
|
||||
// recalculate normal for clipping plane, if camera is looking downward to cut plane
|
||||
normal = end - beg;
|
||||
if (normal == Vec3d::Zero())
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate normal and offset for clipping plane
|
||||
Vec3d normal = end - beg;
|
||||
if (normal == Vec3d::Zero())
|
||||
return;
|
||||
double dist = (m_plane_center - beg).norm();
|
||||
dist = std::clamp(dist, 0.0001, normal.norm());
|
||||
normal.normalize();
|
||||
const double offset = normal.dot(beg) + dist;
|
||||
|
@ -1372,7 +1396,7 @@ void GLGizmoCut3D::render_clipper_cut()
|
|||
|
||||
void GLGizmoCut3D::on_render()
|
||||
{
|
||||
if (update_bb() || force_update_clipper_on_render) {
|
||||
if (update_bb() || force_update_clipper_on_render || m_connectors_editing) {
|
||||
update_clipper_on_render();
|
||||
m_c->object_clipper()->set_behavior(m_connectors_editing, m_connectors_editing, 0.4);
|
||||
}
|
||||
|
@ -1826,7 +1850,7 @@ Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) c
|
|||
return translation_transform(offset) * scale_transform(Vec3d::Ones() - border_scale) * vol_matrix;
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos)
|
||||
bool GLGizmoCut3D::is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos)
|
||||
{
|
||||
// check if connector pos is out of clipping plane
|
||||
if (m_c->object_clipper() && !m_c->object_clipper()->is_projection_inside_cut(cur_pos)) {
|
||||
|
@ -1834,16 +1858,54 @@ bool GLGizmoCut3D::is_conflict_for_connector(size_t idx, const CutConnectors& co
|
|||
return true;
|
||||
}
|
||||
|
||||
// check if connector bottom contour is out of clipping plane
|
||||
const CutConnector& cur_connector = connectors[idx];
|
||||
const CutConnectorShape shape = CutConnectorShape(cur_connector.attribs.shape);
|
||||
const int sectorCount = shape == CutConnectorShape::Triangle ? 3 :
|
||||
shape == CutConnectorShape::Square ? 4 :
|
||||
shape == CutConnectorShape::Circle ? 60: // supposably, 60 points are enough for conflict detection
|
||||
shape == CutConnectorShape::Hexagon ? 6 : 1 ;
|
||||
|
||||
indexed_triangle_set mesh;
|
||||
auto& vertices = mesh.vertices;
|
||||
vertices.reserve(sectorCount + 1);
|
||||
|
||||
float fa = 2 * PI / sectorCount;
|
||||
auto vec = Eigen::Vector2f(0, cur_connector.radius);
|
||||
for (float angle = 0; angle < 2.f * PI; angle += fa) {
|
||||
Vec2f p = Eigen::Rotation2Df(angle) * vec;
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
|
||||
}
|
||||
its_transform(mesh, translation_transform(cur_pos) * m_rotation_m);
|
||||
|
||||
for (auto vertex : vertices) {
|
||||
if (m_c->object_clipper() && !m_c->object_clipper()->is_projection_inside_cut(vertex.cast<double>())) {
|
||||
m_info_stats.outside_cut_contour++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos)
|
||||
{
|
||||
if (is_outside_of_cut_contour(idx, connectors, cur_pos))
|
||||
return true;
|
||||
|
||||
const CutConnector& cur_connector = connectors[idx];
|
||||
|
||||
const Transform3d matrix = translation_transform(cur_pos) * m_rotation_m *
|
||||
scale_transform(Vec3f(cur_connector.radius, cur_connector.radius, cur_connector.height).cast<double>());
|
||||
const BoundingBoxf3 cur_tbb = m_shapes[cur_connector.attribs].model.get_bounding_box().transformed(matrix);
|
||||
|
||||
// check if connector's bounding box is inside the object's bounding box
|
||||
if (!bounding_box().contains(cur_tbb)) {
|
||||
m_info_stats.outside_bb++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if connectors are overlapping
|
||||
for (size_t i = 0; i < connectors.size(); ++i) {
|
||||
if (i == idx)
|
||||
continue;
|
||||
|
@ -1897,7 +1959,8 @@ void GLGizmoCut3D::render_connectors()
|
|||
Vec3d pos = connector.pos + instance_offset + sla_shift * Vec3d::UnitZ();
|
||||
|
||||
// First decide about the color of the point.
|
||||
if (is_conflict_for_connector(i, connectors, pos)) {
|
||||
const bool conflict_connector = is_conflict_for_connector(i, connectors, pos);
|
||||
if (conflict_connector) {
|
||||
m_has_invalid_connector = true;
|
||||
render_color = CONNECTOR_ERR_COLOR;
|
||||
}
|
||||
|
@ -1907,16 +1970,23 @@ void GLGizmoCut3D::render_connectors()
|
|||
if (!m_connectors_editing)
|
||||
render_color = CONNECTOR_ERR_COLOR;
|
||||
else if (size_t(m_hover_id - m_connectors_group_id) == i)
|
||||
render_color = connector.attribs.type == CutConnectorType::Dowel ? HOVERED_DOWEL_COLOR : HOVERED_PLAG_COLOR;
|
||||
render_color = conflict_connector ? HOVERED_ERR_COLOR :
|
||||
connector.attribs.type == CutConnectorType::Dowel ? HOVERED_DOWEL_COLOR : HOVERED_PLAG_COLOR;
|
||||
else if (m_selected[i])
|
||||
render_color = connector.attribs.type == CutConnectorType::Dowel ? SELECTED_DOWEL_COLOR : SELECTED_PLAG_COLOR;
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
if (connector.attribs.type == CutConnectorType::Dowel &&
|
||||
connector.attribs.style == CutConnectorStyle::Prizm) {
|
||||
pos -= height * normal;
|
||||
if (is_looking_forward())
|
||||
pos -= height * normal;
|
||||
else
|
||||
pos += height * normal;
|
||||
height *= 2;
|
||||
}
|
||||
else if (!is_looking_forward())
|
||||
pos += 0.05 * normal;
|
||||
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(pos) * m_rotation_m *
|
||||
scale_transform(Vec3f(connector.radius, connector.radius, height).cast<double>());
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||
GLModel m_angle_arc;
|
||||
|
||||
Vec3d m_old_center;
|
||||
Vec3d m_cut_normal;
|
||||
|
||||
struct InvalidConnectorsStatistics
|
||||
{
|
||||
|
@ -160,6 +161,7 @@ public:
|
|||
|
||||
bool is_in_editing_mode() const override { return m_connectors_editing; }
|
||||
bool is_selection_rectangle_dragging() const override { return m_selection_rectangle.is_dragging(); }
|
||||
bool is_looking_forward() const;
|
||||
|
||||
/// <summary>
|
||||
/// Drag of plane
|
||||
|
@ -239,6 +241,7 @@ private:
|
|||
bool render_reset_button(const std::string& label_id, const std::string& tooltip) const;
|
||||
bool render_connect_type_radio_button(CutConnectorType type);
|
||||
Transform3d get_volume_transformation(const ModelVolume* volume) const;
|
||||
bool is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
|
||||
bool is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
|
||||
void render_connectors();
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -87,8 +87,10 @@ private:
|
|||
// localized default text
|
||||
void set_default_text();
|
||||
|
||||
void check_selection();
|
||||
ModelVolume *get_selected_volume();
|
||||
void set_volume_by_selection();
|
||||
// load text configuration from volume into gizmo
|
||||
bool set_volume(ModelVolume *volume);
|
||||
|
||||
// create volume from text - main functionality
|
||||
bool process();
|
||||
void close();
|
||||
|
@ -109,6 +111,9 @@ private:
|
|||
void draw_font_preview(FaceName &face, bool is_visible);
|
||||
void draw_font_list();
|
||||
void draw_style_edit();
|
||||
void draw_height(std::optional<float> scale, bool use_inch);
|
||||
void draw_depth(std::optional<float> scale, bool use_inch);
|
||||
|
||||
bool draw_italic_button();
|
||||
bool draw_bold_button();
|
||||
void draw_advanced();
|
||||
|
@ -119,11 +124,9 @@ private:
|
|||
void do_translate(const Vec3d& relative_move);
|
||||
void do_rotate(float relative_z_angle);
|
||||
|
||||
/// <summary>
|
||||
/// Move window for edit emboss text near to embossed object
|
||||
/// NOTE: embossed object must be selected
|
||||
/// </summary>
|
||||
void set_fine_position();
|
||||
bool rev_input_mm(const std::string &name, float &value, const float *default_value,
|
||||
const std::string &undo_tooltip, float step, float step_fast, const char *format,
|
||||
bool use_inch = false, std::optional<float> scale = {});
|
||||
|
||||
/// <summary>
|
||||
/// Reversible input float with option to restor default value
|
||||
|
@ -154,8 +157,6 @@ private:
|
|||
bool choose_true_type_file();
|
||||
bool choose_svg_file();
|
||||
|
||||
bool load_configuration(ModelVolume *volume);
|
||||
|
||||
// When open text loaded from .3mf it could be written with unknown font
|
||||
bool m_is_unknown_font;
|
||||
void create_notification_not_valid_font(const TextConfiguration& tc);
|
||||
|
@ -216,9 +217,12 @@ private:
|
|||
GuiCfg() = default;
|
||||
};
|
||||
std::optional<const GuiCfg> m_gui_cfg;
|
||||
bool m_is_advanced_edit_style = false;
|
||||
|
||||
// when true window will appear near to text
|
||||
bool m_allow_float_window = false;
|
||||
// setted only when wanted to use - not all the time
|
||||
std::optional<ImVec2> m_set_window_offset;
|
||||
bool m_is_advanced_edit_style = false;
|
||||
|
||||
Emboss::StyleManager m_style_manager;
|
||||
|
||||
|
|
|
@ -257,20 +257,39 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt)
|
|||
return false;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
auto to_string = [](wxEventType type) -> std::string {
|
||||
if (type == wxEVT_CHAR) return "Char";
|
||||
if (type == wxEVT_KEY_DOWN) return "KeyDown";
|
||||
if (type == wxEVT_KEY_UP) return "KeyUp";
|
||||
return "Other";
|
||||
};
|
||||
|
||||
if (evt.GetEventType() == wxEVT_CHAR) {
|
||||
wxEventType type = evt.GetEventType();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
BOOST_LOG_TRIVIAL(debug) << "ImGui - key event(" << to_string(type) << "):"
|
||||
//<< " Unicode(" << evt.GetUnicodeKey() << ")"
|
||||
<< " KeyCode(" << evt.GetKeyCode() << ")";
|
||||
|
||||
if (type == wxEVT_CHAR) {
|
||||
// Char event
|
||||
const auto key = evt.GetUnicodeKey();
|
||||
const auto key = evt.GetUnicodeKey();
|
||||
unsigned int key_u = static_cast<unsigned int>(key);
|
||||
|
||||
// Release BackSpace, Delete, ... when miss wxEVT_KEY_UP event
|
||||
// Already Fixed at begining of new frame
|
||||
//if (key_u >= 0 && key_u < IM_ARRAYSIZE(io.KeysDown) && io.KeysDown[key_u]) {
|
||||
// io.KeysDown[key_u] = false;
|
||||
//}
|
||||
|
||||
if (key != 0) {
|
||||
io.AddInputCharacter(key);
|
||||
}
|
||||
} else {
|
||||
} else if (type == wxEVT_KEY_DOWN || type == wxEVT_KEY_UP) {
|
||||
// Key up/down event
|
||||
int key = evt.GetKeyCode();
|
||||
wxCHECK_MSG(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown), false, "Received invalid key code");
|
||||
|
||||
io.KeysDown[key] = evt.GetEventType() == wxEVT_KEY_DOWN;
|
||||
io.KeysDown[key] = (type == wxEVT_KEY_DOWN);
|
||||
io.KeyShift = evt.ShiftDown();
|
||||
io.KeyCtrl = evt.ControlDown();
|
||||
io.KeyAlt = evt.AltDown();
|
||||
|
@ -282,6 +301,7 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#include <array>
|
||||
void ImGuiWrapper::new_frame()
|
||||
{
|
||||
if (m_new_frame_open) {
|
||||
|
@ -292,6 +312,35 @@ void ImGuiWrapper::new_frame()
|
|||
init_font(true);
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
// synchronize key states
|
||||
// when the application loses the focus it may happen that the key up event is not processed
|
||||
|
||||
// synchronize modifier keys
|
||||
constexpr std::array<std::pair<ImGuiKeyModFlags_, wxKeyCode>, 3> imgui_mod_keys{
|
||||
std::make_pair(ImGuiKeyModFlags_Ctrl, WXK_CONTROL),
|
||||
std::make_pair(ImGuiKeyModFlags_Shift, WXK_SHIFT),
|
||||
std::make_pair(ImGuiKeyModFlags_Alt, WXK_ALT)};
|
||||
for (const std::pair<ImGuiKeyModFlags_, wxKeyCode>& key : imgui_mod_keys) {
|
||||
if ((io.KeyMods & key.first) != 0 && !wxGetKeyState(key.second))
|
||||
io.KeyMods &= ~key.first;
|
||||
}
|
||||
|
||||
// Not sure if it is neccessary
|
||||
// values from 33 to 126 are reserved for the standard ASCII characters
|
||||
for (size_t i = 33; i <= 126; ++i) {
|
||||
wxKeyCode keycode = static_cast<wxKeyCode>(i);
|
||||
if (io.KeysDown[i] && keycode != WXK_NONE && !wxGetKeyState(keycode))
|
||||
io.KeysDown[i] = false;
|
||||
}
|
||||
|
||||
// special keys: delete, backspace, ...
|
||||
for (int key: io.KeyMap) {
|
||||
wxKeyCode keycode = static_cast<wxKeyCode>(key);
|
||||
if (io.KeysDown[key] && keycode != WXK_NONE && !wxGetKeyState(keycode))
|
||||
io.KeysDown[key] = false;
|
||||
}
|
||||
|
||||
ImGui::NewFrame();
|
||||
m_new_frame_open = true;
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@ TriangleMesh priv::create_mesh(DataBase &input, Fnc was_canceled, Job::Ctl& ctl)
|
|||
TriangleMesh priv::create_default_mesh()
|
||||
{
|
||||
// When cant load any font use default object loaded from file
|
||||
std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl";
|
||||
std::string path = Slic3r::resources_dir() + "/data/embossed_text.obj";
|
||||
TriangleMesh triangle_mesh;
|
||||
if (!load_obj(path.c_str(), &triangle_mesh)) {
|
||||
// when can't load mesh use cube
|
||||
|
@ -527,10 +527,6 @@ void UpdateJob::update_volume(ModelVolume *volume,
|
|||
obj_list->update_name_in_list(object_idx, volume_idx);
|
||||
}
|
||||
|
||||
// update printable state on canvas
|
||||
if (volume->type() == ModelVolumeType::MODEL_PART)
|
||||
canvas->update_instance_printable_state_for_object((size_t) object_idx);
|
||||
|
||||
// Move object on bed
|
||||
if (GLGizmoEmboss::is_text_object(volume)) volume->get_object()->ensure_on_bed();
|
||||
|
||||
|
@ -679,7 +675,7 @@ OrthoProject3d priv::create_emboss_projection(
|
|||
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
|
||||
{
|
||||
// Offset of clossed side to model
|
||||
const float surface_offset = 1e-3f; // [in mm]
|
||||
const float surface_offset = 0.015f; // [in mm]
|
||||
float
|
||||
front_move = (is_outside) ? emboss : surface_offset,
|
||||
back_move = -((is_outside) ? surface_offset : emboss);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <libslic3r/Emboss.hpp>
|
||||
//#include <libslic3r/ModelVolumeType.hpp>
|
||||
#include "slic3r/Utils/RaycastManager.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "Job.hpp"
|
||||
|
|
|
@ -154,6 +154,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ "L", L("Gizmo FDM paint-on supports") },
|
||||
{ "P", L("Gizmo FDM paint-on seam") },
|
||||
{ "N", L("Gizmo Multi Material painting") },
|
||||
{ "T", L("Gizmo Text emboss / engrave")},
|
||||
{ "Esc", L("Unselect gizmo or clear selection") },
|
||||
{ "K", L("Change camera type (perspective, orthographic)") },
|
||||
{ "B", L("Zoom to Bed") },
|
||||
|
|
|
@ -39,19 +39,19 @@ void StyleManager::init(AppConfig *app_config, const EmbossStyles &default_style
|
|||
m_style_items.push_back({style});
|
||||
}
|
||||
|
||||
std::optional<size_t> activ_index_opt = (app_config != nullptr) ?
|
||||
std::optional<size_t> active_index_opt = (app_config != nullptr) ?
|
||||
EmbossStylesSerializable::load_style_index(*app_config) :
|
||||
std::optional<size_t>{};
|
||||
|
||||
size_t activ_index = 0;
|
||||
if (activ_index_opt.has_value()) activ_index = *activ_index_opt;
|
||||
if (activ_index >= m_style_items.size()) activ_index = 0;
|
||||
size_t active_index = 0;
|
||||
if (active_index_opt.has_value()) active_index = *active_index_opt;
|
||||
if (active_index >= m_style_items.size()) active_index = 0;
|
||||
|
||||
// find valid font item
|
||||
if (!load_style(activ_index)) {
|
||||
m_style_items.erase(m_style_items.begin() + activ_index);
|
||||
activ_index = 0;
|
||||
while (m_style_items.empty() || !load_style(activ_index))
|
||||
if (!load_style(active_index)) {
|
||||
m_style_items.erase(m_style_items.begin() + active_index);
|
||||
active_index = 0;
|
||||
while (m_style_items.empty() || !load_style(active_index))
|
||||
m_style_items.erase(m_style_items.begin());
|
||||
// no one style from config is loadable
|
||||
if (m_style_items.empty()) {
|
||||
|
@ -61,14 +61,14 @@ void StyleManager::init(AppConfig *app_config, const EmbossStyles &default_style
|
|||
m_style_items.push_back({std::move(style)});
|
||||
}
|
||||
// try to load first default font
|
||||
[[maybe_unused]] bool loaded = load_style(activ_index);
|
||||
[[maybe_unused]] bool loaded = load_style(active_index);
|
||||
assert(loaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StyleManager::store_styles_to_app_config(bool use_modification,
|
||||
bool store_activ_index)
|
||||
bool store_active_index)
|
||||
{
|
||||
assert(m_app_config != nullptr);
|
||||
if (m_app_config == nullptr) return false;
|
||||
|
@ -87,7 +87,7 @@ bool StyleManager::store_styles_to_app_config(bool use_modification,
|
|||
m_style_cache.stored_wx_font = m_style_cache.wx_font;
|
||||
}
|
||||
|
||||
if (store_activ_index)
|
||||
if (store_active_index)
|
||||
{
|
||||
size_t style_index = exist_stored_style() ?
|
||||
m_style_cache.style_index :
|
||||
|
@ -200,7 +200,7 @@ bool StyleManager::load_style(const EmbossStyle &style, const wxFont &font)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool StyleManager::is_activ_font() { return m_style_cache.font_file.has_value(); }
|
||||
bool StyleManager::is_active_font() { return m_style_cache.font_file.has_value(); }
|
||||
|
||||
bool StyleManager::load_first_valid_font() {
|
||||
while (!m_style_items.empty()) {
|
||||
|
@ -228,7 +228,7 @@ void StyleManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
|
|||
|
||||
ImFont *StyleManager::get_imgui_font()
|
||||
{
|
||||
if (!is_activ_font()) return nullptr;
|
||||
if (!is_active_font()) return nullptr;
|
||||
|
||||
ImVector<ImFont *> &fonts = m_style_cache.atlas.Fonts;
|
||||
if (fonts.empty()) return nullptr;
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
/// <param name="use_modification">When true cache state will be used for store</param>
|
||||
/// <param name="use_modification">When true store activ index into configuration</param>
|
||||
/// <returns>True on succes otherwise False.</returns>
|
||||
bool store_styles_to_app_config(bool use_modification = true, bool store_activ_index = true);
|
||||
bool store_styles_to_app_config(bool use_modification = true, bool store_active_index = true);
|
||||
|
||||
/// <summary>
|
||||
/// Append actual style to style list
|
||||
|
@ -185,7 +185,7 @@ public:
|
|||
};
|
||||
|
||||
// check if exist selected font style in manager
|
||||
bool is_activ_font();
|
||||
bool is_active_font();
|
||||
|
||||
// Limits for imgui loaded font size
|
||||
// Value out of limits is crop
|
||||
|
|
|
@ -19,7 +19,7 @@ const std::string EmbossStylesSerializable::APP_CONFIG_FONT_COLLECTION = "colle
|
|||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_CHAR_GAP = "char_gap";
|
||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap";
|
||||
|
||||
const std::string EmbossStylesSerializable::APP_CONFIG_ACTIVE_FONT = "activ_font";
|
||||
const std::string EmbossStylesSerializable::APP_CONFIG_ACTIVE_FONT = "active_font";
|
||||
|
||||
std::string EmbossStylesSerializable::create_section_name(unsigned index)
|
||||
{
|
||||
|
@ -150,8 +150,8 @@ void EmbossStylesSerializable::store_style_index(AppConfig &cfg, unsigned index)
|
|||
// store actual font index
|
||||
cfg.clear_section(AppConfig::SECTION_EMBOSS_STYLE);
|
||||
// activ font first index is +1 to correspond with section name
|
||||
std::string activ_font = std::to_string(index);
|
||||
cfg.set(AppConfig::SECTION_EMBOSS_STYLE, APP_CONFIG_ACTIVE_FONT, activ_font);
|
||||
std::string active_font = std::to_string(index);
|
||||
cfg.set(AppConfig::SECTION_EMBOSS_STYLE, APP_CONFIG_ACTIVE_FONT, active_font);
|
||||
}
|
||||
|
||||
std::optional<size_t> EmbossStylesSerializable::load_style_index(const AppConfig &cfg)
|
||||
|
|
|
@ -220,10 +220,16 @@ SCENARIO( "make_xxx functions produce meshes.") {
|
|||
GIVEN("make_sphere() function") {
|
||||
WHEN("make_sphere() is called with arguments 10, PI / 3") {
|
||||
TriangleMesh sph = make_sphere(10, PI / 243.0);
|
||||
THEN("Resulting mesh has one point at 0,0,-10 and one at 0,0,10") {
|
||||
const std::vector<stl_vertex> &verts = sph.its.vertices;
|
||||
REQUIRE(std::count_if(verts.begin(), verts.end(), [](const Vec3f& t) { return is_approx(t, Vec3f(0.f, 0.f, 10.f)); } ) == 1);
|
||||
REQUIRE(std::count_if(verts.begin(), verts.end(), [](const Vec3f& t) { return is_approx(t, Vec3f(0.f, 0.f, -10.f)); } ) == 1);
|
||||
THEN( "Edge length is smaller than limit but not smaller than half of it") {
|
||||
double len = (sph.its.vertices[sph.its.indices[0][0]] - sph.its.vertices[sph.its.indices[0][1]]).norm();
|
||||
double limit = 10*PI/243.;
|
||||
REQUIRE(len <= limit);
|
||||
REQUIRE(len >= limit/2.);
|
||||
}
|
||||
THEN( "Vertices are about the correct distance from the origin") {
|
||||
bool all_vertices_ok = std::all_of(sph.its.vertices.begin(), sph.its.vertices.end(),
|
||||
[](const stl_vertex& pt) { return is_approx(pt.squaredNorm(), 100.f); });
|
||||
REQUIRE(all_vertices_ok);
|
||||
}
|
||||
THEN( "The mesh volume is approximately 4/3 * pi * 10^3") {
|
||||
REQUIRE(abs(sph.volume() - (4.0/3.0 * M_PI * std::pow(10,3))) < 1); // 1% tolerance?
|
||||
|
|
|
@ -201,7 +201,7 @@ ExPolygons heal_and_check(const Polygons &polygons)
|
|||
{
|
||||
Pointfs intersections_prev = intersection_points(polygons);
|
||||
Points polygons_points = to_points(polygons);
|
||||
Points duplicits_prev = collect_duplications(polygons_points);
|
||||
Points duplicits_prev = collect_duplicates(polygons_points);
|
||||
|
||||
ExPolygons shape = Emboss::heal_shape(polygons);
|
||||
|
||||
|
@ -215,7 +215,7 @@ ExPolygons heal_and_check(const Polygons &polygons)
|
|||
|
||||
Pointfs intersections = intersection_points(shape);
|
||||
Points shape_points = to_points(shape);
|
||||
Points duplicits = collect_duplications(shape_points);
|
||||
Points duplicits = collect_duplicates(shape_points);
|
||||
//{
|
||||
// BoundingBox bb(polygons_points);
|
||||
// // bb.scale(svg_scale);
|
||||
|
|
Loading…
Reference in a new issue