Marker storage/display improvements

- Store markers of all types for a marker set in a single map
- Merge all marker type components into a single Markers component
- Add marker type prefixes to dynmap marker ids to ensure they remain unique
- Add id and type properties to marker objects
- Remove now-unused update handler for specific marker types
This commit is contained in:
James Lyne 2022-01-15 15:45:59 +00:00
parent 9abd96ccb1
commit 42e553bda7
12 changed files with 180 additions and 508 deletions

View File

@ -15,30 +15,21 @@
-->
<template>
<Areas :layer-group="layerGroup" :set="markerSet"></Areas>
<Circles :layer-group="layerGroup" :set="markerSet"></Circles>
<Lines :layer-group="layerGroup" :set="markerSet"></Lines>
<Points :layer-group="layerGroup" :set="markerSet"></Points>
<Markers :layer-group="layerGroup" :set="markerSet"></Markers>
</template>
<script lang="ts">
import {defineComponent, computed, onMounted, onUnmounted} from "@vue/runtime-core";
import {useStore} from "@/store";
import Areas from "@/components/map/vector/Areas.vue";
import Circles from "@/components/map/vector/Circles.vue";
import Lines from "@/components/map/vector/Lines.vue";
import Points from "@/components/map/vector/Points.vue";
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasMarkerSet} from "@/index";
import {watch} from "vue";
import Markers from "@/components/map/marker/Markers.vue";
export default defineComponent({
components: {
Areas,
Circles,
Lines,
Points,
Markers,
},
props: {

View File

@ -1,5 +1,5 @@
<!--
- Copyright 2021 James Lyne
- Copyright 2022 James Lyne
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
@ -16,14 +16,16 @@
<script lang="ts">
import {defineComponent, computed, onMounted, watch, onUnmounted} from "@vue/runtime-core";
import {Marker} from 'leaflet';
import {useStore} from "@/store";
import {createPointMarker, updatePointMarker} from "@/util/points";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasPointMarker, LiveAtlasMarkerSet} from "@/index";
import {LiveAtlasAreaMarker, LiveAtlasMarker, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
import {DynmapMarkerUpdate} from "@/dynmap";
import {LiveAtlasMarkerType, registerTypeUpdateHandler, unregisterTypeUpdateHandler} from "@/util/markers";
import {
createMarker,
registerUpdateHandler, unregisterUpdateHandler, updateMarker
} from "@/util/markers";
import {Layer} from "leaflet";
export default defineComponent({
props: {
@ -40,13 +42,13 @@ export default defineComponent({
setup(props) {
const store = useStore(),
currentMap = computed(() => store.state.currentMap),
layers = Object.freeze(new Map()) as Map<string, Marker>;
layers = Object.freeze(new Map()) as Map<string, Layer>;
let converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
let converter = currentMap.value!.locationToLatLng.bind(currentMap.value);
const createMarkers = () => {
nonReactiveState.markers.get(props.set.id)!.points.forEach((marker: LiveAtlasPointMarker, id: string) => {
const layer = createPointMarker(marker, converter);
nonReactiveState.markers.get(props.set.id)!.forEach((area: LiveAtlasMarker, id: string) => {
const layer = createMarker(area, converter);
layers.set(id, layer);
props.layerGroup.addLayer(layer);
@ -54,7 +56,7 @@ export default defineComponent({
};
const deleteMarker = (id: string) => {
let marker = layers.get(id) as Marker;
let marker = layers.get(id);
if(!marker) {
return;
@ -68,7 +70,7 @@ export default defineComponent({
if(update.removed) {
deleteMarker(update.id);
} else {
const layer = updatePointMarker(layers.get(update.id), update.payload as LiveAtlasPointMarker, converter);
const layer = updateMarker(layers.get(update.id), update.payload as LiveAtlasAreaMarker, converter);
if(!layers.has(update.id)) {
props.layerGroup.addLayer(layer);
@ -80,20 +82,20 @@ export default defineComponent({
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
converter = newValue.locationToLatLng.bind(newValue);
for (const [id, marker] of nonReactiveState.markers.get(props.set.id)!.points) {
updatePointMarker(layers.get(id), marker, converter);
for (const [id, area] of nonReactiveState.markers.get(props.set.id)!) {
updateMarker(layers.get(id), area, converter);
}
}
});
onMounted(() => {
createMarkers();
registerTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.POINT);
registerUpdateHandler(handleUpdate, props.set.id);
});
onUnmounted(() => {
unregisterTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.POINT);
unregisterUpdateHandler(handleUpdate, props.set.id);
});
},

View File

@ -1,105 +0,0 @@
<!--
- Copyright 2021 James Lyne
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<script lang="ts">
import {defineComponent, computed, onMounted, watch, onUnmounted} from "@vue/runtime-core";
import {useStore} from "@/store";
import {createArea, updateArea} from "@/util/areas";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import {LiveAtlasAreaMarker, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
import {DynmapMarkerUpdate} from "@/dynmap";
import {LiveAtlasMarkerType, registerTypeUpdateHandler, unregisterTypeUpdateHandler} from "@/util/markers";
export default defineComponent({
props: {
set: {
type: Object as () => LiveAtlasMarkerSet,
required: true,
},
layerGroup: {
type: Object as () => LiveAtlasLayerGroup,
required: true
}
},
setup(props) {
const store = useStore(),
currentMap = computed(() => store.state.currentMap),
layers = Object.freeze(new Map()) as Map<string, LiveAtlasPolygon | LiveAtlasPolyline>;
let converter = currentMap.value!.locationToLatLng.bind(currentMap.value);
const createAreas = () => {
nonReactiveState.markers.get(props.set.id)!.areas.forEach((area: LiveAtlasAreaMarker, id: string) => {
const layer = createArea(area, converter);
layers.set(id, layer);
props.layerGroup.addLayer(layer);
});
};
const deleteArea = (id: string) => {
let area = layers.get(id) as LiveAtlasPolyline;
if(!area) {
return;
}
props.layerGroup.removeLayer(area);
layers.delete(id);
};
const handleUpdate = (update: DynmapMarkerUpdate) => {
if(update.removed) {
deleteArea(update.id);
} else {
const layer = updateArea(layers.get(update.id), update.payload as LiveAtlasAreaMarker, converter);
if(!layers.has(update.id)) {
props.layerGroup.addLayer(layer);
}
layers.set(update.id, layer);
}
};
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
converter = newValue.locationToLatLng.bind(newValue);
for (const [id, area] of nonReactiveState.markers.get(props.set.id)!.areas) {
updateArea(layers.get(id), area, converter);
}
}
});
onMounted(() => {
createAreas();
registerTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.AREA);
});
onUnmounted(() => {
unregisterTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.AREA);
});
},
render() {
return null;
}
});
</script>

View File

@ -1,105 +0,0 @@
<!--
- Copyright 2021 James Lyne
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<script lang="ts">
import {defineComponent, computed, onMounted, watch, onUnmounted} from "@vue/runtime-core";
import {useStore} from "@/store";
import {createCircle, updateCircle} from "@/util/circles";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasCircleMarker, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
import {DynmapMarkerUpdate} from "@/dynmap";
import {LiveAtlasMarkerType, registerTypeUpdateHandler, unregisterTypeUpdateHandler} from "@/util/markers";
export default defineComponent({
props: {
set: {
type: Object as () => LiveAtlasMarkerSet,
required: true,
},
layerGroup: {
type: Object as () => LiveAtlasLayerGroup,
required: true
}
},
setup(props) {
const store = useStore(),
currentMap = computed(() => store.state.currentMap),
layers = Object.freeze(new Map<string, LiveAtlasPolyline | LiveAtlasPolygon>());
let converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
const createCircles = () => {
nonReactiveState.markers.get(props.set.id)!.circles.forEach((circle: LiveAtlasCircleMarker, id: string) => {
const layer = createCircle(circle, converter);
layers.set(id, layer);
props.layerGroup.addLayer(layer);
});
};
const deleteCircle = (id: string) => {
let circle = layers.get(id) as LiveAtlasPolyline;
if (!circle) {
return;
}
props.layerGroup.removeLayer(circle);
layers.delete(id);
};
const handleUpdate = (update: DynmapMarkerUpdate) => {
if(update.removed) {
deleteCircle(update.id);
} else {
const layer = updateCircle(layers.get(update.id), update.payload as LiveAtlasCircleMarker, converter);
if(!layers.has(update.id)) {
props.layerGroup.addLayer(layer);
}
layers.set(update.id, layer);
}
};
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for (const [id, circle] of nonReactiveState.markers.get(props.set.id)!.circles) {
updateCircle(layers.get(id), circle, converter);
}
}
});
onMounted(() => {
createCircles();
registerTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.CIRCLE);
});
onUnmounted(() => {
unregisterTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.CIRCLE);
});
},
render() {
return null;
}
});
</script>

View File

@ -1,104 +0,0 @@
<!--
- Copyright 2021 James Lyne
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<script lang="ts">
import {defineComponent, computed, onMounted, watch, onUnmounted} from "@vue/runtime-core";
import {useStore} from "@/store";
import {createLine, updateLine} from "@/util/lines";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasLineMarker, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
import {DynmapMarkerUpdate} from "@/dynmap";
import {LiveAtlasMarkerType, registerTypeUpdateHandler, unregisterTypeUpdateHandler} from "@/util/markers";
export default defineComponent({
props: {
set: {
type: Object as () => LiveAtlasMarkerSet,
required: true,
},
layerGroup: {
type: Object as () => LiveAtlasLayerGroup,
required: true
}
},
setup(props) {
const store = useStore(),
currentMap = computed(() => store.state.currentMap),
layers = Object.freeze(new Map<string, LiveAtlasPolyline>());
let converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap)
const createLines = () => {
nonReactiveState.markers.get(props.set.id)!.lines.forEach((line: LiveAtlasLineMarker, id: string) => {
const layer = createLine(line, converter);
layers.set(id, layer);
props.layerGroup.addLayer(layer);
});
};
const deleteLine = (id: string) => {
let line = layers.get(id) as LiveAtlasPolyline;
if (!line) {
return;
}
props.layerGroup.removeLayer(line);
layers.delete(id);
};
const handleUpdate = (update: DynmapMarkerUpdate) => {
if(update.removed) {
deleteLine(update.id);
} else {
const layer = updateLine(layers.get(update.id), update.payload as LiveAtlasLineMarker, converter);
if(!layers.has(update.id)) {
props.layerGroup.addLayer(layer);
}
layers.set(update.id, layer);
}
};
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for (const [id, line] of nonReactiveState.markers.get(props.set.id)!.lines) {
updateLine(layers.get(id), line, converter);
}
}
});
onMounted(() => {
createLines();
registerTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.LINE);
});
onUnmounted(() => {
unregisterTypeUpdateHandler(handleUpdate, props.set.id, LiveAtlasMarkerType.LINE);
});
},
render() {
return null;
}
});
</script>

26
src/index.d.ts vendored
View File

@ -22,6 +22,7 @@ import {CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl";
import {ClockControlOptions} from "@/leaflet/control/ClockControl";
import {LogoControlOptions} from "@/leaflet/control/LogoControl";
import {globalMessages, serverMessages} from "../messages";
import {LiveAtlasMarkerType} from "@/util/markers";
declare module "*.png" {
const value: any;
@ -178,14 +179,9 @@ interface LiveAtlasMarkerSet {
showLabels?: boolean;
}
interface LiveAtlasMarkerSetContents {
points: Map<string, LiveAtlasPointMarker>,
areas: Map<string, LiveAtlasAreaMarker>;
lines: Map<string, LiveAtlasLineMarker>;
circles: Map<string, LiveAtlasCircleMarker>;
}
interface LiveAtlasMarker {
id: string;
type: LiveAtlasMarkerType;
tooltip: string;
tooltipHTML?: string;
popup?: string;
@ -196,6 +192,7 @@ interface LiveAtlasMarker {
}
interface LiveAtlasPointMarker extends LiveAtlasMarker {
type: LiveAtlasMarkerType.POINT;
dimensions: PointTuple;
icon: string;
}
@ -204,20 +201,21 @@ interface LiveAtlasPathMarker extends LiveAtlasMarker {
style: PathOptions;
}
interface LiveAtlasAreaMarker extends LiveAtlasPathMarker {
style: PolylineOptions;
outline: boolean;
points: Coordinate[] | Coordinate[][] | Coordinate[][][]
}
interface LiveAtlasLineMarker extends LiveAtlasPathMarker {
type: LiveAtlasMarkerType.LINE;
points: Coordinate[];
style: PolylineOptions;
}
interface LiveAtlasAreaMarker extends LiveAtlasLineMarker {
type: LiveAtlasMarkerType.AREA;
outline: boolean;
points: Coordinate[] | Coordinate[][] | Coordinate[][][];
}
interface LiveAtlasCircleMarker extends LiveAtlasPathMarker {
type: LiveAtlasMarkerType.CIRCLE;
radius: PointTuple;
style: PathOptions;
}
interface HeadQueueEntry {

View File

@ -15,8 +15,8 @@
*/
import {
HeadQueueEntry,
LiveAtlasMarkerSet, LiveAtlasMarkerSetContents,
HeadQueueEntry, LiveAtlasMarker,
LiveAtlasMarkerSet,
LiveAtlasPlayer,
LiveAtlasServerDefinition,
LiveAtlasWorldDefinition
@ -48,7 +48,7 @@ export default class DynmapMapProvider extends MapProvider {
private updateInterval: number = 3000;
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
private markers = new Map<string, LiveAtlasMarkerSetContents>();
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
constructor(config: LiveAtlasServerDefinition) {
super(config);
@ -73,15 +73,16 @@ export default class DynmapMapProvider extends MapProvider {
}
const set: MarkerSet = response.sets[key],
markerSet = buildMarkerSet(key, set);
markerSet = buildMarkerSet(key, set),
markers = new Map<string, LiveAtlasMarker>();
buildMarkers(set.markers || {}, markers);
buildAreas(set.areas || {}, markers);
buildLines(set.lines || {}, markers);
buildCircles(set.circles || {}, markers);
this.markerSets.set(key, markerSet);
this.markers.set(key, Object.seal({
points: buildMarkers(set.markers || {}),
areas: buildAreas(set.areas || {}),
lines: buildLines(set.lines || {}),
circles: buildCircles(set.circles || {}),
}));
this.markers.set(key, markers);
}
}

View File

@ -20,11 +20,11 @@ import {
LiveAtlasCircleMarker,
LiveAtlasComponentConfig,
LiveAtlasDimension,
LiveAtlasLineMarker,
LiveAtlasPointMarker,
LiveAtlasMarkerSet, LiveAtlasMarkerSetContents,
LiveAtlasLineMarker, LiveAtlasMarker,
LiveAtlasMarkerSet,
LiveAtlasPartialComponentConfig,
LiveAtlasPlayer,
LiveAtlasPointMarker,
LiveAtlasServerConfig,
LiveAtlasServerDefinition,
LiveAtlasServerMessageConfig,
@ -35,6 +35,7 @@ import {MutationTypes} from "@/store/mutation-types";
import MapProvider from "@/providers/MapProvider";
import {ActionTypes} from "@/store/action-types";
import {getMiddleFromPoints, stripHTML, titleColoursRegex} from "@/util";
import {LiveAtlasMarkerType} from "@/util/markers";
export default class Pl3xmapMapProvider extends MapProvider {
private configurationAbort?: AbortController = undefined;
@ -57,7 +58,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
}> = new Map();
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
private markers = new Map<string, LiveAtlasMarkerSetContents>();
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
constructor(config: LiveAtlasServerDefinition) {
super(config);
@ -244,31 +245,33 @@ export default class Pl3xmapMapProvider extends MapProvider {
return;
}
const id = set.id;
const points: Map<string, LiveAtlasPointMarker> = Object.freeze(new Map()),
circles: Map<string, LiveAtlasCircleMarker> = Object.freeze(new Map()),
areas: Map<string, LiveAtlasAreaMarker> = Object.freeze(new Map()),
lines: Map<string, LiveAtlasLineMarker> = Object.freeze(new Map());
const id = set.id,
markers: Map<string, LiveAtlasMarker> = Object.freeze(new Map());
(set.markers || []).forEach((marker: any) => {
let markerId;
switch(marker.type) {
case 'icon':
points.set(`marker-${points.size}`, Pl3xmapMapProvider.buildMarker(marker));
markerId = `point_${markers.size}`;
markers.set(markerId, Pl3xmapMapProvider.buildMarker(markerId, marker));
break;
case 'polyline':
lines.set(`line-${lines.size}`, Pl3xmapMapProvider.buildLine(marker));
markerId = `line_${markers.size}`;
markers.set(markerId, Pl3xmapMapProvider.buildLine(markerId, marker));
break;
case 'rectangle':
case 'polygon':
areas.set(`area-${areas.size}`, Pl3xmapMapProvider.buildArea(marker));
markerId = `area_${markers.size}`;
markers.set(markerId, Pl3xmapMapProvider.buildArea(markerId, marker));
break;
case 'circle':
case 'ellipse':
circles.set(`circle-${circles.size}`, Pl3xmapMapProvider.buildCircle(marker));
markerId = `circle_${markers.size}`;
markers.set(markerId, Pl3xmapMapProvider.buildCircle(markerId, marker));
break;
default:
@ -283,12 +286,14 @@ export default class Pl3xmapMapProvider extends MapProvider {
priority: set.order || 0,
showLabels: false
});
this.markers.set(id, Object.seal({points, circles, areas, lines}));
this.markers.set(id, markers);
});
}
private static buildMarker(marker: any): LiveAtlasPointMarker {
private static buildMarker(id: string, marker: any): LiveAtlasPointMarker {
return {
id,
type: LiveAtlasMarkerType.POINT,
location: {
x: marker.point?.x || 0,
y: 0,
@ -304,7 +309,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
};
}
private static buildArea(area: any): LiveAtlasAreaMarker {
private static buildArea(id: string, area: any): LiveAtlasAreaMarker {
let points = area.points;
if(area.type === 'rectangle') {
@ -317,6 +322,8 @@ export default class Pl3xmapMapProvider extends MapProvider {
}
return {
id,
type: LiveAtlasMarkerType.AREA,
style: {
stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true,
color: area.color || '#3388ff',
@ -338,10 +345,12 @@ export default class Pl3xmapMapProvider extends MapProvider {
};
}
private static buildLine(line: any): LiveAtlasLineMarker {
private static buildLine(id: string, line: any): LiveAtlasLineMarker {
const points = this.addY(line.points);
return {
id,
type: LiveAtlasMarkerType.LINE,
style: {
stroke: typeof line.stroke !== 'undefined' ? !!line.stroke : true,
color: line.color || '#3388ff',
@ -358,8 +367,10 @@ export default class Pl3xmapMapProvider extends MapProvider {
};
}
private static buildCircle(circle: any): LiveAtlasCircleMarker {
private static buildCircle(id: string, circle: any): LiveAtlasCircleMarker {
return {
id,
type: LiveAtlasMarkerType.CIRCLE,
location: {
x: circle.center?.x || 0,
y: 0,

View File

@ -32,10 +32,6 @@ import {
LiveAtlasGlobalConfig,
LiveAtlasServerMessageConfig,
LiveAtlasPlayer,
LiveAtlasCircleMarker,
LiveAtlasLineMarker,
LiveAtlasAreaMarker,
LiveAtlasPointMarker,
LiveAtlasMarkerSet,
LiveAtlasServerDefinition,
LiveAtlasServerConfig,
@ -43,12 +39,11 @@ import {
LiveAtlasPartialComponentConfig,
LiveAtlasComponentConfig,
LiveAtlasUIModal,
LiveAtlasSidebarSectionState, LiveAtlasMarkerSetContents
LiveAtlasSidebarSectionState, LiveAtlasMarker
} from "@/index";
import DynmapMapProvider from "@/providers/DynmapMapProvider";
import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider";
import {getGlobalMessages} from "@/util";
import {LiveAtlasMarkerType} from "@/util/markers";
export type CurrentMapPayload = {
worldName: string;
@ -63,7 +58,7 @@ export type Mutations<S = State> = {
[MutationTypes.SET_WORLDS](state: S, worlds: Array<LiveAtlasWorldDefinition>): void
[MutationTypes.SET_COMPONENTS](state: S, components: LiveAtlasPartialComponentConfig | LiveAtlasComponentConfig): void
[MutationTypes.SET_MARKER_SETS](state: S, markerSets: Map<string, LiveAtlasMarkerSet>): void
[MutationTypes.SET_MARKERS](state: S, markers: Map<string, LiveAtlasMarkerSetContents>): void
[MutationTypes.SET_MARKERS](state: S, markers: Map<string, Map<string, LiveAtlasMarker>>): void
[MutationTypes.SET_WORLD_STATE](state: S, worldState: LiveAtlasWorldState): void
[MutationTypes.ADD_MARKER_SET_UPDATES](state: S, updates: DynmapMarkerSetUpdate[]): void
[MutationTypes.ADD_MARKER_UPDATES](state: S, updates: DynmapMarkerUpdate[]): void
@ -209,17 +204,12 @@ export const mutations: MutationTree<State> & Mutations = {
for(const entry of markerSets) {
state.markerSets.set(entry[0], entry[1]);
nonReactiveState.markers.set(entry[0], {
points: new Map<string, LiveAtlasPointMarker>(),
areas: new Map<string, LiveAtlasAreaMarker>(),
lines: new Map<string, LiveAtlasLineMarker>(),
circles: new Map<string, LiveAtlasCircleMarker>(),
});
nonReactiveState.markers.set(entry[0], new Map());
}
},
//Sets the existing marker sets from the last marker fetch
[MutationTypes.SET_MARKERS](state: State, markers: Map<string, LiveAtlasMarkerSetContents>) {
[MutationTypes.SET_MARKERS](state: State, markers: Map<string, Map<string, LiveAtlasMarker>>) {
nonReactiveState.markers.clear();
for(const entry of markers) {
@ -261,12 +251,7 @@ export const mutations: MutationTree<State> & Mutations = {
label: update.payload.label,
hidden: update.payload.hidden,
});
nonReactiveState.markers.set(update.id, {
points: new Map<string, LiveAtlasPointMarker>(),
areas: new Map<string, LiveAtlasAreaMarker>(),
lines: new Map<string, LiveAtlasLineMarker>(),
circles: new Map<string, LiveAtlasCircleMarker>(),
});
nonReactiveState.markers.set(update.id, new Map());
}
}
}
@ -281,41 +266,12 @@ export const mutations: MutationTree<State> & Mutations = {
continue;
}
setContents = nonReactiveState.markers.get(update.set) as LiveAtlasMarkerSetContents;
setContents = nonReactiveState.markers.get(update.set) as Map<string, LiveAtlasMarker>;
switch (update.type) {
case LiveAtlasMarkerType.POINT:
if(update.removed) {
setContents.points.delete(update.id);
setContents.delete(update.id);
} else {
setContents.points.set(update.id, update.payload as LiveAtlasPointMarker);
}
continue;
case LiveAtlasMarkerType.AREA:
if(update.removed) {
setContents.areas.delete(update.id);
} else {
setContents.areas.set(update.id, update.payload as LiveAtlasAreaMarker);
}
continue;
case LiveAtlasMarkerType.LINE:
if(update.removed) {
setContents.lines.delete(update.id);
} else {
setContents.lines.set(update.id, update.payload as LiveAtlasLineMarker);
}
continue;
case LiveAtlasMarkerType.CIRCLE:
if(update.removed) {
setContents.circles.delete(update.id);
} else {
setContents.circles.set(update.id, update.payload as LiveAtlasCircleMarker);
}
setContents.set(update.id, update.payload);
}
}

View File

@ -36,7 +36,7 @@ import {
LiveAtlasChat,
LiveAtlasUIModal,
LiveAtlasSidebarSectionState,
LiveAtlasMarkerSetContents
LiveAtlasMarker
} from "@/index";
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
import {getMessages} from "@/util";
@ -220,5 +220,5 @@ export const state: State = {
};
export const nonReactiveState = Object.freeze({
markers: new Map<string, LiveAtlasMarkerSetContents>(),
markers: new Map<string, Map<string, LiveAtlasMarker>>(),
});

View File

@ -21,8 +21,9 @@ import {
LiveAtlasCircleMarker,
LiveAtlasComponentConfig,
LiveAtlasDimension,
LiveAtlasLineMarker,
LiveAtlasPointMarker, LiveAtlasPlayerImageSize,
LiveAtlasLineMarker, LiveAtlasMarker,
LiveAtlasPlayerImageSize,
LiveAtlasPointMarker,
LiveAtlasServerConfig,
LiveAtlasServerMessageConfig,
LiveAtlasWorldDefinition
@ -40,7 +41,11 @@ import {getLinePoints} from "@/util/lines";
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
import {
Configuration,
Marker, MarkerArea, MarkerCircle, MarkerLine, MarkerSet,
Marker,
MarkerArea,
MarkerCircle,
MarkerLine,
MarkerSet,
Options,
WorldConfiguration,
WorldMapConfiguration
@ -275,21 +280,20 @@ export function buildMarkerSet(id: string, data: MarkerSet): any {
}
}
export function buildMarkers(data: any): Map<string, LiveAtlasPointMarker> {
const markers = Object.freeze(new Map()) as Map<string, LiveAtlasPointMarker>;
export function buildMarkers(data: any, list: Map<string, LiveAtlasMarker>): void {
let id;
for (const key in data) {
if (!Object.prototype.hasOwnProperty.call(data, key)) {
continue;
}
markers.set(key, buildMarker(data[key]));
id = `point_${key}`;
list.set(id, buildMarker(id, data[key]));
}
return markers;
}
export function buildMarker(data: Marker): LiveAtlasPointMarker {
export function buildMarker(id: string, data: Marker): LiveAtlasPointMarker {
let dimensions;
if(data.dim) {
@ -301,6 +305,8 @@ export function buildMarker(data: Marker): LiveAtlasPointMarker {
}
const marker = {
id,
type: LiveAtlasMarkerType.POINT,
location: {
x: data.x || 0,
y: data.y || 0,
@ -314,7 +320,7 @@ export function buildMarker(data: Marker): LiveAtlasPointMarker {
tooltipHTML: data.markup ? data.label : undefined,
popup: data.desc || undefined,
isPopupHTML: true,
};
} as LiveAtlasPointMarker;
//Fix double escaping on non-HTML labels
if(!marker.tooltipHTML) {
@ -324,26 +330,27 @@ export function buildMarker(data: Marker): LiveAtlasPointMarker {
return marker;
}
export function buildAreas(data: any): Map<string, LiveAtlasAreaMarker> {
const areas = Object.freeze(new Map()) as Map<string, LiveAtlasAreaMarker>;
export function buildAreas(data: any, list: Map<string, LiveAtlasMarker>): void {
let id;
for (const key in data) {
if (!Object.prototype.hasOwnProperty.call(data, key)) {
continue;
}
areas.set(key, buildArea(data[key]));
id = `area_${key}`;
list.set(id, buildArea(id, data[key]));
}
return areas;
}
export function buildArea(area: MarkerArea): LiveAtlasAreaMarker {
export function buildArea(id: string, area: MarkerArea): LiveAtlasAreaMarker {
const x = area.x || [0, 0],
y = [area.ybottom || 0, area.ytop || 0] as [number, number],
z = area.z || [0, 0];
return {
id,
type: LiveAtlasMarkerType.AREA,
style: {
color: area.color || '#ff0000',
opacity: area.opacity || 1,
@ -364,26 +371,27 @@ export function buildArea(area: MarkerArea): LiveAtlasAreaMarker {
};
}
export function buildLines(data: any): Map<string, LiveAtlasLineMarker> {
const lines = Object.freeze(new Map()) as Map<string, LiveAtlasLineMarker>;
export function buildLines(data: any, list: Map<string, LiveAtlasMarker>): void {
let id;
for (const key in data) {
if (!Object.prototype.hasOwnProperty.call(data, key)) {
continue;
}
lines.set(key, buildLine(data[key]));
id = `line_${key}`;
list.set(id, buildLine(id, data[key]));
}
return lines;
}
export function buildLine(line: MarkerLine): LiveAtlasLineMarker {
export function buildLine(id: string, line: MarkerLine): LiveAtlasLineMarker {
const x = line.x || [0, 0],
y = line.y || [0, 0],
z = line.z || [0, 0];
return {
id,
type: LiveAtlasMarkerType.LINE,
style: {
color: line.color || '#ff0000',
opacity: line.opacity || 1,
@ -401,22 +409,23 @@ export function buildLine(line: MarkerLine): LiveAtlasLineMarker {
};
}
export function buildCircles(data: any): Map<string, LiveAtlasCircleMarker> {
const circles = Object.freeze(new Map()) as Map<string, LiveAtlasCircleMarker>;
export function buildCircles(data: any, list: Map<string, LiveAtlasMarker>): void {
let id;
for (const key in data) {
if (!Object.prototype.hasOwnProperty.call(data, key)) {
continue;
}
circles.set(key, buildCircle(data[key]));
id = `circle_${key}`;
list.set(id, buildCircle(id, data[key]));
}
return circles;
}
export function buildCircle(circle: MarkerCircle): LiveAtlasCircleMarker {
export function buildCircle(id: string, circle: MarkerCircle): LiveAtlasCircleMarker {
return {
id,
type: LiveAtlasMarkerType.CIRCLE,
location: {
x: circle.x || 0,
y: circle.y || 0,
@ -499,17 +508,21 @@ export function buildUpdates(data: Array<any>, lastUpdate: Date) {
updates.markerSets.push(Object.freeze(update as DynmapMarkerSetUpdate));
} else {
if (entry.msg.startsWith("marker")) {
update.id = `point_${entry.id}`;
update.type = LiveAtlasMarkerType.POINT;
update.payload = update.removed ? undefined : buildMarker(entry);
update.payload = update.removed ? undefined : buildMarker(update.id, entry);
} else if (entry.msg.startsWith("area")) {
update.id = `area_${entry.id}`;
update.type = LiveAtlasMarkerType.AREA;
update.payload = update.removed ? undefined : buildArea(entry);
update.payload = update.removed ? undefined : buildArea(update.id, entry);
} else if (entry.msg.startsWith("circle")) {
update.id = `circle_${entry.id}`;
update.type = LiveAtlasMarkerType.CIRCLE;
update.payload = update.removed ? undefined : buildCircle(entry);
update.payload = update.removed ? undefined : buildCircle(update.id, entry);
} else if (entry.msg.startsWith("line")) {
update.id = `line_${entry.id}`;
update.type = LiveAtlasMarkerType.LINE;
update.payload = update.removed ? undefined : buildLine(entry);
update.payload = update.removed ? undefined : buildLine(update.id, entry);
}
updates.markers.push(Object.freeze(update as DynmapMarkerUpdate));

View File

@ -22,6 +22,21 @@ import {ActionTypes} from "@/store/action-types";
import {DynmapMarkerUpdate} from "@/dynmap";
import {computed, watch} from "@vue/runtime-core";
import {ComputedRef} from "@vue/reactivity";
import {
LiveAtlasAreaMarker,
LiveAtlasCircleMarker,
LiveAtlasLineMarker,
LiveAtlasMarker,
LiveAtlasPointMarker
} from "@/index";
import {Layer} from "leaflet";
import {createCircle, updateCircle} from "@/util/circles";
import {createPointMarker, updatePointMarker} from "@/util/points";
import {createArea, updateArea} from "@/util/areas";
import {createLine, updateLine} from "@/util/lines";
import {GenericMarker} from "@/leaflet/marker/GenericMarker";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
export type LiveAtlasMarkerUpdateCallback = ((update: DynmapMarkerUpdate) => void);
@ -35,8 +50,7 @@ export enum LiveAtlasMarkerType {
let updateFrame = 0;
let pendingUpdates: ComputedRef;
const setHandlers: { [key:string]: Set<LiveAtlasMarkerUpdateCallback>} = {};
const typeHandlers: { [key:string]: Map<LiveAtlasMarkerType, Set<LiveAtlasMarkerUpdateCallback>>} = {};
const updateHandlers: { [key:string]: Set<LiveAtlasMarkerUpdateCallback>} = {};
export const startUpdateHandling = () => {
const store = useStore();
@ -58,41 +72,19 @@ export const stopUpdateHandling = () => {
}
export const registerUpdateHandler = (callback: LiveAtlasMarkerUpdateCallback, set: string) => {
if(!setHandlers[set]) {
setHandlers[set] = new Set();
if(!updateHandlers[set]) {
updateHandlers[set] = new Set();
}
setHandlers[set].add(callback);
}
export const registerTypeUpdateHandler = (callback: LiveAtlasMarkerUpdateCallback, set: string, type: LiveAtlasMarkerType) => {
if(!typeHandlers[set]) {
typeHandlers[set] = new Map();
}
if(typeHandlers[set].has(type)) {
typeHandlers[set].get(type)!.add(callback);
} else {
typeHandlers[set].set(type, new Set([callback]));
}
updateHandlers[set].add(callback);
}
export const unregisterUpdateHandler = (callback: LiveAtlasMarkerUpdateCallback, set: string) => {
if(!setHandlers[set]) {
if(!updateHandlers[set]) {
return;
}
setHandlers[set].delete(callback);
}
export const unregisterTypeUpdateHandler = (callback: LiveAtlasMarkerUpdateCallback, set: string, type: LiveAtlasMarkerType) => {
if(typeHandlers[set]) {
return;
}
if(typeHandlers[set].has(type)) {
typeHandlers[set].get(type)!.delete(callback);
}
updateHandlers[set].delete(callback);
}
const handlePendingUpdates = async () => {
@ -100,12 +92,8 @@ const handlePendingUpdates = async () => {
updates = await store.dispatch(ActionTypes.POP_MARKER_UPDATES, 10);
for(const update of updates) {
if(setHandlers[update.set]) {
setHandlers[update.set].forEach(callback => callback(update));
}
if(typeHandlers[update.set] && typeHandlers[update.set].has(update.type)) {
typeHandlers[update.set].get(update.type)!.forEach(callback => callback(update));
if(updateHandlers[update.set]) {
updateHandlers[update.set].forEach(callback => callback(update));
}
}
@ -116,3 +104,29 @@ const handlePendingUpdates = async () => {
updateFrame = 0;
}
};
export const createMarker = (options: LiveAtlasMarker, converter: Function): Layer => {
switch(options.type) {
case LiveAtlasMarkerType.POINT:
return createPointMarker(options as LiveAtlasPointMarker, converter);
case LiveAtlasMarkerType.AREA:
return createArea(options as LiveAtlasAreaMarker, converter);
case LiveAtlasMarkerType.LINE:
return createLine(options as LiveAtlasLineMarker, converter);
case LiveAtlasMarkerType.CIRCLE:
return createCircle(options as LiveAtlasCircleMarker, converter);
}
}
export const updateMarker = (marker: Layer | undefined, options: LiveAtlasMarker, converter: Function): Layer => {
switch(options.type) {
case LiveAtlasMarkerType.POINT:
return updatePointMarker(marker as GenericMarker, options as LiveAtlasPointMarker, converter);
case LiveAtlasMarkerType.AREA:
return updateArea(marker as LiveAtlasPolygon | LiveAtlasPolyline, options as LiveAtlasAreaMarker, converter);
case LiveAtlasMarkerType.LINE:
return updateLine(marker as LiveAtlasPolyline, options as LiveAtlasLineMarker, converter);
case LiveAtlasMarkerType.CIRCLE:
return updateCircle(marker as LiveAtlasPolyline | LiveAtlasPolygon, options as LiveAtlasCircleMarker, converter);
}
}