mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	ENH: support text modify
Change-Id: Ide5a3c7df5f3ea4395821a65807d79b459f3e46e (cherry picked from commit 55de44d4c80c545de14466aa039a7b0ac144f395)
This commit is contained in:
		
							parent
							
								
									e70253cf25
								
							
						
					
					
						commit
						1c5c9bd3d2
					
				
					 6 changed files with 148 additions and 11 deletions
				
			
		|  | @ -650,6 +650,19 @@ private: | |||
|     friend class ModelVolume; | ||||
| }; | ||||
| 
 | ||||
| struct TextInfo | ||||
| { | ||||
|     std::string m_font_name; | ||||
|     float       m_font_size     = 16.f; | ||||
|     int         m_curr_font_idx = 0; | ||||
|     bool        m_bold          = true; | ||||
|     bool        m_italic        = false; | ||||
|     float       m_thickness     = 2.f; | ||||
|     std::string m_text; | ||||
| 
 | ||||
|     template<typename Archive> void serialize(Archive &ar) { ar(m_font_name, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_text); } | ||||
| }; | ||||
| 
 | ||||
| // An object STL, or a modifier volume, over which a different set of parameters shall be applied.
 | ||||
| // ModelVolume instances are owned by a ModelObject.
 | ||||
| class ModelVolume final : public ObjectBase | ||||
|  | @ -799,6 +812,9 @@ public: | |||
|     void convert_from_imperial_units(); | ||||
|     void convert_from_meters(); | ||||
| 
 | ||||
|     void set_text_info(const TextInfo& text_info) { m_text_info = text_info; } | ||||
|     const TextInfo& get_text_info() const { return m_text_info; } | ||||
| 
 | ||||
|     const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } | ||||
| 
 | ||||
| 	void set_new_unique_id() { | ||||
|  | @ -843,6 +859,8 @@ private: | |||
|     mutable Polygon                     m_cached_2d_polygon;   //BBS, used for convex_hell_2d acceleration
 | ||||
|     Geometry::Transformation        	m_transformation; | ||||
| 
 | ||||
|     TextInfo m_text_info; | ||||
| 
 | ||||
|     //BBS: add convex_hell_2d related logic
 | ||||
|     void  calculate_convex_hull_2d(const Geometry::Transformation &transformation) const; | ||||
| 
 | ||||
|  | @ -961,7 +979,7 @@ private: | |||
|         // BBS: add backup, check modify
 | ||||
|         bool mesh_changed = false; | ||||
|         auto tr = m_transformation; | ||||
|         ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull); | ||||
|         ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, m_text_info); | ||||
|         mesh_changed |= !(tr == m_transformation); | ||||
|         if (mesh_changed) m_transformation.get_matrix(true, true, true, true); // force dirty
 | ||||
|         auto t = supported_facets.timestamp(); | ||||
|  | @ -987,7 +1005,7 @@ private: | |||
| 	} | ||||
| 	template<class Archive> void save(Archive &ar) const { | ||||
| 		bool has_convex_hull = m_convex_hull.get() != nullptr; | ||||
|         ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull); | ||||
|         ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, m_text_info); | ||||
|         cereal::save_by_value(ar, supported_facets); | ||||
|         cereal::save_by_value(ar, seam_facets); | ||||
|         cereal::save_by_value(ar, mmu_segmentation_facets); | ||||
|  |  | |||
|  | @ -2158,7 +2158,7 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name | |||
| #endif /* _DEBUG */ | ||||
| } | ||||
| 
 | ||||
