mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/Prusa3D/PrusaSlicer
This commit is contained in:
		
						commit
						04e4aee246
					
				
					 15 changed files with 422 additions and 62 deletions
				
			
		|  | @ -12,7 +12,7 @@ namespace Slic3r { | |||
| #ifdef  WIN32 | ||||
| 
 | ||||
| //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) | ||||
| { | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ | |||
| #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
 | ||||
| #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_
 | ||||
|  |  | |||
|  | @ -1819,7 +1819,8 @@ void Control::OnChar(wxKeyEvent& event) | |||
| 
 | ||||
| void Control::OnRightDown(wxMouseEvent& event) | ||||
| { | ||||
|     if (HasCapture()) return; | ||||
|     if (HasCapture() || m_is_left_down) | ||||
|         return; | ||||
|     this->CaptureMouse(); | ||||
| 
 | ||||
|     const wxPoint pos = event.GetLogicalPosition(wxClientDC(this)); | ||||
|  | @ -2097,7 +2098,7 @@ void Control::auto_color_change() | |||
| 
 | ||||
| void Control::OnRightUp(wxMouseEvent& event) | ||||
| { | ||||
|     if (!HasCapture()) | ||||
|     if (!HasCapture() || m_is_left_down) | ||||
|         return; | ||||
|     this->ReleaseMouse(); | ||||
|     m_is_right_down = m_is_one_layer = false; | ||||
|  |  | |||
|  | @ -267,7 +267,12 @@ void GCodeViewer::SequentialView::Marker::render() const | |||
|     imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Tool position") + ":"); | ||||
|     ImGui::SameLine(); | ||||
|     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)); | ||||
| 
 | ||||
|     // force extra frame to automatically update window size
 | ||||
|  | @ -862,6 +867,9 @@ void GCodeViewer::render() | |||
|     render_legend(legend_height); | ||||
|     if (m_sequential_view.current.last != m_sequential_view.endpoints.last) { | ||||
|         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); | ||||
|     } | ||||
| #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.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(); | ||||
|     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) { | ||||
|         m_sequential_view.gcode_ids.push_back(move.gcode_id); | ||||
|     } | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| 
 | ||||
|     std::vector<MultiVertexBuffer> vertices(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<InstanceIdBuffer> instances_ids(m_buffers.size()); | ||||
| #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; | ||||
| 
 | ||||
| #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
 | ||||
|     for (size_t i = 0; i < m_moves_count; ++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
 | ||||
|         if (i == 0) | ||||
|  | @ -1538,6 +1570,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|         InstanceBuffer& inst_buffer = instances[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
 | ||||
| 
 | ||||
|         // 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) { | ||||
|                 Path& last_path = t_buffer.paths.back(); | ||||
|                 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); | ||||
| #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::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; } | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|             ++m_statistics.instances_count; | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
|  | @ -1579,7 +1627,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|         } | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|             ++m_statistics.batched_count; | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
|  | @ -1588,7 +1641,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
| #else | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|             ++m_statistics.instances_count; | ||||
| #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
 | ||||
| #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) { | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|         auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) { | ||||
|             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(); | ||||
|         for (const Path& path : t_buffer.paths) { | ||||
|             // 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; | ||||
|             for (size_t j = 1; j < path_vertices_count - 1; ++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& curr = gcode_result.moves[curr_s_id].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
 | ||||
|                 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 (VertexBuffer& v_buffer : v_multibuffer) { | ||||
|             v_buffer.shrink_to_fit(); | ||||
|  | @ -1784,6 +1867,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             if (!inst_buffer.empty()) { | ||||
|                 t_buffer.model.instances.buffer = inst_buffer; | ||||
|                 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 { | ||||
|  | @ -1792,6 +1878,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|                 if (!inst_buffer.empty()) { | ||||
|                     t_buffer.model.instances.buffer = inst_buffer; | ||||
|                     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 | ||||
|  | @ -1800,6 +1889,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             if (!inst_buffer.empty()) { | ||||
|                 t_buffer.model.instances.buffer = inst_buffer; | ||||
|                 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 { | ||||
|  | @ -1860,8 +1952,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|     using VboIndexList = std::vector<unsigned int>; | ||||
|     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) { | ||||
|         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
 | ||||
|         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) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 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); | ||||
| #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) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -1946,17 +2056,29 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|         switch (t_buffer.render_primitive_type) | ||||
|         { | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); | ||||
|             break; | ||||
|         } | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); | ||||
|             break; | ||||
|         } | ||||
|         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); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             break; | ||||
|         } | ||||
| #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
 | ||||
|     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) { | ||||
|         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) { | ||||
|             // layers zs
 | ||||
|             const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); | ||||
|             const double z = static_cast<double>(move.position.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 }); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             else | ||||
| #if ENABLE_FIX_SEAMS_SYNCH | ||||
|                 m_layers.get_endpoints().back().last = move_id; | ||||
| #else | ||||
|                 m_layers.get_endpoints().back().last = i; | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|             // extruder ids
 | ||||
