This commit is contained in:
Vojtech Bubnik 2021-09-23 18:46:15 +02:00
commit 04e4aee246
15 changed files with 422 additions and 62 deletions

View File

@ -12,7 +12,7 @@ namespace Slic3r {
#ifdef WIN32 #ifdef WIN32
//only dll name with .dll suffix - currently case sensitive //only dll name with .dll suffix - currently case sensitive
const std::vector<std::wstring> BlacklistedLibraryCheck::blacklist({ L"NahimicOSD.dll", L"SS2OSD.dll" }); const std::vector<std::wstring> BlacklistedLibraryCheck::blacklist({ L"NahimicOSD.dll", L"SS2OSD.dll", L"amhook.dll", L"AMHook.dll" });
bool BlacklistedLibraryCheck::get_blacklisted(std::vector<std::wstring>& names) bool BlacklistedLibraryCheck::get_blacklisted(std::vector<std::wstring>& names)
{ {

View File

@ -60,6 +60,8 @@
#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) #define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2)
// Enable replacing a missing file during reload from disk command // Enable replacing a missing file during reload from disk command
#define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2) #define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2)
// Enable fixing the synchronization of seams with the horizontal slider in preview
#define ENABLE_FIX_SEAMS_SYNCH (1 && ENABLE_2_4_0_ALPHA2)
#endif // _prusaslicer_technologies_h_ #endif // _prusaslicer_technologies_h_

View File

@ -1819,7 +1819,8 @@ void Control::OnChar(wxKeyEvent& event)
void Control::OnRightDown(wxMouseEvent& event) void Control::OnRightDown(wxMouseEvent& event)
{ {
if (HasCapture()) return; if (HasCapture() || m_is_left_down)
return;
this->CaptureMouse(); this->CaptureMouse();
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this)); const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
@ -2097,7 +2098,7 @@ void Control::auto_color_change()
void Control::OnRightUp(wxMouseEvent& event) void Control::OnRightUp(wxMouseEvent& event)
{ {
if (!HasCapture()) if (!HasCapture() || m_is_left_down)
return; return;
this->ReleaseMouse(); this->ReleaseMouse();
m_is_right_down = m_is_one_layer = false; m_is_right_down = m_is_one_layer = false;

View File

@ -267,7 +267,12 @@ void GCodeViewer::SequentialView::Marker::render() const
imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Tool position") + ":"); imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Tool position") + ":");
ImGui::SameLine(); ImGui::SameLine();
char buf[1024]; char buf[1024];
sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", m_world_position(0), m_world_position(1), m_world_position(2)); #if ENABLE_FIX_SEAMS_SYNCH
const Vec3f position = m_world_position + m_world_offset;
sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", position.x(), position.y(), position.z());
#else
sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", m_world_position.x(), m_world_position.y(), m_world_position.z());
#endif // ENABLE_FIX_SEAMS_SYNCH
imgui.text(std::string(buf)); imgui.text(std::string(buf));
// force extra frame to automatically update window size // force extra frame to automatically update window size
@ -862,6 +867,9 @@ void GCodeViewer::render()
render_legend(legend_height); render_legend(legend_height);
if (m_sequential_view.current.last != m_sequential_view.endpoints.last) { if (m_sequential_view.current.last != m_sequential_view.endpoints.last) {
m_sequential_view.marker.set_world_position(m_sequential_view.current_position); m_sequential_view.marker.set_world_position(m_sequential_view.current_position);
#if ENABLE_FIX_SEAMS_SYNCH
m_sequential_view.marker.set_world_offset(m_sequential_view.current_offset);
#endif // ENABLE_FIX_SEAMS_SYNCH
m_sequential_view.render(legend_height); m_sequential_view.render(legend_height);
} }
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
@ -1500,10 +1508,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
m_max_bounding_box = m_paths_bounding_box; m_max_bounding_box = m_paths_bounding_box;
m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ());
#if ENABLE_FIX_SEAMS_SYNCH
m_sequential_view.gcode_ids.clear(); m_sequential_view.gcode_ids.clear();
for (size_t i = 0; i < gcode_result.moves.size(); ++i) {
const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
if (move.type != EMoveType::Seam)
m_sequential_view.gcode_ids.push_back(move.gcode_id);
}
#else
for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) { for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) {
m_sequential_view.gcode_ids.push_back(move.gcode_id); m_sequential_view.gcode_ids.push_back(move.gcode_id);
} }
#endif // ENABLE_FIX_SEAMS_SYNCH
std::vector<MultiVertexBuffer> vertices(m_buffers.size()); std::vector<MultiVertexBuffer> vertices(m_buffers.size());
std::vector<MultiIndexBuffer> indices(m_buffers.size()); std::vector<MultiIndexBuffer> indices(m_buffers.size());
@ -1511,11 +1527,27 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
std::vector<InstanceBuffer> instances(m_buffers.size()); std::vector<InstanceBuffer> instances(m_buffers.size());
std::vector<InstanceIdBuffer> instances_ids(m_buffers.size()); std::vector<InstanceIdBuffer> instances_ids(m_buffers.size());
#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_SEAMS_USING_MODELS
#if ENABLE_FIX_SEAMS_SYNCH
std::vector<InstancesOffsets> instances_offsets(m_buffers.size());
#endif // ENABLE_FIX_SEAMS_SYNCH
std::vector<float> options_zs; std::vector<float> options_zs;
#if ENABLE_FIX_SEAMS_SYNCH
size_t seams_count = 0;
std::vector<size_t> seams_ids;
#endif // ENABLE_FIX_SEAMS_SYNCH
// toolpaths data -> extract vertices from result // toolpaths data -> extract vertices from result
for (size_t i = 0; i < m_moves_count; ++i) { for (size_t i = 0; i < m_moves_count; ++i) {
const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i]; const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i];
#if ENABLE_FIX_SEAMS_SYNCH
if (curr.type == EMoveType::Seam) {
++seams_count;
seams_ids.push_back(i);
}
size_t move_id = i - seams_count;
#endif // ENABLE_FIX_SEAMS_SYNCH
// skip first vertex // skip first vertex
if (i == 0) if (i == 0)
@ -1538,6 +1570,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
#if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_MODELS
InstanceBuffer& inst_buffer = instances[id]; InstanceBuffer& inst_buffer = instances[id];
InstanceIdBuffer& inst_id_buffer = instances_ids[id]; InstanceIdBuffer& inst_id_buffer = instances_ids[id];
#if ENABLE_FIX_SEAMS_SYNCH
InstancesOffsets& inst_offsets = instances_offsets[id];
#endif // ENABLE_FIX_SEAMS_SYNCH
#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_SEAMS_USING_MODELS
// ensure there is at least one vertex buffer // ensure there is at least one vertex buffer
@ -1556,7 +1591,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
Path& last_path = t_buffer.paths.back(); Path& last_path = t_buffer.paths.back();
if (prev.type == curr.type && last_path.matches(curr)) if (prev.type == curr.type && last_path.matches(curr))
#if ENABLE_FIX_SEAMS_SYNCH
last_path.add_sub_path(prev, static_cast<unsigned int>(v_multibuffer.size()) - 1, 0, move_id - 1);
#else
last_path.add_sub_path(prev, static_cast<unsigned int>(v_multibuffer.size()) - 1, 0, i - 1); last_path.add_sub_path(prev, static_cast<unsigned int>(v_multibuffer.size()) - 1, 0, i - 1);
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
@ -1566,12 +1605,21 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
{ {
case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; }
case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; }
#if ENABLE_FIX_SEAMS_SYNCH
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, move_id); break; }
#else
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, i); break; } case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, i); break; }
#endif // ENABLE_FIX_SEAMS_SYNCH
#if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_MODELS
#if ENABLE_SEAMS_USING_BATCHED_MODELS #if ENABLE_SEAMS_USING_BATCHED_MODELS
case TBuffer::ERenderPrimitiveType::InstancedModel: case TBuffer::ERenderPrimitiveType::InstancedModel:
{ {
#if ENABLE_FIX_SEAMS_SYNCH
add_model_instance(curr, inst_buffer, inst_id_buffer, move_id);
inst_offsets.push_back(prev.position - curr.position);
#else
add_model_instance(curr, inst_buffer, inst_id_buffer, i); add_model_instance(curr, inst_buffer, inst_id_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.instances_count; ++m_statistics.instances_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -1579,7 +1627,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
} }
case TBuffer::ERenderPrimitiveType::BatchedModel: case TBuffer::ERenderPrimitiveType::BatchedModel:
{ {
#if ENABLE_FIX_SEAMS_SYNCH
add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, move_id);
inst_offsets.push_back(prev.position - curr.position);
#else
add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.batched_count; ++m_statistics.batched_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -1588,7 +1641,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
#else #else
case TBuffer::ERenderPrimitiveType::Model: case TBuffer::ERenderPrimitiveType::Model:
{ {
#if ENABLE_FIX_SEAMS_SYNCH
add_model_instance(curr, inst_buffer, inst_id_buffer, move_id);
#else
add_model_instance(curr, inst_buffer, inst_id_buffer, i); add_model_instance(curr, inst_buffer, inst_id_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.instances_count; ++m_statistics.instances_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -1607,7 +1664,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
} }
// smooth toolpaths corners for the given TBuffer using triangles // smooth toolpaths corners for the given TBuffer using triangles
#if ENABLE_FIX_SEAMS_SYNCH
auto smooth_triangle_toolpaths_corners = [&gcode_result, &seams_ids](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) {
#else
auto smooth_triangle_toolpaths_corners = [&gcode_result](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) { auto smooth_triangle_toolpaths_corners = [&gcode_result](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) {
#endif // ENABLE_FIX_SEAMS_SYNCH
auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) { auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) {
return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]); return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]);
}; };
@ -1681,6 +1742,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
} }
}; };
#if ENABLE_FIX_SEAMS_SYNCH
auto extract_move_id = [&seams_ids](size_t id) {
for (int i = seams_ids.size() - 1; i >= 0; --i) {
if (seams_ids[i] < id + i + 1)
return id + (size_t)i + 1;
}
return id;
};
#endif // ENABLE_FIX_SEAMS_SYNCH
size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats(); size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats();
for (const Path& path : t_buffer.paths) { for (const Path& path : t_buffer.paths) {
// the two segments of the path sharing the current vertex may belong // the two segments of the path sharing the current vertex may belong
@ -1691,9 +1762,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
const float half_width = 0.5f * path.width; const float half_width = 0.5f * path.width;
for (size_t j = 1; j < path_vertices_count - 1; ++j) { for (size_t j = 1; j < path_vertices_count - 1; ++j) {
size_t curr_s_id = path.sub_paths.front().first.s_id + j; size_t curr_s_id = path.sub_paths.front().first.s_id + j;
#if ENABLE_FIX_SEAMS_SYNCH
size_t move_id = extract_move_id(curr_s_id);
const Vec3f& prev = gcode_result.moves[move_id - 1].position;
const Vec3f& curr = gcode_result.moves[move_id].position;
const Vec3f& next = gcode_result.moves[move_id + 1].position;
#else
const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position; const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position;
const Vec3f& curr = gcode_result.moves[curr_s_id].position; const Vec3f& curr = gcode_result.moves[curr_s_id].position;
const Vec3f& next = gcode_result.moves[curr_s_id + 1].position; const Vec3f& next = gcode_result.moves[curr_s_id + 1].position;
#endif // ENABLE_FIX_SEAMS_SYNCH
// select the subpaths which contains the previous/next segments // select the subpaths which contains the previous/next segments
if (!path.sub_paths[prev_sub_path_id].contains(curr_s_id)) if (!path.sub_paths[prev_sub_path_id].contains(curr_s_id))
@ -1760,6 +1838,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
} }
} }
#if ENABLE_FIX_SEAMS_SYNCH
// dismiss, no more needed
std::vector<size_t>().swap(seams_ids);
#endif // ENABLE_FIX_SEAMS_SYNCH
for (MultiVertexBuffer& v_multibuffer : vertices) { for (MultiVertexBuffer& v_multibuffer : vertices) {
for (VertexBuffer& v_buffer : v_multibuffer) { for (VertexBuffer& v_buffer : v_multibuffer) {
v_buffer.shrink_to_fit(); v_buffer.shrink_to_fit();
@ -1784,6 +1867,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (!inst_buffer.empty()) { if (!inst_buffer.empty()) {
t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.buffer = inst_buffer;
t_buffer.model.instances.s_ids = instances_ids[i]; t_buffer.model.instances.s_ids = instances_ids[i];
#if ENABLE_FIX_SEAMS_SYNCH
t_buffer.model.instances.offsets = instances_offsets[i];
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
else { else {
@ -1792,6 +1878,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (!inst_buffer.empty()) { if (!inst_buffer.empty()) {
t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.buffer = inst_buffer;
t_buffer.model.instances.s_ids = instances_ids[i]; t_buffer.model.instances.s_ids = instances_ids[i];
#if ENABLE_FIX_SEAMS_SYNCH
t_buffer.model.instances.offsets = instances_offsets[i];
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
#else #else
@ -1800,6 +1889,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (!inst_buffer.empty()) { if (!inst_buffer.empty()) {
t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.buffer = inst_buffer;
t_buffer.model.instances.s_ids = instances_ids[i]; t_buffer.model.instances.s_ids = instances_ids[i];
#if ENABLE_FIX_SEAMS_SYNCH
t_buffer.model.instances.offsets = instances_offsets[i];
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
else { else {
@ -1860,8 +1952,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
using VboIndexList = std::vector<unsigned int>; using VboIndexList = std::vector<unsigned int>;
std::vector<VboIndexList> vbo_indices(m_buffers.size()); std::vector<VboIndexList> vbo_indices(m_buffers.size());
#if ENABLE_FIX_SEAMS_SYNCH
seams_count = 0;
#endif // ENABLE_FIX_SEAMS_SYNCH
for (size_t i = 0; i < m_moves_count; ++i) { for (size_t i = 0; i < m_moves_count; ++i) {
const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i]; const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i];
#if ENABLE_FIX_SEAMS_SYNCH
if (curr.type == EMoveType::Seam)
++seams_count;
size_t move_id = i - seams_count;
#endif // ENABLE_FIX_SEAMS_SYNCH
// skip first vertex // skip first vertex
if (i == 0) if (i == 0)
@ -1912,7 +2014,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
Path& last_path = t_buffer.paths.back(); Path& last_path = t_buffer.paths.back();
#if ENABLE_FIX_SEAMS_SYNCH
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, move_id - 1);
#else
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1); last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1);
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
@ -1937,7 +2043,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
Path& last_path = t_buffer.paths.back(); Path& last_path = t_buffer.paths.back();
#if ENABLE_FIX_SEAMS_SYNCH
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, move_id - 1);
#else
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1); last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1);
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
@ -1946,17 +2056,29 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
switch (t_buffer.render_primitive_type) switch (t_buffer.render_primitive_type)
{ {
case TBuffer::ERenderPrimitiveType::Point: { case TBuffer::ERenderPrimitiveType::Point: {
#if ENABLE_FIX_SEAMS_SYNCH
add_indices_as_point(curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
#else
add_indices_as_point(curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i); add_indices_as_point(curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); curr_vertex_buffer.second += t_buffer.max_vertices_per_segment();
break; break;
} }
case TBuffer::ERenderPrimitiveType::Line: { case TBuffer::ERenderPrimitiveType::Line: {
#if ENABLE_FIX_SEAMS_SYNCH
add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
#else
add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i); add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); curr_vertex_buffer.second += t_buffer.max_vertices_per_segment();
break; break;
} }
case TBuffer::ERenderPrimitiveType::Triangle: { case TBuffer::ERenderPrimitiveType::Triangle: {
#if ENABLE_FIX_SEAMS_SYNCH
add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
#else
add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i); add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i);
#endif // ENABLE_FIX_SEAMS_SYNCH
break; break;
} }
#if ENABLE_SEAMS_USING_BATCHED_MODELS #if ENABLE_SEAMS_USING_BATCHED_MODELS
@ -2051,16 +2173,34 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// layers zs / roles / extruder ids -> extract from result // layers zs / roles / extruder ids -> extract from result
size_t last_travel_s_id = 0; size_t last_travel_s_id = 0;
#if ENABLE_FIX_SEAMS_SYNCH
seams_count = 0;
#endif // ENABLE_FIX_SEAMS_SYNCH
for (size_t i = 0; i < m_moves_count; ++i) { for (size_t i = 0; i < m_moves_count; ++i) {
const GCodeProcessor::MoveVertex& move = gcode_result.moves[i]; const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
#if ENABLE_FIX_SEAMS_SYNCH
if (move.type == EMoveType::Seam)
++seams_count;
size_t move_id = i - seams_count;
#endif // ENABLE_FIX_SEAMS_SYNCH
if (move.type == EMoveType::Extrude) { if (move.type == EMoveType::Extrude) {
// layers zs // layers zs
const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
const double z = static_cast<double>(move.position.z()); const double z = static_cast<double>(move.position.z());
if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
#if ENABLE_FIX_SEAMS_SYNCH
m_layers.append(z, { last_travel_s_id, move_id });
#else
m_layers.append(z, { last_travel_s_id, i }); m_layers.append(z, { last_travel_s_id, i });
#endif // ENABLE_FIX_SEAMS_SYNCH
else else
#if ENABLE_FIX_SEAMS_SYNCH
m_layers.get_endpoints().back().last = move_id;
#else
m_layers.get_endpoints().back().last = i; m_layers.get_endpoints().back().last = i;
#endif // ENABLE_FIX_SEAMS_SYNCH
// extruder ids // extruder ids
m_extruder_ids.emplace_back(move.extruder_id); m_extruder_ids.emplace_back(move.extruder_id);
// roles // roles
@ -2068,10 +2208,17 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
m_roles.emplace_back(move.extrusion_role); m_roles.emplace_back(move.extrusion_role);
} }
else if (move.type == EMoveType::Travel) { else if (move.type == EMoveType::Travel) {
#if ENABLE_FIX_SEAMS_SYNCH
if (move_id - last_travel_s_id > 1 && !m_layers.empty())
m_layers.get_endpoints().back().last = move_id;
last_travel_s_id = move_id;
#else
if (i - last_travel_s_id > 1 && !m_layers.empty()) if (i - last_travel_s_id > 1 && !m_layers.empty())
m_layers.get_endpoints().back().last = i; m_layers.get_endpoints().back().last = i;
last_travel_s_id = i; last_travel_s_id = i;
#endif // ENABLE_FIX_SEAMS_SYNCH
} }
} }
@ -2342,6 +2489,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
sequential_view->current_position.x() = buffer.model.instances.buffer[offset + 0]; sequential_view->current_position.x() = buffer.model.instances.buffer[offset + 0];
sequential_view->current_position.y() = buffer.model.instances.buffer[offset + 1]; sequential_view->current_position.y() = buffer.model.instances.buffer[offset + 1];
sequential_view->current_position.z() = buffer.model.instances.buffer[offset + 2]; sequential_view->current_position.z() = buffer.model.instances.buffer[offset + 2];
#if ENABLE_FIX_SEAMS_SYNCH
sequential_view->current_offset = buffer.model.instances.offsets[i];
#endif // ENABLE_FIX_SEAMS_SYNCH
found = true; found = true;
break; break;
@ -2381,6 +2531,10 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(sequential_view->current_position.data()))); glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(sequential_view->current_position.data())));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
#if ENABLE_FIX_SEAMS_SYNCH
sequential_view->current_offset = Vec3f::Zero();
#endif // ENABLE_FIX_SEAMS_SYNCH
found = true; found = true;
break; break;
} }

View File

@ -31,6 +31,9 @@ class GCodeViewer
using InstanceBuffer = std::vector<float>; using InstanceBuffer = std::vector<float>;
using InstanceIdBuffer = std::vector<size_t>; using InstanceIdBuffer = std::vector<size_t>;
#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_SEAMS_USING_MODELS
#if ENABLE_FIX_SEAMS_SYNCH
using InstancesOffsets = std::vector<Vec3f>;
#endif // ENABLE_FIX_SEAMS_SYNCH
static const std::vector<Color> Extrusion_Role_Colors; static const std::vector<Color> Extrusion_Role_Colors;
static const std::vector<Color> Options_Colors; static const std::vector<Color> Options_Colors;
@ -151,6 +154,10 @@ class GCodeViewer
InstanceBuffer buffer; InstanceBuffer buffer;
// indices of the moves for all instances // indices of the moves for all instances
std::vector<size_t> s_ids; std::vector<size_t> s_ids;
#if ENABLE_FIX_SEAMS_SYNCH
// position offsets, used to show the correct value of the tool position
InstancesOffsets offsets;
#endif // ENABLE_FIX_SEAMS_SYNCH
Ranges render_ranges; Ranges render_ranges;
size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); }
@ -665,6 +672,12 @@ public:
GLModel m_model; GLModel m_model;
Vec3f m_world_position; Vec3f m_world_position;
Transform3f m_world_transform; Transform3f m_world_transform;
#if ENABLE_FIX_SEAMS_SYNCH
// for seams, the position of the marker is on the last endpoint of the toolpath containing it
// the offset is used to show the correct value of tool position in the "ToolPosition" window
// see implementation of render() method
Vec3f m_world_offset;
#endif // ENABLE_FIX_SEAMS_SYNCH
float m_z_offset{ 0.5f }; float m_z_offset{ 0.5f };
bool m_visible{ true }; bool m_visible{ true };
@ -674,6 +687,9 @@ public:
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); } const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
void set_world_position(const Vec3f& position); void set_world_position(const Vec3f& position);
#if ENABLE_FIX_SEAMS_SYNCH
void set_world_offset(const Vec3f& offset) { m_world_offset = offset; }
#endif // ENABLE_FIX_SEAMS_SYNCH
bool is_visible() const { return m_visible; } bool is_visible() const { return m_visible; }
void set_visible(bool visible) { m_visible = visible; } void set_visible(bool visible) { m_visible = visible; }
@ -731,6 +747,9 @@ public:
Endpoints global; Endpoints global;
#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_SEAMS_USING_MODELS
Vec3f current_position{ Vec3f::Zero() }; Vec3f current_position{ Vec3f::Zero() };
#if ENABLE_FIX_SEAMS_SYNCH
Vec3f current_offset{ Vec3f::Zero() };
#endif // ENABLE_FIX_SEAMS_SYNCH
Marker marker; Marker marker;
GCodeWindow gcode_window; GCodeWindow gcode_window;
std::vector<unsigned int> gcode_ids; std::vector<unsigned int> gcode_ids;

