From 5a7489e4ada3de2dbe21d994636ed0b8c0e567d3 Mon Sep 17 00:00:00 2001 From: EmeraldBlock Date: Mon, 26 Oct 2020 12:35:03 -0500 Subject: [PATCH] Allow for compasses for custom waypoints Waypoints that begin with "!" (or another prefix specified by COMPASS_PREFIX) will display a compass that functions identically to the hub compass. Because compasses are remembered by position, two markers in the same position will share a compass, leading to other small issues. Camera recentering is also now exact, with a slight change to how it operates. --- src/css/ingame_hud/waypoints.scss | 17 +++--- src/js/game/camera.js | 6 +- src/js/game/hud/parts/waypoints.js | 95 ++++++++++++++++++++++++------ 3 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/css/ingame_hud/waypoints.scss b/src/css/ingame_hud/waypoints.scss index 5a801196..115ef788 100644 --- a/src/css/ingame_hud/waypoints.scss +++ b/src/css/ingame_hud/waypoints.scss @@ -99,21 +99,20 @@ background: none !important; @include S(padding-left, 0); - canvas { + canvas.compass { @include S(width, 12px); @include S(height, 12px); @include S(margin-right, 1px); + pointer-events: none; } } - &.shapeIcon { - canvas { - @include S(width, 15px); - @include S(height, 15px); - pointer-events: none; - // Double invert, to make sure it has the right color - @include DarkThemeInvert(); - } + canvas.shapeIcon { + @include S(width, 15px); + @include S(height, 15px); + pointer-events: none; + // Double invert, to make sure it has the right color + @include DarkThemeInvert(); } } } diff --git a/src/js/game/camera.js b/src/js/game/camera.js index 107d1fb4..0438b616 100644 --- a/src/js/game/camera.js +++ b/src/js/game/camera.js @@ -958,9 +958,9 @@ export class Camera extends BasicSerializableObject { if (!this.currentlyMoving && this.desiredCenter !== null) { const diff = this.center.direction(this.desiredCenter); const length = diff.length(); - const tolerance = 1 / this.zoomLevel; - if (length > tolerance) { - const movement = diff.multiplyScalar(Math.min(1, dt * 0.008)); + if (length > 0) { + const tolerance = 32 / globalConfig.tileSize; + const movement = diff.multiplyScalar(Math.min(1, dt * 0.008 * (1 + tolerance / length))); this.center.x += movement.x; this.center.y += movement.y; } else { diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js index acab7d06..90ac1016 100644 --- a/src/js/game/hud/parts/waypoints.js +++ b/src/js/game/hud/parts/waypoints.js @@ -32,6 +32,7 @@ import { enumNotificationType } from "./notifications"; const MAX_LABEL_LENGTH = 70; const SHAPE_TEXT_LENGTH = 2; +const COMPASS_PREFIX = "!"; export class HUDWaypoints extends BaseHUDPart { /** @@ -79,6 +80,20 @@ export class HUDWaypoints extends BaseHUDPart { return "Invalid waypoints data"; } this.waypoints = data.waypoints; + + for (let i = 0; i < this.waypoints.length; ++i) { + const waypoint = this.waypoints[i]; + if (waypoint.label && waypoint.label.startsWith(COMPASS_PREFIX)) { + const [canvas, context] = makeOffscreenBuffer(48, 48, { + smooth: true, + reusable: false, + label: "waypoints-compass/" + waypoint.center.x + "/" + waypoint.center.y, + }); + canvas.classList.add("compass"); + this.compassBuffers["" + waypoint.center.x + "/" + waypoint.center.y] = { canvas, context }; + } + } + this.rerenderWaypointList(); } @@ -123,15 +138,16 @@ export class HUDWaypoints extends BaseHUDPart { * This is interpolated over multiple frames so we have some sort of fade effect */ this.currentMarkerOpacity = 1; - this.currentCompassOpacity = 0; + this.currentCompassOpacities = { ["0/0"]: 0 }; // Create buffer which is used to indicate the hub direction const [canvas, context] = makeOffscreenBuffer(48, 48, { smooth: true, reusable: false, - label: "waypoints-compass", + label: "waypoints-compass/0/0", }); - this.compassBuffer = { canvas, context }; + canvas.classList.add("compass"); + this.compassBuffers = { ["0/0"]: { canvas, context } }; /** * Stores a cache from a shape short key to its canvas representation @@ -206,8 +222,8 @@ export class HUDWaypoints extends BaseHUDPart { label: part + "-waypoint-" + i, }); context.drawImage(canvas, 0, 0); + newCanvas.classList.add("shapeIcon"); element.appendChild(newCanvas); - element.classList.add("shapeIcon"); } else { element.appendChild(document.createTextNode(part)); } @@ -219,10 +235,12 @@ export class HUDWaypoints extends BaseHUDPart { this.trackClicks(editButton, () => this.requestSaveMarker({ waypoint })); } - if (!waypoint.label) { - // This must be the hub label + if (!waypoint.label || waypoint.label.startsWith(COMPASS_PREFIX)) { + // This must be a compass label element.classList.add("hub"); - element.insertBefore(this.compassBuffer.canvas, element.childNodes[0]); + + const canvas = this.compassBuffers["" + waypoint.center.x + "/" + waypoint.center.y].canvas; + element.insertBefore(canvas, element.childNodes[0]); } this.trackClicks(element, () => this.moveToWaypoint(waypoint), { @@ -329,6 +347,20 @@ export class HUDWaypoints extends BaseHUDPart { */ addWaypoint(label, position) { const parts = this.splitLabel(label); + + if (label.startsWith(COMPASS_PREFIX)) { + const bufferKey = "" + position.x + "/" + position.y; + if (!this.compassBuffers[bufferKey]) { + const [canvas, context] = makeOffscreenBuffer(48, 48, { + smooth: true, + reusable: false, + label: "waypoints-compass/" + position.x + "/" + position.y, + }); + canvas.classList.add("compass"); + this.compassBuffers[bufferKey] = { canvas, context }; + } + } + this.waypoints.push({ label, parts, @@ -357,6 +389,19 @@ export class HUDWaypoints extends BaseHUDPart { waypoint.label = label; waypoint.parts = this.splitLabel(waypoint.label); + if (label.startsWith(COMPASS_PREFIX)) { + const bufferKey = "" + waypoint.center.x + "/" + waypoint.center.y; + if (!this.compassBuffers[bufferKey]) { + const [canvas, context] = makeOffscreenBuffer(48, 48, { + smooth: true, + reusable: false, + label: "waypoints-compass/" + waypoint.center.x + "/" + waypoint.center.y, + }); + canvas.classList.add("compass"); + this.compassBuffers[bufferKey] = { canvas, context }; + } + } + this.sortWaypoints(); // Show notification about renamed @@ -579,26 +624,37 @@ export class HUDWaypoints extends BaseHUDPart { /** * Rerenders the compass + * @param {Waypoint} waypoint */ - rerenderWaypointsCompass() { + rerenderWaypointsCompass(waypoint) { const dims = 48; const indicatorSize = 30; - const cameraPos = this.root.camera.center; + const relativeCameraPos = new Vector(waypoint.center.x, waypoint.center.y).direction( + this.root.camera.center + ); - const context = this.compassBuffer.context; + const bufferKey = "" + waypoint.center.x + "/" + waypoint.center.y; + const context = this.compassBuffers[bufferKey].context; context.clearRect(0, 0, dims, dims); - const distanceToHub = cameraPos.length(); + const distanceToHub = relativeCameraPos.length(); const compassVisible = distanceToHub > (10 * globalConfig.tileSize) / this.root.camera.zoomLevel; const targetCompassAlpha = compassVisible ? 1 : 0; // Fade the compas in / out - this.currentCompassOpacity = lerp(this.currentCompassOpacity, targetCompassAlpha, 0.08); + if (this.currentCompassOpacities[bufferKey] === undefined) { + this.currentCompassOpacities[bufferKey] = 0; + } + this.currentCompassOpacities[bufferKey] = lerp( + this.currentCompassOpacities[bufferKey], + targetCompassAlpha, + 0.08 + ); // Render the compass - if (this.currentCompassOpacity > 0.01) { - context.globalAlpha = this.currentCompassOpacity; - const angle = cameraPos.angle() + Math.radians(45) + Math.PI / 2; + if (this.currentCompassOpacities[bufferKey] > 0.01) { + context.globalAlpha = this.currentCompassOpacities[bufferKey]; + const angle = relativeCameraPos.angle() + Math.radians(45) + Math.PI / 2; context.translate(dims / 2, dims / 2); context.rotate(angle); this.directionIndicatorSprite.drawCentered(context, 0, 0, indicatorSize); @@ -608,7 +664,7 @@ export class HUDWaypoints extends BaseHUDPart { } // Render the regualr icon - const iconOpacity = 1 - this.currentCompassOpacity; + const iconOpacity = 1 - this.currentCompassOpacities[bufferKey]; if (iconOpacity > 0.01) { context.globalAlpha = iconOpacity; this.waypointSprite.drawCentered(context, dims / 2, dims / 2, dims * 0.7); @@ -625,7 +681,12 @@ export class HUDWaypoints extends BaseHUDPart { const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0; this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08); - this.rerenderWaypointsCompass(); + for (let i = 0; i < this.waypoints.length; ++i) { + const waypoint = this.waypoints[i]; + if (!waypoint.label || waypoint.label.startsWith(COMPASS_PREFIX)) { + this.rerenderWaypointsCompass(waypoint); + } + } // Don't render with low opacity if (this.currentMarkerOpacity < 0.01) {