|             m_extruder_ids.emplace_back(move.extruder_id); | ||||
|             // roles
 | ||||
|  | @ -2068,10 +2208,17 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|                 m_roles.emplace_back(move.extrusion_role); | ||||
|         } | ||||
|         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()) | ||||
|                 m_layers.get_endpoints().back().last = 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.y() = buffer.model.instances.buffer[offset + 1]; | ||||
|                     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; | ||||
|                     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(::glBindBuffer(GL_ARRAY_BUFFER, 0)); | ||||
| 
 | ||||
| #if ENABLE_FIX_SEAMS_SYNCH | ||||
|                         sequential_view->current_offset = Vec3f::Zero(); | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
| 
 | ||||
|                         found = true; | ||||
|                         break; | ||||
|                     } | ||||
|  |  | |||
|  | @ -31,6 +31,9 @@ class GCodeViewer | |||
|     using InstanceBuffer = std::vector<float>; | ||||
|     using InstanceIdBuffer = std::vector<size_t>; | ||||
| #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> Options_Colors; | ||||
|  | @ -151,6 +154,10 @@ class GCodeViewer | |||
|         InstanceBuffer buffer; | ||||
|         // indices of the moves for all instances
 | ||||
|         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; | ||||
| 
 | ||||
|         size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } | ||||
|  | @ -665,6 +672,12 @@ public: | |||
|             GLModel m_model; | ||||
|             Vec3f m_world_position; | ||||
|             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 }; | ||||
|             bool m_visible{ true }; | ||||
| 
 | ||||
|  | @ -674,6 +687,9 @@ public: | |||
|             const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); } | ||||
| 
 | ||||
|             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; } | ||||
|             void set_visible(bool visible) { m_visible = visible; } | ||||
|  | @ -731,6 +747,9 @@ public: | |||
|         Endpoints global; | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|         Vec3f current_position{ Vec3f::Zero() }; | ||||
| #if ENABLE_FIX_SEAMS_SYNCH | ||||
|         Vec3f current_offset{ Vec3f::Zero() }; | ||||
| #endif // ENABLE_FIX_SEAMS_SYNCH
 | ||||
|         Marker marker; | ||||
|         GCodeWindow gcode_window; | ||||
|         std::vector<unsigned int> gcode_ids; | ||||
|  |  | |||
|  | @ -4427,12 +4427,11 @@ bool GLCanvas3D::_init_main_toolbar() | |||
|     arrow_data.top = 0; | ||||
|     arrow_data.right = 0; | ||||
|     arrow_data.bottom = 0; | ||||
| 
 | ||||
|     if (!m_main_toolbar.init_arrow(arrow_data)) | ||||
|     { | ||||
|         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)) | ||||
|     { | ||||
|         BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture."; | ||||
|  | @ -4643,6 +4642,18 @@ bool GLCanvas3D::_init_undoredo_toolbar() | |||
|         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::Horizontal); | ||||
|     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.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 | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
|     // 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 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 top = m_layout.top - icon_stride; | ||||
| 
 | ||||
