29 if (ImGui::Begin(
"Undo History", &visible_))
32 const auto& undo_stack = editing_mgr.
undo_stack;
35 auto undo = editing_mgr.can_undo() ?
"Undo*" :
"Undo";
36 auto redo = editing_mgr.can_redo() ?
"Redo*" :
"Redo";
38 if (ImGui::Button(undo) && editing_mgr.can_undo())
44 if (ImGui::Button(redo) && editing_mgr.can_redo())
50 if (ImGui::Button(
"Clear Stack"))
52 editing_mgr.undo_stack.clear();
57 if (undo_stack.actions.empty())
59 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
"(No actions in stack)");
64 bool is_at_latest_state = (undo_stack.current_index == undo_stack.actions.size());
65 ImGui::PushStyleColor(ImGuiCol_Text, is_at_latest_state ? ImVec4(0.0f, 1.0f, 0.0f, 1.0f) : ImVec4(0.7f, 0.7f, 0.7f, 1.0f));
70 while (editing_mgr.can_redo())
76 if (ImGui::IsItemHovered())
78 ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(FLT_MAX, 800.0f));
79 ImGui::BeginTooltip();
80 ImGui::Text(
"Latest State (all actions executed)");
81 if (!is_at_latest_state)
83 size_t redo_steps = undo_stack.actions.size() - undo_stack.current_index;
85 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f),
86 "Click to redo %zu step%s to latest state",
88 redo_steps == 1 ?
"" :
"s");
92 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"← Current Position");
97 ImGui::PopStyleColor();
103 for (
size_t idx = 0; idx < undo_stack.actions.size(); ++idx)
106 size_t i = undo_stack.actions.size() - 1 - idx;
107 const auto& action = undo_stack.actions[i];
110 bool is_executed = i < undo_stack.current_index;
111 bool is_current = (i == undo_stack.current_index - 1) && undo_stack.current_index > 0;
114 bool is_adjacent_to_current = (i == undo_stack.current_index - 1) || (i == undo_stack.current_index);
115 bool is_invalid = is_adjacent_to_current && !action->is_valid();
119 const char* status_icon =
"";
123 text_color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
130 text_color = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
133 else if (is_executed)
135 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
140 text_color = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
145 ImGui::PushStyleColor(ImGuiCol_Text, text_color);
148 bool is_selected = is_current;
150 auto selectable_label = fmt::format(
"{} [{}] {}", status_icon, i, action->get_name());
152 if (ImGui::Selectable(selectable_label.c_str(), is_selected))
155 size_t target_index = i + 1;
158 while (undo_stack.current_index != target_index)
160 if (undo_stack.current_index > target_index)
163 if (editing_mgr.can_undo())
175 if (editing_mgr.can_redo())
187 ImGui::PopStyleColor();
190 if (ImGui::IsItemHovered())
192 ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(FLT_MAX, 800.0f));
193 ImGui::BeginTooltip();
196 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
"Invalid Action due to missing dependencies.");
200 ImGui::Text(
"Action: %s", action->get_name().c_str());
201 ImGui::Text(
"Status: %s", is_executed ?
"Executed" :
"Not Executed");
202 ImGui::Text(
"Undoable: %s", action->is_undoable() ?
"Yes" :
"No");
204 action->draw_in_inspector(ctx);
207 size_t target_index = i + 1;
208 if (target_index != undo_stack.current_index)
211 if (target_index < undo_stack.current_index)
213 size_t undo_steps = undo_stack.current_index - target_index;
214 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f),
215 "Click to undo %zu step%s",
217 undo_steps == 1 ?
"" :
"s");
221 size_t redo_steps = target_index - undo_stack.current_index;
222 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f),
223 "Click to redo %zu step%s",
225 redo_steps == 1 ?
"" :
"s");
230 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"%s Current Position",
ICON_MDI_ARROW_LEFT);
241 bool is_at_initial_state = (undo_stack.current_index == 0);
242 ImGui::PushStyleColor(ImGuiCol_Text, is_at_initial_state ? ImVec4(0.0f, 1.0f, 0.0f, 1.0f) : ImVec4(0.7f, 0.7f, 0.7f, 1.0f));
247 while (editing_mgr.can_undo())
253 if (ImGui::IsItemHovered())
255 ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(FLT_MAX, 800.0f));
256 ImGui::BeginTooltip();
257 ImGui::Text(
"Initial State (no actions executed)");
258 if (!is_at_initial_state)
260 size_t undo_steps = undo_stack.current_index;
262 ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f),
263 "Click to undo %zu step%s to initial state",
265 undo_steps == 1 ?
"" :
"s");
269 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"%s Current Position",
ICON_MDI_ARROW_LEFT);
274 ImGui::PopStyleColor();
278 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.0f, 1.0f),
"%s",
279 fmt::format(
"Current Position: {} / {}", undo_stack.current_index, undo_stack.actions.size()).c_str());
283 if (!undo_stack.actions.empty())
285 float progress =
static_cast<float>(undo_stack.current_index) /
static_cast<float>(undo_stack.actions.size());
286 ImGui::ProgressBar(progress, ImVec2(-1.0f, 0.0f),
"");