mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Reset buttons - fixed rotation of instances with multiple volumes
Mirroring buttons now hide where appropriate
This commit is contained in:
		
							parent
							
								
									a3c1644ead
								
							
						
					
					
						commit
						980c6673d4
					
				
					 5 changed files with 83 additions and 33 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								resources/icons/mirroring_off.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/icons/mirroring_off.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 589 B | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/mirroring_on.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/icons/mirroring_on.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 600 B | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/mirroring_transparent.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/icons/mirroring_transparent.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 93 B | 
|  | @ -172,33 +172,50 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
|     def.type = coString; |     def.type = coString; | ||||||
|     def.width = field_width - mirror_btn_width;//field_width/*50*/;
 |     def.width = field_width - mirror_btn_width;//field_width/*50*/;
 | ||||||
| 
 | 
 | ||||||
|  |     // Load bitmaps to be used for the mirroring buttons:
 | ||||||
|  |     m_mirror_bitmap_on  = ScalableBitmap(parent, "mirroring_on.png"); | ||||||
|  |     m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off.png"); | ||||||
|  |     m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent.png"); | ||||||
|  | 
 | ||||||
| 	for (const std::string axis : { "x", "y", "z" }) { | 	for (const std::string axis : { "x", "y", "z" }) { | ||||||
|         const std::string label = boost::algorithm::to_upper_copy(axis); |         const std::string label = boost::algorithm::to_upper_copy(axis); | ||||||
|         def.set_default_value(new ConfigOptionString{ "   " + label }); |         def.set_default_value(new ConfigOptionString{ "   " + label }); | ||||||
|         Option option = Option(def, axis + "_axis_legend"); |         Option option = Option(def, axis + "_axis_legend"); | ||||||
| 
 | 
 | ||||||
|  |         unsigned int axis_idx = (axis[0] - 'x'); // 0, 1 or 2
 | ||||||
|  | 
 | ||||||
|         // We will add a button to toggle mirroring to each axis:
 |         // We will add a button to toggle mirroring to each axis:
 | ||||||
|         auto mirror_button = [=](wxWindow* parent) { |         auto mirror_button = [=](wxWindow* parent) { | ||||||
|             m_mirror_bitmap_on  = ScalableBitmap(parent, "colorchange_add_on.png"); |             wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width); | ||||||
|             m_mirror_bitmap_off = ScalableBitmap(parent, "colorchange_delete_off.png"); |             auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off.png", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW); | ||||||
|             auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png", wxEmptyString, wxSize(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width)); |             btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), label)); | ||||||
|             btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), boost::algorithm::to_upper_copy(axis))); | 
 | ||||||
|             m_mirror_buttons[axis] = btn; |             m_mirror_buttons[axis_idx].first = btn; | ||||||
|  |             m_mirror_buttons[axis_idx].second = mbShown; | ||||||
|             auto sizer = new wxBoxSizer(wxHORIZONTAL); |             auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||||
|             sizer->Add(btn, wxBU_EXACTFIT/* | wxRESERVE_SPACE_EVEN_IF_HIDDEN*/); |             sizer->Add(btn); | ||||||
|  | 
 | ||||||
|             btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { |             btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { | ||||||
|                 wxWindow* btn = dynamic_cast<wxWindow*>(e.GetEventObject()); |                 Axis axis = (Axis)(axis_idx + X); | ||||||
|                 Axis axis = (btn == m_mirror_buttons["x"] ? X : ( btn == m_mirror_buttons["y"] ? Y : Z)); |                 if (m_mirror_buttons[axis_idx].second == mbHidden) | ||||||
|  |                     return; | ||||||
|  | 
 | ||||||
|                 GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); |                 GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); | ||||||
|                 Selection& selection = canvas->get_selection(); |                 Selection& selection = canvas->get_selection(); | ||||||
|                 GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin())); |  | ||||||
| 
 | 
 | ||||||
