mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/dev_native' into tm_sla_supports_backend
# Conflicts: # src/libslic3r/SLAPrint.hpp
This commit is contained in:
		
						commit
						9a93b1d3e9
					
				
					 19 changed files with 441 additions and 167 deletions
				
			
		|  | @ -1244,16 +1244,26 @@ size_t ModelVolume::split(unsigned int max_extruders) | |||
|     std::string name = this->name; | ||||
| 
 | ||||
|     Model::reset_auto_extruder_id(); | ||||
| #if ENABLE_MODELVOLUME_TRANSFORM | ||||
|     Vec3d offset = this->get_offset(); | ||||
| #endif // ENABLE_MODELVOLUME_TRANSFORM
 | ||||
| 
 | ||||
|     for (TriangleMesh *mesh : meshptrs) { | ||||
|         mesh->repair(); | ||||
|         if (idx == 0) | ||||
|         { | ||||
|             this->mesh = std::move(*mesh); | ||||
|             this->calculate_convex_hull(); | ||||
|         } | ||||
|         else | ||||
|             this->object->volumes.insert(this->object->volumes.begin() + (++ ivolume), new ModelVolume(object, *this, std::move(*mesh))); | ||||
|         char str_idx[64]; | ||||
|         sprintf(str_idx, "_%d", idx + 1); | ||||
|         this->object->volumes[ivolume]->name = name + str_idx; | ||||
|             this->object->volumes.insert(this->object->volumes.begin() + (++ivolume), new ModelVolume(object, *this, std::move(*mesh))); | ||||
| 
 | ||||
| #if ENABLE_MODELVOLUME_TRANSFORM | ||||
|         this->object->volumes[ivolume]->set_offset(Vec3d::Zero()); | ||||
|         this->object->volumes[ivolume]->center_geometry(); | ||||
|         this->object->volumes[ivolume]->translate(offset); | ||||
| #endif // ENABLE_MODELVOLUME_TRANSFORM
 | ||||
|         this->object->volumes[ivolume]->name = name + "_" + std::to_string(idx + 1); | ||||
|         this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string(max_extruders)); | ||||
|         delete mesh; | ||||
|         ++ idx; | ||||
|  |  | |||
|  | @ -371,4 +371,14 @@ SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object): | |||
| 
 | ||||
| SLAPrintObject::~SLAPrintObject() {} | ||||
| 
 | ||||
| TriangleMesh SLAPrintObject::support_mesh() const | ||||
| { | ||||
| 	return make_cube(10., 10., 10.); | ||||
| } | ||||
| 
 | ||||
| TriangleMesh SLAPrintObject::pad_mesh() const | ||||
| { | ||||
| 	return make_cube(10., 10., 10.); | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -37,7 +37,23 @@ private: // Prevents erroneous use by other classes. | |||
| public: | ||||
|     const ModelObject*      model_object() const    { return m_model_object; } | ||||
|     ModelObject*            model_object()          { return m_model_object; } | ||||
|     const Transform3d&      trafo()        const    { return m_trafo; } | ||||
| 
 | ||||
|     struct Instance { | ||||
|     	ModelID instance_id; | ||||
| 	    // Slic3r::Point objects in scaled G-code coordinates
 | ||||
|     	Point 	shift; | ||||
|     	// Rotation along the Z axis, in radians.
 | ||||
|     	float 	rotation;  | ||||
|     }; | ||||
|     const std::vector<Instance>& instances() const { return m_instances; } | ||||
| 
 | ||||
|     // Get a support mesh centered around origin in XY, and with zero rotation around Z applied.
 | ||||
|     // Support mesh is only valid if this->is_step_done(slaposSupportTree) is true.
 | ||||
|     TriangleMesh            support_mesh() const; | ||||
|     // Get a pad mesh centered around origin in XY, and with zero rotation around Z applied.
 | ||||
|     // Support mesh is only valid if this->is_step_done(slaposPad) is true.
 | ||||
|     TriangleMesh            pad_mesh() const; | ||||
| 
 | ||||
|     // I refuse to grantee copying (Tamas)
 | ||||
|     SLAPrintObject(const SLAPrintObject&) = delete; | ||||
|  | @ -55,14 +71,6 @@ protected: | |||
|     	{ this->m_config.apply_only(other, keys, ignore_nonexistent); } | ||||
|     void                    set_trafo(const Transform3d& trafo) { m_trafo = trafo; } | ||||
| 
 | ||||
|     struct Instance { | ||||
| 	    // Slic3r::Point objects in scaled G-code coordinates
 | ||||
|     	Point 	shift; | ||||
|     	// Rotation along the Z axis, in radians.
 | ||||
|         float 	rotation; | ||||
|         Instance(const Point& tr, float rotZ): shift(tr), rotation(rotZ) {} | ||||
|     }; | ||||
| 
 | ||||
|     bool                    set_instances(const std::vector<Instance> &instances); | ||||
|     // Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint.
 | ||||
|     bool                    invalidate_step(SLAPrintObjectStep step); | ||||
|  | @ -152,6 +160,7 @@ public: | |||
|         if(m_printer) m_printer->save<Fmt>(fname); | ||||
|         std::cout << "Would export the SLA raster" << std::endl; | ||||
|     } | ||||
|     const PrintObjects& objects() const { return m_objects; } | ||||
| 
 | ||||
| private: | ||||
|     using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>; | ||||
|  |  | |||
|  | @ -2,13 +2,14 @@ | |||
| 
 | ||||
| #include "3DScene.hpp" | ||||
| 
 | ||||
| #include "../../libslic3r/ExtrusionEntity.hpp" | ||||
| #include "../../libslic3r/ExtrusionEntityCollection.hpp" | ||||
| #include "../../libslic3r/Geometry.hpp" | ||||
| #include "../../libslic3r/GCode/PreviewData.hpp" | ||||
| #include "../../libslic3r/Print.hpp" | ||||
| #include "../../libslic3r/Slicing.hpp" | ||||
| #include "../../slic3r/GUI/PresetBundle.hpp" | ||||
| #include "libslic3r/ExtrusionEntity.hpp" | ||||
| #include "libslic3r/ExtrusionEntityCollection.hpp" | ||||
| #include "libslic3r/Geometry.hpp" | ||||
| #include "libslic3r/GCode/PreviewData.hpp" | ||||
| #include "libslic3r/Print.hpp" | ||||
| #include "libslic3r/SLAPrint.hpp" | ||||
| #include "libslic3r/Slicing.hpp" | ||||
| #include "slic3r/GUI/PresetBundle.hpp" | ||||
| #include "GCode/Analyzer.hpp" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
|  | @ -209,7 +210,9 @@ GLVolume::GLVolume(float r, float g, float b, float a) | |||
| #endif // ENABLE_MODELVOLUME_TRANSFORM
 | ||||