View File

@ -4427,12 +4427,11 @@ bool GLCanvas3D::_init_main_toolbar()
arrow_data.top = 0; arrow_data.top = 0;
arrow_data.right = 0; arrow_data.right = 0;
arrow_data.bottom = 0; arrow_data.bottom = 0;
if (!m_main_toolbar.init_arrow(arrow_data)) if (!m_main_toolbar.init_arrow(arrow_data))
{ {
BOOST_LOG_TRIVIAL(error) << "Main toolbar failed to load arrow texture."; BOOST_LOG_TRIVIAL(error) << "Main toolbar failed to load arrow texture.";
} }
// m_gizmos is created at constructor, thus we can init arrow here.
if (!m_gizmos.init_arrow(arrow_data)) if (!m_gizmos.init_arrow(arrow_data))
{ {
BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture."; BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture.";
@ -4643,6 +4642,18 @@ bool GLCanvas3D::_init_undoredo_toolbar()
return true; return true;
} }
// init arrow
BackgroundTexture::Metadata arrow_data;
arrow_data.filename = "toolbar_arrow.svg";
arrow_data.left = 0;
arrow_data.top = 0;
arrow_data.right = 0;
arrow_data.bottom = 0;
if (!m_undoredo_toolbar.init_arrow(arrow_data))
{
BOOST_LOG_TRIVIAL(error) << "Undo/Redo toolbar failed to load arrow texture.";
}
// m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Vertical); // m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Vertical);
m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Horizontal);
m_undoredo_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left); m_undoredo_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
@ -5376,6 +5387,10 @@ void GLCanvas3D::_render_undoredo_toolbar()
m_undoredo_toolbar.set_position(top, left); m_undoredo_toolbar.set_position(top, left);
m_undoredo_toolbar.render(*this); m_undoredo_toolbar.render(*this);
if (m_toolbar_highlighter.m_render_arrow)
{
m_undoredo_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item);
}
} }
void GLCanvas3D::_render_collapse_toolbar() const void GLCanvas3D::_render_collapse_toolbar() const

