17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-27 23:27:29 +01:00

feat(editor): the signalling, the hectometre posts and the terrain go to layers of their own: <scenery>_srk.scm, _hektometry.scm, _teren.scm, made by the first of them and included by the scenario file, the active layer left as it is; the station descriptions of the signalling there too

This commit is contained in:
maj00r
2026-10-23 13:07:14 +02:00
parent d14b4534ee
commit fe3dd758ea
10 changed files with 85 additions and 21 deletions

View File

@@ -2986,8 +2986,9 @@ bool editor_mode::save()
}
first_step_done(first_step::save);
// the heightmap terrain is kept in files of its own, the scenery only needs the directive which loads it
// the heightmap terrain is kept in files of its own, the scenery only needs the directive which loads it, in a layer of its own
std::vector<std::string> rootstatements;
std::map<scene::layer_handle, std::vector<std::string>> statements;
if (m_streamer.active())
{
std::string error;
@@ -2997,7 +2998,13 @@ bool editor_mode::save()
return false;
}
if (false == scene::Layers.terrain_directive())
rootstatements.emplace_back("heightmap_terrain " + m_streamer.name() + " endheightmap_terrain");
{
auto const directive{"heightmap_terrain " + m_streamer.name() + " endheightmap_terrain"};
if (auto const layer{output_layer("teren")}; layer != null_handle)
statements[layer].push_back(directive);
else
rootstatements.push_back(directive);
}
}
if (m_profile.changed)
@@ -3016,14 +3023,14 @@ bool editor_mode::save()
m_orthophoto_mark = map;
scene::Layers.mark(scene::layer_handle{1}, "//$o", {map});
}
auto const terrainadded{false == rootstatements.empty()};
auto const terrainadded{false == rootstatements.empty() || false == statements.empty()};
auto const controls{turntable_controls(rootstatements)};
auto const noses{nose_controls(rootstatements)};
std::vector<std::string> trailing;
auto const placed{m_vehicle.trainset_lines(trailing)};
if (placed == 0)
starter_trainset(trailing);
auto const result = scene::Layers.save(rootstatements, trailing);
auto const result = scene::Layers.save(rootstatements, trailing, statements);
if (result.success && controls)
m_turntable_included = true;
if (result.success && noses)

View File

@@ -1896,8 +1896,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri
void apply_switch_drive_choice(TTrack &Switch);
void switch_drive_captured(TTrack const &Track);
void switch_drives_committed(std::vector<TTrack *> const &Tracks);
// places them in the active layer, as one step of the undo. returns: how many were placed
std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error) override;
scene::layer_handle output_layer(std::string const &Part) override;
// places them in the active layer or the given one, as one step of the undo. returns: how many were placed
std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error, scene::layer_handle Layer = scene::layer_handle{}) override;
// moves them, as one step of the undo
std::size_t move_templates(std::vector<std::pair<standing_template, template_item>> const &Moves) override;
// takes them out, as one step of the undo

View File