|     , m_transformed_convex_hull_bounding_box_dirty(true) | ||||
|     , m_convex_hull(nullptr) | ||||
|     , composite_id(-1) | ||||
|     , object_id(-1) | ||||
|     , volume_id(-1) | ||||
|     , instance_id(-1) | ||||
|     , extruder_id(0) | ||||
|     , selected(false) | ||||
|     , disabled(false) | ||||
|  | @ -755,7 +758,9 @@ std::vector<int> GLVolumeCollection::load_object( | |||
|             // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
 | ||||
|             v.bounding_box = v.indexed_vertex_array.bounding_box(); | ||||
|             v.indexed_vertex_array.finalize_geometry(use_VBOs); | ||||
|             v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx; | ||||
|             v.object_id    = obj_idx; | ||||
|             v.volume_id    = volume_idx; | ||||
|             v.instance_id  = instance_idx; | ||||
|             if (model_volume->is_model_part()) | ||||
|             { | ||||
|                 v.set_convex_hull(model_volume->get_convex_hull()); | ||||
|  | @ -780,6 +785,61 @@ std::vector<int> GLVolumeCollection::load_object( | |||
|     return volumes_idx;  | ||||
| } | ||||
| 
 | ||||
| // Load SLA auxiliary GLVolumes (for support trees or pad).
 | ||||
| std::vector<int> GLVolumeCollection::load_object_auxiliary( | ||||
|     const ModelObject       *model_object, | ||||
|     const SLAPrintObject    *print_object, | ||||
|     int                      obj_idx, | ||||
|     SLAPrintObjectStep       milestone, | ||||
|     bool                     use_VBOs) | ||||
| { | ||||
|     std::vector<int> volumes_idx; | ||||
|     // Find the SLAPrintObject's instance to it.
 | ||||
|     if (print_object->is_step_done(milestone)) { | ||||
|         // Get the support mesh.
 | ||||
|         TriangleMesh mesh; | ||||
|         switch (milestone) { | ||||
|         case slaposSupportTree: mesh = print_object->support_mesh(); break; | ||||
|         case slaposBasePool:    mesh = print_object->pad_mesh();     break; | ||||
|         default: | ||||
|             assert(false); | ||||
|         } | ||||
| 		// Convex hull is required for out of print bed detection.
 | ||||
| 		TriangleMesh convex_hull = mesh.convex_hull_3d(); | ||||
|         const std::vector<SLAPrintObject::Instance> &instances = print_object->instances(); | ||||
|         std::map<ModelID, int> map_instances; | ||||
|         for (int i = 0; i < (int)model_object->instances.size(); ++ i) | ||||
|             map_instances[model_object->instances[i]->id()] = i; | ||||
|         for (const SLAPrintObject::Instance &instance : instances) { | ||||
|             auto model_instance_it = map_instances.find(instance.instance_id); | ||||
|             assert(model_instance_it != map_instances.end()); | ||||
|             const int instance_idx = model_instance_it->second; | ||||
|             const ModelInstance *model_instance = model_object->instances[instance_idx]; | ||||
|             volumes_idx.push_back(int(this->volumes.size())); | ||||
|             float color[4] { 0.f, 0.f, 1.f, 1.f }; | ||||
|             this->volumes.emplace_back(new GLVolume(color)); | ||||
|             GLVolume &v = *this->volumes.back(); | ||||
|             if (use_VBOs) | ||||
|                 v.indexed_vertex_array.load_mesh_full_shading(mesh); | ||||
|             else | ||||
|                 v.indexed_vertex_array.load_mesh_flat_shading(mesh); | ||||
|             // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
 | ||||
|             v.bounding_box = v.indexed_vertex_array.bounding_box(); | ||||
|             v.indexed_vertex_array.finalize_geometry(use_VBOs); | ||||
|             v.object_id    = obj_idx; | ||||
|             v.volume_id    = -1; // SLA supports
 | ||||
|             v.instance_id  = instance_idx; | ||||
| 			v.set_convex_hull(convex_hull); | ||||
|             v.is_modifier  = false; | ||||
|             v.shader_outside_printer_detection_enabled = true; | ||||
| 			v.set_instance_transformation(model_instance->get_transformation()); | ||||
| 			// Leave the volume transformation at identity.
 | ||||
|             // v.set_volume_transformation(model_volume->get_transformation());
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return volumes_idx;  | ||||
| } | ||||
| 
 | ||||
| int GLVolumeCollection::load_wipe_tower_preview( | ||||
|     int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width) | ||||
|  | @ -851,7 +911,9 @@ int GLVolumeCollection::load_wipe_tower_preview( | |||
|     // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
 | ||||
|     v.bounding_box = v.indexed_vertex_array.bounding_box(); | ||||
|     v.indexed_vertex_array.finalize_geometry(use_VBOs); | ||||
|     v.composite_id = obj_idx * 1000000; | ||||
|     v.object_id    = obj_idx; | ||||
|     v.volume_id    = 0; | ||||
|     v.instance_id  = 0; | ||||
|     v.is_wipe_tower = true; | ||||
|     v.shader_outside_printer_detection_enabled = ! size_unknown; | ||||
|     return int(this->volumes.size() - 1); | ||||
|  | @ -1848,6 +1910,11 @@ void _3DScene::set_print(wxGLCanvas* canvas, Print* print) | |||
|     s_canvas_mgr.set_print(canvas, print); | ||||
| } | ||||
| 
 | ||||
| void _3DScene::set_SLA_print(wxGLCanvas* canvas, SLAPrint* print) | ||||
| { | ||||
|     s_canvas_mgr.set_SLA_print(canvas, print); | ||||
| } | ||||
| 
 | ||||
| void _3DScene::set_model(wxGLCanvas* canvas, Model* model) | ||||
| { | ||||
|     s_canvas_mgr.set_model(canvas, model); | ||||
|  |  | |||
|  | @ -1,13 +1,13 @@ | |||
| #ifndef slic3r_3DScene_hpp_ | ||||
| #define slic3r_3DScene_hpp_ | ||||
| 
 | ||||
| #include "../../libslic3r/libslic3r.h" | ||||
| #include "../../libslic3r/Point.hpp" | ||||
| #include "../../libslic3r/Line.hpp" | ||||
| #include "../../libslic3r/TriangleMesh.hpp" | ||||
| #include "../../libslic3r/Utils.hpp" | ||||
| #include "../../libslic3r/Model.hpp" | ||||
| #include "../../slic3r/GUI/GLCanvas3DManager.hpp" | ||||
| #include "libslic3r/libslic3r.h" | ||||
| #include "libslic3r/Point.hpp" | ||||
| #include "libslic3r/Line.hpp" | ||||
| #include "libslic3r/TriangleMesh.hpp" | ||||
| #include "libslic3r/Utils.hpp" | ||||
| #include "libslic3r/Model.hpp" | ||||
| #include "slic3r/GUI/GLCanvas3DManager.hpp" | ||||
| 
 | ||||
| class wxBitmap; | ||||
| class wxWindow; | ||||
|  | @ -16,6 +16,9 @@ namespace Slic3r { | |||
| 
 | ||||
| class Print; | ||||
| class PrintObject; | ||||
| class SLAPrint; | ||||
| class SLAPrintObject; | ||||
| enum  SLAPrintObjectStep; | ||||
| class Model; | ||||
| class ModelObject; | ||||
| class GCodePreviewData; | ||||
|  | @ -290,8 +293,15 @@ public: | |||
|     float               color[4]; | ||||
|     // Color used to render this volume.
 | ||||
|     float               render_color[4]; | ||||
|     // An ID containing the object ID, volume ID and instance ID.
 | ||||
|     int                 composite_id; | ||||
|     // Object ID, which is equal to the index of the respective ModelObject in Model.objects array.
 | ||||
|     int                 object_id; | ||||
|     // Volume ID, which is equal to the index of the respective ModelVolume in ModelObject.volumes array.
 | ||||
|     // If negative, it is an index of a geometry produced by the PrintObject for the respective ModelObject,
 | ||||
|     // and which has no associated ModelVolume in ModelObject.volumes. For example, SLA supports.
 | ||||
|     // Volume with a negative volume_id cannot be picked independently, it will pick the associated instance.
 | ||||
|     int                 volume_id; | ||||
|     // Instance ID, which is equal to the index of the respective ModelInstance in ModelObject.instances array.
 | ||||
|     int                 instance_id; | ||||
|     // An ID containing the extruder ID (used to select color).
 | ||||
|     int                 extruder_id; | ||||
|     // Is this object selected?
 | ||||
|  | @ -404,9 +414,9 @@ public: | |||
| 
 | ||||
|     void set_convex_hull(const TriangleMesh& convex_hull); | ||||
| 
 | ||||
|     int                 object_idx() const { return this->composite_id / 1000000; } | ||||
|     int                 volume_idx() const { return (this->composite_id / 1000) % 1000; } | ||||
|     int                 instance_idx() const { return this->composite_id % 1000; } | ||||
|     int                 object_idx() const { return this->object_id; } | ||||
|     int                 volume_idx() const { return this->volume_id; } | ||||
|     int                 instance_idx() const { return this->instance_id; } | ||||
| 
 | ||||
| #if ENABLE_MODELVOLUME_TRANSFORM | ||||
|     Transform3d world_matrix() const { return m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix(); } | ||||
|  | @ -489,6 +499,14 @@ public: | |||
|         const std::string       &color_by, | ||||
|         bool                     use_VBOs); | ||||
| 
 | ||||
|     // Load SLA auxiliary GLVolumes (for support trees or pad).
 | ||||
|     std::vector<int> load_object_auxiliary( | ||||
|         const ModelObject       *model_object, | ||||
|         const SLAPrintObject    *print_object, | ||||
|         int                      obj_idx, | ||||
|         SLAPrintObjectStep       milestone, | ||||
|         bool                     use_VBOs); | ||||
| 
 | ||||
|     int load_wipe_tower_preview( | ||||
|         int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width); | ||||
| 
 | ||||
|  | @ -556,6 +574,7 @@ public: | |||
| 
 | ||||
|     static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); | ||||
|     static void set_print(wxGLCanvas* canvas, Print* print); | ||||
|     static void set_SLA_print(wxGLCanvas* canvas, SLAPrint* print); | ||||
|     static void set_model(wxGLCanvas* canvas, Model* model); | ||||
| 
 | ||||
|     static void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape); | ||||
|  |  | |||
|  | @ -294,6 +294,12 @@ void BackgroundSlicingProcess::stop_internal() | |||
| 	m_print->set_cancel_callback([](){}); | ||||
| } | ||||
| 
 | ||||
| bool BackgroundSlicingProcess::empty() const | ||||
| { | ||||
| 	assert(m_print != nullptr); | ||||
| 	return m_print->empty(); | ||||
| } | ||||
| 
 | ||||
| std::string BackgroundSlicingProcess::validate() | ||||
| { | ||||
| 	assert(m_print != nullptr); | ||||
|  |  | |||
|  | @ -51,11 +51,15 @@ public: | |||
| 	// Useful when the Model or configuration is being changed drastically.
 | ||||
| 	bool reset(); | ||||
| 
 | ||||
| 	// Validate the print. Returns an empty string if valid, returns an error message if invalid.
 | ||||
| 	std::string validate(); | ||||
| 	// Apply config over the print. Returns false, if the new config values caused any of the already
 | ||||
| 	// processed steps to be invalidated, therefore the task will need to be restarted.
 | ||||
| 	Print::ApplyStatus apply(const Model &model, const DynamicPrintConfig &config); | ||||
| 	// After calling apply, the empty() call will report whether there is anything to slice.
 | ||||
| 	bool 		empty() const; | ||||
| 	// Validate the print. Returns an empty string if valid, returns an error message if invalid.
 | ||||
| 	// Call validate before calling start().
 | ||||
| 	std::string validate(); | ||||
| 
 | ||||
| 	// Set the export path of the G-code.
 | ||||
| 	// Once the path is set, the G-code 
 | ||||
| 	void schedule_export(const std::string &path); | ||||
|  |  | |||
|  | @ -1,16 +1,16 @@ | |||
| #include "GLCanvas3D.hpp" | ||||
| 
 | ||||
| #include "../../admesh/stl.h" | ||||
| #include "../../libslic3r/libslic3r.h" | ||||
| #include "../../slic3r/GUI/3DScene.hpp" | ||||
| #include "../../slic3r/GUI/GLShader.hpp" | ||||
| #include "../../slic3r/GUI/GUI.hpp" | ||||
| #include "../../slic3r/GUI/PresetBundle.hpp" | ||||
| #include "../../slic3r/GUI/GLGizmo.hpp" | ||||
| #include "../../libslic3r/ClipperUtils.hpp" | ||||
| #include "../../libslic3r/PrintConfig.hpp" | ||||
| #include "../../libslic3r/GCode/PreviewData.hpp" | ||||
| #include "../../libslic3r/Geometry.hpp" | ||||
| #include "admesh/stl.h" | ||||
| #include "libslic3r/libslic3r.h" | ||||
| #include "slic3r/GUI/3DScene.hpp" | ||||
| #include "slic3r/GUI/GLShader.hpp" | ||||
| #include "slic3r/GUI/GUI.hpp" | ||||
| #include "slic3r/GUI/PresetBundle.hpp" | ||||
| #include "slic3r/GUI/GLGizmo.hpp" | ||||
| #include "libslic3r/ClipperUtils.hpp" | ||||
| #include "libslic3r/PrintConfig.hpp" | ||||
| #include "libslic3r/GCode/PreviewData.hpp" | ||||
| #include "libslic3r/Geometry.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| #include "GUI_ObjectList.hpp" | ||||
| #include "GUI_ObjectManipulation.hpp" | ||||
|  | @ -25,7 +25,8 @@ | |||
| #include <wx/tooltip.h> | ||||
| 
 | ||||
| // Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
 | ||||
| #include "../../libslic3r/Print.hpp" | ||||
| #include "libslic3r/Print.hpp" | ||||
| #include "libslic3r/SLAPrint.hpp" | ||||
| 
 | ||||
| #include <tbb/parallel_for.h> | ||||
| #include <tbb/spin_mutex.h> | ||||
|  | @ -3065,6 +3066,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) | |||
|     , m_toolbar(*this) | ||||
|     , m_config(nullptr) | ||||
|     , m_print(nullptr) | ||||
|     , m_sla_print(nullptr) | ||||
|     , m_model(nullptr) | ||||
|     , m_dirty(true) | ||||
|     , m_initialized(false) | ||||
|  | @ -3247,7 +3249,11 @@ bool GLCanvas3D::move_volume_up(unsigned int id) | |||
|     if ((id > 0) && (id < (unsigned int)m_volumes.volumes.size())) | ||||
|     { | ||||
|         std::swap(m_volumes.volumes[id - 1], m_volumes.volumes[id]); | ||||
|         std::swap(m_volumes.volumes[id - 1]->composite_id, m_volumes.volumes[id]->composite_id); | ||||
|         GLVolume &v1 = *m_volumes.volumes[id - 1]; | ||||
|         GLVolume &v2 = *m_volumes.volumes[id]; | ||||
|         std::swap(v1.object_id,   v2.object_id); | ||||
|         std::swap(v1.volume_id,   v2.volume_id); | ||||
|         std::swap(v1.instance_id, v2.instance_id); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|  | @ -3259,7 +3265,11 @@ bool GLCanvas3D::move_volume_down(unsigned int id) | |||
|     if ((id >= 0) && (id + 1 < (unsigned int)m_volumes.volumes.size())) | ||||
|     { | ||||
|         std::swap(m_volumes.volumes[id + 1], m_volumes.volumes[id]); | ||||
|         std::swap(m_volumes.volumes[id + 1]->composite_id, m_volumes.volumes[id]->composite_id); | ||||
|         GLVolume &v1 = *m_volumes.volumes[id + 1]; | ||||
|         GLVolume &v2 = *m_volumes.volumes[id]; | ||||
|         std::swap(v1.object_id,   v2.object_id); | ||||
|         std::swap(v1.volume_id,   v2.volume_id); | ||||
|         std::swap(v1.instance_id, v2.instance_id); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|  | @ -3276,6 +3286,11 @@ void GLCanvas3D::set_print(Print* print) | |||
|     m_print = print; | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::set_SLA_print(SLAPrint* print) | ||||
| { | ||||
|     m_sla_print = print; | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::set_model(Model* model) | ||||
| { | ||||
|     m_model = model; | ||||
|  | @ -3631,6 +3646,13 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx) | |||
|     return std::vector<int>(); | ||||
| } | ||||
| 
 | ||||
| std::vector<int> GLCanvas3D::load_support_meshes(const Model& model, int obj_idx) | ||||
| { | ||||
|     std::vector<int> volumes = m_volumes.load_object_auxiliary(model.objects[obj_idx], m_sla_print->objects()[obj_idx], obj_idx, slaposSupportTree, m_use_VBOs && m_initialized); | ||||
| 	append(volumes, m_volumes.load_object_auxiliary(model.objects[obj_idx], m_sla_print->objects()[obj_idx], obj_idx, slaposBasePool, m_use_VBOs && m_initialized)); | ||||
|     return volumes; | ||||
| } | ||||
| 
 | ||||
| int GLCanvas3D::get_first_volume_id(int obj_idx) const | ||||
| { | ||||
|     for (int i = 0; i < (int)m_volumes.volumes.size(); ++i) | ||||
|  | @ -3682,11 +3704,14 @@ void GLCanvas3D::reload_scene(bool force) | |||
| 
 | ||||
|     m_reload_delayed = false; | ||||
| 
 | ||||
|     PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); | ||||
|     if (m_regenerate_volumes) | ||||
|     { | ||||
|         for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++obj_idx) | ||||
|         { | ||||
|             load_object(*m_model, obj_idx); | ||||
|             if (printer_technology == ptSLA) | ||||
|                 load_support_meshes(*m_model, obj_idx); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -3694,7 +3719,8 @@ void GLCanvas3D::reload_scene(bool force) | |||
| 
 | ||||
|     if (m_regenerate_volumes) | ||||
|     { | ||||
|         if (m_config->has("nozzle_diameter") && wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) | ||||
|         PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); | ||||
|         if (printer_technology == ptFFF && m_config->has("nozzle_diameter")) | ||||
|         { | ||||
|             // Should the wipe tower be visualized ?
 | ||||
|             unsigned int extruders_count = (unsigned int)dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"))->values.size(); | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ namespace Slic3r { | |||
| 
 | ||||
| class GLShader; | ||||
| class ExPolygon; | ||||
| class SLAPrint; | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
|  | @ -447,17 +448,25 @@ public: | |||
| 
 | ||||
|         struct Cache | ||||
|         { | ||||
|             // Cache of GLVolume derived transformation matrices, valid during mouse dragging.
 | ||||
|             VolumesCache volumes_data; | ||||
|             // Center of the dragged selection, valid during mouse dragging.
 | ||||
|             Vec3d dragging_center; | ||||
|             // Map from indices of ModelObject instances in Model::objects
 | ||||
|             // to a set of indices of ModelVolume instances in ModelObject::instances
 | ||||
|             // Here the index means a position inside the respective std::vector, not ModelID.
 | ||||
|             ObjectIdxsToInstanceIdxsMap content; | ||||
|         }; | ||||
| 
 | ||||
|         // Volumes owned by GLCanvas3D.
 | ||||
|         GLVolumePtrs* m_volumes; | ||||
|         // Model, not owned.
 | ||||
|         Model* m_model; | ||||
| 
 | ||||
|         bool m_valid; | ||||
|         EMode m_mode; | ||||
|         EType m_type; | ||||
|         // set of indices to m_volumes
 | ||||
|         IndicesList m_list; | ||||
|         Cache m_cache; | ||||
|         mutable BoundingBoxf3 m_bounding_box; | ||||
|  | @ -692,6 +701,7 @@ private: | |||
|     Selection m_selection; | ||||
|     DynamicPrintConfig* m_config; | ||||
|     Print* m_print; | ||||
|     SLAPrint* m_sla_print; | ||||
|     Model* m_model; | ||||
| 
 | ||||
|     bool m_dirty; | ||||
|  | @ -745,6 +755,7 @@ public: | |||
| 
 | ||||
|     void set_config(DynamicPrintConfig* config); | ||||
|     void set_print(Print* print); | ||||
|     void set_SLA_print(SLAPrint* print); | ||||
|     void set_model(Model* model); | ||||
| 
 | ||||
|     const Selection& get_selection() const { return m_selection; } | ||||
|  | @ -810,6 +821,9 @@ public: | |||
|     std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs); | ||||
|     std::vector<int> load_object(const Model& model, int obj_idx); | ||||
| 
 | ||||
|     // Load SLA support tree and SLA pad meshes into the scene, if available at the respective SLAPrintObject instances.
 | ||||
|     std::vector<int> load_support_meshes(const Model& model, int obj_idx); | ||||
| 
 | ||||
|     int get_first_volume_id(int obj_idx) const; | ||||
|     int get_in_object_volume_id(int scene_vol_idx) const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -284,6 +284,14 @@ void GLCanvas3DManager::set_print(wxGLCanvas* canvas, Print* print) | |||
|         it->second->set_print(print); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void GLCanvas3DManager::set_SLA_print(wxGLCanvas* canvas, SLAPrint* print) | ||||
| { | ||||
|     CanvasesMap::iterator it = _get_canvas(canvas); | ||||
|     if (it != m_canvases.end()) | ||||
|         it->second->set_SLA_print(print); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3DManager::set_model(wxGLCanvas* canvas, Model* model) | ||||
| { | ||||
|     CanvasesMap::iterator it = _get_canvas(canvas); | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ namespace Slic3r { | |||
| 
 | ||||
| class DynamicPrintConfig; | ||||
| class Print; | ||||
| class SLAPrint; | ||||
| class Model; | ||||
| class ExPolygon; | ||||
| typedef std::vector<ExPolygon> ExPolygons; | ||||
|  | @ -95,6 +96,7 @@ public: | |||
| 
 | ||||
|     void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); | ||||
|     void set_print(wxGLCanvas* canvas, Print* print); | ||||
|     void set_SLA_print(wxGLCanvas* canvas, SLAPrint* print); | ||||
|     void set_model(wxGLCanvas* canvas, Model* model); | ||||
| 
 | ||||
|     void set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape); | ||||
|  |  | |||
|  | @ -494,7 +494,7 @@ void GLGizmoRotate::render_angle() const | |||
| 
 | ||||
| void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const | ||||
| { | ||||
|     double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); | ||||
|     double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset) + 2.0 * (double)m_axis * box.max_size() * (double)Grabber::SizeFactor; | ||||
|     m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); | ||||
|     m_grabbers[0].angles(2) = m_angle; | ||||
| 
 | ||||
|  |  | |||
|  | @ -482,18 +482,16 @@ ConfigMenuIDs GUI_App::get_view_mode() | |||
| // Update view mode according to selected menu
 | ||||
| void GUI_App::update_mode() | ||||
| { | ||||
|     wxWindowUpdateLocker noUpdates(mainframe->m_plater); | ||||
|     wxWindowUpdateLocker noUpdates(&sidebar()); | ||||
| 
 | ||||
|     ConfigMenuIDs mode = wxGetApp().get_view_mode(); | ||||
| 
 | ||||
|     obj_list()->get_sizer()->Show(mode == ConfigMenuModeExpert); | ||||
|     sidebar().show_info_sizer(mode == ConfigMenuModeExpert); | ||||
|     sidebar().set_mode_value(mode); | ||||
|     sidebar().show_buttons(mode == ConfigMenuModeExpert); | ||||
|     obj_manipul()->show_object_name(mode == ConfigMenuModeSimple); | ||||
|     obj_list()->update_manipulation_sizer(mode == ConfigMenuModeSimple); | ||||
|     obj_list()->update_selections(); | ||||
| 
 | ||||
|     sidebar().Layout(); | ||||
|     mainframe->m_plater->Layout(); | ||||
| 
 | ||||
|     ConfigOptionMode opt_mode = mode == ConfigMenuModeSimple ? comSimple : | ||||
|                                 mode == ConfigMenuModeExpert ? comExpert : comAdvanced; | ||||
|  |  | |||
|  | @ -823,9 +823,12 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int | |||
| #endif //no __WXOSX__ //__WXMSW__
 | ||||
| } | ||||
| 
 | ||||
| void ObjectList::del_object(const int obj_idx) | ||||
| { | ||||
|     wxGetApp().plater()->delete_object_from_model(obj_idx); | ||||
| } | ||||
| 
 | ||||
| // Delete subobject
 | ||||
| 
 | ||||
| void ObjectList::del_subobject_item(wxDataViewItem& item) | ||||
| { | ||||
|     if (!item) return; | ||||
|  | @ -1016,7 +1019,6 @@ void ObjectList::part_selection_changed() | |||
| 
 | ||||
|     bool update_and_show_manipulations = false; | ||||
|     bool update_and_show_settings = false; | ||||
|     bool show_info_sizer = false; | ||||
| 
 | ||||
|     if (multiple_selection()) { | ||||
|         og_name = _(L("Group manipulation")); | ||||
|  | @ -1033,7 +1035,6 @@ void ObjectList::part_selection_changed() | |||
|                 og_name = _(L("Object manipulation")); | ||||
|                 m_config = &(*m_objects)[obj_idx]->config; | ||||
|                 update_and_show_manipulations = true; | ||||
|                 show_info_sizer = true; | ||||
|             } | ||||
|             else { | ||||
|                 auto parent = m_objects_model->GetParent(item); | ||||
|  | @ -1082,25 +1083,15 @@ void ObjectList::part_selection_changed() | |||
|     if (update_and_show_settings) | ||||
|         wxGetApp().obj_settings()->get_og()->set_name(" " + og_name + " "); | ||||
| 
 | ||||
|     auto panel = wxGetApp().sidebar().scrolled_panel(); | ||||
|     panel->Freeze(); | ||||
|     Sidebar& panel = wxGetApp().sidebar(); | ||||
|     panel.Freeze(); | ||||
| 
 | ||||
|     wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations); | ||||
|     wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings); | ||||
|     show_info_sizer ? wxGetApp().sidebar().update_info_sizer() : wxGetApp().sidebar().show_info_sizer(false); | ||||
|     wxGetApp().sidebar().show_info_sizer(); | ||||
| 
 | ||||
|     panel->Thaw(); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::update_manipulation_sizer(const bool is_simple_mode) | ||||
| { | ||||
|     auto item = GetSelection(); /// #ys_FIXME_to_multi_sel
 | ||||
|     if (!item || !is_simple_mode) | ||||
|         return; | ||||
| 
 | ||||
|     if (m_objects_model->IsSettingsItem(item)) { | ||||
|         select_item(m_objects_model->GetParent(item)); | ||||
|     } | ||||
|     panel.Layout(); | ||||
|     panel.Thaw(); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::add_object_to_list(size_t obj_idx) | ||||
|  | @ -1167,6 +1158,49 @@ void ObjectList::delete_volume_from_list(const size_t obj_idx, const size_t vol_ | |||
|     select_item(m_objects_model->Delete(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx))); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::delete_instance_from_list(const size_t obj_idx, const size_t inst_idx) | ||||
| { | ||||
|     select_item(m_objects_model->Delete(m_objects_model->GetItemByInstanceId(obj_idx, inst_idx))); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::delete_from_model_and_list(const ItemType type, const int obj_idx, const int sub_obj_idx) | ||||
| { | ||||
|     if ( !(type&(itObject|itVolume|itInstance)) ) | ||||
|         return; | ||||
| 
 | ||||
|     if (type&itObject) { | ||||
|         del_object(obj_idx); | ||||
|         delete_object_from_list(obj_idx); | ||||
|     } | ||||
|     else { | ||||
|         del_subobject_from_object(obj_idx, sub_obj_idx, type); | ||||
| 
 | ||||
|         type == itVolume ? delete_volume_from_list(obj_idx, sub_obj_idx) : | ||||
|             delete_instance_from_list(obj_idx, sub_obj_idx); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete> * items_for_delete) | ||||
| { | ||||
|     for (auto& item : *items_for_delete) | ||||
|     { | ||||
|         if ( !(item.type&(itObject|itVolume|itInstance)) ) | ||||
|             continue; | ||||
|         if (item.type&itObject) { | ||||
|             del_object(item.obj_idx); | ||||
|             m_objects_model->Delete(m_objects_model->GetItemById(item.obj_idx)); | ||||
|         } | ||||
|         else { | ||||
|             del_subobject_from_object(item.obj_idx, item.sub_obj_idx, item.type); | ||||
|             if (item.type&itVolume) | ||||
|                 m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item.obj_idx, item.sub_obj_idx)); | ||||
|             else | ||||
|                 m_objects_model->Delete(m_objects_model->GetItemByInstanceId(item.obj_idx, item.sub_obj_idx)); | ||||
|         } | ||||
|     } | ||||
|     part_selection_changed(); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::delete_all_objects_from_list() | ||||
| { | ||||
|     m_objects_model->DeleteAll(); | ||||
|  |  | |||
|  | @ -5,7 +5,9 @@ | |||
| #include <wx/dataview.h> | ||||
| #include <map> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "Event.hpp" | ||||
| #include "wxExtensions.hpp" | ||||
| 
 | ||||
| class wxBoxSizer; | ||||
| class PrusaObjectDataViewModel; | ||||
|  | @ -20,6 +22,13 @@ namespace GUI { | |||
| 
 | ||||
| wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); | ||||
| 
 | ||||
| struct ItemForDelete | ||||
| { | ||||
|     ItemType    type; | ||||
|     int         obj_idx;  | ||||
|     int         sub_obj_idx; | ||||
| }; | ||||
| 
 | ||||
| class ObjectList : public wxDataViewCtrl | ||||
| { | ||||
|     wxBoxSizer          *m_sizer {nullptr}; | ||||
|  | @ -92,6 +101,7 @@ public: | |||
|     void                load_subobject(int type); | ||||
|     void                load_part(ModelObject* model_object, wxArrayString& part_names, int type); | ||||
|     void                load_generic_subobject(const std::string& type_name, const int type); | ||||
|     void                del_object(const int obj_idx); | ||||
|     void                del_subobject_item(wxDataViewItem& item); | ||||
|     void                del_settings_from_config(); | ||||
|     void                del_instances_from_object(const int obj_idx); | ||||
|  | @ -110,14 +120,15 @@ public: | |||
|     void                 parts_changed(int obj_idx); | ||||
|     void                 part_selection_changed(); | ||||
| 
 | ||||
|     void                 update_manipulation_sizer(const bool is_simple_mode); | ||||
| 
 | ||||
|     // Add object to the list
 | ||||
|     void add_object_to_list(size_t obj_idx); | ||||
|     // Delete object from the list
 | ||||
|     void delete_object_from_list(); | ||||
|     void delete_object_from_list(const size_t obj_idx); | ||||
|     void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx); | ||||
|     void delete_instance_from_list(const size_t obj_idx, const size_t inst_idx); | ||||
|     void delete_from_model_and_list(const ItemType type, const int obj_idx, const int sub_obj_idx); | ||||
|     void delete_from_model_and_list(const std::vector<ItemForDelete> * items_for_delete); | ||||
|     // Delete all objects from the list
 | ||||
|     void delete_all_objects_from_list(); | ||||
|     // Increase instances count
 | ||||
|  |  | |||
|  | @ -87,7 +87,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent): | |||
|         if (option_name == "Rotation") | ||||
|             def.min = -360; | ||||
|         else | ||||
|             def.min == -1000; | ||||
|             def.min = -1000; | ||||
| 
 | ||||
|         const std::string lower_name = boost::algorithm::to_lower_copy(option_name); | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ void OG_Settings::Hide() | |||
| void OG_Settings::UpdateAndShow(const bool show) | ||||
| { | ||||
|     Show(show); | ||||
|     m_parent->Layout(); | ||||
| //     m_parent->Layout();
 | ||||
| } | ||||
| 
 | ||||
| wxSizer* OG_Settings::get_sizer() | ||||
|  |  | |||
|  | @ -447,7 +447,7 @@ struct Sidebar::priv | |||
| 
 | ||||
| void Sidebar::priv::show_preset_comboboxes() | ||||
| { | ||||
|     const bool showSLA = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA; | ||||
|     const bool showSLA = plater->printer_technology() == ptSLA; | ||||
| 
 | ||||
|     wxWindowUpdateLocker noUpdates_scrolled(scrolled); | ||||
| //     scrolled->Freeze();
 | ||||
|  | @ -630,9 +630,8 @@ void Sidebar::update_presets(Preset::Type preset_type) | |||
| 
 | ||||
| 	case Preset::TYPE_PRINTER: | ||||
| 	{ | ||||
| 		PrinterTechnology printer_technology = preset_bundle.printers.get_edited_preset().printer_technology(); | ||||
| 		// Update the print choosers to only contain the compatible presets, update the dirty flags.
 | ||||
| 		if (printer_technology == ptFFF) | ||||
| 		if (p->plater->printer_technology() == ptFFF) | ||||
| 			preset_bundle.prints.update_platter_ui(p->combo_print); | ||||
| 		else | ||||
| 			preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); | ||||
|  | @ -640,7 +639,7 @@ void Sidebar::update_presets(Preset::Type preset_type) | |||
| 		preset_bundle.printers.update_platter_ui(p->combo_printer); | ||||
| 		// Update the filament choosers to only contain the compatible presets, update the color preview,
 | ||||
| 		// update the dirty flags.
 | ||||
|         if (printer_technology == ptFFF) { | ||||
| 		if (p->plater->printer_technology() == ptFFF) { | ||||
|             for (size_t i = 0; i < p->combos_filament.size(); ++ i) | ||||
|                 preset_bundle.update_platter_filament_ui(i, p->combos_filament[i]); | ||||
| 		} | ||||
|  | @ -690,32 +689,31 @@ void Sidebar::update_objects_list_extruder_column(int extruders_count) | |||
|     p->object_list->update_objects_list_extruder_column(extruders_count); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::show_info_sizer(const bool show) | ||||
| void Sidebar::show_info_sizer() | ||||
| { | ||||
|     p->object_info->show_sizer(show); | ||||
|     p->scrolled->Layout(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::update_info_sizer() | ||||
| { | ||||
|     wxWindowUpdateLocker freeze_guard(p->scrolled); | ||||
| 
 | ||||
|     if (/*obj_idx < 0 || */!p->plater->is_single_full_object_selection()) { | ||||
|     if (!p->plater->is_single_full_object_selection() || | ||||
|         m_mode < ConfigMenuModeExpert ) { | ||||
|         p->object_info->Show(false); | ||||
|         p->scrolled->Layout(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     int obj_idx = p->plater->get_selected_object_idx(); | ||||
| 
 | ||||
|     const ModelObject* model_object = (*wxGetApp().model_objects())[obj_idx]; | ||||
|     // hack to avoid crash when deleting the last object on the bed
 | ||||
|     if (model_object->volumes.empty()) | ||||
|     { | ||||
|         p->object_info->Show(false); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const ModelInstance* model_instance = !model_object->instances.empty() ? model_object->instances.front() : nullptr; | ||||
| 
 | ||||
|     auto size = model_object->instance_bounding_box(0).size();     | ||||
|     p->object_info->info_size->SetLabel(wxString::Format("%.2f x %.2f x %.2f",size(0), size(1), size(2))); | ||||
|     p->object_info->info_materials->SetLabel(wxString::Format("%d", static_cast<int>(model_object->materials_count()))); | ||||
| 
 | ||||
|     auto& stats = model_object->volumes[0]->mesh.stl.stats; | ||||
|     auto& stats = model_object->volumes.front()->mesh.stl.stats; | ||||
|     auto sf = model_instance->get_scaling_factor(); | ||||
|     p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume * sf(0) * sf(1) * sf(2))); | ||||
|     p->object_info->info_facets->SetLabel(wxString::Format(_(L("%d (%d shells)")), static_cast<int>(model_object->facets_count()), stats.number_of_parts)); | ||||
|  | @ -743,12 +741,11 @@ void Sidebar::update_info_sizer() | |||
|     } | ||||
| 
 | ||||
|     p->object_info->show_sizer(true); | ||||
|     p->scrolled->Layout(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::show_sliced_info_sizer(const bool show)  | ||||
| { | ||||
|     wxWindowUpdateLocker freeze_guard(p->scrolled); | ||||
|     wxWindowUpdateLocker freeze_guard(this); | ||||
| 
 | ||||
|     p->sliced_info->Show(show); | ||||
|     if (show) { | ||||
|  | @ -777,7 +774,7 @@ void Sidebar::show_sliced_info_sizer(const bool show) | |||
|         p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->print().wipe_tower_data().number_of_toolchanges) : "N/A"); | ||||
|     } | ||||
| 
 | ||||
|     p->scrolled->Layout(); | ||||
|     Layout(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::show_buttons(const bool show) | ||||
|  | @ -787,7 +784,7 @@ void Sidebar::show_buttons(const bool show) | |||
|         TabPrinter *tab = dynamic_cast<TabPrinter*>(wxGetApp().tab_panel()->GetPage(i)); | ||||
|         if (!tab) | ||||
|             continue; | ||||
|         if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) { | ||||
| 		if (p->plater->printer_technology() == ptFFF) { | ||||
|             p->btn_send_gcode->Show(show && !tab->m_config->opt_string("print_host").empty()); | ||||
|         } | ||||
|         break; | ||||
|  | @ -877,10 +874,11 @@ struct Plater::priv | |||
| 
 | ||||
|     // Data
 | ||||
|     Slic3r::DynamicPrintConfig *config; | ||||
|     Slic3r::Print print; | ||||
| 	Slic3r::SLAPrint sla_print; | ||||
|     Slic3r::Model model; | ||||
|     Slic3r::GCodePreviewData gcode_preview_data; | ||||
|     Slic3r::Print               print; | ||||
| 	Slic3r::SLAPrint            sla_print; | ||||
|     Slic3r::Model               model; | ||||
|     PrinterTechnology           printer_technology = ptFFF; | ||||
|     Slic3r::GCodePreviewData    gcode_preview_data; | ||||
| 
 | ||||
|     // GUI elements
 | ||||
|     wxNotebook *notebook; | ||||
|  | @ -916,14 +914,28 @@ struct Plater::priv | |||
|     void object_list_changed(); | ||||
| 
 | ||||
|     void remove(size_t obj_idx); | ||||
|     void delete_object_from_model(size_t obj_idx); | ||||
|     void reset(); | ||||
|     void mirror(Axis axis); | ||||
|     void arrange(); | ||||
|     void split_object(); | ||||
|     void split_volume(); | ||||
|     void schedule_background_process(); | ||||
|     // Update background processing thread from the current config and Model.
 | ||||
|     enum UpdateBackgroundProcessReturnState { | ||||
|         // update_background_process() reports, that the Print / SLAPrint was updated in a way,
 | ||||
|         // that the background process was invalidated and it needs to be re-run.
 | ||||
|         UPDATE_BACKGROUND_PROCESS_RESTART = 1, | ||||
|         // update_background_process() reports, that the Print / SLAPrint was updated in a way,
 | ||||
|         // that a scene needs to be refreshed (you should call _3DScene::reload_scene(canvas3D, false))
 | ||||
|         UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2,    | ||||
|         // update_background_process() reports, that the Print / SLAPrint is invalid, and the error message
 | ||||
|         // was sent to the status line.
 | ||||
|         UPDATE_BACKGROUND_PROCESS_INVALID = 4, | ||||
|     }; | ||||
|     // returns bit mask of UpdateBackgroundProcessReturnState
 | ||||
|     unsigned int update_background_process(); | ||||
|     void async_apply_config(); | ||||
|     void start_background_process(); | ||||
|     void reload_from_disk(); | ||||
|     void export_object_stl(); | ||||
|     void fix_through_netfabb(const int obj_idx); | ||||
|  | @ -989,7 +1001,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : | |||
|     background_process.set_sliced_event(EVT_SLICING_COMPLETED); | ||||
|     background_process.set_finished_event(EVT_PROCESS_COMPLETED); | ||||
| 	// Default printer technology for default config.
 | ||||
|     background_process.select_technology(q->printer_technology()); | ||||
|     background_process.select_technology(this->printer_technology); | ||||
|     // Register progress callback from the Print class to the Platter.
 | ||||
| 
 | ||||
|     auto statuscb = [this](int percent, const std::string &message) { | ||||
|  | @ -1013,6 +1025,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : | |||
|     // XXX: more config from 3D.pm
 | ||||
|     _3DScene::set_model(canvas3D, &model); | ||||
|     _3DScene::set_print(canvas3D, &print); | ||||
|     _3DScene::set_SLA_print(canvas3D, &sla_print); | ||||
|     _3DScene::set_config(canvas3D, config); | ||||
|     _3DScene::enable_gizmos(canvas3D, true); | ||||
|     _3DScene::enable_toolbar(canvas3D, true); | ||||
|  | @ -1095,6 +1108,11 @@ void Plater::priv::update(bool force_autocenter) | |||
|         model.center_instances_around_point(bed_center); | ||||
|     } | ||||
| 
 | ||||
|     if (this->printer_technology == ptSLA) { | ||||
|         // Update the SLAPrint from the current Model, so that the reload_scene()
 | ||||
|         // pulls the correct data.
 | ||||
|         this->update_background_process(); | ||||
|     } | ||||
|     _3DScene::reload_scene(canvas3D, false); | ||||
|     preview->reset_gcode_preview_data(); | ||||
|     preview->reload_print(); | ||||
|  | @ -1416,8 +1434,6 @@ void Plater::priv::selection_changed() | |||
|     _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed()); | ||||
|     // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
 | ||||
|     _3DScene::render(canvas3D); | ||||
| 
 | ||||
|     sidebar->update_info_sizer(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::object_list_changed() | ||||
|  | @ -1450,6 +1466,12 @@ void Plater::priv::remove(size_t obj_idx) | |||
|     update(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Plater::priv::delete_object_from_model(size_t obj_idx) | ||||
| { | ||||
|     model.delete_object(obj_idx); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::reset() | ||||
| { | ||||
|     // Prevent toolpaths preview from rendering while we modify the Print object
 | ||||
|  | @ -1610,10 +1632,18 @@ void Plater::priv::schedule_background_process() | |||
|     this->background_process_timer.Start(500, wxTIMER_ONE_SHOT); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::async_apply_config() | ||||
| // Update background processing thread from the current config and Model.
 | ||||
| // Returns a bitmask of UpdateBackgroundProcessReturnState.
 | ||||
| unsigned int Plater::priv::update_background_process() | ||||
| { | ||||
|     // bitmap of enum UpdateBackgroundProcessReturnState
 | ||||
|     unsigned int return_state = 0; | ||||
| 
 | ||||
|     // If the async_apply_config() was not called by the timer, kill the timer, so the async_apply_config()
 | ||||
|     // will not be called again in vain.
 | ||||
|     this->background_process_timer.Stop(); | ||||
| 
 | ||||
|     DynamicPrintConfig config = wxGetApp().preset_bundle->full_config(); | ||||
|     auto            printer_technology = config.opt_enum<PrinterTechnology>("printer_technology"); | ||||
|     BoundingBox     bed_box_2D = get_extents(Polygon::new_scale(config.opt<ConfigOptionPoints>("bed_shape")->values)); | ||||
|     BoundingBoxf3   print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(config.opt_float("max_print_height")))); | ||||
|     // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
 | ||||
|  | @ -1634,40 +1664,55 @@ void Plater::priv::async_apply_config() | |||
|         // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
 | ||||
|         // Otherwise they will be just refreshed.
 | ||||
|         this->gcode_preview_data.reset(); | ||||
|         if (printer_technology == ptFFF) { | ||||
|         switch (this->printer_technology) { | ||||
|         case ptFFF: | ||||
|             if (this->preview != nullptr) | ||||
|                 // If the preview is not visible, the following line just invalidates the preview,
 | ||||
|                 // but the G-code paths are calculated first once the preview is made visible.
 | ||||
|                 this->preview->reload_print(); | ||||
|             // We also need to reload 3D scene because of the wipe tower preview box
 | ||||
|             if (this->config->opt_bool("wipe_tower")) { | ||||
|     //            std::vector<int> selections = this->collect_selections();
 | ||||
|     //            Slic3r::_3DScene::set_objects_selections(this->canvas3D, selections);
 | ||||
|     //            Slic3r::_3DScene::reload_scene(this->canvas3D, 1);
 | ||||
|                 return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE; | ||||
|             } | ||||
|             break; | ||||
|         case ptSLA: | ||||
|             //FIXME as of now the Print::APPLY_STATUS_INVALIDATED is not reliable, and
 | ||||
|             // currently the scene refresh is expensive and loses selection.
 | ||||
|             //return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
 | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->get_config("background_processing") == "1" && | ||||
|         this->background_process.start()) | ||||
| 		this->statusbar()->set_cancel_callback([this]() { | ||||
|             this->statusbar()->set_status_text(L("Cancelling")); | ||||
| 			this->background_process.stop(); | ||||
|         }); | ||||
| 
 | ||||
|     if (! this->background_process.empty()) { | ||||
|         std::string err = this->background_process.validate(); | ||||
|         if (err.empty()) { | ||||
|             if (invalidated != Print::APPLY_STATUS_UNCHANGED) | ||||
|                 return_state |= UPDATE_BACKGROUND_PROCESS_RESTART; | ||||
|         } else { | ||||
|             // The print is not valid.
 | ||||
|             GUI::show_error(this->q, _(err)); | ||||
|             return_state |= UPDATE_BACKGROUND_PROCESS_INVALID; | ||||
|         } | ||||
|     } | ||||
|     return return_state; | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::start_background_process() | ||||
| void Plater::priv::async_apply_config() | ||||
| { | ||||
| 	if (this->background_process.running()) | ||||
| 		return; | ||||
|     // Don't start process thread if Print is not valid.
 | ||||
|     std::string err = this->background_process.validate(); | ||||
|     if (! err.empty()) { | ||||
|         this->statusbar()->set_status_text(err); | ||||
| 	} else { | ||||
| 		// Copy the names of active presets into the placeholder parser.
 | ||||
|         //FIXME how to generate a file name for the SLA printers?
 | ||||
| 		wxGetApp().preset_bundle->export_selections(this->q->print().placeholder_parser()); | ||||
| 		// Start the background process.
 | ||||
| 		this->background_process.start(); | ||||
| 	} | ||||
|     // bitmask of UpdateBackgroundProcessReturnState
 | ||||
|     unsigned int state = this->update_background_process(); | ||||
|     if (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) | ||||
|         _3DScene::reload_scene(canvas3D, false); | ||||
|     if ((state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 && this->get_config("background_processing") == "1") { | ||||
|         // The print is valid and it can be started.
 | ||||
|         if (this->background_process.start()) | ||||
|             this->statusbar()->set_cancel_callback([this]() { | ||||
|                 this->statusbar()->set_status_text(L("Cancelling")); | ||||
|                 this->background_process.stop(); | ||||
|             }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::reload_from_disk() | ||||
|  | @ -1716,6 +1761,13 @@ void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) | |||
|     const auto current_id = notebook->GetCurrentPage()->GetId(); | ||||
|     if (current_id == canvas3D->GetId()) { | ||||
|         if (_3DScene::is_reload_delayed(canvas3D)) { | ||||
|             // Delayed loading of the 3D scene.
 | ||||
|             if (this->printer_technology == ptSLA) { | ||||
|                 // Update the SLAPrint from the current Model, so that the reload_scene()
 | ||||
|                 // pulls the correct data.
 | ||||
|                 if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART) | ||||
|                     this->schedule_background_process(); | ||||
|             } | ||||
|             _3DScene::reload_scene(canvas3D, true); | ||||
|         } | ||||
|         // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
 | ||||
|  | @ -1811,22 +1863,18 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) | |||
|     //$self->object_list_changed;
 | ||||
|      | ||||
|     // refresh preview
 | ||||
|     if (this->preview != nullptr) | ||||
|         this->preview->reload_print(); | ||||
| 
 | ||||
|     // TODO: this needs to be implemented somehow
 | ||||
|     if(q->printer_technology() == PrinterTechnology::ptSLA) { | ||||
| 
 | ||||
|         class Renderer: public SLASupportRenderer { | ||||
|         public: | ||||
|             void add_pillar(const Mesh&, ClickCb ) override {} | ||||
|             void add_head(const Mesh&, ClickCb) override {} | ||||
|             void add_bridge(const Mesh&, ClickCb) override {} | ||||
|             void add_junction(const Mesh&, ClickCb) override {} | ||||
|             void add_pad(const Mesh&, ClickCb) override {} | ||||
|         } renderer; | ||||
| 
 | ||||
|         sla_print.render_supports(renderer); | ||||
|     switch (this->printer_technology) { | ||||
|     case ptFFF: | ||||
|         if (this->preview != nullptr) | ||||
|             this->preview->reload_print(); | ||||
|         break; | ||||
|     case ptSLA: | ||||
|         // Update the SLAPrint from the current Model, so that the reload_scene()
 | ||||
|         // pulls the correct data.
 | ||||
|         if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART) | ||||
|             this->schedule_background_process(); | ||||
|         _3DScene::reload_scene(canvas3D, true); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -2069,6 +2117,7 @@ void Plater::update(bool force_autocenter) { p->update(force_autocenter); } | |||
| void Plater::select_view(const std::string& direction) { p->select_view(direction); } | ||||
| 
 | ||||
| void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } | ||||
| void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_model(obj_idx); } | ||||
| 
 | ||||
| void Plater::remove_selected() | ||||
| { | ||||
|  | @ -2285,21 +2334,24 @@ void Plater::export_3mf() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Plater::reslice() | ||||
| { | ||||
|     // explicitly cancel a previous thread and start a new one.
 | ||||
|     // Don't reslice if export of G-code or sending to OctoPrint is running.
 | ||||
| //    if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) {
 | ||||
|     // Stop the background processing threads, stop the async update timer.
 | ||||
| //    this->p->stop_background_process();
 | ||||
|     // Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
 | ||||
|     this->p->async_apply_config(); | ||||
| 	this->p->statusbar()->set_cancel_callback([this]() { | ||||
| 		this->p->statusbar()->set_status_text(L("Cancelling")); | ||||
| 		this->p->background_process.stop(); | ||||
|     }); | ||||
|     this->p->start_background_process(); | ||||
|     //FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
 | ||||
|     // bitmask of UpdateBackgroundProcessReturnState
 | ||||
|     unsigned int state = this->p->update_background_process(); | ||||
|     if (state & priv::UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) | ||||
|         _3DScene::reload_scene(this->p->canvas3D, false); | ||||
| 	if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) == 0 && !this->p->background_process.running()) { | ||||
|         // The print is valid and it can be started.
 | ||||
|         // Copy the names of active presets into the placeholder parser.
 | ||||
|         //FIXME how to generate a file name for the SLA printers?
 | ||||
|         wxGetApp().preset_bundle->export_selections(this->print().placeholder_parser()); | ||||
|         if (this->p->background_process.start()) | ||||
| 			this->p->statusbar()->set_cancel_callback([this]() { | ||||
| 				this->p->statusbar()->set_status_text(L("Cancelling")); | ||||
| 				this->p->background_process.stop(); | ||||
|             }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::send_gcode() | ||||
|  | @ -2338,8 +2390,10 @@ void Plater::on_config_change(const DynamicPrintConfig &config) | |||
|     bool update_scheduled = false; | ||||
|     for (auto opt_key : p->config->diff(config)) { | ||||
|         p->config->set_key_value(opt_key, config.option(opt_key)->clone()); | ||||
|         if (opt_key == "printer_technology") | ||||
| 			p->background_process.select_technology(config.opt_enum<PrinterTechnology>(opt_key)); | ||||
|         if (opt_key == "printer_technology") { | ||||
|             p->printer_technology = config.opt_enum<PrinterTechnology>(opt_key); | ||||
| 			p->background_process.select_technology(this->printer_technology()); | ||||
|         } | ||||
|         else if (opt_key  == "bed_shape") { | ||||
|             if (p->canvas3D) _3DScene::set_bed_shape(p->canvas3D, p->config->option<ConfigOptionPoints>(opt_key)->values); | ||||
|             if (p->preview) p->preview->set_bed_shape(p->config->option<ConfigOptionPoints>(opt_key)->values); | ||||
|  | @ -2393,7 +2447,7 @@ int Plater::get_selected_object_idx() | |||
|     return p->get_selected_object_idx(); | ||||
| } | ||||
| 
 | ||||
| bool Plater::is_single_full_object_selection() | ||||
| bool Plater::is_single_full_object_selection() const | ||||
| { | ||||
|     return p->get_selection().is_single_full_object(); | ||||
| } | ||||
|  | @ -2405,7 +2459,7 @@ wxGLCanvas* Plater::canvas3D() | |||
| 
 | ||||
| PrinterTechnology Plater::printer_technology() const | ||||
| { | ||||
|     return wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); | ||||
|     return p->printer_technology; | ||||
| } | ||||
| 
 | ||||
| void Plater::changed_object(int obj_idx) | ||||
|  |  | |||
|  | @ -62,6 +62,7 @@ enum ButtonAction | |||
| 
 | ||||
| class Sidebar : public wxPanel | ||||
| { | ||||
|     /*ConfigMenuIDs*/int    m_mode; | ||||
| public: | ||||
|     Sidebar(Plater *parent); | ||||
|     Sidebar(Sidebar &&) = delete; | ||||
|  | @ -82,13 +83,13 @@ public: | |||
|     ConfigOptionsGroup*     og_freq_chng_params(); | ||||
|     wxButton*               get_wiping_dialog_button(); | ||||
|     void                    update_objects_list_extruder_column(int extruders_count); | ||||
|     void                    show_info_sizer(const bool show); | ||||
|     void                    update_info_sizer(); | ||||
|     void                    show_info_sizer(); | ||||
|     void                    show_sliced_info_sizer(const bool show); | ||||
|     void                    show_buttons(const bool show); | ||||
|     void                    show_button(ButtonAction but_action, bool show); | ||||
|     void                    enable_buttons(bool enable); | ||||
|     bool                    is_multifilament(); | ||||
|     void                    set_mode_value(const /*ConfigMenuIDs*/int mode) { m_mode = mode; } | ||||
| 
 | ||||
|     std::vector<PresetComboBox*>& combos_filament(); | ||||
| private: | ||||
|  | @ -118,6 +119,7 @@ public: | |||
|     void select_view(const std::string& direction); | ||||
| 
 | ||||
|     void remove(size_t obj_idx); | ||||
|     void delete_object_from_model(size_t obj_idx); | ||||
|     void remove_selected(); | ||||
|     void increase_instances(size_t num = 1); | ||||
|     void decrease_instances(size_t num = 1); | ||||
|  | @ -137,7 +139,7 @@ public: | |||
|     void on_config_change(const DynamicPrintConfig &config); | ||||
| 
 | ||||
|     int get_selected_object_idx(); | ||||
|     bool is_single_full_object_selection(); | ||||
|     bool is_single_full_object_selection() const; | ||||
|     wxGLCanvas* canvas3D(); | ||||
| 
 | ||||
|     PrinterTechnology printer_technology() const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros