mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-08 01:54:06 +01:00
feat(editor): undo and redo take back the kept alignments and switches together with the paths: each step of the history keeps the //$h and //$r records from before it; a deleted switch or slip forgets its record in the same step, so undoing the deletion brings it back; edits of the switch number, rail and km and forgetting a kept design stay outside the history; self-test commands deleting paths
This commit is contained in:
@@ -2907,6 +2907,7 @@ bool editor_mode::save()
|
|||||||
if (m_profile.changed)
|
if (m_profile.changed)
|
||||||
profile_store();
|
profile_store();
|
||||||
switch_store::tidy();
|
switch_store::tidy();
|
||||||
|
switch_store::settle();
|
||||||
infra_store();
|
infra_store();
|
||||||
if (false == m_saved_camera.has_value() || glm::distance(m_saved_camera->first, glm::dvec3{Camera.Pos}) > 0.5 || glm::distance(m_saved_camera->second, glm::vec3{Camera.Angle}) > 0.01f)
|
if (false == m_saved_camera.has_value() || glm::distance(m_saved_camera->first, glm::dvec3{Camera.Pos}) > 0.5 || glm::distance(m_saved_camera->second, glm::vec3{Camera.Angle}) > 0.01f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "editor/editorOrthophoto.hpp"
|
#include "editor/editorOrthophoto.hpp"
|
||||||
#include "editor/editorTrack.hpp"
|
#include "editor/editorTrack.hpp"
|
||||||
#include "editor/editorAlignment.hpp"
|
#include "editor/editorAlignment.hpp"
|
||||||
|
#include "editor/editorAlignmentStore.hpp"
|
||||||
|
#include "editor/editorSwitchStore.hpp"
|
||||||
#include "editor/editorSpeed.hpp"
|
#include "editor/editorSpeed.hpp"
|
||||||
#include "editor/editorRoad.hpp"
|
#include "editor/editorRoad.hpp"
|
||||||
#include "editor/editorProfile.hpp"
|
#include "editor/editorProfile.hpp"
|
||||||
@@ -168,6 +170,8 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
std::vector<infra::object_state> infra; // objects which followed the paths
|
std::vector<infra::object_state> infra; // objects which followed the paths
|
||||||
bool profiles{false}; // the stored grade line designs changed too, these were the ones before
|
bool profiles{false}; // the stored grade line designs changed too, these were the ones before
|
||||||
std::vector<stored_profile> profile_library;
|
std::vector<stored_profile> profile_library;
|
||||||
|
std::optional<std::vector<alignment_store::record>> alignments; // the kept horizontal alignments changed too, these were the ones before
|
||||||
|
std::optional<std::vector<switch_store::record>> switch_records; // the kept switches changed too, these were the ones before
|
||||||
std::vector<array_copy> copies; // models an array added to the one it was made of
|
std::vector<array_copy> copies; // models an array added to the one it was made of
|
||||||
bool joined{false}; // undone and redone together with the change before it
|
bool joined{false}; // undone and redone together with the change before it
|
||||||
std::shared_ptr<terrain_streamer::change const> terrain; // the heightmap terrain from before the change (Action::Terrain)
|
std::shared_ptr<terrain_streamer::change const> terrain; // the heightmap terrain from before the change (Action::Terrain)
|
||||||
@@ -630,6 +634,8 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
static bool tracks_editable(std::vector<TTrack *> const &Tracks, std::string &Reason);
|
static bool tracks_editable(std::vector<TTrack *> const &Tracks, std::string &Reason);
|
||||||
void trim_history();
|
void trim_history();
|
||||||
void restore_track_snapshot(EditorSnapshot const &Snapshot, std::vector<EditorSnapshot> &Opposite, bool const Undo);
|
void restore_track_snapshot(EditorSnapshot const &Snapshot, std::vector<EditorSnapshot> &Opposite, bool const Undo);
|
||||||
|
// changes of the kept alignments and switches go into the last step of the history, made just before them
|
||||||
|
void records_to_history();
|
||||||
editor_track::point_ref m_track_point;
|
editor_track::point_ref m_track_point;
|
||||||
std::vector<TTrack *> m_track_drag;
|
std::vector<TTrack *> m_track_drag;
|
||||||
std::vector<std::pair<TTrack *, editor_track::point_ref>> m_track_drag_points;
|
std::vector<std::pair<TTrack *, editor_track::point_ref>> m_track_drag_points;
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
// switchplace <template> <x> <z> <direction> <side> the catalogue template whose label starts so put into the straight
|
// switchplace <template> <x> <z> <direction> <side> the catalogue template whose label starts so put into the straight
|
||||||
// nearest the point, or into the curve (switchcurve); slipplace <template> <x> <z>
|
// nearest the point, or into the curve (switchcurve); slipplace <template> <x> <z>
|
||||||
// switches logs the switches kept in the scenery and the speed of each diverging track
|
// switches logs the switches kept in the scenery and the speed of each diverging track
|
||||||
|
// deletetrack <name>, deletekind <kind> the path deleted as Del does it, or the first path over an element of the kind
|
||||||
// btfcheck <terrain file> the .txtf converted to .btf, the editor lines the binary file keeps logged
|
// btfcheck <terrain file> the .txtf converted to .btf, the editor lines the binary file keeps logged
|
||||||
// screenshot
|
// screenshot
|
||||||
// save
|
// save
|
||||||
@@ -1199,6 +1200,36 @@ void editor_mode::selftest_step()
|
|||||||
}
|
}
|
||||||
WriteLog("SELFTEST " + command + ": " + tool.status + " " + m_straights.status);
|
WriteLog("SELFTEST " + command + ": " + tool.status + " " + m_straights.status);
|
||||||
}
|
}
|
||||||
|
else if (command == "deletetrack" || command == "deletekind")
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
words >> name;
|
||||||
|
TTrack *chosen{nullptr};
|
||||||
|
if (command == "deletetrack")
|
||||||
|
chosen = simulation::Paths.find(name);
|
||||||
|
else
|
||||||
|
for (auto *track : simulation::Paths.sequence())
|
||||||
|
{
|
||||||
|
if (track == nullptr || track->m_editorremoved || track->eType != tt_Normal || track->m_paths.empty())
|
||||||
|
continue;
|
||||||
|
auto const found{alignment_store::on_track(*track)};
|
||||||
|
if (found.has_value() && alignment_store::describe(alignment_store::records()[found->record].result.elements[found->element]).kind == name)
|
||||||
|
{
|
||||||
|
chosen = track;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chosen == nullptr || chosen->m_editorremoved)
|
||||||
|
{
|
||||||
|
WriteLog("SELFTEST " + command + ": no path " + name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_node = chosen;
|
||||||
|
ui()->set_node(m_node);
|
||||||
|
auto const deleted{chosen->name()};
|
||||||
|
delete_selected_track();
|
||||||
|
WriteLog("SELFTEST " + command + ": " + deleted + " deleted");
|
||||||
|
}
|
||||||
else if (command == "btfcheck")
|
else if (command == "btfcheck")
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|||||||
@@ -1233,10 +1233,25 @@ void editor_mode::push_track_snapshot(std::vector<std::pair<TTrack *, editor_tra
|
|||||||
snap.created = std::move(Created);
|
snap.created = std::move(Created);
|
||||||
snap.removed = std::move(Removed);
|
snap.removed = std::move(Removed);
|
||||||
infra_attach(snap);
|
infra_attach(snap);
|
||||||
|
snap.alignments = alignment_store::take_changes();
|
||||||
|
snap.switch_records = switch_store::take_changes();
|
||||||
m_history.push_back(std::move(snap));
|
m_history.push_back(std::move(snap));
|
||||||
g_redo.clear();
|
g_redo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void editor_mode::records_to_history()
|
||||||
|
{
|
||||||
|
auto alignments{alignment_store::take_changes()};
|
||||||
|
auto switches{switch_store::take_changes()};
|
||||||
|
if (m_history.empty() || m_history.back().action != EditorSnapshot::Action::TrackEdit)
|
||||||
|
return;
|
||||||
|
auto &last{m_history.back()};
|
||||||
|
if (alignments.has_value() && false == last.alignments.has_value())
|
||||||
|
last.alignments = std::move(alignments);
|
||||||
|
if (switches.has_value() && false == last.switch_records.has_value())
|
||||||
|
last.switch_records = std::move(switches);
|
||||||
|
}
|
||||||
|
|
||||||
bool editor_mode::tracks_editable(std::vector<TTrack *> const &Tracks, std::string &Reason)
|
bool editor_mode::tracks_editable(std::vector<TTrack *> const &Tracks, std::string &Reason)
|
||||||
{
|
{
|
||||||
for (auto const *track : Tracks)
|
for (auto const *track : Tracks)
|
||||||
@@ -1282,6 +1297,18 @@ void editor_mode::restore_track_snapshot(EditorSnapshot const &Snapshot, std::ve
|
|||||||
m_profiles = Snapshot.profile_library;
|
m_profiles = Snapshot.profile_library;
|
||||||
profile_library_mark(std::move(layers));
|
profile_library_mark(std::move(layers));
|
||||||
}
|
}
|
||||||
|
alignment_store::settle();
|
||||||
|
switch_store::settle();
|
||||||
|
if (Snapshot.alignments.has_value())
|
||||||
|
{
|
||||||
|
current.alignments = alignment_store::records();
|
||||||
|
alignment_store::restore(*Snapshot.alignments);
|
||||||
|
}
|
||||||
|
if (Snapshot.switch_records.has_value())
|
||||||
|
{
|
||||||
|
current.switch_records = switch_store::records();
|
||||||
|
switch_store::restore(*Snapshot.switch_records);
|
||||||
|
}
|
||||||
Opposite.push_back(std::move(current));
|
Opposite.push_back(std::move(current));
|
||||||
|
|
||||||
if (Undo)
|
if (Undo)
|
||||||
@@ -1835,6 +1862,7 @@ void editor_mode::render_turnout_ui()
|
|||||||
editor_track::follow(*track, following);
|
editor_track::follow(*track, following);
|
||||||
editor_track::commit(changed);
|
editor_track::commit(changed);
|
||||||
record_switch(*track, Template);
|
record_switch(*track, Template);
|
||||||
|
records_to_history();
|
||||||
if (false == loose.empty())
|
if (false == loose.empty())
|
||||||
ui()->set_status(STR_C("Too far from the new ends of the switch, left unjoined: ") + loose, true);
|
ui()->set_status(STR_C("Too far from the new ends of the switch, left unjoined: ") + loose, true);
|
||||||
};
|
};
|
||||||
@@ -2552,6 +2580,7 @@ void editor_mode::render_route_stored()
|
|||||||
if (ImGui::SmallButton(STR_C("Forget the kept design")))
|
if (ImGui::SmallButton(STR_C("Forget the kept design")))
|
||||||
{
|
{
|
||||||
alignment_store::forget(route.departed);
|
alignment_store::forget(route.departed);
|
||||||
|
alignment_store::settle();
|
||||||
route.departed = -1;
|
route.departed = -1;
|
||||||
route.status = STR_C("The kept design will be removed from ") + layer + STR_C(" on save");
|
route.status = STR_C("The kept design will be removed from ") + layer + STR_C(" on save");
|
||||||
}
|
}
|
||||||
@@ -2711,6 +2740,7 @@ void editor_mode::route_apply()
|
|||||||
route_update();
|
route_update();
|
||||||
}
|
}
|
||||||
route_store();
|
route_store();
|
||||||
|
records_to_history();
|
||||||
route.status = STR_C("Re-laid ") + std::to_string(chain.tracks.size()) + STR_C(" paths") + (added > 0 ? STR_C(", added ") + std::to_string(added) : std::string{});
|
route.status = STR_C("Re-laid ") + std::to_string(chain.tracks.size()) + STR_C(" paths") + (added > 0 ? STR_C(", added ") + std::to_string(added) : std::string{});
|
||||||
if (startextension > 0.0 || endextension > 0.0)
|
if (startextension > 0.0 || endextension > 0.0)
|
||||||
route.status += format(", the curve took over %.2f / %.2f m of the adjoining straights", startextension, endextension);
|
route.status += format(", the curve took over %.2f / %.2f m of the adjoining straights", startextension, endextension);
|
||||||
@@ -4313,6 +4343,8 @@ void editor_mode::delete_selected_track()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// retired first, so the infrastructure it carried and moves elsewhere is in the same undo step
|
// retired first, so the infrastructure it carried and moves elsewhere is in the same undo step
|
||||||
|
if (auto const known{switch_store::of(*track)})
|
||||||
|
switch_store::forget(known->name);
|
||||||
editor_track::retire(*track);
|
editor_track::retire(*track);
|
||||||
// a switch leaves its main track behind, so the line isn't broken, unless Shift asks for all of it
|
// a switch leaves its main track behind, so the line isn't broken, unless Shift asks for all of it
|
||||||
std::vector<TTrack *> created;
|
std::vector<TTrack *> created;
|
||||||
@@ -6265,7 +6297,10 @@ void editor_mode::render_switch_record(TTrack &Track)
|
|||||||
item_tooltip("Chainage of the start of the switch; taken from the horizontal alignment kept in the scenery when the switch lies on one");
|
item_tooltip("Chainage of the start of the switch; taken from the horizontal alignment kept in the scenery when the switch lies on one");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
if (changed)
|
if (changed)
|
||||||
|
{
|
||||||
switch_store::put(entry, entry.layer);
|
switch_store::put(entry, entry.layer);
|
||||||
|
switch_store::settle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_mode::switch_placed(std::vector<TTrack *> const &Created)
|
void editor_mode::switch_placed(std::vector<TTrack *> const &Created)
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ std::string const kMark{"//$h"};
|
|||||||
double const kStep{1.0};
|
double const kStep{1.0};
|
||||||
|
|
||||||
std::vector<record> g_records;
|
std::vector<record> g_records;
|
||||||
|
std::vector<record> g_base; // as they were before the changes not yet in the undo history
|
||||||
|
bool g_changed{false};
|
||||||
bool g_loaded{false};
|
bool g_loaded{false};
|
||||||
|
|
||||||
// format of the lines, coordinates in the space of the file:
|
// format of the lines, coordinates in the space of the file:
|
||||||
@@ -257,6 +259,8 @@ stored_element describe(alignment::element const &Element)
|
|||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
g_records.clear();
|
g_records.clear();
|
||||||
|
g_base.clear();
|
||||||
|
g_changed = false;
|
||||||
g_loaded = false;
|
g_loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +367,8 @@ void load()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
if (false == g_records.empty())
|
if (false == g_records.empty())
|
||||||
WriteLog("Editor: " + std::to_string(g_records.size()) + " horizontal alignment(s) read from the scenery", logtype::generic);
|
WriteLog("Editor: " + std::to_string(g_records.size()) + " horizontal alignment(s) read from the scenery", logtype::generic);
|
||||||
}
|
}
|
||||||
@@ -585,6 +591,7 @@ int store(alignment::design const &Design, alignment::result const &Result, doub
|
|||||||
g_records.push_back(std::move(entry));
|
g_records.push_back(std::move(entry));
|
||||||
index = static_cast<int>(g_records.size()) - 1;
|
index = static_cast<int>(g_records.size()) - 1;
|
||||||
}
|
}
|
||||||
|
g_changed = true;
|
||||||
mark(g_records[index].layer);
|
mark(g_records[index].layer);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -596,6 +603,7 @@ void forget(int const Index)
|
|||||||
return;
|
return;
|
||||||
auto const layer{g_records[Index].layer};
|
auto const layer{g_records[Index].layer};
|
||||||
g_records.erase(g_records.begin() + Index);
|
g_records.erase(g_records.begin() + Index);
|
||||||
|
g_changed = true;
|
||||||
mark(layer);
|
mark(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,4 +615,32 @@ std::optional<double> chainage_at(glm::dvec3 const &Point)
|
|||||||
return g_records[found->record].origin + found->chainage;
|
return g_records[found->record].origin + found->chainage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<record>> take_changes()
|
||||||
|
{
|
||||||
|
if (false == g_changed)
|
||||||
|
return std::nullopt;
|
||||||
|
auto before{std::move(g_base)};
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void settle()
|
||||||
|
{
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore(std::vector<record> Records)
|
||||||
|
{
|
||||||
|
std::set<scene::layer_handle> layers;
|
||||||
|
for (auto const *list : {&g_records, &Records})
|
||||||
|
for (auto const &entry : *list)
|
||||||
|
layers.insert(entry.layer);
|
||||||
|
g_records = std::move(Records);
|
||||||
|
for (auto const layer : layers)
|
||||||
|
mark(layer);
|
||||||
|
settle();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace alignment_store
|
} // namespace alignment_store
|
||||||
|
|||||||
@@ -87,5 +87,11 @@ int store(alignment::design const &Design, alignment::result const &Result, doub
|
|||||||
void forget(int const Index);
|
void forget(int const Index);
|
||||||
// km of the point on the stored alignments, if it lies on one
|
// km of the point on the stored alignments, if it lies on one
|
||||||
std::optional<double> chainage_at(glm::dvec3 const &Point);
|
std::optional<double> chainage_at(glm::dvec3 const &Point);
|
||||||
|
// the records as they were before the changes made since the last call, if there were any; the current ones become the base
|
||||||
|
std::optional<std::vector<record>> take_changes();
|
||||||
|
// the current records become the base, the changes made so far aren't a part of the undo history
|
||||||
|
void settle();
|
||||||
|
// puts the records back as they were, for undo and redo
|
||||||
|
void restore(std::vector<record> Records);
|
||||||
|
|
||||||
} // namespace alignment_store
|
} // namespace alignment_store
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ std::string const kMark{"//$r"};
|
|||||||
double const kTolerance{0.02};
|
double const kTolerance{0.02};
|
||||||
|
|
||||||
std::vector<record> g_records;
|
std::vector<record> g_records;
|
||||||
|
std::vector<record> g_base; // as they were before the changes not yet in the undo history
|
||||||
|
bool g_changed{false};
|
||||||
bool g_loaded{false};
|
bool g_loaded{false};
|
||||||
|
|
||||||
// format of the lines, coordinates in the space of the file:
|
// format of the lines, coordinates in the space of the file:
|
||||||
@@ -100,6 +102,8 @@ void mark(scene::layer_handle const Layer)
|
|||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
g_records.clear();
|
g_records.clear();
|
||||||
|
g_base.clear();
|
||||||
|
g_changed = false;
|
||||||
g_loaded = false;
|
g_loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +147,8 @@ void load()
|
|||||||
g_records.push_back(std::move(entry));
|
g_records.push_back(std::move(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
if (false == g_records.empty())
|
if (false == g_records.empty())
|
||||||
WriteLog("Editor: " + std::to_string(g_records.size()) + " switch record(s) read from the scenery", logtype::generic);
|
WriteLog("Editor: " + std::to_string(g_records.size()) + " switch record(s) read from the scenery", logtype::generic);
|
||||||
}
|
}
|
||||||
@@ -189,11 +195,13 @@ void put(record Entry, scene::layer_handle const Layer)
|
|||||||
if (Entry.number == "-")
|
if (Entry.number == "-")
|
||||||
Entry.number = existing->number;
|
Entry.number = existing->number;
|
||||||
*existing = std::move(Entry);
|
*existing = std::move(Entry);
|
||||||
|
g_changed = true;
|
||||||
mark(existing->layer);
|
mark(existing->layer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Entry.layer = Layer;
|
Entry.layer = Layer;
|
||||||
g_records.push_back(std::move(Entry));
|
g_records.push_back(std::move(Entry));
|
||||||
|
g_changed = true;
|
||||||
mark(g_records.back().layer);
|
mark(g_records.back().layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +212,9 @@ void forget(std::string const &Name)
|
|||||||
for (auto const &entry : g_records)
|
for (auto const &entry : g_records)
|
||||||
if (entry.name == Name)
|
if (entry.name == Name)
|
||||||
layers.insert(entry.layer);
|
layers.insert(entry.layer);
|
||||||
|
auto const count{g_records.size()};
|
||||||
g_records.erase(std::remove_if(g_records.begin(), g_records.end(), [&](record const &Entry) { return Entry.name == Name; }), g_records.end());
|
g_records.erase(std::remove_if(g_records.begin(), g_records.end(), [&](record const &Entry) { return Entry.name == Name; }), g_records.end());
|
||||||
|
g_changed = g_changed || g_records.size() != count;
|
||||||
for (auto const layer : layers)
|
for (auto const layer : layers)
|
||||||
mark(layer);
|
mark(layer);
|
||||||
}
|
}
|
||||||
@@ -234,6 +244,7 @@ void tidy()
|
|||||||
g_records.erase(std::remove_if(g_records.begin(), g_records.end(), gone), g_records.end());
|
g_records.erase(std::remove_if(g_records.begin(), g_records.end(), gone), g_records.end());
|
||||||
for (auto const layer : layers)
|
for (auto const layer : layers)
|
||||||
mark(layer);
|
mark(layer);
|
||||||
|
g_changed = g_changed || false == layers.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string label(record const &Record)
|
std::string label(record const &Record)
|
||||||
@@ -254,4 +265,32 @@ std::string label(record const &Record)
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<record>> take_changes()
|
||||||
|
{
|
||||||
|
if (false == g_changed)
|
||||||
|
return std::nullopt;
|
||||||
|
auto before{std::move(g_base)};
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void settle()
|
||||||
|
{
|
||||||
|
g_base = g_records;
|
||||||
|
g_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore(std::vector<record> Records)
|
||||||
|
{
|
||||||
|
std::set<scene::layer_handle> layers;
|
||||||
|
for (auto const *list : {&g_records, &Records})
|
||||||
|
for (auto const &entry : *list)
|
||||||
|
layers.insert(entry.layer);
|
||||||
|
g_records = std::move(Records);
|
||||||
|
for (auto const layer : layers)
|
||||||
|
mark(layer);
|
||||||
|
settle();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace switch_store
|
} // namespace switch_store
|
||||||
|
|||||||
@@ -57,5 +57,11 @@ void forget(std::string const &Name);
|
|||||||
void tidy();
|
void tidy();
|
||||||
// "Rz 60E1-500-1:12 L", as the type is written on the lists of the switches
|
// "Rz 60E1-500-1:12 L", as the type is written on the lists of the switches
|
||||||
std::string label(record const &Record);
|
std::string label(record const &Record);
|
||||||
|
// the records as they were before the changes made since the last call, if there were any; the current ones become the base
|
||||||
|
std::optional<std::vector<record>> take_changes();
|
||||||
|
// the current records become the base, the changes made so far aren't a part of the undo history
|
||||||
|
void settle();
|
||||||
|
// puts the records back as they were, for undo and redo
|
||||||
|
void restore(std::vector<record> Records);
|
||||||
|
|
||||||
} // namespace switch_store
|
} // namespace switch_store
|
||||||
|
|||||||
Reference in New Issue
Block a user