Browse Source

dun_render: Avoid `Invalid` tile type

1. Do not call `RenderTile` with invalid values to begin with.
2. Move mask selection out of `RenderTile`.
pull/5564/head
Gleb Mazovetskiy 3 years ago committed by Anders Jenbo
parent
commit
79b330825d
  1. 58
      Source/engine/render/dun_render.cpp
  2. 135
      Source/engine/render/dun_render.hpp
  3. 101
      Source/engine/render/scrollrt.cpp
  4. 2
      Source/levels/gendung.cpp
  5. 2
      Source/levels/gendung.h

58
Source/engine/render/dun_render.cpp

@ -146,16 +146,6 @@ std::string prefixDebugString(int8_t prefix) {
}
#endif
enum class MaskType {
Invalid,
Solid,
Transparent,
Right,
Left,
RightFoliage,
LeftFoliage,
};
enum class LightType : uint8_t {
FullyDark,
PartiallyLit,
@ -1010,39 +1000,6 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileDispatch(uint8_t lightTableIn
}
}
DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT MaskType GetMask(TileType tile, uint16_t levelPieceId, ArchType archType, bool transparency, bool foliage)
{
#ifdef _DEBUG
if ((SDL_GetModState() & KMOD_ALT) != 0) {
return MaskType::Solid;
}
#endif
if (transparency) {
if (archType == ArchType::None) {
return MaskType::Transparent;
}
if (archType == ArchType::Left && tile != TileType::LeftTriangle) {
if (TileHasAny(levelPieceId, TileProperties::TransparentLeft)) {
return MaskType::Left;
}
}
if (archType == ArchType::Right && tile != TileType::RightTriangle) {
if (TileHasAny(levelPieceId, TileProperties::TransparentRight)) {
return MaskType::Right;
}
}
} else if (archType != ArchType::None && foliage) {
if (tile != TileType::TransparentSquare)
return MaskType::Invalid;
if (archType == ArchType::Left)
return MaskType::LeftFoliage;
if (archType == ArchType::Right)
return MaskType::RightFoliage;
}
return MaskType::Solid;
}
// Blit with left and vertical clipping.
void RenderBlackTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, int dstPitch, int sx, DiamondClipY clipY)
{
@ -1153,11 +1110,10 @@ string_view TileTypeToString(TileType tileType)
// clang-format on
}
string_view MaskTypeToString(uint8_t maskType)
string_view MaskTypeToString(MaskType maskType)
{
// clang-format off
switch (static_cast<MaskType>(maskType)) {
case MaskType::Invalid: return "Invalid";
switch (maskType) {
case MaskType::Solid: return "Solid";
case MaskType::Transparent: return "Transparent";
case MaskType::Right: return "Right";
@ -1171,9 +1127,8 @@ string_view MaskTypeToString(uint8_t maskType)
#endif
void RenderTile(const Surface &out, Point position,
LevelCelBlock levelCelBlock, uint16_t levelPieceId,
uint8_t lightTableIndex, ArchType archType,
bool transparency, bool foliage)
uint16_t levelPieceId, LevelCelBlock levelCelBlock,
MaskType maskType, uint8_t lightTableIndex)
{
const TileType tile = levelCelBlock.type();
@ -1191,7 +1146,6 @@ void RenderTile(const Surface &out, Point position,
if (clip.width <= 0 || clip.height <= 0)
return;
MaskType maskType = GetMask(tile, levelPieceId, archType, transparency, foliage);
const uint8_t *tbl = &LightTables[256 * lightTableIndex];
const auto *pFrameTable = reinterpret_cast<const uint32_t *>(pDungeonCels.get());
const auto *src = reinterpret_cast<const uint8_t *>(&pDungeonCels[pFrameTable[levelCelBlock.frame()]]);
@ -1199,12 +1153,10 @@ void RenderTile(const Surface &out, Point position,
const auto dstPitch = out.pitch();
#ifdef DUN_RENDER_STATS
++DunRenderStats[DunRenderType { tile, static_cast<uint8_t>(maskType) }];
++DunRenderStats[DunRenderType { tile, maskType }];
#endif
switch (maskType) {
case MaskType::Invalid:
break;
case MaskType::Solid:
RenderTileDispatch</*OpaquePrefix=*/false, /*PrefixIncrement=*/0>(lightTableIndex, tile, dst, dstPitch, src, tbl, clip);
break;

135
Source/engine/render/dun_render.hpp

@ -85,12 +85,124 @@ enum class TileType : uint8_t {
};
/**
* Specifies the type of arches to render.
* @brief Specifies the mask to use for rendering.
*/
enum class ArchType {
None,
enum class MaskType : uint8_t {
/** @brief The entire tile is opaque. */
Solid,
/** @brief The entire tile is blended with transparency. */
Transparent,
/**
* @brief Upper-right triangle is blended with transparency.
*
* Can only be used with `TileType::LeftTrapezoid` and
* `TileType::TransparentSquare`.
*
* The lower 16 rows are opaque.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):
*
* 🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
*/
Right,
/**
* @brief Upper-left triangle is blended with transparency.
*
* Can only be used with `TileType::RightTrapezoid` and
* `TileType::TransparentSquare`.
*
* The lower 16 rows are opaque.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):
*
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
*/
Left,
Right
/**
* @brief Only the upper-left triangle is rendered.
*
* Can only be used with `TileType::TransparentSquare`.
*
* The lower 16 rows are skipped.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = not rendered):
*
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆
*/
RightFoliage,
/**
* @brief Only the upper right triangle is rendered.
*
* Can only be used with `TileType::TransparentSquare`.
*
* The lower 16 rows are skipped.
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = not rendered):
*
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
* 🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
*/
LeftFoliage,
};
/**
@ -125,7 +237,7 @@ private:
#ifdef DUN_RENDER_STATS
struct DunRenderType {
TileType tileType;
uint8_t maskType;
MaskType maskType;
bool operator==(const DunRenderType &other) const
{
return tileType == other.tileType && maskType == other.maskType;
@ -134,14 +246,14 @@ struct DunRenderType {
struct DunRenderTypeHash {
size_t operator()(DunRenderType t) const noexcept
{
return std::hash<uint16_t> {}((static_cast<uint8_t>(t.tileType) << 1) | t.maskType);
return std::hash<uint32_t> {}((1 < static_cast<uint8_t>(t.tileType)) | static_cast<uint8_t>(t.maskType));
}
};
extern std::unordered_map<DunRenderType, size_t, DunRenderTypeHash> DunRenderStats;
string_view TileTypeToString(TileType tileType);
string_view MaskTypeToString(uint8_t maskType);
string_view MaskTypeToString(MaskType maskType);
#endif
/**
@ -150,15 +262,12 @@ string_view MaskTypeToString(uint8_t maskType);
* @param position Target buffer coordinates
* @param levelCelBlock The MIN block of the level CEL file.
* @param levelPieceId The piece ID (index into SOLData and DPieceMicros).
* @param maskType The mask to use,
* @param lightTableIndex The light level to use for rendering (index into LightTables / 256).
* @param archType The type of arch to render.
* @param transparency Specifies whether transparency is active for the CEL sprite.
* @param foliage Specifies whether the tile has foliage. Foliage is extra content that overlaps the previous tile.
*/
void RenderTile(const Surface &out, Point position,
LevelCelBlock levelCelBlock, uint16_t levelPieceId,
uint8_t lightTableIndex, ArchType archType,
bool transparency, bool foliage);
uint16_t levelPieceId, LevelCelBlock levelCelBlock,
MaskType maskType, uint8_t lightTableIndex);
/**
* @brief Render a black 64x31 tile

101
Source/engine/render/scrollrt.cpp

@ -497,31 +497,98 @@ static void DrawDungeon(const Surface & /*out*/, Point /*tilePosition*/, Point /
void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition)
{
const uint16_t levelPieceId = dPiece[tilePosition.x][tilePosition.y];
MICROS *pMap = &DPieceMicros[levelPieceId];
const MICROS *pMap = &DPieceMicros[levelPieceId];
bool transparency = TileHasAny(levelPieceId, TileProperties::Transparent) && TransList[dTransVal[tilePosition.x][tilePosition.y]];
#ifdef _DEBUG
// Turn transparency off here for debugging
transparency = transparency && (SDL_GetModState() & KMOD_ALT) == 0;
if ((SDL_GetModState() & KMOD_ALT) != 0)
transparency = false;
#endif
const bool foliage = !TileHasAny(levelPieceId, TileProperties::Solid);
for (int i = 0; i < (MicroTileLen / 2); i++) {
const auto getFirstTileMaskLeft = [=](TileType tile) -> MaskType {
if (transparency) {
switch (tile) {
case TileType::LeftTrapezoid:
case TileType::TransparentSquare:
return TileHasAny(levelPieceId, TileProperties::TransparentLeft)
? MaskType::Left
: MaskType::Solid;
case TileType::LeftTriangle:
return MaskType::Solid;
default:
return MaskType::Transparent;
}
}
if (foliage)
return MaskType::LeftFoliage;
return MaskType::Solid;
};
const auto getFirstTileMaskRight = [=](TileType tile) -> MaskType {
if (transparency) {
switch (tile) {
case TileType::RightTrapezoid:
case TileType::TransparentSquare:
return TileHasAny(levelPieceId, TileProperties::TransparentRight)
? MaskType::Right
: MaskType::Solid;
case TileType::RightTriangle:
return MaskType::Solid;
default:
return MaskType::Transparent;
}
}
if (foliage)
return MaskType::RightFoliage;
return MaskType::Solid;
};
// The first micro tile may be rendered with a foliage mask.
// Only `TransparentSquare` tiles are rendered when `foliage` is true.
{
{
const LevelCelBlock levelCelBlock { pMap->mt[0] };
const TileType tileType = levelCelBlock.type();
const MaskType maskType = getFirstTileMaskLeft(tileType);
if (levelCelBlock.hasValue()) {
if (maskType != MaskType::LeftFoliage || tileType == TileType::TransparentSquare) {
RenderTile(out, targetBufferPosition,
levelPieceId, levelCelBlock, maskType, LightTableIndex);
}
}
}
{
const LevelCelBlock levelCelBlock { pMap->mt[1] };
const TileType tileType = levelCelBlock.type();
const MaskType maskType = getFirstTileMaskRight(tileType);
if (levelCelBlock.hasValue()) {
if (transparency || !foliage || levelCelBlock.type() == TileType::TransparentSquare) {
if (maskType != MaskType::RightFoliage || tileType == TileType::TransparentSquare) {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelPieceId, levelCelBlock, maskType, LightTableIndex);
}
}
}
}
targetBufferPosition.y -= TILE_HEIGHT;
}
for (uint_fast8_t i = 2, n = MicroTileLen; i < n; i += 2) {
{
const LevelCelBlock levelCelBlock { pMap->mt[2 * i] };
const LevelCelBlock levelCelBlock { pMap->mt[i] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition,
levelCelBlock, levelPieceId, LightTableIndex,
i == 0 ? ArchType::Left : ArchType::None,
transparency, foliage);
levelPieceId, levelCelBlock,
transparency ? MaskType::Transparent : MaskType::Solid, LightTableIndex);
}
}
{
const LevelCelBlock levelCelBlock { pMap->mt[2 * i + 1] };
const LevelCelBlock levelCelBlock { pMap->mt[i + 1] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelCelBlock, levelPieceId, LightTableIndex,
i == 0 ? ArchType::Right : ArchType::None,
transparency, foliage);
levelPieceId, levelCelBlock,
transparency ? MaskType::Transparent : MaskType::Solid, LightTableIndex);
}
}
targetBufferPosition.y -= TILE_HEIGHT;
@ -543,16 +610,14 @@ void DrawFloor(const Surface &out, Point tilePosition, Point targetBufferPositio
const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[0] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition,
levelCelBlock, levelPieceId, LightTableIndex, ArchType::Left,
/*transparency=*/false, /*foliage=*/false);
levelPieceId, levelCelBlock, MaskType::Solid, LightTableIndex);
}
}
{
const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[1] };
if (levelCelBlock.hasValue()) {
RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 },
levelCelBlock, levelPieceId, LightTableIndex, ArchType::Right,
/*transparency=*/false, /*foliage=*/false);
levelPieceId, levelCelBlock, MaskType::Solid, LightTableIndex);
}
}
}
@ -1031,7 +1096,7 @@ void DrawGame(const Surface &fullOut, Point position)
[](const std::pair<DunRenderType, size_t> &a, const std::pair<DunRenderType, size_t> &b) {
return a.first.maskType == b.first.maskType
? static_cast<uint8_t>(a.first.tileType) < static_cast<uint8_t>(b.first.tileType)
: a.first.maskType < b.first.maskType;
: static_cast<uint8_t>(a.first.maskType) < static_cast<uint8_t>(b.first.maskType);
});
Point pos { 100, 20 };
for (size_t i = 0; i < sortedStats.size(); ++i) {

2
Source/levels/gendung.cpp

@ -34,7 +34,7 @@ bool setlevel;
_setlevels setlvlnum;
dungeon_type setlvltype;
Point ViewPosition;
int MicroTileLen;
uint_fast8_t MicroTileLen;
char TransVal;
bool TransList[256];
uint16_t dPiece[MAXDUNX][MAXDUNY];

2
Source/levels/gendung.h

@ -182,7 +182,7 @@ extern _setlevels setlvlnum;
extern dungeon_type setlvltype;
/** Specifies the player viewpoint X,Y-coordinates of the map. */
extern DVL_API_FOR_TEST Point ViewPosition;
extern int MicroTileLen;
extern uint_fast8_t MicroTileLen;
extern char TransVal;
/** Specifies the active transparency indices. */
extern bool TransList[256];

Loading…
Cancel
Save