mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 23:59:48 +01:00
The name of a node or "(no name)" was written out in twenty places and four local functions, a lower-case copy of a text in four files, the test for a number, the file name of a template made comparable and the heading of a direction in three and two, the green main button of a panel in five and the key=value parameters of a self-test command in five. Each of them is one helper now: name_of, tall_button_height and main_button with the panel helpers, numeric with format, normalized with the include helpers, heading_of with the plan geometry and selftest_values with the tools; lower gives way to ToLower.
297 lines
11 KiB
C++
297 lines
11 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")
|
|
{
|
|
auto values{selftest_values(words)};
|
|
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")
|
|
{
|
|
auto values{selftest_values(words)};
|
|
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.tab().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;
|
|
}
|