diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-05-11 12:22:19 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-05-11 12:22:19 +0100 |
commit | acb76ffa0f45c5369e103f8868356d333ab2d954 (patch) | |
tree | 8ef1116b45b2a3e7e59b4b490ca5c90d48d31081 | |
parent | Link helper to get an End pointer based on position (diff) | |
download | ilt-acb76ffa0f45c5369e103f8868356d333ab2d954.tar.bz2 ilt-acb76ffa0f45c5369e103f8868356d333ab2d954.tar.xz ilt-acb76ffa0f45c5369e103f8868356d333ab2d954.zip |
Build networks with new interface
-rw-r--r-- | application/main.cpp | 39 | ||||
-rw-r--r-- | ui/builders/freeExtend.cpp | 77 | ||||
-rw-r--r-- | ui/builders/freeExtend.h | 21 | ||||
-rw-r--r-- | ui/builders/join.cpp | 55 | ||||
-rw-r--r-- | ui/builders/join.h | 18 | ||||
-rw-r--r-- | ui/builders/straight.cpp | 58 | ||||
-rw-r--r-- | ui/builders/straight.h | 20 | ||||
-rw-r--r-- | ui/editNetwork.cpp | 91 | ||||
-rw-r--r-- | ui/editNetwork.h | 34 | ||||
-rw-r--r-- | ui/gameMainWindow.cpp | 2 |
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); } |