|     bool found = false; | ||||
|     for (const GLToolbarItem* item : m_items) { | ||||
|         if (!item->is_visible()) | ||||
|             continue; | ||||
|  | @ -1164,11 +1169,15 @@ void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighte | |||
|         if (item->is_separator()) | ||||
|             left += separator_stride; | ||||
|         else {    | ||||
|             if (item->get_name() == highlighted_item->get_name()) | ||||
|             if (item->get_name() == highlighted_item->get_name()) { | ||||
|                 found = true; | ||||
|                 break; | ||||
|             } | ||||
|             left += icon_stride; | ||||
|         } | ||||
|     } | ||||
|     if (!found) | ||||
|         return; | ||||
| 
 | ||||
|     left += border; | ||||
|     top -= separator_stride; | ||||
|  |  | |||
|  | @ -84,6 +84,9 @@ public: | |||
|             if (int page_idx = evt.GetId(); page_idx >= 0) | ||||
|                 SetSelection(page_idx); | ||||
|         }); | ||||
| 
 | ||||
|         this->Bind(wxEVT_NAVIGATION_KEY, &Notebook::OnNavigationKey, this); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|  | @ -242,6 +245,89 @@ public: | |||
|         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: | ||||
|     virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override | ||||
|     { | ||||
|  |  | |||
|  | @ -593,7 +593,7 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64 | |||
| 		m_state = EState::Unknown; | ||||
| 		init(); | ||||
| 	// 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; | ||||
| 		if (up_time >= get_duration() * 1000) { | ||||
| 			m_state					= EState::FadingOut; | ||||
|  | @ -633,6 +633,10 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64 | |||
| //---------------ExportFinishedNotification-----------
 | ||||
| void NotificationManager::ExportFinishedNotification::count_spaces() | ||||
| { | ||||
| 	if (m_eject_pending) | ||||
| 	{ | ||||
| 		return PopNotification::count_spaces(); | ||||
| 	} | ||||
| 	//determine line width 
 | ||||
| 	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) | ||||
| { | ||||
| 	 | ||||
| 	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; | ||||
| 	std::string fulltext = m_text1 + m_hypertext; //+ m_text2;
 | ||||
| 	// 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.text(line.c_str()); | ||||
| 			//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.")); | ||||
| 			} | ||||
| 		} | ||||
|  | @ -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) | ||||
| { | ||||
| 	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); | ||||
| } | ||||
| 
 | ||||
|  | @ -725,7 +732,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW | |||
| 		assert(m_evt_handler != nullptr); | ||||
| 		if (m_evt_handler != nullptr) | ||||
| 			wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); | ||||
| 		close(); | ||||
| 		on_eject_click(); | ||||
| 	} | ||||
| 
 | ||||
| 	//invisible large button
 | ||||
|  | @ -736,7 +743,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW | |||
| 		assert(m_evt_handler != nullptr); | ||||
| 		if (m_evt_handler != nullptr) | ||||
| 			wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); | ||||
| 		close(); | ||||
| 		on_eject_click(); | ||||
| 	} | ||||
| 	ImGui::PopStyleColor(5); | ||||
| } | ||||
|  | @ -745,6 +752,14 @@ bool NotificationManager::ExportFinishedNotification::on_text_click() | |||
| 	open_folder(m_export_dir_path); | ||||
| 	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----------------
 | ||||
