Files
EVEngine/src/modules/map/DualGrid.h
T
西风逍遥游 4377e062dd feat: zeroerr parameter validation + Doxygen API documentation
Squashed onto current main. Adds src/engine/common/Assert.h (EV_PARAM_CHECK / EV_ASSERT backed by zeroerr), an EVENGINE_ENABLE_ASSERTS option (non-Debug builds strip ZEROERR_NO_ASSERT unless enabled), parameter checks at key entry points, Doxygen comments across headers, Doxyfile + make docs / CMake docs targets, and Windows setup + code conventions in AGENTS.md.
2026-08-19 09:01:12 +08:00

94 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "map/TileLayer.h"
#include <array>
#include <cstdint>
#include <string>
namespace eve::map {
/**
* @brief Dual-grid autotile (Oskar Stålberg style).
*
* Logic cells are painted on the world grid; display tiles sit on a second grid
* offset by half a step in the active projection, so each display cell samples
* exactly four logic cells (corners). That yields a 4-bit mask → 15 tiles (+ empty).
*
* Works with Orthogonal / Isometric / Staggered / Hexagonal: the corner mask is
* computed in tile-index space; the display layer inherits orientation params and
* receives a projection-correct half-step origin offset.
*
* Tiled does not provide this offset dual-grid workflow natively. Recommended
* authoring path: paint a binary logic tile layer in Tiled (or at runtime), then
* call resolveDualGrid() to fill a display TileLayer. Tiled's Terrain / Wang
* Corner Set is a related but different same-grid matching system.
*/
struct DualGridOptions {
/** @brief 0 = any non-zero logic GID counts as filled; else only this GID. */
int filledGid = 0;
/**
* @brief GID of atlas local id 0 on the display tileset.
* 0 = use display->getTilesetFirstGid() (fallback 1).
*/
int firstDisplayGid = 0;
/** @brief Apply projection-correct half-step origin offset on the display layer. */
bool applyHalfOffset = true;
/** @brief Hide the logic layer after resolve (logic stays for gameplay queries). */
bool hideLogic = true;
/**
* @brief When true, use the default SpriteCook-style 4x4 atlas frame table.
* When false, GID = firstDisplayGid + mask (mask 0 → empty).
*/
bool useDefaultFrameTable = true;
};
/** @brief Pack four corner occupancy bits: TL=1, TR=2, BL=4, BR=8. */
inline int dualGridMaskFromCorners(bool tl, bool tr, bool bl, bool br) {
return (tl ? 1 : 0) | (tr ? 2 : 0) | (bl ? 4 : 0) | (br ? 8 : 0);
}
/**
* @brief Default 4x4 atlas frame index for mask 0..15.
* -1 means draw nothing. Matches the SpriteCook / common dual-grid sheet layout.
*/
int dualGridDefaultFrame(int mask);
/** @brief Copy of the default frame table (16 entries). */
const std::array<int, 16> &dualGridDefaultFrameTable();
/**
* @brief Half-step origin delta for the display layer (added to logic origin).
* Orthogonal: (-tileW/2, -tileH/2)
* Isometric: (0, -tileH/2) — equivalent to logic coords (tx-0.5, ty-0.5)
* Staggered/Hex Y: (-tileW/2, -pitchY/2)
* Staggered/Hex X: (-pitchX/2, -tileH/2)
*/
void dualGridHalfOffset(const TileLayer::Config &cfg, float &offX, float &offY);
/** @brief Whether logic cell (tx,ty) is filled under options. Out of bounds → false. */
bool dualGridLogicFilled(TileLayer &logic, int tx, int ty, int filledGid);
/**
* @brief 4-bit corner mask for display cell (dx,dy) on a (logicW+1)×(logicH+1) grid.
* Samples logic (dx-1,dy-1), (dx,dy-1), (dx-1,dy), (dx,dy) in index space
* (orientation-independent topology).
*/
int dualGridMaskAt(TileLayer &logic, int dx, int dy, int filledGid = 0);
/**
* @brief Resolve logic → display dual-grid tiles.
* Resizes display to (logicW+1)×(logicH+1), copies tile size / orientation /
* stagger / hex from logic, optionally applies projection-correct half-step
* origin offset, writes GIDs.
* Returns false and sets error on invalid args.
*/
bool resolveDualGrid(TileLayer *logic, TileLayer *display, const DualGridOptions &opts,
std::string *error = nullptr);
/** @brief Convenience: any non-zero filled, default frame table, half offset, hide logic. */
bool resolveDualGrid(TileLayer *logic, TileLayer *display, std::string *error = nullptr);
} // namespace eve::map