@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
125 lines (124 loc) • 4.11 kB
JavaScript
;
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);
}
}