summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-05-11 12:22:19 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2025-05-11 12:22:19 +0100
commitacb76ffa0f45c5369e103f8868356d333ab2d954 (patch)
tree8ef1116b45b2a3e7e59b4b490ca5c90d48d31081
parentLink helper to get an End pointer based on position (diff)
downloadilt-acb76ffa0f45c5369e103f8868356d333ab2d954.tar.bz2
ilt-acb76ffa0f45c5369e103f8868356d333ab2d954.tar.xz
ilt-acb76ffa0f45c5369e103f8868356d333ab2d954.zip
Build networks with new interface
-rw-r--r--application/main.cpp39
-rw-r--r--ui/builders/freeExtend.cpp77
-rw-r--r--ui/builders/freeExtend.h21
-rw-r--r--ui/builders/join.cpp55
-rw-r--r--ui/builders/join.h18
-rw-r--r--ui/builders/straight.cpp58
-rw-r--r--ui/builders/straight.h20
-rw-r--r--ui/editNetwork.cpp91
-rw-r--r--ui/editNetwork.h34
-rw-r--r--ui/gameMainWindow.cpp2
10 files changed, 72 insertions, 343 deletions
diff --git a/application/main.cpp b/application/main.cpp
index a0c87c0..d96b188 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -1,6 +1,5 @@
#include "ui/mainApplication.h"
#include "ui/mainWindow.h"
-#include <array>
#include <assetFactory/assetFactory.h>
#include <collection.h>
#include <game/activities/go.h>
@@ -30,9 +29,6 @@
#include <special_members.h>
#include <stream_support.h>
#include <ui/applicationBase.h>
-#include <ui/builders/freeExtend.h>
-#include <ui/builders/join.h>
-#include <ui/builders/straight.h>
#include <ui/gameMainWindow.h>
#include <ui/window.h>
@@ -50,7 +46,7 @@ public:
assets = AssetFactory::loadAll("res");
{
- auto rl = world.create<RailLinks>();
+ auto railLinks = world.create<RailLinks>();
const auto nodes = materializeRange(std::vector<GlobalPosition2D> {
{315103000, 491067000},
{315977000, 490777000},
@@ -60,31 +56,26 @@ public:
{316129566, 490893054},
{315825622, 490833929},
{315106182, 491073714},
+ {314955393, 490999023},
}
| std::views::transform([this](const auto n) {
return terrain->positionAt(n);
}));
- auto l3 = BuilderStraight {}.create(rl.get(), terrain.get(), *nodes.begin(), *++nodes.begin()).front();
- for (const auto & [from, to] : nodes | std::views::drop(1) | std::views::pairwise) {
- const auto links = BuilderFreeExtend {}.createExtend(rl.get(), terrain.get(), from, to);
- }
- for (const auto & [from, to] : std::initializer_list<std::pair<GlobalPosition2D, GlobalPosition2D>> {
- {{315103000, 491067000}, {315003434, 491076253}},
- {{315103000, 491067000}, {315016495, 491019224}},
- {{315016495, 491019224}, {314955393, 490999023}},
- }) {
- const auto links = BuilderFreeExtend {}.createExtend(
- rl.get(), terrain.get(), terrain->positionAt(from), terrain->positionAt(to));
- }
- for (const auto & [from, to] : std::initializer_list<std::pair<GlobalPosition2D, GlobalPosition2D>> {
- {{315106182, 491073714}, {314955393, 490999023}},
- }) {
- auto p1 = rl->intersectRayNodes({from || 0, up})->pos;
- auto p2 = rl->intersectRayNodes({to || 0, up})->pos;
- const auto links = BuilderFreeExtend {}.createJoin(rl.get(), terrain.get(), p1, p2);
+
+ Link::Ptr l3;
+ for (std::optional<Angle> previousDir; const auto [fromPos, toPos] : std::views::pairwise(nodes)) {
+ const auto links = railLinks->create({
+ .fromEnd = {.position = fromPos, .direction = previousDir},
+ .toEnd = {.position = toPos, .direction = std::nullopt},
+ });
+ for (const auto & link : links) {
+ railLinks->add(terrain.get(), link);
+ }
+ l3 = links.back();
+ previousDir = links.back()->endAt(toPos)->dir;
}
- const std::shared_ptr<Train> train = world.create<Train>(l3, 800000);
+ const std::shared_ptr<Train> train = world.create<Train>(l3, 0);
auto b47 = assets.at("brush-47").dynamicCast<RailVehicleClass>();
for (int N = 0; N < 6; N++) {
train->create<RailVehicle>(b47);
diff --git a/ui/builders/freeExtend.cpp b/ui/builders/freeExtend.cpp
deleted file mode 100644
index aff7cd7..0000000
--- a/ui/builders/freeExtend.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "freeExtend.h"
-#include <game/geoData.h>
-
-std::string
-BuilderFreeExtend::hint() const
-{
- if (p1) {
- return "Pick next point";
- }
- return "Pick start node";
-}
-
-void
-BuilderFreeExtend::move(
- Network * network, const GeoData * geoData, const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> & ray)
-{
- if (p1) {
- if (const auto p = network->intersectRayNodes(ray)) {
- candidateLinks = network->candidateJoins(*p1, p->pos);
- }
- else if (const auto p = geoData->intersectRay(ray)) {
- candidateLinks = network->candidateExtend(*p1, p->first);
- }
- else {
- candidateLinks.clear();
- }
- }
- else {
- candidateLinks.clear();
- }
-}
-
-void
-BuilderFreeExtend::click(
- Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e, const Ray<GlobalPosition3D> & ray)
-{
- switch (e.button) {
- case SDL_BUTTON_LEFT:
- if (p1) {
- if (const auto p = network->intersectRayNodes(ray)) {
- createJoin(network, geoData, *p1, p->pos);
- p1 = p->pos;
- }
- else if (const auto p = geoData->intersectRay(ray)) {
- createExtend(network, geoData, *p1, p->first);
- p1 = p->first;
- }
- }
- else {
- if (const auto p = network->intersectRayNodes(ray)) {
- p1 = p->pos;
- }
- }
- return;
- case SDL_BUTTON_MIDDLE:
- p1.reset();
- return;
- }
-}
-
-Link::CCollection
-BuilderFreeExtend::createJoin(
- Network * network, const GeoData * geoData, GlobalPosition3D p1, GlobalPosition3D p2) const
-{
- const auto links = network->addJoins(geoData, p1, p2);
- setHeightsFor(network, links);
- return links;
-}
-
-Link::CCollection
-BuilderFreeExtend::createExtend(
- Network * network, const GeoData * geoData, GlobalPosition3D p1, GlobalPosition3D p2) const
-{
- const auto links = network->addExtend(geoData, p1, p2);
- setHeightsFor(network, links);
- return links;
-}
diff --git a/ui/builders/freeExtend.h b/ui/builders/freeExtend.h
deleted file mode 100644
index 6f28493..0000000
--- a/ui/builders/freeExtend.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-#include "../editNetwork.h"
-
-class Network;
-class GeoData;
-
-class BuilderFreeExtend : public EditNetwork::Builder {
-private:
- std::string hint() const override;
- void click(Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
- void move(Network * network, const GeoData * geoData, const SDL_MouseMotionEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
-
-public:
- Link::CCollection createJoin(Network * network, const GeoData *, GlobalPosition3D, GlobalPosition3D) const;
- Link::CCollection createExtend(Network * network, const GeoData *, GlobalPosition3D, GlobalPosition3D) const;
-
-private:
- std::optional<GlobalPosition3D> p1;
-};
diff --git a/ui/builders/join.cpp b/ui/builders/join.cpp
deleted file mode 100644
index f6cbce5..0000000
--- a/ui/builders/join.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "join.h"
-#include <game/geoData.h>
-
-std::string
-BuilderJoin::hint() const
-{
- if (p1) {
- return "Pick second node";
- }
- return "Pick first node";
-}
-
-void
-BuilderJoin::move(Network * network, const GeoData *, const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> & ray)
-{
- if (p1) {
- if (const auto p = network->intersectRayNodes(ray)) {
- candidateLinks = network->candidateJoins(p1->pos, p->pos);
- }
- else {
- candidateLinks.clear();
- }
- }
-}
-
-void
-BuilderJoin::click(
- Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e, const Ray<GlobalPosition3D> & ray)
-{
- switch (e.button) {
- case SDL_BUTTON_LEFT:
- if (const auto p = network->intersectRayNodes(ray)) {
- if (p1) {
- create(network, geoData, p1, p);
- p1.reset();
- candidateLinks.clear();
- }
- else {
- p1 = p;
- }
- }
- return;
- case SDL_BUTTON_MIDDLE:
- p1.reset();
- return;
- }
-}
-
-Link::CCollection
-BuilderJoin::create(Network * network, const GeoData * geoData, const Node::Ptr & p1, const Node::Ptr & p2) const
-{
- const auto links = network->addJoins(geoData, p1->pos, p2->pos);
- setHeightsFor(network, links);
- return links;
-}
diff --git a/ui/builders/join.h b/ui/builders/join.h
deleted file mode 100644
index 326d23d..0000000
--- a/ui/builders/join.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-#include "../editNetwork.h"
-
-class Network;
-class GeoData;
-
-class BuilderJoin : public EditNetwork::Builder {
-private:
- std::string hint() const override;
- void click(Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
- void move(Network * network, const GeoData * geoData, const SDL_MouseMotionEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
-
- Link::CCollection create(Network * network, const GeoData *, const Node::Ptr & p1, const Node::Ptr & p2) const;
-
- Node::Ptr p1;
-};
diff --git a/ui/builders/straight.cpp b/ui/builders/straight.cpp
deleted file mode 100644
index e7d83b5..0000000
--- a/ui/builders/straight.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "straight.h"
-#include "stream_support.h"
-#include <game/geoData.h>
-
-std::string
-BuilderStraight::hint() const
-{
- if (p1) {
- return "Pick straight end point";
- }
- return "Pick straight start point";
-}
-
-void
-BuilderStraight::move(
- Network * network, const GeoData * geoData, const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> & ray)
-{
- if (p1) {
- if (const auto p = geoData->intersectRay(ray)) {
- candidateLinks = network->candidateStraight(*p1, p->first);
- }
- else {
- candidateLinks.clear();
- }
- }
-}
-
-void
-BuilderStraight::click(
- Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e, const Ray<GlobalPosition3D> & ray)
-{
- switch (e.button) {
- case SDL_BUTTON_LEFT:
- if (const auto p = geoData->intersectRay(ray)) {
- if (p1) {
- create(network, geoData, *p1, p->first);
- candidateLinks.clear();
- p1.reset();
- }
- else {
- p1 = p->first;
- }
- }
- return;
- case SDL_BUTTON_MIDDLE:
- p1.reset();
- candidateLinks.clear();
- return;
- }
-}
-
-Link::CCollection
-BuilderStraight::create(Network * network, const GeoData * geoData, GlobalPosition3D p1, GlobalPosition3D p2) const
-{
- const auto links = network->addStraight(geoData, p1, p2);
- setHeightsFor(network, links);
- return links;
-}
diff --git a/ui/builders/straight.h b/ui/builders/straight.h
deleted file mode 100644
index 0a6f290..0000000
--- a/ui/builders/straight.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-#include "../editNetwork.h"
-
-class Network;
-class GeoData;
-
-class BuilderStraight : public EditNetwork::Builder {
-private:
- std::string hint() const override;
- void click(Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
- void move(Network * network, const GeoData * geoData, const SDL_MouseMotionEvent & e,
- const Ray<GlobalPosition3D> & ray) override;
-
-public:
- Link::CCollection create(Network * network, const GeoData *, GlobalPosition3D p1, GlobalPosition3D p2) const;
-
-private:
- std::optional<GlobalPosition3D> p1;
-};
diff --git a/ui/editNetwork.cpp b/ui/editNetwork.cpp
index c900191..cab13f2 100644
--- a/ui/editNetwork.cpp
+++ b/ui/editNetwork.cpp
@@ -1,32 +1,53 @@
#include "editNetwork.h"
-#include "builders/freeExtend.h"
-#include "builders/join.h"
-#include "builders/straight.h"
#include "imgui_wrap.h"
#include <game/gamestate.h>
#include <game/terrain.h>
#include <gfx/gl/sceneShader.h>
#include <gfx/models/texture.h>
-constexpr const glm::u8vec4 TRANSPARENT_BLUE {30, 50, 255, 200};
-
-EditNetwork::EditNetwork(Network * n) : network {n}, blue {1, 1, &TRANSPARENT_BLUE} { }
+EditNetwork::EditNetwork(Network * n) : network {n} { }
bool
-EditNetwork::click(const SDL_MouseButtonEvent & e, const Ray<GlobalPosition3D> & ray)
+EditNetwork::click(const SDL_MouseButtonEvent & event, const Ray<GlobalPosition3D> & ray)
{
- if (builder && (e.button == SDL_BUTTON_LEFT || e.button == SDL_BUTTON_MIDDLE)) {
- builder->click(network, gameState->terrain.get(), e, ray);
- return true;
+ switch (event.button) {
+ case SDL_BUTTON_MIDDLE:
+ currentStart.reset();
+ candidates.clear();
+ return true;
+ case SDL_BUTTON_LEFT:
+ if (!currentStart) {
+ currentStart = resolveRay(ray);
+ }
+ else {
+ if (const auto def = resolveRay(ray)) {
+ candidates = network->create(CreationDefinition {.fromEnd = *currentStart, .toEnd = *def});
+ for (const auto & link : candidates) {
+ network->add(gameState->terrain.get(), link);
+ }
+ if (continuousMode) {
+ currentStart = def;
+ currentStart->direction = candidates.back()->endAt(def->position)->dir;
+ }
+ else {
+ currentStart.reset();
+ }
+ candidates.clear();
+ }
+ }
+ return true;
+ default:
+ return false;
}
- return false;
}
bool
-EditNetwork::move(const SDL_MouseMotionEvent & e, const Ray<GlobalPosition3D> & ray)
+EditNetwork::move(const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> & ray)
{
- if (builder) {
- builder->move(network, gameState->terrain.get(), e, ray);
+ if (currentStart) {
+ if (const auto def = resolveRay(ray)) {
+ candidates = network->create(CreationDefinition {.fromEnd = *currentStart, .toEnd = *def});
+ }
}
return false;
}
@@ -38,30 +59,22 @@ EditNetwork::handleInput(const SDL_Event &)
}
void
-EditNetwork::render(const SceneShader & shader, const Frustum & frustum) const
-{
- if (builder) {
- blue.bind();
- shader.absolute.use();
- builder->render(shader, frustum);
- }
-}
-
-void
-EditNetwork::Builder::render(const SceneShader & shader, const Frustum & frustum) const
+EditNetwork::render(const SceneShader &, const Frustum &) const
{
- candidateLinks.apply<const Renderable>(&Renderable::render, shader, frustum);
}
-void
-EditNetwork::Builder::setHeightsFor(Network * network, const Link::CCollection & links, GeoData::SetHeightsOpts opts)
+std::optional<CreationDefinitionEnd>
+EditNetwork::resolveRay(const Ray<GlobalPosition3D> & ray) const
{
- opts.surface = network->getBaseSurface();
- const auto width = network->getBaseWidth();
-
- for (const auto & link : links) {
- gameState->terrain->setHeights(link->getBase(width), opts);
+ if (const auto position = gameState->terrain->intersectRay(ray)) {
+ const auto node = network->intersectRayNodes(ray);
+ if (node) {
+ const auto direction = network->findNodeDirection(node);
+ return CreationDefinitionEnd {.position = node->pos, .direction = direction};
+ }
+ return CreationDefinitionEnd {.position = position->first, .direction = std::nullopt};
}
+ return {};
}
void
@@ -69,16 +82,6 @@ EditNetwork::render(bool & open)
{
ImGui::SetNextWindowSize({-1, -1});
ImGui::Begin("Edit Network", &open);
-
- auto builderChoice = [this]<typename Impl>(const char * name) {
- if (ImGui::RadioButton(name, dynamic_cast<Impl *>(builder.get()))) {
- builder = std::make_unique<Impl>();
- }
- };
- builderChoice.operator()<BuilderStraight>("Straight");
- builderChoice.operator()<BuilderJoin>("Join");
- builderChoice.operator()<BuilderFreeExtend>("Free Extend");
- ImGui::TextUnformatted(builder ? builder->hint().c_str() : "Select a build mode");
-
+ ImGui::Checkbox("Continuous mode", &continuousMode);
ImGui::End();
}
diff --git a/ui/editNetwork.h b/ui/editNetwork.h
index 4155534..e155105 100644
--- a/ui/editNetwork.h
+++ b/ui/editNetwork.h
@@ -1,6 +1,5 @@
#pragma once
-#include "game/geoData.h"
#include "gameMainSelector.h"
#include "worldOverlay.h"
#include <game/gamestate.h>
@@ -13,40 +12,25 @@ class EditNetwork : public GameMainSelector::Component, public WorldOverlay {
public:
explicit EditNetwork(Network *);
- bool click(const SDL_MouseButtonEvent & e, const Ray<GlobalPosition3D> &) override;
- bool move(const SDL_MouseMotionEvent & e, const Ray<GlobalPosition3D> &) override;
- bool handleInput(const SDL_Event & e) override;
+ bool click(const SDL_MouseButtonEvent &, const Ray<GlobalPosition3D> &) override;
+ bool move(const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> &) override;
+ bool handleInput(const SDL_Event &) override;
void render(const SceneShader &, const Frustum &) const override;
void render(bool & open) override;
- using NetworkClickPos = std::variant<GlobalPosition3D, Node::Ptr>;
-
- class Builder {
- public:
- virtual ~Builder() = default;
- virtual void render(const SceneShader & shader, const Frustum &) const;
- virtual std::string hint() const = 0;
- virtual void click(Network *, const GeoData *, const SDL_MouseButtonEvent &, const Ray<GlobalPosition3D> &) = 0;
- virtual void move(Network *, const GeoData *, const SDL_MouseMotionEvent &, const Ray<GlobalPosition3D> &) = 0;
-
- static void setHeightsFor(Network *, const Link::CCollection &, GeoData::SetHeightsOpts = {});
-
- using Ptr = std::unique_ptr<Builder>;
-
- protected:
- SharedCollection<const Link> candidateLinks;
- };
-
private:
+ [[nodiscard]] std::optional<CreationDefinitionEnd> resolveRay(const Ray<GlobalPosition3D> &) const;
+
Network * network;
- Builder::Ptr builder;
- Texture blue;
+ bool continuousMode {false};
+ std::optional<CreationDefinitionEnd> currentStart;
+ Link::Collection candidates;
};
template<typename T> class EditNetworkOf : public EditNetwork {
public:
template<typename... P>
- explicit EditNetworkOf(P &&... p) : EditNetwork(gameState->world.findOrCreate<T>(), std::forward<P>(p)...)
+ explicit EditNetworkOf(P &&... params) : EditNetwork(gameState->world.findOrCreate<T>(), std::forward<P>(params)...)
{
}
};
diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp
index dbbf8a7..2b15284 100644
--- a/ui/gameMainWindow.cpp
+++ b/ui/gameMainWindow.cpp
@@ -52,7 +52,7 @@ private:
GameMainWindow::GameMainWindow(ScreenAbsCoord size) : SceneRenderer {size, 0}
{
- uiComponents.create<ManualCameraController>(glm::vec2 {310'727'624, 494'018'810});
+ uiComponents.create<ManualCameraController>(glm::vec2 {315103000, 491067000});
auto gms = uiComponents.create<GameMainSelector>(&camera);
uiComponents.create<GameMainToolbar>(gms);
}