View File

@ -1143,6 +1143,10 @@ void GLToolbar::render_background(float left, float top, float right, float bott
void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item) void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item)
{ {
// arrow texture not initialized
if (m_arrow_texture.texture.get_id() == 0)
return;
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
float factor = inv_zoom * m_layout.scale; float factor = inv_zoom * m_layout.scale;
@ -1157,6 +1161,7 @@ void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighte
float left = m_layout.left; float left = m_layout.left;
float top = m_layout.top - icon_stride; float top = m_layout.top - icon_stride;
bool found = false;
for (const GLToolbarItem* item : m_items) { for (const GLToolbarItem* item : m_items) {
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
@ -1164,11 +1169,15 @@ void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighte
if (item->is_separator()) if (item->is_separator())
left += separator_stride; left += separator_stride;
else { else {
if (item->get_name() == highlighted_item->get_name()) if (item->get_name() == highlighted_item->get_name()) {
found = true;
break; break;
}
left += icon_stride; left += icon_stride;
} }
} }
if (!found)
return;
left += border; left += border;
top -= separator_stride; top -= separator_stride;

View File

@ -84,6 +84,9 @@ public:
if (int page_idx = evt.GetId(); page_idx >= 0) if (int page_idx = evt.GetId(); page_idx >= 0)
SetSelection(page_idx); SetSelection(page_idx);
}); });
this->Bind(wxEVT_NAVIGATION_KEY, &Notebook::OnNavigationKey, this);
return true; return true;
} }
@ -242,6 +245,89 @@ public:
GetBtnsListCtrl()->Rescale(); GetBtnsListCtrl()->Rescale();
} }
void Notebook::OnNavigationKey(wxNavigationKeyEvent& event)
{
if (event.IsWindowChange()) {
// change pages
AdvanceSelection(event.GetDirection());
}
else {
// we get this event in 3 cases
//
// a) one of our pages might have generated it because the user TABbed
// out from it in which case we should propagate the event upwards and
// our parent will take care of setting the focus to prev/next sibling
//
// or
//
// b) the parent panel wants to give the focus to us so that we
// forward it to our selected page. We can't deal with this in
// OnSetFocus() because we don't know which direction the focus came
// from in this case and so can't choose between setting the focus to
// first or last panel child
//
// or
//
// c) we ourselves (see MSWTranslateMessage) generated the event
//
wxWindow* const parent = GetParent();
// the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
const bool isFromParent = event.GetEventObject() == (wxObject*)parent;
const bool isFromSelf = event.GetEventObject() == (wxObject*)this;
const bool isForward = event.GetDirection();
if (isFromSelf && !isForward)
{
// focus is currently on notebook tab and should leave
// it backwards (Shift-TAB)
event.SetCurrentFocus(this);
parent->HandleWindowEvent(event);
}
else if (isFromParent || isFromSelf)
{
// no, it doesn't come from child, case (b) or (c): forward to a
// page but only if entering notebook page (i.e. direction is
// backwards (Shift-TAB) comething from out-of-notebook, or
// direction is forward (TAB) from ourselves),
if (m_selection != wxNOT_FOUND &&
(!event.GetDirection() || isFromSelf))
{
// so that the page knows that the event comes from it's parent
// and is being propagated downwards
event.SetEventObject(this);
wxWindow* page = m_pages[m_selection];
if (!page->HandleWindowEvent(event))
{
page->SetFocus();
}
//else: page manages focus inside it itself
}
else // otherwise set the focus to the notebook itself
{
SetFocus();
}
}
else
{
// it comes from our child, case (a), pass to the parent, but only
// if the direction is forwards. Otherwise set the focus to the
// notebook itself. The notebook is always the 'first' control of a
// page.
if (!isForward)
{
SetFocus();
}
else if (parent)
{
event.SetCurrentFocus(this);
parent->HandleWindowEvent(event);
}
}
}
}
protected: protected:
virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override
{ {

View File

@ -593,7 +593,7 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64
m_state = EState::Unknown; m_state = EState::Unknown;
init(); init();
// Timers when not fading // Timers when not fading
} else if (m_state != EState::NotFading && m_state != EState::FadingOut && get_duration() != 0 && !paused) { } else if (m_state != EState::NotFading && m_state != EState::FadingOut && m_state != EState::ClosePending && m_state != EState::Finished && get_duration() != 0 && !paused) {
int64_t up_time = now - m_notification_start; int64_t up_time = now - m_notification_start;
if (up_time >= get_duration() * 1000) { if (up_time >= get_duration() * 1000) {
m_state = EState::FadingOut; m_state = EState::FadingOut;
@ -633,6 +633,10 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64
//---------------ExportFinishedNotification----------- //---------------ExportFinishedNotification-----------
void NotificationManager::ExportFinishedNotification::count_spaces() void NotificationManager::ExportFinishedNotification::count_spaces()
{ {
if (m_eject_pending)
{
return PopNotification::count_spaces();
}
//determine line width //determine line width
m_line_height = ImGui::CalcTextSize("A").y; m_line_height = ImGui::CalcTextSize("A").y;
@ -650,7 +654,10 @@ void NotificationManager::ExportFinishedNotification::count_spaces()
void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
if (m_eject_pending)
{
return PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
float x_offset = m_left_indentation; float x_offset = m_left_indentation;
std::string fulltext = m_text1 + m_hypertext; //+ m_text2; std::string fulltext = m_text1 + m_hypertext; //+ m_text2;
// Lines are always at least two and m_multiline is always true for ExportFinishedNotification. // Lines are always at least two and m_multiline is always true for ExportFinishedNotification.
@ -669,7 +676,7 @@ void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper&
ImGui::SetCursorPosY(starting_y + i * shift_y); ImGui::SetCursorPosY(starting_y + i * shift_y);
imgui.text(line.c_str()); imgui.text(line.c_str());
//hyperlink text //hyperlink text
if ( i == 0 ) { if ( i == 0 && !m_eject_pending) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize(line.c_str()).x + ImGui::CalcTextSize(" ").x, starting_y, _u8L("Open Folder.")); render_hypertext(imgui, x_offset + ImGui::CalcTextSize(line.c_str()).x + ImGui::CalcTextSize(" ").x, starting_y, _u8L("Open Folder."));
} }
} }
@ -680,7 +687,7 @@ void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper&
void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
PopNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); PopNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
if(m_to_removable) if(m_to_removable && ! m_eject_pending)
render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} }
@ -725,7 +732,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
assert(m_evt_handler != nullptr); assert(m_evt_handler != nullptr);
if (m_evt_handler != nullptr) if (m_evt_handler != nullptr)
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
close(); on_eject_click();
} }
//invisible large button //invisible large button
@ -736,7 +743,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
assert(m_evt_handler != nullptr); assert(m_evt_handler != nullptr);
if (m_evt_handler != nullptr) if (m_evt_handler != nullptr)
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
close(); on_eject_click();
} }
ImGui::PopStyleColor(5); ImGui::PopStyleColor(5);
} }
@ -745,6 +752,14 @@ bool NotificationManager::ExportFinishedNotification::on_text_click()
open_folder(m_export_dir_path); open_folder(m_export_dir_path);
return false; return false;
} }
void NotificationManager::ExportFinishedNotification::on_eject_click()
{
NotificationData data{ get_data().type, get_data().level , 0, _utf8("Ejecting.") };
m_eject_pending = true;
m_multiline = false;
update(data);
}
//------ProgressBar---------------- //------ProgressBar----------------
void NotificationManager::ProgressBarNotification::init() void NotificationManager::ProgressBarNotification::init()
{ {
@ -1071,7 +1086,7 @@ void NotificationManager::UpdatedItemsInfoNotification::render_left_sign(ImGuiWr
imgui.text(text.c_str()); imgui.text(text.c_str());
} }
//------SlicingProgressNotificastion //------SlicingProgressNotification
void NotificationManager::SlicingProgressNotification::init() void NotificationManager::SlicingProgressNotification::init()
{ {
if (m_sp_state == SlicingProgressState::SP_PROGRESS) { if (m_sp_state == SlicingProgressState::SP_PROGRESS) {
@ -1084,46 +1099,53 @@ void NotificationManager::SlicingProgressNotification::init()
} }
} }
void NotificationManager::SlicingProgressNotification::set_progress_state(float percent) bool NotificationManager::SlicingProgressNotification::set_progress_state(float percent)
{ {
if (percent < 0.f) if (percent < 0.f)
set_progress_state(SlicingProgressState::SP_CANCELLED); return true;//set_progress_state(SlicingProgressState::SP_CANCELLED);
else if (percent >= 1.f) else if (percent >= 1.f)
set_progress_state(SlicingProgressState::SP_COMPLETED); return set_progress_state(SlicingProgressState::SP_COMPLETED);
else else
set_progress_state(SlicingProgressState::SP_PROGRESS, percent); return set_progress_state(SlicingProgressState::SP_PROGRESS, percent);
} }
void NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/) bool NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/)
{ {
switch (state) switch (state)
{ {
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING: case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING:
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_BEGAN:
m_state = EState::Hidden; m_state = EState::Hidden;
set_percentage(-1); set_percentage(-1);
m_has_print_info = false; m_has_print_info = false;
set_export_possible(false); set_export_possible(false);
break; m_sp_state = state;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS: case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
if ((m_sp_state != SlicingProgressState::SP_BEGAN && m_sp_state != SlicingProgressState::SP_PROGRESS) || percent < m_percentage)
return false;
set_percentage(percent); set_percentage(percent);
m_has_cancel_button = true; m_has_cancel_button = true;
break; m_sp_state = state;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED: case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED:
set_percentage(-1); set_percentage(-1);
m_has_cancel_button = false; m_has_cancel_button = false;
m_has_print_info = false; m_has_print_info = false;
set_export_possible(false); set_export_possible(false);
break; m_sp_state = state;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED: case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
set_percentage(1); set_percentage(1);
m_has_cancel_button = false; m_has_cancel_button = false;
m_has_print_info = false; m_has_print_info = false;
// m_export_possible is important only for PROGRESS state, thus we can reset it here // m_export_possible is important only for SP_PROGRESS state, thus we can reset it here
set_export_possible(false); set_export_possible(false);
break; m_sp_state = state;
return true;
default: default:
break; break;
} }
m_sp_state = state; return false;
} }
void NotificationManager::SlicingProgressNotification::set_status_text(const std::string& text) void NotificationManager::SlicingProgressNotification::set_status_text(const std::string& text)
{ {
@ -1150,7 +1172,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std
{ {
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slicing finished."), m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") }; NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slicing finished."), m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") };
update(data); update(data);
m_state = EState::Shown; m_state = EState::NotFading;
} }
break; break;
default: default:
@ -1170,7 +1192,7 @@ void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(boo
{ {
m_sidebar_collapsed = collapsed; m_sidebar_collapsed = collapsed;
if (m_sp_state == SlicingProgressState::SP_COMPLETED) if (m_sp_state == SlicingProgressState::SP_COMPLETED)
m_state = EState::Shown; m_state = EState::NotFading;
} }
void NotificationManager::SlicingProgressNotification::on_cancel_button() void NotificationManager::SlicingProgressNotification::on_cancel_button()
@ -1184,9 +1206,9 @@ void NotificationManager::SlicingProgressNotification::on_cancel_button()
int NotificationManager::SlicingProgressNotification::get_duration() int NotificationManager::SlicingProgressNotification::get_duration()
{ {
if (m_sp_state == SlicingProgressState::SP_CANCELLED) if (m_sp_state == SlicingProgressState::SP_CANCELLED)
return 10; return 2;
else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed) else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)
return 5; return 0;
else else
return 0; return 0;
} }
@ -1200,7 +1222,7 @@ bool NotificationManager::SlicingProgressNotification::update_state(bool paused
} }
void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
if (m_sp_state == SlicingProgressState::SP_PROGRESS || (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)) { if (m_sp_state == SlicingProgressState::SP_PROGRESS /*|| (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)*/) {
ProgressBarNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); ProgressBarNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
/* // enable for hypertext during slicing (correct call of export_enabled needed) /* // enable for hypertext during slicing (correct call of export_enabled needed)
if (m_multiline) { if (m_multiline) {
@ -1235,7 +1257,7 @@ void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper&
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} }
*/ */
} else if (m_sp_state == SlicingProgressState::SP_COMPLETED) { } else if (m_sp_state == SlicingProgressState::SP_COMPLETED && m_sidebar_collapsed) {
// "Slicing Finished" on line 1 + hypertext, print info on line // "Slicing Finished" on line 1 + hypertext, print info on line
ImVec2 win_size(win_size_x, win_size_y); ImVec2 win_size(win_size_x, win_size_y);
ImVec2 text1_size = ImGui::CalcTextSize(m_text1.c_str()); ImVec2 text1_size = ImGui::CalcTextSize(m_text1.c_str());
@ -1260,21 +1282,18 @@ void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper&
PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} }
} }
void NotificationManager::SlicingProgressNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::SlicingProgressNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
if (!(m_sp_state == SlicingProgressState::SP_PROGRESS || (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed))) { if (m_sp_state != SlicingProgressState::SP_PROGRESS) {
return; return;
} }
//std::string text;
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
/* }
std::stringstream stream; void NotificationManager::SlicingProgressNotification::render_hypertext(ImGuiWrapper& imgui,const float text_x, const float text_y, const std::string text, bool more)
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%"; {
text = stream.str(); if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)
ImGui::SetCursorPosX(m_left_indentation); return;
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4)); ProgressBarNotification::render_hypertext(imgui, text_x, text_y, text, more);
imgui.text(text.c_str());
*/
} }
void NotificationManager::SlicingProgressNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::SlicingProgressNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
@ -1360,7 +1379,7 @@ void NotificationManager::ProgressIndicatorNotification::init()
m_state = EState::NotFading; m_state = EState::NotFading;
break; break;
case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_COMPLETED: case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_COMPLETED:
m_state = EState::Shown; m_state = EState::ClosePending;
break; break;
default: default:
break; break;
@ -1374,7 +1393,7 @@ void NotificationManager::ProgressIndicatorNotification::set_percentage(float pe
m_has_cancel_button = true; m_has_cancel_button = true;
m_progress_state = ProgressIndicatorState::PIS_PROGRESS_REQUEST; m_progress_state = ProgressIndicatorState::PIS_PROGRESS_REQUEST;
} else if (percent >= 1.0f) { } else if (percent >= 1.0f) {
m_state = EState::Shown; m_state = EState::FadingOut;
m_progress_state = ProgressIndicatorState::PIS_COMPLETED; m_progress_state = ProgressIndicatorState::PIS_COMPLETED;
m_has_cancel_button = false; m_has_cancel_button = false;
} else { } else {
@ -1388,6 +1407,7 @@ bool NotificationManager::ProgressIndicatorNotification::update_state(bool pause
// percentage was changed (and it called schedule_extra_frame), now update must know this needs render // percentage was changed (and it called schedule_extra_frame), now update must know this needs render
m_next_render = 0; m_next_render = 0;
m_progress_state = ProgressIndicatorState::PIS_PROGRESS_UPDATED; m_progress_state = ProgressIndicatorState::PIS_PROGRESS_UPDATED;
m_current_fade_opacity = 1.0f;
return true; return true;
} }
bool ret = ProgressBarNotification::update_state(paused, delta); bool ret = ProgressBarNotification::update_state(paused, delta);
@ -1628,6 +1648,7 @@ void NotificationManager::push_exporting_finished_notification(const std::string
close_notification_of_type(NotificationType::ExportFinished); close_notification_of_type(NotificationType::ExportFinished);
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotificationLevel, on_removable ? 0 : 20, _u8L("Exporting finished.") + "\n" + path }; NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotificationLevel, on_removable ? 0 : 20, _u8L("Exporting finished.") + "\n" + path };
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0); push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
set_slicing_progress_hidden();
} }
void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage) void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage)
@ -1700,12 +1721,39 @@ void NotificationManager::init_slicing_progress_notification(std::function<bool(
}; };
push_notification_data(std::make_unique<NotificationManager::SlicingProgressNotification>(data, m_id_provider, m_evt_handler, cancel_callback), 0); push_notification_data(std::make_unique<NotificationManager::SlicingProgressNotification>(data, m_id_provider, m_evt_handler, cancel_callback), 0);
} }
void NotificationManager::set_slicing_progress_began()
{
for (std::unique_ptr<PopNotification> & notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get());
spn->set_progress_state(SlicingProgressNotification::SlicingProgressState::SP_BEGAN);
return;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager();
}
void NotificationManager::set_slicing_progress_percentage(const std::string& text, float percentage) void NotificationManager::set_slicing_progress_percentage(const std::string& text, float percentage)
{ {
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) { for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) { if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get()); SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get());
spn->set_progress_state(percentage); if(spn->set_progress_state(percentage)) {
spn->set_status_text(text);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
}
return;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager();
}
void NotificationManager::set_slicing_progress_canceled(const std::string& text)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get());
spn->set_progress_state(SlicingProgressNotification::SlicingProgressState::SP_CANCELLED);
spn->set_status_text(text); spn->set_status_text(text);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return; return;
@ -1714,7 +1762,6 @@ void NotificationManager::set_slicing_progress_percentage(const std::string& tex
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended // Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager(); wxGetApp().plater()->init_notification_manager();
} }
void NotificationManager::set_slicing_progress_hidden() void NotificationManager::set_slicing_progress_hidden()
{ {
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) { for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
@ -1772,7 +1819,7 @@ void NotificationManager::init_progress_indicator()
return; return;
} }
} }
NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 2}; NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 1};
auto notification = std::make_unique<NotificationManager::ProgressIndicatorNotification>(data, m_id_provider, m_evt_handler); auto notification = std::make_unique<NotificationManager::ProgressIndicatorNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0); push_notification_data(std::move(notification), 0);
} }

