UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

125 lines (124 loc) 4.11 kB
"use strict"; import { CoreWFCTileAttribute } from "./WFCAttributes"; import { sortTileIds, ALL_SIDES } from "./WFCCommon"; import { createDefaultErrorTileObject, createDefaultUnresolvedTileObject } from "./WFCDebugTileObjects"; import { validRuleObject, wfcRuleFromObject } from "./WFCRule"; import { filterTileObjects, filterRuleObjects } from "./WFCUtils"; const _sortedTileIds = { first: "", second: "" }; function _addRule(rule, rulesByTileId, invert) { sortTileIds(rule.id0, rule.id1, _sortedTileIds, invert); let mapForId0 = rulesByTileId.get(_sortedTileIds.first); if (!mapForId0) { mapForId0 = /* @__PURE__ */ new Map(); rulesByTileId.set(_sortedTileIds.first, mapForId0); } let sides = mapForId0.get(_sortedTileIds.second); if (!sides) { sides = /* @__PURE__ */ new Map(); mapForId0.set(_sortedTileIds.second, sides); } let inverted = rule.id0 != _sortedTileIds.first; const _side0 = inverted ? rule.side1 : rule.side0; const _side1 = inverted ? rule.side0 : rule.side1; const side0s = _side0.split(""); const side1s = _side1.split(""); for (const side0 of side0s) { for (const side1 of side1s) { let side1s2 = sides.get(side0); if (!side1s2) { side1s2 = /* @__PURE__ */ new Set(); sides.set(side0, side1s2); } if (!side1s2.has(side1)) { side1s2.add(side1); } } } } export class WFCTilesCollection { // constructor(options) { this._rulesByTileId = /* @__PURE__ */ new Map(); this._errorTileObject = options.tileAndRuleObjects.find((o) => CoreWFCTileAttribute.getIsErrorTile(o)) || createDefaultErrorTileObject(); this._unresolvedTileObject = options.tileAndRuleObjects.find((o) => CoreWFCTileAttribute.getIsUnresolvedTile(o)) || createDefaultUnresolvedTileObject(); this._tiles = filterTileObjects(options.tileAndRuleObjects); this._tilesById = /* @__PURE__ */ new Map(); for (const tile of this._tiles) { this._tilesById.set(CoreWFCTileAttribute.getTileId(tile), tile); } const ruleObjects = filterRuleObjects(options.tileAndRuleObjects); const rules = ruleObjects.filter(validRuleObject).map(wfcRuleFromObject); for (const rule of rules) { sortTileIds(rule.id0, rule.id1, _sortedTileIds); _addRule(rule, this._rulesByTileId, false); _addRule(rule, this._rulesByTileId, true); } } tiles() { return this._tiles; } tile(tileId) { return this._tilesById.get(tileId); } errorTile() { return this._errorTileObject; } unresolvedTile() { return this._unresolvedTileObject; } traverseRules(id0, id1, callback) { sortTileIds(id0, id1, _sortedTileIds); const mapForFirst = this._rulesByTileId.get(_sortedTileIds.first); if (!mapForFirst) { return; } const sides = mapForFirst.get(_sortedTileIds.second); if (!sides) { return; } sides.forEach((side1s, side0) => { side1s.forEach((side1) => { callback(_sortedTileIds.first, _sortedTileIds.second, side0, side1); }); }); } traverseUnconnectedSides(id, callback) { const mapForFirst = this._rulesByTileId.get(id); if (!mapForFirst) { callback(ALL_SIDES); return; } const unconnectedSides = [...ALL_SIDES]; mapForFirst.forEach((sides, id1) => { sides.forEach((side1s, side0) => { const index = unconnectedSides.indexOf(side0); if (index > -1) { unconnectedSides.splice(index, 1); } }); }); callback(unconnectedSides); } allowedTileConfig(id0, side0, id1, side1) { sortTileIds(id0, id1, _sortedTileIds); const mapForFirst = this._rulesByTileId.get(_sortedTileIds.first); if (!mapForFirst) { return false; } const sides = mapForFirst.get(_sortedTileIds.second); if (!sides) { return false; } let inverted = id0 != _sortedTileIds.first; const key = inverted ? side1 : side0; const value = inverted ? side0 : side1; const side1s = sides.get(key); if (!side1s) { return false; } return side1s.has(value); } }