Merge branch 'et_gcode_viewer' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer
This commit is contained in:
commit
6041ec9aae
87 changed files with 2899 additions and 1761 deletions
|
@ -234,7 +234,7 @@ foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
|||
|
||||
if (_is_multi)
|
||||
list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY_RELEASE})
|
||||
if (MSVC OR OpenVDB_${COMPONENT}_LIBRARY_DEBUG)
|
||||
if (OpenVDB_${COMPONENT}_LIBRARY_DEBUG)
|
||||
list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY_DEBUG})
|
||||
endif ()
|
||||
|
||||
|
|
5
deps/CMakeLists.txt
vendored
5
deps/CMakeLists.txt
vendored
|
@ -152,6 +152,11 @@ include(MPFR/MPFR.cmake)
|
|||
include(CGAL/CGAL.cmake)
|
||||
include(wxWidgets/wxWidgets.cmake)
|
||||
|
||||
if (ZLIB_PKG)
|
||||
add_dependencies(dep_blosc ${ZLIB_PKG})
|
||||
add_dependencies(dep_openexr ${ZLIB_PKG})
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
|
||||
add_custom_target(deps ALL
|
||||
|
|
6
deps/deps-windows.cmake
vendored
6
deps/deps-windows.cmake
vendored
|
@ -35,8 +35,6 @@ else ()
|
|||
set(DEP_PLATFORM "x64")
|
||||
endif ()
|
||||
|
||||
|
||||
|
||||
if (${DEP_DEBUG})
|
||||
set(DEP_BOOST_DEBUG "debug")
|
||||
else ()
|
||||
|
@ -217,7 +215,6 @@ ExternalProject_Add(dep_blosc
|
|||
#URL_HASH SHA256=7463a1df566704f212263312717ab2c36b45d45cba6cd0dccebf91b2cc4b4da9
|
||||
GIT_REPOSITORY https://github.com/Blosc/c-blosc.git
|
||||
GIT_TAG e63775855294b50820ef44d1b157f4de1cc38d3e #v1.17.0
|
||||
DEPENDS ${ZLIB_PKG}
|
||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||
CMAKE_ARGS
|
||||
|
@ -243,8 +240,7 @@ add_debug_dep(dep_blosc)
|
|||
ExternalProject_Add(dep_openexr
|
||||
EXCLUDE_FROM_ALL 1
|
||||
GIT_REPOSITORY https://github.com/openexr/openexr.git
|
||||
GIT_TAG eae0e337c9f5117e78114fd05f7a415819df413a #v2.4.0
|
||||
DEPENDS ${ZLIB_PKG}
|
||||
GIT_TAG eae0e337c9f5117e78114fd05f7a415819df413a #v2.4.0
|
||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||
CMAKE_ARGS
|
||||
|
|
1
deps/wxWidgets/wxWidgets.cmake
vendored
1
deps/wxWidgets/wxWidgets.cmake
vendored
|
@ -19,6 +19,7 @@ prusaslicer_add_cmake_project(wxWidgets
|
|||
-DwxBUILD_PRECOMP=ON
|
||||
${_wx_toolkit}
|
||||
"-DCMAKE_DEBUG_POSTFIX:STRING="
|
||||
-DwxBUILD_DEBUG_LEVEL=0
|
||||
-DwxUSE_DETECT_SM=OFF
|
||||
-DwxUSE_UNICODE=ON
|
||||
-DwxUSE_OPENGL=ON
|
||||
|
|
11
resources/shaders/gouraud_light.fs
Normal file
11
resources/shaders/gouraud_light.fs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#version 110
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
38
resources/shaders/gouraud_light.vs
Normal file
38
resources/shaders/gouraud_light.vs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#version 110
|
||||
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 20.0
|
||||
|
||||
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
void main()
|
||||
{
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
|
@ -565,10 +565,6 @@ int CLI::run(int argc, char **argv)
|
|||
gui->mainframe->load_config(m_extra_config);
|
||||
});
|
||||
int result = wxEntry(argc, argv);
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
//FIXME this is a workaround for the PrusaSlicer 2.1 release.
|
||||
_3DScene::destroy();
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
return result;
|
||||
#else /* SLIC3R_GUI */
|
||||
// No GUI support. Just print out a help.
|
||||
|
|
|
@ -3,3 +3,8 @@
|
|||
For more information go to https://github.com/ocornut/imgui
|
||||
|
||||
THIS DIRECTORY CONTAINS THE imgui-1.75 58b3e02 SOURCE DISTRIBUTION.
|
||||
|
||||
Customized with the following commits:
|
||||
042880ba2df913916b2cc77f7bb677e07bfd2c58
|
||||
67c55c74901f1d337ef08f2090a87cfb4263bb0f
|
||||
a94c952b40d36b1505fb77b87c0dd739e1034659
|
|
@ -107,6 +107,13 @@ namespace ImGui
|
|||
const char ColorMarkerStart = 0x2; // STX
|
||||
const char ColorMarkerEnd = 0x3; // ETX
|
||||
|
||||
// Special ASCII characters are used here as a ikons markers
|
||||
const char PrintIconMarker = 0x4;
|
||||
const char PrinterIconMarker = 0x5;
|
||||
const char PrinterSlaIconMarker = 0x6;
|
||||
const char FilamentIconMarker = 0x7;
|
||||
const char MaterialIconMarker = 0x8;
|
||||
|
||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "CustomGCode.hpp"
|
||||
#include "Config.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GCode.hpp"
|
||||
#else
|
||||
#include "GCode/PreviewData.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#include "GCodeWriter.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -17,8 +21,12 @@ extern void update_custom_gcode_per_print_z_from_config(Info& info, DynamicPrint
|
|||
return;
|
||||
if (info.gcodes.empty() && ! colorprint_heights->values.empty()) {
|
||||
// Convert the old colorprint_heighs only if there is no equivalent data in a new format.
|
||||
const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
|
||||
const auto& colorprint_values = colorprint_heights->values;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const std::vector<std::string>& colors = ColorPrintColors::get();
|
||||
#else
|
||||
const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
const auto& colorprint_values = colorprint_heights->values;
|
||||
info.gcodes.clear();
|
||||
info.gcodes.reserve(colorprint_values.size());
|
||||
int i = 0;
|
||||
|
|
|
@ -1361,7 +1361,6 @@ static void traverse_graph_generate_polylines(
|
|||
continue;
|
||||
}
|
||||
|
||||
dont_connect:
|
||||
// No way to continue the current polyline. Take the rest of the line up to the outer contour.
|
||||
// This will finish the polyline, starting another polyline at a new point.
|
||||
going_up ? ++ it : -- it;
|
||||
|
@ -1442,6 +1441,8 @@ struct MonotonousRegionLink
|
|||
AntPath *next_flipped;
|
||||
};
|
||||
|
||||
// Matrix of paths (AntPath) connecting ends of MontonousRegions.
|
||||
// AntPath lengths and their derived visibilities refer to the length of the perimeter line if such perimeter segment exists.
|
||||
class AntPathMatrix
|
||||
{
|
||||
public:
|
||||
|
@ -1456,6 +1457,12 @@ public:
|
|||
// From end of one region to the start of another region, both flipped or not flipped.
|
||||
m_matrix(regions.size() * regions.size() * 4, AntPath{ -1., -1., initial_pheromone}) {}
|
||||
|
||||
void update_inital_pheromone(float initial_pheromone)
|
||||
{
|
||||
for (AntPath &ap : m_matrix)
|
||||
ap.pheromone = initial_pheromone;
|
||||
}
|
||||
|
||||
AntPath& operator()(const MonotonousRegion ®ion_from, bool flipped_from, const MonotonousRegion ®ion_to, bool flipped_to)
|
||||
{
|
||||
int row = 2 * int(®ion_from - m_regions.data()) + flipped_from;
|
||||
|
@ -1478,7 +1485,7 @@ public:
|
|||
// Just apply the Eucledian distance of the end points.
|
||||
path.length = unscale<float>(Vec2f(vline_to.pos - vline_from.pos, vline_to.intersections[i_to].pos() - vline_from.intersections[i_from].pos()).norm());
|
||||
}
|
||||
path.visibility = 1. / (path.length + EPSILON);
|
||||
path.visibility = 1.f / (path.length + float(EPSILON));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -1497,7 +1504,7 @@ private:
|
|||
const ExPolygonWithOffset &m_poly_with_offset;
|
||||
const std::vector<SegmentedIntersectionLine> &m_segs;
|
||||
// From end of one region to the start of another region, both flipped or not flipped.
|
||||
//FIXME one may possibly use sparse representation of the matrix.
|
||||
//FIXME one may possibly use sparse representation of the matrix, likely using hashing.
|
||||
std::vector<AntPath> m_matrix;
|
||||
};
|
||||
|
||||
|
@ -1724,7 +1731,98 @@ static std::vector<MonotonousRegion> generate_montonous_regions(std::vector<Segm
|
|||
return monotonous_regions;
|
||||
}
|
||||
|
||||
static void connect_monotonous_regions(std::vector<MonotonousRegion> ®ions, std::vector<SegmentedIntersectionLine> &segs)
|
||||
// Traverse path, calculate length of the draw for the purpose of optimization.
|
||||
// This function is very similar to polylines_from_paths() in the way how it traverses the path, but
|
||||
// polylines_from_paths() emits a path, while this function just calculates the path length.
|
||||
static float montonous_region_path_length(const MonotonousRegion ®ion, bool dir, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs)
|
||||
{
|
||||
// From the initial point (i_vline, i_intersection), follow a path.
|
||||
int i_intersection = region.left_intersection_point(dir);
|
||||
int i_vline = region.left.vline;
|
||||
float total_length = 0.;
|
||||
bool no_perimeter = false;
|
||||
Vec2f last_point;
|
||||
|
||||
for (;;) {
|
||||
const SegmentedIntersectionLine &vline = segs[i_vline];
|
||||
const SegmentIntersection *it = &vline.intersections[i_intersection];
|
||||
const bool going_up = it->is_low();
|
||||
|
||||
if (no_perimeter)
|
||||
total_length += (last_point - Vec2f(vline.pos, (it + (going_up ? - 1 : 1))->pos())).norm();
|
||||
|
||||
int iright = it->right_horizontal();
|
||||
if (going_up) {
|
||||
// Traverse the complete vertical segment up to the inner contour.
|
||||
for (;;) {
|
||||
do {
|
||||
++ it;
|
||||
iright = std::max(iright, it->right_horizontal());
|
||||
assert(it->is_inner());
|
||||
} while (it->type != SegmentIntersection::INNER_HIGH || (it + 1)->type != SegmentIntersection::OUTER_HIGH);
|
||||
int inext = it->vertical_up();
|
||||
if (inext == -1 || it->vertical_up_quality() != SegmentIntersection::LinkQuality::Valid)
|
||||
break;
|
||||
assert(it->iContour == vline.intersections[inext].iContour);
|
||||
it = vline.intersections.data() + inext;
|
||||
}
|
||||
} else {
|
||||
// Going down.
|
||||
assert(it->is_high());
|
||||
assert(i_intersection > 0);
|
||||
for (;;) {
|
||||
do {
|
||||
-- it;
|
||||
if (int iright_new = it->right_horizontal(); iright_new != -1)
|
||||
iright = iright_new;
|
||||
assert(it->is_inner());
|
||||
} while (it->type != SegmentIntersection::INNER_LOW || (it - 1)->type != SegmentIntersection::OUTER_LOW);
|
||||
int inext = it->vertical_down();
|
||||
if (inext == -1 || it->vertical_down_quality() != SegmentIntersection::LinkQuality::Valid)
|
||||
break;
|
||||
assert(it->iContour == vline.intersections[inext].iContour);
|
||||
it = vline.intersections.data() + inext;
|
||||
}
|
||||
}
|
||||
|
||||
if (i_vline == region.right.vline)
|
||||
break;
|
||||
|
||||
int inext = it->right_horizontal();
|
||||
if (inext != -1 && it->next_on_contour_quality == SegmentIntersection::LinkQuality::Valid) {
|
||||
// Summarize length of the connection line along the perimeter.
|
||||
//FIXME should it be weighted with a lower weight than non-extruding connection line? What weight?
|
||||
// Taking half of the length.
|
||||
total_length += 0.5f * float(measure_perimeter_horizontal_segment_length(poly_with_offset, segs, i_vline, it - vline.intersections.data(), inext));
|
||||
// Don't add distance to the next vertical line start to the total length.
|
||||
no_perimeter = false;
|
||||
i_intersection = inext;
|
||||
} else {
|
||||
// Finish the current vertical line,
|
||||
going_up ? ++ it : -- it;
|
||||
assert(it->is_outer());
|
||||
assert(it->is_high() == going_up);
|
||||
// Mark the end of this vertical line.
|
||||
last_point = Vec2f(vline.pos, it->pos());
|
||||
// Remember to add distance to the last point.
|
||||
no_perimeter = true;
|
||||
if (inext == -1) {
|
||||
// Find the end of the next overlapping vertical segment.
|
||||
const SegmentedIntersectionLine &vline_right = segs[i_vline + 1];
|
||||
const SegmentIntersection *right = going_up ?
|
||||
&vertical_run_top(vline_right, vline_right.intersections[iright]) : &vertical_run_bottom(vline_right, vline_right.intersections[iright]);
|
||||
i_intersection = int(right - vline_right.intersections.data());
|
||||
} else
|
||||
i_intersection = inext;
|
||||
}
|
||||
|
||||
++ i_vline;
|
||||
}
|
||||
|
||||
return unscale<float>(total_length);
|
||||
}
|
||||
|
||||
static void connect_monotonous_regions(std::vector<MonotonousRegion> ®ions, const ExPolygonWithOffset &poly_with_offset, std::vector<SegmentedIntersectionLine> &segs)
|
||||
{
|
||||
// Map from low intersection to left / right side of a monotonous region.
|
||||
using MapType = std::pair<SegmentIntersection*, MonotonousRegion*>;
|
||||
|
@ -1816,6 +1914,20 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> ®ions, s
|
|||
}
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// Fill in sum length of connecting lines of a region. This length is used for optimizing the infill path for minimum length.
|
||||
for (MonotonousRegion ®ion : regions) {
|
||||
region.len1 = montonous_region_path_length(region, false, poly_with_offset, segs);
|
||||
region.len2 = montonous_region_path_length(region, true, poly_with_offset, segs);
|
||||
// Subtract the smaller length from the longer one, so we will optimize just with the positive difference of the two.
|
||||
if (region.len1 > region.len2) {
|
||||
region.len1 -= region.len2;
|
||||
region.len2 = 0;
|
||||
} else {
|
||||
region.len2 -= region.len1;
|
||||
region.len1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Raad Salman: Algorithms for the Precedence Constrained Generalized Travelling Salesperson Problem
|
||||
|
@ -1851,6 +1963,7 @@ inline void print_ant(const std::string& fmt, TArgs&&... args) {
|
|||
}
|
||||
|
||||
// Find a run through monotonous infill blocks using an 'Ant colony" optimization method.
|
||||
// http://www.scholarpedia.org/article/Ant_colony_optimization
|
||||
static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
||||
std::vector<MonotonousRegion> ®ions, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs, std::mt19937_64 &rng)
|
||||
{
|
||||
|
@ -1940,14 +2053,18 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
};
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// How many times to repeat the ant simulation.
|
||||
constexpr int num_rounds = 10;
|
||||
// How many times to repeat the ant simulation (number of ant generations).
|
||||
constexpr int num_rounds = 25;
|
||||
// After how many rounds without an improvement to exit?
|
||||
constexpr int num_rounds_no_change_exit = 8;
|
||||
// With how many ants each of the run will be performed?
|
||||
constexpr int num_ants = 10;
|
||||
// Base (initial) pheromone level.
|
||||
constexpr float pheromone_initial_deposit = 0.5f;
|
||||
const int num_ants = std::min<int>(regions.size(), 10);
|
||||
// Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found.
|
||||
float pheromone_initial_deposit = 0.5f;
|
||||
// Evaporation rate of pheromones.
|
||||
constexpr float pheromone_evaporation = 0.1f;
|
||||
// Evaporation rate to diversify paths taken by individual ants.
|
||||
constexpr float pheromone_diversification = 0.1f;
|
||||
// Probability at which to take the next best path. Otherwise take the the path based on the cost distribution.
|
||||
constexpr float probability_take_best = 0.9f;
|
||||
// Exponents of the cost function.
|
||||
|
@ -1956,6 +2073,73 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
|
||||
AntPathMatrix path_matrix(regions, poly_with_offset, segs, pheromone_initial_deposit);
|
||||
|
||||
// Find an initial path in a greedy way, set the initial pheromone value to 10% of the cost of the greedy path.
|
||||
{
|
||||
// Construct the first path in a greedy way to calculate an initial value of the pheromone value.
|
||||
queue = queue_initial;
|
||||
left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
|
||||
assert(validate_unprocessed());
|
||||
// Pick the last of the queue.
|
||||
MonotonousRegionLink path_end { queue.back(), false };
|
||||
queue.pop_back();
|
||||
-- left_neighbors_unprocessed[path_end.region - regions.data()];
|
||||
|
||||
float total_length = path_end.region->length(false);
|
||||
while (! queue.empty() || ! path_end.region->right_neighbors.empty()) {
|
||||
// Chain.
|
||||
MonotonousRegion ®ion = *path_end.region;
|
||||
bool dir = path_end.flipped;
|
||||
NextCandidate next_candidate;
|
||||
next_candidate.probability = 0;
|
||||
for (MonotonousRegion *next : region.right_neighbors) {
|
||||
int &unprocessed = left_neighbors_unprocessed[next - regions.data()];
|
||||
assert(unprocessed > 1);
|
||||
if (left_neighbors_unprocessed[next - regions.data()] == 2) {
|
||||
// Dependencies of the successive blocks are satisfied.
|
||||
AntPath &path1 = path_matrix(region, dir, *next, false);
|
||||
AntPath &path2 = path_matrix(region, dir, *next, true);
|
||||
if (path1.visibility > next_candidate.probability)
|
||||
next_candidate = { next, &path1, &path1, path1.visibility, false };
|
||||
if (path2.visibility > next_candidate.probability)
|
||||
next_candidate = { next, &path2, &path2, path2.visibility, true };
|
||||
}
|
||||
}
|
||||
bool from_queue = next_candidate.probability == 0;
|
||||
if (from_queue) {
|
||||
for (MonotonousRegion *next : queue) {
|
||||
AntPath &path1 = path_matrix(region, dir, *next, false);
|
||||
AntPath &path2 = path_matrix(region, dir, *next, true);
|
||||
if (path1.visibility > next_candidate.probability)
|
||||
next_candidate = { next, &path1, &path1, path1.visibility, false };
|
||||
if (path2.visibility > next_candidate.probability)
|
||||
next_candidate = { next, &path2, &path2, path2.visibility, true };
|
||||
}
|
||||
}
|
||||
// Move the other right neighbors with satisified constraints to the queue.
|
||||
for (MonotonousRegion *next : region.right_neighbors)
|
||||
if (-- left_neighbors_unprocessed[next - regions.data()] == 1 && next_candidate.region != next)
|
||||
queue.emplace_back(next);
|
||||
if (from_queue) {
|
||||
// Remove the selected path from the queue.
|
||||
auto it = std::find(queue.begin(), queue.end(), next_candidate.region);
|
||||
assert(it != queue.end());
|
||||
*it = queue.back();
|
||||
queue.pop_back();
|
||||
}
|
||||
// Extend the path.
|
||||
MonotonousRegion *next_region = next_candidate.region;
|
||||
bool next_dir = next_candidate.dir;
|
||||
total_length += next_region->length(next_dir) + path_matrix(*path_end.region, path_end.flipped, *next_region, next_dir).length;
|
||||
path_end = { next_region, next_dir };
|
||||
assert(left_neighbors_unprocessed[next_region - regions.data()] == 1);
|
||||
left_neighbors_unprocessed[next_region - regions.data()] = 0;
|
||||
}
|
||||
|
||||
// Set an initial pheromone value to 10% of the greedy path's value.
|
||||
pheromone_initial_deposit = 0.1 / total_length;
|
||||
path_matrix.update_inital_pheromone(pheromone_initial_deposit);
|
||||
}
|
||||
|
||||
// Probability (unnormalized) of traversing a link between two monotonous regions.
|
||||
auto path_probability = [pheromone_alpha, pheromone_beta](AntPath &path) {
|
||||
return pow(path.pheromone, pheromone_alpha) * pow(path.visibility, pheromone_beta);
|
||||
|
@ -1966,8 +2150,10 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
++ irun;
|
||||
#endif /* SLIC3R_DEBUG_ANTS */
|
||||
|
||||
for (int round = 0; round < num_rounds; ++ round)
|
||||
int num_rounds_no_change = 0;
|
||||
for (int round = 0; round < num_rounds && num_rounds_no_change < num_rounds_no_change_exit; ++ round)
|
||||
{
|
||||
bool improved = false;
|
||||
for (int ant = 0; ant < num_ants; ++ ant)
|
||||
{
|
||||
// Find a new path following the pheromones deposited by the previous ants.
|
||||
|
@ -1977,6 +2163,8 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
|
||||
assert(validate_unprocessed());
|
||||
// Pick randomly the first from the queue at random orientation.
|
||||
//FIXME picking the 1st monotonous region should likely be done based on accumulated pheromone level as well,
|
||||
// but the inefficiency caused by the random pick of the 1st monotonous region is likely insignificant.
|
||||
int first_idx = std::uniform_int_distribution<>(0, int(queue.size()) - 1)(rng);
|
||||
path.emplace_back(MonotonousRegionLink{ queue[first_idx], rng() > rng.max() / 2 });
|
||||
*(queue.begin() + first_idx) = std::move(queue.back());
|
||||
|
@ -2051,7 +2239,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
for (std::vector<NextCandidate>::iterator it_next_candidate = next_candidates.begin(); it_next_candidate != next_candidates.begin() + num_direct_neighbors; ++ it_next_candidate)
|
||||
if ((queue.empty() || it_next_candidate->region != queue.back()) && it_next_candidate->region != take_path->region)
|
||||
queue.emplace_back(it_next_candidate->region);
|
||||
if (take_path - next_candidates.begin() >= num_direct_neighbors) {
|
||||
if (size_t(take_path - next_candidates.begin()) >= num_direct_neighbors) {
|
||||
// Remove the selected path from the queue.
|
||||
auto it = std::find(queue.begin(), queue.end(), take_path->region);
|
||||
assert(it != queue.end());
|
||||
|
@ -2083,8 +2271,10 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
path.back().flipped == path.back().region->flips ? path.back().region->right.high : path.back().region->right.low,
|
||||
path.back().flipped == path.back().region->flips ? path.back().region->right.low : path.back().region->right.high);
|
||||
|
||||
// Update pheromones along this link.
|
||||
take_path->link->pheromone = (1.f - pheromone_evaporation) * take_path->link->pheromone + pheromone_evaporation * pheromone_initial_deposit;
|
||||
// Update pheromones along this link, see Ant Colony System (ACS) update rule.
|
||||
// http://www.scholarpedia.org/article/Ant_colony_optimization
|
||||
// The goal here is to lower the pheromone trace for paths taken to diversify the next path picked in the same batch of ants.
|
||||
take_path->link->pheromone = (1.f - pheromone_diversification) * take_path->link->pheromone + pheromone_diversification * pheromone_initial_deposit;
|
||||
assert(validate_unprocessed());
|
||||
}
|
||||
|
||||
|
@ -2104,18 +2294,33 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
|
|||
if (path_length < best_path_length) {
|
||||
best_path_length = path_length;
|
||||
std::swap(best_path, path);
|
||||
#if 0 // #if ! defined(SLIC3R_DEBUG_ANTS) && ! defined(ndebug)
|
||||
if (round == 0 && ant == 0)
|
||||
std::cout << std::endl;
|
||||
std::cout << Slic3r::format("round %1% ant %2% path length %3%", round, ant, path_length) << std::endl;
|
||||
#endif
|
||||
if (path_length == 0)
|
||||
// Perfect path found.
|
||||
goto end;
|
||||
improved = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reinforce the path feromones with the best path.
|
||||
float total_cost = best_path_length + EPSILON;
|
||||
// Reinforce the path pheromones with the best path.
|
||||
float total_cost = best_path_length + float(EPSILON);
|
||||
for (size_t i = 0; i + 1 < path.size(); ++ i) {
|
||||
MonotonousRegionLink &link = path[i];
|
||||
link.next->pheromone = (1.f - pheromone_evaporation) * link.next->pheromone + pheromone_evaporation / total_cost;
|
||||
}
|
||||
|
||||
if (improved)
|
||||
num_rounds_no_change = 0;
|
||||
else
|
||||
++ num_rounds_no_change;
|
||||
}
|
||||
|
||||
return best_path;
|
||||
end:
|
||||
return best_path;
|
||||
}
|
||||
|
||||
// Traverse path, produce polylines.
|
||||
|
@ -2195,7 +2400,6 @@ static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path,
|
|||
int inext = it->vertical_up();
|
||||
if (inext == -1 || it->vertical_up_quality() != SegmentIntersection::LinkQuality::Valid)
|
||||
break;
|
||||
const Polygon &poly = poly_with_offset.contour(it->iContour);
|
||||
assert(it->iContour == vline.intersections[inext].iContour);
|
||||
emit_perimeter_segment_on_vertical_line(poly_with_offset, segs, i_vline, it->iContour, it - vline.intersections.data(), inext, *polyline, it->has_left_vertical_up());
|
||||
it = vline.intersections.data() + inext;
|
||||
|
@ -2215,7 +2419,6 @@ static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path,
|
|||
int inext = it->vertical_down();
|
||||
if (inext == -1 || it->vertical_down_quality() != SegmentIntersection::LinkQuality::Valid)
|
||||
break;
|
||||
const Polygon &poly = poly_with_offset.contour(it->iContour);
|
||||
assert(it->iContour == vline.intersections[inext].iContour);
|
||||
emit_perimeter_segment_on_vertical_line(poly_with_offset, segs, i_vline, it->iContour, it - vline.intersections.data(), inext, *polyline, it->has_right_vertical_down());
|
||||
it = vline.intersections.data() + inext;
|
||||
|
@ -2285,8 +2488,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||
ExPolygonWithOffset poly_with_offset(
|
||||
surface->expolygon,
|
||||
- rotate_vector.first,
|
||||
scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing),
|
||||
scale_(this->overlap - 0.5 * this->spacing));
|
||||
float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
|
||||
float(scale_(this->overlap - 0.5 * this->spacing)));
|
||||
if (poly_with_offset.n_contours_inner == 0) {
|
||||
// Not a single infill line fits.
|
||||
//FIXME maybe one shall trigger the gap fill here?
|
||||
|
@ -2317,7 +2520,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||
size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing;
|
||||
coord_t x0 = bounding_box.min(0);
|
||||
if (params.full_infill())
|
||||
x0 += (line_spacing + SCALED_EPSILON) / 2;
|
||||
x0 += (line_spacing + coord_t(SCALED_EPSILON)) / 2;
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
static int iRun = 0;
|
||||
|
@ -2359,7 +2562,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||
bool monotonous_infill = params.monotonous; // || params.density > 0.99;
|
||||
if (monotonous_infill) {
|
||||
std::vector<MonotonousRegion> regions = generate_montonous_regions(segs);
|
||||
connect_monotonous_regions(regions, segs);
|
||||
connect_monotonous_regions(regions, poly_with_offset, segs);
|
||||
if (! regions.empty()) {
|
||||
std::mt19937_64 rng;
|
||||
std::vector<MonotonousRegionLink> path = chain_monotonous_regions(regions, poly_with_offset, segs, rng);
|
||||
|
@ -2478,10 +2681,10 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶
|
|||
params3.dont_connect = true;
|
||||
Polylines polylines_out;
|
||||
coordf_t dx = sqrt(0.5) * z;
|
||||
if (! fill_surface_by_lines(surface, params2, 0.f, dx, polylines_out) ||
|
||||
! fill_surface_by_lines(surface, params2, float(M_PI / 3.), - dx, polylines_out) ||
|
||||
if (! fill_surface_by_lines(surface, params2, 0.f, float(dx), polylines_out) ||
|
||||
! fill_surface_by_lines(surface, params2, float(M_PI / 3.), - float(dx), polylines_out) ||
|
||||
// Rotated by PI*2/3 + PI to achieve reverse sloping wall.
|
||||
! fill_surface_by_lines(surface, params3, float(M_PI * 2. / 3.), dx, polylines_out)) {
|
||||
! fill_surface_by_lines(surface, params3, float(M_PI * 2. / 3.), float(dx), polylines_out)) {
|
||||
printf("FillCubic::fill_surface() failed to fill a region.\n");
|
||||
}
|
||||
return polylines_out;
|
||||
|
|
|
@ -572,6 +572,10 @@ std::string WipeTowerIntegration::finalize(GCode &gcodegen)
|
|||
return gcode;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const std::vector<std::string> ColorPrintColors::Colors = { "#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6" };
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
|
||||
|
||||
// Collect pairs of object_layer + support_layer sorted by print_z.
|
||||
|
@ -699,7 +703,7 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
|||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#else
|
||||
void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -724,7 +728,9 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
|
|||
if (file == nullptr)
|
||||
throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
m_enable_analyzer = preview_data != nullptr;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
try {
|
||||
m_placeholder_parser_failed_templates.clear();
|
||||
|
@ -778,16 +784,14 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
|
|||
m_silent_time_estimator.reset();
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
// starts analyzer calculations
|
||||
if (m_enable_analyzer) {
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
m_analyzer.close_debug_output_file();
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info();
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||
m_analyzer.reset();
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
if (rename_file(path_tmp, path))
|
||||
throw std::runtime_error(
|
||||
|
@ -877,7 +881,14 @@ namespace DoExport {
|
|||
}
|
||||
}
|
||||
|
||||
static void init_gcode_analyzer(const PrintConfig &config, GCodeAnalyzer &analyzer)
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor)
|
||||
{
|
||||
processor.reset();
|
||||
processor.apply_config(config);
|
||||
}
|
||||
#else
|
||||
static void init_gcode_analyzer(const PrintConfig &config, GCodeAnalyzer &analyzer)
|
||||
{
|
||||
// resets analyzer
|
||||
analyzer.reset();
|
||||
|
@ -901,17 +912,6 @@ namespace DoExport {
|
|||
|
||||
// tell analyzer about the gcode flavor
|
||||
analyzer.set_gcode_flavor(config.gcode_flavor);
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
analyzer.open_debug_output_file();
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor)
|
||||
{
|
||||
processor.reset();
|
||||
processor.apply_config(config);
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
|
@ -1145,15 +1145,22 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
|||
DoExport::init_time_estimators(print.config(),
|
||||
// modifies the following:
|
||||
m_normal_time_estimator, m_silent_time_estimator, m_silent_time_estimator_enabled);
|
||||
DoExport::init_gcode_analyzer(print.config(), m_analyzer);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
DoExport::init_gcode_processor(print.config(), m_processor);
|
||||
#else
|
||||
DoExport::init_gcode_analyzer(print.config(), m_analyzer);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// resets analyzer's tracking data
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_last_mm3_per_mm = 0.0f;
|
||||
m_last_width = 0.0f;
|
||||
m_last_height = 0.0f;
|
||||
#else
|
||||
m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
|
||||
m_last_width = GCodeAnalyzer::Default_Width;
|
||||
m_last_height = GCodeAnalyzer::Default_Height;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// How many times will be change_layer() called?
|
||||
// change_layer() in turn increments the progress bar status.
|
||||
|
@ -1333,13 +1340,13 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
|||
// Set extruder(s) temperature before and after start G-code.
|
||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false);
|
||||
|
||||
if (m_enable_analyzer)
|
||||
// adds tag for analyzer
|
||||
_write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// adds tag for processor
|
||||
_write_format(file, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
#else
|
||||
if (m_enable_analyzer)
|
||||
// adds tag for analyzer
|
||||
_write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// Write the custom start G-code
|
||||
|
@ -1491,13 +1498,13 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
|||
_write(file, this->retract());
|
||||
_write(file, m_writer.set_fan(false));
|
||||
|
||||
if (m_enable_analyzer)
|
||||
// adds tag for analyzer
|
||||
_write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// adds tag for processor
|
||||
_write_format(file, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
#else
|
||||
if (m_enable_analyzer)
|
||||
// adds tag for analyzer
|
||||
_write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// Process filament-specific gcode in extruder order.
|
||||
|
@ -1821,11 +1828,12 @@ namespace ProcessLayer
|
|||
{
|
||||
assert(m600_extruder_before_layer >= 0);
|
||||
// Color Change or Tool Change as Color Change.
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// add tag for processor
|
||||
gcode += "; " + GCodeProcessor::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
#else
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// add tag for time estimator
|
||||
gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n";
|
||||
|
@ -1846,11 +1854,12 @@ namespace ProcessLayer
|
|||
{
|
||||
if (custom_code == PausePrintCode) // Pause print
|
||||
{
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n";
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// add tag for processor
|
||||
gcode += "; " + GCodeProcessor::Pause_Print_Tag + "\n";
|
||||
#else
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n";
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
//! FIXME_in_fw show message during print pause
|
||||
if (!pause_print_msg.empty())
|
||||
|
@ -1860,11 +1869,12 @@ namespace ProcessLayer
|
|||
}
|
||||
else // custom Gcode
|
||||
{
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n";
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// add tag for processor
|
||||
gcode += "; " + GCodeProcessor::Custom_Code_Tag + "\n";
|
||||
#else
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n";
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// add tag for time estimator
|
||||
//gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n";
|
||||
|
@ -2218,9 +2228,15 @@ void GCode::process_layer(
|
|||
m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
|
||||
this->set_extruder(extruder_id, print_z);
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
m_last_processor_extrusion_role = erWipeTower;
|
||||
#else
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
m_last_analyzer_extrusion_role = erWipeTower;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
|
||||
const std::pair<size_t, size_t> loops = loops_it->second;
|
||||
|
@ -2324,11 +2340,13 @@ void GCode::process_layer(
|
|||
if (m_cooling_buffer)
|
||||
gcode = m_cooling_buffer->process_layer(gcode, layer.id());
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
// add tag for analyzer
|
||||
if (gcode.find(GCodeAnalyzer::Pause_Print_Tag) != gcode.npos)
|
||||
gcode += "\n; " + GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag + "\n";
|
||||
else if (gcode.find(GCodeAnalyzer::Custom_Code_Tag) != gcode.npos)
|
||||
gcode += "\n; " + GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag + "\n";
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
// Apply pressure equalization if enabled;
|
||||
|
@ -2342,9 +2360,11 @@ void GCode::process_layer(
|
|||
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
|
||||
", time estimator memory: " <<
|
||||
format_memsize_MB(m_normal_time_estimator.memory_used() + (m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0)) <<
|
||||
", analyzer memory: " <<
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
", analyzer memory: " <<
|
||||
format_memsize_MB(m_analyzer.memory_used()) <<
|
||||
log_memory_info();
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
log_memory_info();
|
||||
}
|
||||
|
||||
void GCode::apply_print_config(const PrintConfig &print_config)
|
||||
|
@ -2984,8 +3004,12 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
|||
void GCode::_write(FILE* file, const char *what)
|
||||
{
|
||||
if (what != nullptr) {
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const char* gcode = what;
|
||||
#else
|
||||
// apply analyzer, if enabled
|
||||
const char* gcode = m_enable_analyzer ? m_analyzer.process_gcode(what).c_str() : what;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
// writes string to file
|
||||
fwrite(gcode, 1, ::strlen(gcode), file);
|
||||
|
@ -3132,57 +3156,73 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
}
|
||||
|
||||
// adds analyzer tags and updates analyzer's tracking data
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
if (m_enable_analyzer)
|
||||
{
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
// PrusaMultiMaterial::Writer may generate GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines without updating m_last_height and m_last_width
|
||||
// so, if the last role was erWipeTower we force export of GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
bool last_was_wipe_tower = (m_last_processor_extrusion_role == erWipeTower);
|
||||
#else
|
||||
bool last_was_wipe_tower = (m_last_analyzer_extrusion_role == erWipeTower);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
char buf[64];
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (path.role() != m_last_processor_extrusion_role)
|
||||
{
|
||||
m_last_processor_extrusion_role = path.role();
|
||||
sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), int(m_last_processor_extrusion_role));
|
||||
gcode += buf;
|
||||
}
|
||||
#else
|
||||
if (path.role() != m_last_analyzer_extrusion_role)
|
||||
{
|
||||
m_last_analyzer_extrusion_role = path.role();
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role));
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
gcode += buf;
|
||||
sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role));
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
gcode += buf;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
if (last_was_wipe_tower || (m_last_mm3_per_mm != path.mm3_per_mm))
|
||||
{
|
||||
m_last_mm3_per_mm = path.mm3_per_mm;
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
if (last_was_wipe_tower || (m_last_width != path.width))
|
||||
{
|
||||
m_last_width = path.width;
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
if (last_was_wipe_tower || (m_last_height != path.height))
|
||||
{
|
||||
m_last_height = path.height;
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Height_Tag.c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
std::string comment;
|
||||
if (m_enable_cooling_markers) {
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
#include "GCode/WipeTower.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GCode/GCodeProcessor.hpp"
|
||||
#else
|
||||
#include "GCode/Analyzer.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#include "GCodeTimeEstimator.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "GCode/Analyzer.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
@ -33,7 +34,9 @@ namespace Slic3r {
|
|||
|
||||
// Forward declarations.
|
||||
class GCode;
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
class GCodePreviewData;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
class AvoidCrossingPerimeters {
|
||||
public:
|
||||
|
@ -138,6 +141,15 @@ private:
|
|||
double m_last_wipe_tower_print_z = 0.f;
|
||||
};
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
class ColorPrintColors
|
||||
{
|
||||
static const std::vector<std::string> Colors;
|
||||
public:
|
||||
static const std::vector<std::string>& get() { return Colors; }
|
||||
};
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
class GCode {
|
||||
public:
|
||||
GCode() :
|
||||
|
@ -145,17 +157,27 @@ public:
|
|||
m_enable_loop_clipping(true),
|
||||
m_enable_cooling_markers(false),
|
||||
m_enable_extrusion_role_markers(false),
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_last_processor_extrusion_role(erNone),
|
||||
#else
|
||||
m_enable_analyzer(false),
|
||||
m_last_analyzer_extrusion_role(erNone),
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_layer_count(0),
|
||||
m_layer_index(-1),
|
||||
m_layer(nullptr),
|
||||
m_volumetric_speed(0),
|
||||
m_last_pos_defined(false),
|
||||
m_last_extrusion_role(erNone),
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_last_mm3_per_mm(0.0f),
|
||||
m_last_width(0.0f),
|
||||
m_last_height(0.0f),
|
||||
#else
|
||||
m_last_mm3_per_mm(GCodeAnalyzer::Default_mm3_per_mm),
|
||||
m_last_width(GCodeAnalyzer::Default_Width),
|
||||
m_last_height(GCodeAnalyzer::Default_Height),
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_brim_done(false),
|
||||
m_second_layer_things_done(false),
|
||||
m_normal_time_estimator(GCodeTimeEstimator::Normal),
|
||||
|
@ -168,7 +190,7 @@ public:
|
|||
// throws std::runtime_exception on error,
|
||||
// throws CanceledException through print->throw_if_canceled().
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, GCodeProcessor::Result* result = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
void do_export(Print* print, const char* path, GCodeProcessor::Result* result = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#else
|
||||
void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -331,11 +353,16 @@ private:
|
|||
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
||||
// The Pressure Equalizer removes the markers from the final G-code.
|
||||
bool m_enable_extrusion_role_markers;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// Keeps track of the last extrusion role passed to the processor
|
||||
ExtrusionRole m_last_processor_extrusion_role;
|
||||
#else
|
||||
// Enableds the G-code Analyzer.
|
||||
// Extended markers will be added during G-code generation.
|
||||
// The G-code Analyzer will remove these comments from the final G-code.
|
||||
bool m_enable_analyzer;
|
||||
ExtrusionRole m_last_analyzer_extrusion_role;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// How many times will change_layer() be called?
|
||||
// change_layer() will update the progress bar.
|
||||
unsigned int m_layer_count;
|
||||
|
@ -377,12 +404,12 @@ private:
|
|||
GCodeTimeEstimator m_silent_time_estimator;
|
||||
bool m_silent_time_estimator_enabled;
|
||||
|
||||
// Analyzer
|
||||
GCodeAnalyzer m_analyzer;
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// Processor
|
||||
GCodeProcessor m_processor;
|
||||
#else
|
||||
// Analyzer
|
||||
GCodeAnalyzer m_analyzer;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// Write a string into a file.
|
||||
|
|
|
@ -8,19 +8,11 @@
|
|||
#include "Print.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
|
||||
#include "Analyzer.hpp"
|
||||
#include "PreviewData.hpp"
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
// don't worry, this is just temporary
|
||||
static boost::nowide::ofstream g_debug_output;
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
|
||||
static const std::string AXIS_STR = "XYZE";
|
||||
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
|
||||
|
@ -184,19 +176,6 @@ bool GCodeAnalyzer::is_valid_extrusion_role(ExtrusionRole role)
|
|||
return ((erPerimeter <= role) && (role < erMixed));
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
void GCodeAnalyzer::open_debug_output_file()
|
||||
{
|
||||
boost::filesystem::path path("d:/analyzer.output");
|
||||
g_debug_output.open(path.string());
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::close_debug_output_file()
|
||||
{
|
||||
g_debug_output.close();
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
|
||||
void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
// processes 'special' comments contained in line
|
||||
|
@ -945,23 +924,6 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
|||
Vec3f start_position = _get_start_position() + extruder_offset;
|
||||
Vec3f end_position = _get_end_position() + extruder_offset;
|
||||
it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_cp_color_id());
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
if (g_debug_output.good())
|
||||
{
|
||||
g_debug_output << std::to_string(static_cast<int>(type));
|
||||
g_debug_output << ", " << std::to_string(static_cast<int>(_get_extrusion_role()));
|
||||
g_debug_output << ", " << Slic3r::to_string(static_cast<Vec3d>(end_position.cast<double>()));
|
||||
g_debug_output << ", " << std::to_string(extruder_id);
|
||||
g_debug_output << ", " << std::to_string(_get_cp_color_id());
|
||||
g_debug_output << ", " << std::to_string(_get_feedrate());
|
||||
g_debug_output << ", " << std::to_string(_get_width());
|
||||
g_debug_output << ", " << std::to_string(_get_height());
|
||||
g_debug_output << ", " << std::to_string(_get_mm3_per_mm());
|
||||
g_debug_output << ", " << std::to_string(_get_fan_speed());
|
||||
g_debug_output << "\n";
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
}
|
||||
|
||||
bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
|
||||
|
@ -1231,3 +1193,5 @@ size_t GCodeAnalyzer::memory_used() const
|
|||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef slic3r_GCode_Analyzer_hpp_
|
||||
#define slic3r_GCode_Analyzer_hpp_
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "../libslic3r.h"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "../ExtrusionEntity.hpp"
|
||||
|
@ -147,11 +149,6 @@ public:
|
|||
|
||||
static bool is_valid_extrusion_role(ExtrusionRole role);
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
void open_debug_output_file();
|
||||
void close_debug_output_file();
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
|
||||
private:
|
||||
// Processes the given gcode line
|
||||
void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
|
||||
|
@ -307,4 +304,6 @@ private:
|
|||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#endif /* slic3r_GCode_Analyzer_hpp_ */
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
#define L(s) (s)
|
||||
|
||||
|
@ -117,7 +119,8 @@ const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount]
|
|||
Color(1.0f, 1.0f, 0.0f, 1.0f), // erInternalInfill
|
||||
Color(1.0f, 0.0f, 1.0f, 1.0f), // erSolidInfill
|
||||
Color(0.0f, 1.0f, 1.0f, 1.0f), // erTopSolidInfill
|
||||
Color(0.0f, 1.0f, 1.0f, 1.0f), // erIroning
|
||||
// Color(1.0f, 0.7f, 0.61f, 1.0f), // erIroning
|
||||
Color(1.0f, 0.55f, 0.41f, 1.0f), // erIroning
|
||||
Color(0.5f, 0.5f, 0.5f, 1.0f), // erBridgeInfill
|
||||
Color(1.0f, 1.0f, 1.0f, 1.0f), // erGapFill
|
||||
Color(0.5f, 0.0f, 0.0f, 1.0f), // erSkirt
|
||||
|
@ -515,3 +518,5 @@ Color operator * (float f, const Color& color)
|
|||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef slic3r_GCode_PreviewData_hpp_
|
||||
#define slic3r_GCode_PreviewData_hpp_
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "../libslic3r.h"
|
||||
#include "../ExtrusionEntity.hpp"
|
||||
#include "../Point.hpp"
|
||||
|
@ -391,4 +393,6 @@ public:
|
|||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#endif /* slic3r_GCode_PreviewData_hpp_ */
|
||||
|
|
|
@ -21,9 +21,10 @@ TODO LIST
|
|||
#include <vector>
|
||||
#include <numeric>
|
||||
|
||||
#include "Analyzer.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GCodeProcessor.hpp"
|
||||
#else
|
||||
#include "Analyzer.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#include "BoundingBox.hpp"
|
||||
|
||||
|
@ -56,16 +57,16 @@ public:
|
|||
{
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
|
||||
m_gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
|
||||
m_gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||
#else
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_gcode += buf;
|
||||
change_analyzer_line_width(line_width);
|
||||
|
@ -74,12 +75,12 @@ public:
|
|||
WipeTowerWriter& change_analyzer_line_width(float line_width) {
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), line_width);
|
||||
m_gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), line_width);
|
||||
m_gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), line_width);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_gcode += buf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -88,12 +89,12 @@ public:
|
|||
float mm3_per_mm = (len == 0.f ? 0.f : area * e / len);
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
|
||||
m_gcode += buf;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
|
||||
m_gcode += buf;
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_gcode += buf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "SVG.hpp"
|
||||
#include <Eigen/Dense>
|
||||
#include "GCodeWriter.hpp"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
|
@ -411,6 +411,11 @@ public:
|
|||
return timestamp == other.get_timestamp();
|
||||
}
|
||||
|
||||
template<class Archive> void serialize(Archive &ar)
|
||||
{
|
||||
ar(m_data);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int, FacetSupportType> m_data;
|
||||
|
||||
|
@ -613,7 +618,8 @@ private:
|
|||
}
|
||||
template<class Archive> void load(Archive &ar) {
|
||||
bool has_convex_hull;
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation,
|
||||
m_is_splittable, has_convex_hull, m_supported_facets);
|
||||
cereal::load_by_value(ar, config);
|
||||
assert(m_mesh);
|
||||
if (has_convex_hull) {
|
||||
|
@ -626,7 +632,8 @@ private:
|
|||
}
|
||||
template<class Archive> void save(Archive &ar) const {
|
||||
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation,
|
||||
m_is_splittable, has_convex_hull, m_supported_facets);
|
||||
cereal::save_by_value(ar, config);
|
||||
if (has_convex_hull)
|
||||
cereal::save_optional(ar, m_convex_hull);
|
||||
|
|
|
@ -1628,7 +1628,7 @@ void Print::process()
|
|||
// write error into the G-code, cannot execute post-processing scripts).
|
||||
// It is up to the caller to show an error message.
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
std::string Print::export_gcode(const std::string& path_template, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#else
|
||||
std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -1637,7 +1637,11 @@ std::string Print::export_gcode(const std::string& path_template, GCodePreviewDa
|
|||
// The following call may die if the output_filename_format template substitution fails.
|
||||
std::string path = this->output_filepath(path_template);
|
||||
std::string message;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (!path.empty() && result == nullptr) {
|
||||
#else
|
||||
if (! path.empty() && preview_data == nullptr) {
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// Only show the path if preview_data is not set -> running from command line.
|
||||
message = L("Exporting G-code");
|
||||
message += " to ";
|
||||
|
@ -1649,7 +1653,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodePreviewDa
|
|||
// The following line may die for multiple reasons.
|
||||
GCode gcode;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
gcode.do_export(this, path.c_str(), preview_data, result, thumbnail_cb);
|
||||
gcode.do_export(this, path.c_str(), result, thumbnail_cb);
|
||||
#else
|
||||
gcode.do_export(this, path.c_str(), preview_data, thumbnail_cb);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
|
|
@ -372,7 +372,7 @@ public:
|
|||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
std::string export_gcode(const std::string& path_template, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#else
|
||||
std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
|
|
@ -1292,7 +1292,7 @@ void SupportTreeBuildsteps::routing_headless()
|
|||
m_thr();
|
||||
|
||||
const auto R = double(m_support_pts[i].head_front_radius);
|
||||
const double HWIDTH_MM = m_cfg.head_penetration_mm;
|
||||
const double HWIDTH_MM = std::min(R, m_cfg.head_penetration_mm);
|
||||
|
||||
// Exact support position
|
||||
Vec3d sph = m_support_pts[i].pos.cast<double>();
|
||||
|
|
|
@ -53,13 +53,8 @@
|
|||
// Enable rendering of objects colored by facets' slope
|
||||
#define ENABLE_SLOPE_RENDERING (1 && ENABLE_2_3_0_ALPHA1)
|
||||
|
||||
// Moves GLCanvas3DManager from being a static member of _3DScene to be a normal member of GUI_App
|
||||
#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_3_0_ALPHA1)
|
||||
|
||||
// Enable G-Code viewer
|
||||
#define ENABLE_GCODE_VIEWER (1 && ENABLE_2_3_0_ALPHA1)
|
||||
#define ENABLE_GCODE_VIEWER_DEBUG_OUTPUT (0 && ENABLE_GCODE_VIEWER)
|
||||
#define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
|
|
@ -27,8 +27,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/GLShader.hpp
|
||||
GUI/GLCanvas3D.hpp
|
||||
GUI/GLCanvas3D.cpp
|
||||
GUI/GLCanvas3DManager.hpp
|
||||
GUI/GLCanvas3DManager.cpp
|
||||
GUI/OpenGLManager.hpp
|
||||
GUI/OpenGLManager.cpp
|
||||
GUI/Selection.hpp
|
||||
GUI/Selection.cpp
|
||||
GUI/Gizmos/GLGizmosManager.cpp
|
||||
|
@ -55,6 +55,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/Gizmos/GLGizmoHollow.hpp
|
||||
GUI/GLSelectionRectangle.cpp
|
||||
GUI/GLSelectionRectangle.hpp
|
||||
GUI/GLModel.hpp
|
||||
GUI/GLModel.cpp
|
||||
GUI/GLTexture.hpp
|
||||
GUI/GLTexture.cpp
|
||||
GUI/GLToolbar.hpp
|
||||
|
@ -218,6 +220,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||
target_link_libraries(libslic3r_gui ${DBUS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (SLIC3R_STATIC)
|
||||
# FIXME: This was previously exported by wx-config but the wxWidgets
|
||||
# cmake build forgets this and the build fails in debug mode (or on raspberry release)
|
||||
target_compile_definitions(libslic3r_gui PUBLIC -DwxDEBUG_LEVEL=0)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY})
|
||||
endif()
|
||||
|
|
|
@ -5,15 +5,24 @@
|
|||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "3DScene.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include <boost/log/trivial.hpp>
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
static const float GROUND_Z = -0.02f;
|
||||
|
||||
|
@ -119,13 +128,25 @@ const float* GeometryBuffer::get_vertices_data() const
|
|||
return (m_vertices.size() > 0) ? (const float*)m_vertices.data() : nullptr;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
|
||||
const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
||||
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
|
||||
const float Bed3D::Axes::DefaultTipLength = 5.0f;
|
||||
#else
|
||||
const double Bed3D::Axes::Radius = 0.5;
|
||||
const double Bed3D::Axes::ArrowBaseRadius = 2.5 * Bed3D::Axes::Radius;
|
||||
const double Bed3D::Axes::ArrowLength = 5.0;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void Bed3D::Axes::set_stem_length(float length)
|
||||
{
|
||||
m_stem_length = length;
|
||||
m_arrow.reset();
|
||||
}
|
||||
#else
|
||||
Bed3D::Axes::Axes()
|
||||
: origin(Vec3d::Zero())
|
||||
, length(25.0 * Vec3d::Ones())
|
||||
{
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
|
@ -137,9 +158,46 @@ Bed3D::Axes::~Axes()
|
|||
if (m_quadric != nullptr)
|
||||
::gluDeleteQuadric(m_quadric);
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
void Bed3D::Axes::render() const
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
auto render_axis = [this](const Transform3f& transform, GLint color_id, const std::array<float, 4>& color) {
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color.data()));
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixf(transform.data()));
|
||||
m_arrow.render();
|
||||
glsafe(::glPopMatrix());
|
||||
};
|
||||
|
||||
m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
|
||||
if (!m_shader.init("gouraud_light.vs", "gouraud_light.fs"))
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to initialize gouraud_light shader: please, check that the files gouraud_light.vs and gouraud_light.fs are available";
|
||||
|
||||
if (!m_shader.is_initialized())
|
||||
return;
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
m_shader.start_using();
|
||||
GLint color_id = ::glGetUniformLocation(m_shader.get_shader_program_id(), "uniform_color");
|
||||
|
||||
// x axis
|
||||
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0f }).cast<float>(), color_id, { 0.75f, 0.0f, 0.0f, 1.0f });
|
||||
|
||||
// y axis
|
||||
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0f }).cast<float>(), color_id, { 0.0f, 0.75f, 0.0f, 1.0f });
|
||||
|
||||
// z axis
|
||||
render_axis(Geometry::assemble_transform(m_origin).cast<float>(), color_id, { 0.0f, 0.0f, 0.75f, 1.0f });
|
||||
|
||||
m_shader.stop_using();
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
#else
|
||||
if (m_quadric == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -171,8 +229,10 @@ void Bed3D::Axes::render() const
|
|||
|
||||
glsafe(::glDisable(GL_LIGHTING));
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void Bed3D::Axes::render_axis(double length) const
|
||||
{
|
||||
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
|
||||
|
@ -185,6 +245,7 @@ void Bed3D::Axes::render_axis(double length) const
|
|||
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
|
||||
::gluDisk(m_quadric, 0.0, ArrowBaseRadius, 32, 1);
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
Bed3D::Bed3D()
|
||||
: m_type(Custom)
|
||||
|
@ -242,8 +303,13 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c
|
|||
m_model.reset();
|
||||
|
||||
// Set the origin and size for rendering the coordinate system axes.
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_axes.set_origin({ 0.0, 0.0, static_cast<double>(GROUND_Z) });
|
||||
m_axes.set_stem_length(0.1f * static_cast<float>(m_bounding_box.max_size()));
|
||||
#else
|
||||
m_axes.origin = Vec3d(0.0, 0.0, (double)GROUND_Z);
|
||||
m_axes.length = 0.1 * m_bounding_box.max_size() * Vec3d::Ones();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// Let the calee to update the UI.
|
||||
return true;
|
||||
|
@ -290,7 +356,11 @@ void Bed3D::calc_bounding_boxes() const
|
|||
m_extended_bounding_box = m_bounding_box;
|
||||
|
||||
// extend to contain axes
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_extended_bounding_box.merge(m_axes.get_total_length() * Vec3d::Ones());
|
||||
#else
|
||||
m_extended_bounding_box.merge(m_axes.length + Axes::ArrowLength * Vec3d::Ones());
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// extend to contain model, if any
|
||||
if (!m_model.get_filename().empty())
|
||||
|
@ -410,7 +480,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const
|
|||
if (boost::algorithm::iends_with(m_texture_filename, ".svg"))
|
||||
{
|
||||
// use higher resolution images if graphic card and opengl version allow
|
||||
GLint max_tex_size = GLCanvas3DManager::get_gl_info().get_max_tex_size();
|
||||
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
|
||||
if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != m_texture_filename))
|
||||
{
|
||||
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
|
||||
|
|
|
@ -4,11 +4,16 @@
|
|||
#include "GLTexture.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "GLShader.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GLModel.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
class GLUquadric;
|
||||
typedef class GLUquadric GLUquadricObj;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -45,22 +50,50 @@ public:
|
|||
|
||||
class Bed3D
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
class Axes
|
||||
{
|
||||
static const float DefaultStemRadius;
|
||||
static const float DefaultStemLength;
|
||||
static const float DefaultTipRadius;
|
||||
static const float DefaultTipLength;
|
||||
#else
|
||||
struct Axes
|
||||
{
|
||||
static const double Radius;
|
||||
static const double ArrowBaseRadius;
|
||||
static const double ArrowLength;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Vec3d m_origin{ Vec3d::Zero() };
|
||||
float m_stem_length{ DefaultStemLength };
|
||||
mutable GL_Model m_arrow;
|
||||
mutable Shader m_shader;
|
||||
|
||||
public:
|
||||
#else
|
||||
Vec3d origin;
|
||||
Vec3d length;
|
||||
GLUquadricObj* m_quadric;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
Axes();
|
||||
~Axes();
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void set_origin(const Vec3d& origin) { m_origin = origin; }
|
||||
void set_stem_length(float length);
|
||||
float get_total_length() const { return m_stem_length + DefaultTipLength; }
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
void render() const;
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
private:
|
||||
void render_axis(double length) const;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -5,11 +5,15 @@
|
|||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/Analyzer.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "slic3r/GUI/BitmapCache.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
@ -1853,10 +1857,6 @@ void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height
|
|||
thick_point_to_verts(point, width, height, volume);
|
||||
}
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GUI::GLCanvas3DManager _3DScene::s_canvas_mgr;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
GLModel::GLModel()
|
||||
: m_filename("")
|
||||
{
|
||||
|
@ -1944,6 +1944,7 @@ void GLModel::render() const
|
|||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
bool GLArrow::on_init()
|
||||
{
|
||||
Pointf3s vertices;
|
||||
|
@ -2115,6 +2116,7 @@ bool GLCurvedArrow::on_init()
|
|||
m_volume.indexed_vertex_array.finalize_geometry(true);
|
||||
return true;
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
bool GLBed::on_init_from_file(const std::string& filename)
|
||||
{
|
||||
|
@ -2147,41 +2149,4 @@ bool GLBed::on_init_from_file(const std::string& filename)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
std::string _3DScene::get_gl_info(bool format_as_html, bool extensions)
|
||||
{
|
||||
return Slic3r::GUI::GLCanvas3DManager::get_gl_info().to_string(format_as_html, extensions);
|
||||
}
|
||||
|
||||
bool _3DScene::add_canvas(wxGLCanvas* canvas, GUI::Bed3D& bed, GUI::Camera& camera, GUI::GLToolbar& view_toolbar)
|
||||
{
|
||||
return s_canvas_mgr.add(canvas, bed, camera, view_toolbar);
|
||||
}
|
||||
|
||||
bool _3DScene::remove_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
return s_canvas_mgr.remove(canvas);
|
||||
}
|
||||
|
||||
void _3DScene::remove_all_canvases()
|
||||
{
|
||||
s_canvas_mgr.remove_all();
|
||||
}
|
||||
|
||||
bool _3DScene::init(wxGLCanvas* canvas)
|
||||
{
|
||||
return s_canvas_mgr.init(canvas);
|
||||
}
|
||||
|
||||
void _3DScene::destroy()
|
||||
{
|
||||
s_canvas_mgr.destroy();
|
||||
}
|
||||
|
||||
GUI::GLCanvas3D* _3DScene::get_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
return s_canvas_mgr.get_canvas(canvas);
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "slic3r/GUI/GLCanvas3DManager.hpp"
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
@ -645,6 +642,7 @@ protected:
|
|||
virtual bool on_init_from_file(const std::string& filename) { return false; }
|
||||
};
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
class GLArrow : public GLModel
|
||||
{
|
||||
protected:
|
||||
|
@ -661,6 +659,7 @@ public:
|
|||
protected:
|
||||
bool on_init() override;
|
||||
};
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
class GLBed : public GLModel
|
||||
{
|
||||
|
@ -668,30 +667,8 @@ protected:
|
|||
bool on_init_from_file(const std::string& filename) override;
|
||||
};
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
struct _3DScene
|
||||
#else
|
||||
class _3DScene
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
{
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static GUI::GLCanvas3DManager s_canvas_mgr;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
public:
|
||||
static std::string get_gl_info(bool format_as_html, bool extensions);
|
||||
|
||||
static bool add_canvas(wxGLCanvas* canvas, GUI::Bed3D& bed, GUI::Camera& camera, GUI::GLToolbar& view_toolbar);
|
||||
static bool remove_canvas(wxGLCanvas* canvas);
|
||||
static void remove_all_canvases();
|
||||
|
||||
static bool init(wxGLCanvas* canvas);
|
||||
static void destroy();
|
||||
|
||||
static GUI::GLCanvas3D* get_canvas(wxGLCanvas* canvas);
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
||||
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
||||
static void extrusionentity_to_verts(const Polyline &polyline, float width, float height, float print_z, GLVolume& volume);
|
||||
|
|
|
@ -84,6 +84,9 @@ void AppConfig::set_defaults()
|
|||
if (get("custom_toolbar_size").empty())
|
||||
set("custom_toolbar_size", "100");
|
||||
|
||||
if (get("auto_toolbar_size").empty())
|
||||
set("auto_toolbar_size", "100");
|
||||
|
||||
if (get("use_perspective_camera").empty())
|
||||
set("use_perspective_camera", "1");
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/GCode/PostProcessor.hpp"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
|
@ -89,7 +91,7 @@ void BackgroundSlicingProcess::process_fff()
|
|||
m_print->process();
|
||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id));
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_gcode_result, m_thumbnail_cb);
|
||||
m_fff_print->export_gcode(m_temp_output_path, m_gcode_result, m_thumbnail_cb);
|
||||
#else
|
||||
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_cb);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -385,9 +387,7 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn
|
|||
// Some FFF status was invalidated, and the G-code was not exported yet.
|
||||
// Let the G-code preview UI know that the final G-code preview is not valid.
|
||||
// In addition, this early memory deallocation reduces memory footprint.
|
||||
if (m_gcode_preview_data != nullptr)
|
||||
m_gcode_preview_data->reset();
|
||||
else if (m_gcode_result != nullptr)
|
||||
if (m_gcode_result != nullptr)
|
||||
m_gcode_result->reset();
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -50,10 +50,11 @@ public:
|
|||
|
||||
void set_fff_print(Print *print) { m_fff_print = print; }
|
||||
void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); }
|
||||
void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
|
||||
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
|
||||
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void set_gcode_result(GCodeProcessor::Result* result) { m_gcode_result = result; }
|
||||
#else
|
||||
void set_gcode_preview_data(GCodePreviewData* gpd) { m_gcode_preview_data = gpd; }
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// The following wxCommandEvent will be sent to the UI thread / Plater window, when the slicing is finished
|
||||
|
@ -156,15 +157,17 @@ private:
|
|||
// Non-owned pointers to Print instances.
|
||||
Print *m_fff_print = nullptr;
|
||||
SLAPrint *m_sla_print = nullptr;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
// Data structure, to which the G-code export writes its annotations.
|
||||
GCodeProcessor::Result *m_gcode_result = nullptr;
|
||||
#else
|
||||
// Data structure, to which the G-code export writes its annotations.
|
||||
GCodePreviewData *m_gcode_preview_data = nullptr;
|
||||
// Callback function, used to write thumbnails into gcode.
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// Callback function, used to write thumbnails into gcode.
|
||||
ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr;
|
||||
SL1Archive m_sla_archive;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GCodeProcessor::Result* m_gcode_result = nullptr;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
|
||||
// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
|
||||
std::string m_temp_output_path;
|
||||
// Output path provided by the user. The output path may be set even if the slicing is running,
|
||||
// but once set, it cannot be re-set.
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "DoubleSlider.hpp"
|
||||
#include "libslic3r/GCode.hpp"
|
||||
#else
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
@ -1945,7 +1951,11 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, const std::string& c
|
|||
{
|
||||
if (mode == t_mode::SingleExtruder && code == ColorChangeCode && m_use_default_colors)
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const std::vector<std::string>& colors = ColorPrintColors::get();
|
||||
#else
|
||||
const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
if (ticks.empty())
|
||||
return colors[0];
|
||||
m_default_color_idx++;
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include "libslic3r/CustomGCode.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include <wx/wx.h>
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include <wx/window.h>
|
||||
#include <wx/control.h>
|
||||
#include <wx/dc.h>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <regex>
|
||||
#include <wx/numformatter.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#ifdef __WXOSX__
|
||||
|
@ -79,6 +80,29 @@ void Field::PostInitialize()
|
|||
m_em_unit = em_unit(m_parent);
|
||||
|
||||
BUILD();
|
||||
|
||||
// For the mode, when settings are in non-modal dialog, neither dialog nor tabpanel doesn't receive wxEVT_KEY_UP event, when some field is selected.
|
||||
// So, like a workaround check wxEVT_KEY_UP event for the Filed and switch between tabs if Ctrl+(1-4) was pressed
|
||||
if (getWindow())
|
||||
getWindow()->Bind(wxEVT_KEY_UP, [](wxKeyEvent& evt) {
|
||||
if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) {
|
||||
int tab_id = -1;
|
||||
switch (evt.GetKeyCode()) {
|
||||
case '1': { tab_id = 0; break; }
|
||||
case '2': { tab_id = 1; break; }
|
||||
case '3': { tab_id = 2; break; }
|
||||
case '4': { tab_id = 3; break; }
|
||||
default: break;
|
||||
}
|
||||
if (tab_id >= 0)
|
||||
wxGetApp().mainframe->select_tab(tab_id);
|
||||
if (tab_id > 0)
|
||||
// tab panel should be focused for correct navigation between tabs
|
||||
wxGetApp().tab_panel()->SetFocus();
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
});
|
||||
}
|
||||
|
||||
// Values of width to alignments of fields
|
||||
|
@ -397,7 +421,7 @@ void TextCtrl::BUILD() {
|
|||
bKilledFocus = false;
|
||||
#endif // __WXOSX__
|
||||
}), temp->GetId());
|
||||
|
||||
/*
|
||||
// select all text using Ctrl+A
|
||||
temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event)
|
||||
{
|
||||
|
@ -405,7 +429,7 @@ void TextCtrl::BUILD() {
|
|||
temp->SetSelection(-1, -1); //select all
|
||||
event.Skip();
|
||||
}));
|
||||
|
||||
*/
|
||||
// recast as a wxWindow to fit the calling convention
|
||||
window = dynamic_cast<wxWindow*>(temp);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "Camera.hpp"
|
||||
|
@ -100,8 +101,7 @@ void GCodeViewer::IBuffer::reset()
|
|||
}
|
||||
|
||||
// release cpu memory
|
||||
data = std::vector<unsigned int>();
|
||||
data_size = 0;
|
||||
indices_count = 0;
|
||||
paths = std::vector<Path>();
|
||||
render_paths = std::vector<RenderPath>();
|
||||
}
|
||||
|
@ -116,9 +116,9 @@ bool GCodeViewer::IBuffer::init_shader(const std::string& vertex_shader_src, con
|
|||
return true;
|
||||
}
|
||||
|
||||
void GCodeViewer::IBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int v_id)
|
||||
void GCodeViewer::IBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int i_id, unsigned int s_id)
|
||||
{
|
||||
Path::Endpoint endpoint = { static_cast<unsigned int>(data.size()), v_id, move.position };
|
||||
Path::Endpoint endpoint = { i_id, s_id, move.position };
|
||||
paths.push_back({ move.type, move.extrusion_role, endpoint, endpoint, move.delta_extruder, move.height, move.width, move.feedrate, move.fan_speed, move.volumetric_rate(), move.extruder_id, move.cp_color_id });
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,44 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con
|
|||
return ret;
|
||||
}
|
||||
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
|
||||
void GCodeViewer::SequentialView::Marker::init()
|
||||
{
|
||||
m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f));
|
||||
init_shader();
|
||||
}
|
||||
|
||||
void GCodeViewer::SequentialView::Marker::render() const
|
||||
{
|
||||
if (!m_visible || !m_shader.is_initialized())
|
||||
return;
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
m_shader.start_using();
|
||||
GLint color_id = ::glGetUniformLocation(m_shader.get_shader_program_id(), "uniform_color");
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)m_color.data()));
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixf(m_world_transform.data()));
|
||||
|
||||
m_model.render();
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
m_shader.stop_using();
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
void GCodeViewer::SequentialView::Marker::init_shader()
|
||||
{
|
||||
if (!m_shader.init("gouraud_light.vs", "gouraud_light.fs"))
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to initialize gouraud_light shader: please, check that the files gouraud_light.vs and gouraud_light.fs are available";
|
||||
}
|
||||
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors {{
|
||||
{ 0.50f, 0.50f, 0.50f }, // erNone
|
||||
{ 1.00f, 1.00f, 0.40f }, // erPerimeter
|
||||
{ 1.00f, 0.65f, 0.00f }, // erExternalPerimeter
|
||||
|
@ -153,7 +190,7 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
|
|||
{ 0.69f, 0.19f, 0.16f }, // erInternalInfill
|
||||
{ 0.84f, 0.20f, 0.84f }, // erSolidInfill
|
||||
{ 1.00f, 0.10f, 0.10f }, // erTopSolidInfill
|
||||
{ 0.00f, 1.00f, 1.00f }, // erIroning
|
||||
{ 1.00f, 0.55f, 0.41f }, // erIroning
|
||||
{ 0.60f, 0.60f, 1.00f }, // erBridgeInfill
|
||||
{ 1.00f, 1.00f, 1.00f }, // erGapFill
|
||||
{ 0.52f, 0.48f, 0.13f }, // erSkirt
|
||||
|
@ -164,13 +201,13 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
|
|||
{ 0.00f, 0.00f, 0.00f } // erMixed
|
||||
}};
|
||||
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors{ {
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors {{
|
||||
{ 0.0f, 0.0f, 0.5f }, // Move
|
||||
{ 0.0f, 0.5f, 0.0f }, // Extrude
|
||||
{ 0.5f, 0.0f, 0.0f } // Retract
|
||||
}};
|
||||
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors{ {
|
||||
const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors {{
|
||||
{ 0.043f, 0.173f, 0.478f }, // bluish
|
||||
{ 0.075f, 0.349f, 0.522f },
|
||||
{ 0.110f, 0.533f, 0.569f },
|
||||
|
@ -278,11 +315,16 @@ void GCodeViewer::render() const
|
|||
m_statistics.reset_opengl();
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
||||
if (m_roles.empty())
|
||||
return;
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
render_toolpaths();
|
||||
m_sequential_view.marker.set_world_transform(Geometry::assemble_transform(m_sequential_view.current_position.cast<double>() + (0.5 + 12.0) * Vec3d::UnitZ(), { M_PI, 0.0, 0.0 }).cast<float>());
|
||||
m_sequential_view.marker.render();
|
||||
render_shells();
|
||||
render_legend();
|
||||
render_sequential_dlg();
|
||||
render_sequential_bar();
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
render_statistics();
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
@ -316,7 +358,8 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
|
|||
flags = set_flag(flags, 5, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print));
|
||||
flags = set_flag(flags, 6, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode));
|
||||
flags = set_flag(flags, 7, m_shells.visible);
|
||||
flags = set_flag(flags, 8, is_legend_enabled());
|
||||
flags = set_flag(flags, 8, m_sequential_view.marker.is_visible());
|
||||
flags = set_flag(flags, 9, is_legend_enabled());
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
@ -334,7 +377,8 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
|
|||
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print, is_flag_set(5));
|
||||
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode, is_flag_set(6));
|
||||
m_shells.visible = is_flag_set(7);
|
||||
enable_legend(is_flag_set(8));
|
||||
m_sequential_view.marker.set_visible(is_flag_set(8));
|
||||
enable_legend(is_flag_set(9));
|
||||
}
|
||||
|
||||
bool GCodeViewer::init_shaders()
|
||||
|
@ -388,10 +432,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
std::vector<float> vertices_data(m_vertices.vertices_count * 3);
|
||||
for (size_t i = 0; i < m_vertices.vertices_count; ++i) {
|
||||
const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
|
||||
m_bounding_box.merge(move.position.cast<double>());
|
||||
if (move.type == GCodeProcessor::EMoveType::Extrude)
|
||||
m_bounding_box.merge(move.position.cast<double>());
|
||||
::memcpy(static_cast<void*>(&vertices_data[i * 3]), static_cast<const void*>(move.position.data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
m_bounding_box.merge(m_bounding_box.max + m_sequential_view.marker.get_bounding_box().max[2] * Vec3d::UnitZ());
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
m_statistics.vertices_size = SLIC3R_STDVEC_MEMSIZE(vertices_data, float);
|
||||
m_statistics.vertices_gpu_size = vertices_data.size() * sizeof(float);
|
||||
|
@ -403,10 +450,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices_data.size() * sizeof(float), vertices_data.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// vertex data -> free ram
|
||||
// vertex data -> no more needed, free ram
|
||||
vertices_data = std::vector<float>();
|
||||
|
||||
// indices data -> extract from result
|
||||
std::vector<std::vector<unsigned int>> indices(m_buffers.size());
|
||||
for (size_t i = 0; i < m_vertices.vertices_count; ++i)
|
||||
{
|
||||
// skip first vertex
|
||||
|
@ -416,7 +464,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
const GCodeProcessor::MoveVertex& prev = gcode_result.moves[i - 1];
|
||||
const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i];
|
||||
|
||||
IBuffer& buffer = m_buffers[buffer_id(curr.type)];
|
||||
unsigned char id = buffer_id(curr.type);
|
||||
IBuffer& buffer = m_buffers[id];
|
||||
std::vector<unsigned int>& buffer_indices = indices[id];
|
||||
|
||||
switch (curr.type)
|
||||
{
|
||||
|
@ -427,23 +477,23 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
case GCodeProcessor::EMoveType::Retract:
|
||||
case GCodeProcessor::EMoveType::Unretract:
|
||||
{
|
||||
buffer.add_path(curr, static_cast<unsigned int>(i));
|
||||
buffer.data.push_back(static_cast<unsigned int>(i));
|
||||
buffer.add_path(curr, static_cast<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(i));
|
||||
buffer_indices.push_back(static_cast<unsigned int>(i));
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Extrude:
|
||||
case GCodeProcessor::EMoveType::Travel:
|
||||
{
|
||||
if (prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
||||
buffer.add_path(curr, static_cast<unsigned int>(i));
|
||||
buffer.add_path(curr, static_cast<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(i));
|
||||
Path& last_path = buffer.paths.back();
|
||||
last_path.first.position = prev.position;
|
||||
last_path.first.s_id = static_cast<unsigned int>(i - 1);
|
||||
buffer.data.push_back(static_cast<unsigned int>(i - 1));
|
||||
buffer_indices.push_back(static_cast<unsigned int>(i - 1));
|
||||
}
|
||||
|
||||
buffer.paths.back().last = { static_cast<unsigned int>(buffer.data.size()), static_cast<unsigned int>(i), curr.position };
|
||||
buffer.data.push_back(static_cast<unsigned int>(i));
|
||||
buffer.paths.back().last = { static_cast<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(i), curr.position };
|
||||
buffer_indices.push_back(static_cast<unsigned int>(i));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -461,22 +511,21 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
||||
// indices data -> send data to gpu
|
||||
for (IBuffer& buffer : m_buffers)
|
||||
for (size_t i = 0; i < m_buffers.size(); ++i)
|
||||
{
|
||||
buffer.data_size = buffer.data.size();
|
||||
IBuffer& buffer = m_buffers[i];
|
||||
std::vector<unsigned int>& buffer_indices = indices[i];
|
||||
buffer.indices_count = buffer_indices.size();
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
m_statistics.indices_size += SLIC3R_STDVEC_MEMSIZE(buffer.data, unsigned int);
|
||||
m_statistics.indices_gpu_size += buffer.data_size * sizeof(unsigned int);
|
||||
m_statistics.indices_size += SLIC3R_STDVEC_MEMSIZE(buffer_indices, unsigned int);
|
||||
m_statistics.indices_gpu_size += buffer.indices_count * sizeof(unsigned int);
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
||||
if (buffer.data_size > 0) {
|
||||
if (buffer.indices_count > 0) {
|
||||
glsafe(::glGenBuffers(1, &buffer.ibo_id));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.ibo_id));
|
||||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer.data_size * sizeof(unsigned int), buffer.data.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer.indices_count * sizeof(unsigned int), buffer_indices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
|
||||
// indices data -> free ram
|
||||
buffer.data = std::vector<unsigned int>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,6 +690,10 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
|
|||
|
||||
// update current sequential position
|
||||
m_sequential_view.current = keep_sequential_current ? std::clamp(m_sequential_view.current, m_sequential_view.first, m_sequential_view.last) : m_sequential_view.last;
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices.vbo_id));
|
||||
size_t v_size = VBuffer::vertex_size_bytes();
|
||||
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(m_sequential_view.current * v_size), static_cast<GLsizeiptr>(v_size), static_cast<void*>(m_sequential_view.current_position.data())));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// second pass: filter paths by sequential data
|
||||
for (auto&& [buffer, id] : paths) {
|
||||
|
@ -683,7 +736,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
{
|
||||
auto set_color = [](GLint current_program_id, const Color& color) {
|
||||
if (current_program_id > 0) {
|
||||
GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
|
||||
GLint color_id = ::glGetUniformLocation(current_program_id, "uniform_color");
|
||||
if (color_id >= 0) {
|
||||
glsafe(::glUniform3fv(color_id, 1, (const GLfloat*)color.data()));
|
||||
return;
|
||||
|
@ -714,10 +767,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
GCodeProcessor::EMoveType type = buffer_type(i);
|
||||
|
||||
buffer.shader.start_using();
|
||||
|
||||
GLint current_program_id;
|
||||
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id));
|
||||
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.ibo_id));
|
||||
|
||||
switch (type)
|
||||
|
@ -725,7 +775,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Tool_change:
|
||||
{
|
||||
Color color = { 1.0f, 1.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -741,7 +791,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Color_change:
|
||||
{
|
||||
Color color = { 1.0f, 0.0f, 0.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -757,7 +807,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Pause_Print:
|
||||
{
|
||||
Color color = { 0.0f, 1.0f, 0.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -773,7 +823,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Custom_GCode:
|
||||
{
|
||||
Color color = { 0.0f, 0.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -789,7 +839,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Retract:
|
||||
{
|
||||
Color color = { 1.0f, 0.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -805,7 +855,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
case GCodeProcessor::EMoveType::Unretract:
|
||||
{
|
||||
Color color = { 0.0f, 1.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||
|
@ -822,7 +872,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
{
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
set_color(current_program_id, path.color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), path.color);
|
||||
glsafe(::glMultiDrawElements(GL_LINE_STRIP, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
++m_statistics.gl_multi_line_strip_calls_count;
|
||||
|
@ -835,7 +885,7 @@ void GCodeViewer::render_toolpaths() const
|
|||
{
|
||||
for (const RenderPath& path : buffer.render_paths)
|
||||
{
|
||||
set_color(current_program_id, path.color);
|
||||
set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), path.color);
|
||||
glsafe(::glMultiDrawElements(GL_LINE_STRIP, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
++m_statistics.gl_multi_line_strip_calls_count;
|
||||
|
@ -874,7 +924,7 @@ void GCodeViewer::render_legend() const
|
|||
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
||||
static const ImU32 ICON_BORDER_COLOR = ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
if (!m_legend_enabled || m_roles.empty())
|
||||
if (!m_legend_enabled)
|
||||
return;
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
|
@ -928,14 +978,14 @@ void GCodeViewer::render_legend() const
|
|||
ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
|
||||
switch (m_view_type)
|
||||
{
|
||||
case EViewType::FeatureType: { imgui.text(I18N::translate_utf8(L("Feature type"))); break; }
|
||||
case EViewType::Height: { imgui.text(I18N::translate_utf8(L("Height (mm)"))); break; }
|
||||
case EViewType::Width: { imgui.text(I18N::translate_utf8(L("Width (mm)"))); break; }
|
||||
case EViewType::Feedrate: { imgui.text(I18N::translate_utf8(L("Speed (mm/s)"))); break; }
|
||||
case EViewType::FanSpeed: { imgui.text(I18N::translate_utf8(L("Fan Speed (%%)"))); break; }
|
||||
case EViewType::VolumetricRate: { imgui.text(I18N::translate_utf8(L("Volumetric flow rate (mm³/s)"))); break; }
|
||||
case EViewType::Tool: { imgui.text(I18N::translate_utf8(L("Tool"))); break; }
|
||||
case EViewType::ColorPrint: { imgui.text(I18N::translate_utf8(L("Color Print"))); break; }
|
||||
case EViewType::FeatureType: { imgui.text(_u8L("Feature type")); break; }
|
||||
case EViewType::Height: { imgui.text(_u8L("Height (mm)")); break; }
|
||||
case EViewType::Width: { imgui.text(_u8L("Width (mm)")); break; }
|
||||
case EViewType::Feedrate: { imgui.text(_u8L("Speed (mm/s)")); break; }
|
||||
case EViewType::FanSpeed: { imgui.text(_u8L("Fan Speed (%%)")); break; }
|
||||
case EViewType::VolumetricRate: { imgui.text(_u8L("Volumetric flow rate (mm³/s)")); break; }
|
||||
case EViewType::Tool: { imgui.text(_u8L("Tool")); break; }
|
||||
case EViewType::ColorPrint: { imgui.text(_u8L("Color Print")); break; }
|
||||
default: { break; }
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -951,7 +1001,7 @@ void GCodeViewer::render_legend() const
|
|||
if (!visible)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f);
|
||||
|
||||
add_item(Extrusion_Role_Colors[static_cast<unsigned int>(role)], I18N::translate_utf8(ExtrusionEntity::role_to_string(role)), [this, role]() {
|
||||
add_item(Extrusion_Role_Colors[static_cast<unsigned int>(role)], _u8L(ExtrusionEntity::role_to_string(role)), [this, role]() {
|
||||
if (role < erCount)
|
||||
{
|
||||
m_extrusions.role_visibility_flags = is_visible(role) ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role);
|
||||
|
@ -981,7 +1031,7 @@ void GCodeViewer::render_legend() const
|
|||
if (it == m_extruder_ids.end())
|
||||
continue;
|
||||
|
||||
add_item(m_tool_colors[i], (boost::format(I18N::translate_utf8(L("Extruder %d"))) % (i + 1)).str());
|
||||
add_item(m_tool_colors[i], (boost::format(_u8L("Extruder %d")) % (i + 1)).str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -992,7 +1042,7 @@ void GCodeViewer::render_legend() const
|
|||
if (extruders_count == 1) { // single extruder use case
|
||||
if (custom_gcode_per_print_z.empty())
|
||||
// no data to show
|
||||
add_item(m_tool_colors.front(), I18N::translate_utf8(L("Default print color")));
|
||||
add_item(m_tool_colors.front(), _u8L("Default print color"));
|
||||
else {
|
||||
std::vector<std::pair<double, double>> cp_values;
|
||||
cp_values.reserve(custom_gcode_per_print_z.size());
|
||||
|
@ -1016,7 +1066,7 @@ void GCodeViewer::render_legend() const
|
|||
|
||||
const int items_cnt = static_cast<int>(cp_values.size());
|
||||
if (items_cnt == 0) { // There is no one color change, but there are some pause print or custom Gcode
|
||||
add_item(m_tool_colors.front(), I18N::translate_utf8(L("Default print color")));
|
||||
add_item(m_tool_colors.front(), _u8L("Default print color"));
|
||||
}
|
||||
else {
|
||||
for (int i = items_cnt; i >= 0; --i) {
|
||||
|
@ -1024,14 +1074,14 @@ void GCodeViewer::render_legend() const
|
|||
std::string id_str = " (" + std::to_string(i + 1) + ")";
|
||||
|
||||
if (i == 0) {
|
||||
add_item(m_tool_colors[i], (boost::format(I18N::translate_utf8(L("up to %.2f mm"))) % cp_values.front().first).str() + id_str);
|
||||
add_item(m_tool_colors[i], (boost::format(_u8L("up to %.2f mm")) % cp_values.front().first).str() + id_str);
|
||||
break;
|
||||
}
|
||||
else if (i == items_cnt) {
|
||||
add_item(m_tool_colors[i], (boost::format(I18N::translate_utf8(L("above %.2f mm"))) % cp_values[i - 1].second).str() + id_str);
|
||||
add_item(m_tool_colors[i], (boost::format(_u8L("above %.2f mm")) % cp_values[i - 1].second).str() + id_str);
|
||||
continue;
|
||||
}
|
||||
add_item(m_tool_colors[i], (boost::format(I18N::translate_utf8(L("%.2f - %.2f mm"))) % cp_values[i - 1].second % cp_values[i].first).str() + id_str);
|
||||
add_item(m_tool_colors[i], (boost::format(_u8L("%.2f - %.2f mm")) % cp_values[i - 1].second% cp_values[i].first).str() + id_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1040,7 +1090,7 @@ void GCodeViewer::render_legend() const
|
|||
{
|
||||
// extruders
|
||||
for (unsigned int i = 0; i < (unsigned int)extruders_count; ++i) {
|
||||
add_item(m_tool_colors[i], (boost::format(I18N::translate_utf8(L("Extruder %d"))) % (i + 1)).str());
|
||||
add_item(m_tool_colors[i], (boost::format(_u8L("Extruder %d")) % (i + 1)).str());
|
||||
}
|
||||
|
||||
// color changes
|
||||
|
@ -1052,7 +1102,7 @@ void GCodeViewer::render_legend() const
|
|||
std::string id_str = " (" + std::to_string(color_change_idx--) + ")";
|
||||
|
||||
add_item(m_tool_colors[last_color_id--],
|
||||
(boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str() + id_str);
|
||||
(boost::format(_u8L("Color change for Extruder %d at %.2f mm")) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str() + id_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1079,14 +1129,14 @@ void GCodeViewer::render_legend() const
|
|||
ImGui::Spacing();
|
||||
ImGui::Spacing();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
|
||||
imgui.text(I18N::translate_utf8(L("Travel")));
|
||||
imgui.text(_u8L("Travel"));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Separator();
|
||||
|
||||
// items
|
||||
add_item(Travel_Colors[0], I18N::translate_utf8(L("Movement")));
|
||||
add_item(Travel_Colors[1], I18N::translate_utf8(L("Extrusion")));
|
||||
add_item(Travel_Colors[2], I18N::translate_utf8(L("Retraction")));
|
||||
add_item(Travel_Colors[0], _u8L("Movement"));
|
||||
add_item(Travel_Colors[1], _u8L("Extrusion"));
|
||||
add_item(Travel_Colors[2], _u8L("Retraction"));
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1097,7 +1147,7 @@ void GCodeViewer::render_legend() const
|
|||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void GCodeViewer::render_sequential_dlg() const
|
||||
void GCodeViewer::render_sequential_bar() const
|
||||
{
|
||||
static const float MARGIN = 125.0f;
|
||||
static const float BUTTON_W = 50.0f;
|
||||
|
@ -1107,9 +1157,6 @@ void GCodeViewer::render_sequential_dlg() const
|
|||
refresh_render_paths(true);
|
||||
};
|
||||
|
||||
if (m_roles.empty())
|
||||
return;
|
||||
|
||||
if (m_sequential_view.last <= m_sequential_view.first)
|
||||
return;
|
||||
|
||||
|
@ -1191,9 +1238,6 @@ void GCodeViewer::render_statistics() const
|
|||
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
||||
static const float offset = 250.0f;
|
||||
|
||||
if (m_roles.empty())
|
||||
return;
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
|
||||
imgui.set_next_window_pos(0.5f * wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_width(), 0.0f, ImGuiCond_Once, 0.5f, 0.0f);
|
||||
|
|
|
@ -5,11 +5,15 @@
|
|||
#include "GLShader.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GLModel.hpp"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Print;
|
||||
class TriangleMesh;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class GCodeViewer
|
||||
|
@ -73,19 +77,18 @@ class GCodeViewer
|
|||
struct IBuffer
|
||||
{
|
||||
unsigned int ibo_id{ 0 };
|
||||
size_t indices_count{ 0 };
|
||||
Shader shader;
|
||||
std::vector<unsigned int> data;
|
||||
size_t data_size{ 0 };
|
||||
std::vector<Path> paths;
|
||||
std::vector<RenderPath> render_paths;
|
||||
bool visible{ false };
|
||||
|
||||
void reset();
|
||||
bool init_shader(const std::string& vertex_shader_src, const std::string& fragment_shader_src);
|
||||
void add_path(const GCodeProcessor::MoveVertex& move, unsigned int s_id);
|
||||
void add_path(const GCodeProcessor::MoveVertex& move, unsigned int i_id, unsigned int s_id);
|
||||
};
|
||||
|
||||
|
||||
// helper to render shells
|
||||
struct Shells
|
||||
{
|
||||
GLVolumeCollection volumes;
|
||||
|
@ -148,9 +151,36 @@ class GCodeViewer
|
|||
|
||||
struct SequentialView
|
||||
{
|
||||
class Marker
|
||||
{
|
||||
GL_Model m_model;
|
||||
Transform3f m_world_transform;
|
||||
std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
bool m_visible{ false };
|
||||
Shader m_shader;
|
||||
|
||||
public:
|
||||
void init();
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
|
||||
|
||||
void set_world_transform(const Transform3f& transform) { m_world_transform = transform; }
|
||||
void set_color(const std::array<float, 4>& color) { m_color = color; }
|
||||
|
||||
bool is_visible() const { return m_visible; }
|
||||
void set_visible(bool visible) { m_visible = visible; }
|
||||
|
||||
void render() const;
|
||||
|
||||
private:
|
||||
void init_shader();
|
||||
};
|
||||
|
||||
unsigned int first{ 0 };
|
||||
unsigned int last{ 0 };
|
||||
unsigned int current{ 0 };
|
||||
Vec3f current_position{ Vec3f::Zero() };
|
||||
Marker marker;
|
||||
};
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
@ -237,6 +267,7 @@ public:
|
|||
|
||||
bool init() {
|
||||
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Extrude, true);
|
||||
m_sequential_view.marker.init();
|
||||
return init_shaders();
|
||||
}
|
||||
|
||||
|
@ -285,7 +316,7 @@ private:
|
|||
void render_toolpaths() const;
|
||||
void render_shells() const;
|
||||
void render_legend() const;
|
||||
void render_sequential_dlg() const;
|
||||
void render_sequential_bar() const;
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
void render_statistics() const;
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,9 +16,6 @@
|
|||
#include "GUI_ObjectLayers.hpp"
|
||||
#include "GLSelectionRectangle.hpp"
|
||||
#include "MeshUtils.hpp"
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "Camera.hpp"
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GCodeViewer.hpp"
|
||||
|
@ -35,9 +32,7 @@ class wxMouseEvent;
|
|||
class wxTimerEvent;
|
||||
class wxPaintEvent;
|
||||
class wxGLCanvas;
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
class wxGLContext;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
// Support for Retina OpenGL on Mac OS
|
||||
#define ENABLE_RETINA_GL __APPLE__
|
||||
|
@ -420,6 +415,7 @@ private:
|
|||
class Slope
|
||||
{
|
||||
bool m_enabled{ false };
|
||||
bool m_dialog_shown{ false };
|
||||
GLCanvas3D& m_canvas;
|
||||
GLVolumeCollection& m_volumes;
|
||||
|
||||
|
@ -428,9 +424,14 @@ private:
|
|||
|
||||
void enable(bool enable) { m_enabled = enable; }
|
||||
bool is_enabled() const { return m_enabled; }
|
||||
void show(bool show) { m_volumes.set_slope_active(m_enabled ? show : false); }
|
||||
bool is_shown() const { return m_volumes.is_slope_active(); }
|
||||
void use(bool use) { m_volumes.set_slope_active(m_enabled ? use : false); }
|
||||
bool is_used() const { return m_volumes.is_slope_active(); }
|
||||
void show_dialog(bool show) { if (show && is_used()) return; use(show); m_dialog_shown = show; }
|
||||
bool is_dialog_shown() const { return m_dialog_shown; }
|
||||
void render() const;
|
||||
void set_range(const std::array<float, 2>& range) const {
|
||||
m_volumes.set_slope_z_range({ -::cos(Geometry::deg2rad(90.0f - range[0])), -::cos(Geometry::deg2rad(90.0f - range[1])) });
|
||||
}
|
||||
};
|
||||
#endif // ENABLE_SLOPE_RENDERING
|
||||
|
||||
|
@ -453,11 +454,6 @@ private:
|
|||
#endif // !ENABLE_GCODE_VIEWER
|
||||
WarningTexture m_warning_texture;
|
||||
wxTimer m_timer;
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
Bed3D& m_bed;
|
||||
Camera& m_camera;
|
||||
GLToolbar& m_view_toolbar;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
LayersEditing m_layers_editing;
|
||||
Shader m_shader;
|
||||
Mouse m_mouse;
|
||||
|
@ -526,22 +522,17 @@ private:
|
|||
Labels m_labels;
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
mutable Tooltip m_tooltip;
|
||||
mutable bool m_tooltip_enabled{ true };
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
#if ENABLE_SLOPE_RENDERING
|
||||
Slope m_slope;
|
||||
#endif // ENABLE_SLOPE_RENDERING
|
||||
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
explicit GLCanvas3D(wxGLCanvas* canvas);
|
||||
#else
|
||||
GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
~GLCanvas3D();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool is_initialized() const { return m_initialized; }
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
void set_context(wxGLContext* context) { m_context = context; }
|
||||
|
||||
|
@ -593,13 +584,7 @@ public:
|
|||
|
||||
void set_color_by(const std::string& value);
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
void refresh_camera_scene_box();
|
||||
#else
|
||||
void refresh_camera_scene_box() { m_camera.set_scene_box(scene_bounding_box()); }
|
||||
const Camera& get_camera() const { return m_camera; }
|
||||
Camera& get_camera() { return m_camera; }
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Shader& get_shader() const { return m_shader; }
|
||||
|
||||
BoundingBoxf3 volumes_bounding_box() const;
|
||||
|
@ -607,6 +592,7 @@ public:
|
|||
|
||||
bool is_layers_editing_enabled() const;
|
||||
bool is_layers_editing_allowed() const;
|
||||
bool is_search_pressed() const;
|
||||
|
||||
void reset_layer_height_profile();
|
||||
void adaptive_layer_height_profile(float quality_factor);
|
||||
|
@ -662,7 +648,6 @@ public:
|
|||
void set_toolpaths_z_range(const std::array<double, 2>& range);
|
||||
#else
|
||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||
void set_toolpaths_range(double low, double high);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
void set_toolpaths_range(double low, double high);
|
||||
|
||||
|
@ -694,6 +679,9 @@ public:
|
|||
void on_timer(wxTimerEvent& evt);
|
||||
void on_mouse(wxMouseEvent& evt);
|
||||
void on_paint(wxPaintEvent& evt);
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
void on_set_focus(wxFocusEvent& evt);
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
|
||||
Size get_canvas_size() const;
|
||||
Vec2d get_local_mouse_position() const;
|
||||
|
@ -719,10 +707,6 @@ public:
|
|||
|
||||
void update_ui_from_settings();
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float get_view_toolbar_height() const { return m_view_toolbar.get_height(); }
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
int get_move_volume_id() const { return m_mouse.drag.move_volume_idx; }
|
||||
int get_first_hover_volume_idx() const { return m_hover_volume_idxs.empty() ? -1 : m_hover_volume_idxs.front(); }
|
||||
void set_selected_extruder(int extruder) { m_selected_extruder = extruder;}
|
||||
|
@ -765,6 +749,7 @@ public:
|
|||
int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
|
||||
void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
|
||||
void force_main_toolbar_right_action(int item_id) { m_main_toolbar.force_right_action(item_id, *this); }
|
||||
void update_tooltip_for_settings_item_in_main_toolbar();
|
||||
|
||||
bool has_toolpaths_to_export() const;
|
||||
void export_toolpaths_to_obj(const char* filename) const;
|
||||
|
@ -775,8 +760,10 @@ public:
|
|||
void show_labels(bool show) { m_labels.show(show); }
|
||||
|
||||
#if ENABLE_SLOPE_RENDERING
|
||||
bool is_slope_shown() const { return m_slope.is_shown(); }
|
||||
void show_slope(bool show) { m_slope.show(show); }
|
||||
bool is_slope_shown() const { return m_slope.is_dialog_shown(); }
|
||||
void use_slope(bool use) { m_slope.use(use); }
|
||||
void show_slope(bool show) { m_slope.show_dialog(show); }
|
||||
void set_slope_range(const std::array<float, 2>& range) { m_slope.set_range(range); }
|
||||
#endif // ENABLE_SLOPE_RENDERING
|
||||
|
||||
private:
|
||||
|
@ -810,6 +797,7 @@ private:
|
|||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void _render_selection_center() const;
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
void _check_and_update_toolbar_icon_scale() const;
|
||||
void _render_overlays() const;
|
||||
void _render_warning_texture() const;
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
|
@ -872,8 +860,10 @@ private:
|
|||
#endif // !ENABLE_GCODE_VIEWER
|
||||
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
|
||||
void _load_sla_shells();
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
// sets gcode geometry visibility according to user selection
|
||||
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
void _update_toolpath_volumes_outside_state();
|
||||
void _update_sla_shells_outside_state();
|
||||
void _show_warning_texture_if_needed(WarningTexture::Warning warning);
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
#ifndef slic3r_GLCanvas3DManager_hpp_
|
||||
#define slic3r_GLCanvas3DManager_hpp_
|
||||
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class wxWindow;
|
||||
class wxGLCanvas;
|
||||
class wxGLContext;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class BackgroundSlicingProcess;
|
||||
class DynamicPrintConfig;
|
||||
class Model;
|
||||
class ExPolygon;
|
||||
typedef std::vector<ExPolygon> ExPolygons;
|
||||
class ModelObject;
|
||||
class PrintObject;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class GLCanvas3D;
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
class Bed3D;
|
||||
class GLToolbar;
|
||||
struct Camera;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
class GLCanvas3DManager
|
||||
{
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
enum class EFramebufferType : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Arb,
|
||||
Ext
|
||||
};
|
||||
#else
|
||||
enum EFramebufferType : unsigned char
|
||||
{
|
||||
FB_None,
|
||||
FB_Arb,
|
||||
FB_Ext
|
||||
};
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
class GLInfo
|
||||
{
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
mutable bool m_detected{ false };
|
||||
mutable int m_max_tex_size{ 0 };
|
||||
mutable float m_max_anisotropy{ 0.0f };
|
||||
|
||||
mutable std::string m_version;
|
||||
mutable std::string m_glsl_version;
|
||||
mutable std::string m_vendor;
|
||||
mutable std::string m_renderer;
|
||||
#else
|
||||
mutable bool m_detected;
|
||||
|
||||
mutable std::string m_version;
|
||||
mutable std::string m_glsl_version;
|
||||
mutable std::string m_vendor;
|
||||
mutable std::string m_renderer;
|
||||
|
||||
mutable int m_max_tex_size;
|
||||
mutable float m_max_anisotropy;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLInfo() = default;
|
||||
#else
|
||||
GLInfo();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
const std::string& get_version() const;
|
||||
const std::string& get_glsl_version() const;
|
||||
const std::string& get_vendor() const;
|
||||
const std::string& get_renderer() const;
|
||||
|
||||
int get_max_tex_size() const;
|
||||
float get_max_anisotropy() const;
|
||||
|
||||
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
|
||||
|
||||
std::string to_string(bool format_as_html, bool extensions) const;
|
||||
|
||||
private:
|
||||
void detect() const;
|
||||
};
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
struct OSInfo
|
||||
{
|
||||
int major{ 0 };
|
||||
int minor{ 0 };
|
||||
int micro{ 0 };
|
||||
};
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
private:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
enum class EMultisampleState : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Enabled,
|
||||
Disabled
|
||||
};
|
||||
#else
|
||||
enum EMultisampleState : unsigned char
|
||||
{
|
||||
MS_Unknown,
|
||||
MS_Enabled,
|
||||
MS_Disabled
|
||||
};
|
||||
|
||||
typedef std::map<wxGLCanvas*, GLCanvas3D*> CanvasesMap;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool m_gl_initialized{ false };
|
||||
wxGLContext* m_context{ nullptr };
|
||||
#else
|
||||
wxGLContext* m_context;
|
||||
bool m_gl_initialized;
|
||||
CanvasesMap m_canvases;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static GLInfo s_gl_info;
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
static OSInfo s_os_info;
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
static bool s_compressed_textures_supported;
|
||||
static EMultisampleState s_multisample;
|
||||
static EFramebufferType s_framebuffers_type;
|
||||
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager() = default;
|
||||
#else
|
||||
GLCanvas3DManager();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
~GLCanvas3DManager();
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
|
||||
bool remove(wxGLCanvas* canvas);
|
||||
void remove_all();
|
||||
|
||||
size_t count() const;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool init_gl();
|
||||
#else
|
||||
void init_gl();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
wxGLContext* init_glcontext(wxGLCanvas& canvas);
|
||||
#else
|
||||
bool init(wxGLCanvas* canvas);
|
||||
void destroy();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3D* get_canvas(wxGLCanvas* canvas);
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static bool can_multisample() { return s_multisample == EMultisampleState::Enabled; }
|
||||
static bool are_framebuffers_supported() { return (s_framebuffers_type != EFramebufferType::Unknown); }
|
||||
#else
|
||||
static bool can_multisample() { return s_multisample == MS_Enabled; }
|
||||
static bool are_framebuffers_supported() { return (s_framebuffers_type != FB_None); }
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; }
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static wxGLCanvas* create_wxglcanvas(wxWindow& parent);
|
||||
#else
|
||||
static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
static const GLInfo& get_gl_info() { return s_gl_info; }
|
||||
|
||||
private:
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
CanvasesMap::iterator do_get_canvas(wxGLCanvas* canvas);
|
||||
CanvasesMap::const_iterator do_get_canvas(wxGLCanvas* canvas) const;
|
||||
|
||||
bool init(GLCanvas3D& canvas);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static void detect_multisample(int* attribList);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLCanvas3DManager_hpp_
|
508
src/slic3r/GUI/GLModel.cpp
Normal file
508
src/slic3r/GUI/GLModel.cpp
Normal file
|
@ -0,0 +1,508 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#include "GLModel.hpp"
|
||||
|
||||
#include "3DScene.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
void GL_Model::init_from(const GLModelInitializationData& data)
|
||||
{
|
||||
assert(!data.positions.empty() && !data.triangles.empty());
|
||||
assert(data.positions.size() == data.normals.size());
|
||||
|
||||
if (m_vbo_id > 0) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
// vertices/normals data
|
||||
std::vector<float> vertices(6 * data.positions.size());
|
||||
for (size_t i = 0; i < data.positions.size(); ++i) {
|
||||
::memcpy(static_cast<void*>(&vertices[i * 6]), static_cast<const void*>(data.positions[i].data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + i * 6]), static_cast<const void*>(data.normals[i].data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
// indices data
|
||||
std::vector<unsigned int> indices(3 * data.triangles.size());
|
||||
for (size_t i = 0; i < data.triangles.size(); ++i) {
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
indices[i * 3 + j] = static_cast<unsigned int>(data.triangles[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
m_indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = BoundingBoxf3();
|
||||
for (size_t i = 0; i < data.positions.size(); ++i) {
|
||||
m_bounding_box.merge(data.positions[i].cast<double>());
|
||||
}
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
}
|
||||
|
||||
void GL_Model::init_from(const TriangleMesh& mesh)
|
||||
{
|
||||
auto get_normal = [](const std::array<stl_vertex, 3>& triangle) {
|
||||
return (triangle[1] - triangle[0]).cross(triangle[2] - triangle[0]).normalized();
|
||||
};
|
||||
|
||||
if (m_vbo_id > 0) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
assert(!mesh.its.vertices.empty() && !mesh.its.indices.empty()); // call require_shared_vertices() before to pass the mesh to this method
|
||||
|
||||
// vertices data -> load from mesh
|
||||
std::vector<float> vertices(6 * mesh.its.vertices.size());
|
||||
for (size_t i = 0; i < mesh.its.vertices.size(); ++i) {
|
||||
::memcpy(static_cast<void*>(&vertices[i * 6]), static_cast<const void*>(mesh.its.vertices[i].data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
// indices/normals data -> load from mesh
|
||||
std::vector<unsigned int> indices(3 * mesh.its.indices.size());
|
||||
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
|
||||
const stl_triangle_vertex_indices& triangle = mesh.its.indices[i];
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
indices[i * 3 + j] = static_cast<unsigned int>(triangle[j]);
|
||||
}
|
||||
Vec3f normal = get_normal({ mesh.its.vertices[triangle[0]], mesh.its.vertices[triangle[1]], mesh.its.vertices[triangle[2]] });
|
||||
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[0]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[1]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[2]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
m_indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = mesh.bounding_box();
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
}
|
||||
|
||||
void GL_Model::reset()
|
||||
{
|
||||
// release gpu memory
|
||||
if (m_ibo_id > 0) {
|
||||
glsafe(::glDeleteBuffers(1, &m_ibo_id));
|
||||
m_ibo_id = 0;
|
||||
}
|
||||
|
||||
if (m_vbo_id > 0) {
|
||||
glsafe(::glDeleteBuffers(1, &m_vbo_id));
|
||||
m_vbo_id = 0;
|
||||
}
|
||||
|
||||
m_indices_count = 0;
|
||||
m_bounding_box = BoundingBoxf3();
|
||||
}
|
||||
|
||||
void GL_Model::render() const
|
||||
{
|
||||
if (m_vbo_id == 0 || m_ibo_id == 0)
|
||||
return;
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0));
|
||||
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
||||
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
|
||||
glsafe(::glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_indices_count), GL_UNSIGNED_INT, (const void*)0));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
|
||||
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
|
||||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
void GL_Model::send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
|
||||
{
|
||||
// vertex data -> send to gpu
|
||||
glsafe(::glGenBuffers(1, &m_vbo_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// indices data -> send to gpu
|
||||
glsafe(::glGenBuffers(1, &m_ibo_id));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
|
||||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
data.positions.emplace_back(position);
|
||||
data.normals.emplace_back(normal);
|
||||
};
|
||||
|
||||
resolution = std::max(4, resolution);
|
||||
|
||||
GLModelInitializationData data;
|
||||
|
||||
const float angle_step = 2.0f * M_PI / static_cast<float>(resolution);
|
||||
std::vector<float> cosines(resolution);
|
||||
std::vector<float> sines(resolution);
|
||||
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
float angle = angle_step * static_cast<float>(i);
|
||||
cosines[i] = ::cos(angle);
|
||||
sines[i] = -::sin(angle);
|
||||
}
|
||||
|
||||
const float total_height = tip_height + stem_height;
|
||||
|
||||
// tip vertices/normals
|
||||
append_vertex(data, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// tip triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v3 = (i < resolution - 1) ? i + 2 : 1;
|
||||
data.triangles.emplace_back(0, i + 1, v3);
|
||||
}
|
||||
|
||||
// tip cap outer perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap inner perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
|
||||
int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
|
||||
data.triangles.emplace_back(i + resolution + 1, v3, v2);
|
||||
data.triangles.emplace_back(i + resolution + 1, i + 2 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem bottom vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem top vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
|
||||
int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, v3, v2);
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, i + 4 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem cap vertices
|
||||
append_vertex(data, Vec3f::Zero(), -Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// stem cap triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
|
||||
data.triangles.emplace_back(5 * resolution + 1, v3, i + 5 * resolution + 2);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GLModelInitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
data.positions.emplace_back(position);
|
||||
data.normals.emplace_back(normal);
|
||||
};
|
||||
|
||||
resolution = std::max(2, resolution);
|
||||
|
||||
GLModelInitializationData data;
|
||||
|
||||
const float half_thickness = 0.5f * thickness;
|
||||
const float half_stem_width = 0.5f * stem_width;
|
||||
const float half_tip_width = 0.5f * tip_width;
|
||||
|
||||
const float outer_radius = radius + half_stem_width;
|
||||
const float inner_radius = radius - half_stem_width;
|
||||
const float step_angle = 0.5f * PI / static_cast<float>(resolution);
|
||||
|
||||
// tip
|
||||
// top face vertices
|
||||
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { -tip_height, radius, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ());
|
||||
|
||||
// top face triangles
|
||||
data.triangles.emplace_back(0, 1, 2);
|
||||
data.triangles.emplace_back(0, 2, 4);
|
||||
data.triangles.emplace_back(4, 2, 3);
|
||||
|
||||
// bottom face vertices
|
||||
append_vertex(data, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
|
||||
// bottom face triangles
|
||||
data.triangles.emplace_back(5, 7, 6);
|
||||
data.triangles.emplace_back(5, 9, 7);
|
||||
data.triangles.emplace_back(9, 8, 7);
|
||||
|
||||
// side faces vertices
|
||||
append_vertex(data, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
Vec3f normal(-half_tip_width, tip_height, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, normal);
|
||||
append_vertex(data, { -tip_height, radius, -half_thickness }, normal);
|
||||
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, normal);
|
||||
append_vertex(data, { -tip_height, radius, half_thickness }, normal);
|
||||
|
||||
normal = Vec3f(-half_tip_width, -tip_height, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(data, { -tip_height, radius, -half_thickness }, normal);
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, normal);
|
||||
append_vertex(data, { -tip_height, radius, half_thickness }, normal);
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, normal);
|
||||
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
int ii = i * 4;
|
||||
data.triangles.emplace_back(10 + ii, 11 + ii, 13 + ii);
|
||||
data.triangles.emplace_back(10 + ii, 13 + ii, 12 + ii);
|
||||
}
|
||||
|
||||
// stem
|
||||
// top face vertices
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// top face triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.triangles.emplace_back(26 + i, 27 + i, 27 + resolution + i);
|
||||
data.triangles.emplace_back(27 + i, 28 + resolution + i, 27 + resolution + i);
|
||||
}
|
||||
|
||||
// bottom face vertices
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// bottom face triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.triangles.emplace_back(28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
|
||||
data.triangles.emplace_back(29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
|
||||
}
|
||||
|
||||
// side faces vertices and triangles
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f });
|
||||
}
|
||||
|
||||
int first_id = 26 + 4 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int ii = first_id + i;
|
||||
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
|
||||
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
|
||||
}
|
||||
|
||||
append_vertex(data, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { outer_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
first_id = 26 + 6 * (resolution + 1);
|
||||
data.triangles.emplace_back(first_id, first_id + 1, first_id + 3);
|
||||
data.triangles.emplace_back(first_id, first_id + 3, first_id + 2);
|
||||
|
||||
for (int i = resolution; i >= 0; --i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = resolution; i >= 0; --i)
|
||||
{
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f });
|
||||
}
|
||||
|
||||
first_id = 30 + 6 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int ii = first_id + i;
|
||||
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
|
||||
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
data.positions.emplace_back(position);
|
||||
data.normals.emplace_back(normal);
|
||||
};
|
||||
|
||||
GLModelInitializationData data;
|
||||
|
||||
const float half_thickness = 0.5f * thickness;
|
||||
const float half_stem_width = 0.5f * stem_width;
|
||||
const float half_tip_width = 0.5f * tip_width;
|
||||
const float total_height = tip_height + stem_height;
|
||||
|
||||
// top face vertices
|
||||
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0, total_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
|
||||
|
||||
// top face triangles
|
||||
data.triangles.emplace_back(0, 1, 6);
|
||||
data.triangles.emplace_back(6, 1, 5);
|
||||
data.triangles.emplace_back(4, 5, 3);
|
||||
data.triangles.emplace_back(5, 1, 3);
|
||||
data.triangles.emplace_back(1, 2, 3);
|
||||
|
||||
// bottom face vertices
|
||||
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
|
||||
|
||||
// bottom face triangles
|
||||
data.triangles.emplace_back(7, 13, 8);
|
||||
data.triangles.emplace_back(13, 12, 8);
|
||||
data.triangles.emplace_back(12, 11, 10);
|
||||
data.triangles.emplace_back(8, 12, 10);
|
||||
data.triangles.emplace_back(9, 8, 10);
|
||||
|
||||
// side faces vertices
|
||||
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
Vec3f normal(tip_height, half_tip_width, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, normal);
|
||||
append_vertex(data, { 0.0, total_height, -half_thickness }, normal);
|
||||
append_vertex(data, { half_tip_width, stem_height, half_thickness }, normal);
|
||||
append_vertex(data, { 0.0, total_height, half_thickness }, normal);
|
||||
|
||||
normal = Vec3f(-tip_height, half_tip_width, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(data, { 0.0, total_height, -half_thickness }, normal);
|
||||
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, normal);
|
||||
append_vertex(data, { 0.0, total_height, half_thickness }, normal);
|
||||
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, normal);
|
||||
|
||||
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX());
|
||||
|
||||
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(data, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
int ii = i * 4;
|
||||
data.triangles.emplace_back(14 + ii, 15 + ii, 17 + ii);
|
||||
data.triangles.emplace_back(14 + ii, 17 + ii, 16 + ii);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
64
src/slic3r/GUI/GLModel.hpp
Normal file
64
src/slic3r/GUI/GLModel.hpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#ifndef slic3r_GLModel_hpp_
|
||||
#define slic3r_GLModel_hpp_
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class TriangleMesh;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
struct GLModelInitializationData
|
||||
{
|
||||
std::vector<Vec3f> positions;
|
||||
std::vector<Vec3f> normals;
|
||||
std::vector<Vec3i> triangles;
|
||||
};
|
||||
|
||||
class GL_Model
|
||||
{
|
||||
unsigned int m_vbo_id{ 0 };
|
||||
unsigned int m_ibo_id{ 0 };
|
||||
size_t m_indices_count{ 0 };
|
||||
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
|
||||
public:
|
||||
virtual ~GL_Model() { reset(); }
|
||||
|
||||
void init_from(const GLModelInitializationData& data);
|
||||
void init_from(const TriangleMesh& mesh);
|
||||
void reset();
|
||||
void render() const;
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
|
||||
|
||||
private:
|
||||
void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
|
||||
};
|
||||
|
||||
|
||||
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
|
||||
// the origin of the arrow is in the center of the stem cap
|
||||
// the arrow has its axis of symmetry along the Z axis and is pointing upward
|
||||
GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height,
|
||||
float stem_radius, float stem_height);
|
||||
|
||||
// create an arrow whose stem is a quarter of circle, with the given dimensions and resolution
|
||||
// the origin of the arrow is in the center of the circle
|
||||
// the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise
|
||||
GLModelInitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness);
|
||||
|
||||
// create an arrow with the given dimensions
|
||||
// the origin of the arrow is in the center of the stem cap
|
||||
// the arrow is contained in XY plane and has its main axis along the Y axis
|
||||
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness);
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLModel_hpp_
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
#include "Camera.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "GUI_App.hpp"
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
@ -38,11 +36,7 @@ namespace GUI {
|
|||
|
||||
m_state = Off;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#else
|
||||
const Camera& camera = canvas.get_camera();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||
const Transform3d& modelview_matrix = camera.get_view_matrix();
|
||||
const Transform3d& projection_matrix = camera.get_projection_matrix();
|
||||
|
@ -75,11 +69,7 @@ namespace GUI {
|
|||
if (!is_dragging())
|
||||
return;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#else
|
||||
const Camera& camera = canvas.get_camera();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)camera.get_inv_zoom();
|
||||
|
||||
Size cnv_size = canvas.get_canvas_size();
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
#include "GLTexture.hpp"
|
||||
|
||||
#include "3DScene.hpp"
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "GLCanvas3DManager.hpp"
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "OpenGLManager.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
@ -443,7 +441,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
|
|||
|
||||
if (apply_anisotropy)
|
||||
{
|
||||
GLfloat max_anisotropy = GLCanvas3DManager::get_gl_info().get_max_anisotropy();
|
||||
GLfloat max_anisotropy = OpenGLManager::get_gl_info().get_max_anisotropy();
|
||||
if (max_anisotropy > 1.0f)
|
||||
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
|
||||
}
|
||||
|
@ -592,7 +590,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
|
|||
|
||||
if (apply_anisotropy)
|
||||
{
|
||||
GLfloat max_anisotropy = GLCanvas3DManager::get_gl_info().get_max_anisotropy();
|
||||
GLfloat max_anisotropy = OpenGLManager::get_gl_info().get_max_anisotropy();
|
||||
if (max_anisotropy > 1.0f)
|
||||
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
|
||||
}
|
||||
|
|
|
@ -3,14 +3,9 @@
|
|||
|
||||
#include "GLToolbar.hpp"
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#else
|
||||
#include "../../slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "../../slic3r/GUI/Camera.hpp"
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/bitmap.h>
|
||||
|
@ -252,7 +247,7 @@ bool GLToolbar::is_enabled() const
|
|||
|
||||
void GLToolbar::set_enabled(bool enable)
|
||||
{
|
||||
m_enabled = true;
|
||||
m_enabled = enable;//true; etFIXME
|
||||
}
|
||||
|
||||
bool GLToolbar::add_item(const GLToolbarItem::Data& data)
|
||||
|
@ -537,7 +532,12 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
|||
m_mouse_capture.left = true;
|
||||
m_mouse_capture.parent = &parent;
|
||||
processed = true;
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
if ((item_id != -2) && !m_items[item_id]->is_separator() && !m_items[item_id]->is_disabled() &&
|
||||
((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Left)))
|
||||
#else
|
||||
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Left)))
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
{
|
||||
// mouse is inside an icon
|
||||
do_action(GLToolbarItem::Left, item_id, parent, true);
|
||||
|
@ -554,7 +554,12 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
|||
m_mouse_capture.right = true;
|
||||
m_mouse_capture.parent = &parent;
|
||||
processed = true;
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
if ((item_id != -2) && !m_items[item_id]->is_separator() && !m_items[item_id]->is_disabled() &&
|
||||
((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Right)))
|
||||
#else
|
||||
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Right)))
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
{
|
||||
// mouse is inside an icon
|
||||
do_action(GLToolbarItem::Right, item_id, parent, true);
|
||||
|
@ -632,6 +637,16 @@ float GLToolbar::get_main_size() const
|
|||
return size * m_layout.scale;
|
||||
}
|
||||
|
||||
int GLToolbar::get_visible_items_cnt() const
|
||||
{
|
||||
int cnt = 0;
|
||||
for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
|
||||
if (m_items[i]->is_visible() && !m_items[i]->is_separator())
|
||||
cnt++;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover)
|
||||
{
|
||||
if ((m_pressed_toggable_id == -1) || (m_pressed_toggable_id == item_id))
|
||||
|
@ -639,7 +654,11 @@ void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas
|
|||
if ((0 <= item_id) && (item_id < (int)m_items.size()))
|
||||
{
|
||||
GLToolbarItem* item = m_items[item_id];
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
if ((item != nullptr) && !item->is_separator() && !item->is_disabled() && (!check_hover || item->is_hovered()))
|
||||
#else
|
||||
if ((item != nullptr) && !item->is_separator() && (!check_hover || item->is_hovered()))
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
{
|
||||
if (((type == GLToolbarItem::Right) && item->is_right_toggable()) ||
|
||||
((type == GLToolbarItem::Left) && item->is_left_toggable()))
|
||||
|
@ -729,11 +748,7 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
|
|||
{
|
||||
// NB: mouse_pos is already scaled appropriately
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
|
@ -874,11 +889,7 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
|
|||
{
|
||||
// NB: mouse_pos is already scaled appropriately
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
|
@ -1027,11 +1038,7 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
|
|||
{
|
||||
// NB: mouse_pos is already scaled appropriately
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
|
@ -1104,11 +1111,7 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
|
|||
{
|
||||
// NB: mouse_pos is already scaled appropriately
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
|
@ -1260,11 +1263,7 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
|||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = inv_zoom * m_layout.scale;
|
||||
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
|
@ -1312,11 +1311,7 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
|||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float factor = inv_zoom * m_layout.scale;
|
||||
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
|
|
|
@ -319,6 +319,7 @@ public:
|
|||
void get_additional_tooltip(int item_id, std::string& text);
|
||||
void set_additional_tooltip(int item_id, const std::string& text);
|
||||
void set_tooltip(int item_id, const std::string& text);
|
||||
int get_visible_items_cnt() const;
|
||||
|
||||
// returns true if any item changed its state
|
||||
bool update_items_state();
|
||||
|
|
|
@ -283,29 +283,27 @@ GUI_App::~GUI_App()
|
|||
delete preset_updater;
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
std::string GUI_App::get_gl_info(bool format_as_html, bool extensions)
|
||||
{
|
||||
return GLCanvas3DManager::get_gl_info().to_string(format_as_html, extensions);
|
||||
return OpenGLManager::get_gl_info().to_string(format_as_html, extensions);
|
||||
}
|
||||
|
||||
wxGLContext* GUI_App::init_glcontext(wxGLCanvas& canvas)
|
||||
{
|
||||
return m_canvas_mgr.init_glcontext(canvas);
|
||||
return m_opengl_mgr.init_glcontext(canvas);
|
||||
}
|
||||
|
||||
bool GUI_App::init_opengl()
|
||||
{
|
||||
return m_canvas_mgr.init_gl();
|
||||
return m_opengl_mgr.init_gl();
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
void GUI_App::init_app_config()
|
||||
{
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
SetAppName(SLIC3R_APP_KEY);
|
||||
//SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
// SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
|
||||
// Set the Slic3r data directory at the Slic3r XS module.
|
||||
// Unix: ~/ .Slic3r
|
||||
|
@ -324,6 +322,7 @@ void GUI_App::init_app_config()
|
|||
app_config->load();
|
||||
}
|
||||
}
|
||||
|
||||
bool GUI_App::OnInit()
|
||||
{
|
||||
try {
|
||||
|
@ -413,7 +412,8 @@ bool GUI_App::on_init_inner()
|
|||
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
|
||||
wxImage::AddHandler(new wxPNGHandler());
|
||||
mainframe = new MainFrame();
|
||||
mainframe->switch_to(true); // hide settings tabs after first Layout
|
||||
// hide settings tabs after first Layout
|
||||
mainframe->select_tab(0);
|
||||
|
||||
sidebar().obj_list()->init_objects(); // propagate model objects to object list
|
||||
// update_mode(); // !!! do that later
|
||||
|
@ -580,28 +580,47 @@ float GUI_App::toolbar_icon_scale(const bool is_limited/* = false*/) const
|
|||
|
||||
const std::string& use_val = app_config->get("use_custom_toolbar_size");
|
||||
const std::string& val = app_config->get("custom_toolbar_size");
|
||||
const std::string& auto_val = app_config->get("auto_toolbar_size");
|
||||
|
||||
if (val.empty() || use_val.empty() || use_val == "0")
|
||||
if (val.empty() || auto_val.empty() || use_val.empty())
|
||||
return icon_sc;
|
||||
|
||||
int int_val = atoi(val.c_str());
|
||||
int int_val = use_val == "0" ? 100 : atoi(val.c_str());
|
||||
// correct value in respect to auto_toolbar_size
|
||||
int_val = std::min(atoi(auto_val.c_str()), int_val);
|
||||
|
||||
if (is_limited && int_val < 50)
|
||||
int_val = 50;
|
||||
|
||||
return 0.01f * int_val * icon_sc;
|
||||
}
|
||||
|
||||
void GUI_App::recreate_GUI()
|
||||
void GUI_App::set_auto_toolbar_icon_scale(float scale) const
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
const float icon_sc = 1.0f; // for Retina display will be used its own scale
|
||||
#else
|
||||
const float icon_sc = m_em_unit * 0.1f;
|
||||
#endif // __APPLE__
|
||||
|
||||
int int_val = std::min(int(scale / icon_sc * 100), 100);
|
||||
std::string val = std::to_string(int_val);
|
||||
|
||||
app_config->set("auto_toolbar_size", val);
|
||||
}
|
||||
|
||||
void GUI_App::recreate_GUI(const wxString& msg_name)
|
||||
{
|
||||
mainframe->shutdown();
|
||||
|
||||
const auto msg_name = _(L("Changing of an application language")) + dots;
|
||||
wxProgressDialog dlg(msg_name, msg_name);
|
||||
dlg.Pulse();
|
||||
dlg.Update(10, _(L("Recreating")) + dots);
|
||||
|
||||
MainFrame *old_main_frame = mainframe;
|
||||
mainframe = new MainFrame();
|
||||
// hide settings tabs after first Layout
|
||||
mainframe->select_tab(0);
|
||||
// Propagate model objects to object list.
|
||||
sidebar().obj_list()->init_objects();
|
||||
SetTopWindow(mainframe);
|
||||
|
@ -705,12 +724,6 @@ void GUI_App::load_project(wxWindow *parent, wxString& input_file) const
|
|||
|
||||
void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
|
||||
{
|
||||
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
if (this->plater_ != nullptr)
|
||||
// hides the tooltip
|
||||
plater_->get_current_canvas3D()->set_tooltip("");
|
||||
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
||||
|
||||
input_files.Clear();
|
||||
wxFileDialog dialog(parent ? parent : GetTopWindow(),
|
||||
_(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")),
|
||||
|
@ -724,7 +737,7 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
|
|||
bool GUI_App::switch_language()
|
||||
{
|
||||
if (select_language()) {
|
||||
recreate_GUI();
|
||||
recreate_GUI(_L("Changing of an application language") + dots);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1028,8 +1041,17 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
break;
|
||||
case ConfigMenuPreferences:
|
||||
{
|
||||
PreferencesDialog dlg(mainframe);
|
||||
dlg.ShowModal();
|
||||
bool recreate_app = false;
|
||||
{
|
||||
// the dialog needs to be destroyed before the call to recreate_GUI()
|
||||
// or sometimes the application crashes into wxDialogBase() destructor
|
||||
// so we put it into an inner scope
|
||||
PreferencesDialog dlg(mainframe);
|
||||
dlg.ShowModal();
|
||||
recreate_app = dlg.settings_layout_changed();
|
||||
}
|
||||
if (recreate_app)
|
||||
recreate_GUI(_L("Changing of the settings layout") + dots);
|
||||
break;
|
||||
}
|
||||
case ConfigMenuLanguage:
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
#include "MainFrame.hpp"
|
||||
#include "ImGuiWrapper.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "GLCanvas3DManager.hpp"
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "OpenGLManager.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
|
@ -100,9 +98,7 @@ class GUI_App : public wxApp
|
|||
// Best translation language, provided by Windows or OSX, owned by wxWidgets.
|
||||
const wxLanguageInfo *m_language_info_best = nullptr;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager m_canvas_mgr;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
OpenGLManager m_opengl_mgr;
|
||||
|
||||
std::unique_ptr<RemovableDriveManager> m_removable_drive_manager;
|
||||
|
||||
|
@ -117,11 +113,9 @@ public:
|
|||
GUI_App();
|
||||
~GUI_App() override;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
static std::string get_gl_info(bool format_as_html, bool extensions);
|
||||
wxGLContext* init_glcontext(wxGLCanvas& canvas);
|
||||
bool init_opengl();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
static unsigned get_colour_approx_luma(const wxColour &colour);
|
||||
static bool dark_mode();
|
||||
|
@ -141,8 +135,9 @@ public:
|
|||
const wxFont& normal_font() { return m_normal_font; }
|
||||
int em_unit() const { return m_em_unit; }
|
||||
float toolbar_icon_scale(const bool is_limited = false) const;
|
||||
void set_auto_toolbar_icon_scale(float scale) const;
|
||||
|
||||
void recreate_GUI();
|
||||
void recreate_GUI(const wxString& message);
|
||||
void system_info();
|
||||
void keyboard_shortcuts();
|
||||
void load_project(wxWindow *parent, wxString& input_file) const;
|
||||
|
@ -168,6 +163,7 @@ public:
|
|||
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
|
||||
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
||||
wxString current_language_code_safe() const;
|
||||
bool is_localized() const { return m_wxLocale->GetLocale() != "English"; }
|
||||
|
||||
virtual bool OnExceptionInMainLoop() override;
|
||||
|
||||
|
|
|
@ -2771,6 +2771,7 @@ void ObjectList::delete_all_objects_from_list()
|
|||
void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num)
|
||||
{
|
||||
select_item(m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num));
|
||||
selection_changed();
|
||||
}
|
||||
|
||||
void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t num)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "GUI_Preview.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
|
@ -7,7 +9,7 @@
|
|||
#include "AppConfig.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "GLCanvas3DManager.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "DoubleSlider.hpp"
|
||||
|
@ -27,65 +29,36 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
View3D::View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
: m_canvas_widget(nullptr)
|
||||
, m_canvas(nullptr)
|
||||
{
|
||||
init(parent, model, config, process);
|
||||
}
|
||||
#else
|
||||
View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
: m_canvas_widget(nullptr)
|
||||
, m_canvas(nullptr)
|
||||
{
|
||||
init(parent, bed, camera, view_toolbar, model, config, process);
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
View3D::~View3D()
|
||||
{
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (m_canvas != nullptr)
|
||||
delete m_canvas;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
if (m_canvas_widget != nullptr)
|
||||
{
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
_3DScene::remove_canvas(m_canvas_widget);
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
delete m_canvas_widget;
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_canvas = nullptr;
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool View3D::init(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
#else
|
||||
bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
{
|
||||
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))
|
||||
return false;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(*this);
|
||||
m_canvas_widget = OpenGLManager::create_wxglcanvas(*this);
|
||||
if (m_canvas_widget == nullptr)
|
||||
return false;
|
||||
|
||||
m_canvas = new GLCanvas3D(m_canvas_widget);
|
||||
m_canvas->set_context(wxGetApp().init_glcontext(*m_canvas_widget));
|
||||
m_canvas->bind_event_handlers();
|
||||
#else
|
||||
m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this);
|
||||
_3DScene::add_canvas(m_canvas_widget, bed, camera, view_toolbar);
|
||||
m_canvas = _3DScene::get_canvas(this->m_canvas_widget);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
m_canvas->allow_multisample(GLCanvas3DManager::can_multisample());
|
||||
m_canvas->allow_multisample(OpenGLManager::can_multisample());
|
||||
// XXX: If have OpenGL
|
||||
m_canvas->enable_picking(true);
|
||||
m_canvas->enable_moving(true);
|
||||
|
@ -199,27 +172,15 @@ void View3D::render()
|
|||
m_canvas->set_as_dirty();
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Preview::Preview(
|
||||
wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process_func)
|
||||
BackgroundSlicingProcess* process, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process_func)
|
||||
#else
|
||||
Preview::Preview(
|
||||
wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#else
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Preview::Preview(
|
||||
wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process_func)
|
||||
#else
|
||||
Preview::Preview(
|
||||
wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
: m_canvas_widget(nullptr)
|
||||
, m_canvas(nullptr)
|
||||
, m_double_slider_sizer(nullptr)
|
||||
|
@ -241,9 +202,10 @@ Preview::Preview(
|
|||
#endif // ENABLE_GCODE_VIEWER
|
||||
, m_config(config)
|
||||
, m_process(process)
|
||||
, m_gcode_preview_data(gcode_preview_data)
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
, m_gcode_result(gcode_result)
|
||||
#else
|
||||
, m_gcode_preview_data(gcode_preview_data)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
, m_number_extruders(1)
|
||||
, m_preferred_color_mode("feature")
|
||||
|
@ -254,11 +216,7 @@ Preview::Preview(
|
|||
, m_volumes_cleanup_required(false)
|
||||
#endif // __linux__
|
||||
{
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (init(parent, model))
|
||||
#else
|
||||
if (init(parent, bed, camera, view_toolbar, model))
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
{
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
show_hide_ui_elements("none");
|
||||
|
@ -267,29 +225,19 @@ Preview::Preview(
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool Preview::init(wxWindow* parent, Model* model)
|
||||
#else
|
||||
bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model)
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
{
|
||||
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))
|
||||
return false;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(*this);
|
||||
m_canvas_widget = OpenGLManager::create_wxglcanvas(*this);
|
||||
if (m_canvas_widget == nullptr)
|
||||
return false;
|
||||
|
||||
m_canvas = new GLCanvas3D(m_canvas_widget);
|
||||
m_canvas->set_context(wxGetApp().init_glcontext(*m_canvas_widget));
|
||||
m_canvas->bind_event_handlers();
|
||||
#else
|
||||
m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this);
|
||||
_3DScene::add_canvas(m_canvas_widget, bed, camera, view_toolbar);
|
||||
m_canvas = _3DScene::get_canvas(this->m_canvas_widget);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_canvas->allow_multisample(GLCanvas3DManager::can_multisample());
|
||||
m_canvas->allow_multisample(OpenGLManager::can_multisample());
|
||||
m_canvas->set_config(m_config);
|
||||
m_canvas->set_model(model);
|
||||
m_canvas->set_process(m_process);
|
||||
|
@ -350,8 +298,9 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view
|
|||
_L("Pause prints") + "|0|" +
|
||||
_L("Custom GCodes") + "|0|" +
|
||||
_L("Shells") + "|0|" +
|
||||
_L("Tool marker") + "|1|" +
|
||||
_L("Legend") + "|1"
|
||||
);
|
||||
);
|
||||
Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
|
||||
#else
|
||||
m_checkbox_travel = new wxCheckBox(this, wxID_ANY, _(L("Travel")));
|
||||
|
@ -435,19 +384,11 @@ Preview::~Preview()
|
|||
{
|
||||
unbind_event_handlers();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (m_canvas != nullptr)
|
||||
delete m_canvas;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
if (m_canvas_widget != nullptr)
|
||||
{
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
_3DScene::remove_canvas(m_canvas_widget);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
delete m_canvas_widget;
|
||||
m_canvas = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Preview::set_as_dirty()
|
||||
|
@ -464,8 +405,13 @@ void Preview::set_number_extruders(unsigned int number_extruders)
|
|||
int tool_idx = m_choice_view_type->FindString(_(L("Tool")));
|
||||
int type = (number_extruders > 1) ? tool_idx /* color by a tool number */ : 0; // color by a feature type
|
||||
m_choice_view_type->SetSelection(type);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
|
||||
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
|
||||
#else
|
||||
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
|
||||
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
m_preferred_color_mode = (type == tool_idx) ? "tool_or_feature" : "feature";
|
||||
}
|
||||
|
@ -742,8 +688,13 @@ void Preview::update_view_type(bool slice_completed)
|
|||
int type = m_choice_view_type->FindString(choice);
|
||||
if (m_choice_view_type->GetSelection() != type) {
|
||||
m_choice_view_type->SetSelection(type);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
|
||||
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
|
||||
#else
|
||||
if (0 <= type && type < (int)GCodePreviewData::Extrusion::Num_View_Types)
|
||||
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_preferred_color_mode = "feature";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,7 @@ class GLCanvas3D;
|
|||
class GLToolbar;
|
||||
class Bed3D;
|
||||
struct Camera;
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
class Plater;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
class View3D : public wxPanel
|
||||
{
|
||||
|
@ -47,11 +45,7 @@ class View3D : public wxPanel
|
|||
GLCanvas3D* m_canvas;
|
||||
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process);
|
||||
#else
|
||||
View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
virtual ~View3D();
|
||||
|
||||
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }
|
||||
|
@ -79,11 +73,7 @@ public:
|
|||
void render();
|
||||
|
||||
private:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool init(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process);
|
||||
#else
|
||||
bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
};
|
||||
|
||||
class Preview : public wxPanel
|
||||
|
@ -133,23 +123,13 @@ class Preview : public wxPanel
|
|||
DoubleSlider::Control* m_slider {nullptr};
|
||||
|
||||
public:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
|
||||
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
|
||||
GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
|
||||
#else
|
||||
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
||||
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = []() {});
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#else
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
|
||||
#else
|
||||
Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config,
|
||||
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = []() {});
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
virtual ~Preview();
|
||||
|
||||
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }
|
||||
|
@ -180,11 +160,7 @@ public:
|
|||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
private:
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool init(wxWindow* parent, Model* model);
|
||||
#else
|
||||
bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
void bind_event_handlers();
|
||||
void unbind_event_handlers();
|
||||
|
|
|
@ -134,11 +134,8 @@ wxFont get_default_font_for_dpi(int dpi)
|
|||
NONCLIENTMETRICS nm;
|
||||
memset(&nm, 0, sizeof(NONCLIENTMETRICS));
|
||||
nm.cbSize = sizeof(NONCLIENTMETRICS);
|
||||
if (SystemParametersInfoForDpi_fn(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nm, 0, dpi)) {
|
||||
wxNativeFontInfo info;
|
||||
info.lf = nm.lfMessageFont;
|
||||
return wxFont(info);
|
||||
}
|
||||
if (SystemParametersInfoForDpi_fn(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nm, 0, dpi))
|
||||
return wxFont(wxNativeFontInfo(nm.lfMessageFont));
|
||||
}
|
||||
// Then try to guesstimate the font DPI scaling on Windows 8.
|
||||
// Let's hope that the font returned by the SystemParametersInfo(), which is used by wxWidgets internally, makes sense.
|
||||
|
|
|
@ -58,10 +58,10 @@ void GLGizmoFdmSupports::set_fdm_support_data(ModelObject* model_object, const S
|
|||
return;
|
||||
|
||||
if (mo && selection.is_from_single_instance()
|
||||
&& (mo != m_old_mo || mo->volumes.size() != m_old_volumes_size))
|
||||
&& (mo->id() != m_old_mo_id || mo->volumes.size() != m_old_volumes_size))
|
||||
{
|
||||
update_mesh();
|
||||
m_old_mo = mo;
|
||||
update_from_model_object();
|
||||
m_old_mo_id = mo->id();
|
||||
m_old_volumes_size = mo->volumes.size();
|
||||
}
|
||||
}
|
||||
|
@ -84,12 +84,29 @@ void GLGizmoFdmSupports::on_render() const
|
|||
|
||||
void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||
{
|
||||
if (m_setting_angle)
|
||||
return;
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
|
||||
glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
|
||||
ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); } );
|
||||
glsafe(::glPolygonOffset(-1.0, 1.0));
|
||||
|
||||
// Take care of the clipping plane. The normal of the clipping plane is
|
||||
// saved with opposite sign than we need to pass to OpenGL (FIXME)
|
||||
bool clipping_plane_active = m_c->object_clipper()->get_position() != 0.;
|
||||
if (clipping_plane_active) {
|
||||
const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane();
|
||||
double clp_data[4];
|
||||
memcpy(clp_data, clp->get_data(), 4 * sizeof(double));
|
||||
for (int i=0; i<3; ++i)
|
||||
clp_data[i] = -1. * clp_data[i];
|
||||
|
||||
glsafe(::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)clp_data));
|
||||
glsafe(::glEnable(GL_CLIP_PLANE0));
|
||||
}
|
||||
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (! mv->is_model_part())
|
||||
|
@ -113,6 +130,8 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
|||
}
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
if (clipping_plane_active)
|
||||
glsafe(::glDisable(GL_CLIP_PLANE0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,14 +180,21 @@ void GLGizmoFdmSupports::render_cursor_circle() const
|
|||
}
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::on_render_for_picking() const
|
||||
void GLGizmoFdmSupports::update_model_object() const
|
||||
{
|
||||
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
++idx;
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
for (int i=0; i<int(m_selected_facets[idx].size()); ++i)
|
||||
mv->m_supported_facets.set_facet(i, m_selected_facets[idx][i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::update_mesh()
|
||||
void GLGizmoFdmSupports::update_from_model_object()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
|
@ -177,7 +203,6 @@ void GLGizmoFdmSupports::update_mesh()
|
|||
for (const ModelVolume* mv : mo->volumes)
|
||||
if (mv->is_model_part())
|
||||
++num_of_volumes;
|
||||
|
||||
m_selected_facets.resize(num_of_volumes);
|
||||
m_neighbors.resize(num_of_volumes);
|
||||
m_ivas.clear();
|
||||
|
@ -218,6 +243,21 @@ void GLGizmoFdmSupports::update_mesh()
|
|||
|
||||
|
||||
|
||||
bool GLGizmoFdmSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||
{
|
||||
if (m_c->object_clipper()->get_position() == 0.)
|
||||
return false;
|
||||
|
||||
auto sel_info = m_c->selection_info();
|
||||
int active_inst = m_c->selection_info()->get_active_instance();
|
||||
const ModelInstance* mi = sel_info->model_object()->instances[active_inst];
|
||||
const Transform3d& trafo = mi->get_transformation().get_matrix();
|
||||
|
||||
Vec3d transformed_point = trafo * point;
|
||||
transformed_point(2) += sel_info->get_sla_shift();
|
||||
return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point);
|
||||
}
|
||||
|
||||
|
||||
bool operator<(const GLGizmoFdmSupports::NeighborData& a, const GLGizmoFdmSupports::NeighborData& b) {
|
||||
return a.first < b.first;
|
||||
|
@ -310,6 +350,12 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
m_clipping_plane.get(),
|
||||
&facet))
|
||||
{
|
||||
// In case this hit is clipped, skip it.
|
||||
if (is_mesh_point_clipped(hit.cast<double>())) {
|
||||
some_mesh_was_hit = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this hit the closest to the camera so far?
|
||||
double hit_squared_distance = (camera.get_position()-trafo_matrices[mesh_id]*hit.cast<double>()).squaredNorm();
|
||||
if (hit_squared_distance < closest_hit_squared_distance) {
|
||||
|
@ -430,19 +476,16 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
||||
&& m_button_down != Button::None) {
|
||||
// Take snapshot and update ModelVolume data.
|
||||
wxString action_name = shift_down
|
||||
? _L("Remove selection")
|
||||
: (m_button_down == Button::Left
|
||||
? _L("Add supports")
|
||||
: _L("Block supports"));
|
||||
Plater::TakeSnapshot(wxGetApp().plater(), action_name);
|
||||
update_model_object();
|
||||
|
||||
m_button_down = Button::None;
|
||||
|
||||
// Synchronize gizmo with ModelVolume data.
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
++idx;
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
for (int i=0; i<int(m_selected_facets[idx].size()); ++i)
|
||||
mv->m_supported_facets.set_facet(i, m_selected_facets[idx][i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -481,6 +524,46 @@ void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
|||
}
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool overwrite, bool block)
|
||||
{
|
||||
float threshold = (M_PI/180.)*threshold_deg;
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
|
||||
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++mesh_id;
|
||||
|
||||
const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
|
||||
Vec3f down = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
|
||||
Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();
|
||||
|
||||
float dot_limit = limit.dot(down);
|
||||
|
||||
// Now calculate dot product of vert_direction and facets' normals.
|
||||
int idx = -1;
|
||||
for (const stl_facet& facet : mv->mesh().stl.facet_start) {
|
||||
++idx;
|
||||
if (facet.normal.dot(down) > dot_limit && (overwrite || m_selected_facets[mesh_id][idx] == FacetSupportType::NONE))
|
||||
m_selected_facets[mesh_id][idx] = block
|
||||
? FacetSupportType::BLOCKER
|
||||
: FacetSupportType::ENFORCER;
|
||||
}
|
||||
update_vertex_buffers(mv, mesh_id, true, true);
|
||||
}
|
||||
|
||||
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||
: _L("Add supports by angle"));
|
||||
update_model_object();
|
||||
m_parent.set_as_dirty();
|
||||
m_setting_angle = false;
|
||||
}
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (! m_c->selection_info()->model_object())
|
||||
|
@ -489,96 +572,131 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||
const float approx_height = m_imgui->scaled(18.0f);
|
||||
y = std::min(y, bottom_limit - approx_height);
|
||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
|
||||
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
|
||||
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
|
||||
const float minimal_slider_width = m_imgui->scaled(4.f);
|
||||
if (! m_setting_angle) {
|
||||
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
float caption_max = 0.f;
|
||||
float total_text_max = 0.;
|
||||
for (const std::string& t : {"enforce", "block", "remove"}) {
|
||||
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x);
|
||||
total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x);
|
||||
}
|
||||
caption_max += m_imgui->scaled(1.f);
|
||||
total_text_max += m_imgui->scaled(1.f);
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
|
||||
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
|
||||
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
|
||||
const float minimal_slider_width = m_imgui->scaled(4.f);
|
||||
|
||||
float window_width = minimal_slider_width + std::max(cursor_slider_left, clipping_slider_left);
|
||||
window_width = std::max(window_width, total_text_max);
|
||||
window_width = std::max(window_width, button_width);
|
||||
float caption_max = 0.f;
|
||||
float total_text_max = 0.;
|
||||
for (const std::string& t : {"enforce", "block", "remove"}) {
|
||||
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x);
|
||||
total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x);
|
||||
}
|
||||
caption_max += m_imgui->scaled(1.f);
|
||||
total_text_max += m_imgui->scaled(1.f);
|
||||
|
||||
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
|
||||
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
|
||||
m_imgui->text(caption);
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine(caption_max);
|
||||
m_imgui->text(text);
|
||||
};
|
||||
float window_width = minimal_slider_width + std::max(cursor_slider_left, clipping_slider_left);
|
||||
window_width = std::max(window_width, total_text_max);
|
||||
window_width = std::max(window_width, button_width);
|
||||
|
||||
for (const std::string& t : {"enforce", "block", "remove"})
|
||||
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
|
||||
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
|
||||
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
|
||||
m_imgui->text(caption);
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SameLine(caption_max);
|
||||
m_imgui->text(text);
|
||||
};
|
||||
|
||||
m_imgui->text("");
|
||||
for (const std::string& t : {"enforce", "block", "remove"})
|
||||
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
|
||||
|
||||
if (m_imgui->button(m_desc.at("remove_all"))) {
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
++idx;
|
||||
if (mv->is_model_part()) {
|
||||
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
||||
mv->m_supported_facets.clear();
|
||||
update_vertex_buffers(mv, idx, true, true);
|
||||
m_parent.set_as_dirty();
|
||||
m_imgui->text("");
|
||||
|
||||
if (m_imgui->button("Autoset by angle...")) {
|
||||
m_setting_angle = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (m_imgui->button(m_desc.at("remove_all"))) {
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
++idx;
|
||||
if (mv->is_model_part()) {
|
||||
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
||||
mv->m_supported_facets.clear();
|
||||
update_vertex_buffers(mv, idx, true, true);
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
|
||||
m_imgui->text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
ImGui::SliderFloat(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
m_imgui->text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
ImGui::SliderFloat(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (m_c->object_clipper()->get_position() == 0.f)
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
else {
|
||||
if (m_imgui->button(m_desc.at("reset_direction"))) {
|
||||
wxGetApp().CallAfter([this](){
|
||||
m_c->object_clipper()->set_position(-1., false);
|
||||
});
|
||||
ImGui::Separator();
|
||||
if (m_c->object_clipper()->get_position() == 0.f)
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
else {
|
||||
if (m_imgui->button(m_desc.at("reset_direction"))) {
|
||||
wxGetApp().CallAfter([this](){
|
||||
m_c->object_clipper()->set_position(-1., false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
float clp_dist = m_c->object_clipper()->get_position();
|
||||
if (ImGui::SliderFloat(" ", &clp_dist, 0.f, 1.f, "%.2f"))
|
||||
m_c->object_clipper()->set_position(clp_dist, true);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted(_L("Ctrl + Mouse wheel").ToUTF8().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
m_imgui->end();
|
||||
if (m_setting_angle) {
|
||||
m_parent.show_slope(false);
|
||||
m_parent.set_slope_range({90.f - m_angle_threshold_deg, 90.f - m_angle_threshold_deg});
|
||||
m_parent.use_slope(true);
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
float clp_dist = m_c->object_clipper()->get_position();
|
||||
if (ImGui::SliderFloat(" ", &clp_dist, 0.f, 1.f, "%.2f"))
|
||||
m_c->object_clipper()->set_position(clp_dist, true);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted(_L("Ctrl + Mouse wheel").ToUTF8().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
else {
|
||||
std::string name = "Autoset custom supports";
|
||||
m_imgui->begin(wxString(name), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
m_imgui->text("Threshold:");
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, "%.f"))
|
||||
m_parent.set_slope_range({90.f - m_angle_threshold_deg, 90.f - m_angle_threshold_deg});
|
||||
m_imgui->checkbox(wxString("Overwrite already selected facets"), m_overwrite_selected);
|
||||
if (m_imgui->button("Enforce"))
|
||||
select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, false);
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button("Block"))
|
||||
select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, true);
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button("Cancel"))
|
||||
m_setting_angle = false;
|
||||
m_imgui->end();
|
||||
if (! m_setting_angle) {
|
||||
m_parent.use_slope(false);
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_imgui->end();
|
||||
}
|
||||
|
||||
bool GLGizmoFdmSupports::on_is_activable() const
|
||||
|
@ -627,12 +745,24 @@ void GLGizmoFdmSupports::on_set_state()
|
|||
return;
|
||||
|
||||
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned on")));
|
||||
{
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned on")));
|
||||
}
|
||||
if (! m_parent.get_gizmos_manager().is_serializing()) {
|
||||
wxGetApp().CallAfter([]() {
|
||||
wxGetApp().plater()->enter_gizmos_stack();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
||||
// we are actually shutting down
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
||||
m_old_mo = nullptr;
|
||||
m_setting_angle = false;
|
||||
m_parent.use_slope(false);
|
||||
wxGetApp().plater()->leave_gizmos_stack();
|
||||
{
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
||||
}
|
||||
m_old_mo_id = -1;
|
||||
m_ivas.clear();
|
||||
m_neighbors.clear();
|
||||
m_selected_facets.clear();
|
||||
|
@ -657,7 +787,7 @@ void GLGizmoFdmSupports::on_stop_dragging()
|
|||
|
||||
void GLGizmoFdmSupports::on_load(cereal::BinaryInputArchive& ar)
|
||||
{
|
||||
|
||||
update_from_model_object();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ enum class SLAGizmoEventType : unsigned char;
|
|||
class GLGizmoFdmSupports : public GLGizmoBase
|
||||
{
|
||||
private:
|
||||
const ModelObject* m_old_mo = nullptr;
|
||||
ObjectID m_old_mo_id;
|
||||
size_t m_old_volumes_size = 0;
|
||||
|
||||
GLUquadricObj* m_quadric;
|
||||
|
@ -53,14 +53,23 @@ public:
|
|||
private:
|
||||
bool on_init() override;
|
||||
void on_render() const override;
|
||||
void on_render_for_picking() const override;
|
||||
void on_render_for_picking() const override {}
|
||||
|
||||
void render_triangles(const Selection& selection) const;
|
||||
void render_cursor_circle() const;
|
||||
void update_mesh();
|
||||
|
||||
void update_model_object() const;
|
||||
void update_from_model_object();
|
||||
|
||||
void select_facets_by_angle(float threshold, bool overwrite, bool block);
|
||||
bool m_overwrite_selected = false;
|
||||
float m_angle_threshold_deg = 45.f;
|
||||
|
||||
bool is_mesh_point_clipped(const Vec3d& point) const;
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
bool m_setting_angle = false;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
|
|
|
@ -58,7 +58,10 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&)
|
|||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
if (mo) {
|
||||
reload_cache();
|
||||
if (m_old_mo_id != mo->id()) {
|
||||
reload_cache();
|
||||
m_old_mo_id = mo->id();
|
||||
}
|
||||
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
|
||||
m_holes_in_drilled_mesh = mo->sla_drain_holes;
|
||||
}
|
||||
|
@ -220,11 +223,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
|
|||
if (! m_c->raycaster()->raycaster())
|
||||
return false;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#else
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
Geometry::Transformation trafo = volume->get_instance_transformation();
|
||||
|
|
|
@ -43,6 +43,8 @@ private:
|
|||
void hollow_mesh(bool postpone_error_messages = false);
|
||||
bool unsaved_changes() const;
|
||||
|
||||
ObjectID m_old_mo_id = -1;
|
||||
|
||||
// bool m_show_supports = true;
|
||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||
float m_new_hole_height = 6.f;
|
||||
|
|
|
@ -66,11 +66,10 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
|
|||
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
|
||||
if (mo != m_old_mo) {
|
||||
if (mo && mo->id() != m_old_mo_id) {
|
||||
disable_editing_mode();
|
||||
if (mo)
|
||||
reload_cache();
|
||||
m_old_mo = mo;
|
||||
reload_cache();
|
||||
m_old_mo_id = mo->id();
|
||||
}
|
||||
|
||||
// If we triggered autogeneration before, check backend and fetch results if they are there
|
||||
|
|
|
@ -83,7 +83,7 @@ private:
|
|||
float m_density_stash = 0.f; // and again
|
||||
mutable std::vector<CacheEntry> m_editing_cache; // a support point and whether it is currently selected
|
||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||
const ModelObject* m_old_mo = nullptr;
|
||||
ObjectID m_old_mo_id;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
#include "GLGizmosManager.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
|
@ -371,15 +369,6 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
|
|||
|| wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
return;
|
||||
|
||||
/*m_common_gizmos_data->update_from_backend(m_parent, model_object);
|
||||
|
||||
auto* gizmo_supports = dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get());
|
||||
|
||||
|
||||
// note: sla support gizmo takes care of updating the common data.
|
||||
// following lines are thus dependent
|
||||
//gizmo_supports->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
*/
|
||||
auto* gizmo_hollow = dynamic_cast<GLGizmoHollow*>(m_gizmos[Hollow].get());
|
||||
auto* gizmo_supports = dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get());
|
||||
gizmo_hollow->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
|
@ -1076,13 +1065,8 @@ void GLGizmosManager::do_render_overlay() const
|
|||
|
||||
float cnv_w = (float)m_parent.get_canvas_size().get_width();
|
||||
float cnv_h = (float)m_parent.get_canvas_size().get_height();
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float zoom = (float)wxGetApp().plater()->get_camera().get_zoom();
|
||||
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
#else
|
||||
float zoom = (float)m_parent.get_camera().get_zoom();
|
||||
float inv_zoom = (float)m_parent.get_camera().get_inv_zoom();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
float height = get_scaled_total_height();
|
||||
float width = get_scaled_total_width();
|
||||
|
@ -1133,11 +1117,7 @@ void GLGizmosManager::do_render_overlay() const
|
|||
|
||||
GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
|
||||
if (idx == m_current) {
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
float toolbar_top = cnv_h - wxGetApp().plater()->get_view_toolbar().get_height();
|
||||
#else
|
||||
float toolbar_top = cnv_h - m_parent.get_view_toolbar_height();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top);
|
||||
}
|
||||
zoomed_top_y -= zoomed_stride_y;
|
||||
|
|
|
@ -139,6 +139,11 @@ public:
|
|||
EType new_current = m_current;
|
||||
m_current = old_current;
|
||||
|
||||
// Update common data. They should be updated when activate_gizmo is
|
||||
// called, so it can be used in on_set_state which is called from there.
|
||||
if (new_current != Undefined)
|
||||
m_common_gizmos_data->update(m_gizmos[new_current]->get_requirements());
|
||||
|
||||
// activate_gizmo call sets m_current and calls set_state for the gizmo
|
||||
// it does nothing in case the gizmo is already activated
|
||||
// it can safely be called for Undefined gizmo
|
||||
|
@ -167,6 +172,7 @@ public:
|
|||
|
||||
void refresh_on_off_state();
|
||||
void reset_all_states();
|
||||
bool is_serializing() const { return m_serializing; }
|
||||
|
||||
void set_hover_id(int id);
|
||||
void enable_grabber(EType type, unsigned int id, bool enable);
|
||||
|
@ -220,6 +226,8 @@ public:
|
|||
|
||||
void update_after_undo_redo(const UndoRedo::Snapshot& snapshot);
|
||||
|
||||
int get_selectable_icons_cnt() const { return get_selectable_idxs().size(); }
|
||||
|
||||
private:
|
||||
void render_background(float left, float top, float right, float bottom, float border) const;
|
||||
void do_render_overlay() const;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/event.h>
|
||||
|
@ -27,10 +28,22 @@
|
|||
#include "I18N.hpp"
|
||||
#include "Search.hpp"
|
||||
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#include "nanosvg/nanosvg.h"
|
||||
#include "nanosvg/nanosvgrast.h"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
static const std::map<const char, std::string> font_icons = {
|
||||
{ImGui::PrintIconMarker , "cog" },
|
||||
{ImGui::PrinterIconMarker , "printer" },
|
||||
{ImGui::PrinterSlaIconMarker, "sla_printer"},
|
||||
{ImGui::FilamentIconMarker , "spool" },
|
||||
{ImGui::MaterialIconMarker , "resin" }
|
||||
};
|
||||
|
||||
ImGuiWrapper::ImGuiWrapper()
|
||||
: m_glyph_ranges(nullptr)
|
||||
, m_font_cjk(false)
|
||||
|
@ -614,8 +627,9 @@ static void process_key_down(ImGuiKey imgui_key, std::function<void()> f)
|
|||
}
|
||||
|
||||
void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
|
||||
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel)
|
||||
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized)
|
||||
{
|
||||
int& hovered_id = view_params.hovered_id;
|
||||
// ImGui::ListBoxHeader("", size);
|
||||
{
|
||||
// rewrote part of function to add a TextInput instead of label Text
|
||||
|
@ -655,7 +669,7 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
ImGui::InputTextEx("", NULL, search_str, 20, search_size, ImGuiInputTextFlags_AutoSelectAll, NULL, NULL);
|
||||
edited = ImGui::IsItemEdited();
|
||||
if (edited)
|
||||
view_params.hovered_id = -1;
|
||||
hovered_id = 0;
|
||||
|
||||
process_key_down(ImGuiKey_Escape, [&selected, search_str, str]() {
|
||||
// use 9999 to mark selection as a Esc key
|
||||
|
@ -671,7 +685,6 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
const char* item_text;
|
||||
const char* tooltip;
|
||||
int mouse_hovered = -1;
|
||||
int& hovered_id = view_params.hovered_id;
|
||||
|
||||
while (items_getter(i, &item_text, &tooltip))
|
||||
{
|
||||
|
@ -679,7 +692,7 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("%s", /*item_text*/tooltip);
|
||||
view_params.hovered_id = -1;
|
||||
hovered_id = -1;
|
||||
mouse_hovered = i;
|
||||
}
|
||||
|
||||
|
@ -688,8 +701,6 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
i++;
|
||||
}
|
||||
|
||||
scroll_y(mouse_hovered);
|
||||
|
||||
// Process mouse wheel
|
||||
if (mouse_hovered > 0)
|
||||
process_mouse_wheel(mouse_wheel);
|
||||
|
@ -699,7 +710,7 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
if (mouse_hovered > 0)
|
||||
scroll_up();
|
||||
else {
|
||||
if (hovered_id > 0 && hovered_id != size_t(-1))
|
||||
if (hovered_id > 0)
|
||||
--hovered_id;
|
||||
scroll_y(hovered_id);
|
||||
}
|
||||
|
@ -709,9 +720,9 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
if (mouse_hovered > 0)
|
||||
scroll_down();
|
||||
else {
|
||||
if (hovered_id == size_t(-1))
|
||||
if (hovered_id < 0)
|
||||
hovered_id = 0;
|
||||
else if (hovered_id < size_t(i - 1))
|
||||
else if (hovered_id < i - 1)
|
||||
++hovered_id;
|
||||
scroll_y(hovered_id);
|
||||
}
|
||||
|
@ -735,9 +746,10 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
|||
|
||||
// add checkboxes for show/hide Categories and Groups
|
||||
text(_L("Use for search")+":");
|
||||
check_box(_L("Type"), view_params.type);
|
||||
check_box(_L("Category"), view_params.category);
|
||||
check_box(_L("Group"), view_params.group);
|
||||
if (is_localized)
|
||||
check_box(_L("Search in English"), view_params.english);
|
||||
}
|
||||
|
||||
void ImGuiWrapper::disabled_begin(bool disabled)
|
||||
|
@ -791,6 +803,59 @@ static const ImWchar ranges_keyboard_shortcuts[] =
|
|||
};
|
||||
#endif // __APPLE__
|
||||
|
||||
|
||||
std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// Note: win->GetContentScaleFactor() is not used anymore here because it tends to
|
||||
// return bogus results quite often (such as 1.0 on Retina or even 0.0).
|
||||
// We're using the max scaling factor across all screens because it's very likely to be good enough.
|
||||
double scale = mac_max_scaling_factor();
|
||||
#else
|
||||
double scale = 1.0;
|
||||
#endif
|
||||
std::vector<unsigned char> empty_vector;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
std::string folder = "white\\";
|
||||
#else
|
||||
std::string folder = "white/";
|
||||
#endif
|
||||
if (!boost::filesystem::exists(Slic3r::var(folder + bitmap_name + ".svg")))
|
||||
folder.clear();
|
||||
|
||||
NSVGimage* image = ::nsvgParseFromFile(Slic3r::var(folder + bitmap_name + ".svg").c_str(), "px", 96.0f);
|
||||
if (image == nullptr)
|
||||
return empty_vector;
|
||||
|
||||
target_height != 0 ? target_height *= scale : target_width *= scale;
|
||||
|
||||
float svg_scale = target_height != 0 ?
|
||||
(float)target_height / image->height : target_width != 0 ?
|
||||
(float)target_width / image->width : 1;
|
||||
|
||||
int width = (int)(svg_scale * image->width + 0.5f);
|
||||
int height = (int)(svg_scale * image->height + 0.5f);
|
||||
int n_pixels = width * height;
|
||||
if (n_pixels <= 0) {
|
||||
::nsvgDelete(image);
|
||||
return empty_vector;
|
||||
}
|
||||
|
||||
NSVGrasterizer* rast = ::nsvgCreateRasterizer();
|
||||
if (rast == nullptr) {
|
||||
::nsvgDelete(image);
|
||||
return empty_vector;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
::nsvgRasterize(rast, image, 0, 0, svg_scale, data.data(), width, height, width * 4);
|
||||
::nsvgDeleteRasterizer(rast);
|
||||
::nsvgDelete(image);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ImGuiWrapper::init_font(bool compress)
|
||||
{
|
||||
destroy_font();
|
||||
|
@ -829,11 +894,33 @@ void ImGuiWrapper::init_font(bool compress)
|
|||
}
|
||||
#endif
|
||||
|
||||
float font_scale = m_font_size/15;
|
||||
int icon_sz = lround(16 * font_scale); // default size of icon is 16 px
|
||||
|
||||
int rect_id = io.Fonts->CustomRects.Size; // id of the rectangle added next
|
||||
// add rectangles for the icons to the font atlas
|
||||
for (auto& icon : font_icons)
|
||||
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz);
|
||||
|
||||
// Build texture atlas
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Fill rectangles from the SVG-icons
|
||||
for (auto icon : font_icons) {
|
||||
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
|
||||
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz);
|
||||
const ImU32* pIn = (ImU32*)raw_data.data();
|
||||
for (int y = 0; y < icon_sz; y++) {
|
||||
ImU32* pOut = (ImU32*)pixels + (rect->Y + y) * width + (rect->X);
|
||||
for (int x = 0; x < icon_sz; x++)
|
||||
*pOut++ = *pIn++;
|
||||
}
|
||||
}
|
||||
rect_id++;
|
||||
}
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
|
||||
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel);
|
||||
void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
|
||||
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel);
|
||||
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized);
|
||||
|
||||
void disabled_begin(bool disabled);
|
||||
void disabled_end();
|
||||
|
@ -96,6 +96,7 @@ private:
|
|||
void render_draw_data(ImDrawData *draw_data);
|
||||
bool display_initialized() const;
|
||||
void destroy_font();
|
||||
std::vector<unsigned char> load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height);
|
||||
|
||||
static const char* clipboard_get(void* user_data);
|
||||
static void clipboard_set(void* user_data, const char* text);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <wx/menu.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <wx/glcanvas.h>
|
||||
//#include <wx/glcanvas.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
@ -28,6 +28,7 @@
|
|||
#include "RemovableDriveManager.hpp"
|
||||
#include "InstanceCheck.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include "GUI_App.hpp"
|
||||
|
@ -90,10 +91,12 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
|
||||
// initialize layout
|
||||
auto sizer = new wxBoxSizer(wxVERTICAL);
|
||||
if (m_plater)
|
||||
if (m_plater && m_layout != slOld)
|
||||
sizer->Add(m_plater, 1, wxEXPAND);
|
||||
if (m_tabpanel)
|
||||
|
||||
if (m_tabpanel && m_layout != slDlg)
|
||||
sizer->Add(m_tabpanel, 1, wxEXPAND);
|
||||
|
||||
sizer->SetSizeHints(this);
|
||||
SetSizer(sizer);
|
||||
Fit();
|
||||
|
@ -212,7 +215,6 @@ void MainFrame::shutdown()
|
|||
if (m_plater)
|
||||
m_plater->stop_jobs();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
// Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC,
|
||||
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
|
||||
// causing a crash
|
||||
|
@ -221,7 +223,6 @@ void MainFrame::shutdown()
|
|||
// Cleanup of canvases' volumes needs to be done here or a crash may happen on some Linux Debian flavours
|
||||
// see: https://github.com/prusa3d/PrusaSlicer/issues/3964
|
||||
if (m_plater) m_plater->reset_canvas_volumes();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
// Weird things happen as the Paint messages are floating around the windows being destructed.
|
||||
// Avoid the Paint messages by hiding the main window.
|
||||
|
@ -229,6 +230,9 @@ void MainFrame::shutdown()
|
|||
// In addition, there were some crashes due to the Paint events sent to already destructed windows.
|
||||
this->Show(false);
|
||||
|
||||
if (m_settings_dialog)
|
||||
m_settings_dialog->Destroy();
|
||||
|
||||
// Stop the background thread (Windows and Linux).
|
||||
// Disconnect from a 3DConnextion driver (OSX).
|
||||
m_plater->get_mouse3d_controller().shutdown();
|
||||
|
@ -244,9 +248,6 @@ void MainFrame::shutdown()
|
|||
wxGetApp().app_config->save();
|
||||
// if (m_plater)
|
||||
// m_plater->print = undef;
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
_3DScene::remove_all_canvases();
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
// Slic3r::GUI::deregister_on_request_update_callback();
|
||||
|
||||
// set to null tabs and a plater
|
||||
|
@ -289,12 +290,25 @@ void MainFrame::update_title()
|
|||
|
||||
void MainFrame::init_tabpanel()
|
||||
{
|
||||
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
|
||||
// with multiple high resolution displays connected.
|
||||
m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
|
||||
m_layout = wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? slOld :
|
||||
wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? slNew :
|
||||
wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? slDlg : slOld;
|
||||
|
||||
// From the very beginning the Print settings should be selected
|
||||
m_last_selected_tab = m_layout == slDlg ? 0 : 1;
|
||||
|
||||
if (m_layout == slDlg) {
|
||||
m_settings_dialog = new SettingsDialog(this);
|
||||
m_tabpanel = m_settings_dialog->get_tabpanel();
|
||||
}
|
||||
else {
|
||||
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
|
||||
// with multiple high resolution displays connected.
|
||||
m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
|
||||
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
#endif
|
||||
}
|
||||
|
||||
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&) {
|
||||
auto panel = m_tabpanel->GetCurrentPage();
|
||||
|
@ -307,17 +321,22 @@ void MainFrame::init_tabpanel()
|
|||
// On GTK, the wxEVT_NOTEBOOK_PAGE_CHANGED event is triggered
|
||||
// before the MainFrame is fully set up.
|
||||
static_cast<Tab*>(panel)->OnActivate();
|
||||
m_last_selected_tab = m_tabpanel->GetSelection();
|
||||
}
|
||||
else
|
||||
select_tab(0);
|
||||
});
|
||||
|
||||
//! m_plater = new Slic3r::GUI::Plater(m_tabpanel, this);
|
||||
m_plater = new Plater(this, this);
|
||||
|
||||
if (m_layout == slOld) {
|
||||
m_plater = new Plater(m_tabpanel, this);
|
||||
m_tabpanel->AddPage(m_plater, _L("Plater"));
|
||||
}
|
||||
else {
|
||||
m_plater = new Plater(this, this);
|
||||
if (m_layout == slNew)
|
||||
m_tabpanel->AddPage(new wxPanel(m_tabpanel), _L("Plater")); // empty panel just for Plater tab
|
||||
}
|
||||
wxGetApp().plater_ = m_plater;
|
||||
// m_tabpanel->AddPage(m_plater, _(L("Plater")));
|
||||
m_tabpanel->AddPage(new wxPanel(m_tabpanel), _L("Plater")); // empty panel just for Plater tab
|
||||
|
||||
wxGetApp().obj_list()->create_popup_menus();
|
||||
|
||||
|
@ -343,13 +362,6 @@ void MainFrame::init_tabpanel()
|
|||
}
|
||||
}
|
||||
|
||||
void MainFrame::switch_to(bool plater)
|
||||
{
|
||||
this->m_plater->Show(plater);
|
||||
this->m_tabpanel->Show(!plater);
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
void MainFrame::create_preset_tabs()
|
||||
{
|
||||
wxGetApp().update_label_colours_from_appconfig();
|
||||
|
@ -465,6 +477,11 @@ bool MainFrame::can_slice() const
|
|||
|
||||
bool MainFrame::can_change_view() const
|
||||
{
|
||||
if (m_layout == slNew)
|
||||
return m_plater->IsShown();
|
||||
if (m_layout == slDlg)
|
||||
return true;
|
||||
// slOld layout mode
|
||||
int page_id = m_tabpanel->GetSelection();
|
||||
return page_id != wxNOT_FOUND && dynamic_cast<const Slic3r::GUI::Plater*>(m_tabpanel->GetPage((size_t)page_id)) != nullptr;
|
||||
}
|
||||
|
@ -763,25 +780,21 @@ void MainFrame::init_menubar()
|
|||
// Window menu
|
||||
auto windowMenu = new wxMenu();
|
||||
{
|
||||
//! size_t tab_offset = 0;
|
||||
if (m_plater) {
|
||||
append_menu_item(windowMenu, wxID_HIGHEST + 1, _(L("&Plater Tab")) + "\tCtrl+1", _(L("Show the plater")),
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*(size_t)(-1)*/0); }, "plater", nullptr,
|
||||
[this](wxCommandEvent&) { select_tab(0); }, "plater", nullptr,
|
||||
[this]() {return true; }, this);
|
||||
//! tab_offset += 1;
|
||||
//! }
|
||||
//! if (tab_offset > 0) {
|
||||
windowMenu->AppendSeparator();
|
||||
}
|
||||
append_menu_item(windowMenu, wxID_HIGHEST + 2, _(L("P&rint Settings Tab")) + "\tCtrl+2", _(L("Show the print settings")),
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 0*/1); }, "cog", nullptr,
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(1); }, "cog", nullptr,
|
||||
[this]() {return true; }, this);
|
||||
wxMenuItem* item_material_tab = append_menu_item(windowMenu, wxID_HIGHEST + 3, _(L("&Filament Settings Tab")) + "\tCtrl+3", _(L("Show the filament settings")),
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 1*/2); }, "spool", nullptr,
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(2); }, "spool", nullptr,
|
||||
[this]() {return true; }, this);
|
||||
m_changeable_menu_items.push_back(item_material_tab);
|
||||
wxMenuItem* item_printer_tab = append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")),
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 2*/3); }, "printer", nullptr,
|
||||
[this/*, tab_offset*/](wxCommandEvent&) { select_tab(3); }, "printer", nullptr,
|
||||
[this]() {return true; }, this);
|
||||
m_changeable_menu_items.push_back(item_printer_tab);
|
||||
if (m_plater) {
|
||||
|
@ -1245,17 +1258,39 @@ void MainFrame::load_config(const DynamicPrintConfig& config)
|
|||
#endif
|
||||
}
|
||||
|
||||
void MainFrame::select_tab(size_t tab)
|
||||
void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
|
||||
{
|
||||
if (tab == /*(size_t)(-1)*/0) {
|
||||
if (m_plater && !m_plater->IsShown())
|
||||
this->switch_to(true);
|
||||
if (m_layout == slDlg) {
|
||||
if (tab==0) {
|
||||
if (m_settings_dialog->IsShown())
|
||||
this->SetFocus();
|
||||
// plater should be focused for correct navigation inside search window
|
||||
if (m_plater->canvas3D()->is_search_pressed())
|
||||
m_plater->SetFocus();
|
||||
return;
|
||||
}
|
||||
// Show/Activate Settings Dialog
|
||||
if (m_settings_dialog->IsShown())
|
||||
#ifdef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||
m_settings_dialog->Hide();
|
||||
#else
|
||||
m_settings_dialog->SetFocus();
|
||||
else
|
||||
#endif
|
||||
m_settings_dialog->Show();
|
||||
}
|
||||
else {
|
||||
if (m_plater && m_plater->IsShown())
|
||||
switch_to(false);
|
||||
m_tabpanel->SetSelection(tab);
|
||||
else if (m_layout == slNew) {
|
||||
m_plater->Show(tab == 0);
|
||||
m_tabpanel->Show(tab != 0);
|
||||
|
||||
// plater should be focused for correct navigation inside search window
|
||||
if (tab == 0 && m_plater->canvas3D()->is_search_pressed())
|
||||
m_plater->SetFocus();
|
||||
Layout();
|
||||
}
|
||||
|
||||
// when tab == -1, it means we should to show the last selected tab
|
||||
m_tabpanel->SetSelection(tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == slDlg && tab != 0) ? tab-1 : tab);
|
||||
}
|
||||
|
||||
// Set a camera direction, zoom to all objects.
|
||||
|
@ -1360,5 +1395,79 @@ std::string MainFrame::get_dir_name(const wxString &full_name) const
|
|||
return boost::filesystem::path(full_name.wx_str()).parent_path().string();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SettingsDialog
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SettingsDialog::SettingsDialog(MainFrame* mainframe)
|
||||
: DPIDialog(nullptr, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings")),
|
||||
m_main_frame(mainframe)
|
||||
{
|
||||
this->SetFont(wxGetApp().normal_font());
|
||||
|
||||
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
this->SetBackgroundColour(bgr_clr);
|
||||
|
||||
// Load the icon either from the exe, or from the ico file.
|
||||
#if _WIN32
|
||||
{
|
||||
TCHAR szExeFileName[MAX_PATH];
|
||||
GetModuleFileName(nullptr, szExeFileName, MAX_PATH);
|
||||
SetIcon(wxIcon(szExeFileName, wxBITMAP_TYPE_ICO));
|
||||
}
|
||||
#else
|
||||
SetIcon(wxIcon(var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
|
||||
#endif // _WIN32
|
||||
|
||||
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
|
||||
// with multiple high resolution displays connected.
|
||||
m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
|
||||
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||
m_tabpanel->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
#endif
|
||||
|
||||
m_tabpanel->Bind(wxEVT_KEY_UP, [this](wxKeyEvent& evt) {
|
||||
if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) {
|
||||
switch (evt.GetKeyCode()) {
|
||||
case '1': { m_main_frame->select_tab(0); break; }
|
||||
case '2': { m_main_frame->select_tab(1); break; }
|
||||
case '3': { m_main_frame->select_tab(2); break; }
|
||||
case '4': { m_main_frame->select_tab(3); break; }
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// initialize layout
|
||||
auto sizer = new wxBoxSizer(wxVERTICAL);
|
||||
sizer->Add(m_tabpanel, 1, wxEXPAND);
|
||||
sizer->SetSizeHints(this);
|
||||
SetSizer(sizer);
|
||||
Fit();
|
||||
|
||||
const wxSize min_size = wxSize(85 * em_unit(), 50 * em_unit());
|
||||
#ifdef __APPLE__
|
||||
// Using SetMinSize() on Mac messes up the window position in some cases
|
||||
// cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
|
||||
SetSize(min_size);
|
||||
#else
|
||||
SetMinSize(min_size);
|
||||
SetSize(GetMinSize());
|
||||
#endif
|
||||
Layout();
|
||||
}
|
||||
|
||||
void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
const int& em = em_unit();
|
||||
const wxSize& size = wxSize(85 * em, 50 * em);
|
||||
|
||||
SetMinSize(size);
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
|
|
@ -43,6 +43,23 @@ struct PresetTab {
|
|||
PrinterTechnology technology;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SettingsDialog
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class SettingsDialog : public DPIDialog
|
||||
{
|
||||
wxNotebook* m_tabpanel { nullptr };
|
||||
MainFrame* m_main_frame {nullptr };
|
||||
public:
|
||||
SettingsDialog(MainFrame* mainframe);
|
||||
~SettingsDialog() {}
|
||||
wxNotebook* get_tabpanel() { return m_tabpanel; }
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
};
|
||||
|
||||
class MainFrame : public DPIFrame
|
||||
{
|
||||
bool m_loaded {false};
|
||||
|
@ -57,6 +74,8 @@ class MainFrame : public DPIFrame
|
|||
|
||||
PrintHostQueueDialog *m_printhost_queue_dlg;
|
||||
|
||||
size_t m_last_selected_tab;
|
||||
|
||||
std::string get_base_name(const wxString &full_name, const char *extension = nullptr) const;
|
||||
std::string get_dir_name(const wxString &full_name) const;
|
||||
|
||||
|
@ -94,6 +113,12 @@ class MainFrame : public DPIFrame
|
|||
|
||||
wxFileHistory m_recent_projects;
|
||||
|
||||
enum SettingsLayout {
|
||||
slOld = 0,
|
||||
slNew,
|
||||
slDlg,
|
||||
} m_layout;
|
||||
|
||||
protected:
|
||||
virtual void on_dpi_changed(const wxRect &suggested_rect);
|
||||
|
||||
|
@ -109,7 +134,6 @@ public:
|
|||
void update_title();
|
||||
|
||||
void init_tabpanel();
|
||||
void switch_to(bool plater);
|
||||
void create_preset_tabs();
|
||||
void add_created_tab(Tab* panel);
|
||||
void init_menubar();
|
||||
|
@ -130,7 +154,9 @@ public:
|
|||
void export_configbundle();
|
||||
void load_configbundle(wxString file = wxEmptyString);
|
||||
void load_config(const DynamicPrintConfig& config);
|
||||
void select_tab(size_t tab);
|
||||
// Select tab in m_tabpanel
|
||||
// When tab == -1, will be selected last selected tab
|
||||
void select_tab(size_t tab = size_t(-1));
|
||||
void select_view(const std::string& direction);
|
||||
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
|
||||
void on_config_changed(DynamicPrintConfig* cfg) const ;
|
||||
|
@ -141,6 +167,7 @@ public:
|
|||
|
||||
Plater* m_plater { nullptr };
|
||||
wxNotebook* m_tabpanel { nullptr };
|
||||
SettingsDialog* m_settings_dialog { nullptr };
|
||||
wxProgressDialog* m_progress_dialog { nullptr };
|
||||
std::shared_ptr<ProgressStatusBar> m_statusbar;
|
||||
|
||||
|
|
|
@ -1710,10 +1710,11 @@ bool BitmapChoiceRenderer::Render(wxRect rect, wxDC* dc, int state)
|
|||
{
|
||||
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon.GetHeight()) / 2);
|
||||
xoffset = icon.GetWidth() + 4;
|
||||
|
||||
if (rect.height==0)
|
||||
rect.height= icon.GetHeight();
|
||||
}
|
||||
|
||||
if (rect.height==0)
|
||||
rect.height= icon.GetHeight();
|
||||
RenderText(m_value.GetText(), xoffset, rect, dc, state);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#include "GLCanvas3DManager.hpp"
|
||||
#include "../../slic3r/GUI/GUI.hpp"
|
||||
#include "../../slic3r/GUI/AppConfig.hpp"
|
||||
#include "../../slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "3DScene.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include <boost/log/trivial.hpp>
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
|
@ -33,20 +28,7 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager::GLInfo::GLInfo()
|
||||
: m_detected(false)
|
||||
, m_version("")
|
||||
, m_glsl_version("")
|
||||
, m_vendor("")
|
||||
, m_renderer("")
|
||||
, m_max_tex_size(0)
|
||||
, m_max_anisotropy(0.0f)
|
||||
{
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
const std::string& GLCanvas3DManager::GLInfo::get_version() const
|
||||
const std::string& OpenGLManager::GLInfo::get_version() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -54,7 +36,7 @@ const std::string& GLCanvas3DManager::GLInfo::get_version() const
|
|||
return m_version;
|
||||
}
|
||||
|
||||
const std::string& GLCanvas3DManager::GLInfo::get_glsl_version() const
|
||||
const std::string& OpenGLManager::GLInfo::get_glsl_version() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -62,7 +44,7 @@ const std::string& GLCanvas3DManager::GLInfo::get_glsl_version() const
|
|||
return m_glsl_version;
|
||||
}
|
||||
|
||||
const std::string& GLCanvas3DManager::GLInfo::get_vendor() const
|
||||
const std::string& OpenGLManager::GLInfo::get_vendor() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -70,7 +52,7 @@ const std::string& GLCanvas3DManager::GLInfo::get_vendor() const
|
|||
return m_vendor;
|
||||
}
|
||||
|
||||
const std::string& GLCanvas3DManager::GLInfo::get_renderer() const
|
||||
const std::string& OpenGLManager::GLInfo::get_renderer() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -78,7 +60,7 @@ const std::string& GLCanvas3DManager::GLInfo::get_renderer() const
|
|||
return m_renderer;
|
||||
}
|
||||
|
||||
int GLCanvas3DManager::GLInfo::get_max_tex_size() const
|
||||
int OpenGLManager::GLInfo::get_max_tex_size() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -93,7 +75,7 @@ int GLCanvas3DManager::GLInfo::get_max_tex_size() const
|
|||
#endif // __APPLE__
|
||||
}
|
||||
|
||||
float GLCanvas3DManager::GLInfo::get_max_anisotropy() const
|
||||
float OpenGLManager::GLInfo::get_max_anisotropy() const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -101,7 +83,7 @@ float GLCanvas3DManager::GLInfo::get_max_anisotropy() const
|
|||
return m_max_anisotropy;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::GLInfo::detect() const
|
||||
void OpenGLManager::GLInfo::detect() const
|
||||
{
|
||||
const char* data = (const char*)::glGetString(GL_VERSION);
|
||||
if (data != nullptr)
|
||||
|
@ -132,7 +114,7 @@ void GLCanvas3DManager::GLInfo::detect() const
|
|||
m_detected = true;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
||||
bool OpenGLManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -163,7 +145,7 @@ bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int majo
|
|||
return gl_minor >= minor;
|
||||
}
|
||||
|
||||
std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
|
||||
std::string OpenGLManager::GLInfo::to_string(bool format_as_html, bool extensions) const
|
||||
{
|
||||
if (!m_detected)
|
||||
detect();
|
||||
|
@ -203,34 +185,20 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
|
|||
return out.str();
|
||||
}
|
||||
|
||||
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
||||
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::EMultisampleState::Unknown;
|
||||
GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::EFramebufferType::Unknown;
|
||||
#else
|
||||
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
|
||||
GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
OpenGLManager::GLInfo OpenGLManager::s_gl_info;
|
||||
bool OpenGLManager::s_compressed_textures_supported = false;
|
||||
OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::EMultisampleState::Unknown;
|
||||
OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown;
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
GLCanvas3DManager::OSInfo GLCanvas3DManager::s_os_info;
|
||||
OpenGLManager::OSInfo OpenGLManager::s_os_info;
|
||||
#endif // __APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager::GLCanvas3DManager()
|
||||
: m_context(nullptr)
|
||||
, m_gl_initialized(false)
|
||||
OpenGLManager::~OpenGLManager()
|
||||
{
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
GLCanvas3DManager::~GLCanvas3DManager()
|
||||
{
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// This is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 with newer wxWidgets
|
||||
|
@ -248,116 +216,29 @@ GLCanvas3DManager::~GLCanvas3DManager()
|
|||
}
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#else
|
||||
this->destroy();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
}
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
|
||||
{
|
||||
if (canvas == nullptr)
|
||||
return false;
|
||||
|
||||
if (do_get_canvas(canvas) != m_canvases.end())
|
||||
return false;
|
||||
|
||||
GLCanvas3D* canvas3D = new GLCanvas3D(canvas, bed, camera, view_toolbar);
|
||||
if (canvas3D == nullptr)
|
||||
return false;
|
||||
|
||||
canvas3D->bind_event_handlers();
|
||||
|
||||
if (m_context == nullptr)
|
||||
{
|
||||
m_context = new wxGLContext(canvas);
|
||||
if (m_context == nullptr)
|
||||
return false;
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion();
|
||||
s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion();
|
||||
s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion();
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
}
|
||||
|
||||
canvas3D->set_context(m_context);
|
||||
|
||||
m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::remove(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = do_get_canvas(canvas);
|
||||
if (it == m_canvases.end())
|
||||
return false;
|
||||
|
||||
it->second->unbind_event_handlers();
|
||||
delete it->second;
|
||||
m_canvases.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::remove_all()
|
||||
{
|
||||
for (CanvasesMap::value_type& item : m_canvases)
|
||||
{
|
||||
item.second->unbind_event_handlers();
|
||||
delete item.second;
|
||||
}
|
||||
m_canvases.clear();
|
||||
}
|
||||
|
||||
size_t GLCanvas3DManager::count() const
|
||||
{
|
||||
return m_canvases.size();
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool GLCanvas3DManager::init_gl()
|
||||
#else
|
||||
void GLCanvas3DManager::init_gl()
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
bool OpenGLManager::init_gl()
|
||||
{
|
||||
if (!m_gl_initialized)
|
||||
{
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to init glew library";
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
glewInit();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_gl_initialized = true;
|
||||
if (GLEW_EXT_texture_compression_s3tc)
|
||||
s_compressed_textures_supported = true;
|
||||
else
|
||||
s_compressed_textures_supported = false;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (GLEW_ARB_framebuffer_object)
|
||||
s_framebuffers_type = EFramebufferType::Arb;
|
||||
else if (GLEW_EXT_framebuffer_object)
|
||||
s_framebuffers_type = EFramebufferType::Ext;
|
||||
else
|
||||
s_framebuffers_type = EFramebufferType::Unknown;
|
||||
#else
|
||||
if (GLEW_ARB_framebuffer_object)
|
||||
s_framebuffers_type = FB_Arb;
|
||||
else if (GLEW_EXT_framebuffer_object)
|
||||
s_framebuffers_type = FB_Ext;
|
||||
else
|
||||
s_framebuffers_type = FB_None;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) {
|
||||
// Complain about the OpenGL version.
|
||||
|
@ -365,22 +246,19 @@ void GLCanvas3DManager::init_gl()
|
|||
_utf8(L("PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n"
|
||||
"while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str());
|
||||
message += "\n";
|
||||
message += _(L("You may need to update your graphics card driver."));
|
||||
message += _L("You may need to update your graphics card driver.");
|
||||
#ifdef _WIN32
|
||||
message += "\n";
|
||||
message += _(L("As a workaround, you may run PrusaSlicer with a software rendered 3D graphics by running prusa-slicer.exe with the --sw_renderer parameter."));
|
||||
message += _L("As a workaround, you may run PrusaSlicer with a software rendered 3D graphics by running prusa-slicer.exe with the --sw_renderer parameter.");
|
||||
#endif
|
||||
wxMessageBox(message, wxString("PrusaSlicer - ") + _(L("Unsupported OpenGL version")), wxOK | wxICON_ERROR);
|
||||
wxMessageBox(message, wxString("PrusaSlicer - ") + _L("Unsupported OpenGL version"), wxOK | wxICON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
return true;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
wxGLContext* GLCanvas3DManager::init_glcontext(wxGLCanvas& canvas)
|
||||
wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas)
|
||||
{
|
||||
if (m_context == nullptr)
|
||||
{
|
||||
|
@ -397,48 +275,8 @@ wxGLContext* GLCanvas3DManager::init_glcontext(wxGLCanvas& canvas)
|
|||
}
|
||||
return m_context;
|
||||
}
|
||||
#else
|
||||
bool GLCanvas3DManager::init(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::const_iterator it = do_get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
return (it->second != nullptr) ? init(*it->second) : false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::destroy()
|
||||
{
|
||||
if (m_context != nullptr)
|
||||
{
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// this is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5
|
||||
// the crash is inside wxGLContext destructor
|
||||
if (s_os_info.major == 10 && s_os_info.minor == 9 && s_os_info.micro == 5)
|
||||
return;
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::const_iterator it = do_get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second : nullptr;
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow& parent)
|
||||
#else
|
||||
wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent)
|
||||
{
|
||||
int attribList[] = {
|
||||
WX_GL_RGBA,
|
||||
|
@ -456,11 +294,7 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
|
|||
0
|
||||
};
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
if (s_multisample == EMultisampleState::Unknown)
|
||||
#else
|
||||
if (s_multisample == MS_Unknown)
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
{
|
||||
detect_multisample(attribList);
|
||||
// // debug output
|
||||
|
@ -470,42 +304,14 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
|
|||
if (! can_multisample())
|
||||
attribList[12] = 0;
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
return new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
|
||||
#else
|
||||
return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
}
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas)
|
||||
{
|
||||
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
|
||||
}
|
||||
|
||||
GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas) const
|
||||
{
|
||||
return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::init(GLCanvas3D& canvas)
|
||||
{
|
||||
if (!m_gl_initialized)
|
||||
init_gl();
|
||||
|
||||
return canvas.init();
|
||||
}
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
void GLCanvas3DManager::detect_multisample(int* attribList)
|
||||
void OpenGLManager::detect_multisample(int* attribList)
|
||||
{
|
||||
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
|
||||
bool enable_multisample = wxVersion >= 30003;
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? EMultisampleState::Enabled : EMultisampleState::Disabled;
|
||||
#else
|
||||
s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
// Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows
|
||||
// s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample");
|
||||
}
|
106
src/slic3r/GUI/OpenGLManager.hpp
Normal file
106
src/slic3r/GUI/OpenGLManager.hpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#ifndef slic3r_OpenGLManager_hpp_
|
||||
#define slic3r_OpenGLManager_hpp_
|
||||
|
||||
class wxWindow;
|
||||
class wxGLCanvas;
|
||||
class wxGLContext;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class OpenGLManager
|
||||
{
|
||||
public:
|
||||
enum class EFramebufferType : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Arb,
|
||||
Ext
|
||||
};
|
||||
|
||||
class GLInfo
|
||||
{
|
||||
mutable bool m_detected{ false };
|
||||
mutable int m_max_tex_size{ 0 };
|
||||
mutable float m_max_anisotropy{ 0.0f };
|
||||
|
||||
mutable std::string m_version;
|
||||
mutable std::string m_glsl_version;
|
||||
mutable std::string m_vendor;
|
||||
mutable std::string m_renderer;
|
||||
|
||||
public:
|
||||
GLInfo() = default;
|
||||
|
||||
const std::string& get_version() const;
|
||||
const std::string& get_glsl_version() const;
|
||||
const std::string& get_vendor() const;
|
||||
const std::string& get_renderer() const;
|
||||
|
||||
int get_max_tex_size() const;
|
||||
float get_max_anisotropy() const;
|
||||
|
||||
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
|
||||
|
||||
std::string to_string(bool format_as_html, bool extensions) const;
|
||||
|
||||
private:
|
||||
void detect() const;
|
||||
};
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
struct OSInfo
|
||||
{
|
||||
int major{ 0 };
|
||||
int minor{ 0 };
|
||||
int micro{ 0 };
|
||||
};
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
private:
|
||||
enum class EMultisampleState : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Enabled,
|
||||
Disabled
|
||||
};
|
||||
|
||||
bool m_gl_initialized{ false };
|
||||
wxGLContext* m_context{ nullptr };
|
||||
static GLInfo s_gl_info;
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
static OSInfo s_os_info;
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
static bool s_compressed_textures_supported;
|
||||
static EMultisampleState s_multisample;
|
||||
static EFramebufferType s_framebuffers_type;
|
||||
|
||||
public:
|
||||
OpenGLManager() = default;
|
||||
~OpenGLManager();
|
||||
|
||||
bool init_gl();
|
||||
|
||||
wxGLContext* init_glcontext(wxGLCanvas& canvas);
|
||||
|
||||
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
||||
static bool can_multisample() { return s_multisample == EMultisampleState::Enabled; }
|
||||
static bool are_framebuffers_supported() { return (s_framebuffers_type != EFramebufferType::Unknown); }
|
||||
static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; }
|
||||
static wxGLCanvas* create_wxglcanvas(wxWindow& parent);
|
||||
static const GLInfo& get_gl_info() { return s_gl_info; }
|
||||
|
||||
private:
|
||||
static void detect_multisample(int* attribList);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_OpenGLManager_hpp_
|
|
@ -105,6 +105,7 @@ void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& fiel
|
|||
if (!m_show_modified_btns) {
|
||||
field->m_Undo_btn->set_as_hidden();
|
||||
field->m_Undo_to_sys_btn->set_as_hidden();
|
||||
field->m_blinking_bmp->Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ public:
|
|||
if (staticbox) {
|
||||
stb = new wxStaticBox(_parent, wxID_ANY, _(title));
|
||||
if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
stb->SetFont(wxGetApp().bold_font());
|
||||
stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font());
|
||||
} else
|
||||
stb = nullptr;
|
||||
sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Format/AMF.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/SLA/Hollowing.hpp"
|
||||
|
@ -77,11 +79,9 @@
|
|||
#include "RemovableDriveManager.hpp"
|
||||
#include "InstanceCheck.hpp"
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#ifdef __APPLE__
|
||||
#include "Gizmos/GLGizmosManager.hpp"
|
||||
#endif // __APPLE__
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
||||
#include "WipeTowerDialog.hpp"
|
||||
|
@ -356,10 +356,10 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
|||
if (page_id == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
wxGetApp().tab_panel()->ChangeSelection(page_id);
|
||||
wxGetApp().tab_panel()->SetSelection(page_id);
|
||||
|
||||
// Switch to Settings NotePad
|
||||
wxGetApp().mainframe->switch_to(false);
|
||||
wxGetApp().mainframe->select_tab();
|
||||
|
||||
/* In a case of a multi-material printing, for editing another Filament Preset
|
||||
* it's needed to select this preset for the "Filament settings" Tab
|
||||
|
@ -1101,9 +1101,8 @@ void Sidebar::jump_to_option(size_t selected)
|
|||
const Search::Option& opt = p->searcher.get_option(selected);
|
||||
wxGetApp().get_tab(opt.type)->activate_option(boost::nowide::narrow(opt.opt_key), boost::nowide::narrow(opt.category));
|
||||
|
||||
// Switch to the Settings NotePad, if plater is shown
|
||||
if (p->plater->IsShown())
|
||||
wxGetApp().mainframe->switch_to(false);
|
||||
// Switch to the Settings NotePad
|
||||
wxGetApp().mainframe->select_tab();
|
||||
}
|
||||
|
||||
ObjectManipulation* Sidebar::obj_manipul()
|
||||
|
@ -1530,9 +1529,10 @@ struct Plater::priv
|
|||
Slic3r::SLAPrint sla_print;
|
||||
Slic3r::Model model;
|
||||
PrinterTechnology printer_technology = ptFFF;
|
||||
Slic3r::GCodePreviewData gcode_preview_data;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Slic3r::GCodeProcessor::Result gcode_result;
|
||||
#else
|
||||
Slic3r::GCodePreviewData gcode_preview_data;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// GUI elements
|
||||
|
@ -1635,10 +1635,8 @@ struct Plater::priv
|
|||
|
||||
void set_current_canvas_as_dirty();
|
||||
GLCanvas3D* get_current_canvas3D();
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
void unbind_canvas_event_handlers();
|
||||
void reset_canvas_volumes();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
bool init_view_toolbar();
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
|
@ -1647,6 +1645,7 @@ struct Plater::priv
|
|||
|
||||
void reset_all_gizmos();
|
||||
void update_ui_from_settings();
|
||||
void update_main_toolbar_tooltips();
|
||||
std::shared_ptr<ProgressStatusBar> statusbar();
|
||||
std::string get_config(const std::string &key) const;
|
||||
BoundingBoxf bed_shape_bb() const;
|
||||
|
@ -1844,9 +1843,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
|
||||
background_process.set_fff_print(&fff_print);
|
||||
background_process.set_sla_print(&sla_print);
|
||||
background_process.set_gcode_preview_data(&gcode_preview_data);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
background_process.set_gcode_result(&gcode_result);
|
||||
#else
|
||||
background_process.set_gcode_preview_data(&gcode_preview_data);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background)
|
||||
{
|
||||
|
@ -1870,10 +1870,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
sla_print.set_status_callback(statuscb);
|
||||
this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this);
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
view3D = new View3D(q, &model, config, &background_process);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, &gcode_result, [this]() { schedule_background_process(); });
|
||||
preview = new Preview(q, &model, config, &background_process, &gcode_result, [this]() { schedule_background_process(); });
|
||||
#else
|
||||
preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, [this]() { schedule_background_process(); });
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -1882,14 +1881,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
// set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size
|
||||
view_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size);
|
||||
#endif // __APPLE__
|
||||
#else
|
||||
view3D = new View3D(q, bed, camera, view_toolbar, &model, config, &background_process);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, &gcode_result, [this]() { schedule_background_process(); });
|
||||
#else
|
||||
preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, [this]() { schedule_background_process(); });
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
panels.push_back(view3D);
|
||||
panels.push_back(preview);
|
||||
|
@ -1990,10 +1981,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
|
||||
// Drop target:
|
||||
q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership
|
||||
|
||||
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
update_ui_from_settings();
|
||||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
q->Layout();
|
||||
|
||||
set_current_panel(view3D);
|
||||
|
@ -2059,7 +2046,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
|
||||
|
||||
// collapse sidebar according to saved value
|
||||
sidebar->collapse(wxGetApp().app_config->get("collapsed_sidebar") == "1");
|
||||
bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1";
|
||||
sidebar->collapse(is_collapsed);
|
||||
// Update an enable of the collapse_toolbar: if sidebar is collapsed, then collapse_toolbar should be visible
|
||||
if (is_collapsed)
|
||||
wxGetApp().app_config->set("show_collapse_button", "1");
|
||||
}
|
||||
|
||||
Plater::priv::~priv()
|
||||
|
@ -2134,6 +2125,13 @@ void Plater::priv::update_ui_from_settings()
|
|||
preview->get_canvas3d()->update_ui_from_settings();
|
||||
}
|
||||
|
||||
// Called after the print technology was changed.
|
||||
// Update the tooltips for "Switch to Settings" button in maintoolbar
|
||||
void Plater::priv::update_main_toolbar_tooltips()
|
||||
{
|
||||
view3D->get_canvas3d()->update_tooltip_for_settings_item_in_main_toolbar();
|
||||
}
|
||||
|
||||
std::shared_ptr<ProgressStatusBar> Plater::priv::statusbar()
|
||||
{
|
||||
return main_frame->m_statusbar;
|
||||
|
@ -3801,7 +3799,6 @@ GLCanvas3D* Plater::priv::get_current_canvas3D()
|
|||
return (current_panel == view3D) ? view3D->get_canvas3d() : ((current_panel == preview) ? preview->get_canvas3d() : nullptr);
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
void Plater::priv::unbind_canvas_event_handlers()
|
||||
{
|
||||
if (view3D != nullptr)
|
||||
|
@ -3819,7 +3816,6 @@ void Plater::priv::reset_canvas_volumes()
|
|||
if (preview != nullptr)
|
||||
preview->get_canvas3d()->reset_volumes();
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
bool Plater::priv::init_view_toolbar()
|
||||
{
|
||||
|
@ -4478,8 +4474,6 @@ void Plater::increase_instances(size_t num)
|
|||
// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec));
|
||||
}
|
||||
|
||||
sidebar().obj_list()->increase_object_instances(obj_idx, was_one_instance ? num + 1 : num);
|
||||
|
||||
if (p->get_config("autocenter") == "1")
|
||||
arrange();
|
||||
|
||||
|
@ -4487,8 +4481,9 @@ void Plater::increase_instances(size_t num)
|
|||
|
||||
p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1);
|
||||
|
||||
p->selection_changed();
|
||||
sidebar().obj_list()->increase_object_instances(obj_idx, was_one_instance ? num + 1 : num);
|
||||
|
||||
p->selection_changed();
|
||||
this->p->schedule_background_process();
|
||||
}
|
||||
|
||||
|
@ -5270,7 +5265,6 @@ void Plater::set_current_canvas_as_dirty()
|
|||
p->set_current_canvas_as_dirty();
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
void Plater::unbind_canvas_event_handlers()
|
||||
{
|
||||
p->unbind_canvas_event_handlers();
|
||||
|
@ -5280,7 +5274,6 @@ void Plater::reset_canvas_volumes()
|
|||
{
|
||||
p->reset_canvas_volumes();
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
PrinterTechnology Plater::printer_technology() const
|
||||
{
|
||||
|
@ -5303,6 +5296,10 @@ void Plater::set_printer_technology(PrinterTechnology printer_technology)
|
|||
|
||||
if (wxGetApp().mainframe)
|
||||
wxGetApp().mainframe->update_menubar();
|
||||
|
||||
p->update_main_toolbar_tooltips();
|
||||
|
||||
p->sidebar->get_searcher().set_printer_technology(printer_technology);
|
||||
}
|
||||
|
||||
void Plater::changed_object(int obj_idx)
|
||||
|
@ -5391,6 +5388,9 @@ void Plater::paste_from_clipboard()
|
|||
void Plater::search(bool plater_is_active)
|
||||
{
|
||||
if (plater_is_active) {
|
||||
// plater should be focused for correct navigation inside search window
|
||||
this->SetFocus();
|
||||
|
||||
wxKeyEvent evt;
|
||||
#ifdef __APPLE__
|
||||
evt.m_keyCode = 'f';
|
||||
|
@ -5438,7 +5438,6 @@ Camera& Plater::get_camera()
|
|||
return p->camera;
|
||||
}
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Bed3D& Plater::get_bed() const
|
||||
{
|
||||
return p->bed;
|
||||
|
@ -5458,7 +5457,6 @@ GLToolbar& Plater::get_view_toolbar()
|
|||
{
|
||||
return p->view_toolbar;
|
||||
}
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void Plater::update_preview_bottom_toolbar()
|
||||
|
|
|
@ -45,10 +45,8 @@ class ObjectList;
|
|||
class GLCanvas3D;
|
||||
class Mouse3DController;
|
||||
struct Camera;
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
class Bed3D;
|
||||
class GLToolbar;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
||||
|
||||
|
@ -280,10 +278,8 @@ public:
|
|||
void find_new_position(const ModelInstancePtrs &instances, coord_t min_d);
|
||||
|
||||
void set_current_canvas_as_dirty();
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
void unbind_canvas_event_handlers();
|
||||
void reset_canvas_volumes();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
PrinterTechnology printer_technology() const;
|
||||
const DynamicPrintConfig * config() const;
|
||||
|
@ -316,13 +312,11 @@ public:
|
|||
const Camera& get_camera() const;
|
||||
Camera& get_camera();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const Bed3D& get_bed() const;
|
||||
Bed3D& get_bed();
|
||||
|
||||
const GLToolbar& get_view_toolbar() const;
|
||||
GLToolbar& get_view_toolbar();
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void update_preview_bottom_toolbar();
|
||||
|
|
|
@ -147,6 +147,13 @@ void PreferencesDialog::build()
|
|||
}
|
||||
};
|
||||
|
||||
def.label = L("Show the button for the collapse sidebar");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("If enabled, the button for the collapse sidebar will be appeared in top right corner of the 3D Scene");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("show_collapse_button") == "1" });
|
||||
option = Option(def, "show_collapse_button");
|
||||
m_optgroup_gui->append_single_option_line(option);
|
||||
|
||||
def.label = L("Use custom size for toolbar icons");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
|
||||
|
@ -157,6 +164,8 @@ void PreferencesDialog::build()
|
|||
create_icon_size_slider();
|
||||
m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1");
|
||||
|
||||
create_settings_mode_widget();
|
||||
|
||||
auto sizer = new wxBoxSizer(wxVERTICAL);
|
||||
sizer->Add(m_optgroup_general->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
|
||||
sizer->Add(m_optgroup_camera->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
|
||||
|
@ -167,7 +176,7 @@ void PreferencesDialog::build()
|
|||
auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||
wxButton* btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); });
|
||||
sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
|
||||
sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 5);
|
||||
|
||||
SetSizer(sizer);
|
||||
sizer->SetSizeHints(this);
|
||||
|
@ -179,17 +188,53 @@ void PreferencesDialog::accept()
|
|||
warning_catcher(this, wxString::Format(_(L("You need to restart %s to make the changes effective.")), SLIC3R_APP_NAME));
|
||||
}
|
||||
|
||||
auto app_config = get_app_config();
|
||||
for (std::map<std::string, std::string>::iterator it = m_values.begin(); it != m_values.end(); ++it) {
|
||||
app_config->set(it->first, it->second);
|
||||
auto app_config = get_app_config();
|
||||
|
||||
m_settings_layout_changed = false;
|
||||
for (const std::string& key : {"old_settings_layout_mode",
|
||||
"new_settings_layout_mode",
|
||||
"dlg_settings_layout_mode" })
|
||||
{
|
||||
auto it = m_values.find(key);
|
||||
if (it != m_values.end() && app_config->get(key) != it->second) {
|
||||
m_settings_layout_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
app_config->save();
|
||||
if (m_settings_layout_changed) {
|
||||
// the dialog needs to be destroyed before the call to recreate_gui()
|
||||
// or sometimes the application crashes into wxDialogBase() destructor
|
||||
// so we put it into an inner scope
|
||||
wxMessageDialog dialog(nullptr,
|
||||
_L("Switching the settings layout mode will trigger application restart.\n"
|
||||
"You will lose content of the plater.") + "\n\n" +
|
||||
_L("Do you want to proceed?"),
|
||||
wxString(SLIC3R_APP_NAME) + " - " + _L("Switching the settings layout mode"),
|
||||
wxICON_QUESTION | wxOK | wxCANCEL);
|
||||
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
{
|
||||
int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 :
|
||||
app_config->get("new_settings_layout_mode") == "1" ? 1 :
|
||||
app_config->get("dlg_settings_layout_mode") == "1" ? 2 : 0;
|
||||
|
||||
m_layout_mode_box->SetSelection(selection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::string>::iterator it = m_values.begin(); it != m_values.end(); ++it)
|
||||
app_config->set(it->first, it->second);
|
||||
|
||||
app_config->save();
|
||||
EndModal(wxID_OK);
|
||||
|
||||
// Nothify the UI to update itself from the ini file.
|
||||
wxGetApp().update_ui_from_settings();
|
||||
if (m_settings_layout_changed)
|
||||
;// application will be recreated after Preference dialog will be destroyed
|
||||
else
|
||||
// Nothify the UI to update itself from the ini file.
|
||||
wxGetApp().update_ui_from_settings();
|
||||
}
|
||||
|
||||
void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
|
@ -272,6 +317,38 @@ void PreferencesDialog::create_icon_size_slider()
|
|||
m_optgroup_gui->sizer->Add(m_icon_size_sizer, 0, wxEXPAND | wxALL, em);
|
||||
}
|
||||
|
||||
void PreferencesDialog::create_settings_mode_widget()
|
||||
{
|
||||
wxString choices[] = { _L("Old regular layout with tab bar"),
|
||||
_L("New layout without the tab bar on the platter"),
|
||||
_L("Settings will be shown in non-modal dialog") };
|
||||
|
||||
auto app_config = get_app_config();
|
||||
int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 :
|
||||
app_config->get("new_settings_layout_mode") == "1" ? 1 :
|
||||
app_config->get("dlg_settings_layout_mode") == "1" ? 2 : 0;
|
||||
|
||||
wxWindow* parent = m_optgroup_gui->ctrl_parent();
|
||||
|
||||
m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Settings layout mode"), wxDefaultPosition, wxDefaultSize, WXSIZEOF(choices), choices,
|
||||
3, wxRA_SPECIFY_ROWS);
|
||||
m_layout_mode_box->SetFont(wxGetApp().normal_font());
|
||||
m_layout_mode_box->SetSelection(selection);
|
||||
|
||||
m_layout_mode_box->Bind(wxEVT_RADIOBOX, [this](wxCommandEvent& e) {
|
||||
int selection = e.GetSelection();
|
||||
|
||||
m_values["old_settings_layout_mode"] = boost::any_cast<bool>(selection == 0) ? "1" : "0";
|
||||
m_values["new_settings_layout_mode"] = boost::any_cast<bool>(selection == 1) ? "1" : "0";
|
||||
m_values["dlg_settings_layout_mode"] = boost::any_cast<bool>(selection == 2) ? "1" : "0";
|
||||
});
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(m_layout_mode_box, 1, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND);
|
||||
}
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
|
@ -7,6 +7,8 @@
|
|||
#include <wx/dialog.h>
|
||||
#include <map>
|
||||
|
||||
class wxRadioBox;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
@ -19,11 +21,15 @@ class PreferencesDialog : public DPIDialog
|
|||
std::shared_ptr<ConfigOptionsGroup> m_optgroup_camera;
|
||||
std::shared_ptr<ConfigOptionsGroup> m_optgroup_gui;
|
||||
wxSizer* m_icon_size_sizer;
|
||||
wxRadioBox* m_layout_mode_box;
|
||||
bool isOSX {false};
|
||||
bool m_settings_layout_changed {false};
|
||||
public:
|
||||
PreferencesDialog(wxWindow* parent);
|
||||
~PreferencesDialog() {}
|
||||
|
||||
bool settings_layout_changed() { return m_settings_layout_changed; }
|
||||
|
||||
void build();
|
||||
void accept();
|
||||
|
||||
|
@ -31,6 +37,7 @@ protected:
|
|||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void layout();
|
||||
void create_icon_size_slider();
|
||||
void create_settings_mode_widget();
|
||||
};
|
||||
|
||||
} // GUI
|
||||
|
|
|
@ -125,6 +125,7 @@ public:
|
|||
TYPE_FILAMENT,
|
||||
TYPE_SLA_MATERIAL,
|
||||
TYPE_PRINTER,
|
||||
TYPE_COUNT,
|
||||
};
|
||||
|
||||
Preset(Type type, const std::string &name, bool is_default = false) : type(type), is_default(is_default), name(name) {}
|
||||
|
|
|
@ -25,41 +25,35 @@ using GUI::into_u8;
|
|||
|
||||
namespace Search {
|
||||
|
||||
static std::map<Preset::Type, std::string> NameByType = {
|
||||
{ Preset::TYPE_PRINT, L("Print") },
|
||||
{ Preset::TYPE_FILAMENT, L("Filament") },
|
||||
{ Preset::TYPE_SLA_MATERIAL, L("Material") },
|
||||
{ Preset::TYPE_SLA_PRINT, L("Print") },
|
||||
{ Preset::TYPE_PRINTER, L("Printer") }
|
||||
};
|
||||
|
||||
FMFlag Option::fuzzy_match(wchar_t const* search_pattern, int& outScore, std::vector<uint16_t> &out_matches) const
|
||||
static const std::vector<std::wstring>& NameByType()
|
||||
{
|
||||
FMFlag flag = fmUndef;
|
||||
int score;
|
||||
static std::vector<std::wstring> data;
|
||||
if (data.empty()) {
|
||||
data.assign(Preset::TYPE_COUNT, std::wstring());
|
||||
data[Preset::TYPE_PRINT ] = _L("Print" ).ToStdWstring();
|
||||
data[Preset::TYPE_FILAMENT ] = _L("Filament" ).ToStdWstring();
|
||||
data[Preset::TYPE_SLA_MATERIAL ] = _L("Material" ).ToStdWstring();
|
||||
data[Preset::TYPE_SLA_PRINT ] = _L("Print" ).ToStdWstring();
|
||||
data[Preset::TYPE_PRINTER ] = _L("Printer" ).ToStdWstring();
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
uint16_t matches[fts::max_matches + 1]; // +1 for the stopper
|
||||
auto save_matches = [&matches, &out_matches]() {
|
||||
size_t cnt = 0;
|
||||
for (; matches[cnt] != fts::stopper; ++cnt);
|
||||
out_matches.assign(matches, matches + cnt);
|
||||
};
|
||||
if (fts::fuzzy_match(search_pattern, label_local.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmLabelLocal ; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, group_local.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmGroupLocal ; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, category_local.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmCategoryLocal; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, opt_key.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmOptKey ; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, label.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmLabel ; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, group.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmGroup ; save_matches(); }
|
||||
if (fts::fuzzy_match(search_pattern, category.c_str(), score, matches) && outScore < score) {
|
||||
outScore = score; flag = fmCategory ; save_matches(); }
|
||||
|
||||
return flag;
|
||||
static char marker_by_type(Preset::Type type, PrinterTechnology pt)
|
||||
{
|
||||
switch(type) {
|
||||
case Preset::TYPE_PRINT:
|
||||
case Preset::TYPE_SLA_PRINT:
|
||||
return ImGui::PrintIconMarker;
|
||||
case Preset::TYPE_FILAMENT:
|
||||
return ImGui::FilamentIconMarker;
|
||||
case Preset::TYPE_SLA_MATERIAL:
|
||||
return ImGui::MaterialIconMarker;
|
||||
case Preset::TYPE_PRINTER:
|
||||
return pt == ptSLA ? ImGui::PrinterSlaIconMarker : ImGui::PrinterIconMarker;
|
||||
default:
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void FoundOption::get_marked_label_and_tooltip(const char** label_, const char** tooltip_) const
|
||||
|
@ -89,12 +83,16 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
|
|||
return;
|
||||
|
||||
wxString suffix;
|
||||
if (gc.category == "Machine limits")
|
||||
wxString suffix_local;
|
||||
if (gc.category == "Machine limits") {
|
||||
suffix = opt_key.back()=='1' ? L("Stealth") : L("Normal");
|
||||
suffix_local = " " + _(suffix);
|
||||
suffix = " " + suffix;
|
||||
}
|
||||
|
||||
if (!label.IsEmpty())
|
||||
options.emplace_back(Option{ boost::nowide::widen(opt_key), type,
|
||||
(label+ " " + suffix).ToStdWstring(), (_(label)+ " " + _(suffix)).ToStdWstring(),
|
||||
(label + suffix).ToStdWstring(), (_(label) + suffix_local).ToStdWstring(),
|
||||
gc.group.ToStdWstring(), _(gc.group).ToStdWstring(),
|
||||
gc.category.ToStdWstring(), _(gc.category).ToStdWstring() });
|
||||
};
|
||||
|
@ -125,17 +123,8 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
|
|||
emplace(opt_key, label);
|
||||
else
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
emplace(opt_key + "#" + std::to_string(i), label);
|
||||
|
||||
/*const GroupAndCategory& gc = groups_and_categories[opt_key];
|
||||
if (gc.group.IsEmpty() || gc.category.IsEmpty())
|
||||
continue;
|
||||
|
||||
if (!label.IsEmpty())
|
||||
options.emplace_back(Option{opt_key, type,
|
||||
label, _(label),
|
||||
gc.group, _(gc.group),
|
||||
gc.category, _(gc.category) });*/
|
||||
// ! It's very important to use "#". opt_key#n is a real option key used in GroupAndCategory
|
||||
emplace(opt_key + "#" + std::to_string(i), label);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +168,20 @@ bool OptionsSearcher::search()
|
|||
return search(search_line, true);
|
||||
}
|
||||
|
||||
static bool fuzzy_match(const std::wstring &search_pattern, const std::wstring &label, int& out_score, std::vector<uint16_t> &out_matches)
|
||||
{
|
||||
uint16_t matches[fts::max_matches + 1]; // +1 for the stopper
|
||||
int score;
|
||||
if (fts::fuzzy_match(search_pattern.c_str(), label.c_str(), score, matches)) {
|
||||
size_t cnt = 0;
|
||||
for (; matches[cnt] != fts::stopper; ++cnt);
|
||||
out_matches.assign(matches, matches + cnt);
|
||||
out_score = score;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OptionsSearcher::search(const std::string& search, bool force/* = false*/)
|
||||
{
|
||||
if (search_line == search && !force)
|
||||
|
@ -187,78 +190,97 @@ bool OptionsSearcher::search(const std::string& search, bool force/* = false*/)
|
|||
found.clear();
|
||||
|
||||
bool full_list = search.empty();
|
||||
wxString sep = " : ";
|
||||
std::wstring sep = L" : ";
|
||||
|
||||
auto get_label = [this, sep](const Option& opt)
|
||||
auto get_label = [this, &sep](const Option& opt)
|
||||
{
|
||||
wxString label;
|
||||
if (view_params.type)
|
||||
label += _(NameByType[opt.type]) + sep;
|
||||
if (view_params.category)
|
||||
label += opt.category_local + sep;
|
||||
if (view_params.group)
|
||||
label += opt.group_local + sep;
|
||||
label += opt.label_local;
|
||||
return label;
|
||||
std::wstring out;
|
||||
out += marker_by_type(opt.type, printer_technology);
|
||||
const std::wstring *prev = nullptr;
|
||||
for (const std::wstring * const s : {
|
||||
view_params.category ? &opt.category_local : nullptr,
|
||||
view_params.group ? &opt.group_local : nullptr,
|
||||
&opt.label_local })
|
||||
if (s != nullptr && (prev == nullptr || *prev != *s)) {
|
||||
// if (! out.empty())
|
||||
if (out.size()>2)
|
||||
out += sep;
|
||||
out += *s;
|
||||
prev = s;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
auto get_tooltip = [this, sep](const Option& opt)
|
||||
auto get_label_english = [this, &sep](const Option& opt)
|
||||
{
|
||||
return _(NameByType[opt.type]) + sep +
|
||||
std::wstring out;
|
||||
out += marker_by_type(opt.type, printer_technology);
|
||||
const std::wstring*prev = nullptr;
|
||||
for (const std::wstring * const s : {
|
||||
view_params.category ? &opt.category : nullptr,
|
||||
view_params.group ? &opt.group : nullptr,
|
||||
&opt.label })
|
||||
if (s != nullptr && (prev == nullptr || *prev != *s)) {
|
||||
// if (! out.empty())
|
||||
if (out.size()>2)
|
||||
out += sep;
|
||||
out += *s;
|
||||
prev = s;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
auto get_tooltip = [this, &sep](const Option& opt)
|
||||
{
|
||||
return marker_by_type(opt.type, printer_technology) +
|
||||
opt.category_local + sep +
|
||||
opt.group_local + sep + opt.label_local;
|
||||
};
|
||||
|
||||
std::vector<uint16_t> matches;
|
||||
std::vector<uint16_t> matches, matches2;
|
||||
for (size_t i=0; i < options.size(); i++)
|
||||
{
|
||||
const Option &opt = options[i];
|
||||
if (full_list) {
|
||||
std::string label = into_u8(get_label(opt));
|
||||
found.emplace_back(FoundOption{ label, label, into_u8(get_tooltip(opt)), i, fmUndef, 0 });
|
||||
found.emplace_back(FoundOption{ label, label, boost::nowide::narrow(get_tooltip(opt)), i, 0 });
|
||||
continue;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
FMFlag fuzzy_match_flag = opt.fuzzy_match(boost::nowide::widen(search).c_str(), score, matches);
|
||||
if (fuzzy_match_flag != fmUndef)
|
||||
{
|
||||
wxString label;
|
||||
|
||||
if (view_params.type)
|
||||
label += _(NameByType[opt.type]) + sep;
|
||||
if (fuzzy_match_flag == fmCategoryLocal)
|
||||
label += mark_string(opt.category_local, matches) + sep;
|
||||
else if (view_params.category)
|
||||
label += opt.category_local + sep;
|
||||
if (fuzzy_match_flag == fmGroupLocal)
|
||||
label += mark_string(opt.group_local, matches) + sep;
|
||||
else if (view_params.group)
|
||||
label += opt.group_local + sep;
|
||||
label += ((fuzzy_match_flag == fmLabelLocal) ? mark_string(opt.label_local, matches) : opt.label_local) + sep;
|
||||
|
||||
switch (fuzzy_match_flag) {
|
||||
case fmLabelLocal:
|
||||
case fmGroupLocal:
|
||||
case fmCategoryLocal:
|
||||
break;
|
||||
case fmLabel: label = get_label(opt) + "(" + mark_string(opt.label, matches) + ")"; break;
|
||||
case fmGroup: label = get_label(opt) + "(" + mark_string(opt.group, matches) + ")"; break;
|
||||
case fmCategory: label = get_label(opt) + "(" + mark_string(opt.category, matches) + ")"; break;
|
||||
case fmOptKey: label = get_label(opt) + "(" + mark_string(opt.opt_key, matches) + ")"; break;
|
||||
case fmUndef: assert(false); break;
|
||||
}
|
||||
|
||||
std::string label_plain = into_u8(label);
|
||||
boost::erase_all(label_plain, std::wstring(1, wchar_t(ImGui::ColorMarkerStart)));
|
||||
boost::erase_all(label_plain, std::wstring(1, wchar_t(ImGui::ColorMarkerEnd)));
|
||||
found.emplace_back(FoundOption{ label_plain, into_u8(label), into_u8(get_tooltip(opt)), i, fuzzy_match_flag, score });
|
||||
std::wstring wsearch = boost::nowide::widen(search);
|
||||
boost::trim_left(wsearch);
|
||||
std::wstring label = get_label(opt);
|
||||
std::wstring label_english = get_label_english(opt);
|
||||
int score = std::numeric_limits<int>::min();
|
||||
int score2;
|
||||
matches.clear();
|
||||
fuzzy_match(wsearch, label, score, matches);
|
||||
if (fuzzy_match(wsearch, opt.opt_key, score2, matches2) && score2 > score) {
|
||||
for (fts::pos_type &pos : matches2)
|
||||
pos += label.size() + 1;
|
||||
label += L"(" + opt.opt_key + L")";
|
||||
append(matches, matches2);
|
||||
score = score2;
|
||||
}
|
||||
if (view_params.english && fuzzy_match(wsearch, label_english, score2, matches2) && score2 > score) {
|
||||
label = std::move(label_english);
|
||||
matches = std::move(matches2);
|
||||
score = score2;
|
||||
}
|
||||
if (score > std::numeric_limits<int>::min()) {
|
||||
label = mark_string(label, matches);
|
||||
label += L" [" + std::to_wstring(score) + L"]";// add score value
|
||||
std::string label_u8 = into_u8(label);
|
||||
std::string label_plain = label_u8;
|
||||
boost::erase_all(label_plain, std::string(1, char(ImGui::ColorMarkerStart)));
|
||||
boost::erase_all(label_plain, std::string(1, char(ImGui::ColorMarkerEnd)));
|
||||
found.emplace_back(FoundOption{ label_plain, label_u8, boost::nowide::narrow(get_tooltip(opt)), i, score });
|
||||
}
|
||||
}
|
||||
|
||||
if (!full_list)
|
||||
sort_found();
|
||||
|
||||
|
||||
if (search_line != search)
|
||||
search_line = search;
|
||||
|
||||
|
@ -411,15 +433,17 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher)
|
|||
|
||||
wxBoxSizer* check_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
check_type = new wxCheckBox(this, wxID_ANY, _L("Type"));
|
||||
check_category = new wxCheckBox(this, wxID_ANY, _L("Category"));
|
||||
check_group = new wxCheckBox(this, wxID_ANY, _L("Group"));
|
||||
if (GUI::wxGetApp().is_localized())
|
||||
check_english = new wxCheckBox(this, wxID_ANY, _L("Search in English"));
|
||||
|
||||
wxStdDialogButtonSizer* cancel_btn = this->CreateStdDialogButtonSizer(wxCANCEL);
|
||||
|
||||
check_sizer->Add(check_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border);
|
||||
check_sizer->Add(check_category, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border);
|
||||
check_sizer->Add(check_group, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border);
|
||||
check_sizer->Add(check_group, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border);
|
||||
if (GUI::wxGetApp().is_localized())
|
||||
check_sizer->Add(check_english, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border);
|
||||
check_sizer->AddStretchSpacer(border);
|
||||
check_sizer->Add(cancel_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
|
@ -438,7 +462,8 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher)
|
|||
search_list->Bind(wxEVT_LEFT_UP, &SearchDialog::OnMouseClick, this);
|
||||
search_list->Bind(wxEVT_KEY_DOWN,&SearchDialog::OnKeyDown, this);
|
||||
|
||||
check_type ->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this);
|
||||
if (GUI::wxGetApp().is_localized())
|
||||
check_english ->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this);
|
||||
check_category->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this);
|
||||
check_group ->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this);
|
||||
|
||||
|
@ -458,9 +483,9 @@ void SearchDialog::Popup(wxPoint position /*= wxDefaultPosition*/)
|
|||
update_list();
|
||||
|
||||
const OptionViewParameters& params = searcher->view_params;
|
||||
check_type->SetValue(params.type);
|
||||
check_category->SetValue(params.category);
|
||||
check_group->SetValue(params.group);
|
||||
check_english->SetValue(params.english);
|
||||
|
||||
this->SetPosition(position);
|
||||
this->ShowModal();
|
||||
|
@ -526,7 +551,7 @@ void SearchDialog::update_list()
|
|||
|
||||
const std::vector<FoundOption>& filters = searcher->found_options();
|
||||
for (const FoundOption& item : filters)
|
||||
search_list->Append(from_u8(item.label));
|
||||
search_list->Append(from_u8(item.label).Remove(0, 1));
|
||||
}
|
||||
|
||||
void SearchDialog::OnKeyDown(wxKeyEvent& event)
|
||||
|
@ -558,7 +583,7 @@ void SearchDialog::OnKeyDown(wxKeyEvent& event)
|
|||
void SearchDialog::OnCheck(wxCommandEvent& event)
|
||||
{
|
||||
OptionViewParameters& params = searcher->view_params;
|
||||
params.type = check_type->GetValue();
|
||||
params.english = check_english->GetValue();
|
||||
params.category = check_category->GetValue();
|
||||
params.group = check_group->GetValue();
|
||||
|
||||
|
|
|
@ -36,20 +36,6 @@ struct GroupAndCategory {
|
|||
wxString category;
|
||||
};
|
||||
|
||||
// fuzzy_match flag
|
||||
// Sorted by the order of importance. The outputs will be sorted by the importance if the match value given by fuzzy_match is equal.
|
||||
enum FMFlag
|
||||
{
|
||||
fmUndef = 0, // didn't find
|
||||
fmOptKey,
|
||||
fmLabel,
|
||||
fmLabelLocal,
|
||||
fmGroup,
|
||||
fmGroupLocal,
|
||||
fmCategory,
|
||||
fmCategoryLocal
|
||||
};
|
||||
|
||||
struct Option {
|
||||
bool operator<(const Option& other) const { return other.label > this->label; }
|
||||
bool operator>(const Option& other) const { return other.label < this->label; }
|
||||
|
@ -64,8 +50,6 @@ struct Option {
|
|||
std::wstring group_local;
|
||||
std::wstring category;
|
||||
std::wstring category_local;
|
||||
|
||||
FMFlag fuzzy_match(wchar_t const *search_pattern, int &outScore, std::vector<uint16_t> &out_matches) const;
|
||||
};
|
||||
|
||||
struct FoundOption {
|
||||
|
@ -74,7 +58,6 @@ struct FoundOption {
|
|||
std::string marked_label;
|
||||
std::string tooltip;
|
||||
size_t option_idx {0};
|
||||
FMFlag category {fmUndef};
|
||||
int outScore {0};
|
||||
|
||||
// Returning pointers to contents of std::string members, to be used by ImGUI for rendering.
|
||||
|
@ -83,17 +66,18 @@ struct FoundOption {
|
|||
|
||||
struct OptionViewParameters
|
||||
{
|
||||
bool type {false};
|
||||
bool category {false};
|
||||
bool group {true };
|
||||
bool english {false};
|
||||
|
||||
int hovered_id {-1};
|
||||
int hovered_id {0};
|
||||
};
|
||||
|
||||
class OptionsSearcher
|
||||
{
|
||||
std::string search_line;
|
||||
std::map<std::string, GroupAndCategory> groups_and_categories;
|
||||
PrinterTechnology printer_technology;
|
||||
|
||||
std::vector<Option> options {};
|
||||
std::vector<FoundOption> found {};
|
||||
|
@ -106,7 +90,7 @@ class OptionsSearcher
|
|||
}
|
||||
void sort_found() {
|
||||
std::sort(found.begin(), found.end(), [](const FoundOption& f1, const FoundOption& f2) {
|
||||
return f1.outScore > f2.outScore || (f1.outScore == f2.outScore && int(f1.category) < int(f2.category)); });
|
||||
return f1.outScore > f2.outScore || (f1.outScore == f2.outScore && f1.label < f2.label); });
|
||||
};
|
||||
|
||||
size_t options_size() const { return options.size(); }
|
||||
|
@ -137,6 +121,8 @@ public:
|
|||
const std::vector<FoundOption>& found_options() { return found; }
|
||||
const GroupAndCategory& get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; }
|
||||
std::string& search_string() { return search_line; }
|
||||
|
||||
void set_printer_technology(PrinterTechnology pt) { printer_technology = pt; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -184,9 +170,9 @@ class SearchDialog : public GUI::DPIDialog
|
|||
|
||||
wxTextCtrl* search_line { nullptr };
|
||||
wxListBox* search_list { nullptr };
|
||||
wxCheckBox* check_type { nullptr };
|
||||
wxCheckBox* check_category { nullptr };
|
||||
wxCheckBox* check_group { nullptr };
|
||||
wxCheckBox* check_english { nullptr };
|
||||
|
||||
OptionsSearcher* searcher;
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include <boost/log/trivial.hpp>
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f };
|
||||
|
||||
|
@ -76,7 +79,9 @@ Selection::Selection()
|
|||
, m_mode(Instance)
|
||||
, m_type(Empty)
|
||||
, m_valid(false)
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
, m_curved_arrow(16)
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
, m_scale_factor(1.0f)
|
||||
{
|
||||
this->set_bounding_boxes_dirty();
|
||||
|
@ -104,6 +109,16 @@ void Selection::set_volumes(GLVolumePtrs* volumes)
|
|||
// Init shall be called from the OpenGL render function, so that the OpenGL context is initialized!
|
||||
bool Selection::init()
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_arrow.init_from(straight_arrow(10.0f, 5.0f, 5.0f, 10.0f, 1.0f));
|
||||
m_curved_arrow.init_from(circular_arrow(16, 10.0f, 5.0f, 10.0f, 5.0f, 1.0f));
|
||||
|
||||
if (!m_arrows_shader.init("gouraud_light.vs", "gouraud_light.fs"))
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to initialize gouraud_light shader: please, check that the files gouraud_light.vs and gouraud_light.fs are available";
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (!m_arrow.init())
|
||||
return false;
|
||||
|
||||
|
@ -113,6 +128,8 @@ bool Selection::init()
|
|||
return false;
|
||||
|
||||
m_curved_arrow.set_scale(5.0 * Vec3d::Ones());
|
||||
#endif //ENABLE_GCODE_VIEWER
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -440,11 +457,9 @@ void Selection::clear()
|
|||
update_type();
|
||||
this->set_bounding_boxes_dirty();
|
||||
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
// this happens while the application is closing
|
||||
if (wxGetApp().obj_manipul() == nullptr)
|
||||
return;
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
||||
// resets the cache in the sidebar
|
||||
wxGetApp().obj_manipul()->reset_cache();
|
||||
|
@ -1229,16 +1244,28 @@ void Selection::render_center(bool gizmo_is_dragging) const
|
|||
}
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void Selection::render_sidebar_hints(const std::string& sidebar_field) const
|
||||
#else
|
||||
void Selection::render_sidebar_hints(const std::string& sidebar_field, const Shader& shader) const
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
{
|
||||
if (sidebar_field.empty())
|
||||
return;
|
||||
|
||||
if (!boost::starts_with(sidebar_field, "layer"))
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (!m_arrows_shader.is_initialized())
|
||||
return;
|
||||
|
||||
m_arrows_shader.start_using();
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
#else
|
||||
shader.start_using();
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_LIGHTING));
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
@ -1309,8 +1336,12 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, const Sha
|
|||
|
||||
if (!boost::starts_with(sidebar_field, "layer"))
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_arrows_shader.stop_using();
|
||||
#else
|
||||
glsafe(::glDisable(GL_LIGHTING));
|
||||
shader.stop_using();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1913,6 +1944,33 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons
|
|||
|
||||
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GLint color_id = ::glGetUniformLocation(m_arrows_shader.get_shader_program_id(), "uniform_color");
|
||||
|
||||
if (boost::ends_with(sidebar_field, "x"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[0]));
|
||||
|
||||
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
|
||||
m_arrow.render();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "y"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[1]));
|
||||
|
||||
m_arrow.render();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "z"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[2]));
|
||||
|
||||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
m_arrow.render();
|
||||
}
|
||||
#else
|
||||
if (boost::ends_with(sidebar_field, "x"))
|
||||
{
|
||||
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
|
||||
|
@ -1925,10 +1983,38 @@ void Selection::render_sidebar_position_hints(const std::string& sidebar_field)
|
|||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
render_sidebar_position_hint(Z);
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GLint color_id = ::glGetUniformLocation(m_arrows_shader.get_shader_program_id(), "uniform_color");
|
||||
|
||||
if (boost::ends_with(sidebar_field, "x"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[0]));
|
||||
|
||||
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
|
||||
render_sidebar_rotation_hint(X);
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "y"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[1]));
|
||||
|
||||
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
|
||||
render_sidebar_rotation_hint(Y);
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "z"))
|
||||
{
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)AXES_COLOR[2]));
|
||||
|
||||
render_sidebar_rotation_hint(Z);
|
||||
}
|
||||
#else
|
||||
if (boost::ends_with(sidebar_field, "x"))
|
||||
{
|
||||
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
|
||||
|
@ -1941,12 +2027,14 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field)
|
|||
}
|
||||
else if (boost::ends_with(sidebar_field, "z"))
|
||||
render_sidebar_rotation_hint(Z);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const
|
||||
{
|
||||
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
|
||||
{
|
||||
glsafe(::glPushMatrix());
|
||||
|
@ -1969,6 +2057,30 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con
|
|||
render_sidebar_scale_hint(Z);
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
#else
|
||||
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
|
||||
{
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
|
||||
render_sidebar_scale_hint(X);
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
if (boost::ends_with(sidebar_field, "y") || uniform_scale)
|
||||
{
|
||||
glsafe(::glPushMatrix());
|
||||
render_sidebar_scale_hint(Y);
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
if (boost::ends_with(sidebar_field, "z") || uniform_scale)
|
||||
{
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
render_sidebar_scale_hint(Z);
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_size_hints(const std::string& sidebar_field) const
|
||||
|
@ -2048,24 +2160,34 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
|
|||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void Selection::render_sidebar_position_hint(Axis axis) const
|
||||
{
|
||||
m_arrow.set_color(AXES_COLOR[axis], 3);
|
||||
m_arrow.render();
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
void Selection::render_sidebar_rotation_hint(Axis axis) const
|
||||
{
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
m_curved_arrow.set_color(AXES_COLOR[axis], 3);
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
m_curved_arrow.render();
|
||||
|
||||
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
|
||||
m_curved_arrow.render();
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_scale_hint(Axis axis) const
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GLint color_id = ::glGetUniformLocation(m_arrows_shader.get_shader_program_id(), "uniform_color");
|
||||
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? (const GLfloat*)UNIFORM_SCALE_COLOR : (const GLfloat*)AXES_COLOR[axis]));
|
||||
#else
|
||||
m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
glsafe(::glTranslated(0.0, 5.0, 0.0));
|
||||
m_arrow.render();
|
||||
|
@ -2075,9 +2197,11 @@ void Selection::render_sidebar_scale_hint(Axis axis) const
|
|||
m_arrow.render();
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void Selection::render_sidebar_size_hint(Axis axis, double length) const
|
||||
{
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#ifndef NDEBUG
|
||||
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#include <set>
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GLModel.hpp"
|
||||
#include "GLShader.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
class GLUquadric;
|
||||
|
@ -200,8 +204,14 @@ private:
|
|||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
GLUquadricObj* m_quadric;
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GL_Model m_arrow;
|
||||
GL_Model m_curved_arrow;
|
||||
Shader m_arrows_shader;
|
||||
#else
|
||||
mutable GLArrow m_arrow;
|
||||
mutable GLCurvedArrow m_curved_arrow;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
mutable float m_scale_factor;
|
||||
|
||||
|
@ -316,7 +326,11 @@ public:
|
|||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void render_center(bool gizmo_is_dragging) const;
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void render_sidebar_hints(const std::string& sidebar_field) const;
|
||||
#else
|
||||
void render_sidebar_hints(const std::string& sidebar_field, const Shader& shader) const;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
bool requires_local_axes() const;
|
||||
|
||||
|
@ -359,10 +373,14 @@ private:
|
|||
void render_sidebar_scale_hints(const std::string& sidebar_field) const;
|
||||
void render_sidebar_size_hints(const std::string& sidebar_field) const;
|
||||
void render_sidebar_layers_hints(const std::string& sidebar_field) const;
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void render_sidebar_position_hint(Axis axis) const;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
void render_sidebar_rotation_hint(Axis axis) const;
|
||||
void render_sidebar_scale_hint(Axis axis) const;
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void render_sidebar_size_hint(Axis axis, double length) const;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
public:
|
||||
enum SyncRotationType {
|
||||
|
|
|
@ -145,11 +145,7 @@ SysInfoDialog::SysInfoDialog()
|
|||
"</font>"
|
||||
"</body>"
|
||||
"</html>", bgr_clr_str, text_clr_str, text_clr_str,
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
get_mem_info(true) + "<br>" + wxGetApp().get_gl_info(true, true));
|
||||
#else
|
||||
get_mem_info(true) + "<br>" + _3DScene::get_gl_info(true, true));
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
m_opengl_info_html->SetPage(text);
|
||||
main_sizer->Add(m_opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15);
|
||||
}
|
||||
|
@ -202,11 +198,7 @@ void SysInfoDialog::on_dpi_changed(const wxRect &suggested_rect)
|
|||
void SysInfoDialog::onCopyToClipboard(wxEvent &)
|
||||
{
|
||||
wxTheClipboard->Open();
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
const auto text = get_main_info(false) + "\n" + wxGetApp().get_gl_info(false, true);
|
||||
#else
|
||||
const auto text = get_main_info(false)+"\n"+_3DScene::get_gl_info(false, true);
|
||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
wxTheClipboard->SetData(new wxTextDataObject(text));
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace fts {
|
|||
namespace fuzzy_internal {
|
||||
static bool fuzzy_match_recursive(const char_type * pattern, const char_type * str, int & outScore, const char_type * const strBegin,
|
||||
pos_type const * srcMatches, pos_type * newMatches, int nextMatch,
|
||||
int & recursionCount, int recursionLimit);
|
||||
int recursionCount, const int recursionLimit);
|
||||
static void copy_matches(pos_type * dst, pos_type const* src);
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,8 @@ namespace fts {
|
|||
// Recursion count is input / output to track the maximum depth reached.
|
||||
// Was given by reference &recursionCount, see discussion in https://github.com/forrestthewoods/lib_fts/issues/21
|
||||
// int & recursionCount,
|
||||
int & recursionCount,
|
||||
int recursionLimit)
|
||||
int recursionCount,
|
||||
const int recursionLimit)
|
||||
{
|
||||
// Count recursions
|
||||
if (++ recursionCount >= recursionLimit)
|
||||
|
@ -183,29 +183,44 @@ namespace fts {
|
|||
// Initialize score
|
||||
outScore = 100;
|
||||
|
||||
// Start of the first group that contains matches[0].
|
||||
const char_type *group_start = strBegin + matches[0];
|
||||
for (const char_type *c = group_start; c >= strBegin && *c != ':'; -- c)
|
||||
if (*c != ' ' && *c != '\t')
|
||||
group_start = c;
|
||||
|
||||
// Apply leading letter penalty or bonus.
|
||||
outScore += matches[0] == 0 ?
|
||||
outScore += matches[0] == int(group_start - strBegin) ?
|
||||
first_letter_bonus :
|
||||
std::max(matches[0] * leading_letter_penalty, max_leading_letter_penalty);
|
||||
std::max((matches[0] - int(group_start - strBegin)) * leading_letter_penalty, max_leading_letter_penalty);
|
||||
|
||||
// Apply unmatched letters after the end penalty
|
||||
// outScore += (int(str - strBegin) - matches[nextMatch-1] + 1) * unmatched_letter_penalty;
|
||||
// outScore += (int(str - group_start) - matches[nextMatch-1] + 1) * unmatched_letter_penalty;
|
||||
// Apply unmatched penalty
|
||||
outScore += (int(str - strBegin) - nextMatch) * unmatched_letter_penalty;
|
||||
outScore += (int(str - group_start) - nextMatch) * unmatched_letter_penalty;
|
||||
|
||||
// Apply ordering bonuses
|
||||
int sequential_state = sequential_bonus;
|
||||
for (int i = 0; i < nextMatch; ++i) {
|
||||
pos_type currIdx = matches[i];
|
||||
|
||||
// Check for bonuses based on neighbor character value
|
||||
if (currIdx > 0) {
|
||||
if (i > 0 && currIdx == matches[i - 1] + 1)
|
||||
if (i > 0 && currIdx == matches[i - 1] + 1) {
|
||||
// Sequential
|
||||
outScore += sequential_bonus;
|
||||
// Camel case
|
||||
outScore += sequential_state;
|
||||
// Exponential grow of the sequential bonus.
|
||||
sequential_state = std::min(5 * sequential_bonus, sequential_state + sequential_state / 3);
|
||||
} else {
|
||||
// Reset the sequential bonus exponential grow.
|
||||
sequential_state = sequential_bonus;
|
||||
}
|
||||
char_type prev = strBegin[currIdx - 1];
|
||||
/*
|
||||
// Camel case
|
||||
if (std::islower(prev) && std::isupper(strBegin[currIdx]))
|
||||
outScore += camel_bonus;
|
||||
*/
|
||||
// Separator
|
||||
if (prev == '_' || prev == ' ')
|
||||
outScore += separator_bonus;
|
||||
|
|
|
@ -214,7 +214,7 @@ wxSize wxCheckListBoxComboPopup::GetAdjustedSize(int minWidth, int prefHeight, i
|
|||
max_width = std::max(max_width, 60 + GetTextExtent(GetString(i)).x);
|
||||
}
|
||||
size.SetWidth(max_width);
|
||||
size.SetHeight(count * GetTextExtent(GetString(0)).y);
|
||||
size.SetHeight(4 + count * (2 + GetTextExtent(GetString(0)).y));
|
||||
}
|
||||
else
|
||||
size.SetHeight(DefaultHeight);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
set(SLIC3R_APP_NAME "PrusaSlicer")
|
||||
set(SLIC3R_APP_KEY "PrusaSlicer")
|
||||
set(SLIC3R_VERSION "2.2.0")
|
||||
set(SLIC3R_VERSION "2.3.0-alpha0")
|
||||
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
|
||||
set(SLIC3R_RC_VERSION "2,2,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.2.0.0")
|
||||
set(SLIC3R_RC_VERSION "2,3,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.3.0.0")
|
||||
|
|
|
@ -15,7 +15,7 @@ REGISTER_CLASS(Filler, "Filler");
|
|||
REGISTER_CLASS(Flow, "Flow");
|
||||
REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
|
||||
REGISTER_CLASS(GCode, "GCode");
|
||||
REGISTER_CLASS(GCodePreviewData, "GCode::PreviewData");
|
||||
//REGISTER_CLASS(GCodePreviewData, "GCode::PreviewData");
|
||||
// REGISTER_CLASS(GCodeSender, "GCode::Sender");
|
||||
REGISTER_CLASS(Layer, "Layer");
|
||||
REGISTER_CLASS(SupportLayer, "Layer::Support");
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
croak("%s\n", e.what());
|
||||
}
|
||||
%};
|
||||
void do_export_w_preview(Print *print, const char *path, GCodePreviewData *preview_data)
|
||||
%code%{
|
||||
try {
|
||||
THIS->do_export(print, path, preview_data);
|
||||
} catch (std::exception& e) {
|
||||
croak("%s\n", e.what());
|
||||
}
|
||||
%};
|
||||
// void do_export_w_preview(Print *print, const char *path, GCodePreviewData *preview_data)
|
||||
// %code%{
|
||||
// try {
|
||||
// THIS->do_export(print, path, preview_data);
|
||||
// } catch (std::exception& e) {
|
||||
// croak("%s\n", e.what());
|
||||
// }
|
||||
// %};
|
||||
|
||||
Ref<Vec2d> origin()
|
||||
%code{% RETVAL = &(THIS->origin()); %};
|
||||
|
@ -60,26 +60,26 @@
|
|||
%code{% RETVAL = const_cast<StaticPrintConfig*>(static_cast<const StaticPrintConfig*>(static_cast<const PrintObjectConfig*>(&THIS->config()))); %};
|
||||
};
|
||||
|
||||
%name{Slic3r::GCode::PreviewData} class GCodePreviewData {
|
||||
GCodePreviewData();
|
||||
~GCodePreviewData();
|
||||
void reset();
|
||||
bool empty() const;
|
||||
void set_type(int type)
|
||||
%code%{
|
||||
if ((0 <= type) && (type < GCodePreviewData::Extrusion::Num_View_Types))
|
||||
THIS->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
%};
|
||||
int type() %code%{ RETVAL = (int)THIS->extrusion.view_type; %};
|
||||
void set_extrusion_flags(int flags)
|
||||
%code%{ THIS->extrusion.role_flags = (unsigned int)flags; %};
|
||||
void set_travel_visible(bool visible)
|
||||
%code%{ THIS->travel.is_visible = visible; %};
|
||||
void set_retractions_visible(bool visible)
|
||||
%code%{ THIS->retraction.is_visible = visible; %};
|
||||
void set_unretractions_visible(bool visible)
|
||||
%code%{ THIS->unretraction.is_visible = visible; %};
|
||||
void set_shells_visible(bool visible)
|
||||
%code%{ THIS->shell.is_visible = visible; %};
|
||||
void set_extrusion_paths_colors(std::vector<std::string> colors);
|
||||
};
|
||||
//%name{Slic3r::GCode::PreviewData} class GCodePreviewData {
|
||||
// GCodePreviewData();
|
||||
// ~GCodePreviewData();
|
||||
// void reset();
|
||||
// bool empty() const;
|
||||
// void set_type(int type)
|
||||
// %code%{
|
||||
// if ((0 <= type) && (type < GCodePreviewData::Extrusion::Num_View_Types))
|
||||
// THIS->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
// %};
|
||||
// int type() %code%{ RETVAL = (int)THIS->extrusion.view_type; %};
|
||||
// void set_extrusion_flags(int flags)
|
||||
// %code%{ THIS->extrusion.role_flags = (unsigned int)flags; %};
|
||||
// void set_travel_visible(bool visible)
|
||||
// %code%{ THIS->travel.is_visible = visible; %};
|
||||
// void set_retractions_visible(bool visible)
|
||||
// %code%{ THIS->retraction.is_visible = visible; %};
|
||||
// void set_unretractions_visible(bool visible)
|
||||
// %code%{ THIS->unretraction.is_visible = visible; %};
|
||||
// void set_shells_visible(bool visible)
|
||||
// %code%{ THIS->shell.is_visible = visible; %};
|
||||
// void set_extrusion_paths_colors(std::vector<std::string> colors);
|
||||
//};
|
||||
|
|
|
@ -164,7 +164,7 @@ _constant()
|
|||
|
||||
void export_gcode(char *path_template) %code%{
|
||||
try {
|
||||
THIS->export_gcode(path_template, nullptr, nullptr);
|
||||
THIS->export_gcode(path_template, nullptr);
|
||||
} catch (std::exception& e) {
|
||||
croak("%s\n", e.what());
|
||||
}
|
||||
|
|
|
@ -191,9 +191,9 @@ GCode* O_OBJECT_SLIC3R
|
|||
Ref<GCode> O_OBJECT_SLIC3R_T
|
||||
Clone<GCode> O_OBJECT_SLIC3R_T
|
||||
|
||||
GCodePreviewData* O_OBJECT_SLIC3R
|
||||
Ref<GCodePreviewData> O_OBJECT_SLIC3R_T
|
||||
Clone<GCodePreviewData> O_OBJECT_SLIC3R_T
|
||||
//GCodePreviewData* O_OBJECT_SLIC3R
|
||||
//Ref<GCodePreviewData> O_OBJECT_SLIC3R_T
|
||||
//Clone<GCodePreviewData> O_OBJECT_SLIC3R_T
|
||||
|
||||
MotionPlanner* O_OBJECT_SLIC3R
|
||||
Ref<MotionPlanner> O_OBJECT_SLIC3R_T
|
||||
|
|
|
@ -155,9 +155,9 @@
|
|||
%typemap{Ref<GCode>}{simple};
|
||||
%typemap{Clone<GCode>}{simple};
|
||||
|
||||
%typemap{GCodePreviewData*};
|
||||
%typemap{Ref<GCodePreviewData>}{simple};
|
||||
%typemap{Clone<GCodePreviewData>}{simple};
|
||||
//%typemap{GCodePreviewData*};
|
||||
//%typemap{Ref<GCodePreviewData>}{simple};
|
||||
//%typemap{Clone<GCodePreviewData>}{simple};
|
||||
|
||||
%typemap{Points};
|
||||
%typemap{Pointfs};
|
||||
|
|
Loading…
Add table
Reference in a new issue