4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file slope_func.h Functions related to slopes. */
15 #include "core/math_func.hpp"
16 #include "map/subcoord.h"
17 #include "slope_type.h"
18 #include "direction_type.h"
21 * Rangecheck for Corner enumeration.
23 * @param corner A #Corner.
24 * @return true iff corner is in a valid range.
26 static inline bool IsValidCorner(Corner corner
)
28 return IsInsideMM(corner
, 0, CORNER_END
);
33 * Checks if a slope is steep.
35 * @param s The given #Slope.
36 * @return True if the slope is steep, else false.
38 static inline bool IsSteepSlope(Slope s
)
40 return (s
& SLOPE_STEEP
) != 0;
44 * Checks for non-continuous slope on halftile foundations.
46 * @param s The given #Slope.
47 * @return True if the slope is non-continuous, else false.
49 static inline bool IsHalftileSlope(Slope s
)
51 return (s
& SLOPE_HALFTILE
) != 0;
55 * Removes a halftile slope from a slope
57 * Non-halftile slopes remain unmodified.
60 * @return The slope s without its halftile slope.
62 static inline Slope
RemoveHalftileSlope(Slope s
)
64 return s
& ~SLOPE_HALFTILE_MASK
;
68 * Return the complement of a slope.
70 * This method returns the complement of a slope. The complement of a
71 * slope is a slope with raised corner which aren't raised in the given
74 * @pre The slope must neither be steep nor a halftile slope.
75 * @param s The #Slope to get the complement.
76 * @return a complement Slope of the given slope.
78 static inline Slope
ComplementSlope(Slope s
)
80 assert(!IsSteepSlope(s
) && !IsHalftileSlope(s
));
81 return s
^ SLOPE_ELEVATED
;
85 * Tests if a specific slope has exactly one corner raised.
88 * @return true iff exactly one corner is raised
90 static inline bool IsSlopeWithOneCornerRaised(Slope s
)
92 return (s
== SLOPE_W
) || (s
== SLOPE_S
) || (s
== SLOPE_E
) || (s
== SLOPE_N
);
96 * Returns the slope with a specific corner raised.
98 * @param corner The #Corner.
99 * @return The #Slope with corner "corner" raised.
101 static inline Slope
SlopeWithOneCornerRaised(Corner corner
)
103 assert(IsValidCorner(corner
));
104 return (Slope
)(1 << corner
);
108 * Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
110 * Note: A halftile slope is ignored.
112 * @param s The #Slope.
113 * @return true iff the slope has a highest corner.
115 static inline bool HasSlopeHighestCorner(Slope s
)
117 s
= RemoveHalftileSlope(s
);
118 return IsSteepSlope(s
) || IsSlopeWithOneCornerRaised(s
);
122 * Returns the highest corner of a slope (one corner raised or a steep slope).
124 * @pre The slope must be a slope with one corner raised or a steep slope. A halftile slope is ignored.
125 * @param s The #Slope.
126 * @return Highest corner.
128 static inline Corner
GetHighestSlopeCorner(Slope s
)
130 switch (RemoveHalftileSlope(s
)) {
132 case SLOPE_STEEP_W
: return CORNER_W
;
134 case SLOPE_STEEP_S
: return CORNER_S
;
136 case SLOPE_STEEP_E
: return CORNER_E
;
138 case SLOPE_STEEP_N
: return CORNER_N
;
139 default: NOT_REACHED();
144 * Returns the leveled halftile of a halftile slope.
146 * @pre The slope must be a halftile slope.
147 * @param s The #Slope.
148 * @return The corner of the leveled halftile.
150 static inline Corner
GetHalftileSlopeCorner(Slope s
)
152 assert(IsHalftileSlope(s
));
153 return (Corner
)((s
>> 6) & 3);
157 * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
159 * @param s The #Slope.
160 * @return Relative height of highest corner.
162 static inline int GetSlopeMaxZ(Slope s
)
164 if (s
== SLOPE_FLAT
) return 0;
165 if (IsSteepSlope(s
)) return 2;
170 * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
172 * @param s The #Slope.
173 * @return Relative height of highest corner.
175 static inline int GetSlopeMaxPixelZ(Slope s
)
177 return GetSlopeMaxZ(s
) * TILE_HEIGHT
;
181 * Returns the opposite corner.
183 * @param corner A #Corner.
184 * @return The opposite corner to "corner".
186 static inline Corner
OppositeCorner(Corner corner
)
188 return (Corner
)(corner
^ 2);
192 * Tests if a specific slope has exactly three corners raised.
194 * @param s The #Slope
195 * @return true iff exactly three corners are raised
197 static inline bool IsSlopeWithThreeCornersRaised(Slope s
)
199 return !IsHalftileSlope(s
) && !IsSteepSlope(s
) && IsSlopeWithOneCornerRaised(ComplementSlope(s
));
203 * Returns the slope with all except one corner raised.
205 * @param corner The #Corner.
206 * @return The #Slope with all corners but "corner" raised.
208 static inline Slope
SlopeWithThreeCornersRaised(Corner corner
)
210 return ComplementSlope(SlopeWithOneCornerRaised(corner
));
214 * Returns a specific steep slope
216 * @param corner A #Corner.
217 * @return The steep #Slope with "corner" as highest corner.
219 static inline Slope
SteepSlope(Corner corner
)
221 return SLOPE_STEEP
| SlopeWithThreeCornersRaised(OppositeCorner(corner
));
225 * Tests if a specific slope is an inclined slope.
227 * @param s The #Slope
228 * @return true iff the slope is inclined.
230 static inline bool IsInclinedSlope(Slope s
)
232 return (s
== SLOPE_NW
) || (s
== SLOPE_SW
) || (s
== SLOPE_SE
) || (s
== SLOPE_NE
);
236 * Returns the direction of an inclined slope.
239 * @return The direction the slope goes up in. Or INVALID_DIAGDIR if the slope is not an inclined slope.
241 static inline DiagDirection
GetInclinedSlopeDirection(Slope s
)
244 case SLOPE_NE
: return DIAGDIR_NE
;
245 case SLOPE_SE
: return DIAGDIR_SE
;
246 case SLOPE_SW
: return DIAGDIR_SW
;
247 case SLOPE_NW
: return DIAGDIR_NW
;
248 default: return INVALID_DIAGDIR
;
253 * Returns the slope that is inclined in a specific direction.
255 * @param dir A #DiagDirection
256 * @return The #Slope that goes up in direction dir.
258 static inline Slope
InclinedSlope(DiagDirection dir
)
261 case DIAGDIR_NE
: return SLOPE_NE
;
262 case DIAGDIR_SE
: return SLOPE_SE
;
263 case DIAGDIR_SW
: return SLOPE_SW
;
264 case DIAGDIR_NW
: return SLOPE_NW
;
265 default: NOT_REACHED();
270 * Adds a halftile slope to a slope.
272 * @param s #Slope without a halftile slope.
273 * @param corner The #Corner of the halftile.
274 * @return The #Slope s with the halftile slope added.
276 static inline Slope
HalftileSlope(Slope s
, Corner corner
)
278 assert(IsValidCorner(corner
));
279 return (Slope
)(s
| SLOPE_HALFTILE
| (corner
<< 6));
284 * Tests for FOUNDATION_NONE.
286 * @param f Maybe a #Foundation.
287 * @return true iff f is a foundation.
289 static inline bool IsFoundation(Foundation f
)
291 return f
!= FOUNDATION_NONE
;
295 * Tests if the foundation is a leveled foundation.
297 * @param f The #Foundation.
298 * @return true iff f is a leveled foundation.
300 static inline bool IsLeveledFoundation(Foundation f
)
302 return f
== FOUNDATION_LEVELED
;
306 * Tests if the foundation is an inclined foundation.
308 * @param f The #Foundation.
309 * @return true iff f is an inclined foundation.
311 static inline bool IsInclinedFoundation(Foundation f
)
313 return (f
== FOUNDATION_INCLINED_X
) || (f
== FOUNDATION_INCLINED_Y
);
317 * Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH.
319 * @param f The #Foundation.
320 * @return true iff f is a non-continuous foundation
322 static inline bool IsNonContinuousFoundation(Foundation f
)
324 return IsInsideMM(f
, FOUNDATION_STEEP_BOTH
, FOUNDATION_HALFTILE_N
+ 1);
328 * Returns the halftile corner of a halftile-foundation
330 * @pre f != FOUNDATION_STEEP_BOTH
332 * @param f The #Foundation.
333 * @return The #Corner with track.
335 static inline Corner
GetHalftileFoundationCorner(Foundation f
)
337 assert(IsInsideMM(f
, FOUNDATION_HALFTILE_W
, FOUNDATION_HALFTILE_N
+ 1));
338 return (Corner
)(f
- FOUNDATION_HALFTILE_W
);
342 * Tests if a foundation is a special rail foundation for single horizontal/vertical track.
344 * @param f The #Foundation.
345 * @return true iff f is a special rail foundation for single horizontal/vertical track.
347 static inline bool IsSpecialRailFoundation(Foundation f
)
349 return IsInsideMM(f
, FOUNDATION_RAIL_W
, FOUNDATION_RAIL_N
+ 1);
353 * Returns the track corner of a special rail foundation
355 * @param f The #Foundation.
356 * @return The #Corner with track.
358 static inline Corner
GetRailFoundationCorner(Foundation f
)
360 assert(IsSpecialRailFoundation(f
));
361 return (Corner
)(f
- FOUNDATION_RAIL_W
);
365 * Returns the foundation needed to flatten a slope.
366 * The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED.
368 * @param s The current #Slope.
369 * @return The needed #Foundation.
371 static inline Foundation
FlatteningFoundation(Slope s
)
373 return (s
== SLOPE_FLAT
? FOUNDATION_NONE
: FOUNDATION_LEVELED
);
377 * Returns the along a specific axis inclined foundation.
379 * @param axis The #Axis.
380 * @return The needed #Foundation.
382 static inline Foundation
InclinedFoundation(Axis axis
)
384 return (axis
== AXIS_X
? FOUNDATION_INCLINED_X
: FOUNDATION_INCLINED_Y
);
388 * Returns the halftile foundation for single horizontal/vertical track.
390 * @param corner The #Corner with the track.
391 * @return The wanted #Foundation.
393 static inline Foundation
HalftileFoundation(Corner corner
)
395 assert(IsValidCorner(corner
));
396 return (Foundation
)(FOUNDATION_HALFTILE_W
+ corner
);
400 * Returns the special rail foundation for single horizontal/vertical track.
402 * @param corner The #Corner with the track.
403 * @return The wanted #Foundation.
405 static inline Foundation
SpecialRailFoundation(Corner corner
)
407 assert(IsValidCorner(corner
));
408 return (Foundation
)(FOUNDATION_RAIL_W
+ corner
);
412 * Returns the #Sprite offset for a given #Slope.
414 * @param s The #Slope to get the offset for.
415 * @return The sprite offset for this #Slope.
417 static inline uint
SlopeToSpriteOffset(Slope s
)
419 extern const byte _slope_to_sprite_offset
[32];
420 return _slope_to_sprite_offset
[s
];
423 #endif /* SLOPE_FUNC_H */