View File

@ -189,8 +189,10 @@ public:
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
// slicing progress // slicing progress
void init_slicing_progress_notification(std::function<bool()> cancel_callback); void init_slicing_progress_notification(std::function<bool()> cancel_callback);
void set_slicing_progress_began();
// percentage negative = canceled, <0-1) = progress, 1 = completed // percentage negative = canceled, <0-1) = progress, 1 = completed
void set_slicing_progress_percentage(const std::string& text, float percentage); void set_slicing_progress_percentage(const std::string& text, float percentage);
void set_slicing_progress_canceled(const std::string& text);
// hides slicing progress notification imidietly // hides slicing progress notification imidietly
void set_slicing_progress_hidden(); void set_slicing_progress_hidden();
// Add a print time estimate to an existing SlicingProgress notification. Set said notification to SP_COMPLETED state. // Add a print time estimate to an existing SlicingProgress notification. Set said notification to SP_COMPLETED state.
@ -492,6 +494,7 @@ private:
enum class SlicingProgressState enum class SlicingProgressState
{ {
SP_NO_SLICING, // hidden SP_NO_SLICING, // hidden
SP_BEGAN, // still hidden but allows to go to SP_PROGRESS state. This prevents showing progress after slicing was canceled.
SP_PROGRESS, // never fades outs, no close button, has cancel button SP_PROGRESS, // never fades outs, no close button, has cancel button
SP_CANCELLED, // fades after 10 seconds, simple message SP_CANCELLED, // fades after 10 seconds, simple message
SP_COMPLETED // Has export hyperlink and print info, fades after 20 sec if sidebar is shown, otherwise no fade out SP_COMPLETED // Has export hyperlink and print info, fades after 20 sec if sidebar is shown, otherwise no fade out
@ -509,10 +512,10 @@ private:
// sets cancel button callback // sets cancel button callback
void set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; } void set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; }
bool has_cancel_callback() const { return m_cancel_callback != nullptr; } bool has_cancel_callback() const { return m_cancel_callback != nullptr; }
// sets SlicingProgressState, negative percent means canceled // sets SlicingProgressState, negative percent means canceled, returns true if state was set succesfully.
void set_progress_state(float percent); bool set_progress_state(float percent);
// sets SlicingProgressState, percent is used only at progress state. // sets SlicingProgressState, percent is used only at progress state. Returns true if state was set succesfully.
void set_progress_state(SlicingProgressState state,float percent = 0.f); bool set_progress_state(SlicingProgressState state,float percent = 0.f);
// sets additional string of print info and puts notification into Completed state. // sets additional string of print info and puts notification into Completed state.
void set_print_info(const std::string& info); void set_print_info(const std::string& info);
// sets fading if in Completed state. // sets fading if in Completed state.
@ -541,8 +544,12 @@ private:
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
void render_close_button(ImGuiWrapper& imgui, void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
void render_hypertext(ImGuiWrapper& imgui,
const float text_x, const float text_y,
const std::string text,
bool more = false) override ;
void on_cancel_button(); void on_cancel_button();
int get_duration() override; int get_duration() override;
// if returns false, process was already canceled // if returns false, process was already canceled
@ -626,8 +633,10 @@ private:
void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override
{ m_minimize_b_visible = false; } { m_minimize_b_visible = false; }
bool on_text_click() override; bool on_text_click() override;
void on_eject_click();
// local time of last hover for showing tooltip // local time of last hover for showing tooltip
long m_hover_time { 0 }; long m_hover_time { 0 };
bool m_eject_pending { false };
}; };
class UpdatedItemsInfoNotification : public PopNotification class UpdatedItemsInfoNotification : public PopNotification

