mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-11 12:24:25 +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:
@@ -2986,8 +2986,9 @@ bool editor_mode::save()
|
|||||||
}
|
}
|
||||||
first_step_done(first_step::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::vector<std::string> rootstatements;
|
||||||
|
std::map<scene::layer_handle, std::vector<std::string>> statements;
|
||||||
if (m_streamer.active())
|
if (m_streamer.active())
|
||||||
{
|
{
|
||||||
std::string error;
|
std::string error;
|
||||||
@@ -2997,7 +2998,13 @@ bool editor_mode::save()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (false == scene::Layers.terrain_directive())
|
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)
|
if (m_profile.changed)
|
||||||
@@ -3016,14 +3023,14 @@ bool editor_mode::save()
|
|||||||
m_orthophoto_mark = map;
|
m_orthophoto_mark = map;
|
||||||
scene::Layers.mark(scene::layer_handle{1}, "//$o", {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 controls{turntable_controls(rootstatements)};
|
||||||
auto const noses{nose_controls(rootstatements)};
|
auto const noses{nose_controls(rootstatements)};
|
||||||
std::vector<std::string> trailing;
|
std::vector<std::string> trailing;
|
||||||
auto const placed{m_vehicle.trainset_lines(trailing)};
|
auto const placed{m_vehicle.trainset_lines(trailing)};
|
||||||
if (placed == 0)
|
if (placed == 0)
|
||||||
starter_trainset(trailing);
|
starter_trainset(trailing);
|
||||||
auto const result = scene::Layers.save(rootstatements, trailing);
|
auto const result = scene::Layers.save(rootstatements, trailing, statements);
|
||||||
if (result.success && controls)
|
if (result.success && controls)
|
||||||
m_turntable_included = true;
|
m_turntable_included = true;
|
||||||
if (result.success && noses)
|
if (result.success && noses)
|
||||||
|
|||||||
@@ -1896,8 +1896,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
|||||||
void apply_switch_drive_choice(TTrack &Switch);
|
void apply_switch_drive_choice(TTrack &Switch);
|
||||||
void switch_drive_captured(TTrack const &Track);
|
void switch_drive_captured(TTrack const &Track);
|
||||||
void switch_drives_committed(std::vector<TTrack *> const &Tracks);
|
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
|
scene::layer_handle output_layer(std::string const &Part) override;
|
||||||
std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error) 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
|
// moves them, as one step of the undo
|
||||||
std::size_t move_templates(std::vector<std::pair<standing_template, template_item>> const &Moves) override;
|
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
|
// takes them out, as one step of the undo
|
||||||
|
|||||||
@@ -243,7 +243,41 @@ std::vector<editor_mode::standing_template> editor_mode::standing_templates(std:
|
|||||||
return result;
|
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())
|
if (Items.empty())
|
||||||
return 0;
|
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)");
|
Error = STR_C("Templates can be placed only in a scenery opened for editing (-edit)");
|
||||||
return 0;
|
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))
|
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);
|
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));
|
items.push_back(std::move(item));
|
||||||
}
|
}
|
||||||
std::string error;
|
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;
|
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)
|
if (placed > 0)
|
||||||
m_guide.first_step_done(editor_first_step::posts);
|
m_guide.first_step_done(editor_first_step::posts);
|
||||||
WriteLog("Editor: " + tool.status, logtype::generic);
|
WriteLog("Editor: " + tool.status, logtype::generic);
|
||||||
|
|||||||
@@ -844,7 +844,7 @@ bool editor_mode::signal_place(signal_spot const &Spot, signal_template const &T
|
|||||||
if (Template.linked)
|
if (Template.linked)
|
||||||
item.values["#7"] = tool.linked[0] != '\0' ? std::string{tool.linked} : std::string{"none"};
|
item.values["#7"] = tool.linked[0] != '\0' ? std::string{tool.linked} : std::string{"none"};
|
||||||
std::string error;
|
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);
|
tool.status = refused(STR_C("The signal couldn't be placed: ") + error);
|
||||||
return false;
|
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;
|
std::vector<scene::instance_handle> instances;
|
||||||
if (Error.empty() && false == items.empty())
|
if (Error.empty() && false == items.empty())
|
||||||
{
|
{
|
||||||
if (place_templates(items, Error) == 0)
|
if (place_templates(items, Error, output_layer("srk")) == 0)
|
||||||
reads.clear();
|
reads.clear();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -879,7 +879,9 @@ srk_tool::record &srk_tool::record_of_open()
|
|||||||
auto *first{m_layout->switches.front()};
|
auto *first{m_layout->switches.front()};
|
||||||
entry.anchor = first->name();
|
entry.anchor = first->name();
|
||||||
entry.track = first;
|
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_records.push_back(std::move(entry));
|
||||||
m_record = static_cast<int>(m_records.size()) - 1;
|
m_record = static_cast<int>(m_records.size()) - 1;
|
||||||
m_anchor = first;
|
m_anchor = first;
|
||||||
|
|||||||
@@ -199,7 +199,10 @@ class editor_templates
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual std::vector<standing_template> standing_templates(std::function<bool(std::string const &)> const &Accept) const = 0;
|
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 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;
|
virtual std::size_t remove_templates(std::vector<scene::instance_handle> const &Instances) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
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ą"
|
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\")"
|
||||||
|
|||||||
@@ -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
|
// 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);
|
Parent = resolve(Parent);
|
||||||
if (false == valid(Parent) || layer(Parent).removed || layer(Parent).binary)
|
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_begin = valid(anchor) ? layer(anchor).context_end : layer(Parent).context_insert();
|
||||||
created.context_end = created.context_begin;
|
created.context_end = created.context_begin;
|
||||||
|
|
||||||
active(layerhandle);
|
if (Activate)
|
||||||
|
{
|
||||||
|
active(layerhandle);
|
||||||
|
}
|
||||||
|
|
||||||
return layerhandle;
|
return layerhandle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ class node_layers
|
|||||||
void mark(layer_handle Layer, std::string const &Mark, std::vector<std::string> Lines);
|
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()
|
// 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
|
// 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);
|
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;
|
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
|
// 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);
|
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
|
// 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.
|
// 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
|
// 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 = {});
|
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;
|
std::string check_sources() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -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
|
// 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;
|
save_result result;
|
||||||
if (m_layers.empty())
|
if (m_layers.empty())
|
||||||
@@ -1455,7 +1455,7 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements, st
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (layer(candidate).created || state.patches.count(candidate) != 0 || appended.count(candidate) != 0 || created.count(candidate) != 0 || placed.count(candidate) != 0 ||
|
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);
|
outputs.emplace_back(candidate);
|
||||||
}
|
}
|
||||||
@@ -1568,6 +1568,14 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements, st
|
|||||||
added.text += statement + eol;
|
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())
|
if (output == root && false == Trailingstatements.empty())
|
||||||
{
|
{
|
||||||
composition trailing;
|
composition trailing;
|
||||||
|
|||||||
Reference in New Issue
Block a user