From 4d3f48c0dc017bfc4c80a9b051d4b71b74f73a69 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 28 Feb 2010 21:59:53 +0000 Subject: [PATCH] Load sloped track from XML --- include/IMap.hpp | 7 +++++ schemas/map.xsd | 9 ++++++ src/Editor.cpp | 27 +++------------- src/Map.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++ src/SlopeTrack.cpp | 16 +++++++++- 5 files changed, 113 insertions(+), 23 deletions(-) diff --git a/include/IMap.hpp b/include/IMap.hpp index 7246c70..3abe1ea 100644 --- a/include/IMap.hpp +++ b/include/IMap.hpp @@ -115,6 +115,13 @@ public: virtual Vector slopeAt(Point where, track::Direction axis, bool& level) const = 0; + // Similar to slopeAt, but calculates slope of tile before and + // after along `axis' + virtual Vector slopeBefore(Point where, + track::Direction axis, bool &valid) const = 0; + virtual Vector slopeAfter(Point where, + track::Direction axis, bool &valid) const = 0; + // Place a tree, building, etc. at a location virtual void addScenery(Point where, ISceneryPtr s) = 0; diff --git a/schemas/map.xsd b/schemas/map.xsd index f362141..1d1e209 100644 --- a/schemas/map.xsd +++ b/schemas/map.xsd @@ -42,6 +42,15 @@ + + + + + + + where, track::Direction axis) return true; } else { - Point before, after; - - if (axis == axis::X) { - before = where + makePoint(-1, 0); - after = where + makePoint(1, 0); - } - else { - before = where + makePoint(0, -1); - after = where + makePoint(0, 1); - } - - const bool offEdge = - (axis == axis::X - && (before.x < 0 || after.x >= map->width())) - || (axis == axis::Y - && (before.y < 0 || after.y >= map->depth())); - - if (offEdge) { + bool bValid, aValid; + Vector slopeBefore = map->slopeBefore(where, axis, bValid); + Vector slopeAfter = map->slopeAfter(where, axis, aValid); + + if (!bValid || !aValid) { warn() << "Cannot place track here"; return false; } else { - bool ignored; - Vector slopeBefore = map->slopeAt(before, axis, ignored); - Vector slopeAfter = map->slopeAt(after, axis, ignored); - debug() << "slope=" << slope << " before=" << slopeBefore << " after=" << slopeAfter; diff --git a/src/Map.cpp b/src/Map.cpp index 5d3873c..66c2f7b 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -112,6 +112,10 @@ public: float heightAt(float x, float y) const; Vector slopeAt(Point where, track::Direction axis, bool& level) const; + Vector slopeBefore(Point where, + track::Direction axis, bool &valid) const; + Vector slopeAfter(Point where, + track::Direction axis, bool &valid) const; void addScenery(Point where, ISceneryPtr s); // ISectorRenderable interface @@ -1009,6 +1013,54 @@ Vector Map::slopeAt(Point where, return v1; } +Vector Map::slopeBefore(Point where, + track::Direction axis, bool &valid) const +{ + Point before; + + if (axis == axis::X) + before = where + makePoint(-1, 0); + else + before = where + makePoint(0, -1); + + const bool offEdge = + (axis == axis::X && before.x < 0) + || (axis == axis::Y && before.y < 0); + + valid = !offEdge; + + if (offEdge) + return makeVector(0.0f, 0.0f, 0.0f); + else { + bool ignored; + return slopeAt(before, axis, ignored); + } +} + +Vector Map::slopeAfter(Point where, + track::Direction axis, bool &valid) const +{ + Point after; + + if (axis == axis::X) + after = where + makePoint(1, 0); + else + after = where + makePoint(0, 1); + + const bool offEdge = + (axis == axis::X && after.x >= width()) + || (axis == axis::Y && after.y >= depth()); + + valid = !offEdge; + + if (offEdge) + return makeVector(0.0f, 0.0f, 0.0f); + else { + bool ignored; + return slopeAt(after, axis, ignored); + } +} + void Map::changeAreaHeight(const Point& aStartPos, const Point& aFinishPos, float aHeightDelta) @@ -1328,6 +1380,8 @@ public: handleCrossoverTrack(attrs); else if (localName == "points") handlePoints(attrs); + else if (localName == "slopeTrack") + handleSlopeTrack(attrs); else if (localName == "stationPart") handleStationPart(attrs); else if (localName == "station") @@ -1425,6 +1479,29 @@ private: myMap->setTrackAt(tile, makeStraightTrack(axis)); } + void handleSlopeTrack(const AttributeSet& attrs) + { + string align; + bool flip; + attrs.get("align", align); + attrs.get("flip", flip); + + track::Direction axis = align == "x" ? axis::X : axis::Y; + + bool level; + Vector slope = myMap->slopeAt(tile, axis, level); + + bool aValid, bValid; + Vector slopeBefore = myMap->slopeBefore(tile, axis, bValid); + Vector slopeAfter = myMap->slopeAfter(tile, axis, aValid); + + if (!aValid || !bValid || !level) + throw runtime_error("SlopeTrack in invalid location"); + + myMap->setTrackAt(tile, + makeSlopeTrack(axis, slope, slopeBefore, slopeAfter)); + } + void handlePoints(const AttributeSet& attrs) { string align; diff --git a/src/SlopeTrack.cpp b/src/SlopeTrack.cpp index b08be0c..bc746f4 100644 --- a/src/SlopeTrack.cpp +++ b/src/SlopeTrack.cpp @@ -64,6 +64,7 @@ private: IMeshPtr railMesh; track::Direction axis; float length; + bool flip; }; SlopeTrack::SlopeTrack(track::Direction axis, Vector slope, @@ -72,6 +73,14 @@ SlopeTrack::SlopeTrack(track::Direction axis, Vector slope, { const float OFF = 0.1f; + if ((flip = (slope.y < 0.0f))) { + slope.y = abs(slope.y); + slopeBefore.y = abs(slopeBefore.y); + slopeAfter.y = abs(slopeAfter.y); + + swap(slopeBefore, slopeAfter); + } + const float hFactor0 = sqrt(OFF / (1 + slopeBefore.y * slopeBefore.y)); const float hFactor1 = sqrt(OFF / (1 + slopeAfter.y * slopeAfter.y)); @@ -104,6 +113,9 @@ void SlopeTrack::render() const if (axis == axis::Y) glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); + if (flip) + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); + renderRailMesh(railMesh); glPopMatrix(); @@ -206,7 +218,9 @@ ITrackSegmentPtr SlopeTrack::mergeExit(Point where, track::Direction dir) xml::element SlopeTrack::toXml() const { - return xml::element("slopeTrack"); + return xml::element("slopeTrack") + .addAttribute("align", axis == axis::X ? "x" : "y") + .addAttribute("flip", flip); } ITrackSegmentPtr makeSlopeTrack(track::Direction axis, Vector slope, -- 2.39.2