| void ObjectList::load_mesh_part(const TriangleMesh& mesh, const wxString& name, bool center) | ||||
| void ObjectList::load_mesh_part(const TriangleMesh &mesh, const wxString &name, const TextInfo &text_info, bool center) | ||||
| { | ||||
|     wxDataViewItem item = GetSelection(); | ||||
|     // we can add volumes for Object or Instance
 | ||||
|  | @ -2181,9 +2181,11 @@ void ObjectList::load_mesh_part(const TriangleMesh& mesh, const wxString& name, | |||
| 
 | ||||
|     ModelVolume* mv = mo->add_volume(mesh); | ||||
|     Vec3d instance_bbox = mo->mesh().bounding_box().size(); | ||||
|     Vec3d offset = Vec3d(0, 0, instance_bbox[2] / 2); | ||||
|     Vec3d offset = Vec3d(0, 0, instance_bbox[2] / 2 + mv->get_offset(Axis::Z)); | ||||
|     mv->set_offset(offset); | ||||
|     mv->name = name.ToStdString(); | ||||
|     if (!text_info.m_text.empty()) | ||||
|         mv->set_text_info(text_info); | ||||
| 
 | ||||
|     std::vector<ModelVolume*> volumes; | ||||
|     volumes.push_back(mv); | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ class ModelConfig; | |||
| class ModelObject; | ||||
| class ModelVolume; | ||||
| class TriangleMesh; | ||||
| class TextInfo; | ||||
| enum class ModelVolumeType : int; | ||||
| 
 | ||||
| // FIXME: broken build on mac os because of this is missing:
 | ||||
|  | @ -283,7 +284,7 @@ public: | |||
|     void                load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true); | ||||
|     // BBS
 | ||||
|     void                switch_to_object_process(); | ||||
|     void                load_mesh_part(const TriangleMesh& mesh, const wxString& name, bool center = true); | ||||
|     void                load_mesh_part(const TriangleMesh &mesh, const wxString &name, const TextInfo &text_info, bool center = true); | ||||
|     void                del_object(const int obj_idx, bool refresh_immediately = true); | ||||
|     void                del_subobject_item(wxDataViewItem& item); | ||||
|     void                del_settings_from_config(const wxDataViewItem& parent_item); | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include "slic3r/GUI/GUI_App.hpp" | ||||
| #include "slic3r/GUI/ImGuiWrapper.hpp" | ||||
| #include "slic3r/GUI/GUI_ObjectList.hpp" | ||||
| #include "slic3r/GUI/Plater.hpp" | ||||
| 
 | ||||
| #include "libslic3r/Geometry/ConvexHull.hpp" | ||||
| #include "libslic3r/Model.hpp" | ||||
|  | @ -85,6 +86,23 @@ void GLGizmoText::update_font_texture() | |||
| 
 | ||||
| void GLGizmoText::on_set_state() | ||||
| { | ||||
|     if (m_state == EState::On && m_parent.get_selection().is_single_volume()) { | ||||
|         ModelVolume *model_volume  = get_selected_single_volume(m_object_idx, m_volume_idx); | ||||
|         TextInfo     text_info     = model_volume->get_text_info(); | ||||
|         if (!text_info.m_text.empty()) { | ||||
|             m_font_name     = text_info.m_font_name; | ||||
|             m_font_size     = text_info.m_font_size; | ||||
|             m_curr_font_idx = text_info.m_curr_font_idx; | ||||
|             m_bold          = text_info.m_bold; | ||||
|             m_italic        = text_info.m_italic; | ||||
|             m_thickness     = text_info.m_thickness; | ||||
|             strcpy(m_text, text_info.m_text.c_str()); | ||||
|             m_is_modify = true; | ||||
|         } | ||||
|     } | ||||
|     else if (m_state == EState::Off) { | ||||
|         reset_text_info(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CommonGizmosDataID GLGizmoText::on_get_requirements() const | ||||
|  | @ -101,7 +119,15 @@ bool GLGizmoText::on_is_activable() const | |||
| { | ||||
|     // This is assumed in GLCanvas3D::do_rotate, do not change this
 | ||||
|     // without updating that function too.
 | ||||
|     return m_parent.get_selection().is_single_full_instance(); | ||||
|     if (m_parent.get_selection().is_single_full_instance()) | ||||
|         return true; | ||||
| 
 | ||||
|     int obejct_idx, volume_idx; | ||||
|     ModelVolume *model_volume = get_selected_single_volume(obejct_idx, volume_idx); | ||||
|     if (model_volume) | ||||
|         return !model_volume->get_text_info().m_text.empty(); | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void GLGizmoText::on_render() | ||||
|  | @ -197,6 +223,35 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const Selection &selection = m_parent.get_selection(); | ||||
|     if (selection.is_single_full_instance() || selection.is_single_full_object()) { | ||||
|         const GLVolume * gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); | ||||
|         int object_idx = gl_volume->object_idx(); | ||||
|         if (object_idx != m_object_idx || (object_idx == m_object_idx && m_volume_idx != -1)) { | ||||
|             m_object_idx = object_idx; | ||||
|             m_volume_idx = -1; | ||||
|             reset_text_info(); | ||||
|         } | ||||
|     } else if (selection.is_single_volume()) { | ||||
|         int object_idx, volume_idx; | ||||
|         ModelVolume *model_volume = get_selected_single_volume(object_idx, volume_idx); | ||||
|         if ((object_idx != m_object_idx || (object_idx == m_object_idx && volume_idx != m_volume_idx)) | ||||
|             && model_volume) { | ||||
|             TextInfo text_info = model_volume->get_text_info(); | ||||
|             m_font_name        = text_info.m_font_name; | ||||
|             m_font_size        = text_info.m_font_size; | ||||
|             m_curr_font_idx    = text_info.m_curr_font_idx; | ||||
|             m_bold             = text_info.m_bold; | ||||
|             m_italic           = text_info.m_italic; | ||||
|             m_thickness        = text_info.m_thickness; | ||||
|             strcpy(m_text, text_info.m_text.c_str()); | ||||
| 
 | ||||
|             m_is_modify = true; | ||||
|             m_volume_idx = volume_idx; | ||||
|             m_object_idx = object_idx; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     const float win_h = ImGui::GetWindowHeight(); | ||||
|     y = std::min(y, bottom_limit - win_h); | ||||
|     GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f); | ||||
|  | @ -305,17 +360,43 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) | |||
|     float offset =  caption_size + input_text_size -  m_imgui->calc_text_size(_L("Add")).x - space_size; | ||||
|     ImGui::Dummy({0.0, 0.0}); | ||||
|     ImGui::SameLine(offset); | ||||
|     bool add_clicked = m_imgui->button(_L("Add")); | ||||
|     if (add_clicked) { | ||||
|     bool btn_clicked = m_imgui->button(m_is_modify ? _L("Modify") : _L("Add")); | ||||
|     if (btn_clicked) { | ||||
|         m_imgui->disabled_end(); | ||||
|         GizmoImguiEnd(); | ||||
|         ImGui::PopStyleVar(); | ||||
|         ImGuiWrapper::pop_toolbar_style(); | ||||
| 
 | ||||
|         TextInfo text_info; | ||||
|         text_info.m_font_name     = m_font_name; | ||||
|         text_info.m_font_size     = m_font_size; | ||||
|         text_info.m_curr_font_idx = m_curr_font_idx; | ||||
|         text_info.m_bold          = m_bold; | ||||
|         text_info.m_italic        = m_italic; | ||||
|         text_info.m_thickness     = m_thickness; | ||||
|         text_info.m_text          = m_text; | ||||
|         TriangleMesh mesh; | ||||
|         load_text_shape(m_text, m_font_name.c_str(), m_font_size, m_thickness, m_bold, m_italic, mesh); | ||||
|         ObjectList* obj_list = wxGetApp().obj_list(); | ||||
|         obj_list->load_mesh_part(mesh, "text_shape"); | ||||
|              | ||||
|         if (m_is_modify) { | ||||
|             Plater *plater = wxGetApp().plater(); | ||||
|             if (!plater) | ||||
|                 return; | ||||
| 
 | ||||
|             plater->take_snapshot("Modify Text"); | ||||
|             const Selection &selection    = m_parent.get_selection(); | ||||
|             ModelObject *    model_object = selection.get_model()->objects[m_object_idx]; | ||||
|             ModelVolume *    model_volume = model_object->volumes[m_volume_idx]; | ||||
|             ModelVolume *    new_model_volume = model_object->add_volume(*model_volume, std::move(mesh)); | ||||
|             new_model_volume->set_text_info(text_info); | ||||
|             new_model_volume->set_transformation(model_volume->get_transformation()); | ||||
|             std::swap(model_object->volumes[m_volume_idx], model_object->volumes.back()); | ||||
|             model_object->delete_volume(model_object->volumes.size() - 1); | ||||
|             plater->update(); | ||||
|         } else { | ||||
|             ObjectList *obj_list = wxGetApp().obj_list(); | ||||
|             obj_list->load_mesh_part(mesh, "text_shape", text_info); | ||||
|         } | ||||
| 
 | ||||
|         return; | ||||
|     } | ||||
|  | @ -335,5 +416,31 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) | |||
|     ImGuiWrapper::pop_toolbar_style(); | ||||
| } | ||||
| 
 | ||||
| ModelVolume *GLGizmoText::get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const | ||||
| { | ||||
|     if (m_parent.get_selection().is_single_volume()) { | ||||
|         const Selection &selection = m_parent.get_selection(); | ||||
|         const GLVolume * gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); | ||||
|         out_object_idx             = gl_volume->object_idx(); | ||||
|         ModelObject *model_object  = selection.get_model()->objects[out_object_idx]; | ||||
|         out_volume_idx             = gl_volume->volume_idx(); | ||||
|         ModelVolume *model_volume  = model_object->volumes[out_volume_idx]; | ||||
|         return model_volume; | ||||
|     } | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| void GLGizmoText::reset_text_info() | ||||
| { | ||||
|     m_font_name     = ""; | ||||
|     m_font_size     = 16.f; | ||||
|     m_curr_font_idx = 0; | ||||
|     m_bold          = true; | ||||
|     m_italic        = false; | ||||
|     m_thickness     = 2.f; | ||||
|     strcpy(m_text, m_font_name.c_str()); | ||||
|     m_is_modify = false; | ||||
| } | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| namespace Slic3r { | ||||
| 
 | ||||
| enum class ModelVolumeType : int; | ||||
| class ModelVolume; | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
|  | @ -38,6 +39,10 @@ private: | |||
| 
 | ||||
|     std::vector<TextureInfo> m_textures; | ||||
| 
 | ||||
|     bool m_is_modify = false; | ||||
|     int  m_object_idx; | ||||
|     int  m_volume_idx; | ||||
| 
 | ||||
| public: | ||||
|     GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); | ||||
|     ~GLGizmoText(); | ||||
|  | @ -57,6 +62,10 @@ protected: | |||
|     virtual void on_set_state() override; | ||||
|     virtual CommonGizmosDataID on_get_requirements() const override; | ||||
|     virtual void on_render_input_window(float x, float y, float bottom_limit); | ||||
| 
 | ||||
| private: | ||||
|     ModelVolume *get_selected_single_volume(int& out_object_idx, int& out_volume_idx) const; | ||||
|     void reset_text_info(); | ||||
| }; | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
|  |  | |||
|  | @ -1501,7 +1501,7 @@ void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos) | |||
|     if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx) { | ||||
|         activate_gizmo(m_current == idx ? Undefined : (EType)idx); | ||||
|         // BBS
 | ||||
|         wxGetApp().obj_list()->select_object_item((EType)idx <= Scale); | ||||
|         wxGetApp().obj_list()->select_object_item((EType) idx <= Scale || (EType) idx == Text); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 zhimin.zeng
						zhimin.zeng