mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-24 00:06:13 +02:00
fix(editor): signals move along their track again, and the editor finds the descriptions of the templates beside the game data
- a press on the mast of a selected signal grabbed the gizmo, whose up axis runs along the mast, and lifted the signal instead of moving it along the track; the gizmo gives way over a signal and while one is dragged - dragged beside its track, off every track, the signal follows the nearest place of the track it stands by instead of staying put - a drop away from any track, and a signal in a file the editor doesn't change, say so instead of doing nothing - a template without a //$e description of its own takes it from editor/templates/<its path in the scenery folder>; the header scripts write there with --sidecar, leaving the templates alone, so a check of the game files by the store doesn't take the descriptions away (the descriptions written into the templates on 8.10 and 11.10 were gone, and with them every signal and drive the editor knew)
This commit is contained in:
@@ -5301,7 +5301,12 @@ void editor_mode::render_include_gizmo(glm::mat4 const &View, glm::mat4 const &P
|
||||
glm::vec3 const snapvalue(translating ? m_gizmo_snap : 5.0f);
|
||||
float const *snap = Global.ctrlState && snapvalue.x > 0.0f ? glm::value_ptr(snapvalue) : nullptr;
|
||||
|
||||
// in the signal tool a press on the mast drags the signal along its track: the gizmo, whose up axis runs along the
|
||||
// mast, gives way over a signal and while one is dragged
|
||||
auto const yield{ui()->mode() == nodebank_panel::TRACK && m_track_tab == track_tab::signals && false == ImGuizmo::IsUsing() && (m_signal.moving || m_signal.placing || signal_hit() >= 0)};
|
||||
ImGuizmo::Enable(false == yield);
|
||||
ImGuizmo::Manipulate(glm::value_ptr(View), glm::value_ptr(Projection), static_cast<ImGuizmo::OPERATION>(operation), mode, glm::value_ptr(matrix), nullptr, snap);
|
||||
ImGuizmo::Enable(true);
|
||||
|
||||
if (false == ImGuizmo::IsUsing())
|
||||
return;
|
||||
|
||||
@@ -473,7 +473,23 @@ void editor_mode::signal_move_update()
|
||||
if (false == dragged)
|
||||
return;
|
||||
auto const found{std::find_if(tool.standing.begin(), tool.standing.end(), [&](signal_standing const &Standing) { return Standing.include.instance == tool.selected; })};
|
||||
if (found == tool.standing.end() || m_hover.track == nullptr)
|
||||
if (found == tool.standing.end())
|
||||
{
|
||||
tool.moved_valid = false;
|
||||
return;
|
||||
}
|
||||
// the track under the cursor; off every track, as it is when the signal is dragged beside its track, the place of the
|
||||
// track the signal stands by nearest the cursor
|
||||
auto *track{m_hover.track};
|
||||
auto path{m_hover.path};
|
||||
auto point{m_hover.point};
|
||||
if (track == nullptr && found->track != nullptr && false == found->track->m_editorremoved && false == found->track->m_paths.empty())
|
||||
{
|
||||
track = found->track;
|
||||
path = std::clamp(found->spot.path, 0, static_cast<int>(track->m_paths.size()) - 1);
|
||||
point = bezier{track->m_paths[path]}.point(nearest_on(*track, path, cursor_level(found->spot.axis.y)));
|
||||
}
|
||||
if (track == nullptr)
|
||||
{
|
||||
tool.moved_valid = false;
|
||||
return;
|
||||
@@ -481,13 +497,14 @@ void editor_mode::signal_move_update()
|
||||
auto const *item{signal_template_of(found->include.file)};
|
||||
if (item == nullptr)
|
||||
return;
|
||||
path = std::clamp(path, 0, static_cast<int>(track->m_paths.size()) - 1);
|
||||
auto const yaw{glm::radians(found->include.yaw + 180.0)};
|
||||
glm::dvec2 const travel{std::sin(yaw), std::cos(yaw)};
|
||||
auto const parameter{nearest_on(*m_hover.track, std::clamp(m_hover.path, 0, static_cast<int>(m_hover.track->m_paths.size()) - 1), m_hover.point)};
|
||||
auto const forward{forward_at(*m_hover.track, std::clamp(m_hover.path, 0, static_cast<int>(m_hover.track->m_paths.size()) - 1), parameter)};
|
||||
auto const parameter{nearest_on(*track, path, point)};
|
||||
auto const forward{forward_at(*track, path, parameter)};
|
||||
auto const facing{glm::dot(forward, travel) >= 0.0 ? 1 : -1};
|
||||
auto const sideoftravel{glm::dot(plan_of(found->include.location) - plan_of(m_hover.point), right_of(travel)) >= 0.0 ? 1 : -1};
|
||||
tool.moved_valid = signal_spot_at(*m_hover.track, m_hover.path, m_hover.point, m_hover.point, facing, sideoftravel * facing, *item, tool.moved);
|
||||
auto const sideoftravel{glm::dot(plan_of(found->include.location) - plan_of(point), right_of(travel)) >= 0.0 ? 1 : -1};
|
||||
tool.moved_valid = signal_spot_at(*track, path, point, point, facing, sideoftravel * facing, *item, tool.moved);
|
||||
}
|
||||
|
||||
void editor_mode::signal_release()
|
||||
@@ -504,12 +521,22 @@ void editor_mode::signal_release()
|
||||
return;
|
||||
tool.moving = false;
|
||||
auto const &mouse{ImGui::GetIO().MousePos};
|
||||
if (false == tool.moved_valid || glm::length(glm::vec2{mouse.x, mouse.y} - tool.pressed) <= kDragStart)
|
||||
if (glm::length(glm::vec2{mouse.x, mouse.y} - tool.pressed) <= kDragStart)
|
||||
return;
|
||||
if (false == tool.moved_valid)
|
||||
{
|
||||
tool.status = STR_C("Drop the signal by a track");
|
||||
return;
|
||||
}
|
||||
tool.moved_valid = false;
|
||||
auto const found{std::find_if(tool.standing.begin(), tool.standing.end(), [&](signal_standing const &Standing) { return Standing.include.instance == tool.selected; })};
|
||||
if (found == tool.standing.end() || false == scene::Layers.tracked(found->include.instance) || false == scene::Layers.removable(found->include.instance))
|
||||
if (found == tool.standing.end())
|
||||
return;
|
||||
if (false == scene::Layers.tracked(found->include.instance) || false == scene::Layers.removable(found->include.instance))
|
||||
{
|
||||
tool.status = STR_C("This signal is in a file the editor doesn't change, it can't be moved");
|
||||
return;
|
||||
}
|
||||
auto const &spot{tool.moved};
|
||||
auto const &included{scene::Layers.instance(found->include.instance)};
|
||||
auto values{found->include.values};
|
||||
|
||||
@@ -129,6 +129,14 @@ bool read_template(std::string const &File, template_text &Text, std::string &Er
|
||||
}
|
||||
linebegin = next;
|
||||
}
|
||||
// a template without a description of its own may have one beside the game data, in editor/templates, where the
|
||||
// scripts of tools/editor write it with --sidecar: a check of the game files doesn't take it away
|
||||
if (Text.yaml.empty())
|
||||
{
|
||||
std::ifstream beside{"editor/templates/" + File, std::ios_base::binary};
|
||||
if (beside.is_open())
|
||||
Text.yaml.assign(std::istreambuf_iterator<char>(beside), std::istreambuf_iterator<char>());
|
||||
}
|
||||
if (false == is_utf8(Text.yaml, extended))
|
||||
{
|
||||
Text.yaml = win1250_to_utf8(Text.yaml);
|
||||
@@ -752,7 +760,7 @@ include_entry examine(std::string const &File)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
entry.described = false == text.lines.empty();
|
||||
entry.described = false == text.yaml.empty();
|
||||
if (false == entry.described)
|
||||
{
|
||||
entry.issue = "the template has no description";
|
||||
|
||||
@@ -7052,3 +7052,9 @@ msgstr "Klik: przesuń ten W17 na miejsce"
|
||||
|
||||
msgid "Click: put the W17 here"
|
||||
msgstr "Klik: postaw tu W17"
|
||||
|
||||
msgid "Drop the signal by a track"
|
||||
msgstr "Upuść sygnalizator przy torze"
|
||||
|
||||
msgid "This signal is in a file the editor doesn't change, it can't be moved"
|
||||
msgstr "Ten sygnalizator jest w pliku, którego edytor nie zmienia, nie da się go przesunąć"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Writes //$e descriptions into the switch drive templates (scenery/tory/napedy), so the editor places them with a switch.
|
||||
|
||||
usage: drive_headers.py <data root> [--write] [--zip <file>]
|
||||
usage: drive_headers.py <data root> [--write] [--zip <file>] [--sidecar]
|
||||
without --write it only reports what it would write; --zip packs the written templates with their scenery/ paths
|
||||
"""
|
||||
|
||||
@@ -9,7 +9,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from editor_headers import body_lines, decode, load, options, pack, write
|
||||
from editor_headers import body_lines, decode, load, options, pack, sidecar, write
|
||||
|
||||
FOLDER = 'scenery/tory/napedy'
|
||||
PATTERN = re.compile(r'^(ele1?|mech[12]?)-rz([lp])-([lp])((?:_[a-z]+)*)\.inc$')
|
||||
@@ -78,6 +78,8 @@ def main():
|
||||
print('%d described, %d skipped' % (len(done), len(skipped)))
|
||||
if writing:
|
||||
write(data, FOLDER, 'drives', done)
|
||||
if '--sidecar' in sys.argv:
|
||||
sidecar(data, FOLDER, done)
|
||||
if target:
|
||||
pack(target, FOLDER, done)
|
||||
return 0
|
||||
|
||||
@@ -50,6 +50,23 @@ def options(argv, usage):
|
||||
return argv[1], '--write' in argv, pack
|
||||
|
||||
|
||||
def sidecar(data, folder, entries):
|
||||
"""the descriptions next to the game data instead of in the templates: <data>/editor/templates/<the path of the
|
||||
template in the scenery folder>, the lines without the marks, which the editor reads for a template without its own;
|
||||
the templates stay as they are, so a check of the game files by the store doesn't take the descriptions away"""
|
||||
root = os.path.join(data, 'editor', 'templates', os.path.relpath(folder, 'scenery'))
|
||||
written = 0
|
||||
for file, info in entries:
|
||||
if info.get('header') is None:
|
||||
continue
|
||||
target = os.path.normpath(os.path.join(root, file))
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True) # NOSONAR
|
||||
with open(target, 'w', encoding='utf-8', newline='\n') as out: # NOSONAR
|
||||
out.write('\n'.join(info['header']) + '\n')
|
||||
written += 1
|
||||
print('%d descriptions written beside the data in %s' % (written, root))
|
||||
|
||||
|
||||
def write(data, folder, name, entries):
|
||||
backup = os.path.join(data, 'editor_backup')
|
||||
os.makedirs(backup, exist_ok=True) # NOSONAR
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Writes //$e descriptions into the signal templates of the scenery directory, so the editor can place them.
|
||||
|
||||
usage: signal_headers.py <data root> [--write]
|
||||
without --write it only reports what it would write
|
||||
usage: signal_headers.py <data root> [--write] [--sidecar]
|
||||
without --write it only reports what it would write; --sidecar writes them beside the data, in editor/templates, the
|
||||
templates left as they are
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from editor_headers import body_lines, decode, load, write
|
||||
from editor_headers import body_lines, decode, load, sidecar, write
|
||||
|
||||
FAMILIES = [
|
||||
(re.compile(r'^ss[dow]?\d'), 'main'),
|
||||
@@ -200,6 +201,8 @@ def main():
|
||||
|
||||
if writing:
|
||||
write(sys.argv[1], 'scenery', 'signals', done)
|
||||
if '--sidecar' in sys.argv:
|
||||
sidecar(sys.argv[1], 'scenery', done)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Writes //$e descriptions into the turntable templates of the scenery, so the editor places them as turntables.
|
||||
|
||||
usage: turntable_headers.py <data root> [--write] [--zip <file>]
|
||||
usage: turntable_headers.py <data root> [--write] [--zip <file>] [--sidecar]
|
||||
without --write it only reports what it would write; --zip packs every described turntable template with its scenery/ path
|
||||
"""
|
||||
|
||||
@@ -9,7 +9,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from editor_headers import LINEMARK, body_lines, decode, load, options, pack, write
|
||||
from editor_headers import LINEMARK, body_lines, decode, load, options, pack, sidecar, write
|
||||
|
||||
FOLDER = 'scenery'
|
||||
ROTATION = re.compile(r'^event\s+\S*tor(\d+)rot\s+animation\s+\S+\s+\S+\s+rotate\s+\S+\s+\S+\s+\S+\s+(\S+)', re.I | re.M)
|
||||
@@ -95,6 +95,8 @@ def main():
|
||||
write(data, FOLDER, 'turntables', fresh)
|
||||
if target:
|
||||
pack(target, FOLDER, done)
|
||||
if '--sidecar' in sys.argv:
|
||||
sidecar(data, FOLDER, done)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user