| void NotificationManager::ProgressBarNotification::init() | ||||
| { | ||||
|  | @ -1071,7 +1086,7 @@ void NotificationManager::UpdatedItemsInfoNotification::render_left_sign(ImGuiWr | |||
| 	imgui.text(text.c_str()); | ||||
| } | ||||
| 
 | ||||
| //------SlicingProgressNotificastion
 | ||||
| //------SlicingProgressNotification
 | ||||
| void NotificationManager::SlicingProgressNotification::init() | ||||
| { | ||||
| 	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) | ||||
| 		set_progress_state(SlicingProgressState::SP_CANCELLED); | ||||
| 		return true;//set_progress_state(SlicingProgressState::SP_CANCELLED);
 | ||||
| 	else if (percent >= 1.f) | ||||
| 		set_progress_state(SlicingProgressState::SP_COMPLETED); | ||||
| 		return set_progress_state(SlicingProgressState::SP_COMPLETED); | ||||
| 	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) | ||||
| 	{ | ||||
| 	case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING: | ||||
| 	case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_BEGAN: | ||||
| 		m_state = EState::Hidden; | ||||
| 		set_percentage(-1); | ||||
| 		m_has_print_info = false; | ||||
| 		set_export_possible(false); | ||||
| 		break; | ||||
| 		m_sp_state = state; | ||||
| 		return true; | ||||
| 	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); | ||||
| 		m_has_cancel_button = true; | ||||
| 		break; | ||||
| 		m_sp_state = state; | ||||
| 		return true; | ||||
| 	case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED: | ||||
| 		set_percentage(-1); | ||||
| 		m_has_cancel_button = false; | ||||
| 		m_has_print_info = false; | ||||
| 		set_export_possible(false); | ||||
| 		break; | ||||
| 		m_sp_state = state; | ||||
| 		return true; | ||||
| 	case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED: | ||||
| 		set_percentage(1); | ||||
| 		m_has_cancel_button = 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); | ||||
| 		break; | ||||
| 		m_sp_state = state; | ||||
| 		return true; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 	m_sp_state = state; | ||||
| 	return false; | ||||
| } | ||||
| 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.") }; | ||||
| 		update(data); | ||||
| 		m_state = EState::Shown; | ||||
| 		m_state = EState::NotFading; | ||||
| 	} | ||||
| 		break; | ||||
| 	default: | ||||
|  | @ -1170,7 +1192,7 @@ void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(boo | |||
| { | ||||
| 	m_sidebar_collapsed = collapsed; | ||||
| 	if (m_sp_state == SlicingProgressState::SP_COMPLETED) | ||||
| 		m_state = EState::Shown; | ||||
| 		m_state = EState::NotFading; | ||||
| } | ||||
| 
 | ||||
| void NotificationManager::SlicingProgressNotification::on_cancel_button() | ||||
|  | @ -1184,9 +1206,9 @@ void NotificationManager::SlicingProgressNotification::on_cancel_button() | |||
| int NotificationManager::SlicingProgressNotification::get_duration() | ||||
| { | ||||
| 	if (m_sp_state == SlicingProgressState::SP_CANCELLED) | ||||
| 		return 10; | ||||
| 		return 2; | ||||
| 	else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed) | ||||
| 		return 5; | ||||
| 		return 0; | ||||
| 	else | ||||
| 		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) | ||||
| { | ||||
| 	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); | ||||
| 		/* // enable for hypertext during slicing (correct call of export_enabled needed)
 | ||||
| 		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); | ||||
| 		} | ||||
| 		*/ | ||||
| 	} 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
 | ||||
| 		ImVec2 win_size(win_size_x, win_size_y); | ||||
| 		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); | ||||
| 	} | ||||
| } | ||||
| 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; | ||||
| 	} | ||||
| 	//std::string text;
 | ||||
