mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-13 07:10:57 +00:00
424 lines
10 KiB
C
424 lines
10 KiB
C
/* $Id$ */
|
|
|
|
/*
|
|
* This file is part of OpenTTD.
|
|
* 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.
|
|
* 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.
|
|
* 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/>.
|
|
*/
|
|
|
|
/** @file slope_func.h Functions related to slopes. */
|
|
|
|
#ifndef SLOPE_FUNC_H
|
|
#define SLOPE_FUNC_H
|
|
|
|
#include "core/math_func.hpp"
|
|
#include "slope_type.h"
|
|
#include "direction_type.h"
|
|
#include "tile_type.h"
|
|
|
|
/**
|
|
* Rangecheck for Corner enumeration.
|
|
*
|
|
* @param corner A #Corner.
|
|
* @return true iff corner is in a valid range.
|
|
*/
|
|
static inline bool IsValidCorner(Corner corner)
|
|
{
|
|
return IsInsideMM(corner, 0, CORNER_END);
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if a slope is steep.
|
|
*
|
|
* @param s The given #Slope.
|
|
* @return True if the slope is steep, else false.
|
|
*/
|
|
static inline bool IsSteepSlope(Slope s)
|
|
{
|
|
return (s & SLOPE_STEEP) != 0;
|
|
}
|
|
|
|
/**
|
|
* Checks for non-continuous slope on halftile foundations.
|
|
*
|
|
* @param s The given #Slope.
|
|
* @return True if the slope is non-continuous, else false.
|
|
*/
|
|
static inline bool IsHalftileSlope(Slope s)
|
|
{
|
|
return (s & SLOPE_HALFTILE) != 0;
|
|
}
|
|
|
|
/**
|
|
* Removes a halftile slope from a slope
|
|
*
|
|
* Non-halftile slopes remain unmodified.
|
|
*
|
|
* @param s A #Slope.
|
|
* @return The slope s without its halftile slope.
|
|
*/
|
|
static inline Slope RemoveHalftileSlope(Slope s)
|
|
{
|
|
return s & ~SLOPE_HALFTILE_MASK;
|
|
}
|
|
|
|
/**
|
|
* Return the complement of a slope.
|
|
*
|
|
* This method returns the complement of a slope. The complement of a
|
|
* slope is a slope with raised corner which aren't raised in the given
|
|
* slope.
|
|
*
|
|
* @pre The slope must neither be steep nor a halftile slope.
|
|
* @param s The #Slope to get the complement.
|
|
* @return a complement Slope of the given slope.
|
|
*/
|
|
static inline Slope ComplementSlope(Slope s)
|
|
{
|
|
assert(!IsSteepSlope(s) && !IsHalftileSlope(s));
|
|
return s ^ SLOPE_ELEVATED;
|
|
}
|
|
|
|
/**
|
|
* Tests if a specific slope has exactly one corner raised.
|
|
*
|
|
* @param s The #Slope
|
|
* @return true iff exactly one corner is raised
|
|
*/
|
|
static inline bool IsSlopeWithOneCornerRaised(Slope s)
|
|
{
|
|
return (s == SLOPE_W) || (s == SLOPE_S) || (s == SLOPE_E) || (s == SLOPE_N);
|
|
}
|
|
|
|
/**
|
|
* Returns the slope with a specific corner raised.
|
|
*
|
|
* @param corner The #Corner.
|
|
* @return The #Slope with corner "corner" raised.
|
|
*/
|
|
static inline Slope SlopeWithOneCornerRaised(Corner corner)
|
|
{
|
|
assert(IsValidCorner(corner));
|
|
return (Slope)(1 << corner);
|
|
}
|
|
|
|
/**
|
|
* Tests if a slope has a highest corner (i.e. one corner raised or a steep slope).
|
|
*
|
|
* Note: A halftile slope is ignored.
|
|
*
|
|
* @param s The #Slope.
|
|
* @return true iff the slope has a highest corner.
|
|
*/
|
|
static inline bool HasSlopeHighestCorner(Slope s)
|
|
{
|
|
s = RemoveHalftileSlope(s);
|
|
return IsSteepSlope(s) || IsSlopeWithOneCornerRaised(s);
|
|
}
|
|
|
|
/**
|
|
* Returns the highest corner of a slope (one corner raised or a steep slope).
|
|
*
|
|
* @pre The slope must be a slope with one corner raised or a steep slope. A halftile slope is ignored.
|
|
* @param s The #Slope.
|
|
* @return Highest corner.
|
|
*/
|
|
static inline Corner GetHighestSlopeCorner(Slope s)
|
|
{
|
|
switch (RemoveHalftileSlope(s)) {
|
|
case SLOPE_W:
|
|
case SLOPE_STEEP_W: return CORNER_W;
|
|
case SLOPE_S:
|
|
case SLOPE_STEEP_S: return CORNER_S;
|
|
case SLOPE_E:
|
|
case SLOPE_STEEP_E: return CORNER_E;
|
|
case SLOPE_N:
|
|
case SLOPE_STEEP_N: return CORNER_N;
|
|
default: NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the leveled halftile of a halftile slope.
|
|
*
|
|
* @pre The slope must be a halftile slope.
|
|
* @param s The #Slope.
|
|
* @return The corner of the leveled halftile.
|
|
*/
|
|
static inline Corner GetHalftileSlopeCorner(Slope s)
|
|
{
|
|
assert(IsHalftileSlope(s));
|
|
return (Corner)((s >> 6) & 3);
|
|
}
|
|
|
|
/**
|
|
* Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
|
|
*
|
|
* @param s The #Slope.
|
|
* @return Relative height of highest corner.
|
|
*/
|
|
static inline int GetSlopeMaxZ(Slope s)
|
|
{
|
|
if (s == SLOPE_FLAT) return 0;
|
|
if (IsSteepSlope(s)) return 2;
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
|
|
*
|
|
* @param s The #Slope.
|
|
* @return Relative height of highest corner.
|
|
*/
|
|
static inline int GetSlopeMaxPixelZ(Slope s)
|
|
{
|
|
return GetSlopeMaxZ(s) * TILE_HEIGHT;
|
|
}
|
|
|
|
/**
|
|
* Returns the opposite corner.
|
|
*
|
|
* @param corner A #Corner.
|
|
* @return The opposite corner to "corner".
|
|
*/
|
|
static inline Corner OppositeCorner(Corner corner)
|
|
{
|
|
return (Corner)(corner ^ 2);
|
|
}
|
|
|
|
/**
|
|
* Tests if a specific slope has exactly three corners raised.
|
|
*
|
|
* @param s The #Slope
|
|
* @return true iff exactly three corners are raised
|
|
*/
|
|
static inline bool IsSlopeWithThreeCornersRaised(Slope s)
|
|
{
|
|
return !IsHalftileSlope(s) && !IsSteepSlope(s) && IsSlopeWithOneCornerRaised(ComplementSlope(s));
|
|
}
|
|
|
|
/**
|
|
* Returns the slope with all except one corner raised.
|
|
*
|
|
* @param corner The #Corner.
|
|
* @return The #Slope with all corners but "corner" raised.
|
|
*/
|
|
static inline Slope SlopeWithThreeCornersRaised(Corner corner)
|
|
{
|
|
return ComplementSlope(SlopeWithOneCornerRaised(corner));
|
|
}
|
|
|
|
/**
|
|
* Returns a specific steep slope
|
|
*
|
|
* @param corner A #Corner.
|
|
* @return The steep #Slope with "corner" as highest corner.
|
|
*/
|
|
static inline Slope SteepSlope(Corner corner)
|
|
{
|
|
return SLOPE_STEEP | SlopeWithThreeCornersRaised(OppositeCorner(corner));
|
|
}
|
|
|
|
/**
|
|
* Tests if a specific slope is an inclined slope.
|
|
*
|
|
* @param s The #Slope
|
|
* @return true iff the slope is inclined.
|
|
*/
|
|
static inline bool IsInclinedSlope(Slope s)
|
|
{
|
|
return (s == SLOPE_NW) || (s == SLOPE_SW) || (s == SLOPE_SE) || (s == SLOPE_NE);
|
|
}
|
|
|
|
/**
|
|
* Returns the direction of an inclined slope.
|
|
*
|
|
* @param s A #Slope
|
|
* @return The direction the slope goes up in. Or INVALID_DIAGDIR if the slope is not an inclined slope.
|
|
*/
|
|
static inline DiagDirection GetInclinedSlopeDirection(Slope s)
|
|
{
|
|
switch (s) {
|
|
case SLOPE_NE: return DIAGDIR_NE;
|
|
case SLOPE_SE: return DIAGDIR_SE;
|
|
case SLOPE_SW: return DIAGDIR_SW;
|
|
case SLOPE_NW: return DIAGDIR_NW;
|
|
default: return INVALID_DIAGDIR;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the slope that is inclined in a specific direction.
|
|
*
|
|
* @param dir A #DiagDirection
|
|
* @return The #Slope that goes up in direction dir.
|
|
*/
|
|
static inline Slope InclinedSlope(DiagDirection dir)
|
|
{
|
|
switch (dir) {
|
|
case DIAGDIR_NE: return SLOPE_NE;
|
|
case DIAGDIR_SE: return SLOPE_SE;
|
|
case DIAGDIR_SW: return SLOPE_SW;
|
|
case DIAGDIR_NW: return SLOPE_NW;
|
|
default: NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a halftile slope to a slope.
|
|
*
|
|
* @param s #Slope without a halftile slope.
|
|
* @param corner The #Corner of the halftile.
|
|
* @return The #Slope s with the halftile slope added.
|
|
*/
|
|
static inline Slope HalftileSlope(Slope s, Corner corner)
|
|
{
|
|
assert(IsValidCorner(corner));
|
|
return (Slope)(s | SLOPE_HALFTILE | (corner << 6));
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests for FOUNDATION_NONE.
|
|
*
|
|
* @param f Maybe a #Foundation.
|
|
* @return true iff f is a foundation.
|
|
*/
|
|
static inline bool IsFoundation(Foundation f)
|
|
{
|
|
return f != FOUNDATION_NONE;
|
|
}
|
|
|
|
/**
|
|
* Tests if the foundation is a leveled foundation.
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return true iff f is a leveled foundation.
|
|
*/
|
|
static inline bool IsLeveledFoundation(Foundation f)
|
|
{
|
|
return f == FOUNDATION_LEVELED;
|
|
}
|
|
|
|
/**
|
|
* Tests if the foundation is an inclined foundation.
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return true iff f is an inclined foundation.
|
|
*/
|
|
static inline bool IsInclinedFoundation(Foundation f)
|
|
{
|
|
return (f == FOUNDATION_INCLINED_X) || (f == FOUNDATION_INCLINED_Y);
|
|
}
|
|
|
|
/**
|
|
* Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH.
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return true iff f is a non-continuous foundation
|
|
*/
|
|
static inline bool IsNonContinuousFoundation(Foundation f)
|
|
{
|
|
return IsInsideMM(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1);
|
|
}
|
|
|
|
/**
|
|
* Returns the halftile corner of a halftile-foundation
|
|
*
|
|
* @pre f != FOUNDATION_STEEP_BOTH
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return The #Corner with track.
|
|
*/
|
|
static inline Corner GetHalftileFoundationCorner(Foundation f)
|
|
{
|
|
assert(IsInsideMM(f, FOUNDATION_HALFTILE_W, FOUNDATION_HALFTILE_N + 1));
|
|
return (Corner)(f - FOUNDATION_HALFTILE_W);
|
|
}
|
|
|
|
/**
|
|
* Tests if a foundation is a special rail foundation for single horizontal/vertical track.
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return true iff f is a special rail foundation for single horizontal/vertical track.
|
|
*/
|
|
static inline bool IsSpecialRailFoundation(Foundation f)
|
|
{
|
|
return IsInsideMM(f, FOUNDATION_RAIL_W, FOUNDATION_RAIL_N + 1);
|
|
}
|
|
|
|
/**
|
|
* Returns the track corner of a special rail foundation
|
|
*
|
|
* @param f The #Foundation.
|
|
* @return The #Corner with track.
|
|
*/
|
|
static inline Corner GetRailFoundationCorner(Foundation f)
|
|
{
|
|
assert(IsSpecialRailFoundation(f));
|
|
return (Corner)(f - FOUNDATION_RAIL_W);
|
|
}
|
|
|
|
/**
|
|
* Returns the foundation needed to flatten a slope.
|
|
* The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED.
|
|
*
|
|
* @param s The current #Slope.
|
|
* @return The needed #Foundation.
|
|
*/
|
|
static inline Foundation FlatteningFoundation(Slope s)
|
|
{
|
|
return (s == SLOPE_FLAT ? FOUNDATION_NONE : FOUNDATION_LEVELED);
|
|
}
|
|
|
|
/**
|
|
* Returns the along a specific axis inclined foundation.
|
|
*
|
|
* @param axis The #Axis.
|
|
* @return The needed #Foundation.
|
|
*/
|
|
static inline Foundation InclinedFoundation(Axis axis)
|
|
{
|
|
return (axis == AXIS_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y);
|
|
}
|
|
|
|
/**
|
|
* Returns the halftile foundation for single horizontal/vertical track.
|
|
*
|
|
* @param corner The #Corner with the track.
|
|
* @return The wanted #Foundation.
|
|
*/
|
|
static inline Foundation HalftileFoundation(Corner corner)
|
|
{
|
|
assert(IsValidCorner(corner));
|
|
return (Foundation)(FOUNDATION_HALFTILE_W + corner);
|
|
}
|
|
|
|
/**
|
|
* Returns the special rail foundation for single horizontal/vertical track.
|
|
*
|
|
* @param corner The #Corner with the track.
|
|
* @return The wanted #Foundation.
|
|
*/
|
|
static inline Foundation SpecialRailFoundation(Corner corner)
|
|
{
|
|
assert(IsValidCorner(corner));
|
|
return (Foundation)(FOUNDATION_RAIL_W + corner);
|
|
}
|
|
|
|
/**
|
|
* Returns the #Sprite offset for a given #Slope.
|
|
*
|
|
* @param s The #Slope to get the offset for.
|
|
* @return The sprite offset for this #Slope.
|
|
*/
|
|
static inline uint SlopeToSpriteOffset(Slope s)
|
|
{
|
|
extern const byte _slope_to_sprite_offset[32];
|
|
return _slope_to_sprite_offset[s];
|
|
}
|
|
|
|
#endif /* SLOPE_FUNC_H */
|