|
| 1 | +package com.sc4nam.module |
| 2 | + |
| 3 | +import io.github.memo33.metarules.meta._, syntax._, Network._, RotFlip._, Flags._ |
| 4 | +import Implicits.segmentToTile |
| 5 | +import com.sc4nam.module.{NetworkProperties => NP} |
| 6 | + |
| 7 | +object ViaductResolver { |
| 8 | + |
| 9 | + val viaductRangeId = Map( |
| 10 | + L1Road -> 0x5c000000, |
| 11 | + L1Onewayroad -> 0x5c010000, |
| 12 | + L1Avenue -> 0x5c020000, |
| 13 | + L2Road -> 0x5c030000, |
| 14 | + L2Onewayroad -> 0x5c040000, |
| 15 | + L2Avenue -> 0x5c050000, |
| 16 | + ) |
| 17 | + |
| 18 | + val viaductPieceId = |
| 19 | + Map.from[Network, Int](Iterable( |
| 20 | + 0x1000 -> Street, |
| 21 | + 0x1100 -> Road, 0x1110 -> L1Road, 0x1120 -> L2Road, |
| 22 | + 0x1200 -> Onewayroad, 0x1210 -> L1Onewayroad, 0x1220 -> L2Onewayroad, |
| 23 | + 0x1300 -> Avenue, 0x1310 -> L1Avenue, 0x1320 -> L2Avenue, |
| 24 | + 0x1400 -> Groundhighway, 0x1420 -> Highway, |
| 25 | + 0x1500 -> Rail, 0x1505 -> Str, |
| 26 | + 0x1700 -> Glr1, 0x1705 -> Glr3, 0x1720 -> Lightrail, // 0x1730 L4 Lightrail |
| 27 | + 0x1800 -> Glr2, 0x1805 -> Glr4, |
| 28 | + 0x1905 -> Hsr, 0x1925 -> L2Hsr, 0x1920 -> Monorail, // 0x1930 L4 Monorail |
| 29 | + |
| 30 | + 0x1a00 -> Tla3, 0x1b00 -> Ave2, 0x1c00 -> Ard3, |
| 31 | + 0x1d00 -> Owr1, 0x1e00 -> Owr3, 0x1f00 -> Nrd4, |
| 32 | + 0x2000 -> Tla5, 0x2100 -> Owr4, 0x2200 -> Owr5, |
| 33 | + 0x2300 -> Rd4, 0x2400 -> Rd6, 0x2500 -> Ave6, |
| 34 | + 0x2580 -> Tla7m, 0x2600 -> Ave8, 0x2680 -> Ave6m, |
| 35 | + // 0x2700 Tram-on-Street, 0x2800 Tram-in-Road, 0x2805 Tram-on-Road, 0x2a00 Tram-in-Avenue |
| 36 | + ).map(_.swap)) |
| 37 | + |
| 38 | +} |
| 39 | + |
| 40 | +class ViaductResolver extends IdResolver { |
| 41 | + def isDefinedAt(t: Tile): Boolean = tileMap.isDefinedAt(t) |
| 42 | + def apply(tile: Tile): IdTile = tileMap(tile) |
| 43 | + |
| 44 | + val tileMap = { |
| 45 | + val builder = new ResolverBuilder |
| 46 | + import builder.add |
| 47 | + |
| 48 | + // curves |
| 49 | + for (n <- Viaducts) { |
| 50 | + val id = ViaductResolver.viaductRangeId(n) |
| 51 | + |
| 52 | + if (NP.isSingleTile(n)) { |
| 53 | + add(id + 0x0400, n~(0,2,0,11)) // 45 curve |
| 54 | + add(id + 0x0500, n~(0,0,1,13)) // 45 curve |
| 55 | + add(id + 0x0600, n~(0,11,0,11)) // S curve |
| 56 | + add(id + 0x0700, n~(0,11,0,13)) // boomerang |
| 57 | + add(id + 0x0800, n~(0,0,2,2)) // 90 curve |
| 58 | + } else { |
| 59 | + add(id + 0x0300, n~SharedDiagLeft) |
| 60 | + add(id + 0x0500, n~(0,-2,0,+11)) // 45 curve |
| 61 | + add(id + 0x0600, n~(0,+2,0,-11)) // 45 curve |
| 62 | + add(id + 0x0700, n~(0,-11,+3,0)) // 45 curve |
| 63 | + add(id + 0x0800, n~(-3,+11,-3,+1)) // 45 curve |
| 64 | + add(id + 0x0a00, n~(+2,0,-113,0)) // 90 curve extended |
| 65 | + add(id + 0x0b00, n~(+2,0,0,-2)) // 90 curve outside |
| 66 | + add(id + 0x0c00, n~(-2,0,0,+2)) // 90 curve inside |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + // crossings |
| 71 | + for { |
| 72 | + n <- Viaducts.iterator |
| 73 | + n2 <- ViaductResolver.viaductPieceId.keysIterator |
| 74 | + if !RhwResolver.greater(n2, n) |
| 75 | + if NP.intersectionAllowed(n, n2) || n.height == 2 && (n2 == Lightrail || n2 == Monorail) // Lightrail and Monorail are base network crossings, but might not actually be needed for overrides |
| 76 | + } { |
| 77 | + val pid = ViaductResolver.viaductPieceId(n2) |
| 78 | + val id = ViaductResolver.viaductRangeId(n) + pid |
| 79 | + val (rev00, rev01, rev10, rev11) = // for reversed directions of networks |
| 80 | + if (n.typ == AvenueLike) (0x00, 0x09, 0x80, 0x89) |
| 81 | + else (0x00, 0x05, 0x80, 0x85) |
| 82 | + val orientA: IntFlags => IntFlags = if (n2 == Ard3) reverseIntFlags else identity |
| 83 | + |
| 84 | + // O×O |
| 85 | + add(n~NS & n2~orientA(EW), id + 0x0000) |
| 86 | + |
| 87 | + // O×D |
| 88 | + if (!n2.isNwm && !Viaducts.contains(n2)) { |
| 89 | + val ne = if (n2.typ == AvenueLike) SharedDiagLeft else NE |
| 90 | + if (n.typ == AvenueLike) { |
| 91 | + add(n~NS & n2~SW, id + 0x3000 + rev00) |
| 92 | + add(n~NS & n2~NE, id + 0x3000 + rev01, when = !n2.isSymm) |
| 93 | + add(n~NS & n2~ne, id + 0x3000 + rev10, when = !n.isSymm) // TODO Monorail swaps 0x80 and 0x00 -> model issue only |
| 94 | + // add(n~??? & n2~???, id + 0x3000 + rev11, when = !n.isSymm && (n2.typ == Asymmetrical)) |
| 95 | + } else { |
| 96 | + add(n~NS & n2~SW, id + 0x3000 + rev00) |
| 97 | + add(n~NS & n2~ne, id + 0x3000 + rev01, when = !n2.isSymm) |
| 98 | + } |
| 99 | + } |
| 100 | + // D×O |
| 101 | + if (!n2.isNwm && !Viaducts.contains(n2)) { |
| 102 | + if (n.typ == AvenueLike) { |
| 103 | + add(n~NE & n2~NS, id + 0x6000 + rev00) |
| 104 | + add(n~NE & n2~SN, id + 0x6000 + rev01, when = !n2.isSymm) |
| 105 | + add(n~SharedDiagLeft & n2~NS, id + 0x6000 + rev10, when = !n.isSymm) |
| 106 | + // add(n~??? & n2~???, id + 0x6000 + rev11, when = (n.typ == Asymmetrical) && !n2.isSymm) |
| 107 | + } else { |
| 108 | + add(n~ES & n2~WE, id + 0x6000 + rev00) |
| 109 | + add(n~ES & n2~EW, id + 0x6000 + rev10, when = !n2.isSymm) |
| 110 | + } |
| 111 | + } |
| 112 | + // D×D |
| 113 | + if (!n2.isNwm && !Viaducts.contains(n2)) { |
| 114 | + val se = if (n2.typ == AvenueLike) SharedDiagRight else SE |
| 115 | + if (n.typ == AvenueLike) { |
| 116 | + add(n~NE & n2~ES, id + 0x9000 + rev00) |
| 117 | + add(n~NE & n2~SharedDiagRight, id + 0x9000 + rev01, when = n2.typ == AvenueLike) |
| 118 | + add(n~SharedDiagLeft & n2~se, id + 0x9000 + rev10, when = !n.isSymm) |
| 119 | + add(n~SharedDiagLeft & n2~WN, id + 0x9000 + rev11, when = !n.isSymm && !n2.isSymm) |
| 120 | + } else { |
| 121 | + add(n~ES & n2~SW, id + 0x9000 + rev00) |
| 122 | + add(n~ES & n2~SharedDiagLeft, id + 0x9000 + rev10, when = n2.typ == AvenueLike) |
| 123 | + } |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + // T intersections |
| 128 | + for (n <- Viaducts) { |
| 129 | + val id = ViaductResolver.viaductRangeId(n) |
| 130 | + if (n.height == 1) { |
| 131 | + add(id + 0x3110, n~SN & L1Road~CE) |
| 132 | + add(id + 0x3115, n~SN & L1Road~WC, when = !n.isSymm) |
| 133 | + add(id + 0x3210, n~SN & L1Onewayroad~CE) |
| 134 | + add(id + 0x3215, n~SN & L1Onewayroad~WC, when = !n.isSymm) |
| 135 | + add(id + 0x3310, n~WE & L1Avenue~NC, when = n.isSymm) |
| 136 | + add(id + 0x3315, n~WE & L1Avenue~NC, when = !n.isSymm) |
| 137 | + } |
| 138 | + if (n.height == 2) { |
| 139 | + add(id + 0x3120, n~SN & L2Road~CE) |
| 140 | + add(id + 0x3125, n~SN & L2Road~WC, when = !n.isSymm) |
| 141 | + add(id + 0x3220, n~SN & L2Onewayroad~CE) |
| 142 | + add(id + 0x3225, n~SN & L2Onewayroad~WC, when = !n.isSymm) |
| 143 | + add(id + 0x3320, n~WE & L2Avenue~NC, when = n.isSymm) |
| 144 | + add(id + 0x3325, n~WE & L2Avenue~NC, when = !n.isSymm) |
| 145 | + } |
| 146 | + } |
| 147 | + |
| 148 | + // Onslope transitions |
| 149 | + add(0x5c060000, L1Road~NC & Road~CS) |
| 150 | + add(0x5c060010, L2Road~NC & L1Road~CS) |
| 151 | + add(0x5c060100, L2Road~NC & Road~CS) |
| 152 | + add(0x5c070000, L1Onewayroad~NC & Onewayroad~CS) |
| 153 | + add(0x5c070010, L2Onewayroad~NC & L1Onewayroad~CS) |
| 154 | + add(0x5c070100, L2Onewayroad~NC & Onewayroad~CS) |
| 155 | + add(0x5c080000, L1Avenue~NC & Avenue~CS) |
| 156 | + add(0x5c080010, L2Avenue~NC & L1Avenue~CS) |
| 157 | + add(0x5c080100, L2Avenue~NC & Avenue~CS) |
| 158 | + |
| 159 | + builder.result() |
| 160 | + } |
| 161 | +} |
0 commit comments