View File

@ -1920,6 +1920,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this);
sidebar->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); }); sidebar->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); });
sidebar->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); }); sidebar->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
// jump to found option from SearchDialog
q->Bind(wxCUSTOMEVT_JUMP_TO_OPTION, [this](wxCommandEvent& evt) { sidebar->jump_to_option(evt.GetInt()); });
} }
wxGLCanvas* view3D_canvas = view3D->get_wxglcanvas(); wxGLCanvas* view3D_canvas = view3D->get_wxglcanvas();
@ -3102,6 +3104,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 || // if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
// (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 ) // (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
// this->statusbar()->set_status_text(_L("Ready to slice")); // this->statusbar()->set_status_text(_L("Ready to slice"));
if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
(return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
notification_manager->set_slicing_progress_hidden();
sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export)); sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export));
sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send)); sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send));
@ -3961,6 +3966,7 @@ void Plater::priv::on_slicing_began()
clear_warnings(); clear_warnings();
notification_manager->close_notification_of_type(NotificationType::SignDetected); notification_manager->close_notification_of_type(NotificationType::SignDetected);
notification_manager->close_notification_of_type(NotificationType::ExportFinished); notification_manager->close_notification_of_type(NotificationType::ExportFinished);
notification_manager->set_slicing_progress_began();
} }
void Plater::priv::add_warning(const Slic3r::PrintStateBase::Warning& warning, size_t oid) void Plater::priv::add_warning(const Slic3r::PrintStateBase::Warning& warning, size_t oid)
{ {
@ -4058,7 +4064,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
} }
if (evt.cancelled()) { if (evt.cancelled()) {
// this->statusbar()->set_status_text(_L("Cancelled")); // this->statusbar()->set_status_text(_L("Cancelled"));
this->notification_manager->set_slicing_progress_percentage(_utf8("Slicing Cancelled."), -1); this->notification_manager->set_slicing_progress_canceled(_utf8("Slicing Cancelled."));
} }
this->sidebar->show_sliced_info_sizer(evt.success()); this->sidebar->show_sliced_info_sizer(evt.success());
@ -6373,6 +6379,7 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology)
p->sidebar->get_searcher().set_printer_technology(printer_technology); p->sidebar->get_searcher().set_printer_technology(printer_technology);
p->notification_manager->set_fff(printer_technology == ptFFF); p->notification_manager->set_fff(printer_technology == ptFFF);
p->notification_manager->set_slicing_progress_hidden();
return ret; return ret;
} }