| 	ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); | ||||
| 	/*
 | ||||
| 	std::stringstream stream; | ||||
| 	stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%"; | ||||
| 	text = stream.str(); | ||||
| 	ImGui::SetCursorPosX(m_left_indentation); | ||||
| 	ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4)); | ||||
| 	imgui.text(text.c_str()); | ||||
| 	*/ | ||||
| } | ||||
| void  NotificationManager::SlicingProgressNotification::render_hypertext(ImGuiWrapper& imgui,const float text_x, const float text_y, const std::string text, bool more) | ||||
| { | ||||
| 	if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)  | ||||
| 		return; | ||||
| 	ProgressBarNotification::render_hypertext(imgui, text_x, text_y, text, more); | ||||
| } | ||||
| 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; | ||||
| 		break; | ||||
| 	case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_COMPLETED: | ||||
| 		m_state = EState::Shown; | ||||
| 		m_state = EState::ClosePending; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
|  | @ -1374,7 +1393,7 @@ void NotificationManager::ProgressIndicatorNotification::set_percentage(float pe | |||
| 		m_has_cancel_button = true; | ||||
| 		m_progress_state = ProgressIndicatorState::PIS_PROGRESS_REQUEST; | ||||
| 	} else if (percent >= 1.0f) { | ||||
| 		m_state = EState::Shown; | ||||
| 		m_state = EState::FadingOut; | ||||
| 		m_progress_state = ProgressIndicatorState::PIS_COMPLETED; | ||||
| 		m_has_cancel_button = false; | ||||
| 	} 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
 | ||||
| 		m_next_render = 0; | ||||
| 		m_progress_state = ProgressIndicatorState::PIS_PROGRESS_UPDATED; | ||||
| 		m_current_fade_opacity = 1.0f; | ||||
| 		return true; | ||||
| 	} | ||||
| 	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); | ||||
| 	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); | ||||
| 	set_slicing_progress_hidden(); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 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) | ||||
| { | ||||
| 	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(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); | ||||
| 			wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); | ||||
| 			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
 | ||||
| 	wxGetApp().plater()->init_notification_manager(); | ||||
| } | ||||
| 
 | ||||
| void NotificationManager::set_slicing_progress_hidden() | ||||
| { | ||||
| 	for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) { | ||||
|  | @ -1772,7 +1819,7 @@ void NotificationManager::init_progress_indicator() | |||
| 			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); | ||||
| 	push_notification_data(std::move(notification), 0); | ||||
| } | ||||
|  |  | |||
|  | @ -189,8 +189,10 @@ public: | |||
| 	void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); | ||||
| 	// slicing progress
 | ||||
| 	void init_slicing_progress_notification(std::function<bool()> cancel_callback); | ||||
| 	void set_slicing_progress_began(); | ||||
| 	// percentage negative = canceled, <0-1) = progress, 1 = completed 
 | ||||
| 	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
 | ||||
| 	void set_slicing_progress_hidden(); | ||||
| 	// 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 | ||||
| 		{ | ||||
| 			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_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
 | ||||
|  | @ -509,10 +512,10 @@ private: | |||
| 		// sets cancel button callback
 | ||||
| 		void			    set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; } | ||||
| 		bool                has_cancel_callback() const { return m_cancel_callback != nullptr; } | ||||
| 		// sets SlicingProgressState, negative percent means canceled
 | ||||
| 		void				set_progress_state(float percent); | ||||
| 		// sets SlicingProgressState, percent is used only at progress state.
 | ||||
| 		void				set_progress_state(SlicingProgressState state,float percent = 0.f); | ||||
| 		// sets SlicingProgressState, negative percent means canceled, returns true if state was set succesfully.
 | ||||
| 		bool				set_progress_state(float percent); | ||||
| 		// sets SlicingProgressState, percent is used only at progress state. Returns true if state was set succesfully.
 | ||||
| 		bool				set_progress_state(SlicingProgressState state,float percent = 0.f); | ||||
| 		// sets additional string of print info and puts notification into Completed state.
 | ||||
| 		void			    set_print_info(const std::string& info); | ||||
| 		// sets fading if in Completed state.
 | ||||
|  | @ -541,8 +544,12 @@ private: | |||
| 											const float win_size_x, const float win_size_y, | ||||
| 											const float win_pos_x, const float win_pos_y) override; | ||||
| 		void		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) override; | ||||
| 										const float win_size_x, const float win_size_y, | ||||
| 										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(); | ||||
| 		int		   get_duration() override; | ||||
| 		// 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 | ||||
| 			{ m_minimize_b_visible = false; } | ||||
| 		bool on_text_click() override; | ||||
| 		void on_eject_click(); | ||||
| 		// local time of last hover for showing tooltip
 | ||||
