mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 16:57:53 -06:00
Merge remote-tracking branch 'remotes/origin/vb_undo_redo'
This commit is contained in:
commit
ab7ecc1819
60 changed files with 2799 additions and 578 deletions
|
@ -1188,6 +1188,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent);
|
|||
wxDEFINE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
||||
|
||||
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
|
||||
: m_canvas(canvas)
|
||||
|
@ -1791,7 +1793,7 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
|||
void GLCanvas3D::mirror_selection(Axis axis)
|
||||
{
|
||||
m_selection.mirror(axis);
|
||||
do_mirror();
|
||||
do_mirror("Mirror Object");
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
}
|
||||
|
||||
|
@ -1812,14 +1814,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
struct ModelVolumeState {
|
||||
ModelVolumeState(const GLVolume *volume) :
|
||||
model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
|
||||
ModelVolumeState(const ModelVolume *model_volume, const ModelID &instance_id, const GLVolume::CompositeID &composite_id) :
|
||||
ModelVolumeState(const ModelVolume *model_volume, const ObjectID &instance_id, const GLVolume::CompositeID &composite_id) :
|
||||
model_volume(model_volume), geometry_id(std::make_pair(model_volume->id().id, instance_id.id)), composite_id(composite_id), volume_idx(-1) {}
|
||||
ModelVolumeState(const ModelID &volume_id, const ModelID &instance_id) :
|
||||
ModelVolumeState(const ObjectID &volume_id, const ObjectID &instance_id) :
|
||||
model_volume(nullptr), geometry_id(std::make_pair(volume_id.id, instance_id.id)), volume_idx(-1) {}
|
||||
bool new_geometry() const { return this->volume_idx == size_t(-1); }
|
||||
const ModelVolume *model_volume;
|
||||
// ModelID of ModelVolume + ModelID of ModelInstance
|
||||
// or timestamp of an SLAPrintObjectStep + ModelID of ModelInstance
|
||||
// ObjectID of ModelVolume + ObjectID of ModelInstance
|
||||
// or timestamp of an SLAPrintObjectStep + ObjectID of ModelInstance
|
||||
std::pair<size_t, size_t> geometry_id;
|
||||
GLVolume::CompositeID composite_id;
|
||||
// Volume index in the new GLVolume vector.
|
||||
|
@ -2316,6 +2318,9 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items())
|
||||
return;
|
||||
|
||||
if (m_gizmos.on_char(evt, *this))
|
||||
return;
|
||||
|
||||
|
@ -2348,6 +2353,25 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
#endif /* __APPLE__ */
|
||||
post_event(SimpleEvent(EVT_GLTOOLBAR_PASTE));
|
||||
break;
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
case 'y':
|
||||
case 'Y':
|
||||
#else /* __APPLE__ */
|
||||
case WXK_CONTROL_Y:
|
||||
#endif /* __APPLE__ */
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_REDO));
|
||||
break;
|
||||
#ifdef __APPLE__
|
||||
case 'z':
|
||||
case 'Z':
|
||||
#else /* __APPLE__ */
|
||||
case WXK_CONTROL_Z:
|
||||
#endif /* __APPLE__ */
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_UNDO));
|
||||
break;
|
||||
|
||||
#ifdef __APPLE__
|
||||
case WXK_BACK: // the low cost Apple solutions are not equipped with a Delete key, use Backspace instead.
|
||||
#else /* __APPLE__ */
|
||||
|
@ -2368,7 +2392,6 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
#endif /* __APPLE__ */
|
||||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE: { deselect_all(); break; }
|
||||
case '0': { select_view("iso"); break; }
|
||||
case '1': { select_view("top"); break; }
|
||||
|
@ -2715,12 +2738,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
}
|
||||
else if (evt.Leaving())
|
||||
{
|
||||
_deactivate_undo_redo_toolbar_items();
|
||||
|
||||
// to remove hover on objects when the mouse goes out of this canvas
|
||||
m_mouse.position = Vec2d(-1.0, -1.0);
|
||||
m_dirty = true;
|
||||
}
|
||||
else if (evt.LeftDown() || evt.RightDown())
|
||||
else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown())
|
||||
{
|
||||
if (_deactivate_undo_redo_toolbar_items())
|
||||
return;
|
||||
|
||||
// If user pressed left or right button we first check whether this happened
|
||||
// on a volume or not.
|
||||
m_layers_editing.state = LayersEditing::Unknown;
|
||||
|
@ -2918,9 +2946,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
|
||||
{
|
||||
m_regenerate_volumes = false;
|
||||
do_move();
|
||||
do_move("Move Object");
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
// Let the platter know that the dragging finished, so a delayed refresh
|
||||
// Let the plater know that the dragging finished, so a delayed refresh
|
||||
// of the scene with the background processing data should be performed.
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||
}
|
||||
|
@ -3077,11 +3105,14 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
|
|||
}
|
||||
|
||||
|
||||
void GLCanvas3D::do_move()
|
||||
void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
return;
|
||||
|
||||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
bool object_moved = false;
|
||||
Vec3d wipe_tower_origin = Vec3d::Zero();
|
||||
|
@ -3132,13 +3163,18 @@ void GLCanvas3D::do_move()
|
|||
|
||||
if (wipe_tower_origin != Vec3d::Zero())
|
||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin)));
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_rotate()
|
||||
void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
return;
|
||||
|
||||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
Selection::EMode selection_mode = m_selection.get_mode();
|
||||
|
@ -3187,13 +3223,18 @@ void GLCanvas3D::do_rotate()
|
|||
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_scale()
|
||||
void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
return;
|
||||
|
||||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
Selection::EMode selection_mode = m_selection.get_mode();
|
||||
|
@ -3239,18 +3280,27 @@ void GLCanvas3D::do_scale()
|
|||
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_flatten()
|
||||
void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_type)
|
||||
{
|
||||
do_rotate();
|
||||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
|
||||
|
||||
m_selection.flattening_rotate(normal);
|
||||
do_rotate(""); // avoid taking another snapshot
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_mirror()
|
||||
void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
return;
|
||||
|
||||
if (!snapshot_type.empty())
|
||||
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
Selection::EMode selection_mode = m_selection.get_mode();
|
||||
|
@ -3289,6 +3339,8 @@ void GLCanvas3D::do_mirror()
|
|||
}
|
||||
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_camera_zoom(double zoom)
|
||||
|
@ -3412,6 +3464,40 @@ bool GLCanvas3D::_is_shown_on_screen() const
|
|||
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
||||
}
|
||||
|
||||
// Getter for the const char*[]
|
||||
static bool string_getter(const bool is_undo, int idx, const char** out_text)
|
||||
{
|
||||
return wxGetApp().plater()->undo_redo_string_getter(is_undo, idx, out_text);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
|
||||
{
|
||||
const wxString& stack_name = _(is_undo ? L("Undo") : L("Redo"));
|
||||
ImGuiWrapper* imgui = wxGetApp().imgui();
|
||||
|
||||
const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width();
|
||||
imgui->set_next_window_pos(x, m_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
|
||||
imgui->set_next_window_bg_alpha(0.5f);
|
||||
imgui->begin(wxString::Format(_(L("%s Stack")), stack_name),
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
int hovered = m_imgui_undo_redo_hovered_pos;
|
||||
int selected = -1;
|
||||
const float em = static_cast<float>(wxGetApp().em_unit());
|
||||
|
||||
if (imgui->undo_redo_list(ImVec2(12 * em, 20 * em), is_undo, &string_getter, hovered, selected))
|
||||
m_imgui_undo_redo_hovered_pos = hovered;
|
||||
else
|
||||
m_imgui_undo_redo_hovered_pos = -1;
|
||||
|
||||
if (selected >= 0)
|
||||
is_undo ? wxGetApp().plater()->undo_to(selected) : wxGetApp().plater()->redo_to(selected);
|
||||
|
||||
imgui->text(wxString::Format(_(L("%s %d Action")), stack_name, hovered + 1));
|
||||
|
||||
imgui->end();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_init_toolbar()
|
||||
{
|
||||
if (!m_toolbar.is_enabled())
|
||||
|
@ -3444,7 +3530,7 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "add.svg";
|
||||
item.tooltip = _utf8(L("Add...")) + " [" + GUI::shortkey_ctrl_prefix() + "I]";
|
||||
item.sprite_id = 0;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3452,8 +3538,8 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "remove.svg";
|
||||
item.tooltip = _utf8(L("Delete")) + " [Del]";
|
||||
item.sprite_id = 1;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3461,8 +3547,8 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "delete_all.svg";
|
||||
item.tooltip = _utf8(L("Delete all")) + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
|
||||
item.sprite_id = 2;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3470,8 +3556,8 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "arrange.svg";
|
||||
item.tooltip = _utf8(L("Arrange")) + " [A]";
|
||||
item.sprite_id = 3;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3482,8 +3568,8 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "copy.svg";
|
||||
item.tooltip = _utf8(L("Copy")) + " [" + GUI::shortkey_ctrl_prefix() + "C]";
|
||||
item.sprite_id = 4;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_copy_to_clipboard(); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_copy_to_clipboard(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3491,8 +3577,8 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "paste.svg";
|
||||
item.tooltip = _utf8(L("Paste")) + " [" + GUI::shortkey_ctrl_prefix() + "V]";
|
||||
item.sprite_id = 5;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_paste_from_clipboard(); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_paste_from_clipboard(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3503,9 +3589,10 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "instance_add.svg";
|
||||
item.tooltip = _utf8(L("Add instance")) + " [+]";
|
||||
item.sprite_id = 6;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
|
||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
|
||||
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3513,9 +3600,9 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "instance_remove.svg";
|
||||
item.tooltip = _utf8(L("Remove instance")) + " [-]";
|
||||
item.sprite_id = 7;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
|
||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3526,9 +3613,9 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "split_objects.svg";
|
||||
item.tooltip = _utf8(L("Split to objects"));
|
||||
item.sprite_id = 8;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
|
||||
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3536,9 +3623,9 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "split_parts.svg";
|
||||
item.tooltip = _utf8(L("Split to parts"));
|
||||
item.sprite_id = 9;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
|
||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -3549,10 +3636,42 @@ bool GLCanvas3D::_init_toolbar()
|
|||
item.icon_filename = "layers_white.svg";
|
||||
item.tooltip = _utf8(L("Layers editing"));
|
||||
item.sprite_id = 10;
|
||||
item.is_toggable = true;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
|
||||
item.left.toggable = true;
|
||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
|
||||
item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
|
||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
if (!m_toolbar.add_separator())
|
||||
return false;
|
||||
|
||||
item.name = "undo";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.icon_filename = "undo_toolbar.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]";
|
||||
item.sprite_id = 11;
|
||||
item.left.toggable = false;
|
||||
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); };
|
||||
item.right.toggable = true;
|
||||
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
||||
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(true, 0.5f * (left + right)); };
|
||||
item.visibility_callback = []()->bool { return true; };
|
||||
item.enabling_callback = [this]()->bool { return wxGetApp().plater()->can_undo(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
item.name = "redo";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.icon_filename = "redo_toolbar.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]";
|
||||
item.sprite_id = 12;
|
||||
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_REDO)); };
|
||||
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
||||
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(false, 0.5f * (left + right)); };
|
||||
item.enabling_callback = [this]()->bool { return wxGetApp().plater()->can_redo(); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
|
@ -5551,6 +5670,22 @@ void GLCanvas3D::_update_selection_from_hover()
|
|||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_deactivate_undo_redo_toolbar_items()
|
||||
{
|
||||
if (m_toolbar.is_item_pressed("undo"))
|
||||
{
|
||||
m_toolbar.force_right_action(m_toolbar.get_item_id("undo"), *this);
|
||||
return true;
|
||||
}
|
||||
else if (m_toolbar.is_item_pressed("redo"))
|
||||
{
|
||||
m_toolbar.force_right_action(m_toolbar.get_item_id("redo"), *this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const Print* GLCanvas3D::fff_print() const
|
||||
{
|
||||
return (m_process == nullptr) ? nullptr : m_process->fff_print();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue