mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-05 19:29:11 +01:00
feat(editor): every switch laid gets its drive at once, also the one made by pulling a free end into a straight (named z1, z2... like the others): the drive marked default: true in its //$e description (mech_komin) until another is picked, on the diverging side or the other; the drive goes into the same undo step as the switch; a switch with a drive puts it on the other side with one button, as one undo step; drive_headers.py marks mech_komin as the default; self-test commands drives and driveflip; Polish translation
This commit is contained in:
@@ -933,6 +933,7 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::array<std::string, 4> files;
|
std::array<std::string, 4> files;
|
||||||
|
bool preferred{false};
|
||||||
};
|
};
|
||||||
std::vector<drive_family> drives;
|
std::vector<drive_family> drives;
|
||||||
bool drives_scanned{false};
|
bool drives_scanned{false};
|
||||||
@@ -964,6 +965,9 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
void scan_switch_drives();
|
void scan_switch_drives();
|
||||||
std::string switch_name_for_new() const;
|
std::string switch_name_for_new() const;
|
||||||
bool place_switch_drive(TTrack &Switch);
|
bool place_switch_drive(TTrack &Switch);
|
||||||
|
bool flip_switch_drive(TTrack &Switch);
|
||||||
|
void advance_switch_name();
|
||||||
|
void join_last_steps();
|
||||||
bool render_switch_drive_choice();
|
bool render_switch_drive_choice();
|
||||||
int m_turnout_template{0};
|
int m_turnout_template{0};
|
||||||
struct turntable_template
|
struct turntable_template
|
||||||
|
|||||||
@@ -405,6 +405,28 @@ void editor_mode::selftest_step()
|
|||||||
m_switch.drive_side = side;
|
m_switch.drive_side = side;
|
||||||
WriteLog("SELFTEST switchdrive: " + (index >= 0 && index < static_cast<int>(m_switch.drives.size()) ? m_switch.drives[index].name : std::string{"none"}));
|
WriteLog("SELFTEST switchdrive: " + (index >= 0 && index < static_cast<int>(m_switch.drives.size()) ? m_switch.drives[index].name : std::string{"none"}));
|
||||||
}
|
}
|
||||||
|
else if (command == "drives")
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
words >> name;
|
||||||
|
scan_switch_drives();
|
||||||
|
std::string files;
|
||||||
|
for (auto const &standing : standing_templates([](std::string const &File) { return File.find("napedy/") != std::string::npos; }))
|
||||||
|
if (false == standing.values.empty() && standing.values[0] == name)
|
||||||
|
files += " " + standing.file;
|
||||||
|
for (scene::instance_handle handle = 1; handle <= scene::Layers.instance_count(); ++handle)
|
||||||
|
if (scene::Layers.tracked(handle) && scene::Layers.instance(handle).file != nullptr && scene::Layers.instance(handle).file->find("napedy") != std::string::npos)
|
||||||
|
files += format(" [%d %s removed %d dead %d]", static_cast<int>(handle), scene::Layers.instance(handle).file->c_str(), scene::Layers.instance(handle).removed ? 1 : 0, scene::Layers.instance(handle).dead ? 1 : 0);
|
||||||
|
WriteLog("SELFTEST drives " + name + ": chosen " + (m_switch.drive >= 0 ? m_switch.drives[m_switch.drive].name : std::string{"none"}) + ", side " + std::to_string(m_switch.drive_side) + ", standing" + files + ", steps " + std::to_string(m_history.size()));
|
||||||
|
}
|
||||||
|
else if (command == "driveflip")
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
words >> name;
|
||||||
|
auto *track{simulation::Paths.find(name)};
|
||||||
|
auto const done{track != nullptr && flip_switch_drive(*track)};
|
||||||
|
WriteLog("SELFTEST driveflip " + name + ": " + (done ? "done " : "failed ") + m_switch.status);
|
||||||
|
}
|
||||||
else if (command == "drivetilt")
|
else if (command == "drivetilt")
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|||||||
@@ -1927,7 +1927,12 @@ void editor_mode::render_turnout_ui()
|
|||||||
render_track_name(*track);
|
render_track_name(*track);
|
||||||
render_switch_record(*track);
|
render_switch_record(*track);
|
||||||
if ((simulation::Events.FindEvent(track->name() + "+") != nullptr && simulation::Events.FindEvent(track->name() + "-") != nullptr) || (m_track_name.track == track && m_track_name.uses.includes > 0))
|
if ((simulation::Events.FindEvent(track->name() + "+") != nullptr && simulation::Events.FindEvent(track->name() + "-") != nullptr) || (m_track_name.track == track && m_track_name.uses.includes > 0))
|
||||||
|
{
|
||||||
ImGui::TextDisabled(STR_C("Drive: events %s+ and %s- switch it, also in the map"), track->name().c_str(), track->name().c_str());
|
ImGui::TextDisabled(STR_C("Drive: events %s+ and %s- switch it, also in the map"), track->name().c_str(), track->name().c_str());
|
||||||
|
if (ImGui::Button(STR_C("Drive to the other side")))
|
||||||
|
flip_switch_drive(*track);
|
||||||
|
item_tooltip("Puts the drive of the switch on the other side of the track: the same drive, its variant for the other side");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.7f, 0.2f, 1.0f), "%s", STR_C("No drive: the switch can't be switched during the game"));
|
ImGui::TextColored(ImVec4(1.0f, 0.7f, 0.2f, 1.0f), "%s", STR_C("No drive: the switch can't be switched during the game"));
|
||||||
@@ -5769,8 +5774,9 @@ void editor_mode::finish_extend()
|
|||||||
std::vector<std::pair<TTrack *, editor_track::state>> states;
|
std::vector<std::pair<TTrack *, editor_track::state>> states;
|
||||||
std::vector<TTrack *> created;
|
std::vector<TTrack *> created;
|
||||||
std::vector<TTrack *> removed;
|
std::vector<TTrack *> removed;
|
||||||
if (false == place_switch_on_straight(plan.target, plan.shape, origin, plan.along, plan.direction, plan.side, false, states, created, removed))
|
if (false == place_switch_on_straight(plan.target, plan.shape, origin, plan.along, plan.direction, plan.side, false, states, created, removed, switch_name_for_new()))
|
||||||
return;
|
return;
|
||||||
|
auto *placed{*std::find_if(created.begin(), created.end(), [](TTrack const *Track) { return Track != nullptr && Track->eType == tt_Switch; })};
|
||||||
if (glm::distance(plan.insert.points[segment_data::point::start], plan.insert.points[segment_data::point::end]) > 0.01)
|
if (glm::distance(plan.insert.points[segment_data::point::start], plan.insert.points[segment_data::point::end]) > 0.01)
|
||||||
{
|
{
|
||||||
auto *insert{editor_track::create_path(*origin, plan.insert)};
|
auto *insert{editor_track::create_path(*origin, plan.insert)};
|
||||||
@@ -5779,6 +5785,9 @@ void editor_mode::finish_extend()
|
|||||||
}
|
}
|
||||||
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
|
if (place_switch_drive(*placed))
|
||||||
|
join_last_steps();
|
||||||
|
advance_switch_name();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const pieces{extend_pieces()};
|
auto const pieces{extend_pieces()};
|
||||||
@@ -6552,8 +6561,13 @@ void editor_mode::switch_placed(std::vector<TTrack *> const &Created)
|
|||||||
ui()->set_node(m_node);
|
ui()->set_node(m_node);
|
||||||
if (slip)
|
if (slip)
|
||||||
return;
|
return;
|
||||||
if (m_switch.drive >= 0)
|
if (place_switch_drive(**found))
|
||||||
place_switch_drive(**found);
|
join_last_steps();
|
||||||
|
advance_switch_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void editor_mode::advance_switch_name()
|
||||||
|
{
|
||||||
std::string name{m_switch.name};
|
std::string name{m_switch.name};
|
||||||
auto digits{name.size()};
|
auto digits{name.size()};
|
||||||
while (digits > 0 && std::isdigit(static_cast<unsigned char>(name[digits - 1])))
|
while (digits > 0 && std::isdigit(static_cast<unsigned char>(name[digits - 1])))
|
||||||
@@ -6595,9 +6609,11 @@ void editor_mode::scan_switch_drives()
|
|||||||
family = std::prev(tool.drives.end());
|
family = std::prev(tool.drives.end());
|
||||||
}
|
}
|
||||||
family->files[hand * 2 + drive] = entry.file;
|
family->files[hand * 2 + drive] = entry.file;
|
||||||
|
family->preferred |= info.switch_default;
|
||||||
}
|
}
|
||||||
std::sort(tool.drives.begin(), tool.drives.end(), [](switch_tool::drive_family const &A, switch_tool::drive_family const &B) { return A.name < B.name; });
|
std::sort(tool.drives.begin(), tool.drives.end(), [](switch_tool::drive_family const &A, switch_tool::drive_family const &B) { return A.name < B.name; });
|
||||||
tool.drive = tool.drives.empty() ? -1 : 0;
|
auto const preferred{std::find_if(tool.drives.begin(), tool.drives.end(), [](switch_tool::drive_family const &Family) { return Family.preferred; })};
|
||||||
|
tool.drive = tool.drives.empty() ? -1 : preferred != tool.drives.end() ? static_cast<int>(preferred - tool.drives.begin()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string editor_mode::switch_name_for_new() const
|
std::string editor_mode::switch_name_for_new() const
|
||||||
@@ -6615,6 +6631,7 @@ std::string editor_mode::switch_name_for_new() const
|
|||||||
bool editor_mode::place_switch_drive(TTrack &Switch)
|
bool editor_mode::place_switch_drive(TTrack &Switch)
|
||||||
{
|
{
|
||||||
auto &tool{m_switch};
|
auto &tool{m_switch};
|
||||||
|
scan_switch_drives();
|
||||||
if (tool.drive < 0 || tool.drive >= static_cast<int>(tool.drives.size()) || Switch.eType != tt_Switch || Switch.m_paths.size() < 2)
|
if (tool.drive < 0 || tool.drive >= static_cast<int>(tool.drives.size()) || Switch.eType != tt_Switch || Switch.m_paths.size() < 2)
|
||||||
return false;
|
return false;
|
||||||
auto const &main{Switch.m_paths[0]};
|
auto const &main{Switch.m_paths[0]};
|
||||||
@@ -6659,6 +6676,75 @@ bool editor_mode::place_switch_drive(TTrack &Switch)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool editor_mode::flip_switch_drive(TTrack &Switch)
|
||||||
|
{
|
||||||
|
auto &tool{m_switch};
|
||||||
|
scan_switch_drives();
|
||||||
|
auto const plain = [](std::string Text) {
|
||||||
|
std::replace(Text.begin(), Text.end(), '\\', '/');
|
||||||
|
std::transform(Text.begin(), Text.end(), Text.begin(), [](unsigned char Character) { return static_cast<char>(std::tolower(Character)); });
|
||||||
|
return Text;
|
||||||
|
};
|
||||||
|
std::map<std::string, std::pair<int, int>> variants;
|
||||||
|
for (int family = 0; family < static_cast<int>(tool.drives.size()); ++family)
|
||||||
|
for (int index = 0; index < 4; ++index)
|
||||||
|
if (false == tool.drives[family].files[index].empty())
|
||||||
|
variants[plain(tool.drives[family].files[index])] = {family, index};
|
||||||
|
auto const name{plain(Switch.name())};
|
||||||
|
auto const standing{standing_templates([&](std::string const &File) { return variants.count(File) > 0; })};
|
||||||
|
auto const found{std::find_if(standing.begin(), standing.end(), [&](standing_template const &Drive) { return plain(Drive.values[0]) == name; })};
|
||||||
|
if (found == standing.end())
|
||||||
|
{
|
||||||
|
tool.status = format(STR_C("No drive of the switch %s among the described drives"), Switch.name().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto const [family, index]{variants[found->file]};
|
||||||
|
template_item item;
|
||||||
|
item.file = tool.drives[family].files[index ^ 1];
|
||||||
|
if (item.file.empty())
|
||||||
|
{
|
||||||
|
tool.status = format(STR_C("The drive %s has no variant with the drive on the other side"), tool.drives[family].name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
item.location = found->location;
|
||||||
|
item.yaw = found->yaw;
|
||||||
|
item.described = true;
|
||||||
|
item.track = Switch.name();
|
||||||
|
auto const angle = [&](std::size_t const Index) {
|
||||||
|
double value{0.0};
|
||||||
|
if (Index < found->values.size())
|
||||||
|
std::sscanf(found->values[Index].c_str(), "%lf", &value);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
item.tilt = {angle(5), angle(6)};
|
||||||
|
if (remove_templates({found->instance}) == 0)
|
||||||
|
{
|
||||||
|
tool.status = STR_C("The drive of this switch can't be changed in its file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string error;
|
||||||
|
if (place_templates({item}, error) == 0)
|
||||||
|
{
|
||||||
|
scene::Layers.removed(found->instance, false);
|
||||||
|
m_history.pop_back();
|
||||||
|
tool.status = STR_C("The drive couldn't be placed: ") + error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
join_last_steps();
|
||||||
|
tool.status = format((index ^ 1) & 1 ? STR_C("Switch %s: the drive %s, on the right now") : STR_C("Switch %s: the drive %s, on the left now"), Switch.name().c_str(), item.file.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editor_mode::join_last_steps()
|
||||||
|
{
|
||||||
|
if (m_history.size() < 2)
|
||||||
|
return;
|
||||||
|
auto last{std::move(m_history.back())};
|
||||||
|
m_history.pop_back();
|
||||||
|
auto &previous{m_history.back()};
|
||||||
|
previous.instances.insert(previous.instances.end(), last.instances.begin(), last.instances.end());
|
||||||
|
}
|
||||||
|
|
||||||
bool editor_mode::render_switch_drive_choice()
|
bool editor_mode::render_switch_drive_choice()
|
||||||
{
|
{
|
||||||
auto &tool{m_switch};
|
auto &tool{m_switch};
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ bool parse(template_text const &Text, include_info &Info, std::string &Error)
|
|||||||
{
|
{
|
||||||
Info.switch_hand = drive["hand"].as<std::string>("");
|
Info.switch_hand = drive["hand"].as<std::string>("");
|
||||||
Info.switch_drive = drive["drive"].as<std::string>("");
|
Info.switch_drive = drive["drive"].as<std::string>("");
|
||||||
|
Info.switch_default = drive["default"].as<bool>(false);
|
||||||
}
|
}
|
||||||
if (auto const signal{document["signal"]}; signal.IsDefined() && signal.IsMap())
|
if (auto const signal{document["signal"]}; signal.IsDefined() && signal.IsMap())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ struct include_info
|
|||||||
std::string description;
|
std::string description;
|
||||||
std::string switch_hand; // a switch drive: side of the diverging track, left or right, looking from the start of the switch
|
std::string switch_hand; // a switch drive: side of the diverging track, left or right, looking from the start of the switch
|
||||||
std::string switch_drive; // and the side the drive stands on
|
std::string switch_drive; // and the side the drive stands on
|
||||||
|
bool switch_default{false}; // the drive put with a new switch until another is picked
|
||||||
double turntable_length{0.0};
|
double turntable_length{0.0};
|
||||||
int turntable_angles{0};
|
int turntable_angles{0};
|
||||||
int turntable_positions{0};
|
int turntable_positions{0};
|
||||||
|
|||||||
@@ -5421,3 +5421,24 @@ msgstr "Miejsce na prostej: %.2f m do tyłu, %.2f m do przodu"
|
|||||||
|
|
||||||
msgid "Click: edit this switch, drag: slide it along the straight"
|
msgid "Click: edit this switch, drag: slide it along the straight"
|
||||||
msgstr "Klik: edytuj ten rozjazd, przeciągnij: przesuń go wzdłuż prostej"
|
msgstr "Klik: edytuj ten rozjazd, przeciągnij: przesuń go wzdłuż prostej"
|
||||||
|
|
||||||
|
msgid "Drive to the other side"
|
||||||
|
msgstr "Napęd na drugą stronę"
|
||||||
|
|
||||||
|
msgid "Puts the drive of the switch on the other side of the track: the same drive, its variant for the other side"
|
||||||
|
msgstr "Stawia napęd zwrotnicy po drugiej stronie toru: ten sam napęd, jego wariant na drugą stronę"
|
||||||
|
|
||||||
|
msgid "No drive of the switch %s among the described drives"
|
||||||
|
msgstr "Wśród opisanych napędów nie ma napędu zwrotnicy %s"
|
||||||
|
|
||||||
|
msgid "The drive %s has no variant with the drive on the other side"
|
||||||
|
msgstr "Napęd %s nie ma wariantu z napędem po drugiej stronie"
|
||||||
|
|
||||||
|
msgid "The drive of this switch can't be changed in its file"
|
||||||
|
msgstr "Napędu tej zwrotnicy nie da się zmienić w jego pliku"
|
||||||
|
|
||||||
|
msgid "Switch %s: the drive %s, on the right now"
|
||||||
|
msgstr "Zwrotnica %s: napęd %s, teraz po prawej"
|
||||||
|
|
||||||
|
msgid "Switch %s: the drive %s, on the left now"
|
||||||
|
msgstr "Zwrotnica %s: napęd %s, teraz po lewej"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ LINEMARK = '//$e'
|
|||||||
FOLDER = 'scenery/tory/napedy'
|
FOLDER = 'scenery/tory/napedy'
|
||||||
PATTERN = re.compile(r'^(ele1?|mech[12]?)-rz([lp])-([lp])((?:_[a-z]+)*)\.inc$')
|
PATTERN = re.compile(r'^(ele1?|mech[12]?)-rz([lp])-([lp])((?:_[a-z]+)*)\.inc$')
|
||||||
KINDS = {'ele': 'elektryczny', 'mech': 'mechaniczny'}
|
KINDS = {'ele': 'elektryczny', 'mech': 'mechaniczny'}
|
||||||
|
DEFAULT = 'mech_komin'
|
||||||
|
|
||||||
|
|
||||||
def examine(path, file):
|
def examine(path, file):
|
||||||
@@ -48,7 +49,7 @@ def examine(path, file):
|
|||||||
'name: ' + family,
|
'name: ' + family,
|
||||||
'category: switch drive',
|
'category: switch drive',
|
||||||
'description: "' + description + '"',
|
'description: "' + description + '"',
|
||||||
'switch: {hand: %s, drive: %s}' % (hand, side),
|
'switch: {hand: %s, drive: %s%s}' % (hand, side, ', default: true' if family == DEFAULT else ''),
|
||||||
'params:',
|
'params:',
|
||||||
' - {id: 1, role: track, label: Switch}',
|
' - {id: 1, role: track, label: Switch}',
|
||||||
' - {id: 2, role: pos.x}',
|
' - {id: 2, role: pos.x}',
|
||||||
|
|||||||
Reference in New Issue
Block a user