Merge branch 'development' into feature/no_multiplayer_grf_limit
[openttd-joker.git] / src / slope_func.h
blob156c8124f55a6c097d163bd5f303f0eec1aa88df
1 /* $Id: slope_func.h 23106 2011-11-04 11:30:37Z rubidium $ */
3 /*
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/>.
8 */
10 /** @file slope_func.h Functions related to slopes. */
12 #ifndef SLOPE_FUNC_H
13 #define SLOPE_FUNC_H
15 #include "core/math_func.hpp"
16 #include "slope_type.h"
17 #include "direction_type.h"
18 #include "tile_type.h"
20 /**
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);
32 /**
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;
43 /**
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;
54 /**
55 * Removes a halftile slope from a slope
57 * Non-halftile slopes remain unmodified.
59 * @param s A #Slope.
60 * @return The slope s without its halftile slope.
62 static inline Slope RemoveHalftileSlope(Slope s)
64 return s & ~SLOPE_HALFTILE_MASK;
67 /**
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
72 * slope.
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;
84 /**
85 * Tests if a specific slope has exactly one corner raised.
87 * @param s The #Slope
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);
95 /**
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)) {
131 case SLOPE_W:
132 case SLOPE_STEEP_W: return CORNER_W;
133 case SLOPE_S:
134 case SLOPE_STEEP_S: return CORNER_S;
135 case SLOPE_E:
136 case SLOPE_STEEP_E: return CORNER_E;
137 case SLOPE_N:
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;
166 return 1;
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.
238 * @param s A #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)
243 switch (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)
260 switch (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 */