| 		long      m_hover_time { 0 }; | ||||
| 		bool	  m_eject_pending { false }; | ||||
| 	}; | ||||
| 
 | ||||
| 	class UpdatedItemsInfoNotification : public PopNotification | ||||
|  |  | |||
|  | @ -1920,6 +1920,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|         sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); | ||||
|         sidebar->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); }); | ||||
|         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(); | ||||
|  | @ -3102,6 +3104,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool | |||
| //        if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
 | ||||
| //            (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
 | ||||
| //            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::abSendGCode, _(label_btn_send)); | ||||
|  | @ -3961,6 +3966,7 @@ void Plater::priv::on_slicing_began() | |||
| 	clear_warnings(); | ||||
|     notification_manager->close_notification_of_type(NotificationType::SignDetected); | ||||
|     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) | ||||
| { | ||||
|  | @ -4058,7 +4064,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) | |||
|     } | ||||
|     if (evt.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()); | ||||
|  | @ -6373,6 +6379,7 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology) | |||
|     p->sidebar->get_searcher().set_printer_technology(printer_technology); | ||||
| 
 | ||||
|     p->notification_manager->set_fff(printer_technology == ptFFF); | ||||
|     p->notification_manager->set_slicing_progress_hidden(); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ using boost::optional; | |||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| wxDEFINE_EVENT(wxCUSTOMEVT_JUMP_TO_OPTION, wxCommandEvent); | ||||
| 
 | ||||
| using GUI::from_u8; | ||||
| using GUI::into_u8; | ||||
| 
 | ||||
|  | @ -293,8 +295,6 @@ OptionsSearcher::OptionsSearcher() | |||
| 
 | ||||
| OptionsSearcher::~OptionsSearcher() | ||||
| { | ||||
|     if (search_dialog) | ||||
|         search_dialog->Destroy(); | ||||
| } | ||||
| 
 | ||||
| void OptionsSearcher::init(std::vector<InputInfo> input_values) | ||||
|  | @ -530,9 +530,16 @@ void SearchDialog::ProcessSelection(wxDataViewItem selection) | |||
| { | ||||
|     if (!selection.IsOk()) | ||||
|         return; | ||||
| 
 | ||||
|     GUI::wxGetApp().sidebar().jump_to_option(search_list_model->GetRow(selection)); | ||||
|     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&) | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ | |||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| wxDECLARE_EVENT(wxCUSTOMEVT_JUMP_TO_OPTION, wxCommandEvent); | ||||
| 
 | ||||
| namespace Search{ | ||||
| 
 | ||||
| class SearchDialog; | ||||
|  |  | |||
|  | @ -501,6 +501,8 @@ void Tab::OnActivate() | |||
|         m_presets_choice->SetMinSize(ok_sz); | ||||
|         m_presets_choice->SetSize(ok_sz); | ||||
|         GetSizer()->GetItem(size_t(0))->GetSizer()->Layout(); | ||||
|         if (wxGetApp().tabs_as_menu()) | ||||
|             m_presets_choice->update(); | ||||
|     } | ||||
| #endif // _MSW_DARK_MODE
 | ||||
|     Refresh(); | ||||
|  |  | |||
|  | @ -1214,9 +1214,9 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent | |||
|         for (Tab* tab : wxGetApp().tabs_list) | ||||
|             if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) | ||||
|                 presets_cnt++; | ||||
|         m_action_line->SetLabel((header.IsEmpty() ? "" : header + "\n\n") + //_L("The following presets were modified:"));
 | ||||
|                                 + _L_PLURAL("The following preset was modified", | ||||
|                                             "The following presets were modified", presets_cnt)); | ||||
|         m_action_line->SetLabel((header.IsEmpty() ? "" : header + "\n\n") +  | ||||
|                                 _L_PLURAL("The following preset was modified", | ||||
|                                           "The following presets were modified", presets_cnt)); | ||||
|     } | ||||
|     else { | ||||
|         wxString action_msg; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vojtech Bubnik
						Vojtech Bubnik