View File

@ -24,6 +24,8 @@ using boost::optional;
namespace Slic3r { namespace Slic3r {
wxDEFINE_EVENT(wxCUSTOMEVT_JUMP_TO_OPTION, wxCommandEvent);
using GUI::from_u8; using GUI::from_u8;
using GUI::into_u8; using GUI::into_u8;
@ -293,8 +295,6 @@ OptionsSearcher::OptionsSearcher()
OptionsSearcher::~OptionsSearcher() OptionsSearcher::~OptionsSearcher()
{ {
if (search_dialog)
search_dialog->Destroy();
} }
void OptionsSearcher::init(std::vector<InputInfo> input_values) void OptionsSearcher::init(std::vector<InputInfo> input_values)
@ -530,9 +530,16 @@ void SearchDialog::ProcessSelection(wxDataViewItem selection)
{ {
if (!selection.IsOk()) if (!selection.IsOk())
return; return;
GUI::wxGetApp().sidebar().jump_to_option(search_list_model->GetRow(selection));
this->EndModal(wxID_CLOSE); this->EndModal(wxID_CLOSE);
// If call GUI::wxGetApp().sidebar.jump_to_option() directly from here,
// then mainframe will not have focus and found option will not be "active" (have cursor) as a result
// SearchDialog have to be closed and have to lose a focus
// and only after that jump_to_option() function can be called
// So, post event to plater:
wxCommandEvent event(wxCUSTOMEVT_JUMP_TO_OPTION);
event.SetInt(search_list_model->GetRow(selection));
wxPostEvent(GUI::wxGetApp().plater(), event);
} }
void SearchDialog::OnInputText(wxCommandEvent&) void SearchDialog::OnInputText(wxCommandEvent&)

View File

@ -22,6 +22,8 @@
namespace Slic3r { namespace Slic3r {
wxDECLARE_EVENT(wxCUSTOMEVT_JUMP_TO_OPTION, wxCommandEvent);
namespace Search{ namespace Search{
class SearchDialog; class SearchDialog;

View File

@ -501,6 +501,8 @@ void Tab::OnActivate()
m_presets_choice->SetMinSize(ok_sz); m_presets_choice->SetMinSize(ok_sz);
m_presets_choice->SetSize(ok_sz); m_presets_choice->SetSize(ok_sz);
GetSizer()->GetItem(size_t(0))->GetSizer()->Layout(); GetSizer()->GetItem(size_t(0))->GetSizer()->Layout();
if (wxGetApp().tabs_as_menu())
m_presets_choice->update();
} }
#endif // _MSW_DARK_MODE #endif // _MSW_DARK_MODE
Refresh(); Refresh();

View File

@ -1214,9 +1214,9 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent
for (Tab* tab : wxGetApp().tabs_list) for (Tab* tab : wxGetApp().tabs_list)
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
presets_cnt++; presets_cnt++;
m_action_line->SetLabel((header.IsEmpty() ? "" : header + "\n\n") + //_L("The following presets were modified:")); m_action_line->SetLabel((header.IsEmpty() ? "" : header + "\n\n") +
+ _L_PLURAL("The following preset was modified", _L_PLURAL("The following preset was modified",
"The following presets were modified", presets_cnt)); "The following presets were modified", presets_cnt));
} }
else { else {
wxString action_msg; wxString action_msg;