stuff
This commit is contained in:
parent
1e6dfcaff4
commit
537e4e1287
8 changed files with 8845 additions and 8396 deletions
95
README.md
95
README.md
|
@ -4,97 +4,4 @@ EventMapper, a lightweight (hopefully), easily-deployable, nearly-static digital
|
||||||
|
|
||||||
## Specifications
|
## Specifications
|
||||||
|
|
||||||
### Data Folder Structure
|
TO BE REDONE
|
||||||
```
|
|
||||||
/events
|
|
||||||
[FLOOR].json
|
|
||||||
/rooms
|
|
||||||
[FLOOR].json
|
|
||||||
floors.json
|
|
||||||
tags.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### Floor
|
|
||||||
Used to represent a floor in a building. It is a parent to both its [Rooms](#room) and [Events](#events).
|
|
||||||
This object gets represented in the app as a map poly, and in a set of buttons among other floors.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "[FLOOR ID]",
|
|
||||||
"poly": [
|
|
||||||
[x, y], // An array of vertex positions.
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"lang": {
|
|
||||||
"[IETF LANGUAGE TAG]": {
|
|
||||||
"name": "[SHORT SINGLE-LINE STRING]",
|
|
||||||
"description": "[SINGLE-LINE STRING]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This will be stored in an array in `floors.json` to be accessed by clients.
|
|
||||||
|
|
||||||
### Room
|
|
||||||
Used to represent a space in which events can happen. It is a child to a [Floor](#floor), and a parent to [Events](#event).
|
|
||||||
This object gets represented in the app as a map poly.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "[FLOOR]_[ROOM ID]",
|
|
||||||
"poly": [
|
|
||||||
[x, y], // An array of vertex positions.
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"tags": ["[ARRAY", "OF", "TAG", "IDS]"],
|
|
||||||
"lang": {
|
|
||||||
"[IETF LANGUAGE TAG]": {
|
|
||||||
"name": "[SINGLE-LINE STRING]",
|
|
||||||
"shortName": "[INITIALS OF NAME]",
|
|
||||||
"description": "[SINGLE-LINE STRING]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This will be stored in an array in `rooms/[FLOOR].json` to be accessed by clients.
|
|
||||||
|
|
||||||
### Event
|
|
||||||
Used to represent a point in time when an activity happens. It is a child to both a [Floor](#floor) and a [Room](#room), reflected in its ID.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "[FLOOR]_[ROOM]_[EVENT ID]",
|
|
||||||
"when": {
|
|
||||||
"start": "[ISO 8601 DATE]",
|
|
||||||
"end": "[ISO 8601 DATE]"
|
|
||||||
},
|
|
||||||
"tags": ["[ARRAY", "OF", "TAG", "IDS]"],
|
|
||||||
"lang": {
|
|
||||||
"[IETF LANGUAGE TAG]": {
|
|
||||||
"name": "[SINGLE-LINE STRING]",
|
|
||||||
"description": "[MULTI-LINE STRING]",
|
|
||||||
"host": "[HOST NAME (OPTIONAL)]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This will be stored in an array in `events/[FLOOR].json` to be accessed by clients.
|
|
||||||
|
|
||||||
### Tag
|
|
||||||
Used to represent a tag that can be applied by ID to a Room or Event.
|
|
||||||
This object gets represented in the app as a searchable tag chip.
|
|
||||||
|
|
||||||
`radiogroup` can be used to un-toggle other tags when this one is selected.
|
|
||||||
`show` can be used to hide the tag from search completely.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "[FLOOR ID]",
|
|
||||||
"radiogroup": "[GROUP ID]",
|
|
||||||
"show": <boolean>,
|
|
||||||
"lang": {
|
|
||||||
"[IETF LANGUAGE TAG]": {
|
|
||||||
"name": "[SHORT SINGLE-LINE STRING]",
|
|
||||||
"shortName": "[INITIALS OF NAME]",
|
|
||||||
"description": "[SINGLE-LINE STRING]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This will be stored in an array in `tags.json` to be accessed by clients.
|
|
|
@ -1,20 +1,34 @@
|
||||||
export class GameObjManager {
|
export class GameObjManager {
|
||||||
map;
|
map;
|
||||||
opts = {
|
opts = {
|
||||||
textColor: "FFFFFF",
|
styles: {
|
||||||
bgColor: "303030",
|
default: {
|
||||||
bgFocusColor: "505030",
|
textColor: "FFFFFF",
|
||||||
bgHoverColor: "505050",
|
backgroundColor: "303030",
|
||||||
bgFocusHoverColor: "707050",
|
borderColor: "000000",
|
||||||
bgClickColor: "202020",
|
actionColor: "000000",
|
||||||
bgFocusClickColor: "404020",
|
textOpacity: 1,
|
||||||
borderColor: "000000",
|
backgroundOpacity: 0.75,
|
||||||
borderFocusColor: "808000",
|
borderOpacity: 1,
|
||||||
font: "monospace",
|
borderWidth: 8,
|
||||||
fontSize: 24,
|
font: "monospace",
|
||||||
maxFontWidth: 16,
|
fontSize: 24,
|
||||||
floorOpacity: 0.75,
|
fontWidth: 16,
|
||||||
roomOpacity: 0.75,
|
},
|
||||||
|
defaultFocused: {
|
||||||
|
textColor: "FFFFFF",
|
||||||
|
backgroundColor: "505030",
|
||||||
|
borderColor: "808000",
|
||||||
|
actionColor: "000000",
|
||||||
|
textOpacity: 1,
|
||||||
|
backgroundOpacity: 0.75,
|
||||||
|
borderOpacity: 1,
|
||||||
|
borderWidth: 8,
|
||||||
|
font: "monospace",
|
||||||
|
fontSize: 24,
|
||||||
|
fontWidth: 16,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
mainmanager;
|
mainmanager;
|
||||||
|
@ -30,45 +44,126 @@ export class GameObjManager {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__getTopStyle(styles = [], focused = false) {
|
||||||
|
const defaultFocused = {
|
||||||
|
...this.opts.styles.default,
|
||||||
|
...this.opts.styles.defaultFocused,
|
||||||
|
};
|
||||||
|
if (focused) {
|
||||||
|
return styles.reduce((lastStyle, style) => {
|
||||||
|
return {
|
||||||
|
...lastStyle,
|
||||||
|
...this.opts.styles[style],
|
||||||
|
...this.opts.styles[style + "Focused"],
|
||||||
|
};
|
||||||
|
}, defaultFocused);
|
||||||
|
} else {
|
||||||
|
return styles.reduce((lastStyle, style) => {
|
||||||
|
return {
|
||||||
|
...lastStyle,
|
||||||
|
...this.opts.styles[style],
|
||||||
|
};
|
||||||
|
}, this.opts.styles.default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__getTopFloorStyle(styles = []) {
|
||||||
|
const defaultFloor = {
|
||||||
|
...this.opts.styles.default,
|
||||||
|
...this.opts.styles.default_floor,
|
||||||
|
};
|
||||||
|
return styles.reduce((lastStyle, style) => {
|
||||||
|
return {
|
||||||
|
...lastStyle,
|
||||||
|
...this.opts.styles[style],
|
||||||
|
};
|
||||||
|
}, defaultFloor);
|
||||||
|
}
|
||||||
|
|
||||||
generateFloor() {
|
generateFloor() {
|
||||||
if (this.floorObject) this.floorObject.destroy();
|
if (this.floorObject) this.floorObject.destroy();
|
||||||
|
|
||||||
const currentFloor = this.mainmanager.getCurrentFocusObject("floor");
|
const currentFloor = this.mainmanager.getCurrentFocusObject("floor");
|
||||||
|
|
||||||
|
// Generate regular polygon for area()
|
||||||
|
if (currentFloor.polys && currentFloor.poly == null)
|
||||||
|
currentFloor.poly = currentFloor.polys.flat(1);
|
||||||
|
|
||||||
const polygon = new this.map.kp.Polygon(
|
const polygon = new this.map.kp.Polygon(
|
||||||
currentFloor.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
currentFloor.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
||||||
);
|
);
|
||||||
|
|
||||||
this.floorObject = this.map.kp.make([
|
|
||||||
this.map.kp.polygon(polygon.pts),
|
|
||||||
this.map.kp.color(this.map.kp.Color.fromHex(this.opts.bgColor)),
|
|
||||||
this.map.kp.opacity(this.opts.floorOpacity),
|
|
||||||
this.map.kp.pos(),
|
|
||||||
this.map.kp.z(5),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const bounds = polygon.bbox();
|
const bounds = polygon.bbox();
|
||||||
|
|
||||||
this.map.camBounds = bounds;
|
this.map.camBounds = bounds;
|
||||||
|
|
||||||
|
const curStyle = this.__getTopFloorStyle(currentFloor.styles);
|
||||||
|
|
||||||
|
this.floorObject = this.map.kp.make([
|
||||||
|
this.map.kp.polygon(polygon.pts, {
|
||||||
|
triangulate: true,
|
||||||
|
}),
|
||||||
|
this.map.kp.opacity(0),
|
||||||
|
this.map.kp.pos(),
|
||||||
|
this.map.kp.z(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let polysgon;
|
||||||
|
if (currentFloor.polys)
|
||||||
|
polysgon = currentFloor.polys.map(
|
||||||
|
(poly) =>
|
||||||
|
new this.map.kp.Polygon(poly.map(([x, y]) => this.map.kp.vec2(x, y)))
|
||||||
|
);
|
||||||
|
|
||||||
this.floorObject.onDraw(() => {
|
this.floorObject.onDraw(() => {
|
||||||
const camScale = 1 / this.map.kp.camScale().y;
|
const camScale = 1 / this.map.kp.camScale().y;
|
||||||
|
|
||||||
|
if (polysgon) {
|
||||||
|
polysgon.forEach((poly) => {
|
||||||
|
this.map.kp.drawPolygon({
|
||||||
|
pts: poly.pts,
|
||||||
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.backgroundColor),
|
||||||
|
opacity: curStyle.backgroundOpacity,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.map.kp.drawPolygon({
|
||||||
|
pts: polygon.pts,
|
||||||
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.backgroundColor),
|
||||||
|
opacity: curStyle.backgroundOpacity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.map.kp.drawPolygon({
|
this.map.kp.drawPolygon({
|
||||||
pts: polygon.pts,
|
pts: polygon.pts,
|
||||||
pos: this.map.kp.vec2(0),
|
pos: this.map.kp.vec2(0),
|
||||||
fill: false,
|
fill: false,
|
||||||
|
triangulate: true,
|
||||||
outline: {
|
outline: {
|
||||||
color: this.map.kp.Color.fromHex(this.opts.borderColor),
|
color: this.map.kp.Color.fromHex(curStyle.borderColor),
|
||||||
width: 8 * camScale,
|
opacity: curStyle.borderOpacity,
|
||||||
|
width: curStyle.borderWidth * camScale,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let text = currentFloor.name;
|
||||||
|
if (curStyle.textTransform == "uppercase") {
|
||||||
|
text = text.toUpperCase();
|
||||||
|
} else if (curStyle.textTransform == "lowercase") {
|
||||||
|
text = text.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
this.map.kp.drawText({
|
this.map.kp.drawText({
|
||||||
text: currentFloor.name,
|
text,
|
||||||
size: 24 * camScale,
|
size: curStyle.fontSize * camScale,
|
||||||
|
font: curStyle.font,
|
||||||
pos: this.map.kp.vec2(-4 * camScale, -8 * camScale),
|
pos: this.map.kp.vec2(-4 * camScale, -8 * camScale),
|
||||||
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
color: this.map.kp.Color.fromHex(curStyle.textColor),
|
||||||
|
opacity: curStyle.textOpacity,
|
||||||
anchor: "botleft",
|
anchor: "botleft",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -76,14 +171,14 @@ export class GameObjManager {
|
||||||
this.map.kp.add(this.floorObject);
|
this.map.kp.add(this.floorObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomToBounds(boundingBox) {
|
zoomToBounds(boundingBox, pos) {
|
||||||
// Get screen size
|
// Get screen size
|
||||||
const width = this.map.kp.width();
|
const width = this.map.kp.width();
|
||||||
const height = this.map.kp.height();
|
const height = this.map.kp.height();
|
||||||
|
|
||||||
// Get bbox size
|
// Get bbox size
|
||||||
const bBoxWidth = boundingBox.width * 2;
|
const bBoxWidth = boundingBox.width * 1.25;
|
||||||
const bBoxHeight = boundingBox.height * 2;
|
const bBoxHeight = boundingBox.height * 1.25;
|
||||||
|
|
||||||
// Compare bounds
|
// Compare bounds
|
||||||
const scaledWidth = width / bBoxWidth;
|
const scaledWidth = width / bBoxWidth;
|
||||||
|
@ -92,9 +187,12 @@ export class GameObjManager {
|
||||||
// Whichever one is biggest
|
// Whichever one is biggest
|
||||||
const scale = Math.min(scaledWidth, scaledHeight);
|
const scale = Math.min(scaledWidth, scaledHeight);
|
||||||
|
|
||||||
|
let newPos = boundingBox.center();
|
||||||
|
if (pos) newPos = newPos.add(pos);
|
||||||
|
|
||||||
this.map.zoomToAbs(
|
this.map.zoomToAbs(
|
||||||
Math.log2(scale), // log scale
|
Math.log2(scale), // log scale
|
||||||
boundingBox.center()
|
newPos
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +208,7 @@ export class GameObjManager {
|
||||||
|
|
||||||
const objectBounds = selectedObject.renderArea().bbox();
|
const objectBounds = selectedObject.renderArea().bbox();
|
||||||
|
|
||||||
this.zoomToBounds(objectBounds);
|
this.zoomToBounds(objectBounds, selectedObject.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateRooms() {
|
generateRooms() {
|
||||||
|
@ -122,17 +220,30 @@ export class GameObjManager {
|
||||||
const currentRooms = this.mainmanager.getAllFocusObject("room");
|
const currentRooms = this.mainmanager.getAllFocusObject("room");
|
||||||
|
|
||||||
currentRooms.forEach((room) => {
|
currentRooms.forEach((room) => {
|
||||||
|
// Generate regular polygon for area()
|
||||||
|
if (room.polys && room.poly == null) room.poly = room.polys.flat(1);
|
||||||
|
|
||||||
const polygon = new this.map.kp.Polygon(
|
const polygon = new this.map.kp.Polygon(
|
||||||
room.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
room.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const polygonBbox = polygon.bbox();
|
||||||
|
const polygonCenter = polygonBbox.center();
|
||||||
|
|
||||||
|
polygon.pts = polygon.pts.map((point) => point.sub(polygonCenter));
|
||||||
|
|
||||||
|
let roomFocused = this.mainmanager.getCurrentFocus("room") == room.id;
|
||||||
|
|
||||||
|
let curStyle = this.__getTopStyle(room.styles, roomFocused);
|
||||||
|
|
||||||
const obj = this.map.kp.make([
|
const obj = this.map.kp.make([
|
||||||
this.map.kp.polygon(polygon.pts),
|
this.map.kp.polygon(polygon.pts, {
|
||||||
this.map.kp.color(this.map.kp.Color.fromHex(this.opts.bgColor)),
|
triangulate: true,
|
||||||
this.map.kp.opacity(this.opts.roomOpacity),
|
}),
|
||||||
|
this.map.kp.opacity(0),
|
||||||
this.map.kp.area(),
|
this.map.kp.area(),
|
||||||
this.map.kp.pos(),
|
this.map.kp.pos(polygonCenter),
|
||||||
this.map.kp.z(6),
|
this.map.kp.z(room.empty ? 5 : 6),
|
||||||
{
|
{
|
||||||
clickForgiveness: 5,
|
clickForgiveness: 5,
|
||||||
startClickPosition: null,
|
startClickPosition: null,
|
||||||
|
@ -141,8 +252,40 @@ export class GameObjManager {
|
||||||
|
|
||||||
this.roomObjects.set(room.id, obj);
|
this.roomObjects.set(room.id, obj);
|
||||||
|
|
||||||
obj.onUpdate(() => {
|
let polysgon;
|
||||||
const roomFocused = this.mainmanager.getCurrentFocus("room") == room.id;
|
if (room.polys)
|
||||||
|
polysgon = room.polys.map(
|
||||||
|
(poly) =>
|
||||||
|
new this.map.kp.Polygon(
|
||||||
|
poly.map(([x, y]) => this.map.kp.vec2(x, y).sub(polygonCenter))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let labelPos = this.map.kp.vec2(0);
|
||||||
|
let labelWidth = polygonBbox.width;
|
||||||
|
if (room.label?.pos)
|
||||||
|
labelPos = this.map.kp.vec2(room.label.pos).sub(polygonCenter);
|
||||||
|
if (room.label?.width) labelWidth = room.label.width;
|
||||||
|
|
||||||
|
obj.onDraw(() => {
|
||||||
|
// Check if room is within bounds
|
||||||
|
const camScale = 1 / this.map.kp.camScale().y;
|
||||||
|
const camBounds = this.map.kp.vec2(
|
||||||
|
this.map.kp.width() * camScale,
|
||||||
|
this.map.kp.height() * camScale
|
||||||
|
);
|
||||||
|
const camPos = this.map.kp.camPos().sub(camBounds.scale(0.5));
|
||||||
|
|
||||||
|
const rect = new this.map.kp.Rect(camPos, camBounds.x, camBounds.y);
|
||||||
|
|
||||||
|
if (!rect.collides(polygonBbox)) return;
|
||||||
|
|
||||||
|
const curRoomFocused =
|
||||||
|
this.mainmanager.getCurrentFocus("room") == room.id;
|
||||||
|
if (curRoomFocused != roomFocused) {
|
||||||
|
curStyle = this.__getTopStyle(room.styles, curRoomFocused);
|
||||||
|
roomFocused = curRoomFocused;
|
||||||
|
}
|
||||||
|
|
||||||
if (roomFocused) {
|
if (roomFocused) {
|
||||||
obj.z = 7;
|
obj.z = 7;
|
||||||
|
@ -150,78 +293,145 @@ export class GameObjManager {
|
||||||
obj.z = 6;
|
obj.z = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj.isHovering()) {
|
if (polysgon) {
|
||||||
if (roomFocused)
|
polysgon.forEach((poly) => {
|
||||||
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusHoverColor);
|
this.map.kp.drawPolygon({
|
||||||
else obj.color = this.map.kp.Color.fromHex(this.opts.bgHoverColor);
|
pts: poly.pts,
|
||||||
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.backgroundColor),
|
||||||
|
opacity: curStyle.backgroundOpacity,
|
||||||
|
});
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (roomFocused)
|
this.map.kp.drawPolygon({
|
||||||
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusColor);
|
pts: polygon.pts,
|
||||||
else obj.color = this.map.kp.Color.fromHex(this.opts.bgColor);
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.backgroundColor),
|
||||||
|
opacity: curStyle.backgroundOpacity,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.map.kp.isMousePressed() && obj.isHovering()) {
|
if (!room.empty) {
|
||||||
obj.startClickPosition = this.map.kp.mousePos();
|
let opacity = 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (this.map.kp.isMouseDown() && obj.isHovering()) {
|
if (obj.isHovering()) {
|
||||||
if (roomFocused)
|
opacity = 0.25;
|
||||||
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusClickColor);
|
|
||||||
else obj.color = this.map.kp.Color.fromHex(this.opts.bgClickColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.map.kp.isMouseReleased() && obj.isHovering()) {
|
|
||||||
const endClickPosition = this.map.kp.mousePos();
|
|
||||||
if (
|
|
||||||
obj.startClickPosition &&
|
|
||||||
obj.startClickPosition.dist(endClickPosition) < obj.clickForgiveness
|
|
||||||
) {
|
|
||||||
window.location.hash = room.id;
|
|
||||||
}
|
}
|
||||||
if (roomFocused)
|
|
||||||
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusHoverColor);
|
|
||||||
this.map.clearMouseMode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
obj.onDraw(() => {
|
if (this.map.kp.isMousePressed() && obj.isHovering()) {
|
||||||
const camScale = 1 / this.map.kp.camScale().y;
|
obj.startClickPosition = this.map.kp.mousePos();
|
||||||
const roomFocused = this.mainmanager.getCurrentFocus("room") == room.id;
|
}
|
||||||
|
|
||||||
|
if (this.map.kp.isMouseDown() && obj.isHovering()) {
|
||||||
|
opacity = 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.map.kp.isMouseReleased() && obj.isHovering()) {
|
||||||
|
const endClickPosition = this.map.kp.mousePos();
|
||||||
|
if (
|
||||||
|
obj.startClickPosition &&
|
||||||
|
obj.startClickPosition.dist(endClickPosition) <
|
||||||
|
obj.clickForgiveness
|
||||||
|
) {
|
||||||
|
window.location.hash = room.id;
|
||||||
|
}
|
||||||
|
this.map.clearMouseMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polysgon) {
|
||||||
|
polysgon.forEach((poly) => {
|
||||||
|
this.map.kp.drawPolygon({
|
||||||
|
pts: poly.pts,
|
||||||
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.actionColor),
|
||||||
|
opacity,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.map.kp.drawPolygon({
|
||||||
|
pts: polygon.pts,
|
||||||
|
pos: this.map.kp.vec2(0),
|
||||||
|
triangulate: true,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.actionColor),
|
||||||
|
opacity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.map.kp.drawPolygon({
|
this.map.kp.drawPolygon({
|
||||||
pts: polygon.pts,
|
pts: polygon.pts,
|
||||||
pos: this.map.kp.vec2(0),
|
pos: this.map.kp.vec2(0),
|
||||||
fill: false,
|
fill: false,
|
||||||
|
triangulate: true,
|
||||||
outline: {
|
outline: {
|
||||||
color: this.map.kp.Color.fromHex(
|
color: this.map.kp.Color.fromHex(curStyle.borderColor),
|
||||||
roomFocused ? this.opts.borderFocusColor : this.opts.borderColor
|
opacity: curStyle.borderOpacity,
|
||||||
),
|
width: curStyle.borderWidth * camScale,
|
||||||
width: 8 * camScale,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
// Easy optimization: Don't draw empty room names
|
||||||
this.opts.maxFontWidth * camScale * room.name.length >
|
if (room.name != "") {
|
||||||
polygon.bbox().width
|
if (
|
||||||
)
|
room.shortName != "" &&
|
||||||
this.map.kp.drawText({
|
curStyle.fontWidth * camScale * room.name.length > labelWidth
|
||||||
text: room.shortName + "…",
|
) {
|
||||||
size: this.opts.fontSize * camScale,
|
if (
|
||||||
pos: polygon.bbox().center(),
|
curStyle.shortNameCollapse &&
|
||||||
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
curStyle.fontWidth * camScale * room.shortName.length > labelWidth
|
||||||
align: "center",
|
)
|
||||||
anchor: "center",
|
return;
|
||||||
});
|
|
||||||
else
|
let text = room.shortName + (curStyle.textCut ?? "…");
|
||||||
this.map.kp.drawText({
|
if (curStyle.textTransform == "uppercase") {
|
||||||
text: room.name,
|
text = text.toUpperCase();
|
||||||
width: polygon.bbox().width,
|
} else if (curStyle.textTransform == "lowercase") {
|
||||||
size: this.opts.fontSize * camScale,
|
text = text.toLowerCase();
|
||||||
pos: polygon.bbox().center(),
|
}
|
||||||
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
|
||||||
align: "center",
|
this.map.kp.drawText({
|
||||||
anchor: "center",
|
text,
|
||||||
});
|
size: curStyle.shortNameMinScale
|
||||||
|
? Math.min(curStyle.fontSize, curStyle.fontSize * camScale)
|
||||||
|
: curStyle.fontSize * camScale,
|
||||||
|
font: curStyle.font,
|
||||||
|
pos: labelPos,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.textColor),
|
||||||
|
opacity: curStyle.textOpacity,
|
||||||
|
align: "center",
|
||||||
|
anchor: "center",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
curStyle.shortNameCollapse &&
|
||||||
|
curStyle.fontWidth * camScale * room.name.length > labelWidth
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let text = room.name;
|
||||||
|
if (curStyle.textTransform == "uppercase") {
|
||||||
|
text = text.toUpperCase();
|
||||||
|
} else if (curStyle.textTransform == "lowercase") {
|
||||||
|
text = text.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.map.kp.drawText({
|
||||||
|
text,
|
||||||
|
size: curStyle.shortNameMinScale
|
||||||
|
? Math.min(labelWidth, curStyle.fontSize * camScale)
|
||||||
|
: curStyle.fontSize * camScale,
|
||||||
|
font: curStyle.font,
|
||||||
|
pos: labelPos,
|
||||||
|
color: this.map.kp.Color.fromHex(curStyle.textColor),
|
||||||
|
opacity: curStyle.textOpacity,
|
||||||
|
align: "center",
|
||||||
|
anchor: "center",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.floorObject.add(obj);
|
this.floorObject.add(obj);
|
||||||
|
|
|
@ -48,7 +48,8 @@ See https://git.gay/MeowcaTheoRange/EventMapper for more info
|
||||||
Thanks to:
|
Thanks to:
|
||||||
- Joe 2DCon @ https://2dcon.gg/
|
- Joe 2DCon @ https://2dcon.gg/
|
||||||
- KikiCraft @ https://kikicraft.com/
|
- KikiCraft @ https://kikicraft.com/
|
||||||
- Captain Zach @ https://discord.gg/2dcon`,
|
- Captain Zach @ https://discord.gg/2dcon
|
||||||
|
- Jason @ https://discord.gg/2dcon`,
|
||||||
search_dialog_close_button: "Close search",
|
search_dialog_close_button: "Close search",
|
||||||
search_dialog_header_title: "Search Events",
|
search_dialog_header_title: "Search Events",
|
||||||
search_dialog_search_bar: "Type search query here...",
|
search_dialog_search_bar: "Type search query here...",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,33 +15,24 @@ const kp = kaplay({
|
||||||
global: false,
|
global: false,
|
||||||
maxFPS: 120,
|
maxFPS: 120,
|
||||||
texFilter: "nearest",
|
texFilter: "nearest",
|
||||||
background: window.backgroundBranding ?? "404040",
|
background: window.branding?.background ?? "404040",
|
||||||
});
|
});
|
||||||
|
|
||||||
const kaplaymap = new KaplayMap(kp, {});
|
const kaplaymap = new KaplayMap(kp, {
|
||||||
|
minZoomLevel: 0,
|
||||||
|
maxZoomLevel: 6,
|
||||||
|
...window.branding?.kaplayMap,
|
||||||
|
});
|
||||||
const eventmappermanager = new EventMapperManager(kaplaymap, mapUi, {
|
const eventmappermanager = new EventMapperManager(kaplaymap, mapUi, {
|
||||||
gameobj: window.gameObjBranding,
|
gameobj: window.branding?.gameObj,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const grid = kp.loadSprite(null, "/files/images/grid.png");
|
if (window.branding?.init != null) window.branding.init(kp);
|
||||||
|
|
||||||
kp.onDraw(() => {
|
|
||||||
kp.drawSprite({
|
|
||||||
sprite: grid,
|
|
||||||
tiled: true,
|
|
||||||
opacity: 0.25,
|
|
||||||
width: kp.width() + 200,
|
|
||||||
height: kp.height() + 200,
|
|
||||||
anchor: "center",
|
|
||||||
pos: kp.vec2(
|
|
||||||
Math.floor(kp.camPos().x / 100) * 100 + 0.5,
|
|
||||||
Math.floor(kp.camPos().y / 100) * 100 + 0.5
|
|
||||||
),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await eventmappermanager.load();
|
await eventmappermanager.load();
|
||||||
|
|
||||||
|
console.log(kp.VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -11,7 +11,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"http-proxy-middleware": "^3.0.0",
|
"http-proxy-middleware": "^3.0.0",
|
||||||
"https": "^1.0.0"
|
"https": "^1.0.0",
|
||||||
|
"kaplay": "^3001.0.0-alpha.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.1.1"
|
"nodemon": "^3.1.1"
|
||||||
|
@ -674,6 +675,11 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/kaplay": {
|
||||||
|
"version": "3001.0.0-alpha.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/kaplay/-/kaplay-3001.0.0-alpha.10.tgz",
|
||||||
|
"integrity": "sha512-Nsl0GvOszQdIZDnUSWaB46Iehk24CczXVAD3aiaYWMeAUHZNx/DDbnliNC/sosQB0F9m/+h2D+qhxkNTJ+5ITw=="
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"http-proxy-middleware": "^3.0.0",
|
"http-proxy-middleware": "^3.0.0",
|
||||||
"https": "^1.0.0"
|
"https": "^1.0.0",
|
||||||
|
"kaplay": "^3001.0.0-alpha.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.1.1"
|
"nodemon": "^3.1.1"
|
||||||
|
|
|
@ -8,6 +8,9 @@ app.use("/assets", express.static('assets'));
|
||||||
|
|
||||||
app.use("/", express.static('pages'));
|
app.use("/", express.static('pages'));
|
||||||
|
|
||||||
|
app.use("/dataServer", express.static('data'));
|
||||||
|
app.use("/fileServer", express.static('files'));
|
||||||
|
|
||||||
app.get('/files/*', async (req, res) => {
|
app.get('/files/*', async (req, res) => {
|
||||||
// Get events
|
// Get events
|
||||||
let eventsReq = await fetch(new URL(req.params[0], config.files_url));
|
let eventsReq = await fetch(new URL(req.params[0], config.files_url));
|
||||||
|
|
Loading…
Reference in a new issue