|                 if (selection.is_single_volume() || selection.is_single_modifier()) |                 if (selection.is_single_volume() || selection.is_single_modifier()) { | ||||||
|  |                     GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin())); | ||||||
|                     volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis)); |                     volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis)); | ||||||
|                 else if (selection.is_single_full_instance()) |                 } | ||||||
|                     volume->set_instance_mirror(axis, -volume->get_instance_mirror(axis)); |                 else if (selection.is_single_full_instance()) { | ||||||
|  |                     for (unsigned int idx : selection.get_volume_idxs()){ | ||||||
|  |                         GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(idx)); | ||||||
|  |                         volume->set_instance_mirror(axis, -volume->get_instance_mirror(axis)); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 else |                 else | ||||||
|                     return; |                     return; | ||||||
|  | 
 | ||||||
|                 canvas->do_mirror(); |                 canvas->do_mirror(); | ||||||
|                 canvas->set_as_dirty(); |                 canvas->set_as_dirty(); | ||||||
|                 UpdateAndShow(true); |                 UpdateAndShow(true); | ||||||
|  | @ -238,7 +255,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
|             }; |             }; | ||||||
|             // Add reset scale button
 |             // Add reset scale button
 | ||||||
|             auto reset_scale_button = [=](wxWindow* parent) { |             auto reset_scale_button = [=](wxWindow* parent) { | ||||||
|                 auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png"); |                 auto btn = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); | ||||||
|                 btn->SetToolTip(_(L("Reset scale"))); |                 btn->SetToolTip(_(L("Reset scale"))); | ||||||
|                 m_reset_scale_button = btn; |                 m_reset_scale_button = btn; | ||||||
|                 auto sizer = new wxBoxSizer(wxHORIZONTAL); |                 auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||||
|  | @ -255,7 +272,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
|         else if (option_name == "Rotation") { |         else if (option_name == "Rotation") { | ||||||
|             // Add reset rotation button
 |             // Add reset rotation button
 | ||||||
|             auto reset_rotation_button = [=](wxWindow* parent) { |             auto reset_rotation_button = [=](wxWindow* parent) { | ||||||
|                 auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png"); |                 auto btn = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); | ||||||
|                 btn->SetToolTip(_(L("Reset rotation"))); |                 btn->SetToolTip(_(L("Reset rotation"))); | ||||||
|                 m_reset_rotation_button = btn; |                 m_reset_rotation_button = btn; | ||||||
|                 auto sizer = new wxBoxSizer(wxHORIZONTAL); |                 auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||||
|  | @ -263,12 +280,17 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
|                 btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { |                 btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { | ||||||
|                     GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); |                     GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); | ||||||
|                     Selection& selection = canvas->get_selection(); |                     Selection& selection = canvas->get_selection(); | ||||||
|                     GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin())); |  | ||||||
| 
 | 
 | ||||||
|                     if (selection.is_single_volume() || selection.is_single_modifier()) |                     if (selection.is_single_volume() || selection.is_single_modifier()) { | ||||||
|  |                         GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin())); | ||||||
|                         volume->set_volume_rotation(Vec3d::Zero()); |                         volume->set_volume_rotation(Vec3d::Zero()); | ||||||
|                     else if (selection.is_single_full_instance()) |                     } | ||||||
|                         volume->set_instance_rotation(Vec3d::Zero()); |                     else if (selection.is_single_full_instance()) { | ||||||
|  |                         for (unsigned int idx : selection.get_volume_idxs()){ | ||||||
|  |                             GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(idx)); | ||||||
|  |                             volume->set_instance_rotation(Vec3d::Zero()); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|                     else |                     else | ||||||
|                         return; |                         return; | ||||||
| 
 | 
 | ||||||
|  | @ -534,25 +556,42 @@ void ObjectManipulation::update_mirror_buttons_visibility() | ||||||
| { | { | ||||||
|     GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); |     GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); | ||||||
|     Selection& selection = canvas->get_selection(); |     Selection& selection = canvas->get_selection(); | ||||||
|     std::array<bool, 3> show = {false, false, false}; |     std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden}; | ||||||
| 
 | 
 | ||||||
|     if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) { |     if (!m_world_coordinates) { | ||||||
|         const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); |         if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) { | ||||||
|         Vec3d mirror; |             const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); | ||||||
|  |             Vec3d mirror; | ||||||
| 
 | 
 | ||||||
|         if (selection.is_single_full_instance()) |             if (selection.is_single_full_instance()) | ||||||
|             mirror = volume->get_instance_mirror(); |                 mirror = volume->get_instance_mirror(); | ||||||
|         else |             else | ||||||
|             mirror = volume->get_volume_mirror(); |                 mirror = volume->get_volume_mirror(); | ||||||
| 
 | 
 | ||||||
|         for (unsigned char i=0; i<3; ++i) |             for (unsigned char i=0; i<3; ++i) | ||||||
|             show[i] = mirror[i] < 0.; |                 new_states[i] = (mirror[i] < 0. ? mbActive : mbShown); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         // the mirroring buttons should be hidden in world coordinates,
 | ||||||
|  |         // unless we make it actually mirror in world coords.
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     wxGetApp().CallAfter([this, show]{ |     // Hiding the buttons through Hide() always messed up the sizers. As a workaround, the button
 | ||||||
|         m_mirror_buttons["x"]->SetBitmap(show[0] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); |     // is assigned a transparent bitmap. We must of course remember the actual state.
 | ||||||
|         m_mirror_buttons["y"]->SetBitmap(show[1] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); |     wxGetApp().CallAfter([this, new_states]{ | ||||||
|         m_mirror_buttons["z"]->SetBitmap(show[2] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); |         for (int i=0; i<3; ++i) { | ||||||
|  |             if (new_states[i] != m_mirror_buttons[i].second) { | ||||||
|  |                 const wxBitmap* bmp; | ||||||
|  |                 switch (new_states[i]) { | ||||||
|  |                     case mbHidden : bmp = &m_mirror_bitmap_hidden.bmp(); m_mirror_buttons[i].first->Enable(false); break; | ||||||
|  |                     case mbShown  : bmp = &m_mirror_bitmap_off.bmp(); m_mirror_buttons[i].first->Enable(true); break; | ||||||
|  |                     case mbActive : bmp = &m_mirror_bitmap_on.bmp(); m_mirror_buttons[i].first->Enable(true); break; | ||||||
|  |                 } | ||||||
|  |                 m_mirror_buttons[i].first->SetBitmap(*bmp); | ||||||
|  |                 m_mirror_buttons[i].second = new_states[i]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -817,6 +856,7 @@ void ObjectManipulation::msw_rescale() | ||||||
| 
 | 
 | ||||||
|     m_mirror_bitmap_on.msw_rescale(); |     m_mirror_bitmap_on.msw_rescale(); | ||||||
|     m_mirror_bitmap_off.msw_rescale(); |     m_mirror_bitmap_off.msw_rescale(); | ||||||
|  |     m_mirror_bitmap_hidden.msw_rescale(); | ||||||
|     m_reset_scale_button->msw_rescale(); |     m_reset_scale_button->msw_rescale(); | ||||||
|     m_reset_rotation_button->msw_rescale(); |     m_reset_rotation_button->msw_rescale(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,9 +56,19 @@ class ObjectManipulation : public OG_Settings | ||||||
|     // Non-owning pointers to the reset buttons, so we can hide and show them.
 |     // Non-owning pointers to the reset buttons, so we can hide and show them.
 | ||||||
|     ScalableButton* m_reset_scale_button = nullptr; |     ScalableButton* m_reset_scale_button = nullptr; | ||||||
|     ScalableButton* m_reset_rotation_button = nullptr; |     ScalableButton* m_reset_rotation_button = nullptr; | ||||||
|     std::map<std::string, ScalableButton*> m_mirror_buttons; | 
 | ||||||
|  |     // Mirroring buttons and their current state
 | ||||||
|  |     enum MirrorButtonState { | ||||||
|  |         mbHidden, | ||||||
|  |         mbShown, | ||||||
|  |         mbActive | ||||||
|  |     }; | ||||||
|  |     std::array<std::pair<ScalableButton*, MirrorButtonState>, 3> m_mirror_buttons; | ||||||
|  | 
 | ||||||
|  |     // Bitmaps for the mirroring buttons.
 | ||||||
|     ScalableBitmap m_mirror_bitmap_on; |     ScalableBitmap m_mirror_bitmap_on; | ||||||
|     ScalableBitmap m_mirror_bitmap_off; |     ScalableBitmap m_mirror_bitmap_off; | ||||||
|  |     ScalableBitmap m_mirror_bitmap_hidden; | ||||||
| 
 | 
 | ||||||
|     // Needs to be updated from OnIdle?
 |     // Needs to be updated from OnIdle?
 | ||||||
|     bool            m_dirty = false; |     bool            m_dirty = false; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Matena
						Lukas Matena