@@ -243,7 +243,41 @@ std::vector<editor_mode::standing_template> editor_mode::standing_templates(std:
return result;
}
std::size_t editor_mode::place_templates(std::vector<template_item> const &Items, std::string &Error)
scene::layer_handle editor_mode::output_layer(std::string const &Part)
{
if (scene::Layers.empty())
return null_handle;
auto stem{scene::Layers.layer(scene::layer_handle{1}).name};
if (auto const slash{stem.find_last_of("/\\")}; slash != std::string::npos)
stem.erase(0, slash + 1);
if (auto const dot{stem.rfind('.')}; dot != std::string::npos)
stem.erase(dot);
stem.erase(0, stem.find_first_not_of('$'));
if (stem.empty())
stem = "scenery";
std::string reason;
// a file of that name the scenery doesn't include, or one which can't take more, gives way to the next number
for (int attempt = 1; attempt <= 9; ++attempt)
{
auto const name{ToLower(stem + "_" + Part + (attempt > 1 ? std::to_string(attempt) : std::string{}) + ".scm")};
auto layer{null_handle};
for (std::size_t index = 1; index <= scene::Layers.size() && layer == null_handle; ++index)
if (auto const &existing{scene::Layers.layer(static_cast<scene::layer_handle>(index))}; false == existing.dead && false == existing.removed && existing.name == name)
layer = scene::Layers.resolve(static_cast<scene::layer_handle>(index));
if (layer == null_handle)
layer = scene::Layers.create(name, scene::layer_handle{1}, reason, false);
if (layer != null_handle && scene::Layers.accepts(layer, &reason))
{
scene::Layers.visible(layer, true);
scene::Layers.locked(layer, false);
return layer;
}
}
WriteLog("Editor: no layer for " + Part + ", the active one takes it: " + reason, logtype::generic);
return null_handle;
}
std::size_t editor_mode::place_templates(std::vector<template_item> const &Items, std::string &Error, scene::layer_handle const Layer)
{
if (Items.empty())
return 0;
@@ -252,7 +286,7 @@ std::size_t editor_mode::place_templates(std::vector<template_item> const &Items
Error = STR_C("Templates can be placed only in a scenery opened for editing (-edit)");
return 0;
}
auto const layer{scene::Layers.resolve(scene::Layers.active())};
auto const layer{scene::Layers.resolve(Layer != null_handle ? Layer : scene::Layers.active())};
if (std::string reason; false == scene::Layers.accepts(layer, &reason))
{
Error = STR_C("The active layer can't take them: ") + (reason.empty() ? std::string{STR_C("there's no active layer")} : reason);
@@ -569,8 +603,11 @@ void hekto_tool::hekto_place()
items.push_back(std::move(item));
}
std::string error;
auto const placed{m_templates.place_templates(items, error)};
auto const layer{items.empty() ? null_handle : m_templates.output_layer("hektometry")};
auto const placed{m_templates.place_templates(items, error, layer)};
tool.status = placed > 0 ? format(STR_P("%zu hectometre post placed, Ctrl+Z takes it back", "%zu hectometre posts placed, Ctrl+Z takes them back", static_cast<long long>(placed)), placed) : error;
if (placed > 0 && layer != null_handle)
tool.status += format(STR_C(" (layer \"%s\")"), scene::Layers.layer(layer).name.c_str());
if (placed > 0)
m_guide.first_step_done(editor_first_step::posts);
WriteLog("Editor: " + tool.status, logtype::generic);

View File

@@ -844,7 +844,7 @@ bool editor_mode::signal_place(signal_spot const &Spot, signal_template const &T
if (Template.linked)
item.values["#7"] = tool.linked[0] != '\0' ? std::string{tool.linked} : std::string{"none"};
std::string error;
if (place_templates({item}, error) == 0)
if (place_templates({item}, error, output_layer("srk")) == 0)
{
tool.status = refused(STR_C("The signal couldn't be placed: ") + error);
return false;
@@ -1452,7 +1452,7 @@ std::size_t editor_mode::signal_batch(signal_changes const &Changes, std::vector
std::vector<scene::instance_handle> instances;
if (Error.empty() && false == items.empty())
{
if (place_templates(items, Error) == 0)
if (place_templates(items, Error, output_layer("srk")) == 0)
reads.clear();
else
{

View File

@@ -879,7 +879,9 @@ srk_tool::record &srk_tool::record_of_open()
auto *first{m_layout->switches.front()};
entry.anchor = first->name();
entry.track = first;
entry.layer = alignment_store::layer_of(*first);
entry.layer = m_templates.output_layer("srk");
if (entry.layer == null_handle)
entry.layer = alignment_store::layer_of(*first);
m_records.push_back(std::move(entry));
m_record = static_cast<int>(m_records.size()) - 1;
m_anchor = first;

View File

@@ -199,7 +199,10 @@ class editor_templates
{
public:
virtual std::vector<standing_template> standing_templates(std::function<bool(std::string const &)> const &Accept) const = 0;
virtual std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error) = 0;
// the layer a tool keeps what it makes in, "<scenery>_<Part>.scm", made when the scenery has none yet. returns: null_handle if there can't be one
virtual scene::layer_handle output_layer(std::string const &Part) = 0;
// in the active layer unless given another
virtual std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error, scene::layer_handle Layer = scene::layer_handle{}) = 0;
virtual std::size_t move_templates(std::vector<std::pair<standing_template, template_item>> const &Moves) = 0;
virtual std::size_t remove_templates(std::vector<scene::instance_handle> const &Instances) = 0;

View File

@@ -11469,3 +11469,6 @@ msgstr[2] "Odczyt przywrócony: %zu z %zu semaforów"
msgid ": the rest stand farther than 10 m from a track, by vehicles or their events are gone"
msgstr ": pozostałe stoją dalej niż 10 m od toru, przy torze z pojazdami albo ich zdarzenia już nie istnieją"
msgid " (layer \"%s\")"
msgstr " (warstwa \"%s\")"

View File

@@ -558,7 +558,7 @@ void node_layers::stat(layer_handle const Layer)
}
// creates empty layer, included from specified one. returns: handle to the new layer, or null_handle with the explanation in Reason
layer_handle node_layers::create(std::string Name, layer_handle Parent, std::string &Reason)
layer_handle node_layers::create(std::string Name, layer_handle Parent, std::string &Reason, bool const Activate)
{
Parent = resolve(Parent);
if (false == valid(Parent) || layer(Parent).removed || layer(Parent).binary)
@@ -639,7 +639,10 @@ layer_handle node_layers::create(std::string Name, layer_handle Parent, std::str
created.context_begin = valid(anchor) ? layer(anchor).context_end : layer(Parent).context_insert();
created.context_end = created.context_begin;
active(layerhandle);
if (Activate)
{
active(layerhandle);
}
return layerhandle;
}

View File

@@ -294,8 +294,8 @@ class node_layers
void mark(layer_handle Layer, std::string const &Mark, std::vector<std::string> Lines);
// layer management. changes are applied to the scenery files by save()
// creates empty layer, included from specified one. returns: handle to the new layer, or null_handle with the explanation in Reason
layer_handle create(std::string Name, layer_handle Parent, std::string &Reason);
// creates empty layer, included from specified one, made active unless told otherwise. returns: handle to the new layer, or null_handle with the explanation in Reason
layer_handle create(std::string Name, layer_handle Parent, std::string &Reason, bool const Activate = true);
bool can_remove(layer_handle Layer, std::string &Reason) const;
// marks specified layer and the layers it includes as dropped from the scenery. their files are left on the disk
bool remove(layer_handle Layer);
@@ -348,8 +348,8 @@ class node_layers
// writes changes made in the editor to the scenery files: changed, created and deleted model instances and
// memory cells, and layer changes. the files are left intact unless the whole operation can be performed.
// Rootstatements: additional statements to place at the end of the scenario file
save_result save(std::vector<std::string> const &Rootstatements = {}, std::vector<std::string> const &Trailingstatements = {});
// Rootstatements: additional statements to place at the end of the scenario file; Statements: the same for other layers
save_result save(std::vector<std::string> const &Rootstatements = {}, std::vector<std::string> const &Trailingstatements = {}, std::map<layer_handle, std::vector<std::string>> const &Statements = {});
std::string check_sources() const;
private:

View File

@@ -633,7 +633,7 @@ bool node_layers::compose(save_state &State, layer_handle const Layer, compositi
}
// writes changes made in the editor to the scenery files
save_result node_layers::save(std::vector<std::string> const &Rootstatements, std::vector<std::string> const &Trailingstatements)
save_result node_layers::save(std::vector<std::string> const &Rootstatements, std::vector<std::string> const &Trailingstatements, std::map<layer_handle, std::vector<std::string>> const &Statements)
{
save_result result;
if (m_layers.empty())
@@ -1455,7 +1455,7 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements, st
continue;
}
if (layer(candidate).created || state.patches.count(candidate) != 0 || appended.count(candidate) != 0 || created.count(candidate) != 0 || placed.count(candidate) != 0 ||
markedtext.count(candidate) != 0 || (candidate == root && (false == Rootstatements.empty() || false == Trailingstatements.empty())))
markedtext.count(candidate) != 0 || Statements.count(candidate) != 0 || (candidate == root && (false == Rootstatements.empty() || false == Trailingstatements.empty())))
{
outputs.emplace_back(candidate);
}
@@ -1568,6 +1568,14 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements, st
added.text += statement + eol;
}
}
if (auto const lookup{Statements.find(output)}; lookup != Statements.end())
{
for (auto const &statement : lookup->second)
{
ensure_newline(added.text, eol);
added.text += statement + eol;
}
}
if (output == root && false == Trailingstatements.empty())
{
composition trailing;