]> git.localhorst.tv Git - alttp.git/commitdiff
zootr map labels
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 27 May 2025 15:20:46 +0000 (17:20 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 27 May 2025 15:20:46 +0000 (17:20 +0200)
resources/js/components/zootr/MixedPoolsTracker.js
resources/sass/zootr.scss

index f27b547c627540e8b7be6ae165ce606e8bedc0c7..a97dd3fafa53b7af74b355264d8cb7a96f634169 100644 (file)
@@ -17,6 +17,7 @@ const AREAS = [
                                off: { x: 0, y: 0 },
                                scale: 1.3,
                        },
+                       labelPos: { x: 90, y: 70 },
                },
                entrances: [
                        {
@@ -126,6 +127,7 @@ const AREAS = [
                                off: { x: 0, y: 0 },
                                scale: 1.3,
                        },
+                       labelPos: { x: 40, y: 85 },
                },
                entrances: [
                        {
@@ -208,6 +210,7 @@ const AREAS = [
                                off: { x: -20, y: 0 },
                                scale: 4.3,
                        },
+                       labelPos: { x: 15, y: 110 },
                },
                entrances: [
                        {
@@ -271,6 +274,7 @@ const AREAS = [
                                off: { x: 0, y: -5 },
                                scale: 1.5,
                        },
+                       labelPos: { x: 65, y: 35 },
                },
                entrances: [
                        {
@@ -352,6 +356,7 @@ const AREAS = [
                                off: { x: -7, y: 0 },
                                scale: 1.7,
                        },
+                       labelPos: { x: 20, y: 95 },
                },
                entrances: [
                        {
@@ -515,6 +520,7 @@ const AREAS = [
                                off: { x: 0, y: -6 },
                                scale: 1.0,
                        },
+                       labelPos: { x: 38, y: 30 },
                },
                entrances: [
                        {
@@ -632,6 +638,7 @@ const AREAS = [
                                off: { x: -3, y: -3 },
                                scale: 3.6,
                        },
+                       labelPos: { x: -2, y: 25 },
                },
                entrances: [
                        {
@@ -677,6 +684,7 @@ const AREAS = [
                                off: { x: 0, y: 0 },
                                scale: 1.2,
                        },
+                       labelPos: { x: 25, y: 65 },
                },
                entrances: [
                        {
@@ -740,6 +748,7 @@ const AREAS = [
                                off: { x: -16, y: 0 },
                                scale: 1.8,
                        },
+                       labelPos: { x: 100, y: 10 },
                },
                entrances: [
                        {
@@ -894,6 +903,7 @@ const AREAS = [
                                off: { x: 0, y: 0 },
                                scale: 1.3,
                        },
+                       labelPos: { x: 60, y: 40 },
                },
                entrances: [
                        {
@@ -967,6 +977,7 @@ const AREAS = [
                                off: { x: -15, y: -5 },
                                scale: 2.3,
                        },
+                       labelPos: { x: 18, y: 40 },
                },
                entrances: [
                        {
@@ -1030,6 +1041,7 @@ const AREAS = [
                                off: { x: -5, y: 0 },
                                scale: 2.1,
                        },
+                       labelPos: { x: 60, y: 35 },
                },
                entrances: [
                        {
@@ -1084,6 +1096,7 @@ const AREAS = [
                                off: { x: -15, y: -5 },
                                scale: 1.9,
                        },
+                       labelPos: { x: 70, y: 65 },
                },
                entrances: [
                        {
@@ -1156,6 +1169,7 @@ const AREAS = [
                                off: { x: -22, y: -6 },
                                scale: 2.6,
                        },
+                       labelPos: { x: 40, y: 50 },
                },
                entrances: [
                        {
@@ -1219,6 +1233,7 @@ const AREAS = [
                                off: { x: -17, y: -5 },
                                scale: 1.9,
                        },
+                       labelPos: { x: 20, y: 55 },
                },
                entrances: [
                        {
@@ -1292,6 +1307,7 @@ const AREAS = [
                                off: { x: -5, y: -35 },
                                scale: 2.5,
                        },
+                       labelPos: { x: 15, y: 50 },
                },
                entrances: [
                        {
@@ -1346,6 +1362,7 @@ const AREAS = [
                                off: { x: 0, y: -2 },
                                scale: 2.0,
                        },
+                       labelPos: { x: 50, y: 50 },
                },
                entrances: [
                        {
@@ -1425,6 +1442,7 @@ const AREAS = [
                                off: { x: -15, y: -3 },
                                scale: 1.9,
                        },
+                       labelPos: { x: 52, y: 62 },
                },
                entrances: [
                        {
@@ -1497,6 +1515,7 @@ const AREAS = [
                                off: { x: -12, y: 0 },
                                scale: 3.8,
                        },
+                       labelPos: { x: -10, y: 50 },
                },
                entrances: [
                        {
@@ -1579,6 +1598,7 @@ const AREAS = [
                                off: { x: -2, y: 0 },
                                scale: 2.0,
                        },
+                       labelPos: { x: 25, y: 105 },
                },
                entrances: [
                        {
@@ -1995,6 +2015,7 @@ const AREAS = [
                                short: 'Minuet',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-minuet.png',
                        },
                        {
                                id: 'bolero',
@@ -2004,6 +2025,7 @@ const AREAS = [
                                short: 'Bolero',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-bolero.png',
                        },
                        {
                                id: 'serenade',
@@ -2013,6 +2035,7 @@ const AREAS = [
                                short: 'Serenade',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-serenade.png',
                        },
                        {
                                id: 'nocturne',
@@ -2022,6 +2045,7 @@ const AREAS = [
                                short: 'Nocturne',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-nocturne.png',
                        },
                        {
                                id: 'requiem',
@@ -2031,6 +2055,7 @@ const AREAS = [
                                short: 'Requiem',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-requiem.png',
                        },
                        {
                                id: 'prelude',
@@ -2040,6 +2065,7 @@ const AREAS = [
                                short: 'Prelude',
                                oneway: true,
                                type: 'WarpSong',
+                               icon: '/media/oot/icons/song-prelude.png',
                        },
                ],
        },
@@ -2058,6 +2084,8 @@ const AREAS = [
                                short: 'Child',
                                oneway: true,
                                type: 'Spawn',
+                               icon: '/media/oot/icons/link-child.png',
+                               iconSize: 10,
                        },
                        {
                                id: 'adult',
@@ -2067,6 +2095,7 @@ const AREAS = [
                                short: 'Adult',
                                oneway: true,
                                type: 'Spawn',
+                               icon: '/media/oot/icons/link-adult.png',
                        },
                ],
        },
@@ -2085,6 +2114,7 @@ const AREAS = [
                                short: 'LH Owl',
                                oneway: true,
                                type: 'OwlDrop',
+                               icon: '/media/oot/icons/owl-lake.png',
                        },
                        {
                                id: 'dmtowl',
@@ -2094,6 +2124,7 @@ const AREAS = [
                                short: 'Trail Owl',
                                oneway: true,
                                type: 'OwlDrop',
+                               icon: '/media/oot/icons/owl-trail.png',
                        },
                ],
        },
@@ -2414,9 +2445,12 @@ const vecMul = (v, f) => ({ x: v.x * f, y: v.y * f });
 const MAPS = AREAS
        .filter((area) => !!area.map)
        .map((area) => ({
+               color: area.bgColor,
                id: area.id,
+               labelPos: area.map.labelPos ? vecAdd(area.map.pos, area.map.labelPos) : null,
                name: area.name,
                pos: area.map.pos,
+               short: area.short,
                size: area.map.size,
                bg: {
                        src: area.map.bg.src,
@@ -2689,6 +2723,31 @@ MapConnector.propTypes = {
        })
 };
 
+const MapAnnotation = ({ annotation }) => {
+       return <image
+               className="annotation"
+               href={annotation.icon}
+               x={annotation.pos.x}
+               y={annotation.pos.y}
+               width={annotation.size}
+               height={annotation.size}
+       >
+               <title>{annotation.name}</title>
+       </image>;
+};
+
+MapAnnotation.propTypes = {
+       annotation: PropTypes.shape({
+               icon: PropTypes.string,
+               name: PropTypes.string,
+               pos: PropTypes.shape({
+                       x: PropTypes.number,
+                       y: PropTypes.number,
+               }),
+               size: PropTypes.number,
+       }),
+};
+
 const MixedPoolsTracker = () => {
        const [connections, setConnections] = React.useState({});
        const [dragging, setDragging] = React.useState(null);
@@ -2816,6 +2875,36 @@ const MixedPoolsTracker = () => {
                return cs;
        }, [connections]);
 
+       const annotations = React.useMemo(() => {
+               const annotate = [
+                       'songs.minuet',
+                       'songs.bolero',
+                       'songs.serenade',
+                       'songs.nocturne',
+                       'songs.requiem',
+                       'songs.prelude',
+                       'spawns.child',
+                       'spawns.adult',
+                       'owls.lhowl',
+                       'owls.dmtowl',
+               ];
+               const ans = [];
+               annotate.forEach((id) => {
+                       if (!connections[id]) return;
+                       const srcEntrance = getEntrance(id);
+                       if (!srcEntrance) return;
+                       const dstMap = getMapEntrance(connections[id]);
+                       if (!dstMap) return;
+                       ans.push({
+                               icon: srcEntrance.icon,
+                               name: srcEntrance.name,
+                               pos: vecAdd(dstMap.pos, dstMap.annotationOffset || { x: 0, y: 0 }),
+                               size: srcEntrance.iconSize || 8,
+                       });
+               });
+               return ans;
+       }, [connections]);
+
        return <CONTEXT.Provider value={context}>
                <div className="mixed-pools-tracker">
                        <div className="columns">
@@ -2881,13 +2970,23 @@ const MixedPoolsTracker = () => {
                                        onContextMenu={(e) => { e.preventDefault(); e.stopPropagation(); }}
                                >
                                        {MAPS.map((map) =>
-                                               <g key={map.id} title={map.name}>
+                                               <g className="area" key={map.id} title={map.name}>
                                                        <image
                                                                href={map.bg.src}
                                                                pointerEvents="none"
                                                                x={map.bg.pos.x} y={map.bg.pos.y}
                                                                width={map.bg.size.x}
                                                        />
+                                                       {map.labelPos ?
+                                                               <text
+                                                                       className="area-label"
+                                                                       x={map.labelPos.x}
+                                                                       y={map.labelPos.y}
+                                                                       fill={map.color}
+                                                               >
+                                                                       {map.short}
+                                                               </text>
+                                                       : null}
                                                        {map.entrances.map((entrance) =>
                                                                <MapEntrance key={entrance.id} entrance={entrance} />
                                                        )}
@@ -2902,6 +3001,14 @@ const MixedPoolsTracker = () => {
                                                        />
                                                )}
                                        </g>
+                                       <g title="anotations">
+                                               {annotations.map((a) =>
+                                                       <MapAnnotation
+                                                               key={`${a.id}`}
+                                                               annotation={a}
+                                                       />
+                                               )}
+                                       </g>
                                </svg>
                        </div>
                </div>
index 3070837c7d855ccd26d44083430b358e8b3e4d47..766a2fd7205cde643e70fdccb7e858f26a8806b7 100644 (file)
                        stroke: #cc0000;
                        pointer-events: none;
                }
+               .annotation {
+                       pointer-events: none;
+               }
+               .area-label {
+                       pointer-events: none;
+                       font-size: 10px;
+                       font-weight: bold;
+                       stroke: #000000;
+                       stroke-width: 3px;
+                       paint-order: stroke fill;
+                       text-anchor: middle;
+                       alignment-baseline: middle;
+                       opacity: 0.25;
+               }
+               .area:hover .area-label {
+                       opacity: 1;
+               }
                .entrance {
                        &.is-trash {
                                fill: #000000;