arx-level-generator
Version:
A tool for creating Arx Fatalis maps
213 lines • 6.38 kB
JavaScript
import { Entities } from './Entities.js';
import { Fogs } from './Fogs.js';
import { Lights } from './Lights.js';
import { Paths } from './Paths.js';
import { Polygons } from './Polygons.js';
import { Zones } from './Zones.js';
import { groupSequences } from './faux-ramda.js';
export class Selection {
selection = [];
items;
constructor(items) {
this.items = items;
}
get() {
return this.items;
}
clearSelection() {
this.selection = [];
return this;
}
hasSelection() {
return this.selection.length > 0;
}
sizeOfSelection() {
return this.selection.length;
}
selectAll() {
this.selection = Array.from(this.items.keys());
return this;
}
/**
* selects items based on a given predicate
* if there are already items selected then this filters those further
*/
selectBy(predicate) {
if (!this.hasSelection()) {
this.selectAll();
}
this.selection = this.selection.filter((idx) => {
const item = this.items[idx];
return predicate(item, idx);
});
return this;
}
invertSelection() {
// none selected -> all selected
if (!this.hasSelection()) {
return this.selectAll();
}
// all selected -> none selected
if (this.sizeOfSelection() === this.items.length) {
return this.clearSelection();
}
const selection = this.selection.toSorted((a, b) => a - b);
this.selection = [];
let idx = 0;
let current = selection[idx];
for (let candidate = 0; candidate < this.items.length; candidate++) {
if (candidate === current) {
if (idx < selection.length) {
idx += 1;
current = selection[idx];
}
}
else {
this.selection.push(candidate);
}
}
return this;
}
/**
* Removes items which have been selected
*
* @returns a copy of the elements that have been deleted
*/
delete() {
const copiedItems = this.copy().get();
if (copiedItems.length > 0) {
groupSequences(this.selection)
.reverse()
.forEach(([start, size]) => {
this.items.splice(start, size);
});
this.selection = [];
}
return copiedItems;
}
apply(fn) {
this.selection.forEach((idx) => {
const item = this.items[idx];
fn(item, idx);
});
return this;
}
move(offset) {
return this.apply((item) => {
item.move(offset);
});
}
}
// ----------------------------------------
export class PolygonSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new PolygonSelection(new Polygons(...copiedItems));
}
/**
* selects polygons which go outside the 0-160 meters boundary on the horizontal axis
*/
selectOutOfBounds() {
return this.selectBy((polygon) => polygon.isOutOfBounds());
}
selectWithinBox(box) {
return this.selectBy((polygon) => polygon.isWithin(box));
}
selectByTextures(textures) {
return this.selectBy((polygon) => polygon.texture?.equalsAny(textures) ?? false);
}
makeDoubleSided() {
return this.apply((polygon) => {
polygon.makeDoubleSided();
});
}
moveToRoom1() {
return this.apply((polygon) => {
if (polygon.room < 1) {
return;
}
polygon.room = 1;
});
}
scale(scale) {
return this.apply((polygon) => {
polygon.scale(scale);
});
}
flipUVHorizontally() {
return this.apply((polygon) => {
polygon.flipUVHorizontally();
});
}
flipUVVertically() {
return this.apply((polygon) => {
polygon.flipUVVertically();
});
}
}
export class LightsSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new LightsSelection(new Lights(...copiedItems));
}
}
export class EntitiesSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new EntitiesSelection(new Entities(...copiedItems));
}
}
export class FogsSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new FogsSelection(new Fogs(...copiedItems));
}
}
export class PathsSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new PathsSelection(new Paths(...copiedItems));
}
}
export class ZonesSelection extends Selection {
copy() {
const copiedItems = this.selection.map((idx) => this.items[idx].clone());
return new ZonesSelection(new Zones(...copiedItems));
}
}
const instances = new WeakMap();
/**
* Calling methods on the selected items will mutate the original values
* unless you create a copy of them with the `.copy()` method
* the copied (or original if no copy has been called) values can
* be read with the `.get()` method.
*/
export const $ = (items) => {
if (items instanceof Selection) {
return items;
}
let instance = instances.get(items);
if (instance === undefined) {
if (items instanceof Polygons) {
instance = new PolygonSelection(items);
}
else if (items instanceof Entities) {
instance = new EntitiesSelection(items);
}
else if (items instanceof Lights) {
instance = new LightsSelection(items);
}
else if (items instanceof Fogs) {
instance = new FogsSelection(items);
}
else if (items instanceof Paths) {
instance = new PathsSelection(items);
}
else {
instance = new ZonesSelection(items);
}
instances.set(items, instance);
}
return instance;
};
//# sourceMappingURL=Selection.js.map