Completed plugins framework

More work required to define all interfaces for the useful classes in the @types folder
This commit is contained in:
Pax1601 2023-09-15 23:07:15 +02:00
parent 588228c050
commit 2f125e3d0e
15 changed files with 244 additions and 531 deletions

3
.gitignore vendored
View File

@ -9,4 +9,5 @@ Output
node_modules
/client/TODO.txt
/client/public/javascripts/bundle.js
!client/bin
!client/bin
/client/public/plugins

View File

@ -11,68 +11,72 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ControlTips_instances, _ControlTips_element, _ControlTips_app, _ControlTips_shortcutManager, _ControlTips_cursorIsHoveringOverUnit, _ControlTips_cursorIsHoveringOverAirbase, _ControlTips_updateTips;
var _ControlTipsPlugin_instances, _ControlTipsPlugin_element, _ControlTipsPlugin_app, _ControlTipsPlugin_shortcutManager, _ControlTipsPlugin_cursorIsHoveringOverUnit, _ControlTipsPlugin_cursorIsHoveringOverAirbase, _ControlTipsPlugin_updateTips;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ControlTips = void 0;
class ControlTips {
exports.ControlTipsPlugin = void 0;
const SHOW_CONTROL_TIPS = "Show control tips";
class ControlTipsPlugin {
constructor() {
_ControlTips_instances.add(this);
_ControlTips_element.set(this, void 0);
_ControlTips_app.set(this, void 0);
_ControlTips_shortcutManager.set(this, void 0);
_ControlTips_cursorIsHoveringOverUnit.set(this, false);
_ControlTips_cursorIsHoveringOverAirbase.set(this, false);
__classPrivateFieldSet(this, _ControlTips_element, document.createElement("div"), "f");
__classPrivateFieldGet(this, _ControlTips_element, "f").id = "control-tips-panel";
document.body.appendChild(__classPrivateFieldGet(this, _ControlTips_element, "f"));
console.log("HELLO");
_ControlTipsPlugin_instances.add(this);
_ControlTipsPlugin_element.set(this, void 0);
_ControlTipsPlugin_app.set(this, void 0);
_ControlTipsPlugin_shortcutManager.set(this, void 0);
_ControlTipsPlugin_cursorIsHoveringOverUnit.set(this, false);
_ControlTipsPlugin_cursorIsHoveringOverAirbase.set(this, false);
__classPrivateFieldSet(this, _ControlTipsPlugin_element, document.createElement("div"), "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_element, "f").id = "control-tips-panel";
document.body.appendChild(__classPrivateFieldGet(this, _ControlTipsPlugin_element, "f"));
}
getName() {
return "Control Tips Plugin";
}
initialize(app) {
__classPrivateFieldSet(this, _ControlTips_app, app, "f");
__classPrivateFieldSet(this, _ControlTips_shortcutManager, __classPrivateFieldGet(this, _ControlTips_app, "f").getShortcutManager(), "f");
__classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").onKeyDown(() => {
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldSet(this, _ControlTipsPlugin_app, app, "f");
__classPrivateFieldSet(this, _ControlTipsPlugin_shortcutManager, __classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getShortcutManager(), "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_shortcutManager, "f").onKeyDown(() => {
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
__classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").onKeyUp(() => {
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldGet(this, _ControlTipsPlugin_shortcutManager, "f").onKeyUp(() => {
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
document.addEventListener("airbaseMouseover", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverAirbase, true, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldSet(this, _ControlTipsPlugin_cursorIsHoveringOverAirbase, true, "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
document.addEventListener("airbaseMouseout", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverAirbase, false, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldSet(this, _ControlTipsPlugin_cursorIsHoveringOverAirbase, false, "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
document.addEventListener("unitDeselection", (ev) => {
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
//document.addEventListener("unitDeselection", (ev: CustomEvent) => {
// this.#updateTips();
//});
document.addEventListener("unitMouseover", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverUnit, true, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldSet(this, _ControlTipsPlugin_cursorIsHoveringOverUnit, true, "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
document.addEventListener("unitMouseout", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverUnit, false, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
__classPrivateFieldSet(this, _ControlTipsPlugin_cursorIsHoveringOverUnit, false, "f");
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
//document.addEventListener("unitSelection", (ev: CustomEvent) => {
// this.#updateTips()
//});
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
document.addEventListener("unitSelection", (ev) => {
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
});
document.addEventListener("mapVisibilityOptionsChanged", () => {
this.toggle(!__classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getMap().getVisibilityOptions()[SHOW_CONTROL_TIPS]);
});
__classPrivateFieldGet(this, _ControlTipsPlugin_instances, "m", _ControlTipsPlugin_updateTips).call(this);
__classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getMap().addVisibilityOption(SHOW_CONTROL_TIPS, true);
return true;
}
getElement() {
return __classPrivateFieldGet(this, _ControlTips_element, "f");
return __classPrivateFieldGet(this, _ControlTipsPlugin_element, "f");
}
toggle(bool) {
this.getElement().classList.toggle("hide", bool);
}
}
exports.ControlTips = ControlTips;
_ControlTips_element = new WeakMap(), _ControlTips_app = new WeakMap(), _ControlTips_shortcutManager = new WeakMap(), _ControlTips_cursorIsHoveringOverUnit = new WeakMap(), _ControlTips_cursorIsHoveringOverAirbase = new WeakMap(), _ControlTips_instances = new WeakSet(), _ControlTips_updateTips = function _ControlTips_updateTips() {
exports.ControlTipsPlugin = ControlTipsPlugin;
_ControlTipsPlugin_element = new WeakMap(), _ControlTipsPlugin_app = new WeakMap(), _ControlTipsPlugin_shortcutManager = new WeakMap(), _ControlTipsPlugin_cursorIsHoveringOverUnit = new WeakMap(), _ControlTipsPlugin_cursorIsHoveringOverAirbase = new WeakMap(), _ControlTipsPlugin_instances = new WeakSet(), _ControlTipsPlugin_updateTips = function _ControlTipsPlugin_updateTips() {
const combos = [
{
"keys": [],
@ -205,13 +209,13 @@ _ControlTips_element = new WeakMap(), _ControlTips_app = new WeakMap(), _Control
]
}
];
const currentCombo = combos.find((combo) => __classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").keyComboMatches(combo.keys)) || combos[0];
const currentCombo = combos.find((combo) => __classPrivateFieldGet(this, _ControlTipsPlugin_shortcutManager, "f").keyComboMatches(combo.keys)) || combos[0];
const element = this.getElement();
element.innerHTML = "";
let numSelectedUnits = 0;
let unitSelectionContainsControlled = false;
if (__classPrivateFieldGet(this, _ControlTips_app, "f").getUnitsManager()) {
let selectedUnits = Object.values(__classPrivateFieldGet(this, _ControlTips_app, "f").getUnitsManager().getSelectedUnits());
if (__classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getUnitsManager()) {
let selectedUnits = Object.values(__classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getUnitsManager().getSelectedUnits());
numSelectedUnits = selectedUnits.length;
unitSelectionContainsControlled = selectedUnits.some((unit) => unit.getControlled());
}
@ -228,12 +232,12 @@ _ControlTips_element = new WeakMap(), _ControlTips_app = new WeakMap(), _Control
return;
}
if (typeof tip.showIfHoveringOverAirbase === "boolean") {
if (tip.showIfHoveringOverAirbase !== __classPrivateFieldGet(this, _ControlTips_cursorIsHoveringOverAirbase, "f")) {
if (tip.showIfHoveringOverAirbase !== __classPrivateFieldGet(this, _ControlTipsPlugin_cursorIsHoveringOverAirbase, "f")) {
return;
}
}
if (typeof tip.showIfHoveringOverUnit === "boolean") {
if (tip.showIfHoveringOverUnit !== __classPrivateFieldGet(this, _ControlTips_cursorIsHoveringOverUnit, "f")) {
if (tip.showIfHoveringOverUnit !== __classPrivateFieldGet(this, _ControlTipsPlugin_cursorIsHoveringOverUnit, "f")) {
return;
}
}
@ -246,7 +250,7 @@ _ControlTips_element = new WeakMap(), _ControlTips_app = new WeakMap(), _Control
Object.defineProperty(exports, "__esModule", { value: true });
const controltips_1 = require("./controltips");
globalThis.getOlympusPlugin = () => {
return new controltips_1.ControlTips();
return new controltips_1.ControlTipsPlugin();
};
},{"./controltips":1}]},{},[2]);

View File

@ -1,3 +1,5 @@
const SHOW_CONTROL_TIPS = "Show control tips"
export class ControlTipsPlugin implements OlympusPlugin {
#element: HTMLElement;
#app: any;
@ -9,8 +11,6 @@ export class ControlTipsPlugin implements OlympusPlugin {
this.#element = document.createElement("div");
this.#element.id = "control-tips-panel";
document.body.appendChild(this.#element);
console.log("HELLO")
}
getName() {
@ -40,9 +40,9 @@ export class ControlTipsPlugin implements OlympusPlugin {
this.#updateTips();
});
//document.addEventListener("unitDeselection", (ev: CustomEvent) => {
// this.#updateTips();
//});
document.addEventListener("unitDeselection", (ev: CustomEvent) => {
this.#updateTips();
});
document.addEventListener("unitMouseover", (ev: CustomEventInit) => {
this.#cursorIsHoveringOverUnit = true;
@ -54,12 +54,18 @@ export class ControlTipsPlugin implements OlympusPlugin {
this.#updateTips();
});
//document.addEventListener("unitSelection", (ev: CustomEvent) => {
// this.#updateTips()
//});
document.addEventListener("unitSelection", (ev: CustomEvent) => {
this.#updateTips()
});
document.addEventListener("mapVisibilityOptionsChanged", () => {
this.toggle( !this.#app.getMap().getVisibilityOptions()[SHOW_CONTROL_TIPS] );
});
this.#updateTips();
this.#app.getMap().addVisibilityOption(SHOW_CONTROL_TIPS, true);
return true;
}
@ -72,7 +78,6 @@ export class ControlTipsPlugin implements OlympusPlugin {
}
#updateTips() {
const combos: Array<object> = [
{
"keys": [],
@ -249,7 +254,6 @@ export class ControlTipsPlugin implements OlympusPlugin {
}
element.innerHTML += `<div><span class="key">${tip.key}</span><span class="action">${tip.action}</span></div>`
});
}
}

View File

@ -1,4 +1,4 @@
import { ControlTipsPlugin } from "./controltips";
import { ControlTipsPlugin } from "./controltipsplugin";
globalThis.getOlympusPlugin = () => {
return new ControlTipsPlugin();

View File

@ -1,252 +0,0 @@
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ControlTips_instances, _ControlTips_element, _ControlTips_app, _ControlTips_shortcutManager, _ControlTips_cursorIsHoveringOverUnit, _ControlTips_cursorIsHoveringOverAirbase, _ControlTips_updateTips;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ControlTips = void 0;
class ControlTips {
constructor() {
_ControlTips_instances.add(this);
_ControlTips_element.set(this, void 0);
_ControlTips_app.set(this, void 0);
_ControlTips_shortcutManager.set(this, void 0);
_ControlTips_cursorIsHoveringOverUnit.set(this, false);
_ControlTips_cursorIsHoveringOverAirbase.set(this, false);
__classPrivateFieldSet(this, _ControlTips_element, document.createElement("div"), "f");
__classPrivateFieldGet(this, _ControlTips_element, "f").id = "control-tips-panel";
document.body.appendChild(__classPrivateFieldGet(this, _ControlTips_element, "f"));
console.log("HELLO");
}
getName() {
return "Control Tips Plugin";
}
initialize(app) {
__classPrivateFieldSet(this, _ControlTips_app, app, "f");
__classPrivateFieldSet(this, _ControlTips_shortcutManager, __classPrivateFieldGet(this, _ControlTips_app, "f").getShortcutManager(), "f");
__classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").onKeyDown(() => {
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
__classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").onKeyUp(() => {
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
document.addEventListener("airbaseMouseover", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverAirbase, true, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
document.addEventListener("airbaseMouseout", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverAirbase, false, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
//document.addEventListener("unitDeselection", (ev: CustomEvent) => {
// this.#updateTips();
//});
document.addEventListener("unitMouseover", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverUnit, true, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
document.addEventListener("unitMouseout", (ev) => {
__classPrivateFieldSet(this, _ControlTips_cursorIsHoveringOverUnit, false, "f");
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
});
//document.addEventListener("unitSelection", (ev: CustomEvent) => {
// this.#updateTips()
//});
__classPrivateFieldGet(this, _ControlTips_instances, "m", _ControlTips_updateTips).call(this);
return true;
}
getElement() {
return __classPrivateFieldGet(this, _ControlTips_element, "f");
}
toggle(bool) {
this.getElement().classList.toggle("hide", bool);
}
}
exports.ControlTips = ControlTips;
_ControlTips_element = new WeakMap(), _ControlTips_app = new WeakMap(), _ControlTips_shortcutManager = new WeakMap(), _ControlTips_cursorIsHoveringOverUnit = new WeakMap(), _ControlTips_cursorIsHoveringOverAirbase = new WeakMap(), _ControlTips_instances = new WeakSet(), _ControlTips_updateTips = function _ControlTips_updateTips() {
const combos = [
{
"keys": [],
"tips": [
{
"key": `SHIFT`,
"action": `Box select`,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false,
"showIfUnitSelected": false
},
{
"key": `Mouse1`,
"action": `Deselect`,
"showIfUnitSelected": true
},
{
"key": `Mouse1+drag`,
"action": `Move map`,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false,
"showIfUnitSelected": false
},
{
"key": `Mouse2`,
"action": `Spawn menu`,
"showIfUnitSelected": false,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false
},
{
"key": `Mouse2`,
"action": `Quick options`,
"showIfUnitSelected": false,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": true
},
{
"key": `Mouse2`,
"action": `Airbase menu`,
"showIfUnitSelected": false,
"showIfHoveringOverAirbase": true,
"showIfHoveringOverUnit": false
},
{
"key": `Mouse2`,
"action": `Set first waypoint`,
"showIfHoveringOverAirbase": false,
"showIfUnitSelected": true,
"unitsMustBeControlled": true
},
{
"key": "CTRL+Mouse2",
"action": "Add waypoint",
"showIfUnitSelected": true,
"showIfHoveringOverAirbase": false,
"unitsMustBeControlled": true
},
{
"key": `Mouse2 (hold)`,
"action": `Point operations`,
"showIfUnitSelected": true,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false,
"unitsMustBeControlled": true
},
{
"key": "CTRL",
"action": " Pin tool",
"showIfUnitSelected": false,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false,
"unitsMustBeControlled": true
},
{
"key": "CTRL+Mouse2",
"action": " Airbase menu",
"showIfUnitSelected": true,
"showIfHoveringOverAirbase": true,
"unitsMustBeControlled": true
},
{
"key": `Delete`,
"action": `Delete unit`,
"showIfHoveringOverAirbase": false,
"showIfUnitSelected": true
}
]
},
{
"keys": ["ControlLeft"],
"tips": [
{
"key": `Mouse1`,
"action": "Toggle pin",
"showIfUnitSelected": false,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": false
},
{
"key": `Mouse1`,
"action": "Toggle selection",
"showIfUnitSelected": true,
"showIfHoveringOverAirbase": false,
"showIfHoveringOverUnit": true
},
{
"key": `Mouse2`,
"action": `Add waypoint`,
"showIfHoveringOverAirbase": false,
"showIfUnitSelected": true,
"unitsMustBeControlled": true
},
{
"key": `Mouse2`,
"action": `Airbase menu`,
"showIfHoveringOverAirbase": true,
"showIfUnitSelected": true,
"unitsMustBeControlled": true
}
]
},
{
"keys": ["ShiftLeft"],
"tips": [
{
"key": `mouse1+drag`,
"action": "Box select"
}
]
}
];
const currentCombo = combos.find((combo) => __classPrivateFieldGet(this, _ControlTips_shortcutManager, "f").keyComboMatches(combo.keys)) || combos[0];
const element = this.getElement();
element.innerHTML = "";
let numSelectedUnits = 0;
let unitSelectionContainsControlled = false;
if (__classPrivateFieldGet(this, _ControlTips_app, "f").getUnitsManager()) {
let selectedUnits = Object.values(__classPrivateFieldGet(this, _ControlTips_app, "f").getUnitsManager().getSelectedUnits());
numSelectedUnits = selectedUnits.length;
unitSelectionContainsControlled = selectedUnits.some((unit) => unit.getControlled());
}
currentCombo.tips.forEach((tip) => {
if (numSelectedUnits > 0) {
if (tip.showIfUnitSelected === false) {
return;
}
if (tip.unitsMustBeControlled === true && unitSelectionContainsControlled === false) {
return;
}
}
if (numSelectedUnits === 0 && tip.showIfUnitSelected === true) {
return;
}
if (typeof tip.showIfHoveringOverAirbase === "boolean") {
if (tip.showIfHoveringOverAirbase !== __classPrivateFieldGet(this, _ControlTips_cursorIsHoveringOverAirbase, "f")) {
return;
}
}
if (typeof tip.showIfHoveringOverUnit === "boolean") {
if (tip.showIfHoveringOverUnit !== __classPrivateFieldGet(this, _ControlTips_cursorIsHoveringOverUnit, "f")) {
return;
}
}
element.innerHTML += `<div><span class="key">${tip.key}</span><span class="action">${tip.action}</span></div>`;
});
};
},{}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const controltips_1 = require("./controltips");
globalThis.getOlympusPlugin = () => {
return new controltips_1.ControlTips();
};
},{"./controltips":1}]},{},[2]);

View File

@ -1,6 +0,0 @@
{
"name": "Control Tip Plugin",
"version": "0.0.1",
"description": "This plugin shows useful control tips on the right side of the screen. The tips change dynamically depending on what the user does",
"author": "Peekaboo"
}

View File

@ -1,33 +0,0 @@
#control-tips-panel {
align-self: center;
display: flex;
flex-flow: column wrap;
font-size: 13px;
justify-self: flex-end;
position: absolute;
right: 10px;
row-gap: 20px;
text-align: right;
z-index: 999;
}
#control-tips-panel>* {
align-items: center;
align-self: end;
background-color: var(--background-steel);
border-radius: var(--border-radius-md);
color: white;
column-gap: 8px;
display: flex;
justify-items: right;
opacity: .9;
padding: 5px;
width: fit-content;
}
#control-tips-panel>*>.key {
background-color: var(--background-grey);
border-radius: var(--border-radius-sm);
color: white;
padding: 1px 4px;
}

View File

@ -1,7 +1,6 @@
@import url("layout/layout.css");
@import url("style/style.css");
@import url("other/controltips.css");
@import url("panels/connectionstatus.css");
@import url("panels/serverstatus.css");
@import url("panels/mouseinfo.css");

View File

@ -653,17 +653,6 @@ nav.ol-panel> :last-child {
stroke: var(--background-steel) !important;
}
#atc-navbar-control {
align-items: center;
display: flex;
flex-direction: column;
}
#atc-navbar-control button svg {
height: 24px;
width: 24px;
}
#roe-buttons-container button,
#reaction-to-threat-buttons-container button,
#emissions-countermeasures-buttons-container button {

View File

@ -17,6 +17,9 @@ import { WeaponsManager } from "./weapon/weaponsmanager";
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "./constants/constants";
import { Manager } from "./other/manager";
import { ShortcutKeyboard } from "./shortcut/shortcut";
import { getPaused, setCredentials, setPaused, startUpdate, toggleDemoEnabled } from "./server/server";
import { SVGInjector } from "@tanem/svg-injector";
export class OlympusApp {
/* Global data */
@ -36,11 +39,11 @@ export class OlympusApp {
#shortcutManager: ShortcutManager | null = null;
/* UI Toolbars */
#primaryToolbar: PrimaryToolbar| null = null;
#commandModeToolbar: CommandModeToolbar| null = null;
#primaryToolbar: PrimaryToolbar | null = null;
#commandModeToolbar: CommandModeToolbar | null = null;
constructor() {
}
getMap() {
@ -122,7 +125,7 @@ export class OlympusApp {
this.#unitsManager = new UnitsManager();
this.#weaponsManager = new WeaponsManager();
this.#missionManager = new MissionManager();
this.#shortcutManager = new ShortcutManager();
this.#panelsManager = new Manager();
@ -136,16 +139,130 @@ export class OlympusApp {
.add("mouseInfo", new MouseInfoPanel("mouse-info-panel"))
.add("log", new LogPanel("log-panel"))
.add("serverStatus", new ServerStatusPanel("server-status-panel"))
.add("unitControl", new UnitControlPanel("unit-control-panel"))
.add("unitControl", new UnitControlPanel("unit-control-panel"))
.add("unitInfo", new UnitInfoPanel("unit-info-panel"))
// Popups
this.getPopupsManager().add("infoPopup", new Popup("info-popup"));
// Toolbars
this.getToolbarsManager().add("primaryToolbar", new PrimaryToolbar("primary-toolbar"))
.add("commandModeToolbar", new PrimaryToolbar("command-mode-toolbar"));
.add("commandModeToolbar", new PrimaryToolbar("command-mode-toolbar"));
this.#pluginsManager = new PluginsManager();
this.#setupEvents();
}
#setupEvents() {
/* Generic clicks */
document.addEventListener("click", (ev) => {
if (ev instanceof MouseEvent && ev.target instanceof HTMLElement) {
const target = ev.target;
if (target.classList.contains("olympus-dialog-close")) {
target.closest("div.olympus-dialog")?.classList.add("hide");
}
const triggerElement = target.closest("[data-on-click]");
if (triggerElement instanceof HTMLElement) {
const eventName: string = triggerElement.dataset.onClick || "";
let params = JSON.parse(triggerElement.dataset.onClickParams || "{}");
params._element = triggerElement;
if (eventName) {
document.dispatchEvent(new CustomEvent(eventName, {
detail: params
}));
}
}
}
});
const shortcutManager = this.getShortcutManager();
shortcutManager.add("toggleDemo", new ShortcutKeyboard({
"callback": () => {
toggleDemoEnabled();
},
"code": "KeyT"
})).add("togglePause", new ShortcutKeyboard({
"altKey": false,
"callback": () => {
setPaused(!getPaused());
},
"code": "Space",
"ctrlKey": false
}));
["KeyW", "KeyA", "KeyS", "KeyD", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].forEach(code => {
shortcutManager.add(`pan${code}keydown`, new ShortcutKeyboard({
"altKey": false,
"callback": (ev: KeyboardEvent) => {
this.getMap().handleMapPanning(ev);
},
"code": code,
"ctrlKey": false,
"event": "keydown"
}));
});
["KeyW", "KeyA", "KeyS", "KeyD", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].forEach(code => {
shortcutManager.add(`pan${code}keyup`, new ShortcutKeyboard({
"callback": (ev: KeyboardEvent) => {
this.getMap().handleMapPanning(ev);
},
"code": code
}));
});
["Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9"].forEach(code => {
shortcutManager.add(`hotgroup${code}`, new ShortcutKeyboard({
"callback": (ev: KeyboardEvent) => {
if (ev.ctrlKey && ev.shiftKey)
this.getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
else if (ev.ctrlKey && !ev.shiftKey)
this.getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5)));
else
this.getUnitsManager().selectUnitsByHotgroup(parseInt(ev.code.substring(5)));
},
"code": code
}));
});
// TODO: move from here in dedicated class
document.addEventListener("closeDialog", (ev: CustomEventInit) => {
ev.detail._element.closest(".ol-dialog").classList.add("hide");
});
/* Try and connect with the Olympus REST server */
document.addEventListener("tryConnection", () => {
const form = document.querySelector("#splash-content")?.querySelector("#authentication-form");
const username = (form?.querySelector("#username") as HTMLInputElement).value;
const password = (form?.querySelector("#password") as HTMLInputElement).value;
/* Update the user credentials */
setCredentials(username, password);
/* Start periodically requesting updates */
startUpdate();
this.setLoginStatus("connecting");
})
/* Reload the page, used to mimic a restart of the app */
document.addEventListener("reloadPage", () => {
location.reload();
})
/* Inject the svgs with the corresponding svg code. This allows to dynamically manipulate the svg, like changing colors */
document.querySelectorAll("[inject-svg]").forEach((el: Element) => {
var img = el as HTMLImageElement;
var isLoaded = img.complete;
if (isLoaded)
SVGInjector(img);
else
img.addEventListener("load", () => { SVGInjector(img); });
})
}
}

View File

@ -153,7 +153,6 @@ export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3
export const SHOW_CONTACT_LINES = "Show unit contact lines";
export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out";
export const SHOW_CONTROL_TIPS = "Show control tips";
export const SHOW_UNIT_LABELS = "Show unit labels";
export const SHOW_UNIT_PATHS = "Show unit paths";
export const SHOW_UNIT_TARGETS = "Show unit targets";

View File

@ -68,6 +68,10 @@ export class Dropdown {
return this.#options.children;
}
addOptionElement(optionElement: HTMLElement) {
this.#options.appendChild(optionElement);
}
selectText(text: string) {
const index = [].slice.call(this.#options.children).findIndex((opt: Element) => opt.querySelector("button")?.innerText === text);
if (index > -1) {

View File

@ -1,156 +1,30 @@
import { getConfig, getPaused, setAddress, setCredentials, setPaused, startUpdate, toggleDemoEnabled } from "./server/server";
import { SVGInjector } from "@tanem/svg-injector";
import { getConfig, setAddress } from "./server/server";
import { OlympusApp } from "./app";
import { ShortcutKeyboard } from "./shortcut/shortcut";
var app: OlympusApp;
function setup() {
/* Load the config file from the app server*/
getConfig((config: ConfigurationOptions) => readConfig(config));
getConfig((config: ConfigurationOptions) => {
if (config && config.address != undefined && config.port != undefined) {
const address = config.address;
const port = config.port;
if (typeof address === 'string' && typeof port == 'number') {
setAddress(address == "*" ? window.location.hostname : address, <number>port);
app = new OlympusApp();
app.start();
/* Setup event handlers */
setupEvents(app);
/* If the configuration file was successfully loaded, start the app */
app = new OlympusApp();
app.start();
}
}
else {
throw new Error('Could not read configuration file');
}
});
}
export function getApp() {
return app;
}
/** Loads the configuration parameters
*
* @param config ConfigParameters, defines the address and port of the Olympus REST server
*/
function readConfig(config: ConfigurationOptions) {
if (config && config.address != undefined && config.port != undefined) {
const address = config.address;
const port = config.port;
if (typeof address === 'string' && typeof port == 'number')
setAddress(address == "*" ? window.location.hostname : address, <number>port);
}
else {
throw new Error('Could not read configuration file');
}
}
function setupEvents(app: OlympusApp) {
/* Generic clicks */
document.addEventListener("click", (ev) => {
if (ev instanceof MouseEvent && ev.target instanceof HTMLElement) {
const target = ev.target;
if (target.classList.contains("olympus-dialog-close")) {
target.closest("div.olympus-dialog")?.classList.add("hide");
}
const triggerElement = target.closest("[data-on-click]");
if (triggerElement instanceof HTMLElement) {
const eventName: string = triggerElement.dataset.onClick || "";
let params = JSON.parse(triggerElement.dataset.onClickParams || "{}");
params._element = triggerElement;
if (eventName) {
document.dispatchEvent(new CustomEvent(eventName, {
detail: params
}));
}
}
}
});
const shortcutManager = app.getShortcutManager();
shortcutManager.add("toggleDemo", new ShortcutKeyboard({
"callback": () => {
toggleDemoEnabled();
},
"code": "KeyT"
})
)
.add("togglePause", new ShortcutKeyboard({
"altKey": false,
"callback": () => {
setPaused(!getPaused());
},
"code": "Space",
"ctrlKey": false
})
);
["KeyW", "KeyA", "KeyS", "KeyD", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].forEach(code => {
shortcutManager.add(`pan${code}keydown`, new ShortcutKeyboard({
"altKey": false,
"callback": (ev: KeyboardEvent) => {
getApp().getMap().handleMapPanning(ev);
},
"code": code,
"ctrlKey": false,
"event": "keydown"
}));
});
["KeyW", "KeyA", "KeyS", "KeyD", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].forEach(code => {
shortcutManager.add(`pan${code}keyup`, new ShortcutKeyboard({
"callback": (ev: KeyboardEvent) => {
getApp().getMap().handleMapPanning(ev);
},
"code": code
}));
});
["Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9"].forEach(code => {
shortcutManager.add(`hotgroup${code}`, new ShortcutKeyboard({
"callback": (ev: KeyboardEvent) => {
if (ev.ctrlKey && ev.shiftKey)
getApp().getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
else if (ev.ctrlKey && !ev.shiftKey)
getApp().getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5)));
else
getApp().getUnitsManager().selectUnitsByHotgroup(parseInt(ev.code.substring(5)));
},
"code": code
}));
});
// TODO: move from here in dedicated class
document.addEventListener("closeDialog", (ev: CustomEventInit) => {
ev.detail._element.closest(".ol-dialog").classList.add("hide");
});
/* Try and connect with the Olympus REST server */
document.addEventListener("tryConnection", () => {
const form = document.querySelector("#splash-content")?.querySelector("#authentication-form");
const username = (form?.querySelector("#username") as HTMLInputElement).value;
const password = (form?.querySelector("#password") as HTMLInputElement).value;
/* Update the user credentials */
setCredentials(username, password);
/* Start periodically requesting updates */
startUpdate();
getApp().setLoginStatus("connecting");
})
/* Reload the page, used to mimic a restart of the app */
document.addEventListener("reloadPage", () => {
location.reload();
})
/* Inject the svgs with the corresponding svg code. This allows to dynamically manipulate the svg, like changing colors */
document.querySelectorAll("[inject-svg]").forEach((el: Element) => {
var img = el as HTMLImageElement;
var isLoaded = img.complete;
if (isLoaded)
SVGInjector(img);
else
img.addEventListener("load", () => {
SVGInjector(img);
});
})
}
window.onload = setup;

View File

@ -12,7 +12,7 @@ import { DestinationPreviewMarker } from "./markers/destinationpreviewmarker";
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
import { ClickableMiniMap } from "./clickableminimap";
import { SVGInjector } from '@tanem/svg-injector'
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTooltips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS, SHOW_CONTROL_TIPS } from "../constants/constants";
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTooltips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS } from "../constants/constants";
import { TargetMarker } from "./markers/targetmarker";
import { CoalitionArea } from "./coalitionarea/coalitionarea";
import { CoalitionAreaContextMenu } from "../contextmenus/coalitionareacontextmenu";
@ -161,7 +161,6 @@ export class Map extends L.Map {
document.addEventListener("mapVisibilityOptionsChanged", () => {
this.getContainer().toggleAttribute("data-hide-labels", !this.getVisibilityOptions()[SHOW_UNIT_LABELS]);
// TODO this.getControlTips().toggle( !this.getVisibilityOptions()[SHOW_CONTROL_TIPS] );
});
/* Pan interval */
@ -180,20 +179,16 @@ export class Map extends L.Map {
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
/* Create the checkboxes to select the advanced visibility options */
this.#visibilityOptions[SHOW_CONTACT_LINES] = false;
this.#visibilityOptions[HIDE_GROUP_MEMBERS] = true;
this.#visibilityOptions[SHOW_UNIT_PATHS] = true;
this.#visibilityOptions[SHOW_UNIT_TARGETS] = true;
this.#visibilityOptions[SHOW_UNIT_LABELS] = true;
// Manual until we use the App approach
this.#visibilityOptions[SHOW_CONTROL_TIPS] = JSON.parse( localStorage.getItem( "featureSwitches" ) || "{}" )?.controlTips || true;
this.addVisibilityOption(SHOW_CONTACT_LINES, false);
this.addVisibilityOption(HIDE_GROUP_MEMBERS, true);
this.addVisibilityOption(SHOW_UNIT_PATHS, true);
this.addVisibilityOption(SHOW_UNIT_TARGETS, true);
this.addVisibilityOption(SHOW_UNIT_LABELS, true);
}
this.#mapVisibilityOptionsDropdown.setOptionsElements(Object.keys(this.#visibilityOptions).map((option: string) => {
return createCheckboxOption(option, option, this.#visibilityOptions[option], (ev: any) => {
this.#setVisibilityOption(option, ev);
});
}));
addVisibilityOption(option: string, defaultValue: boolean) {
this.#visibilityOptions[option] = defaultValue;
this.#mapVisibilityOptionsDropdown.addOptionElement(createCheckboxOption(option, option, defaultValue, (ev: any) => { this.#setVisibilityOption(option, ev); }));
}
setLayer(layerName: string) {

View File

@ -2,6 +2,11 @@ import path from "path";
import { Manager } from "../other/manager";
import { getApp } from "..";
/** The plugins manager is responsible for loading and initializing all the plugins. Plugins are located in the public/plugins folder.
* Each plugin must be comprised of a single folder containing a index.js file. Each plugin must set the globalThis.getOlympusPlugin variable to
* return a valid class implementing the OlympusPlugin interface.
*/
export class PluginsManager extends Manager {
constructor() {
super();
@ -36,15 +41,28 @@ export class PluginsManager extends Manager {
document.getElementsByTagName("head")[0].appendChild(link);
/* Evaluate the plugin javascript */
eval(xhr.response);
const plugin = globalThis.getOlympusPlugin() as OlympusPlugin;
console.log(plugin.getName() + " loaded correctly");
if (plugin.initialize(getApp())) {
console.log(plugin.getName() + " initialized correctly");
this.add(pluginName, plugin);
var plugin: OlympusPlugin | null = null;
try {
eval(xhr.response);
plugin = globalThis.getOlympusPlugin() as OlympusPlugin;
console.log(plugin.getName() + " loaded correctly");
} catch (error: any) {
console.log("An error occured while loading a plugin from " + pluginName);
console.log(error);
}
/* If the plugin was loaded, try to initialize it */
if (plugin != null) {
try {
if (plugin.initialize(getApp())) {
console.log(plugin.getName() + " initialized correctly");
this.add(pluginName, plugin);
}
} catch (error: any) {
console.log("An error occured while initializing a plugin from " + pluginName);
console.log(error);
}
}
} else {
console.error(`Error retrieving plugin from ${pluginName}`)
}