mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
More work on database editing
This commit is contained in:
parent
ff42126b0e
commit
94901849e6
19
client/@types/olympus/index.d.ts
vendored
19
client/@types/olympus/index.d.ts
vendored
@ -542,6 +542,8 @@ declare module "interfaces" {
|
||||
};
|
||||
};
|
||||
cost?: number;
|
||||
barrelHeight?: number;
|
||||
muzzleVelocity?: number;
|
||||
}
|
||||
export interface UnitSpawnOptions {
|
||||
roleType: string;
|
||||
@ -722,6 +724,7 @@ declare module "other/utils" {
|
||||
export function getCheckboxOptions(dropdown: Dropdown): {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
export function getGroundElevation(latlng: LatLng, callback: CallableFunction): void;
|
||||
}
|
||||
declare module "controls/slider" {
|
||||
import { Control } from "controls/control";
|
||||
@ -1080,6 +1083,7 @@ declare module "unit/unit" {
|
||||
carpetBomb(latlng: LatLng): void;
|
||||
bombBuilding(latlng: LatLng): void;
|
||||
fireAtArea(latlng: LatLng): void;
|
||||
simulateFireFight(latlng: LatLng, groundElevation: number | null): void;
|
||||
/***********************************************/
|
||||
onAdd(map: Map): this;
|
||||
}
|
||||
@ -1289,9 +1293,14 @@ declare module "panels/panel" {
|
||||
}
|
||||
declare module "popups/popup" {
|
||||
import { Panel } from "panels/panel";
|
||||
export class PopupMessage {
|
||||
#private;
|
||||
constructor(text: string, fateTime: number);
|
||||
getElement(): HTMLDivElement;
|
||||
}
|
||||
export class Popup extends Panel {
|
||||
#private;
|
||||
constructor(elementId: string);
|
||||
constructor(ID: string, stackAfter?: number);
|
||||
setFadeTime(fadeTime: number): void;
|
||||
setText(text: string): void;
|
||||
}
|
||||
@ -1747,6 +1756,11 @@ declare module "unit/unitsmanager" {
|
||||
* @param latlng Location to fire at
|
||||
*/
|
||||
selectedUnitsFireAtArea(latlng: LatLng): void;
|
||||
/** Instruct the selected units to simulate a fire fight at specific coordinates
|
||||
*
|
||||
* @param latlng Location to fire at
|
||||
*/
|
||||
selectedUnitsSimulateFireFight(latlng: LatLng): void;
|
||||
/*********************** Control operations on selected units ************************/
|
||||
/** See getUnitsCategories for more info
|
||||
*
|
||||
@ -1886,7 +1900,7 @@ declare module "server/servermanager" {
|
||||
toggleDemoEnabled(): void;
|
||||
setCredentials(newUsername: string, newPassword: string): void;
|
||||
GET(callback: CallableFunction, uri: string, options?: ServerRequestOptions, responseType?: string): void;
|
||||
POST(request: object, callback: CallableFunction): void;
|
||||
PUT(request: object, callback: CallableFunction): void;
|
||||
getConfig(callback: CallableFunction): void;
|
||||
setAddress(address: string, port: number): void;
|
||||
getAirbases(callback: CallableFunction): void;
|
||||
@ -1932,6 +1946,7 @@ declare module "server/servermanager" {
|
||||
carpetBomb(ID: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
bombBuilding(ID: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
fireAtArea(ID: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
simulateFireFight(ID: number, latlng: LatLng, altitude: number, callback?: CallableFunction): void;
|
||||
setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback?: CallableFunction): void;
|
||||
setCommandModeOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {
|
||||
blue: number;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
|
||||
copy .\\node_modules\\leaflet-gesture-handling\\dist\\leaflet-gesture-handling.css .\\public\\stylesheets\\leaflet\\leaflet-gesture-handling.css
|
||||
copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
|
||||
copy .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js
|
||||
copy .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js
|
||||
|
||||
@ -14,7 +14,7 @@ const DEMO_UNIT_DATA = {
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile with a longer name\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}, {ID: 5, detectionMethod: 4}],
|
||||
activePath: [{lat: 38, lng: -115, alt: 0}, {lat: 38, lng: -114, alt: 0}]
|
||||
},
|
||||
|
||||
5327
client/package-lock.json
generated
5327
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
||||
"ejs": "^3.1.8",
|
||||
"express": "~4.16.1",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"leaflet-gesture-handling": "^1.2.2",
|
||||
"morgan": "~1.9.1",
|
||||
"save": "^2.9.0",
|
||||
"srtm-elevation": "^2.1.2"
|
||||
|
||||
@ -3,6 +3,7 @@ import { AirUnitEditor } from "./airuniteditor";
|
||||
import { OlympusApp } from "olympusapp";
|
||||
import { GroundUnitEditor } from "./grounduniteditor";
|
||||
import { PrimaryToolbar } from "toolbars/primarytoolbar";
|
||||
import { NavyUnitEditor } from "./navyuniteditor";
|
||||
|
||||
export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
#app: OlympusApp | null = null;
|
||||
@ -26,6 +27,7 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
#aircraftEditor: AirUnitEditor;
|
||||
#helicopterEditor: AirUnitEditor;
|
||||
#groundUnitEditor: GroundUnitEditor;
|
||||
#navyUnitEditor: NavyUnitEditor;
|
||||
|
||||
constructor() {
|
||||
this.#element = document.createElement("div");
|
||||
@ -59,6 +61,7 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
this.#button4 = document.createElement("button");
|
||||
this.#button4.classList.add("tab-button");
|
||||
this.#button4.textContent = "Navy Unit database";
|
||||
this.#button4.onclick = () => { this.hideAll(); this.#navyUnitEditor.show(); this.#button4.classList.add("selected"); };
|
||||
topButtonContainer.appendChild(this.#button4);
|
||||
|
||||
this.#element.appendChild(topButtonContainer);
|
||||
@ -82,6 +85,7 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
this.#aircraftEditor = new AirUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#helicopterEditor = new AirUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#groundUnitEditor = new GroundUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
this.#navyUnitEditor = new NavyUnitEditor(this.#contentDiv1, this.#contentDiv2, this.#contentDiv3);
|
||||
|
||||
let bottomButtonContainer = document.createElement("div");
|
||||
|
||||
@ -100,6 +104,10 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
var groundUnitDatabase = this.#groundUnitEditor.getDatabase();
|
||||
if (groundUnitDatabase)
|
||||
this.uploadDatabase(groundUnitDatabase, "groundUnitDatabase");
|
||||
|
||||
var navyUnitDatabase = this.#navyUnitEditor.getDatabase();
|
||||
if (navyUnitDatabase)
|
||||
this.uploadDatabase(navyUnitDatabase, "navyUnitDatabase");
|
||||
};
|
||||
bottomButtonContainer.appendChild(this.#button5);
|
||||
|
||||
@ -161,6 +169,10 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
if (groundUnitDatabase != null)
|
||||
this.#groundUnitEditor.setDatabase(groundUnitDatabase);
|
||||
|
||||
var navyUnitDatabase = this.#app?.getNavyUnitDatabase();
|
||||
if (navyUnitDatabase != null)
|
||||
this.#navyUnitEditor.setDatabase(navyUnitDatabase);
|
||||
|
||||
this.hideAll();
|
||||
this.#aircraftEditor.show();
|
||||
this.#button1.classList.add("selected");
|
||||
|
||||
@ -34,8 +34,10 @@ export class GroundUnitEditor extends UnitEditor {
|
||||
addStringInput(this.contentDiv2, "Type", blueprint.type?? "", "text", (value: string) => {blueprint.type = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"],);
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"]);
|
||||
addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost)?? "", "number", (value: string) => {blueprint.cost = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Barrel height [m]", String(blueprint.barrelHeight)?? "", "number", (value: string) => {blueprint.barrelHeight = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Muzzle velocity [m/s]", String(blueprint.muzzleVelocity)?? "", "number", (value: string) => {blueprint.muzzleVelocity = parseFloat(value); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
55
client/plugins/databasemanager/src/navyuniteditor.ts
Normal file
55
client/plugins/databasemanager/src/navyuniteditor.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { UnitBlueprint } from "interfaces";
|
||||
import { UnitEditor } from "./uniteditor";
|
||||
import { addDropdownInput, addStringInput } from "./utils";
|
||||
|
||||
export class NavyUnitEditor extends UnitEditor {
|
||||
#blueprint: UnitBlueprint | null = null;
|
||||
|
||||
constructor(contentDiv1: HTMLElement, contentDiv2: HTMLElement, contentDiv3: HTMLElement) {
|
||||
super(contentDiv1, contentDiv2, contentDiv3);
|
||||
this.contentDiv2.addEventListener("refresh", () => {
|
||||
if (this.visible) {
|
||||
if (this.#blueprint !== null)
|
||||
this.setBlueprint(this.#blueprint);
|
||||
}
|
||||
});
|
||||
|
||||
this.contentDiv3.addEventListener("refresh", () => {
|
||||
if (this.visible) {
|
||||
if (this.#blueprint !== null)
|
||||
this.setBlueprint(this.#blueprint);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setBlueprint(blueprint: UnitBlueprint) {
|
||||
this.#blueprint = blueprint;
|
||||
|
||||
if (this.#blueprint !== null) {
|
||||
this.contentDiv2.replaceChildren();
|
||||
|
||||
addStringInput(this.contentDiv2, "Name", blueprint.name, "text", (value: string) => {blueprint.name = value; }, true);
|
||||
addStringInput(this.contentDiv2, "Label", blueprint.label, "text", (value: string) => {blueprint.label = value; });
|
||||
addStringInput(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value: string) => {blueprint.shortLabel = value; });
|
||||
addStringInput(this.contentDiv2, "Type", blueprint.type?? "", "text", (value: string) => {blueprint.type = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"],);
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"]);
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost)?? "", "number", (value: string) => {blueprint.cost = parseFloat(value); });
|
||||
}
|
||||
}
|
||||
|
||||
addBlueprint(key: string) {
|
||||
if (this.database != null) {
|
||||
this.database.blueprints[key] = {
|
||||
name: key,
|
||||
coalition: "",
|
||||
label: "",
|
||||
shortLabel: "",
|
||||
era: ""
|
||||
}
|
||||
this.show();
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,30 @@
|
||||
#database-manager-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--background-steel) !important;
|
||||
z-index: 9999999;
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.dm-container {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: portrait) {
|
||||
.dm-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
#database-manager-panel * {
|
||||
font-size: 13;
|
||||
font-weight: bold;
|
||||
font-family: 'Open Sans', sans-serif !important;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#database-manager-panel>div:first-child {
|
||||
@ -27,11 +42,10 @@
|
||||
}
|
||||
|
||||
.dm-container {
|
||||
background-color: #555555;
|
||||
background-color: var(--background-grey);
|
||||
border: 2px solid #777777;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
height: calc(100% - 64px - 5px);
|
||||
@ -48,9 +62,21 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 5px;
|
||||
height: calc(100% - 20px);
|
||||
min-width: 200px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.dm-content-container {
|
||||
height: calc(100% - 20px);
|
||||
min-width: 200px;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: portrait) {
|
||||
.dm-content-container {
|
||||
width: 100% - calc(20px);
|
||||
height: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.dm-scroll-container {
|
||||
@ -62,10 +88,6 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-scroll-container>* {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div:nth-child(even) {
|
||||
background-color: gainsboro;
|
||||
}
|
||||
@ -77,9 +99,10 @@
|
||||
.dm-scroll-container>div *:nth-child(1) {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div *:nth-child(1):hover{
|
||||
.dm-scroll-container>div *:nth-child(1):hover {
|
||||
background-color: var(--secondary-blue-text);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
@ -104,7 +127,7 @@
|
||||
}
|
||||
|
||||
.input-row>dt {
|
||||
width: 150px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.input-row>dd {
|
||||
@ -113,11 +136,12 @@
|
||||
|
||||
.input-row>dd>* {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-loadout-container {
|
||||
max-height: 100%;
|
||||
width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dm-items-container {
|
||||
@ -136,11 +160,13 @@
|
||||
}
|
||||
|
||||
.dm-items-container div>input:nth-of-type(1) {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-items-container div>input:nth-of-type(2) {
|
||||
width: 40px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-new-element-input {
|
||||
@ -170,16 +196,16 @@
|
||||
|
||||
.tab-button {
|
||||
transform: translateY(+3px);
|
||||
background-color: #333333;
|
||||
background-color: var(--background-steel);
|
||||
border-radius: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
border-top: 2px solid #777777;
|
||||
border-left: 2px solid #777777;
|
||||
border-right: 0px solid #777777;
|
||||
border-bottom: 2px solid transparent !important;
|
||||
border-top: 2px solid #777777 !important;
|
||||
border-left: 2px solid #777777 !important;
|
||||
border-right: 0px solid #777777 !important;
|
||||
}
|
||||
|
||||
.tab-button.selected {
|
||||
background-color: #555555;
|
||||
background-color: var(--background-grey);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@ -189,5 +215,9 @@
|
||||
|
||||
.tab-button:last-of-type {
|
||||
border-top-right-radius: 5px;
|
||||
border-right: 2px solid #777777;
|
||||
border-right: 2px solid #777777 !important;
|
||||
}
|
||||
|
||||
#database-manager-panel button :not(.dm-scroll-container>div) {
|
||||
border: 1px solid white;
|
||||
}
|
||||
@ -13,11 +13,30 @@
|
||||
top: 10px;
|
||||
z-index: 99999;
|
||||
column-gap: 10px;
|
||||
margin-right: 320px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#toolbar-container {
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
row-gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#primary-toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: fit-content;
|
||||
min-width: 650px;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#primary-toolbar {
|
||||
row-gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
#command-mode-toolbar {
|
||||
@ -83,6 +102,18 @@
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#unit-control-panel {
|
||||
top: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1350px) {
|
||||
#unit-control-panel {
|
||||
top: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
#unit-info-panel {
|
||||
bottom: 20px;
|
||||
font-size: 12px;
|
||||
@ -91,6 +122,15 @@
|
||||
width: fit-content;
|
||||
z-index: 9999;
|
||||
padding: 24px 30px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
@media (max-width: 1525px) {
|
||||
#unit-info-panel {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
#info-popup {
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
}
|
||||
|
||||
.ol-popup-stack {
|
||||
transform: translateY(+80%);
|
||||
margin-bottom: -20px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.visible {
|
||||
|
||||
@ -9,11 +9,27 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#server-status-panel .ol-data-grid:first-of-type {
|
||||
border-right: 1px solid gray;
|
||||
padding-right: 10px;
|
||||
@media (min-width: 1525px) {
|
||||
#server-status-panel .ol-data-grid:first-of-type {
|
||||
border-right: 1px solid gray;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1525px) {
|
||||
#server-status-panel {
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
#server-status-panel .ol-data-grid:first-of-type {
|
||||
border-bottom: 1px solid gray;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#server-status-panel dd {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -91,8 +91,8 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#advanced-settings-dialog h4 {
|
||||
white-space: nowrap;
|
||||
#advanced-settings-dialog>.ol-dialog-content>div input[type="number"] {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
#advanced-settings-dialog hr {
|
||||
@ -102,6 +102,12 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
|
||||
#advanced-settings-dialog .ol-text-input input {
|
||||
height: 40px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#advanced-settings-dialog h4 {
|
||||
width: fit-content;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
#general-settings-grid {
|
||||
|
||||
@ -4,6 +4,45 @@
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
@media (min-width: 1525px) {
|
||||
#unit-info-panel>.panel-section {
|
||||
border-right: 1px solid #555;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:first-child {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-child {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type {
|
||||
border-right-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1525px) {
|
||||
#unit-info-panel>.panel-section {
|
||||
border-bottom: 1px solid #555;
|
||||
padding: 30px 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-child {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#general {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -58,10 +97,14 @@
|
||||
}
|
||||
|
||||
#loadout-items {
|
||||
margin-right: 20px;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
flex-flow: column;
|
||||
row-gap: 8px;
|
||||
column-gap: 8px;
|
||||
max-height: 90px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#loadout-items>* {
|
||||
|
||||
@ -13,6 +13,7 @@ body {
|
||||
display: grid;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
html,
|
||||
@ -305,29 +306,6 @@ form>div {
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
.ol-panel-board {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.ol-panel-board>.panel-section {
|
||||
border-right: 1px solid #555;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.ol-panel-board>.panel-section:first-child {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.ol-panel-board>.panel-section:last-child {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.ol-panel-board>.panel-section:last-of-type {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
@ -702,15 +680,21 @@ nav.ol-panel> :last-child {
|
||||
|
||||
/****************************************************************************************/
|
||||
#splash-screen {
|
||||
background-image: url("/resources/theme/images/splash/1.png");
|
||||
background-position: 100% 50%;
|
||||
background-size: 60%;
|
||||
border-radius: var(--border-radius-md);
|
||||
overflow: hidden;
|
||||
width: 1200px;
|
||||
width: 70%;
|
||||
max-width: 1200px;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
@media (min-width: 1700px) {
|
||||
#splash-screen {
|
||||
background-image: url("/resources/theme/images/splash/1.png");
|
||||
background-position: 100% 50%;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
#splash-content {
|
||||
background-color: var(--background-steel);
|
||||
display: flex;
|
||||
@ -721,6 +705,12 @@ nav.ol-panel> :last-child {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
@media (max-width: 1700px) {
|
||||
#splash-content {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#splash-content::after {
|
||||
background-color: var(--background-steel);
|
||||
content: "";
|
||||
@ -760,6 +750,10 @@ nav.ol-panel> :last-child {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#splash-content #legal-stuff {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#splash-content #legal-stuff h5 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@ -770,12 +764,14 @@ nav.ol-panel> :last-child {
|
||||
width: 120%;
|
||||
}
|
||||
|
||||
#splash-content.ol-dialog-content {
|
||||
margin: 0px;
|
||||
@media (max-width: 1700px) {
|
||||
#splash-content #legal-stuff p {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-splashScreen #splash-screen {
|
||||
display: flex;
|
||||
#splash-content.ol-dialog-content {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#gray-out {
|
||||
@ -794,6 +790,8 @@ nav.ol-panel> :last-child {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px 0px;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#authentication-form>div {
|
||||
|
||||
@ -204,6 +204,8 @@ export interface UnitBlueprint {
|
||||
filename?: string;
|
||||
liveries?: { [key: string]: { name: string, countries: string[] } };
|
||||
cost?: number;
|
||||
barrelHeight?: number;
|
||||
muzzleVelocity?: number;
|
||||
}
|
||||
|
||||
export interface UnitSpawnOptions {
|
||||
|
||||
@ -19,8 +19,19 @@ import { CoalitionAreaContextMenu } from "../contextmenus/coalitionareacontextme
|
||||
import { DrawingCursor } from "./coalitionarea/drawingcursor";
|
||||
import { AirbaseSpawnContextMenu } from "../contextmenus/airbasespawnmenu";
|
||||
import { Popup } from "../popups/popup";
|
||||
import { GestureHandling } from "leaflet-gesture-handling";
|
||||
import { TouchBoxSelect } from "./touchboxselect";
|
||||
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
var hasTouchScreen = false;
|
||||
if ("maxTouchPoints" in navigator)
|
||||
hasTouchScreen = navigator.maxTouchPoints > 0;
|
||||
|
||||
if (hasTouchScreen)
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', TouchBoxSelect);
|
||||
else
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
|
||||
L.Map.addInitHook("addHandler", "gestureHandling", GestureHandling);
|
||||
|
||||
// TODO would be nice to convert to ts - yes
|
||||
require("../../public/javascripts/leaflet.nauticscale.js")
|
||||
@ -77,8 +88,22 @@ export class Map extends L.Map {
|
||||
*/
|
||||
constructor(ID: string){
|
||||
/* Init the leaflet map */
|
||||
//@ts-ignore Needed because the boxSelect option is non-standard
|
||||
super(ID, { zoomSnap: 0, zoomDelta: 0.25, preferCanvas: true, doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7, keyboard: true, keyboardPanDelta: 0 });
|
||||
super(ID, {
|
||||
zoomSnap: 0,
|
||||
zoomDelta: 0.25,
|
||||
preferCanvas: true,
|
||||
doubleClickZoom: false,
|
||||
zoomControl: false,
|
||||
boxZoom: false,
|
||||
//@ts-ignore Needed because the boxSelect option is non-standard
|
||||
boxSelect: true,
|
||||
zoomAnimation: true,
|
||||
maxBoundsViscosity: 1.0,
|
||||
minZoom: 7,
|
||||
keyboard: true,
|
||||
keyboardPanDelta: 0,
|
||||
gestureHandling: hasTouchScreen
|
||||
});
|
||||
this.setView([37.23, -115.8], 10);
|
||||
|
||||
this.#ID = ID;
|
||||
@ -486,7 +511,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
|
||||
136
client/src/map/touchboxselect.ts
Normal file
136
client/src/map/touchboxselect.ts
Normal file
@ -0,0 +1,136 @@
|
||||
import { Map, Point } from 'leaflet';
|
||||
import { Handler } from 'leaflet';
|
||||
import { Util } from 'leaflet';
|
||||
import { DomUtil } from 'leaflet';
|
||||
import { DomEvent } from 'leaflet';
|
||||
import { LatLngBounds } from 'leaflet';
|
||||
import { Bounds } from 'leaflet';
|
||||
|
||||
export var TouchBoxSelect = Handler.extend({
|
||||
initialize: function (map: Map) {
|
||||
this._map = map;
|
||||
this._container = map.getContainer();
|
||||
this._pane = map.getPanes().overlayPane;
|
||||
this._resetStateTimeout = 0;
|
||||
this._doubleClicked = false;
|
||||
map.on('unload', this._destroy, this);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
DomEvent.on(this._container, 'touchstart', this._onMouseDown, this);
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
DomEvent.off(this._container, 'touchstart', this._onMouseDown, this);
|
||||
},
|
||||
|
||||
moved: function () {
|
||||
return this._moved;
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
DomUtil.remove(this._pane);
|
||||
delete this._pane;
|
||||
},
|
||||
|
||||
_resetState: function () {
|
||||
this._resetStateTimeout = 0;
|
||||
this._moved = false;
|
||||
},
|
||||
|
||||
_clearDeferredResetState: function () {
|
||||
if (this._resetStateTimeout !== 0) {
|
||||
clearTimeout(this._resetStateTimeout);
|
||||
this._resetStateTimeout = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseDown: function (e: any) {
|
||||
if ((e.which == 0)) {
|
||||
this._map.fire('selectionstart');
|
||||
// Clear the deferred resetState if it hasn't executed yet, otherwise it
|
||||
// will interrupt the interaction and orphan a box element in the container.
|
||||
this._clearDeferredResetState();
|
||||
this._resetState();
|
||||
|
||||
DomUtil.disableTextSelection();
|
||||
DomUtil.disableImageDrag();
|
||||
|
||||
this._startPoint = this._getMousePosition(e);
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.on(document, {
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp
|
||||
}, this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseMove: function (e: any) {
|
||||
if (!this._moved) {
|
||||
this._moved = true;
|
||||
|
||||
this._box = DomUtil.create('div', 'leaflet-zoom-box', this._container);
|
||||
DomUtil.addClass(this._container, 'leaflet-crosshair');
|
||||
}
|
||||
|
||||
this._point = this._getMousePosition(e);
|
||||
|
||||
var bounds = new Bounds(this._point, this._startPoint),
|
||||
size = bounds.getSize();
|
||||
|
||||
if (bounds.min != undefined)
|
||||
DomUtil.setPosition(this._box, bounds.min);
|
||||
|
||||
this._box.style.width = size.x + 'px';
|
||||
this._box.style.height = size.y + 'px';
|
||||
},
|
||||
|
||||
_finish: function () {
|
||||
if (this._moved) {
|
||||
DomUtil.remove(this._box);
|
||||
DomUtil.removeClass(this._container, 'leaflet-crosshair');
|
||||
}
|
||||
|
||||
DomUtil.enableTextSelection();
|
||||
DomUtil.enableImageDrag();
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.off(document, {
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onMouseUp: function (e: any) {
|
||||
if ((e.which !== 0)) { return; }
|
||||
|
||||
this._finish();
|
||||
|
||||
if (!this._moved) { return; }
|
||||
// Postpone to next JS tick so internal click event handling
|
||||
// still see it as "moved".
|
||||
window.setTimeout(Util.bind(this._resetState, this), 0);
|
||||
var bounds = new LatLngBounds(
|
||||
this._map.containerPointToLatLng(this._startPoint),
|
||||
this._map.containerPointToLatLng(this._point));
|
||||
|
||||
this._map.fire('selectionend', { selectionBounds: bounds });
|
||||
},
|
||||
|
||||
_getMousePosition(e: any) {
|
||||
var scale = DomUtil.getScale(this._container), offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)
|
||||
|
||||
return new Point(
|
||||
// offset.left/top values are in page scale (like clientX/Y),
|
||||
// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
|
||||
(e.touches[0].clientX - offset.left) / scale.x - this._container.clientLeft,
|
||||
(e.touches[0].clientY - offset.top) / scale.y - this._container.clientTop
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -28,16 +28,16 @@ export class PopupMessage {
|
||||
}
|
||||
|
||||
export class Popup extends Panel {
|
||||
#fadeTime: number = 2000; // Milliseconds
|
||||
#messages: PopupMessage[] = [];
|
||||
#stackAfter: number;
|
||||
|
||||
constructor(ID: string, stackAfter: number = 5) {
|
||||
constructor(ID: string, stackAfter: number = 3) {
|
||||
super(ID);
|
||||
this.show();
|
||||
this.#stackAfter = stackAfter;
|
||||
}
|
||||
|
||||
#fadeTime: number = 2000; // Milliseconds
|
||||
setFadeTime(fadeTime: number) {
|
||||
this.#fadeTime = fadeTime;
|
||||
}
|
||||
@ -52,7 +52,7 @@ export class Popup extends Panel {
|
||||
this.getElement().appendChild(message.getElement());
|
||||
this.#messages.push(message);
|
||||
if (this.#messages.length > this.#stackAfter) {
|
||||
this.#messages[this.#messages.length - this.#stackAfter].getElement().classList.add("ol-popup-stack");
|
||||
this.#messages[this.#messages.length - this.#stackAfter - 1].getElement().classList.add("ol-popup-stack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,7 +326,7 @@ export class ServerManager {
|
||||
simulateFireFight(ID: number, latlng: LatLng, altitude: number, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID, "location": latlng, "altitude": altitude }
|
||||
var data = { "simulateFireFight": command }
|
||||
this.POST(data, callback);
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback: CallableFunction = () => {}) {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<title>Olympus client</title>
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/olympus.css" />
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/leaflet/leaflet.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/leaflet/leaflet-gesture-handling.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/resources/theme/theme.css" /> <!-- Theme specifc css, autorouted to point to active theme -->
|
||||
|
||||
|
||||
@ -1,29 +1,25 @@
|
||||
<div id="unit-info-panel" class="ol-panel" oncontextmenu="return false;">
|
||||
|
||||
<div class="ol-panel-board">
|
||||
|
||||
<div id="general" class="panel-section">
|
||||
<h3 id="unit-name"></h3>
|
||||
<div class="ol-group">
|
||||
<div id="unit-label"></div>
|
||||
<div id="unit-control"></div>
|
||||
</div>
|
||||
<div id="current-task" class="pill highlight-coalition" data-coalition="blue" data-current-task=""></div>
|
||||
<div id="general" class="panel-section">
|
||||
<h3 id="unit-name"></h3>
|
||||
<div class="ol-group">
|
||||
<div id="unit-label"></div>
|
||||
<div id="unit-control"></div>
|
||||
</div>
|
||||
<div id="current-task" class="pill highlight-coalition" data-coalition="blue" data-current-task=""></div>
|
||||
</div>
|
||||
|
||||
<div id="loadout-container" class="panel-section">
|
||||
|
||||
<div id="loadout">
|
||||
<img id="loadout-silhouette"/>
|
||||
<div id="loadout-items">
|
||||
</div>
|
||||
<div id="loadout-container" class="panel-section">
|
||||
|
||||
<div id="loadout">
|
||||
<img id="loadout-silhouette"/>
|
||||
<div id="loadout-items">
|
||||
</div>
|
||||
|
||||
<div id="fuel-percentage" data-percentage=""></div>
|
||||
<div id="fuel-display">
|
||||
<div id="fuel-bar" class="highlight-coalition" data-coalition="blue" style="width:30%;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="fuel-percentage" data-percentage=""></div>
|
||||
<div id="fuel-display">
|
||||
<div id="fuel-bar" class="highlight-coalition" data-coalition="blue" style="width:30%;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user