载入中...
搜索中...
未找到
Map.cpp
浏览该文件的文档.
1#include "map/Map.h"
2
3#include "common/Capability.h"
4#include "common/Module.h"
6#include "graphics/Graphics.h"
9#include "map/DualGrid.h"
10#include "map/FlowField.h"
11#include "map/Fov.h"
13#include "map/Path.h"
14#include "map/Pathfinder.h"
15#include "map/TileConfig.h"
16#include "map/TileSystem.h"
17
18#include <simplesquirrel/simplesquirrel.hpp>
19
20#include <algorithm>
21#include <cmath>
22#include <iterator>
23
24namespace eve::map {
25namespace {
26
27void retireReplacedLayers(const std::vector<TileLayer *> &previous,
28 const std::vector<TileLayer *> &replacement) {
29 for (TileLayer *layer : previous) {
30 if (!layer || std::find(replacement.begin(), replacement.end(), layer) != replacement.end())
31 continue;
32 layer->clear();
33 layer->setVisible(false);
34 }
35}
36
37void discardCandidateLayers(const std::vector<TileLayer *> &layers) {
38 for (TileLayer *layer : layers) {
39 if (!layer) continue;
40 layer->clear();
41 layer->setVisible(false);
42 }
43}
44
45} // namespace
46
48
50
51TileLayer *Map::newLayer(int mapW, int mapH, float tileW, float tileH) {
52 return TileLayer::createLayer(mapW, mapH, tileW, tileH);
53}
54
56 if (!layer) return nullptr;
57 return new Pathfinder(layer);
58}
59
60Pathfinder *Map::newPathfinderSize(int mapW, int mapH) {
61 if (mapW <= 0 || mapH <= 0) return nullptr;
62 return new Pathfinder(mapW, mapH);
63}
64
66 if (!layer) return nullptr;
67 return new Fov(layer);
68}
69
70Fov *Map::newFovSize(int mapW, int mapH) {
71 if (mapW <= 0 || mapH <= 0) return nullptr;
72 return new Fov(mapW, mapH);
73}
74
75Fov *Map::newFovVolume(int mapW, int mapH, int depth) {
76 if (mapW <= 0 || mapH <= 0 || depth <= 0) return nullptr;
77 return new Fov(mapW, mapH, depth);
78}
79
80TileLayer *Map::newLayerFromFile(const std::string &path) {
81 std::vector<MapObject> objs;
82 auto layers = loadMapFile(path, &objs, nullptr);
83 if (layers.empty()) return nullptr;
84 retireReplacedLayers(loadedLayers_, layers);
85 setObjects(std::move(objs));
86 loadedLayers_ = std::move(layers);
87 return loadedLayers_.front();
88}
89
90int Map::loadFromFile(const std::string &path) {
91 std::vector<MapObject> objs;
92 auto layers = loadMapFile(path, &objs, nullptr);
93 if (layers.empty()) return 0;
94 retireReplacedLayers(loadedLayers_, layers);
95 setObjects(std::move(objs));
96 loadedLayers_ = std::move(layers);
97 return int(loadedLayers_.size());
98}
99
100void Map::update(float dt) {
103}
104
106 if (!gfx) return;
107 std::vector<graphics::DrawItem2D> items;
109 TileRenderSystem::collect(items, gfx->getWidth(), gfx->getHeight());
110 graphics::RenderSystem::drawItems(*gfx, items, false);
111}
112
114
120
122 collisionRects_.clear();
123 if (!layer) return 0;
124 const auto config = layer->config();
125 const auto tiles = layer->tiles();
126 const auto tileset = layer->tileset();
127 if (config->orientation != MapOrientation::Orthogonal) return 0;
128
129 std::vector<uint8_t> solid(size_t(config->mapW * config->mapH), 0);
130 for (int y = 0; y < config->mapH; ++y) {
131 for (int x = 0; x < config->mapW; ++x) {
132 const int gid = int(tileGid(tiles->gids[size_t(y * config->mapW + x)]));
133 const auto it = std::find_if(tileset->visuals.begin(), tileset->visuals.end(),
134 [gid](const auto &v) { return v.gid == gid; });
135 if (gid != 0 && it != tileset->visuals.end() && !it->collisionShapes.empty()) {
136 const float originX = config->originX + x * (config->tileW + config->cellGapX);
137 const float originY = config->originY + y * (config->tileH + config->cellGapY);
138 for (const auto &shape : it->collisionShapes)
139 collisionRects_.push_back({originX + shape.x, originY + shape.y, shape.width, shape.height});
140 } else {
141 solid[size_t(y * config->mapW + x)] = gid != 0 && it != tileset->visuals.end() && !it->walkable;
142 }
143 }
144 }
145 for (int y = 0; y < config->mapH; ++y) {
146 for (int x = 0; x < config->mapW; ++x) {
147 if (!solid[size_t(y * config->mapW + x)]) continue;
148 int width = 1;
149 while (x + width < config->mapW && solid[size_t(y * config->mapW + x + width)])
150 ++width;
151 int height = 1;
152 bool canGrow = true;
153 while (y + height < config->mapH && canGrow) {
154 for (int dx = 0; dx < width; ++dx)
155 if (!solid[size_t((y + height) * config->mapW + x + dx)]) canGrow = false;
156 if (canGrow) ++height;
157 }
158 for (int dy = 0; dy < height; ++dy)
159 for (int dx = 0; dx < width; ++dx)
160 solid[size_t((y + dy) * config->mapW + x + dx)] = 0;
161 collisionRects_.push_back({config->originX + x * (config->tileW + config->cellGapX),
162 config->originY + y * (config->tileH + config->cellGapY),
163 width * (config->tileW + config->cellGapX),
164 height * (config->tileH + config->cellGapY)});
165 }
166 }
167 cap::forEach<ITileCollisionSink>([&](ITileCollisionSink *sink) {
168 sink->replaceTileCollision(layer, collisionRects_.data(), collisionRects_.size());
169 });
170 return int(collisionRects_.size());
171}
172
173int Map::getCollisionRectCount() const { return int(collisionRects_.size()); }
174float Map::getCollisionRectX(int index) const {
175 return index >= 0 && index < int(collisionRects_.size())
176 ? collisionRects_[size_t(index)].x
177 : 0.f;
178}
179float Map::getCollisionRectY(int index) const {
180 return index >= 0 && index < int(collisionRects_.size())
181 ? collisionRects_[size_t(index)].y
182 : 0.f;
183}
184float Map::getCollisionRectWidth(int index) const {
185 return index >= 0 && index < int(collisionRects_.size())
186 ? collisionRects_[size_t(index)].width
187 : 0.f;
188}
189float Map::getCollisionRectHeight(int index) const {
190 return index >= 0 && index < int(collisionRects_.size())
191 ? collisionRects_[size_t(index)].height
192 : 0.f;
193}
194
195int Map::getLayerCount() const {
196 if (ecs::current()->getManager<TileLayer>() == nullptr) return 0;
197 int n = 0;
198 auto view = ecs::View<TileLayer, TileLayer::Config>();
199 for (auto it = view.begin(); it != view.end(); ++it) ++n;
200 return n;
201}
202
203TileLayer *Map::getLayer(int index) const {
204 if (index < 0 || index >= int(loadedLayers_.size())) return nullptr;
205 return loadedLayers_[size_t(index)];
206}
207
208void Map::setObjects(std::vector<MapObject> objects) { objects_ = std::move(objects); }
209
210int Map::getObjectCount() const { return int(objects_.size()); }
211
212std::string Map::getObjectName(int i) const {
213 if (i < 0 || i >= int(objects_.size())) return {};
214 return objects_[size_t(i)].name;
215}
216
217std::string Map::getObjectType(int i) const {
218 if (i < 0 || i >= int(objects_.size())) return {};
219 return objects_[size_t(i)].type;
220}
221
222float Map::getObjectX(int i) const {
223 if (i < 0 || i >= int(objects_.size())) return 0.f;
224 return objects_[size_t(i)].x;
225}
226
227float Map::getObjectY(int i) const {
228 if (i < 0 || i >= int(objects_.size())) return 0.f;
229 return objects_[size_t(i)].y;
230}
231
232float Map::getObjectWidth(int i) const {
233 if (i < 0 || i >= int(objects_.size())) return 0.f;
234 return objects_[size_t(i)].width;
235}
236
237float Map::getObjectHeight(int i) const {
238 if (i < 0 || i >= int(objects_.size())) return 0.f;
239 return objects_[size_t(i)].height;
240}
241
242int Map::getObjectGid(int i) const {
243 if (i < 0 || i >= int(objects_.size())) return 0;
244 return int(objects_[size_t(i)].gid);
245}
246
247eve::Result<int> Map::loadFromFileWithObjectContract(const std::string &path,
248 std::string_view contractJson) {
249 std::vector<MapObject> objects;
250 std::string error;
251 auto layers = loadMapFile(path, &objects, &error);
252 if (layers.empty()) {
254 eve::DiagnosticCode::ParseError, error.empty() ? "map could not be loaded" : error, path, {},
255 "map.load"));
256 }
257 auto admitted = validateMapObjects(objects, contractJson);
258 if (!admitted.ok()) {
259 discardCandidateLayers(layers);
260 return eve::Result<int>::failure(admitted.status());
261 }
262 retireReplacedLayers(loadedLayers_, layers);
263 setObjects(std::move(objects));
264 loadedLayers_ = std::move(layers);
265 return eve::Result<int>::success(static_cast<int>(loadedLayers_.size()),
267}
268
269eve::Result<int> Map::loadFromTextWithObjectContract(std::string_view mapJson,
270 std::string_view contractJson) {
271 std::vector<MapObject> objects;
272 std::string error;
273 auto layers = loadMapText(std::string(mapJson), &objects, &error);
274 if (layers.empty()) {
276 eve::DiagnosticCode::ParseError, error.empty() ? "map text could not be loaded" : error,
277 "$map", {}, "map.load"));
278 }
279 auto admitted = validateMapObjects(objects, contractJson);
280 if (!admitted.ok()) {
281 discardCandidateLayers(layers);
282 return eve::Result<int>::failure(admitted.status());
283 }
284 retireReplacedLayers(loadedLayers_, layers);
285 setObjects(std::move(objects));
286 loadedLayers_ = std::move(layers);
287 return eve::Result<int>::success(static_cast<int>(loadedLayers_.size()),
289}
290
291int Map::getObjectPropertyCount(int objectIndex) const {
292 if (objectIndex < 0 || objectIndex >= int(objects_.size())) return 0;
293 return int(objects_[size_t(objectIndex)].properties.size());
294}
295
296std::string Map::getObjectPropertyName(int objectIndex, int propertyIndex) const {
297 if (objectIndex < 0 || objectIndex >= int(objects_.size()) || propertyIndex < 0) return {};
298 const auto &properties = objects_[size_t(objectIndex)].properties;
299 if (propertyIndex >= int(properties.size())) return {};
300 auto it = properties.begin();
301 std::advance(it, propertyIndex);
302 return it->first;
303}
304
305bool Map::hasObjectProperty(int objectIndex, std::string_view name) const {
306 if (objectIndex < 0 || objectIndex >= int(objects_.size())) return false;
307 return objects_[size_t(objectIndex)].properties.contains(std::string(name));
308}
309
310std::string Map::getObjectProperty(int objectIndex, std::string_view name, std::string defaultValue) const {
311 if (objectIndex < 0 || objectIndex >= int(objects_.size())) return defaultValue;
312 const auto &properties = objects_[size_t(objectIndex)].properties;
313 auto it = properties.find(std::string(name));
314 return it == properties.end() ? defaultValue : it->second;
315}
316
317std::optional<std::size_t> Map::findObjectByName(std::string_view name) const {
318 for (std::size_t index = 0; index < objects_.size(); ++index)
319 if (objects_[index].name == name) return index;
320 return std::nullopt;
321}
322
323std::optional<std::size_t> Map::findObjectAt(float x, float y, std::string_view type) const {
324 if (!std::isfinite(x) || !std::isfinite(y)) return std::nullopt;
325 for (std::size_t index = 0; index < objects_.size(); ++index) {
326 const MapObject &object = objects_[index];
327 if (!type.empty() && object.type != type) continue;
328 const bool point = object.width <= 0.f && object.height <= 0.f;
329 if (point ? (object.x == x && object.y == y)
330 : (x >= object.x && y >= object.y && x <= object.x + std::max(0.f, object.width) &&
331 y <= object.y + std::max(0.f, object.height)))
332 return index;
333 }
334 return std::nullopt;
335}
336
337bool Map::resolveDualGrid(TileLayer *logic, TileLayer *display) {
338 DualGridOptions opts;
339 const bool ok = eve::map::resolveDualGrid(logic, display, opts, &dualGridError_);
340 return ok;
341}
342
343bool Map::resolveDualGridFilled(TileLayer *logic, TileLayer *display, int filledGid) {
344 DualGridOptions opts;
345 opts.filledGid = filledGid;
346 const bool ok = eve::map::resolveDualGrid(logic, display, opts, &dualGridError_);
347 return ok;
348}
349
350int Map::dualGridMaskAt(TileLayer *logic, int dx, int dy, int filledGid) {
351 if (!logic) return 0;
352 return eve::map::dualGridMaskAt(*logic, dx, dy, filledGid);
353}
354
355int Map::dualGridFrame(int mask) { return dualGridDefaultFrame(mask); }
356
357float Map::dualGridOffsetX(TileLayer *logic) {
358 if (!logic) return 0.f;
359 float ox = 0.f, oy = 0.f;
360 dualGridHalfOffset(*logic->config(), ox, oy);
361 return ox;
362}
363
364float Map::dualGridOffsetY(TileLayer *logic) {
365 if (!logic) return 0.f;
366 float ox = 0.f, oy = 0.f;
367 dualGridHalfOffset(*logic->config(), ox, oy);
368 return oy;
369}
370
371std::string Map::lastDualGridError() const { return dualGridError_; }
372
373void Map::expose(ssq::Table &table) {
374 auto cls = table.addClass(name, Map::create, false);
375 expose(cls);
376
377 auto layer = table.addClass<TileLayer>(
378 "TileLayer", std::function<TileLayer *()>([]() -> TileLayer * { return nullptr; }), true);
379 layer.addFunc("setOrigin", &TileLayer::setOrigin);
380 layer.addFunc("getX", &TileLayer::getX);
381 layer.addFunc("getY", &TileLayer::getY);
382 layer.addFunc("getMapWidth", &TileLayer::getMapWidth);
383 layer.addFunc("getMapHeight", &TileLayer::getMapHeight);
384 layer.addFunc("getTileWidth", &TileLayer::getTileWidth);
385 layer.addFunc("getTileHeight", &TileLayer::getTileHeight);
386 layer.addFunc("setTileSize", &TileLayer::setTileSize);
387 layer.addFunc("setCellGap", &TileLayer::setCellGap);
388 layer.addFunc("setRenderSpacing", &TileLayer::setRenderSpacing);
389 layer.addFunc("getCellGapX", &TileLayer::getCellGapX);
390 layer.addFunc("getCellGapY", &TileLayer::getCellGapY);
391 layer.addFunc("getRenderSpacingX", &TileLayer::getRenderSpacingX);
392 layer.addFunc("getRenderSpacingY", &TileLayer::getRenderSpacingY);
393 layer.addFunc("setVisualScale", &TileLayer::setVisualScale);
394 layer.addFunc("getVisualScaleX", &TileLayer::getVisualScaleX);
395 layer.addFunc("getVisualScaleY", &TileLayer::getVisualScaleY);
396 layer.addFunc("resize", &TileLayer::resize);
397 layer.addFunc("setTile", &TileLayer::setTile);
398 layer.addFunc("getTile", &TileLayer::getTile);
399 layer.addFunc("fillRect", &TileLayer::fillRect);
400 layer.addFunc("fill", &TileLayer::fill);
401 layer.addFunc("clear", &TileLayer::clear);
402 layer.addFunc("getRevision", &TileLayer::getRevision);
403 layer.addFunc("getChunkSize", &TileLayer::getChunkSize);
404 layer.addFunc("getChunkCount", &TileLayer::getChunkCount);
405 layer.addFunc("getNonEmptyChunkCount", &TileLayer::getNonEmptyChunkCount);
406 layer.addFunc("clearTileAnimation", &TileLayer::clearTileAnimation);
407 layer.addFunc("addTileAnimationFrame", &TileLayer::addTileAnimationFrame);
408 layer.addFunc("getTileAnimationFrameCount", &TileLayer::getTileAnimationFrameCount);
409 layer.addFunc("setTileDataString", &TileLayer::setTileDataString);
410 layer.addFunc("setTileDataNumber", &TileLayer::setTileDataNumber);
411 layer.addFunc("setTileDataBool", &TileLayer::setTileDataBool);
412 layer.addFunc("getTileDataType", &TileLayer::getTileDataType);
413 layer.addFunc("getTileDataString", &TileLayer::getTileDataString);
414 layer.addFunc("getTileDataNumber", &TileLayer::getTileDataNumber);
415 layer.addFunc("getTileDataBool", &TileLayer::getTileDataBool);
416 layer.addFunc("setTerrainRule", &TileLayer::setTerrainRule);
417 layer.addFunc("defineAutotileFamily", &TileLayer::defineAutotileFamily);
418 layer.addFunc("setAutotileRule", &TileLayer::setAutotileRule);
419 layer.addFunc("clearTerrainRules", &TileLayer::clearTerrainRules);
420 layer.addFunc("paintTerrain", &TileLayer::paintTerrain);
421 layer.addFunc("paintTerrainRect", &TileLayer::paintTerrainRect);
422 layer.addFunc("fillTerrain", &TileLayer::fillTerrain);
423 layer.addFunc("eraseTerrainRect", &TileLayer::eraseTerrainRect);
424 layer.addFunc("getTerrain", &TileLayer::getTerrain);
425 layer.addFunc("setTileset", &TileLayer::setTileset);
426 layer.addFunc("setTilesetTileSize", &TileLayer::setTilesetTileSize);
427 layer.addFunc("setTileVisual", &TileLayer::setTileVisual);
428 layer.addFunc("clearTileVisuals", &TileLayer::clearTileVisuals);
429 layer.addFunc("getTileVisualCount", &TileLayer::getTileVisualCount);
430 layer.addFunc("setTileMetadata", &TileLayer::setTileMetadata);
431 layer.addFunc("setTileNavigationProfile", &TileLayer::setTileNavigationProfile);
432 layer.addFunc("loadTilesetManifest", &TileLayer::loadTilesetManifest);
433 layer.addFunc("getTilesetTexture", &TileLayer::getTilesetTexture);
434 layer.addFunc("getTilesetFirstGid", &TileLayer::getTilesetFirstGid);
435 layer.addFunc("getTilesetColumns", &TileLayer::getTilesetColumns);
436 layer.addFunc("setCanvas", &TileLayer::setCanvas);
437 layer.addFunc("setCamera", &TileLayer::setCamera);
438 layer.addFunc("setLayer", &TileLayer::setLayer);
439 layer.addFunc("getLayer", &TileLayer::getLayer);
440 layer.addFunc("setVisible", &TileLayer::setVisible);
441 layer.addFunc("isVisible", &TileLayer::isVisible);
442 layer.addFunc("setReceiveLight", &TileLayer::setReceiveLight);
443 layer.addFunc("getReceiveLight", &TileLayer::getReceiveLight);
444 layer.addFunc("setTint", &TileLayer::setTint);
445 layer.addFunc("applyConfig", &TileLayer::applyConfig);
446 layer.addFunc("loadConfig", &TileLayer::loadConfig);
447 layer.addFunc("reloadConfig", &TileLayer::reloadConfig);
448 layer.addFunc("setAutoReload", &TileLayer::setAutoReload);
449 layer.addFunc("getAutoReload", &TileLayer::getAutoReload);
450 layer.addFunc("getConfigPath", &TileLayer::getConfigPath);
451 layer.addFunc("tileToWorldX", &TileLayer::tileToWorldX);
452 layer.addFunc("tileToWorldY", &TileLayer::tileToWorldY);
453 layer.addFunc("depthYAt", &TileLayer::depthYAt);
454 layer.addFunc("worldToTileX", &TileLayer::worldToTileX);
455 layer.addFunc("worldToTileY", &TileLayer::worldToTileY);
456
457 auto path = table.addClass<Path>(
458 "Path", std::function<Path *()>([]() -> Path * { return nullptr; }), true);
459 path.addFunc("getLength", &Path::getLength);
460 path.addFunc("getX", &Path::getX);
461 path.addFunc("getY", &Path::getY);
462 path.addFunc("getTotalCost", &Path::getTotalCost);
463
464 auto field = table.addClass<FlowField>(
465 "FlowField", std::function<FlowField *()>([]() -> FlowField * { return nullptr; }), true);
466 field.addFunc("getWidth", &FlowField::getWidth);
467 field.addFunc("getHeight", &FlowField::getHeight);
468 field.addFunc("getGoalX", &FlowField::getGoalX);
469 field.addFunc("getGoalY", &FlowField::getGoalY);
470 field.addFunc("costAt", &FlowField::costAt);
471 field.addFunc("nextX", &FlowField::nextX);
472 field.addFunc("nextY", &FlowField::nextY);
473 field.addFunc("isReachable", &FlowField::isReachable);
474
475 auto pf = table.addClass<Pathfinder>(
476 "Pathfinder", std::function<Pathfinder *()>([]() -> Pathfinder * { return nullptr; }), true);
477 pf.addFunc("setTopology", &Pathfinder::setTopology);
478 pf.addFunc("getTopology", &Pathfinder::getTopology);
479 pf.addFunc("setDiagonal", &Pathfinder::setDiagonal);
480 pf.addFunc("getDiagonal", &Pathfinder::getDiagonal);
481 pf.addFunc("blockGid", &Pathfinder::blockGid);
482 pf.addFunc("unblockGid", &Pathfinder::unblockGid);
483 pf.addFunc("clearBlockedGids", &Pathfinder::clearBlockedGids);
484 pf.addFunc("setBlockEmpty", &Pathfinder::setBlockEmpty);
485 pf.addFunc("getBlockEmpty", &Pathfinder::getBlockEmpty);
486 pf.addFunc("setBlocked", &Pathfinder::setBlocked);
487 pf.addFunc("isWalkable", &Pathfinder::isWalkable);
488 pf.addFunc("setCellCost", &Pathfinder::setCellCost);
489 pf.addFunc("getCellCost", &Pathfinder::getCellCost);
490 pf.addFunc("syncFromLayer", &Pathfinder::syncFromLayer);
491 pf.addFunc("findPath", static_cast<Path *(Pathfinder::*)(int, int, int, int)>(&Pathfinder::findPath));
492 pf.addFunc("buildFlowField", &Pathfinder::buildFlowField);
493 pf.addFunc("followFlow", &Pathfinder::followFlow);
494 pf.addFunc("findGroupPath", &Pathfinder::findGroupPath);
495 pf.addFunc("invalidateCache", &Pathfinder::invalidateCache);
496
497 auto fov = table.addClass<Fov>("Fov", std::function<Fov *()>([]() -> Fov * { return nullptr; }),
498 true);
499 fov.addFunc("getWidth", &Fov::getWidth);
500 fov.addFunc("getHeight", &Fov::getHeight);
501 fov.addFunc("getDepth", &Fov::getDepth);
502 fov.addFunc("setMode", &Fov::setMode);
503 fov.addFunc("getMode", &Fov::getMode);
504 fov.addFunc("setAlgorithm", &Fov::setAlgorithm);
505 fov.addFunc("getAlgorithm", &Fov::getAlgorithm);
506 fov.addFunc("setRadiusMetric", &Fov::setRadiusMetric);
507 fov.addFunc("getRadiusMetric", &Fov::getRadiusMetric);
508 fov.addFunc("setTopology", &Fov::setTopology);
509 fov.addFunc("getTopology", &Fov::getTopology);
510 fov.addFunc("setCornerPeek", &Fov::setCornerPeek);
511 fov.addFunc("getCornerPeek", &Fov::getCornerPeek);
512 fov.addFunc("blockOpaqueGid", &Fov::blockOpaqueGid);
513 fov.addFunc("unblockOpaqueGid", &Fov::unblockOpaqueGid);
514 fov.addFunc("clearOpaqueGids", &Fov::clearOpaqueGids);
515 fov.addFunc("setBlockEmpty", &Fov::setBlockEmpty);
516 fov.addFunc("getBlockEmpty", &Fov::getBlockEmpty);
517 fov.addFunc("setOpaque", &Fov::setOpaque);
518 fov.addFunc("isOpaque", &Fov::isOpaque);
519 fov.addFunc("setOpaque3", &Fov::setOpaque3);
520 fov.addFunc("isOpaque3", &Fov::isOpaque3);
521 fov.addFunc("syncFromLayer", &Fov::syncFromLayer);
522 fov.addFunc("setElevation", &Fov::setElevation);
523 fov.addFunc("getElevation", &Fov::getElevation);
524 fov.addFunc("setCliffBlock", &Fov::setCliffBlock);
525 fov.addFunc("getCliffBlock", &Fov::getCliffBlock);
526 fov.addFunc("setEyeOffset", &Fov::setEyeOffset);
527 fov.addFunc("getEyeOffset", &Fov::getEyeOffset);
528 fov.addFunc("setVerticalRange", &Fov::setVerticalRange);
529 fov.addFunc("getVerticalRange", &Fov::getVerticalRange);
530 fov.addFunc("addRevealer", &Fov::addRevealer);
531 fov.addFunc("addRevealer3", &Fov::addRevealer3);
532 fov.addFunc("removeRevealer", &Fov::removeRevealer);
533 fov.addFunc("clearRevealers", &Fov::clearRevealers);
534 fov.addFunc("setRevealerPosition", &Fov::setRevealerPosition);
535 fov.addFunc("setRevealerPosition3", &Fov::setRevealerPosition3);
536 fov.addFunc("setRevealerRadius", &Fov::setRevealerRadius);
537 fov.addFunc("setRevealerFacing", &Fov::setRevealerFacing);
538 fov.addFunc("clearRevealerFacing", &Fov::clearRevealerFacing);
539 fov.addFunc("setRevealerEnabled", &Fov::setRevealerEnabled);
540 fov.addFunc("getRevealerCount", &Fov::getRevealerCount);
541 fov.addFunc("setRevealerPerception", &Fov::setRevealerPerception);
542 fov.addFunc("getRevealerPerception", &Fov::getRevealerPerception);
543 fov.addFunc("setPerceptionRadiusScale", &Fov::setPerceptionRadiusScale);
544 fov.addFunc("getPerceptionRadiusScale", &Fov::getPerceptionRadiusScale);
545 fov.addFunc("setDetectionMargin", &Fov::setDetectionMargin);
546 fov.addFunc("getDetectionMargin", &Fov::getDetectionMargin);
547 fov.addFunc("getEffectiveRadius", &Fov::getEffectiveRadius);
548 fov.addFunc("canDetect", &Fov::canDetect);
549 fov.addFunc("canDetect3", &Fov::canDetect3);
550 fov.addFunc("markDirty", &Fov::markDirty);
551 fov.addFunc("isDirty", &Fov::isDirty);
552 fov.addFunc("compute", &Fov::compute);
553 fov.addFunc("isVisible", &Fov::isVisible);
554 fov.addFunc("isExplored", &Fov::isExplored);
555 fov.addFunc("isVisible3", &Fov::isVisible3);
556 fov.addFunc("isExplored3", &Fov::isExplored3);
557 fov.addFunc("getState", &Fov::getState);
558 fov.addFunc("getState3", &Fov::getState3);
559 fov.addFunc("clearMemory", &Fov::clearMemory);
560 fov.addFunc("resetVisibleOnly", &Fov::resetVisibleOnly);
561 fov.addFunc("getMaskValue", &Fov::getMaskValue);
562 fov.addFunc("getMaskByte", &Fov::getMaskByte);
563 fov.addFunc("getMaskValue3", &Fov::getMaskValue3);
564 fov.addFunc("getMaskByte3", &Fov::getMaskByte3);
565 fov.addFunc("buildMaskTexture", &Fov::buildMaskTexture);
566 fov.addFunc("buildMaskTextureSlice", &Fov::buildMaskTextureSlice);
567}
568
569void Map::expose(ssq::Class &cls) {
570 const HSQUIRRELVM vm = cls.getHandle();
571 cls.addFunc("getName", &Map::getName);
572 cls.addFunc("newLayer", &Map::newLayer);
573 cls.addFunc("newLayerFromFile", &Map::newLayerFromFile);
574 cls.addFunc("loadFromFile", &Map::loadFromFile);
575 cls.addFunc("loadFromFileWithObjectContract",
576 [vm](Map *value, const std::string &path, const std::string &contractJson) {
577 if (!value)
580 eve::DiagnosticCode::InvalidArgument, "Map receiver must not be null", "map",
581 {}, "map.squirrel")),
582 [](int count) { return eve::Value(count); });
584 value->loadFromFileWithObjectContract(path, contractJson),
585 [](int count) { return eve::Value(count); });
586 });
587 cls.addFunc("newPathfinder", &Map::newPathfinder);
588 cls.addFunc("newPathfinderSize", &Map::newPathfinderSize);
589 cls.addFunc("newFov", &Map::newFov);
590 cls.addFunc("newFovSize", &Map::newFovSize);
591 cls.addFunc("newFovVolume", &Map::newFovVolume);
592 cls.addFunc("update", &Map::update);
593 cls.addFunc("render", &Map::render);
594 cls.addFunc("pollConfigs", &Map::pollConfigs);
595 cls.addFunc("getLastVisibleTileCount", &Map::getLastVisibleTileCount);
596 cls.addFunc("getLastCustomVisualCount", &Map::getLastCustomVisualCount);
597 cls.addFunc("getLastAtlasCount", &Map::getLastAtlasCount);
598 cls.addFunc("getLastVisitedChunkCount", &Map::getLastVisitedChunkCount);
599 cls.addFunc("getLastVisitedCellCount", &Map::getLastVisitedCellCount);
600 cls.addFunc("publishCollision", &Map::publishCollision);
601 cls.addFunc("getCollisionRectCount", &Map::getCollisionRectCount);
602 cls.addFunc("getCollisionRectX", &Map::getCollisionRectX);
603 cls.addFunc("getCollisionRectY", &Map::getCollisionRectY);
604 cls.addFunc("getCollisionRectWidth", &Map::getCollisionRectWidth);
605 cls.addFunc("getCollisionRectHeight", &Map::getCollisionRectHeight);
606 cls.addFunc("getLayerCount", &Map::getLayerCount);
607 cls.addFunc("getLayer", &Map::getLayer);
608 cls.addFunc("getObjectCount", &Map::getObjectCount);
609 cls.addFunc("getObjectName", &Map::getObjectName);
610 cls.addFunc("getObjectType", &Map::getObjectType);
611 cls.addFunc("getObjectX", &Map::getObjectX);
612 cls.addFunc("getObjectY", &Map::getObjectY);
613 cls.addFunc("getObjectWidth", &Map::getObjectWidth);
614 cls.addFunc("getObjectHeight", &Map::getObjectHeight);
615 cls.addFunc("getObjectGid", &Map::getObjectGid);
616 cls.addFunc("getObjectPropertyCount", &Map::getObjectPropertyCount);
617 cls.addFunc("getObjectPropertyName", &Map::getObjectPropertyName);
618 cls.addFunc("hasObjectProperty", [](Map *self, int objectIndex, const std::string &name) {
619 return self && self->hasObjectProperty(objectIndex, name);
620 });
621 cls.addFunc("getObjectProperty",
622 [](Map *self, int objectIndex, const std::string &name, const std::string &defaultValue) {
623 return self ? self->getObjectProperty(objectIndex, name, defaultValue) : defaultValue;
624 });
625 cls.addFunc("findObjectByName", [](Map *value, const std::string &name) -> int {
626 if (!value) return -1;
627 const auto found = value->findObjectByName(name);
628 return found ? static_cast<int>(*found) : -1;
629 });
630 cls.addFunc("findObjectAt", [](Map *value, float x, float y, const std::string &type) -> int {
631 if (!value) return -1;
632 const auto found = value->findObjectAt(x, y, type);
633 return found ? static_cast<int>(*found) : -1;
634 });
635 cls.addFunc("resolveDualGrid", &Map::resolveDualGrid);
636 cls.addFunc("resolveDualGridFilled", &Map::resolveDualGridFilled);
637 cls.addFunc("dualGridMaskAt", &Map::dualGridMaskAt);
638 cls.addFunc("dualGridFrame", &Map::dualGridFrame);
639 cls.addFunc("dualGridOffsetX", &Map::dualGridOffsetX);
640 cls.addFunc("dualGridOffsetY", &Map::dualGridOffsetY);
641 cls.addFunc("lastDualGridError", &Map::lastDualGridError);
642}
643
644} // namespace eve::map
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
int mask
struct SQVM * HSQUIRRELVM
HSQUIRRELVM vm
Definition ECS.cpp:20
HSQOBJECT cls
Definition ECS.cpp:21
ShaderImageInput shape
glm::vec3 n
Definition Grass.cpp:63
float v
std::uint32_t height
std::uint32_t width
std::map< std::string, PropertyRule > properties
std::string name
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:26
graphics::Canvas * previous
std::string error
Definition Package.cpp:60
TileLayer * layer
std::string path
Definition PlayHost.cpp:110
glm::mat4 view
bool found
float dy
float dx
std::uint32_t count
The single Squirrel projection for common Result, Status and Value.
int tileW
int tileH
uint32_t index
std::uint32_t depth
double oy
double ox
glm::vec3 point
std::vector< WfcTile > tiles
Definition WfcSimple.cpp:22
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
int getWidth() const
Returns the width.
Definition Graphics.h:502
int getHeight() const
Returns the height.
Definition Graphics.h:504
static void collectSprites(std::vector< DrawItem2D > &out)
Append visible Renderable2D sprites into a shared queue.
static void drawItems(Graphics &gfx, std::vector< DrawItem2D > &items, bool present)
Sort and draw items. If present=true, calls gfx.present() at the end. Map::render uses present=false ...
Dynamic field-of-view / fog-of-war facade. Phase A: 2D shadowcast + multi-revealer + explored memory....
Definition Fov.h:27
Map module — factory + script binding for 2D tilemaps. Per-frame: TileConfigSystem (hot reload) → uni...
Definition Map.h:30
TileLayer * newLayerFromFile(const std::string &path)
Load map JSON (Tiled-compatible subset or EVEngine simplified format). Creates one TileLayer per tile...
Definition Map.cpp:80
void setObjects(std::vector< MapObject > objects)
Replace object cache (used by load / hot reload).
Definition Map.cpp:208
void update(float dt)
Updates .
Definition Map.cpp:100
int loadFromFile(const std::string &path)
Same transactional replacement as newLayerFromFile, returning the published layer count.
Definition Map.cpp:90
Pathfinder * newPathfinderSize(int mapW, int mapH)
Custom grid pathfinder (no layer); fill with setBlocked / setCellCost.
Definition Map.cpp:60
int getLastCustomVisualCount() const
Returns the last custom visual count.
Definition Map.cpp:116
int getLastVisitedChunkCount() const
Returns the last visited chunk count.
Definition Map.cpp:118
int getLastAtlasCount() const
Returns the last atlas count.
Definition Map.cpp:117
Pathfinder * newPathfinder(TileLayer *layer)
Pathfinder bound to a TileLayer (syncs walkability from GIDs).
Definition Map.cpp:55
Fov * newFovVolume(int mapW, int mapH, int depth)
Volume FOV (W×H×D voxels); mode defaults to volume.
Definition Map.cpp:75
TileLayer * newLayer(int mapW, int mapH, float tileW=32.f, float tileH=32.f)
Creates a layer. @ownership Caller deletes unless documented otherwise.
Definition Map.cpp:51
Fov * newFovSize(int mapW, int mapH)
Custom grid FOV (no layer); fill with setOpaque.
Definition Map.cpp:70
void render(graphics::Graphics *gfx)
Renders .
Definition Map.cpp:105
int getLastVisitedCellCount() const
Returns the last visited cell count.
Definition Map.cpp:119
Map()
Map.
Definition Map.cpp:47
Fov * newFov(TileLayer *layer)
FOV bound to a TileLayer (syncs opacity from opaque GIDs).
Definition Map.cpp:65
int getLastVisibleTileCount() const
Last tile collection counters for project-owned diagnostics UIs.
Definition Map.cpp:115
int publishCollision(TileLayer *layer)
Generate merged collision from non-walkable tile metadata and notify adapters.
Definition Map.cpp:121
int pollConfigs()
Polls configs.
Definition Map.cpp:113
Pathfinding facade. Single-agent: A*. Group (same goal): Flow Field + follow. Grid/topology internals...
Definition Pathfinder.h:20
static int poll()
Polls .
ECS tile layer entity. Script mutates tile GIDs / tileset / draw; TileRenderSystem batch-draws atlas ...
Definition TileLayer.h:32
void clear()
Clears the layer to empty.
static TileLayer * createLayer(int mapW, int mapH, float tileW=32.f, float tileH=32.f)
Definition TileLayer.cpp:14
void setVisible(bool visible)
static int lastVisibleTileCount()
Number of non-empty visible tiles collected by the last pass.
static void collect(std::vector< graphics::DrawItem2D > &out)
Append non-empty visible tiles into a shared 2D draw queue.
static int lastVisitedCellCount()
Last visited cell count.
static int lastAtlasCount()
Number of distinct atlas textures referenced by the last pass.
static int lastCustomVisualCount()
Number of collected tiles using irregular per-GID metadata.
static void update(float dt)
Advance TileSet animation clocks once per map update.
static int lastVisitedChunkCount()
Spatial-index work counters for deterministic performance regressions.
Map-owned CPU registry provider for generated grid artifacts.
const char * defaultValue
放置世界:格子占用(多通道)+ 地形语义 + 已放置建筑实例。 行为由 PlacementSystem 提供;本类暴露便于脚本绑定的薄封装方法。 坐标换算统一走 eve::grid(支持 rectang...
int dualGridMaskAt(TileLayer &logic, int dx, int dy, int filledGid)
4-bit corner mask for display cell (dx,dy) on a (logicW+1)×(logicH+1) grid. Samples logic (dx-1,...
Definition DualGrid.cpp:236
std::vector< TileLayer * > loadMapText(const std::string &json, std::vector< MapObject > *objects, std::string *error)
Parse map JSON text (no filesystem). Same semantics as loadMapFile.
void dualGridHalfOffset(const TileLayer::Config &cfg, float &offX, float &offY)
Half-step origin delta for the display layer (added to logic origin). Orthogonal: (-tileW/2,...
Definition DualGrid.cpp:202
uint32_t tileGid(uint32_t raw)
Strip Tiled flip / rotate flags; keep low 28 bits.
Definition TileLayer.h:383
void registerMapArtifactProvider()
Register the map provider in the common capability registry.
std::vector< TileLayer * > loadMapFile(const std::string &path, std::vector< MapObject > *objects, std::string *error)
Loads map file.
bool resolveDualGrid(TileLayer *logic, TileLayer *display, const DualGridOptions &opts, std::string *error)
Resolve logic → display dual-grid tiles. Resizes display to (logicW+1)×(logicH+1),...
Definition DualGrid.cpp:244
eve::Result< void > validateMapObjects(std::span< const MapObject > objects, std::string_view contractJson)
Validate map objects against an owning JSON content contract.
int dualGridDefaultFrame(int mask)
Default 4x4 atlas frame index for mask 0..15. -1 means draw nothing. Matches the SpriteCook / common ...
Definition DualGrid.cpp:197
const EditorValue * field(const EditorValue &value, const char *name)
std::unordered_map< std::string, SkillDefinition > & table()
Definition Skill.cpp:65
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.
Dual-grid autotile (Oskar Stålberg style).
Definition DualGrid.h:32
int filledGid
0 = any non-zero logic GID counts as filled; else only this GID.
Definition DualGrid.h:34
A named, typed rectangle object from a Tiled objectgroup layer. Used by Map::setObjects / getObject* ...
Definition MapObject.h:13
float width
Extent in pixels.
Definition MapObject.h:20