2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file slope_func.h Functions related to slopes. */
13 #include "core/math_func.hpp"
14 #include "slope_type.h"
15 #include "direction_type.h"
16 #include "tile_type.h"
19 * Rangecheck for Corner enumeration.
21 * @param corner A #Corner.
22 * @return true iff corner is in a valid range.
24 static constexpr inline bool IsValidCorner(Corner corner
)
26 return IsInsideMM(corner
, 0, CORNER_END
);
31 * Checks if a slope is steep.
33 * @param s The given #Slope.
34 * @return True if the slope is steep, else false.
36 static constexpr inline bool IsSteepSlope(Slope s
)
38 return (s
& SLOPE_STEEP
) != 0;
42 * Checks for non-continuous slope on halftile foundations.
44 * @param s The given #Slope.
45 * @return True if the slope is non-continuous, else false.
47 static constexpr inline bool IsHalftileSlope(Slope s
)
49 return (s
& SLOPE_HALFTILE
) != 0;
53 * Removes a halftile slope from a slope
55 * Non-halftile slopes remain unmodified.
58 * @return The slope s without its halftile slope.
60 static constexpr inline Slope
RemoveHalftileSlope(Slope s
)
62 return s
& ~SLOPE_HALFTILE_MASK
;
66 * Return the complement of a slope.
68 * This method returns the complement of a slope. The complement of a
69 * slope is a slope with raised corner which aren't raised in the given
72 * @pre The slope must neither be steep nor a halftile slope.
73 * @param s The #Slope to get the complement.
74 * @return a complement Slope of the given slope.
76 inline Slope
ComplementSlope(Slope s
)
78 assert(!IsSteepSlope(s
) && !IsHalftileSlope(s
));
79 return s
^ SLOPE_ELEVATED
;
83 * Tests if a specific slope has exactly one corner raised.
86 * @return true iff exactly one corner is raised
88 inline bool IsSlopeWithOneCornerRaised(Slope s
)
90 return (s
== SLOPE_W
) || (s
== SLOPE_S
) || (s
== SLOPE_E
) || (s
== SLOPE_N
);
94 * Returns the slope with a specific corner raised.
96 * @param corner The #Corner.
97 * @return The #Slope with corner "corner" raised.
99 inline Slope
SlopeWithOneCornerRaised(Corner corner
)
101 assert(IsValidCorner(corner
));
102 return (Slope
)(1 << corner
);
106 * Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
108 * Note: A halftile slope is ignored.
110 * @param s The #Slope.
111 * @return true iff the slope has a highest corner.
113 inline bool HasSlopeHighestCorner(Slope s
)
115 s
= RemoveHalftileSlope(s
);
116 return IsSteepSlope(s
) || IsSlopeWithOneCornerRaised(s
);
120 * Returns the highest corner of a slope (one corner raised or a steep slope).
122 * @pre The slope must be a slope with one corner raised or a steep slope. A halftile slope is ignored.
123 * @param s The #Slope.
124 * @return Highest corner.
126 inline Corner
GetHighestSlopeCorner(Slope s
)
128 switch (RemoveHalftileSlope(s
)) {
130 case SLOPE_STEEP_W
: return CORNER_W
;
132 case SLOPE_STEEP_S
: return CORNER_S
;
134 case SLOPE_STEEP_E
: return CORNER_E
;
136 case SLOPE_STEEP_N
: return CORNER_N
;
137 default: NOT_REACHED();
142 * Returns the leveled halftile of a halftile slope.
144 * @pre The slope must be a halftile slope.
145 * @param s The #Slope.
146 * @return The corner of the leveled halftile.
148 static constexpr inline Corner
GetHalftileSlopeCorner(Slope s
)
150 assert(IsHalftileSlope(s
));
151 return (Corner
)((s
>> 6) & 3);
155 * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
157 * @param s The #Slope.
158 * @return Relative height of highest corner.
160 static constexpr inline int GetSlopeMaxZ(Slope s
)
162 if (s
== SLOPE_FLAT
) return 0;
163 if (IsSteepSlope(s
)) return 2;
168 * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
170 * @param s The #Slope.
171 * @return Relative height of highest corner.
173 static constexpr inline int GetSlopeMaxPixelZ(Slope s
)
175 return GetSlopeMaxZ(s
) * TILE_HEIGHT
;
179 * Returns the opposite corner.
181 * @param corner A #Corner.
182 * @return The opposite corner to "corner".
184 inline Corner
OppositeCorner(Corner corner
)
186 return (Corner
)(corner
^ 2);
190 * Tests if a specific slope has exactly three corners raised.
192 * @param s The #Slope
193 * @return true iff exactly three corners are raised
195 inline bool IsSlopeWithThreeCornersRaised(Slope s
)
197 return !IsHalftileSlope(s
) && !IsSteepSlope(s
) && IsSlopeWithOneCornerRaised(ComplementSlope(s
));
201 * Returns the slope with all except one corner raised.
203 * @param corner The #Corner.
204 * @return The #Slope with all corners but "corner" raised.
206 inline Slope
SlopeWithThreeCornersRaised(Corner corner
)
208 return ComplementSlope(SlopeWithOneCornerRaised(corner
));
212 * Returns a specific steep slope
214 * @param corner A #Corner.
215 * @return The steep #Slope with "corner" as highest corner.
217 inline Slope
SteepSlope(Corner corner
)
219 return SLOPE_STEEP
| SlopeWithThreeCornersRaised(OppositeCorner(corner
));
223 * Tests if a specific slope is an inclined slope.
225 * @param s The #Slope
226 * @return true iff the slope is inclined.
228 inline bool IsInclinedSlope(Slope s
)
230 return (s
== SLOPE_NW
) || (s
== SLOPE_SW
) || (s
== SLOPE_SE
) || (s
== SLOPE_NE
);
234 * Returns the direction of an inclined slope.
237 * @return The direction the slope goes up in. Or INVALID_DIAGDIR if the slope is not an inclined slope.
239 inline DiagDirection
GetInclinedSlopeDirection(Slope s
)
242 case SLOPE_NE
: return DIAGDIR_NE
;
243 case SLOPE_SE
: return DIAGDIR_SE
;
244 case SLOPE_SW
: return DIAGDIR_SW
;
245 case SLOPE_NW
: return DIAGDIR_NW
;
246 default: return INVALID_DIAGDIR
;
251 * Returns the slope that is inclined in a specific direction.
253 * @param dir A #DiagDirection
254 * @return The #Slope that goes up in direction dir.
256 inline Slope
InclinedSlope(DiagDirection dir
)
259 case DIAGDIR_NE
: return SLOPE_NE
;
260 case DIAGDIR_SE
: return SLOPE_SE
;
261 case DIAGDIR_SW
: return SLOPE_SW
;
262 case DIAGDIR_NW
: return SLOPE_NW
;
263 default: NOT_REACHED();
268 * Adds a halftile slope to a slope.
270 * @param s #Slope without a halftile slope.
271 * @param corner The #Corner of the halftile.
272 * @return The #Slope s with the halftile slope added.
274 static constexpr inline Slope
HalftileSlope(Slope s
, Corner corner
)
276 assert(IsValidCorner(corner
));
277 return (Slope
)(s
| SLOPE_HALFTILE
| (corner
<< 6));
282 * Tests for FOUNDATION_NONE.
284 * @param f Maybe a #Foundation.
285 * @return true iff f is a foundation.
287 inline bool IsFoundation(Foundation f
)
289 return f
!= FOUNDATION_NONE
;
293 * Tests if the foundation is a leveled foundation.
295 * @param f The #Foundation.
296 * @return true iff f is a leveled foundation.
298 inline bool IsLeveledFoundation(Foundation f
)
300 return f
== FOUNDATION_LEVELED
;
304 * Tests if the foundation is an inclined foundation.
306 * @param f The #Foundation.
307 * @return true iff f is an inclined foundation.
309 inline bool IsInclinedFoundation(Foundation f
)
311 return (f
== FOUNDATION_INCLINED_X
) || (f
== FOUNDATION_INCLINED_Y
);
315 * Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH.
317 * @param f The #Foundation.
318 * @return true iff f is a non-continuous foundation
320 inline bool IsNonContinuousFoundation(Foundation f
)
322 return IsInsideMM(f
, FOUNDATION_STEEP_BOTH
, FOUNDATION_HALFTILE_N
+ 1);
326 * Returns the halftile corner of a halftile-foundation
328 * @pre f != FOUNDATION_STEEP_BOTH
330 * @param f The #Foundation.
331 * @return The #Corner with track.
333 inline Corner
GetHalftileFoundationCorner(Foundation f
)
335 assert(IsInsideMM(f
, FOUNDATION_HALFTILE_W
, FOUNDATION_HALFTILE_N
+ 1));
336 return (Corner
)(f
- FOUNDATION_HALFTILE_W
);
340 * Tests if a foundation is a special rail foundation for single horizontal/vertical track.
342 * @param f The #Foundation.
343 * @return true iff f is a special rail foundation for single horizontal/vertical track.
345 inline bool IsSpecialRailFoundation(Foundation f
)
347 return IsInsideMM(f
, FOUNDATION_RAIL_W
, FOUNDATION_RAIL_N
+ 1);
351 * Returns the track corner of a special rail foundation
353 * @param f The #Foundation.
354 * @return The #Corner with track.
356 inline Corner
GetRailFoundationCorner(Foundation f
)
358 assert(IsSpecialRailFoundation(f
));
359 return (Corner
)(f
- FOUNDATION_RAIL_W
);
363 * Returns the foundation needed to flatten a slope.
364 * The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED.
366 * @param s The current #Slope.
367 * @return The needed #Foundation.
369 inline Foundation
FlatteningFoundation(Slope s
)
371 return (s
== SLOPE_FLAT
? FOUNDATION_NONE
: FOUNDATION_LEVELED
);
375 * Returns the along a specific axis inclined foundation.
377 * @param axis The #Axis.
378 * @return The needed #Foundation.
380 inline Foundation
InclinedFoundation(Axis axis
)
382 return (axis
== AXIS_X
? FOUNDATION_INCLINED_X
: FOUNDATION_INCLINED_Y
);
386 * Returns the halftile foundation for single horizontal/vertical track.
388 * @param corner The #Corner with the track.
389 * @return The wanted #Foundation.
391 inline Foundation
HalftileFoundation(Corner corner
)
393 assert(IsValidCorner(corner
));
394 return static_cast<Foundation
>(static_cast<uint
>(FOUNDATION_HALFTILE_W
) + static_cast<uint
>(corner
));
398 * Returns the special rail foundation for single horizontal/vertical track.
400 * @param corner The #Corner with the track.
401 * @return The wanted #Foundation.
403 inline Foundation
SpecialRailFoundation(Corner corner
)
405 assert(IsValidCorner(corner
));
406 return static_cast<Foundation
>(static_cast<uint
>(FOUNDATION_RAIL_W
) + static_cast<uint
>(corner
));
410 * Returns the #Sprite offset for a given #Slope.
412 * @param s The #Slope to get the offset for.
413 * @return The sprite offset for this #Slope.
415 inline uint
SlopeToSpriteOffset(Slope s
)
417 extern const uint8_t _slope_to_sprite_offset
[32];
418 return _slope_to_sprite_offset
[s
];
421 #endif /* SLOPE_FUNC_H */