mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 23:59:48 +01:00
The fifth and the sixth tool out of editor_mode, the two lineside ones sharing their file. Placing, moving and taking out the templates which stand by the track become services of the editor, with the template types of their own, and so do the tab of the track tools shown, the ground under a point and the first step done. The context menu, the click on a fouling point in the view and the lineside tabs go through the public calls of the tools. The self-test commands hekto and fouling move with them and log the same as before.
311 lines
12 KiB
C++
311 lines
12 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "application/editormode.h"
|
|
#include "editor/editorSettings.hpp"
|
|
#include "editor/editorGeometry.hpp"
|
|
#include "application/application.h"
|
|
#include "application/editoruilayer.h"
|
|
#include "application/editorprojection.h"
|
|
|
|
#include "simulation/simulation.h"
|
|
#include "simulation/simulationtime.h"
|
|
#include "scene/scenelayers.h"
|
|
#include "utilities/Globals.h"
|
|
#include "utilities/Logs.h"
|
|
#include "world/Track.h"
|
|
#include "world/TrackRails.h"
|
|
#include "world/MemCell.h"
|
|
#include "world/Event.h"
|
|
#include "vehicle/DynObj.h"
|
|
#include "model/AnimModel.h"
|
|
#include "model/Model3d.h"
|
|
#include "rendering/renderer.h"
|
|
#include "world/Sweep.h"
|
|
#include "input/keyboardinput.h"
|
|
#include "launcher/textures_scanner.h"
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <algorithm>
|
|
#include "editor/editorFormat.hpp"
|
|
#include "editor/editorAlignmentStore.hpp"
|
|
#include "editor/editorSwitchStore.hpp"
|
|
#include "scene/sceneterrain.h"
|
|
#include "editor/editorSpeed.hpp"
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <sstream>
|
|
#include "application/editormodeselftest.h"
|
|
|
|
editor_mode::selftest_result editor_mode::selftest_sweep(std::string const &command, std::istringstream &words)
|
|
{
|
|
if (command == "sweep")
|
|
{
|
|
std::map<std::string, std::string> values;
|
|
std::string pair;
|
|
while (words >> pair)
|
|
{
|
|
auto const equals{pair.find('=')};
|
|
if (equals != std::string::npos)
|
|
values[pair.substr(0, equals)] = pair.substr(equals + 1);
|
|
}
|
|
auto &tool{m_sweep};
|
|
auto const get = [&](char const *Key, std::string const &Default) { auto const found{values.find(Key)}; return found != values.end() ? found->second : Default; };
|
|
tool.edited = nullptr;
|
|
tool.curve_for = nullptr;
|
|
std::snprintf(tool.model, sizeof(tool.model), "%s", get("model", "").c_str());
|
|
tool.parameters.clear();
|
|
std::stringstream parameters(get("params", ""));
|
|
std::string parameter;
|
|
while (std::getline(parameters, parameter, ','))
|
|
{
|
|
tool.parameters.emplace_back();
|
|
std::snprintf(tool.parameters.back().data(), tool.parameters.back().size(), "%s", parameter.c_str());
|
|
}
|
|
tool.parameters_for = tool.model;
|
|
auto &settings{tool.settings};
|
|
settings.lateral = std::stod(get("lateral", "0"));
|
|
settings.height = std::stod(get("height", "0"));
|
|
auto const side{get("side", "origin")};
|
|
settings.side_anchor = side == "near" ? 1 : side == "far" ? 2 : side == "centre" ? 3 : 0;
|
|
auto const top{get("top", "origin")};
|
|
settings.height_anchor = top == "bottom" ? 1 : top == "top" ? 2 : top == "edge" ? 3 : 0;
|
|
settings.bend = get("mode", "bend") != "repeat";
|
|
settings.step = std::stod(get("step", "0"));
|
|
settings.widen = get("widen", "0") == "1";
|
|
settings.platform = get("platform", "0") == "1";
|
|
settings.face = get("face", "1") == "1";
|
|
settings.tilt = get("tilt", "0") == "1";
|
|
settings.from = std::stod(get("from", "0"));
|
|
settings.to = std::stod(get("to", "-1"));
|
|
auto const length{get("length", "all")};
|
|
tool.length_mode = length == "original" ? 0 : length == "all" ? 2 : 1;
|
|
if (tool.length_mode == 1)
|
|
tool.length = std::stod(length);
|
|
if (values.count("edge"))
|
|
EditorSettings.platform_edge(std::stod(values["edge"]));
|
|
tool.measured.clear();
|
|
tool.open = true;
|
|
sweep_curve();
|
|
sweep_measure();
|
|
if (values.count("widen"))
|
|
settings.widen = get("widen", "0") == "1";
|
|
if (values.count("platform"))
|
|
settings.platform = get("platform", "0") == "1";
|
|
if (get("create", "1") == "1")
|
|
{
|
|
sweep_create();
|
|
WriteLog("SELFTEST sweep: " + tool.status);
|
|
}
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "drag")
|
|
{
|
|
glm::dvec3 from{0.0};
|
|
glm::dvec3 to{0.0};
|
|
words >> from.x >> from.z >> to.x >> to.z;
|
|
m_sweep.open = true;
|
|
if (false == sweep_press_at(from, false))
|
|
{
|
|
WriteLog("SELFTEST drag: the press wasn't taken");
|
|
return selftest_result::handled;
|
|
}
|
|
sweep_drag_at(to);
|
|
sweep_release();
|
|
WriteLog("SELFTEST drag: " + m_sweep.status);
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "spread")
|
|
{
|
|
std::string name;
|
|
words >> name >> m_spread.stop >> m_spread.reach;
|
|
if (auto *track{simulation::Paths.find(name)})
|
|
{
|
|
std::string names;
|
|
for (auto const *other : track_spread_from(*track))
|
|
names += ' ' + other->name();
|
|
WriteLog("SELFTEST spread " + name + ":" + names + " | prev " + (track->trPrev ? track->trPrev->name() : std::string{"-"}) + " next " + (track->trNext ? track->trNext->name() : std::string{"-"}));
|
|
}
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "turntable")
|
|
{
|
|
glm::dvec3 centre{0.0};
|
|
double yaw{0.0};
|
|
words >> centre.x >> centre.y >> centre.z >> yaw;
|
|
turntable_place(centre, yaw);
|
|
for (double angle; words >> angle;)
|
|
{
|
|
m_turntable.heading = m_turntable.table_yaw + angle;
|
|
m_turntable.exit_length = 10.0;
|
|
track_intent intent;
|
|
intent.what = track_intent::kind::turntable_exit;
|
|
turntable_press(intent);
|
|
}
|
|
WriteLog("SELFTEST turntable: " + (m_turntable.error.empty() ? m_turntable.status : m_turntable.error));
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "bend" || command == "bendset")
|
|
{
|
|
std::map<std::string, std::string> values;
|
|
std::string pair;
|
|
while (words >> pair)
|
|
{
|
|
auto const equals{pair.find('=')};
|
|
if (equals != std::string::npos)
|
|
values[pair.substr(0, equals)] = pair.substr(equals + 1);
|
|
}
|
|
auto const vector = [](std::string Text) {
|
|
std::replace(Text.begin(), Text.end(), ',', ' ');
|
|
std::istringstream numbers(Text);
|
|
glm::dvec3 result{0.0};
|
|
numbers >> result.x >> result.y >> result.z;
|
|
return result;
|
|
};
|
|
auto const index = [](std::string const &Text, std::vector<std::string> const &Names) {
|
|
return static_cast<int>(std::find(Names.begin(), Names.end(), Text) - Names.begin());
|
|
};
|
|
auto &tool{m_bend};
|
|
auto const along{values.count("along") ? index(values["along"], {"start", "origin", "middle", "end", "point"}) : tool.along_anchor};
|
|
auto const side{values.count("side") ? index(values["side"], {"origin", "near", "far", "middle", "point"}) : tool.side_anchor};
|
|
auto const height{values.count("height") ? index(values["height"], {"origin", "bottom", "top", "edge", "point"}) : tool.height_anchor};
|
|
auto const point{values.count("point") ? vector(values["point"]) : tool.point};
|
|
if (command == "bend")
|
|
{
|
|
tool.edited = nullptr;
|
|
tool.along_anchor = along;
|
|
tool.side_anchor = side;
|
|
tool.height_anchor = height;
|
|
tool.point = point;
|
|
tool.axis = values.count("axis") ? index(values["axis"], {"auto", "z", "x"}) : 0;
|
|
tool.turned = values["turned"] == "1";
|
|
bend_source source;
|
|
if (false == bend_source_of_selection(source))
|
|
{
|
|
std::string reason;
|
|
auto const editable{m_node != nullptr && scene::Layers.editable(m_node, &reason)};
|
|
WriteLog(format("SELFTEST bend: nothing to bend (node %p template %d editable %d %s, instance %d)", static_cast<void *>(m_node), m_node != nullptr && m_node->from_template() ? 1 : 0, editable ? 1 : 0, reason.c_str(), static_cast<int>(m_instance)));
|
|
return selftest_result::handled;
|
|
}
|
|
tool.tracks_for = nullptr;
|
|
bend_find_tracks(glm::dvec3(source.transform[3]), source.model != nullptr ? static_cast<void const *>(source.model) : reinterpret_cast<void const *>(static_cast<std::uintptr_t>(source.instance)));
|
|
tool.track = values.count("track") ? std::stoi(values["track"]) : 0;
|
|
if (values.count("pick"))
|
|
bend_pick(vector(values["pick"]));
|
|
if (tool.tracks.empty())
|
|
{
|
|
WriteLog("SELFTEST bend: no track nearby");
|
|
return selftest_result::handled;
|
|
}
|
|
sweep_node::state state;
|
|
std::vector<TTrack *> tracks;
|
|
bend_definition(source, *tool.tracks[tool.track].first, state, tracks);
|
|
WriteLog(format("SELFTEST bend: track %s, %zu paths, anchor before %.3f %.3f %.3f, lateral %.3f height %.3f from %.3f to %.3f, axis %s flip %d; %s", tool.tracks[tool.track].first->name().c_str(), tracks.size(),
|
|
tool.marker.x, tool.marker.y, tool.marker.z, state.lateral, state.height, state.from, state.to, state.along_x ? "x" : "z", state.flip ? 1 : 0, tool.status.c_str()));
|
|
if (values["go"] == "1")
|
|
{
|
|
bend_selection();
|
|
WriteLog("SELFTEST bend: " + tool.status);
|
|
}
|
|
}
|
|
else if (auto *sweep{tool.edited})
|
|
{
|
|
auto state{sweep->definition()};
|
|
tool.along_anchor = along;
|
|
if (side != tool.side_anchor || height != tool.height_anchor || point != tool.point)
|
|
{
|
|
tool.side_anchor = side;
|
|
tool.height_anchor = height;
|
|
tool.point = point;
|
|
bend_reanchor(state, side, height, point);
|
|
}
|
|
if (values.count("lateral"))
|
|
state.lateral = std::stod(values["lateral"]);
|
|
if (values.count("up"))
|
|
state.height = std::stod(values["up"]);
|
|
if (values.count("widen"))
|
|
state.widen = values["widen"] == "1";
|
|
if (values.count("pick"))
|
|
{
|
|
bend_pick(vector(values["pick"]));
|
|
state = sweep->definition();
|
|
}
|
|
if (values.count("length"))
|
|
{
|
|
bend_stretch(*sweep, bend_fixed(*sweep, state.point), std::stod(values["length"]), state.point, state);
|
|
}
|
|
bend_edit(state);
|
|
WriteLog("SELFTEST bendset done");
|
|
}
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "bendprobe")
|
|
{
|
|
auto *sweep{m_bend.edited};
|
|
if (sweep == nullptr)
|
|
{
|
|
WriteLog("SELFTEST bendprobe: nothing bent");
|
|
return selftest_result::handled;
|
|
}
|
|
glm::dvec3 low;
|
|
glm::dvec3 high;
|
|
glm::dvec3 shift;
|
|
sweep->bounds(low, high, shift);
|
|
auto const &state{sweep->definition()};
|
|
auto const marker{bend_marker(*sweep)};
|
|
glm::dvec3 boxlow{std::numeric_limits<double>::max()};
|
|
glm::dvec3 boxhigh{-std::numeric_limits<double>::max()};
|
|
std::size_t vertices{0};
|
|
for (auto const &shape : sweep->create_shapes())
|
|
for (auto const &vertex : shape.data().vertices)
|
|
{
|
|
boxlow = glm::min(boxlow, vertex.position);
|
|
boxhigh = glm::max(boxhigh, vertex.position);
|
|
++vertices;
|
|
}
|
|
WriteLog(format("SELFTEST bendprobe %s: stations %.3f - %.3f, along the reference line %.3f m, model %.3f m, lateral %.3f height %.3f anchors %d/%d point %.3f %.3f %.3f, marker %.3f %.3f %.3f, box %.2f %.2f %.2f - %.2f %.2f %.2f, %zu vertices, removed %d",
|
|
sweep->name().c_str(), sweep->start(), sweep->end(), sweep->distance_at(sweep->end()) - sweep->distance_at(sweep->start()), high.x - low.x, state.lateral, state.height, state.side_anchor, state.height_anchor, state.point.x,
|
|
state.point.y, state.point.z, marker.x, marker.y, marker.z, boxlow.x, boxlow.y, boxlow.z, boxhigh.x, boxhigh.y, boxhigh.z, vertices, sweep->m_editorremoved ? 1 : 0));
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "lineside")
|
|
{
|
|
std::string tab;
|
|
words >> tab;
|
|
show_track_tab(tab == "parallel" ? track_tab::parallel : track_tab::lineside);
|
|
(tab == "vehicle" ? m_vehicle.tab().expand : tab == "hekto" ? m_hekto.tab().expand : tab == "fouling" ? m_fouling.tab().expand : m_parallel.expand) = true;
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "bendpanel")
|
|
{
|
|
ui()->expand_bend();
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "ttincludes")
|
|
{
|
|
std::string name;
|
|
words >> name;
|
|
auto const *track{simulation::Paths.find(name)};
|
|
WriteLog(format("SELFTEST ttincludes %s: track %s, includes %d", name.c_str(), track == nullptr ? "none" : track->m_editorremoved ? "removed" : "present",
|
|
track != nullptr ? static_cast<int>(turntable_includes(*track).size()) : -1));
|
|
return selftest_result::handled;
|
|
}
|
|
if (command == "checkspans")
|
|
{
|
|
WriteLog("SELFTEST spans: " + scene::Layers.check_sources());
|
|
return selftest_result::handled;
|
|
}
|
|
return selftest_result::unhandled;
|
|
}
|