diff --git a/src/css/ingame_hud/statistics.scss b/src/css/ingame_hud/statistics.scss index 595861e2..8a7bf952 100644 --- a/src/css/ingame_hud/statistics.scss +++ b/src/css/ingame_hud/statistics.scss @@ -105,7 +105,7 @@ @include S(padding, 0, 3px); } - div.pin { + button.pin { @include S(width, 12px); @include S(height, 12px); @include S(padding, 0px); @@ -114,8 +114,50 @@ opacity: 0.6; transition: opacity 0.12s ease-in-out; + opacity: 0.6; + cursor: pointer; + pointer-events: all; + @include IncreasedClickArea(5px); + transition: opacity 0.12s ease-in-out; @include DarkThemeInvert; + + $disabledOpacity: 0.2; + $enabledOpacity: 0.6; + + &:hover { + opacity: $enabledOpacity + 0.1; + } + + &.alreadyPinned { + opacity: $disabledOpacity !important; + + &:hover { + opacity: $disabledOpacity + 0.1 !important; + } + } + + &.isGoal { + background: uiResource("icons/current_goal_marker.png") center center / 95% + no-repeat; + opacity: $disabledOpacity !important; + cursor: default; + pointer-events: none; + } + + &.pinned { + opacity: $disabledOpacity; + &:hover { + opacity: $disabledOpacity + 0.1; + } + } + + &.unpinned { + opacity: $enabledOpacity; + &:hover { + opacity: $enabledOpacity + 0.1; + } + } } } } diff --git a/src/js/game/hud/parts/statistics.js b/src/js/game/hud/parts/statistics.js index 0452d7e5..461de518 100644 --- a/src/js/game/hud/parts/statistics.js +++ b/src/js/game/hud/parts/statistics.js @@ -96,6 +96,11 @@ export class HUDStatistics extends BaseHUDPart { this.lastFullRerender = 0; + // since pinning shapes changes sort-order, the list should rerender + // every time a shape is pinned or unpinned + this.root.hud.signals.shapePinRequested.add(this.rerenderFull, this); + this.root.hud.signals.shapeUnpinRequested.add(this.rerenderFull, this); + this.close(); this.rerenderFull(); } diff --git a/src/js/game/hud/parts/statistics_handle.js b/src/js/game/hud/parts/statistics_handle.js index c684a896..4151eaeb 100644 --- a/src/js/game/hud/parts/statistics_handle.js +++ b/src/js/game/hud/parts/statistics_handle.js @@ -5,6 +5,7 @@ import { formatBigNumber, clamp } from "../../../core/utils"; import { globalConfig } from "../../../core/config"; import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { T } from "../../../translations"; +import { ClickDetector } from "../../../core/click_detector"; /** @enum {string} */ export const enumDisplayMode = { @@ -31,12 +32,24 @@ export class HUDShapeStatisticsHandle { initElement() { this.element = document.createElement("div"); - this.element.setAttribute("data-shape-key", this.definition.getHash()); - if (this.root.hud.parts.pinnedShapes.isShapePinned(this.definition.getHash())) { - const pinButton = document.createElement("div"); - pinButton.classList.add("pin"); - this.element.appendChild(pinButton); - } + const shape = this.definition.getHash(); + this.element.setAttribute("data-shape-key", shape); + const pinButton = document.createElement("button"); + pinButton.classList.add("pin"); + const pinDetector = new ClickDetector(pinButton, { + consumeEvents: true, + preventDefault: true, + }); + pinDetector.click.add(() => { + if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { + this.root.hud.signals.shapeUnpinRequested.dispatch(shape); + } else { + this.root.hud.signals.shapePinRequested.dispatch(this.definition); + } + }); + this.pinButton = pinButton; + this.updatePinClasses(); + this.element.appendChild(this.pinButton); this.counter = document.createElement("span"); this.counter.classList.add("counter"); this.element.appendChild(this.counter); @@ -64,6 +77,24 @@ export class HUDShapeStatisticsHandle { } } + /** + * Updates the classes on `this.pinButton` to ensure the UI accurately reflects + * the current pin-state of the shape + */ + updatePinClasses() { + const shape = this.definition.getHash(); + const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); + if (shape === currentGoalShape) { + this.pinButton.classList.add("isGoal"); + } else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { + this.pinButton.classList.add("pinned", "alreadyPinned"); + this.pinButton.classList.remove("unpinned"); + } else { + this.pinButton.classList.remove("pinned", "alreadyPinned"); + this.pinButton.classList.add("unpinned"); + } + } + /** * * @param {enumDisplayMode} displayMode @@ -77,7 +108,7 @@ export class HUDShapeStatisticsHandle { if (!this.visible && !forced) { return; } - + this.updatePinClasses(); switch (dataSource) { case enumAnalyticsDataSource.stored: { this.counter.innerText = formatBigNumber(