diff --git a/client/app.js b/client/app.js index 8fbd41c1..a10aaf2f 100644 --- a/client/app.js +++ b/client/app.js @@ -9,6 +9,7 @@ var atcRouter = require('./routes/api/atc'); var indexRouter = require('./routes/index'); var uikitRouter = require('./routes/uikit'); var usersRouter = require('./routes/users'); +var resourcesRouter = require('./routes/resources'); var app = express(); @@ -22,6 +23,7 @@ app.use('/', indexRouter); app.use('/api/atc', atcRouter); app.use('/users', usersRouter); app.use('/uikit', uikitRouter); +app.use('/resources', resourcesRouter); app.set('view engine', 'ejs'); diff --git a/client/copy.bat b/client/copy.bat new file mode 100644 index 00000000..1acc220e --- /dev/null +++ b/client/copy.bat @@ -0,0 +1,3 @@ +copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css +copy .\\node_modules\\@iconfu\\svg-inject\\dist\\svg-inject.js .\\public\\javascripts\\svg-inject.js +copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js diff --git a/client/demo.js b/client/demo.js index 2c113e9f..292e2f52 100644 --- a/client/demo.js +++ b/client/demo.js @@ -4,8 +4,8 @@ const DEMO_UNIT_DATA = { baseData: { AI: false, name: "KC-135", - unitName: "Olympus 1-1", - groupName: "Group 1", + unitName: "Olympus 1-1 aka Mr. Very long name", + groupName: "Group 2", alive: true, category: "Aircraft", }, @@ -71,7 +71,7 @@ const DEMO_UNIT_DATA = { AI: true, name: "KC-135", unitName: "Olympus 1-2", - groupName: "Group 1", + groupName: "Group 3", alive: true, category: "Aircraft", }, @@ -114,7 +114,7 @@ const DEMO_UNIT_DATA = { AI: true, name: "2S6 Tunguska", unitName: "Olympus 1-3", - groupName: "Group 1", + groupName: "Group 4", alive: true, category: "GroundUnit", }, @@ -284,7 +284,7 @@ const DEMO_UNIT_DATA = { ["7"]:{ baseData: { AI: true, - name: "CVN-75", + name: "CVN-75 Very long name", unitName: "Olympus 1-7", groupName: "Group 1", alive: true, @@ -677,15 +677,18 @@ class DemoDataGenerator { var ret = {bullseyes: { "0": { latitude: 37.25, - longitude: -115.8 + longitude: -115.8, + coalition: "neutral" }, "1": { latitude: 37.25, - longitude: -115.75 + longitude: -115.75, + coalition: "red" }, "2": { latitude: 37.25, - longitude: -115.7 + longitude: -115.7, + coalition: "blue" } }}; ret.time = Date.now(); diff --git a/client/package-lock.json b/client/package-lock.json index 55970983..e6e672a7 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,26 +10,27 @@ "dependencies": { "@types/geojson": "^7946.0.10", "@types/leaflet": "^1.9.0", + "@types/svg-injector": "^0.0.29", "cookie-parser": "~1.4.4", "debug": "~2.6.9", "ejs": "^3.1.8", "express": "~4.16.1", - "geomag": "^1.0.0", "leaflet": "^1.9.3", "leaflet-control-mini-map": "^0.4.0", "leaflet.nauticscale": "^1.1.0", - "milsymbol": "^2.0.0", "morgan": "~1.9.1", "save": "^2.9.0" }, "devDependencies": { "@babel/preset-env": "^7.21.4", + "@tanem/svg-injector": "^10.1.55", "@types/gtag.js": "^0.0.12", "@types/node": "^18.16.1", "@types/sortablejs": "^1.15.0", "babelify": "^10.0.0", "browserify": "^17.0.0", "concurrently": "^7.6.0", + "cp": "^0.2.0", "esmify": "^2.1.1", "express-basic-auth": "^1.2.1", "nodemon": "^2.0.20", @@ -1686,9 +1687,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" @@ -1823,6 +1824,17 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, + "node_modules/@tanem/svg-injector": { + "version": "10.1.55", + "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-10.1.55.tgz", + "integrity": "sha512-xh8ejdvjDaH1eddZC0CdI45eeid4BIU2ppjNEhiTiWMYcLGT19KWjbES/ttDS4mq9gIAQfXx57g5zimEVohqYA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.5", + "content-type": "^1.0.5", + "tslib": "^2.5.0" + } + }, "node_modules/@types/geojson": { "version": "7946.0.10", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", @@ -1854,6 +1866,11 @@ "integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==", "dev": true }, + "node_modules/@types/svg-injector": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/svg-injector/-/svg-injector-0.0.29.tgz", + "integrity": "sha512-tNvoN0Xk2si6IfxQI/PqInipOuCyXkDZhCh9Vc4aFv/l1DhIBfTFbXRXYUHBAGXaUNMOCHEtg9475O9J+4NXOg==" + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2816,9 +2833,9 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } @@ -2881,6 +2898,12 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cp": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cp/-/cp-0.2.0.tgz", + "integrity": "sha512-4ftCvShHjIZG/zzomHyunNpBof3sOFTTmU6s6q9DdqAL/ANqrKV3pr6Z6kVfBI4hjn59DFLImrBqn7GuuMqSZA==", + "dev": true + }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -3428,11 +3451,6 @@ "node": ">=6.9.0" } }, - "node_modules/geomag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/geomag/-/geomag-1.0.0.tgz", - "integrity": "sha512-mEblE1vO7HojL7nk2R2s670s1nc/u0jtQaP/8EvZxPZ7XlfkwEJ+TWpjgkNy2402Yj2/VaxaefGQgIzbUzUwHg==" - }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -4135,11 +4153,6 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, - "node_modules/milsymbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz", - "integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ==" - }, "node_modules/mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", @@ -5330,9 +5343,9 @@ } }, "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==", "dev": true }, "node_modules/tty-browserify": { @@ -6828,9 +6841,9 @@ "dev": true }, "@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dev": true, "requires": { "regenerator-runtime": "^0.13.11" @@ -6940,6 +6953,17 @@ } } }, + "@tanem/svg-injector": { + "version": "10.1.55", + "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-10.1.55.tgz", + "integrity": "sha512-xh8ejdvjDaH1eddZC0CdI45eeid4BIU2ppjNEhiTiWMYcLGT19KWjbES/ttDS4mq9gIAQfXx57g5zimEVohqYA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.21.5", + "content-type": "^1.0.5", + "tslib": "^2.5.0" + } + }, "@types/geojson": { "version": "7946.0.10", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", @@ -6971,6 +6995,11 @@ "integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==", "dev": true }, + "@types/svg-injector": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/svg-injector/-/svg-injector-0.0.29.tgz", + "integrity": "sha512-tNvoN0Xk2si6IfxQI/PqInipOuCyXkDZhCh9Vc4aFv/l1DhIBfTFbXRXYUHBAGXaUNMOCHEtg9475O9J+4NXOg==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -7748,9 +7777,9 @@ "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==" }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { "version": "1.1.3", @@ -7798,6 +7827,12 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cp": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cp/-/cp-0.2.0.tgz", + "integrity": "sha512-4ftCvShHjIZG/zzomHyunNpBof3sOFTTmU6s6q9DdqAL/ANqrKV3pr6Z6kVfBI4hjn59DFLImrBqn7GuuMqSZA==", + "dev": true + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -8271,11 +8306,6 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, - "geomag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/geomag/-/geomag-1.0.0.tgz", - "integrity": "sha512-mEblE1vO7HojL7nk2R2s670s1nc/u0jtQaP/8EvZxPZ7XlfkwEJ+TWpjgkNy2402Yj2/VaxaefGQgIzbUzUwHg==" - }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -8807,11 +8837,6 @@ } } }, - "milsymbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz", - "integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ==" - }, "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", @@ -9780,9 +9805,9 @@ } }, "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==", "dev": true }, "tty-browserify": { diff --git a/client/package.json b/client/package.json index fce35cdf..f0db50cb 100644 --- a/client/package.json +++ b/client/package.json @@ -5,33 +5,34 @@ "version": "v0.2.1-alpha", "private": true, "scripts": { - "copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css", + "copy": "copy.bat", "start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"", "watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]" }, "dependencies": { "@types/geojson": "^7946.0.10", "@types/leaflet": "^1.9.0", + "@types/svg-injector": "^0.0.29", "cookie-parser": "~1.4.4", "debug": "~2.6.9", "ejs": "^3.1.8", "express": "~4.16.1", - "geomag": "^1.0.0", "leaflet": "^1.9.3", "leaflet-control-mini-map": "^0.4.0", "leaflet.nauticscale": "^1.1.0", - "milsymbol": "^2.0.0", "morgan": "~1.9.1", "save": "^2.9.0" }, "devDependencies": { "@babel/preset-env": "^7.21.4", + "@tanem/svg-injector": "^10.1.55", "@types/gtag.js": "^0.0.12", "@types/node": "^18.16.1", "@types/sortablejs": "^1.15.0", "babelify": "^10.0.0", "browserify": "^17.0.0", "concurrently": "^7.6.0", + "cp": "^0.2.0", "esmify": "^2.1.1", "express-basic-auth": "^1.2.1", "nodemon": "^2.0.20", diff --git a/client/prepare.bat b/client/prepare.bat new file mode 100644 index 00000000..f163f70e --- /dev/null +++ b/client/prepare.bat @@ -0,0 +1,2 @@ +copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css +copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js diff --git a/client/public/images/bullseye.png b/client/public/images/bullseye.png deleted file mode 100644 index f7024954..00000000 Binary files a/client/public/images/bullseye.png and /dev/null differ diff --git a/client/public/images/bullseye.xcf b/client/public/images/bullseye.xcf deleted file mode 100644 index 097722f6..00000000 Binary files a/client/public/images/bullseye.xcf and /dev/null differ diff --git a/client/public/images/bullseye0.png b/client/public/images/bullseye0.png deleted file mode 100644 index a51fe39f..00000000 Binary files a/client/public/images/bullseye0.png and /dev/null differ diff --git a/client/public/images/bullseye1.png b/client/public/images/bullseye1.png deleted file mode 100644 index 6d574bbd..00000000 Binary files a/client/public/images/bullseye1.png and /dev/null differ diff --git a/client/public/images/bullseye2.png b/client/public/images/bullseye2.png deleted file mode 100644 index 4e99f79e..00000000 Binary files a/client/public/images/bullseye2.png and /dev/null differ diff --git a/client/public/images/buttons/edit.svg b/client/public/images/buttons/edit.svg deleted file mode 100644 index 5b51c67c..00000000 --- a/client/public/images/buttons/edit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/images/buttons/reorder.svg b/client/public/images/buttons/reorder.svg deleted file mode 100644 index 4ae9b04e..00000000 --- a/client/public/images/buttons/reorder.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - diff --git a/client/public/images/formations/azimuth.png b/client/public/images/formations/azimuth.png deleted file mode 100644 index 1264e20a..00000000 Binary files a/client/public/images/formations/azimuth.png and /dev/null differ diff --git a/client/public/images/formations/range.png b/client/public/images/formations/range.png deleted file mode 100644 index 9df137cb..00000000 Binary files a/client/public/images/formations/range.png and /dev/null differ diff --git a/client/public/images/formations/single.png b/client/public/images/formations/single.png deleted file mode 100644 index 2a92faee..00000000 Binary files a/client/public/images/formations/single.png and /dev/null differ diff --git a/client/public/images/icons/bullseye-solid.svg b/client/public/images/icons/bullseye-solid.svg deleted file mode 100644 index c6400970..00000000 --- a/client/public/images/icons/bullseye-solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/public/images/icons/formation.png b/client/public/images/icons/formation.png deleted file mode 100644 index b140e9f6..00000000 Binary files a/client/public/images/icons/formation.png and /dev/null differ diff --git a/client/public/images/icons/leader.png b/client/public/images/icons/leader.png deleted file mode 100644 index 8744386f..00000000 Binary files a/client/public/images/icons/leader.png and /dev/null differ diff --git a/client/public/images/icons/singleton.png b/client/public/images/icons/singleton.png deleted file mode 100644 index 06644361..00000000 Binary files a/client/public/images/icons/singleton.png and /dev/null differ diff --git a/client/public/images/icons/square-check-regular.svg b/client/public/images/icons/square-check-regular.svg deleted file mode 100644 index 4ce0ff82..00000000 --- a/client/public/images/icons/square-check-regular.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/public/images/icons/trash-can-regular.svg b/client/public/images/icons/trash-can-regular.svg deleted file mode 100644 index 011e1a5e..00000000 --- a/client/public/images/icons/trash-can-regular.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/public/images/pin.svg b/client/public/images/pin.svg deleted file mode 100644 index 19e92ec2..00000000 --- a/client/public/images/pin.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/public/images/reference-system-test.svg b/client/public/images/reference-system-test.svg deleted file mode 100644 index ff6f152a..00000000 --- a/client/public/images/reference-system-test.svg +++ /dev/null @@ -1,370 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - diff --git a/client/public/images/reference-system.svg b/client/public/images/reference-system.svg deleted file mode 100644 index cd71d782..00000000 --- a/client/public/images/reference-system.svg +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/client/public/images/unit.png b/client/public/images/unit.png deleted file mode 100644 index ae72bc19..00000000 Binary files a/client/public/images/unit.png and /dev/null differ diff --git a/client/public/javascripts/leaflet.nauticscale.js b/client/public/javascripts/leaflet.nauticscale.js new file mode 100644 index 00000000..ccf19ac3 --- /dev/null +++ b/client/public/javascripts/leaflet.nauticscale.js @@ -0,0 +1,38 @@ +L.Control.ScaleNautic = L.Control.Scale.extend({ + options: { + nautic: false + }, + + _addScales: function(options, className, container) { + L.Control.Scale.prototype._addScales.call(this, options, className, container); + L.setOptions(options); + if (this.options.nautic) { + this._nScale = L.DomUtil.create('div', className, container); + } + }, + + _updateScales: function (maxMeters) { + L.Control.Scale.prototype._updateScales.call(this, maxMeters); + if (this.options.nautic && maxMeters) { + this._updateNautic(maxMeters); + } + }, + + _updateNautic: function (maxMeters) { + var scale = this._nScale, + maxNauticalMiles = maxMeters / 1852, nauticalMiles; + + if(maxMeters >= 1852) { + nauticalMiles = L.Control.Scale.prototype._getRoundNum.call(this, maxNauticalMiles); + } else { + nauticalMiles = maxNauticalMiles > 0.1 ? Math.round(maxNauticalMiles * 10) / 10 : Math.round(maxNauticalMiles * 100) / 100; + } + + scale.style.width = Math.round(this.options.maxWidth * (nauticalMiles / maxNauticalMiles)) - 10 + 'px'; + scale.innerHTML = nauticalMiles + ' nm'; + } +}); + +L.control.scalenautic = function (options) { + return new L.Control.ScaleNautic(options); +}; diff --git a/client/public/stylesheets/aic.css b/client/public/stylesheets/aic/aic.css similarity index 100% rename from client/public/stylesheets/aic.css rename to client/public/stylesheets/aic/aic.css diff --git a/client/public/stylesheets/airbase.css b/client/public/stylesheets/airbase.css deleted file mode 100644 index fac5497b..00000000 --- a/client/public/stylesheets/airbase.css +++ /dev/null @@ -1,45 +0,0 @@ -:root { - --airbase-marker-height: 40px; - --airbase-marker-width: 40px; -} - -[data-object|="airbase"] { - align-items: center; - cursor: pointer; - display: flex; - justify-content: center; - position: relative; -} - -[data-hide-airbase] #map-container [data-object|="airbase"] { - display: none; -} - -/****************************** -Marker -******************************/ - -[data-object|="airbase"] .airbase { - background-color: transparent; - background-repeat: no-repeat; - background-size: cover; - position: absolute; - transform-origin: center; - z-index: 3; -} - -/* Airbase */ -[data-object|="airbase"] .airbase-marker { - background-image: var(--airbase-marker-neutral-url); - background-size: contain; - height: var(--airbase-marker-height); - width: var(--airbase-marker-width); -} - -[data-object|="airbase"][data-coalition="red"] .airbase-marker { - background-image: var(--airbase-marker-red-url); -} - -[data-object|="airbase"][data-coalition="blue"] .airbase-marker { - background-image: var(--airbase-marker-blue-url); -} \ No newline at end of file diff --git a/client/public/stylesheets/atc.css b/client/public/stylesheets/atc/atc.css similarity index 100% rename from client/public/stylesheets/atc.css rename to client/public/stylesheets/atc/atc.css diff --git a/client/public/stylesheets/unitdatatable.css b/client/public/stylesheets/atc/unitdatatable.css similarity index 100% rename from client/public/stylesheets/unitdatatable.css rename to client/public/stylesheets/atc/unitdatatable.css diff --git a/client/public/stylesheets/layout.css b/client/public/stylesheets/layout.css deleted file mode 100644 index dfa23432..00000000 --- a/client/public/stylesheets/layout.css +++ /dev/null @@ -1,246 +0,0 @@ -/* Page style */ -#map-container { - height: 100%; - min-width: 820px; - width: 100%; -} - -#primary-toolbar { - align-items: center; - display:flex; - position: absolute; - left: 10px; - top: 10px; - z-index: 1000; -} - -#olympus-toolbar-summary { - background-image: url("/images/icon-round.png"); - background-position: 20px 22px; - background-repeat: no-repeat; - background-size: 45px 45px; - display: flex; - flex-direction: column; - text-indent: 60px; - padding: 20px; -} - -dl.ol-data-grid { - align-items: center; - display: flex; - flex-direction: row; - flex-wrap: wrap; - margin: 0; - row-gap: 4px; -} - -dl.ol-data-grid dt { - width: 60%; -} - -dl.ol-data-grid dd { - width: 40%; -} - - -dl.ol-data-grid dt.icon { - text-indent: 10px; -} - -dl.ol-data-grid dt.icon::before { - content: url(/images/icons/speed.svg ); - display: inline-block; - filter: invert(100%); - width: 20px; - translate: -20px 2px; -} - - -dl.ol-data-grid dt.icon-speed::before { - content: url(/images/icons/speed.svg ); -} - - -dl.ol-data-grid dt.icon-altitude::before { - content: url(/images/icons/altitude.svg ); -} - -dl.ol-data-grid dd { - display: flex; - justify-content: flex-end; - margin-left: auto; -} - -.br-info::after { - content: attr(data-bearing) '\00B0 / ' attr(data-distance) attr(data-distance-units); -} - -.br-info[data-message]::after { - content: attr(data-message); -} - -.coordinates::after { - content: attr(data-dd) "\00b0 " attr(data-mm) "'" attr(data-ss) "." attr(data-sss) '"' attr(data-label); -} - -.ol-button-box { - column-gap: 6px; - display: flex; - flex-direction: row; - flex-wrap: wrap; - margin: 5px 0; - row-gap: 5px; -} - -.ol-button-box button { - background-repeat: no-repeat; - ; - border: 1px solid var(--accent-light-blue); - color: var(--accent-light-blue); -} - -.ol-dialog { - align-self: center; - background-color: var(--background-slate-blue); - color: white; - justify-self: center; - position: absolute; - z-index: 1000; -} - -.ol-panel.ol-dialog { - padding: 24px 30px; -} - -.ol-dialog-close { - cursor: pointer; - font-size: 16px; - font-weight: var(--font-weight-bolder); - position: absolute; - right: 20px; - top: 10px; -} - -.ol-dialog-close::before { - content: "\d7"; -} - -.ol-dialog-header { - border-bottom: 1px solid var(--background-grey); - padding-bottom: 10px; -} - -.ol-dialog-content { - margin:4px 0; -} - -.ol-dialog-footer { - border-top: 1px solid var(--background-grey); - padding-top: 15px; - display: flex; - row-gap: 10px; -} - -.ol-dialog.scrollable .ol-dialog-content { - overflow-y: auto; -} - -.ol-checkbox label { - align-items: center; - cursor: pointer; - display: flex; - flex-wrap: nowrap; - white-space: nowrap; -} - -.ol-checkbox input[type="checkbox"] { - appearance: none; - background-color: transparent; - border: none; - margin: 0; -} - -.ol-checkbox input[type="checkbox"]::before { - align-self: center; - background-image: url("/images/icons/square-regular.svg"); - background-repeat: no-repeat; - content: ""; - filter: invert(100%); - display: flex; - height: 16px; - margin-right: 10px; - width: 16px; -} - -.ol-checkbox input[type="checkbox"]:checked::before { - background-image: url("/images/icons/square-check-solid.svg"); -} - -.ol-text-input input { - height: 32px; - border-radius: 5px; - color: var(--background-offwhite); - background-color: var(--background-grey); - border: 1px solid var(--background-grey); - border-radius: var(--border-radius-sm); - text-align: center; - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); -} - -input[type=number] { - -moz-appearance: textfield; - appearance: textfield; - margin: 0; -} - -input[type=number]::-webkit-inner-spin-button, -input[type=number]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -[class|="ol-button"] { - align-items: center; - background-repeat: no-repeat; - display: flex; - font-weight: normal; - padding: 8px 10px; - white-space: nowrap; -} - -[class|="ol-button"]::before { - margin-right: 8px; -} - -.ol-button-close { - background: transparent; - border: 1px solid white; -} - -.ol-button-close::before { - content: "\d7"; -} - -.ol-button-apply { - background: transparent; - border: 1px solid white; -} - -.ol-button-apply::before { - content: "\2713"; -} - -.ol-button-settings { - background-color: var(--background-slate-blue); -} - -.ol-button-settings::before { - background-image: url("/images/icons/gears-solid.svg"); - background-position: 0 50%; - background-size: 24px 24px; - content: ""; - display: flex; - filter: invert(100%); - height: 24px; - width: 24px; -} \ No newline at end of file diff --git a/client/public/stylesheets/layout/layout.css b/client/public/stylesheets/layout/layout.css new file mode 100644 index 00000000..91926b4b --- /dev/null +++ b/client/public/stylesheets/layout/layout.css @@ -0,0 +1,75 @@ +/* Page style */ +#map-container { + height: 100%; + min-width: 820px; + width: 100%; +} + +#primary-toolbar { + align-items: center; + display: flex; + left: 10px; + position: absolute; + top: 10px; + z-index: 1000; +} + +#toolbar-summary { + background-image: url("/images/icon-round.png"); + background-position: 20px 22px; + background-repeat: no-repeat; + background-size: 45px 45px; + display: flex; + flex-direction: column; + padding: 20px; + text-indent: 60px; +} + +#connection-status-panel { + bottom: 20px; + font-size: 12px; + position: absolute; + right: 10px; + width: 160px; + z-index: 1000; +} + +#mouse-info-panel { + bottom: 60px; + display: flex; + flex-direction: column; + height: fit-content; + position: absolute; + right: 10px; + row-gap: 10px; + width: 160px; + z-index: 1000; +} + +#unit-control-panel { + height: fit-content; + left: 10px; + position: absolute; + top: 80px; + width: 240px; + z-index: 1000; +} + +#unit-info-panel { + bottom: 20px; + font-size: 12px; + left: 10px; + position: absolute; + width: fit-content; + z-index: 1000; +} + +#info-popup { + position: absolute; + width: fit-content; + height: fit-content; + top: 100px; + left: 50%; + translate: -50% 0%; + z-index: 9999; +} \ No newline at end of file diff --git a/client/public/stylesheets/leaflet.css b/client/public/stylesheets/leaflet/leaflet.css similarity index 100% rename from client/public/stylesheets/leaflet.css rename to client/public/stylesheets/leaflet/leaflet.css diff --git a/client/public/stylesheets/markers/airbase.css b/client/public/stylesheets/markers/airbase.css new file mode 100644 index 00000000..a9640cf3 --- /dev/null +++ b/client/public/stylesheets/markers/airbase.css @@ -0,0 +1,20 @@ +.airbase-icon { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + position: relative; +} + +.airbase-icon[data-coalition="red"] svg * { + stroke: var(--unit-background-red); +} + +.airbase-icon[data-coalition="blue"] svg * { + stroke: var(--unit-background-blue); +} + +.airbase-icon[data-coalition="neutral"] svg * { + stroke: var(--unit-background-neutral); +} + diff --git a/client/public/stylesheets/markers/bullseye.css b/client/public/stylesheets/markers/bullseye.css new file mode 100644 index 00000000..81663b09 --- /dev/null +++ b/client/public/stylesheets/markers/bullseye.css @@ -0,0 +1,22 @@ +.bullseye-icon { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + position: relative; +} + +.bullseye-icon[data-coalition="red"] svg * { + stroke: var(--unit-background-red); + fill: var(--unit-background-red); +} + +.bullseye-icon[data-coalition="blue"] svg * { + stroke: var(--unit-background-blue); + fill: var(--unit-background-blue); +} + +.bullseye-icon[data-coalition="neutral"] svg * { + stroke: var(--unit-background-neutral); + fill: var(--unit-background-neutral); +} diff --git a/client/public/stylesheets/markers/units.css b/client/public/stylesheets/markers/units.css new file mode 100644 index 00000000..43bc53a0 --- /dev/null +++ b/client/public/stylesheets/markers/units.css @@ -0,0 +1,309 @@ +:root { + /* Generic marker settings */ + --unit-centre-x: calc(var(--unit-width) / 2); + --unit-centre-y: calc(var(--unit-height) / 2); +} + +/*** Unit marker elements ***/ +[data-object|="unit"] { + align-items: center; + cursor: pointer; + display: flex; + height: 100%; + justify-content: center; + position: relative; + width: 100%; +} + +.unit-vvi { + align-self: center; + background: var(--secondary-gunmetal-grey); + display: flex; + justify-self: center; + padding-bottom: calc((var(--unit-aircraft-width) / 2) + var(--unit-stroke-width)); + position: absolute; + transform-origin: bottom; + translate: 0 -50%; + width: var(--unit-aircraft-vvi-width); +} + +.unit-hotgroup { + align-content: center; + background-color: var(--background-steel); + border-radius: var(--border-radius-xs); + display: none; + height: 15px; + justify-content: center; + position: absolute; + transform: rotate(-45deg); + translate: 0 -200%; + width: 15px; +} + +.unit-hotgroup-id { + background-color: transparent; + color: white; + font-size: 9px; + font-weight: bolder; + transform: rotate(45deg); + translate: -1px 1px; +} + +.unit-icon { + height: var(--unit-height); + position: absolute; + transform-origin: center; + width: var(--unit-width); +} + +[data-is-selected] .unit-icon::before { + background-color: var(--unit-spotlight-fill); + border-radius: 50%; + content: ""; + height: 100%; + position: absolute; + width: 100%; + z-index: -1; +} + +/*** Basic colours ***/ +[data-coalition="blue"] .unit-icon svg>*:first-child { + fill: var(--unit-background-blue); +} + +[data-coalition="red"] .unit-icon svg>*:first-child { + fill: var(--unit-background-red); +} + +[data-coalition="neutral"] .unit-icon svg>*:first-child { + fill: var(--unit-background-neutral); +} + +[data-is-selected] .unit-icon svg>*:first-child { + fill: white; +} + +[data-is-highlighted] .unit-icon svg>*:first-child { + stroke: white; +} + +/*** Cursors ***/ +[data-is-dead], +[data-object|="unit-missile"], +[data-object|="unit-bomb"] { + cursor: default; +} + +/*** Labels ***/ +[data-object|="unit"] .unit-short-label { + color: var(--secondary-gunmetal-grey); + font-size: var(--unit-font-size); + font-weight: var(--unit-font-weight); + line-height: normal; + position: absolute; +} + +/*** Fuel indicator ***/ +[data-object|="unit"] .unit-fuel { + background: white; + border: var(--unit-aircraft-fuel-border-width) solid var(--secondary-dark-steel); + border-radius: var(--border-radius-sm); + display: none; + height: var(--unit-aircraft-fuel-height); + position: absolute; + translate: var(--unit-aircraft-fuel-x) var(--unit-aircraft-fuel-y); + width: var(--unit-aircraft-fuel-width); +} + +[data-object|="unit"] .unit-fuel-level { + background-color: var(--secondary-light-grey); + height: 100%; + width: 100%; +} + +/*** Ammo indicator ***/ +[data-object|="unit"] .unit-ammo { + column-gap: var(--unit-aircraft-ammo-spacing); + display: none; + height: fit-content; + position: absolute; + translate: var(--unit-aircraft-ammo-x) var(--unit-aircraft-ammo-y); + width: fit-content; +} + +[data-object|="unit"] .unit-ammo>* { + background-color: white; + border: var(--unit-aircraft-ammo-border-width) solid var(--secondary-dark-steel); + border-radius: 50%; + padding: var(--unit-aircraft-ammo-radius); +} + +/*** Unit summary ***/ +[data-object|="unit"] .unit-summary { + color: white; + column-gap: 6px; + display: flex; + flex-wrap: wrap; + font-size: 11px; + font-weight: bold; + justify-content: right; + line-height: 12px; + pointer-events: none; + position: absolute; + row-gap: 1px; + text-shadow: + -1px -1px 0 #000, + 1px -1px 0 #000, + -1px 1px 0 #000, + 1px 1px 0 #000; + translate: -60px 0; + width: fit-content; +} + +[data-hide-labels] [data-object|="unit"] .unit-summary { + display: none; +} + +[data-object|="unit"] .unit-summary>* { + padding: 1px; +} + +[data-object|="unit"] .unit-summary .unit-callsign { + color: white; + overflow: hidden; + text-align: right; + transform-origin: right; + white-space: nowrap; + width: 80px; +} + +[data-object|="unit"] .unit-summary .unit-callsign:hover { + direction: rtl; + overflow: visible; +} + +/*** Common ***/ +[data-object|="unit"]:hover .unit-ammo, +[data-object|="unit"]:hover .unit-fuel { + display: flex; +} + +@keyframes pulse { + 50% { + opacity: 0; + } +} + +[data-object|="unit"][data-has-low-fuel] .unit-fuel { + animation: pulse 1.5s linear infinite; +} + +[data-object|="unit"][data-is-in-hotgroup] .unit-hotgroup, +[data-object|="unit"][data-is-selected] .unit-ammo, +[data-object|="unit"][data-is-selected] .unit-fuel, +[data-object|="unit"][data-is-selected] .unit-selected-spotlight { + display: flex; +} + +[data-object|="unit"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { + background-color: var(--secondary-gunmetal-grey); +} + +[data-object|="unit"][data-coalition="blue"][data-is-selected] .unit-short-label { + color: var(--secondary-blue-text); +} + +[data-object|="unit"][data-coalition="blue"] .unit-fuel-level, +[data-object|="unit"][data-coalition="blue"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-coalition="blue"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-coalition="blue"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-coalition="blue"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { + background-color: var(--primary-blue); +} + +[data-object|="unit"][data-coalition="blue"] .unit-vvi { + background-color: var(--secondary-blue-outline); +} + +[data-object|="unit"][data-coalition="red"][data-is-selected] .unit-short-label { + color: var(--secondary-red-text); +} + +[data-object|="unit"][data-coalition="red"] .unit-fuel-level, +[data-object|="unit"][data-coalition="red"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-coalition="red"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-coalition="red"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-coalition="red"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { + background-color: var(--primary-red); +} + +[data-object|="unit"][data-coalition="blue"] .unit-vvi { + background-color: var(--secondary-red-outline); +} + +/*** Unit state ***/ +[data-object|="unit"] .unit-state { + background-repeat: no-repeat; + height: 20px; + position: absolute; + width: 20px; + left: 0px; + top: 0px; +} + +[data-object|="unit"][data-state="rtb"] .unit-state { + background-image: url("/resources/theme/images/states/rtb.svg"); +} + +[data-object|="unit"][data-state="land"] .unit-state { + background-image: url("/resources/theme/images/states/rtb.svg"); +} + +[data-object|="unit"][data-state="idle"] .unit-state { + background-image: url("/resources/theme/images/states/idle.svg"); +} + +[data-object|="unit"][data-state="attack"] .unit-state { + background-image: url("/resources/theme/images/states/attack.svg"); +} + +[data-object|="unit"][data-state="follow"] .unit-state { + background-image: url("/resources/theme/images/states/follow.svg"); +} + +[data-object|="unit"][data-state="refuel"] .unit-state { + background-image: url("/resources/theme/images/states/refuel.svg"); +} + +[data-object|="unit"][data-state="human"] .unit-state { + background-image: url("/resources/theme/images/states/human.svg"); +} + +[data-object|="unit"][data-state="dcs"] .unit-state { + background-image: url("/resources/theme/images/states/dcs.svg"); +} + +/*** Dead unit ***/ +[data-object|="unit-aircraft"][data-is-dead] .unit-selected-spotlight, +[data-object|="unit-aircraft"][data-is-dead] .unit-short-label, +[data-object|="unit-aircraft"][data-is-dead] .unit-vvi, +[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup, +[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup-id, +[data-object|="unit-aircraft"][data-is-dead] .unit-state, +[data-object|="unit-aircraft"][data-is-dead] .unit-fuel, +[data-object|="unit-aircraft"][data-is-dead] .unit-ammo, +[data-object|="unit-aircraft"][data-is-dead]:hover .unit-fuel, +[data-object|="unit-aircraft"][data-is-dead]:hover .unit-ammo { + display: none; +} + +[data-object|="unit-aircraft"][data-is-dead] .unit-summary>* { + display: none; +} + +[data-object|="unit-aircraft"][data-is-dead] .unit-summary .unit-callsign { + display: block; +} \ No newline at end of file diff --git a/client/public/stylesheets/mouseinfopanel.css b/client/public/stylesheets/mouseinfopanel.css deleted file mode 100644 index fe8030a3..00000000 --- a/client/public/stylesheets/mouseinfopanel.css +++ /dev/null @@ -1,91 +0,0 @@ -#mouse-info-panel { - bottom: 60px; - display:flex; - flex-direction: column; - height: fit-content; - position: absolute; - right: 10px; - row-gap: 10px; - width: 160px; - z-index: 1000; -} - - -#mouse-info-panel > * { - background-color: var( --background-grey ); - border-radius: var( --border-radius-sm ); - padding:6px; -} - - -#mouse-info-panel dl { - margin-bottom:4px; - row-gap: 8px; -} - -#mouse-info-panel dt { - height:20px; - width:30%; -} - -#mouse-info-panel dt::after { - align-items: center; - background-color: white; - border-radius: var( --border-radius-sm ); - color: var( --background-steel ); - display:flex; - font-size:15.6px; - font-weight: bolder; - height:16px; - justify-content: center; - line-height: 16px; - padding:4px; - text-transform: uppercase; - width:16px; -} - -#mouse-info-panel dt#ref-unit-position::after { - background-image: url( "/images/icons/ruler.svg" ); - background-position: 50% 50%; - background-repeat: no-repeat; - background-size:16px 16px; - content: ""; -} - -#mouse-info-panel dt#ref-measure-position::after { - background-image: url( "/images/pin.png" ); - background-position: 50% 50%; - background-repeat: no-repeat; - background-size:16px 16px; - content: ""; -} - - -#mouse-info-panel dt[data-label]::after { - content: attr( data-label ); -} - -#mouse-info-panel dt[data-coalition="blue"]::after { - background-color: var( --primary-blue ); -} - -#mouse-info-panel dt[data-coalition="red"]::after { - background-color: var( --primary-red ); -} - - -#mouse-info-panel dt[data-tooltip]:hover::before { - background-color: var( --background-grey ); - border-radius: 5px; - content: attr( data-tooltip ); - display:flex; - flex-wrap: nowrap; - padding: 5px; - position: absolute; - translate: calc( -100% - 15px ) 0; - white-space: nowrap; -} - -#mouse-info-panel dd { - width:70%; -} \ No newline at end of file diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index a0cd6fc7..2bce5980 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -1,14 +1,16 @@ -@import url("layout.css"); -@import url("airbase.css"); -@import url("atc.css"); -@import url("connectionstatuspanel.css"); -@import url("contextmenus.css"); -@import url("mouseinfopanel.css"); -@import url("units.css"); -@import url("unitdatatable.css"); -@import url("unitcontrolpanel.css"); -@import url("unitinfopanel.css"); -@import url("popup.css"); +@import url("layout/layout.css"); +@import url("atc/atc.css"); +@import url("atc/unitdatatable.css"); +@import url("aic/aic.css"); +@import url("panels/connectionstatus.css"); +@import url("panels/mouseinfo.css"); +@import url("panels/unitcontrol.css"); +@import url("panels/unitinfo.css"); +@import url("other/contextmenus.css"); +@import url("other/popup.css"); +@import url("markers/airbase.css"); +@import url("markers/bullseye.css"); +@import url("markers/units.css"); * { -moz-box-sizing: border-box; @@ -87,8 +89,8 @@ form>div { .ol-scrollable::-webkit-scrollbar-track { background-color: transparent; - border-top-right-radius: 10px; border-bottom-right-radius: 10px; + border-top-right-radius: 10px; margin-top: 0px; } @@ -103,8 +105,8 @@ form>div { .ol-scrollable::-webkit-scrollbar-thumb { background-color: white; border-radius: 100px; - opacity: 0.8; margin-top: 10px; + opacity: 0.8; } .ol-panel { @@ -136,15 +138,15 @@ form>div { .ol-ellipsed { display: inline-block; - width: calc(100%); overflow: hidden; - text-overflow: ellipsis; text-align: left; + text-overflow: ellipsis; + width: calc(100%); } .ol-select { - position: relative; color: var(--nav-text); + position: relative; } .ol-select>.ol-select-value { @@ -153,23 +155,23 @@ form>div { cursor: pointer; display: flex; justify-content: left; + min-width: 0; text-align: center; white-space: nowrap; width: 100%; - min-width: 0; } .ol-select:not(.ol-select-image)>.ol-select-value { align-items: center; background-color: var(--background-grey); border-radius: var(--border-radius-sm); - height: 32px; - padding-right: 30px; - padding-left: 20px; - - width: calc(100%); + height: 40px; overflow: hidden; + padding-left: 20px; + padding-right: 30px; text-overflow: ellipsis; + + width: calc(100%); } .ol-select.narrow:not(.ol-select-image)>.ol-select-value { @@ -182,22 +184,22 @@ form>div { } .ol-select:not(.ol-select-image)>.ol-select-value:after { + content: url("/resources/theme/images/icons/chevron-down.svg"); position: absolute; - content: url("/themes/olympus/images/chevron-down.svg"); right: 10px; } .ol-select>.ol-select-options { border-radius: var(--border-radius-md); + max-height: 0; overflow: hidden; position: absolute; - max-height: 0; z-index: 1000; } .ol-select-options.scrollbar-visible { - border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; + border-top-right-radius: 0px !important; } .ol-select.ol-select-image>.ol-select-options { @@ -206,11 +208,11 @@ form>div { .ol-select.is-open>.ol-select-options { max-height: 382px; + min-width: 100%; overflow: visible; overflow-y: auto; - min-width: 100%; - z-index: 9999; translate: 0px 5px; + z-index: 9999; } .ol-select.is-open[data-position="top"]>.ol-select-options { @@ -223,7 +225,7 @@ form>div { box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); display: flex; justify-content: left; - padding: 2px 10px; + padding: 2px 15px; width: 100%; } @@ -246,16 +248,17 @@ form>div { background-color: transparent; border: none; border-radius: 0; + border-radius: var(--border-radius-sm); color: white; display: block; - font-size: 12px; + font-size: 13px; font-weight: normal; + height: 32px; padding: 6px 2px; + padding: 5px; text-align: left; white-space: nowrap; width: 100%; - padding: 5px; - border-radius: var(--border-radius-sm); } .ol-select>.ol-select-options>div a:hover, @@ -367,13 +370,13 @@ nav.ol-panel> :last-child { } .ol-panel .ol-group { + align-items: center; border-radius: var(--border-radius-sm); column-gap: 10px; display: flex; flex-direction: row; flex-wrap: nowrap; row-gap: 4px; - align-items: center; } .ol-group-header { @@ -404,7 +407,7 @@ nav.ol-panel> :last-child { } .ol-panel .ol-group-button-toggle button::before { - background-image: url("/images/icons/square-check-solid.svg"); + background-image: url("/resources/theme/images/icons/square-check-solid.svg"); background-repeat: no-repeat; content: ""; filter: invert(100%); @@ -414,7 +417,7 @@ nav.ol-panel> :last-child { } .ol-panel .ol-group-button-toggle button.off::before { - background-image: url("/images/icons/square-regular.svg"); + background-image: url("/resources/theme/images/icons/square-regular.svg"); } .highlight-primary { @@ -469,9 +472,9 @@ nav.ol-panel> :last-child { } .icon-small { - width: 20px; - padding: 2px; filter: invert(100%); + padding: 2px; + width: 20px; } .ol-data-grid { @@ -484,17 +487,17 @@ nav.ol-panel> :last-child { } .slider { - width: 100%; -webkit-appearance: none; appearance: none; - height: 2px; background: #d3d3d3; - outline: none; + height: 2px; + margin-bottom: 10px; + margin-top: 10px; opacity: 0.7; + outline: none; -webkit-transition: .2s; transition: opacity .2s; - margin-top: 10px; - margin-bottom: 10px; + width: 100%; } .slider:hover { @@ -504,11 +507,11 @@ nav.ol-panel> :last-child { .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; - width: 20px; - height: 20px; background: gray; - cursor: pointer; border-radius: 999px; + cursor: pointer; + height: 20px; + width: 20px; } .active .slider::-webkit-slider-thumb { @@ -516,11 +519,11 @@ nav.ol-panel> :last-child { } .slider::-moz-range-thumb { - width: 20px; - height: 20px; background: gray; - cursor: pointer; border-radius: 999px; + cursor: pointer; + height: 20px; + width: 20px; } .active .slider::-moz-range-thumb { @@ -528,25 +531,25 @@ nav.ol-panel> :last-child { } .main-logo { - width: 40px; height: 40px; + width: 40px; } .ol-measure-box { - position: absolute; + background-color: var(--background-steel); + border-radius: 999px; + color: var(--primary-neutral); + font-size: 12px; + font-weight: var(--font-weight-bolder); + height: fit-content; + padding-bottom: 0.2em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; - padding-bottom: 0.2em; - background-color: var(--background-steel); - border-radius: 999px; - width: fit-content; - height: fit-content; + position: absolute; text-align: center; - color: var(--primary-neutral); - font-size: 12px; + width: fit-content; z-index: 2000; - font-weight: var(--font-weight-bolder); } .ol-sortable .handle { @@ -574,7 +577,7 @@ nav.ol-panel> :last-child { width: 28px; } -#unit-selection #unit-identification [data-object|="unit"] .unit-marker { +#unit-selection #unit-identification [data-object|="unit"] .unit-icon { background-size: 28px 28px; height: 28px; width: 28px; @@ -587,47 +590,34 @@ nav.ol-panel> :last-child { #unit-visibility-control button { border: none; height: 32px; + padding: 0px; width: 32px; } -#unit-visibility-control-aircraft { - background-image: var(--visibility-control-aircraft-visible-url); +#unit-visibility-control button svg { + height: 16px; + pointer-events: none; + width: 16px; } -body[data-hide-aircraft] #unit-visibility-control-aircraft { - background-image: var(--visibility-control-aircraft-hidden-url); +#unit-visibility-control button { + background-color: white; + border: 1px solid transparent; } -#unit-visibility-control-groundunit { - background-image: var(--visibility-control-groundunit-visible-url); +#unit-visibility-control button.off { + background-color: transparent; + border: 1px solid white; } -body[data-hide-groundunit] #unit-visibility-control-groundunit { - background-image: var(--visibility-control-groundunit-hidden-url); +#unit-visibility-control button.off svg * { + fill: white !important; + stroke: white !important; } -#unit-visibility-control-sam { - background-image: var(--visibility-control-sam-visible-url); -} - -body[data-hide-sam] #unit-visibility-control-sam { - background-image: var(--visibility-control-sam-hidden-url); -} - -#unit-visibility-control-threat { - background-image: var(--visibility-control-threat-visible-url); -} - -body[data-hide-threat] #unit-visibility-control-threat { - background-image: var(--visibility-control-threat-hidden-url); -} - -#unit-visibility-control-navyunit { - background-image: var(--visibility-control-navyunit-visible-url); -} - -body[data-hide-navyunit] #unit-visibility-control-navyunit { - background-image: var(--visibility-control-navyunit-hidden-url); +#unit-visibility-control button svg * { + fill: var(--background-steel) !important; + stroke: var(--background-steel) !important; } #atc-navbar-control { @@ -642,130 +632,30 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { padding: 4px; } -#roe-buttons-container button { +#roe-buttons-container button, +#reaction-to-threat-buttons-container button, +#emissions-countermeasures-buttons-container button { + align-items: center; background-color: transparent; border: 1px solid var(--accent-light-blue); + display: flex; + height: 30px; + justify-content: center; + width: 30px; } -#roe-buttons-container button.selected, -#reaction-to-threat-buttons-container button.selected, -#emissions-countermeasures-buttons-container button.selected { +#unit-control-panel .ol-option-button button.selected { background-color: white; border-color: white; } -#roe-buttons-container button::before, -#reaction-to-threat-buttons-container button::before, -#emissions-countermeasures-buttons-container button::before { - background-position: center; - background-repeat: no-repeat; - content: ""; - display: block; - height: 24px; - width: 24px; -} - -#roe-buttons-container button[value="Hold"]::before { - background-image: url("/themes/olympus/images/icons_roe_stop_light.svg"); -} - -#roe-buttons-container button[value="Hold"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_stop_dark.svg"); -} - -/**/ -#roe-buttons-container button[value="Return"]::before { - background-image: url("/themes/olympus/images/icons_roe_defend_light.svg"); -} - -#roe-buttons-container button[value="Return"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_defend_dark.svg"); -} - -/**/ -#roe-buttons-container button[value="Designated"]::before { - background-image: url("/themes/olympus/images/icons_roe_target_light.svg"); -} - -#roe-buttons-container button[value="Designated"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_target_dark.svg"); -} - -/**/ -#roe-buttons-container button[value="Free"]::before { - background-image: url("/themes/olympus/images/icons_roe_free_light.svg"); -} - -#roe-buttons-container button[value="Free"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_free_dark.svg"); -} - -/****************************************************************************************/ -#reaction-to-threat-buttons-container button[value="None"]::before { - background-image: url("/themes/olympus/images/icons_threat_nothing_light.svg"); -} - -#reaction-to-threat-buttons-container button[value="None"].selected::before { - background-image: url("/themes/olympus/images/icons_threat_nothing_dark.svg"); -} - -/**/ -#reaction-to-threat-buttons-container button[value="Passive"]::before { - background-image: url("/themes/olympus/images/icons_threat_cms_light.svg"); -} - -#reaction-to-threat-buttons-container button[value="Passive"].selected::before { - background-image: url("/themes/olympus/images/icons_threat_cms_dark.svg"); -} - -/**/ -#reaction-to-threat-buttons-container button[value="Evade"]::before { - background-image: url("/themes/olympus/images/icons_threat_defend_light.svg"); -} - -#reaction-to-threat-buttons-container button[value="Evade"].selected::before { - background-image: url("/themes/olympus/images/icons_threat_defend_dark.svg"); -} - -/****************************************************************************************/ -#emissions-countermeasures-buttons-container button[value="Silent"]::before { - background-image: url("/themes/olympus/images/icons_roe_stop_light.svg"); -} - -#emissions-countermeasures-buttons-container button[value="Silent"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_stop_dark.svg"); -} - -/**/ -#emissions-countermeasures-buttons-container button[value="Defend"]::before { - background-image: url("/themes/olympus/images/icons_roe_defend_light.svg"); -} - -#emissions-countermeasures-buttons-container button[value="Defend"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_defend_dark.svg"); -} - -/**/ -#emissions-countermeasures-buttons-container button[value="Attack"]::before { - background-image: url("/themes/olympus/images/icons_roe_target_light.svg"); -} - -#emissions-countermeasures-buttons-container button[value="Attack"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_target_dark.svg"); -} - -/**/ -#emissions-countermeasures-buttons-container button[value="Free"]::before { - background-image: url("/themes/olympus/images/icons_roe_free_light.svg"); -} - -#emissions-countermeasures-buttons-container button[value="Free"].selected::before { - background-image: url("/themes/olympus/images/icons_roe_free_dark.svg"); +#unit-control-panel .ol-option-button button.selected svg * { + fill: var(--background-steel); } /****************************************************************************************/ #splash-screen { - background-image: url("/images/splash/splash_pic_ship.png"); + background-image: url("/resources/theme/images/splash/1.png"); background-position: 100% 50%; background-size: 60%; border-radius: var(--border-radius-lg); @@ -815,9 +705,9 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { #splash-content #app-summary>* { height: fit-content; line-height: 25px; + padding: 2px; white-space: nowrap; width: fit-content; - padding: 2px; } #splash-content .app-version { @@ -829,8 +719,8 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { } #splash-content #legal-stuff p { + color: #FFF7; font-size: 10px; - color:#FFF7; width: 120%; } @@ -843,34 +733,34 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { } #gray-out { - position: fixed; - height: 100%; - width: 100%; - left: 0px; - top: 0px; - z-index: 9999; background-color: #000A; + height: 100%; + left: 0px; + position: fixed; + top: 0px; + width: 100%; + z-index: 9999; } #authentication-form { - display: flex; align-items: end; column-gap: 10px; - margin: 10px 0px; + display: flex; flex-direction: row; + margin: 10px 0px; } #authentication-form>div { - display: flex; align-items: start; - row-gap: 4px; + display: flex; flex-direction: column; + row-gap: 4px; } #authentication-form>div>input { - height: 35px; - border-radius: var(--border-radius-sm); border: 0px solid transparent; + border-radius: var(--border-radius-sm); + height: 35px; width: 200px; } @@ -884,13 +774,13 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { } #connection-status[data-status="connecting"]::before { - content: "Connecting..."; animation: blinker 1s linear infinite; + content: "Connecting..."; } #connection-status[data-status="failed"]::before { - content: "Incorrect username/password!"; color: var(--primary-red); + content: "Incorrect username/password!"; } @keyframes blinker { @@ -900,34 +790,263 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { } #hotgroup-panel { - position: absolute; bottom: 40px; + column-gap: 10px; + display: flex; left: 50%; + position: absolute; translate: -50%; z-index: 9999; - display: flex; - column-gap: 10px; } #hotgroup-panel>div { - width: 50px; - height: 50px; + align-items: center; background-color: var(--background-steel); + border: 0px solid transparent; border-radius: var(--border-radius-sm); color: white; display: flex; - align-items: center; - justify-content: center; font-weight: bold; - border: 0px solid transparent; + height: 50px; + justify-content: center; + width: 50px; } #hotgroup-panel>div:hover { - cursor: pointer; border: 2px solid white; + cursor: pointer; } .hotgroup-selector>.unit-hotgroup { display: flex; translate: 0% -300%; +} + +.ol-destination-preview-icon { + background-color: var(--secondary-yellow); + border-radius: 999px; + height: 52px; + pointer-events: none; + width: 52px; +} + +.ol-destination-preview { + pointer-events: none; +} + +dl.ol-data-grid { + align-items: center; + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 0; + row-gap: 4px; +} + +dl.ol-data-grid dt { + width: 60%; +} + +dl.ol-data-grid dd { + width: 40%; +} + +dl.ol-data-grid dt.icon { + text-indent: 10px; +} + +dl.ol-data-grid dt.icon::before { + content: url("/resources/theme/images/icons/speed.svg"); + display: inline-block; + filter: invert(100%); + translate: -20px 2px; + width: 20px; +} + +dl.ol-data-grid dt.icon-speed::before { + content: url("/images/icons/speed.svg"); +} + +dl.ol-data-grid dt.icon-altitude::before { + content: url("/images/icons/altitude.svg"); +} + +dl.ol-data-grid dd { + display: flex; + justify-content: flex-end; + margin-left: auto; +} + +.br-info::after { + content: attr(data-bearing) '\00B0 / ' attr(data-distance) attr(data-distance-units); +} + +.br-info[data-message]::after { + content: attr(data-message); +} + +.coordinates::after { + content: attr(data-dd) "\00b0 " attr(data-mm) "'" attr(data-ss) "." attr(data-sss) '"' attr(data-label); +} + +.ol-button-box { + column-gap: 6px; + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 5px 0; + row-gap: 5px; +} + +.ol-button-box button { + background-repeat: no-repeat; + ; + border: 1px solid var(--accent-light-blue); + color: var(--accent-light-blue); +} + +.ol-dialog { + align-self: center; + background-color: var(--background-slate-blue); + color: white; + justify-self: center; + position: absolute; + z-index: 1000; +} + +.ol-panel.ol-dialog { + padding: 24px 30px; +} + +.ol-dialog-close { + cursor: pointer; + font-size: 16px; + font-weight: var(--font-weight-bolder); + position: absolute; + right: 20px; + top: 10px; +} + +.ol-dialog-close::before { + content: "\d7"; +} + +.ol-dialog-header { + border-bottom: 1px solid var(--background-grey); + padding-bottom: 10px; +} + +.ol-dialog-content { + margin: 4px 0; +} + +.ol-dialog-footer { + border-top: 1px solid var(--background-grey); + display: flex; + padding-top: 15px; + row-gap: 10px; +} + +.ol-dialog.scrollable .ol-dialog-content { + overflow-y: auto; +} + +.ol-checkbox label { + align-items: center; + cursor: pointer; + display: flex; + flex-wrap: nowrap; + white-space: nowrap; +} + +.ol-checkbox input[type="checkbox"] { + appearance: none; + background-color: transparent; + border: none; + margin: 0; +} + +.ol-checkbox input[type="checkbox"]::before { + align-self: center; + background-image: url("/resources/theme/images/icons/square-regular.svg"); + background-repeat: no-repeat; + content: ""; + display: flex; + filter: invert(100%); + height: 16px; + margin-right: 10px; + width: 16px; +} + +.ol-checkbox input[type="checkbox"]:checked::before { + background-image: url("/resources/theme/images/icons/square-check-solid.svg"); +} + +.ol-text-input input { + background-color: var(--background-grey); + border: 1px solid var(--background-grey); + border-radius: 5px; + border-radius: var(--border-radius-sm); + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + color: var(--background-offwhite); + height: 32px; + text-align: center; +} + +input[type=number] { + -moz-appearance: textfield; + appearance: textfield; + margin: 0; +} + +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +[class|="ol-button"] { + align-items: center; + background-repeat: no-repeat; + display: flex; + font-weight: normal; + padding: 8px 10px; + white-space: nowrap; +} + +[class|="ol-button"]::before { + margin-right: 8px; +} + +.ol-button-close { + background: transparent; + border: 1px solid white; +} + +.ol-button-close::before { + content: "\d7"; +} + +.ol-button-apply { + background: transparent; + border: 1px solid white; +} + +.ol-button-apply::before { + content: "\2713"; +} + +.ol-button-settings { + background-color: var(--background-slate-blue); +} + +.ol-button-settings::before { + background-image: url("/resources/theme/images/icons/gears-solid.svg"); + background-position: 0 50%; + background-size: 24px 24px; + content: ""; + display: flex; + filter: invert(100%); + height: 24px; + width: 24px; } \ No newline at end of file diff --git a/client/public/stylesheets/contextmenus.css b/client/public/stylesheets/other/contextmenus.css similarity index 68% rename from client/public/stylesheets/contextmenus.css rename to client/public/stylesheets/other/contextmenus.css index 573bba4b..9e325678 100644 --- a/client/public/stylesheets/contextmenus.css +++ b/client/public/stylesheets/other/contextmenus.css @@ -17,23 +17,23 @@ } #active-coalition-label { - position: absolute; - top: -28px; border-radius: 999px; - width: fit-content; + color: var(--nav-text); + font-size: 12px; + font-weight: 600; height: fit-content; padding: 3px 10px; padding-bottom: 3px; - font-weight: 600; - color: var(--nav-text); - font-size: 12px; + position: absolute; + top: -28px; + width: fit-content; } #context-menu-switch { margin-right: 10px; } -#map-contextmenu>div:nth-child(2){ +#map-contextmenu>div:nth-child(2) { align-items: center; display: flex; flex-direction: row; @@ -41,22 +41,22 @@ padding-right: 0px; } -#map-contextmenu>ul{ +#map-contextmenu>ul { max-height: 200px; overflow-x: hidden; overflow-y: auto; } #map-contextmenu .ol-panel { - width: 100%; border-radius: var(--border-radius-sm); + width: 100%; } #map-contextmenu ul { margin: 0px; } -#map-contextmenu>div:nth-child(n+3){ +#map-contextmenu>div:nth-child(n+3) { align-items: center; display: flex; flex-direction: column; @@ -64,10 +64,10 @@ row-gap: 5px; } -#map-contextmenu .ol-select-container{ - width: 100%; - flex:0 0 auto; +#map-contextmenu .ol-select-container { align-self: stretch; + flex: 0 0 auto; + width: 100%; } #aircraft-spawn-menu .ol-select.is-open .ol-select-options { @@ -76,28 +76,28 @@ #aircraft-spawn-menu>button, #ground-unit-spawn-menu>button { - width: 100%; text-align: center; + width: 100%; } #aircraft-spawn-button { - background-image: var( --spawn-aircraft-url ); + background-image: url("/resources/theme/images/buttons/spawn/aircraft.svg"); background-size: 48px; } #ground-unit-spawn-button { - background-image: var( --spawn-groundunit-url ); + background-image: url("/resources/theme/images/buttons/spawn/ground.svg"); background-size: 48px; } #smoke-spawn-button { - background-image: var( --spawn-smoke-url ); + background-image: url("/resources/theme/images/buttons/spawn/smoke.svg"); background-size: 48px; } .unit-spawn-button { - border-radius: 0px; border: none; + border-radius: 0px; height: 48px; margin-bottom: -10px; margin-top: -10px; @@ -105,37 +105,34 @@ } .unit-spawn-button:last-of-type { - border-top-right-radius: var(--border-radius-sm); border-bottom-right-radius: var(--border-radius-sm); + border-top-right-radius: var(--border-radius-sm); } [data-active-coalition="blue"].toggle-fill, -[data-active-coalition="blue"].unit-spawn-button:hover, -[data-active-coalition="blue"].unit-spawn-button.is-open, +[data-active-coalition="blue"].unit-spawn-button:hover, +[data-active-coalition="blue"].unit-spawn-button.is-open, [data-active-coalition="blue"]#active-coalition-label, [data-active-coalition="blue"].deploy-unit-button, -[data-active-coalition="blue"]#spawn-airbase-aircraft-button -{ +[data-active-coalition="blue"]#spawn-airbase-aircraft-button { background-color: var(--primary-blue) } [data-active-coalition="red"].toggle-fill, -[data-active-coalition="red"].unit-spawn-button:hover, -[data-active-coalition="red"].unit-spawn-button.is-open, +[data-active-coalition="red"].unit-spawn-button:hover, +[data-active-coalition="red"].unit-spawn-button.is-open, [data-active-coalition="red"]#active-coalition-label, [data-active-coalition="red"].deploy-unit-button, -[data-active-coalition="red"]#spawn-airbase-aircraft-button -{ +[data-active-coalition="red"]#spawn-airbase-aircraft-button { background-color: var(--primary-red) } [data-active-coalition="neutral"].toggle-fill, -[data-active-coalition="neutral"].unit-spawn-button:hover, -[data-active-coalition="neutral"].unit-spawn-button.is-open, +[data-active-coalition="neutral"].unit-spawn-button:hover, +[data-active-coalition="neutral"].unit-spawn-button.is-open, [data-active-coalition="neutral"]#active-coalition-label, [data-active-coalition="neutral"].deploy-unit-button, -[data-active-coalition="neutral"]#spawn-airbase-aircraft-button -{ +[data-active-coalition="neutral"]#spawn-airbase-aircraft-button { background-color: var(--primary-neutral) } @@ -144,11 +141,13 @@ border: 1px solid var(--primary-blue); cursor: default; } + [data-active-coalition="red"].deploy-unit-button:disabled { background-color: transparent; border: 1px solid var(--primary-red); cursor: default; } + [data-active-coalition="neutral"].deploy-unit-button:disabled { background-color: transparent; border: 1px solid var(--primary-neutral); @@ -158,9 +157,11 @@ [data-active-coalition="blue"].toggle-fill::after { transform: translateX(0); } + [data-active-coalition="red"].toggle-fill::after { transform: translateX(var(--height)); } + [data-active-coalition="neutral"].toggle-fill::after { transform: translateX(calc(var(--height) / 2)); } @@ -168,182 +169,203 @@ [data-active-coalition="blue"]#active-coalition-label::after { content: "Create blue unit"; } + [data-active-coalition="red"]#active-coalition-label::after { content: "Create red unit"; } + [data-active-coalition="neutral"]#active-coalition-label::after { content: "Create neutral unit"; } #loadout-preview { - display: flex; - flex-direction: row; align-content: space-between; align-items: center; - width: 100%; column-gap: 20px; + display: flex; + flex-direction: row; + width: 100%; } #loadout-list { + align-content: center; display: flex; flex-direction: column; - align-content: center; height: 100%; } #unit-image { - width: 100px; - height: 100px; filter: invert(100%); - margin-top: 10px; + height: 100px; margin-bottom: 10px; + margin-top: 10px; + width: 100px; } #smoke-spawn-menu { + align-items: center; display: flex; flex-direction: column; - align-items: center; text-align: center; } #smoke-spawn-menu>button { - width: 100%; - text-align: left; - display: flex; - flex-wrap: wrap; align-items: center; column-gap: 10px; + display: flex; + flex-wrap: wrap; + text-align: left; + width: 100%; } #smoke-spawn-menu>button::before { - display: block; - width: 10px; - height: 10px; border-radius: 999px; content: ""; + display: block; + height: 10px; + width: 10px; } -[data-smoke-color="red"]::before{ background-color: red; } -[data-smoke-color="white"]::before{ background-color: white; } -[data-smoke-color="blue"]::before{ background-color: blue; } -[data-smoke-color="green"]::before{ background-color: green; } -[data-smoke-color="orange"]::before{ background-color: orange; } +[data-smoke-color="red"]::before { + background-color: red; +} + +[data-smoke-color="white"]::before { + background-color: white; +} + +[data-smoke-color="blue"]::before { + background-color: blue; +} + +[data-smoke-color="green"]::before { + background-color: green; +} + +[data-smoke-color="orange"]::before { + background-color: orange; +} /* Unit context menu */ #unit-contextmenu { display: flex; flex-direction: column; height: fit-content; - width: fit-content; + padding: 15px; position: absolute; row-gap: 5px; + width: fit-content; z-index: 1000; - padding: 15px; } #unit-contextmenu button { border: 1px solid var(--background-offwhite); border-radius: var(--border-radius-sm); - padding: 12px; font-weight: normal; + padding: 12px; } #unit-contextmenu div { + align-content: center; display: flex; flex-direction: row; - align-content: center; } #unit-contextmenu div:before { - display: inline-block; - filter: invert(100%); - height: 16px; - margin-right: 15px; - width: 16px; + display: inline-block; + filter: invert(100%); + height: 16px; + margin-right: 15px; + width: 16px; } #center-map::before { - content: url( /images/icons/arrows-to-eye-solid.svg ); + content: url("/resources/theme/images/icons/arrows-to-eye-solid.svg"); } #refuel::before { - content: url( /images/icons/fuel.svg ); + content: url("/resources/theme/images/icons/fuel.svg"); } #attack::before { - content: url( /images/icons/sword.svg ); + content: url("/resources/theme/images/icons/sword.svg"); } #follow::before { - content: url( /images/icons/follow.svg ); + content: url("/resources/theme/images/icons/follow.svg"); } #trail::before { - content: url( /images/icons/trail.svg ); + content: url("/resources/theme/images/icons/trail.svg"); } #echelon-lh::before { - content: url( /images/icons/echelon-lh.svg ); + content: url("/resources/theme/images/icons/echelon-lh.svg"); } #echelon-rh::before { - content: url( /images/icons/echelon-rh.svg ); + content: url("/resources/theme/images/icons/echelon-rh.svg"); } -#line-abreast::before { - content: url( /images/icons/line-abreast.svg ); +#line-abreast-rh::before, +#line-abreast-lh::before { + content: url("/resources/theme/images/icons/line-abreast.svg"); } #front::before { - content: url( /images/icons/front.svg ); + content: url("/resources/theme/images/icons/front.svg"); +} + +#diamond::before { + content: url("/resources/theme/images/icons/diamond.svg"); } #custom::before { - content: url( /images/icons/custom.svg ); + content: url("/resources/theme/images/icons/custom.svg"); } #custom-formation-dialog { - width: 250px; + width: 250px; } -#custom-formation-dialog > .ol-dialog-content { - margin-top: 10px; - margin-bottom: 10px; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - row-gap: 10px; +#custom-formation-dialog>.ol-dialog-content { align-items: center; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + margin-bottom: 10px; + margin-top: 10px; + row-gap: 10px; } -#custom-formation-dialog > .ol-dialog-content > .ol-group { +#custom-formation-dialog>.ol-dialog-content>.ol-group { + justify-content: space-between; width: 100%; - justify-content: space-between; } #reference-system { - content: url( /images/reference-system.svg ); + content: url("/images/reference-system.svg"); display: inline-block; - filter: invert(100%); - width: 50px; - transform: translate(-50%, -50%); + filter: invert(100%); position: absolute; + transform: translate(-50%, -50%); + width: 50px; } .formation-position-clock { - position: relative; height: 100px; - width: 100px; margin: 15px; + position: relative; + width: 100px; } -.formation-position-clock > .clock-hand { - transform: translate(-50%, -50%); - display: flex; - position: absolute; - align-items: center; - justify-content: center; - height: 20px; +.formation-position-clock>.clock-hand { + align-items: center; + display: flex; + height: 20px; + justify-content: center; + position: absolute; + transform: translate(-50%, -50%); width: 20px; } @@ -362,9 +384,9 @@ --width: 40px; --height: calc(var(--width) / 2); --border-radius: calc(var(--height) / 2); + cursor: pointer; display: inline-block; - cursor: pointer; } .toggle-input { @@ -372,23 +394,22 @@ } .toggle-fill { - position: relative; - width: var(--width); - height: var(--height); border-radius: var(--border-radius); + height: var(--height); + position: relative; transition: background-color 0.2s; + width: var(--width); } .toggle-fill::after { + background-color: #ffffff; + border-radius: var(--border-radius); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.25); content: ""; + height: calc(var(--height) - 4px); + left: 2; position: absolute; top: 2; - left: 2; - height: calc(var(--height) - 4px); - width: calc(var(--height) - 4px); - background-color: #ffffff; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.25); - border-radius: var(--border-radius); transition: transform 0.2s; -} - + width: calc(var(--height) - 4px); +} \ No newline at end of file diff --git a/client/public/stylesheets/popup.css b/client/public/stylesheets/other/popup.css similarity index 50% rename from client/public/stylesheets/popup.css rename to client/public/stylesheets/other/popup.css index fb514460..521e4cde 100644 --- a/client/public/stylesheets/popup.css +++ b/client/public/stylesheets/other/popup.css @@ -1,13 +1,3 @@ -#info-popup { - position: absolute; - width: fit-content; - height: fit-content; - top: 100px; - left: 50%; - translate: -50% 0%; - z-index: 9999; -} - .ol-popup > div { padding-left: 15px; padding-right: 15px; diff --git a/client/public/stylesheets/connectionstatuspanel.css b/client/public/stylesheets/panels/connectionstatus.css similarity index 61% rename from client/public/stylesheets/connectionstatuspanel.css rename to client/public/stylesheets/panels/connectionstatus.css index 362657cf..2b7dcec4 100644 --- a/client/public/stylesheets/connectionstatuspanel.css +++ b/client/public/stylesheets/panels/connectionstatus.css @@ -1,12 +1,3 @@ -#connection-status-panel { - bottom: 20px; - font-size:12px; - position: absolute; - right: 10px; - width: 160px; - z-index: 1000; -} - #connection-status-panel dt::before { content: "No connection"; } @@ -15,15 +6,14 @@ border-radius: 50%; background: red; content: " "; - height:12px; - width:12px; + height: 12px; + width: 12px; } - #connection-status-panel[data-is-connected] dt::before { content: "Connected"; } #connection-status-panel[data-is-connected] dd::after { - background:var( --accent-green ); + background: var(--accent-green); } \ No newline at end of file diff --git a/client/public/stylesheets/panels/mouseinfo.css b/client/public/stylesheets/panels/mouseinfo.css new file mode 100644 index 00000000..1c3d5e2e --- /dev/null +++ b/client/public/stylesheets/panels/mouseinfo.css @@ -0,0 +1,75 @@ +#mouse-info-panel>* { + background-color: var(--background-grey); + border-radius: var(--border-radius-sm); + padding: 6px; +} + +#mouse-info-panel dl { + margin-bottom: 4px; + row-gap: 8px; +} + +#mouse-info-panel dt { + height: 20px; + width: 30%; +} + +#mouse-info-panel dt::after { + align-items: center; + background-color: white; + border-radius: var(--border-radius-sm); + color: var(--background-steel); + display: flex; + font-size: 15.6px; + font-weight: bolder; + height: 16px; + justify-content: center; + line-height: 16px; + padding: 4px; + text-transform: uppercase; + width: 16px; +} + +#mouse-info-panel dt#ref-unit-position::after { + background-image: url("/resources/theme/images/icons/ruler.svg"); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 16px 16px; + content: ""; +} + +#mouse-info-panel dt#ref-measure-position::after { + background-image: url("/resources/theme/images/icons/pin.png"); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 16px 16px; + content: ""; +} + +#mouse-info-panel dt[data-label]::after { + content: attr(data-label); +} + +#mouse-info-panel dt[data-coalition="blue"]::after { + background-color: var(--primary-blue); +} + +#mouse-info-panel dt[data-coalition="red"]::after { + background-color: var(--primary-red); +} + +#mouse-info-panel dt[data-tooltip]:hover::before { + background-color: var(--background-grey); + border-radius: 5px; + content: attr(data-tooltip); + display: flex; + flex-wrap: nowrap; + padding: 5px; + position: absolute; + translate: calc(-100% - 15px) 0; + white-space: nowrap; +} + +#mouse-info-panel dd { + width: 70%; +} \ No newline at end of file diff --git a/client/public/stylesheets/unitcontrolpanel.css b/client/public/stylesheets/panels/unitcontrol.css similarity index 79% rename from client/public/stylesheets/unitcontrolpanel.css rename to client/public/stylesheets/panels/unitcontrol.css index a0f7b507..521ec15f 100644 --- a/client/public/stylesheets/unitcontrolpanel.css +++ b/client/public/stylesheets/panels/unitcontrol.css @@ -2,16 +2,6 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { display: block !important; } - -#unit-control-panel { - height: fit-content; - left: 10px; - position: absolute; - top: 80px; - width: 260px; - z-index: 1000; -} - #unit-control-panel h3 { margin-bottom: 8px; } @@ -21,7 +11,8 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { border-radius: var(--border-radius-md); display: flex; flex-direction: column; - max-height: 136px; + max-height: 215px; + overflow-x: hidden; overflow-y: auto; row-gap: 4px; } @@ -32,21 +23,31 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { display: flex; font-size: 11px; height: 32px; + margin-right: 5px; padding: 8px 0; position: relative; - width: 100%; + width: calc(100% - 5px); } #unit-control-panel #selected-units-container button::before { - background-color: var( --primary-neutral ); + background-color: var(--primary-neutral); border-radius: 999px; content: attr(data-short-label); - margin: 0 5px; - padding: 4px 6px; - white-space: nowrap; - width: 30px; - text-overflow: ellipsis; + font-size: 10px; + margin: 2px 4px; + max-width: 30px; + min-width: 20px; overflow: hidden; + padding: 4px 6px; + text-overflow: ellipsis; + white-space: nowrap; + width: fit-content; +} + +#unit-control-panel #selected-units-container button:hover::before { + background-color: black; + max-width: 100%; + text-overflow: unset; } #unit-control-panel #selected-units-container button[data-coalition="blue"]::before { @@ -71,24 +72,6 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { width: fit-content; } - -#unit-control-panel #selected-units-container button:hover::after { - overflow: visible; - text-overflow: initial; -} - -#unit-control-panel #selected-units-container button:hover::after { - background-color: var(--background-grey); -} - -#unit-control-panel #selected-units-container button[data-coalition="blue"]:hover::after { - background-color: var(--primary-blue); -} - -#unit-control-panel #selected-units-container button[data-coalition="red"]:hover::after { - background-color: var(--primary-red); -} - #unit-control-panel h4 { margin-bottom: 8px; } @@ -127,13 +110,12 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { display: none; } - #advanced-settings-dialog>.ol-dialog-content { - margin-top: 10px; - margin-bottom: 10px; display: flex; flex-direction: column; flex-wrap: nowrap; + margin-bottom: 10px; + margin-top: 10px; row-gap: 10px; } @@ -153,8 +135,8 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #advanced-settings-dialog hr { - margin-top: 15px; margin-bottom: 10px; + margin-top: 15px; } #general-settings-grid { diff --git a/client/public/stylesheets/panels/unitinfo.css b/client/public/stylesheets/panels/unitinfo.css new file mode 100644 index 00000000..8e20e07d --- /dev/null +++ b/client/public/stylesheets/panels/unitinfo.css @@ -0,0 +1,106 @@ +#unit-info-panel #unit-name { + padding: 0px 0; + margin-bottom: 4px; +} + +#unit-info-panel #current-task { + border-radius: var(--border-radius-lg); + margin-top: 8px; + padding: 6px 16px; +} + +#unit-info-panel #current-task::after { + content: attr(data-current-task); + display: block; +} + +#loadout { + display: flex; + overflow: visible; +} + +#loadout-silhouette { + align-items: center; + display: flex; + justify-content: center; + width: 100px; +} + +#loadout-silhouette::before { + background-image: var(--loadout-background-image); + background-repeat: no-repeat; + background-size: 75px 75px; + content: ""; + display: block; + filter: invert(100%); + height: 75px; + translate: -10px 0; + width: 75px; +} + +#loadout-items { + align-self: center; + display: flex; + flex-flow: column nowrap; + row-gap: 8px; +} + + +#loadout-items>* { + align-items: center; + column-gap: 8px; + display: flex; + justify-content: flex-end; + white-space: nowrap; +} + +#loadout-items>*::before { + align-items: center; + background-color: var(--secondary-light-grey); + border-radius: var(--border-radius-sm); + content: attr(data-qty); + display: flex; + font-weight: var(--font-weight-bolder); + padding: 1px 4px; +} + +#loadout-items>*::after { + content: attr(data-item); + overflow: hidden; + position: relative; + text-overflow: ellipsis; + width: 80px; +} + + +#fuel-percentage { + align-items: center; + display: flex; +} + +#fuel-percentage::before { + content: url("/resources/theme/images/icons/fuel.svg"); + display: inline-block; + filter: invert(100%); + height: 16px; + margin-right: 6px; + width: 16px; +} + +#fuel-percentage::after { + content: attr(data-percentage) "%"; +} + + +#fuel-display { + background-color: var(--background-grey); + border-radius: var(--border-radius-md); + height: 6px; + margin-top: 4px; + overflow: hidden; +} + +#fuel-display #fuel-bar { + border-radius: var(--border-radius-md); + height: 100%; +} \ No newline at end of file diff --git a/client/public/stylesheets/uikit.css b/client/public/stylesheets/uikit/uikit.css similarity index 100% rename from client/public/stylesheets/uikit.css rename to client/public/stylesheets/uikit/uikit.css diff --git a/client/public/stylesheets/unitinfopanel.css b/client/public/stylesheets/unitinfopanel.css deleted file mode 100644 index 1fa1e3ee..00000000 --- a/client/public/stylesheets/unitinfopanel.css +++ /dev/null @@ -1,119 +0,0 @@ - -#unit-info-panel { - bottom: 20px; - font-size:12px; - position: absolute; - left: 10px; - width: fit-content; - z-index: 1000; -} - - -#unit-info-panel #unit-name { - padding:0px 0; - margin-bottom:4px; -} - -#unit-info-panel #current-task { - border-radius: var( --border-radius-lg ); - margin-top:8px; - padding:6px 16px; -} - -#unit-info-panel #current-task::after { - content: attr( data-current-task ); - display:block; -} - - -#loadout { - display:flex; - overflow: visible; -} - -#loadout-silhouette { - align-items: center; - display:flex; - justify-content: center; - width:100px; -} - -#loadout-silhouette::before { - background-image: var( --loadout-background-image ); - background-repeat: no-repeat; - background-size:75px 75px; - content:""; - display:block; - filter: invert( 100% ); - height:75px; - translate:-10px 0; - width:75px; -} - -#loadout-items { - align-self: center; - display:flex; - flex-flow: column nowrap; - row-gap: 8px; -} - - -#loadout-items > * { - align-items: center; - column-gap: 8px; - display:flex; - justify-content: flex-end; - white-space: nowrap; -} - -#loadout-items > *::before { - align-items: center; - background-color: var( --secondary-light-grey ); - border-radius: var( --border-radius-sm ); - content: attr( data-qty ); - display:flex; - font-weight: var( --font-weight-bolder ); - padding:1px 4px; -} - -#loadout-items > *::after { - content: attr( data-item ); - overflow: hidden; - position:relative; - text-overflow: ellipsis; - width:80px; -} - - -#fuel-percentage { - align-items: center; - display:flex; -} - -#fuel-percentage::before { - content: url( /images/icons/fuel.svg ); - display:inline-block; - filter:invert(100%); - height:16px; - margin-right:6px; - width:16px; -} - -#fuel-percentage::after { - content: attr( data-percentage ) "%"; -} - - -#fuel-display { - background-color: var( --background-grey ); - border-radius: var( --border-radius-md ); - height:6px; - margin-top:4px; - overflow: hidden; -} - -#fuel-display #fuel-bar { - border-radius: var( --border-radius-md ); - height:100%; -} - diff --git a/client/public/stylesheets/units.css b/client/public/stylesheets/units.css deleted file mode 100644 index b48389d6..00000000 --- a/client/public/stylesheets/units.css +++ /dev/null @@ -1,573 +0,0 @@ -:root { - /* Generic marker settings */ - --unit-centre-x: calc(var(--unit-width) / 2); - --unit-centre-y: calc(var(--unit-height) / 2); - - --unit-hotgroup-height: 15px; - --unit-hotgroup-width: var(--unit-hotgroup-height); - - - /* Air units' marker settings */ - --unit-aircraft-label-x: calc(var(--unit-centre-x) - (var(--unit-aircraft-width) / 2) + (var(--unit-stroke-width) / 2)); - --unit-aircraft-label-y: calc(var(--unit-centre-y) - (var(--unit-aircraft-height) / 2) + (var(--unit-stroke-width) / 2)); -} - - -[data-object|="unit"] { - align-items: center; - cursor: pointer; - display: flex; - justify-content: center; - position: relative; - height: 100%; - width: 100%; -} - -.unit-selected-spotlight { - background-color: var(--unit-spotlight-fill); - border-radius: 50%; - display: none; - padding: var(--unit-spotlight-radius); - position: absolute; - z-index: 1; -} - -.unit-vvi { - align-self: center; - background: var(--secondary-gunmetal-grey); - display: flex; - justify-self: center; - transform-origin: bottom; - translate: 0 -50%; - padding-bottom: calc((var(--unit-aircraft-width) / 2) + var(--unit-stroke-width)); - position: absolute; - width: var(--unit-aircraft-vvi-width); - z-index: 3; -} - -.unit-marker-border { - border-radius: var(--border-radius-sm); - display: none; - height: calc(var(--unit-aircraft-height) + (var(--unit-label-border-width) * 2)); - position: absolute; - width: calc(var(--unit-aircraft-width) + (var(--unit-label-border-width) * 2)); - z-index: 2; -} - -.unit-hotgroup { - align-content: center; - background-color: var(--background-steel); - border-radius: var(--border-radius-xs); - display: none; - height: var(--unit-hotgroup-height); - justify-content: center; - position: absolute; - transform: rotate(-45deg); - translate: 0 -200%; - width: var(--unit-hotgroup-width); - z-index: 5; -} - -.unit-hotgroup-id { - background-color: transparent; - color: white; - font-size: 9px; - font-weight: bolder; - transform: rotate(45deg); - translate: -1px 1px; -} - - -/****************************** - Marker -******************************/ - -[data-object|="unit"] .unit-marker { - background-color: transparent; - background-repeat: no-repeat; - background-size: cover; - position: absolute; - transform-origin: center; - z-index: 3; -} - -/* Air */ - -[data-object|="unit-aircraft"] .unit-marker { - background-image: var(--unit-aircraft-marker-neutral-url); - height: var(--unit-aircraft-marker-height); - width: var(--unit-aircraft-marker-width); -} - -[data-object|="unit-aircraft"][data-is-highlighted] .unit-marker { - background-image: var(--unit-aircraft-marker-neutral-hover-url); -} - -[data-object|="unit-aircraft"][data-is-selected] .unit-marker { - background-image: var(--unit-aircraft-marker-neutral-selected-url); -} - -[data-object|="unit-aircraft"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-aircraft-marker-blue-url); -} - -[data-object|="unit-aircraft"][data-coalition="blue"][data-is-highlighted] .unit-marker { - background-image: var(--unit-aircraft-marker-blue-hover-url); -} - -[data-object|="unit-aircraft"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var(--unit-aircraft-marker-blue-selected-url); -} - - -[data-object|="unit-aircraft"][data-coalition="red"] .unit-marker { - background-image: var(--unit-aircraft-marker-red-url); -} - -[data-object|="unit-aircraft"][data-coalition="red"][data-is-highlighted] .unit-marker { - background-image: var(--unit-aircraft-marker-red-hover-url); -} - -[data-object|="unit-aircraft"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var(--unit-aircraft-marker-red-selected-url); -} - -/* Ground vehicles (not SAMs) */ - -[data-object|="unit-groundunit"] .unit-marker { - background-image: var(--unit-groundunit-marker-neutral-url); - height: var(--unit-groundunit-marker-height); - width: var(--unit-groundunit-marker-width); -} - -[data-object|="unit-groundunit"][data-is-highlighted] .unit-marker { - background-image: var(--unit-groundunit-marker-neutral-hover-url); -} - -[data-object|="unit-groundunit"][data-is-selected] .unit-marker { - background-image: var(--unit-groundunit-marker-neutral-selected-url); -} - - -[data-object|="unit-groundunit"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-groundunit-marker-blue-url); -} - -[data-object|="unit-groundunit"][data-coalition="blue"][data-is-highlighted] .unit-marker { - background-image: var(--unit-groundunit-marker-blue-hover-url); -} - -[data-object|="unit-groundunit"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var(--unit-groundunit-marker-blue-selected-url); -} - - -[data-object|="unit-groundunit"][data-coalition="red"] .unit-marker { - background-image: var(--unit-groundunit-marker-red-url); -} - -[data-object|="unit-groundunit"][data-coalition="red"][data-is-highlighted] .unit-marker { - background-image: var(--unit-groundunit-marker-red-hover-url); -} - -[data-object|="unit-groundunit"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var(--unit-groundunit-marker-red-selected-url); -} - - -/* SAMs */ - -[data-object|="unit-sam"] .unit-selected-spotlight { - translate: 0 2px; -} - -[data-object|="unit-sam"] .unit-marker { - background-image: var(--unit-sam-marker-neutral-url); - height: var(--unit-sam-marker-height); - width: var(--unit-sam-marker-width); -} - - -[data-object|="unit-sam"][data-is-highlighted] .unit-marker { - background-image: var(--unit-sam-marker-neutral-hover-url); -} - -[data-object|="unit-sam"][data-is-selected] .unit-marker { - background-image: var(--unit-sam-marker-neutral-selected-url); -} - - -[data-object|="unit-sam"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-sam-marker-blue-url); -} - -[data-object|="unit-sam"][data-coalition="blue"][data-is-highlighted] .unit-marker { - background-image: var(--unit-sam-marker-blue-hover-url); -} - -[data-object|="unit-sam"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var(--unit-sam-marker-blue-selected-url); -} - - -[data-object|="unit-sam"][data-coalition="red"] .unit-marker { - background-image: var(--unit-sam-marker-red-url); -} - -[data-object|="unit-sam"][data-coalition="red"][data-is-highlighted] .unit-marker { - background-image: var(--unit-sam-marker-red-hover-url); -} - -[data-object|="unit-sam"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var(--unit-sam-marker-red-selected-url); -} - - -/* navyunit */ - -[data-object|="unit-navyunit"] .unit-selected-spotlight { - translate: 0 -2px; -} - -[data-object|="unit-navyunit"] .unit-marker { - background-image: var(--unit-navyunit-marker-neutral-url); - height: var(--unit-navyunit-marker-height); - width: var(--unit-navyunit-marker-width); -} - - -[data-object|="unit-navyunit"][data-is-highlighted] .unit-marker { - background-image: var(--unit-navyunit-marker-neutral-hover-url); -} - -[data-object|="unit-navyunit"][data-is-selected] .unit-marker { - background-image: var(--unit-navyunit-marker-neutral-selected-url); -} - - -[data-object|="unit-navyunit"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-navyunit-marker-blue-url); -} - -[data-object|="unit-navyunit"][data-coalition="blue"][data-is-highlighted] .unit-marker { - background-image: var(--unit-navyunit-marker-blue-hover-url); -} - -[data-object|="unit-navyunit"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var(--unit-navyunit-marker-blue-selected-url); -} - - -[data-object|="unit-navyunit"][data-coalition="red"] .unit-marker { - background-image: var(--unit-navyunit-marker-red-url); -} - -[data-object|="unit-navyunit"][data-coalition="red"][data-is-highlighted] .unit-marker { - background-image: var(--unit-navyunit-marker-red-hover-url); -} - -[data-object|="unit-navyunit"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var(--unit-navyunit-marker-red-selected-url); -} - - -/* Building */ -[data-object|="unit-building"] .unit-marker { - background-image: var(--unit-building-marker-neutral-url); - height: var(--unit-building-marker-height); - width: var(--unit-building-marker-width); -} - - -[data-object|="unit-building"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-building-marker-blue-url); -} - - -[data-object|="unit-building"][data-coalition="red"] .unit-marker { - background-image: var(--unit-building-marker-red-url); -} - -/* Weapons */ - -[data-object|="unit-missile"], -[data-object|="unit-bomb"] { - cursor: default; -} - -[data-object|="unit-missile"] .unit-marker { - background-image: var(--unit-missile-marker-neutral-url); - height: var(--unit-missile-marker-height); - width: var(--unit-missile-marker-width); -} - -[data-object|="unit-missile"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-missile-marker-blue-url); -} - -[data-object|="unit-missile"][data-coalition="red"] .unit-marker { - background-image: var(--unit-missile-marker-red-url); -} - -[data-object|="unit-bomb"] .unit-marker { - background-image: var(--unit-bomb-marker-neutral-url); - height: var(--unit-bomb-marker-height); - width: var(--unit-bomb-marker-width); -} - -[data-object|="unit-bomb"][data-coalition="blue"] .unit-marker { - background-image: var(--unit-bomb-marker-blue-url); -} - -[data-object|="unit-bomb"][data-coalition="red"] .unit-marker { - background-image: var(--unit-bomb-marker-red-url); -} - - -/******************************************** -* Labels -********************************************/ - -[data-object|="unit"] .unit-short-label { - color: var(--secondary-gunmetal-grey); - font-size: var(--unit-font-size); - font-weight: var(--unit-font-weight); - line-height: normal; - position: absolute; - z-index: 10; -} - -[data-object|="unit-groundunit"] .unit-short-label { - translate: -1px 0; -} - -[data-object|="unit-sam"] .unit-short-label { - translate: 0 25%; -} - -[data-object|="unit-navyunit"] .unit-short-label { - translate: 0 -50%; -} - - -[data-object|="unit"] .unit-fuel { - background: white; - border: var(--unit-aircraft-fuel-border-width) solid var(--secondary-dark-steel); - border-radius: var(--border-radius-sm); - display: none; - height: var(--unit-aircraft-fuel-height); - position: absolute; - translate: var(--unit-aircraft-fuel-x) var(--unit-aircraft-fuel-y); - width: var(--unit-aircraft-fuel-width); - z-index: 5; -} - -[data-object|="unit"] .unit-fuel-level { - background-color: var(--secondary-light-grey); - height: 100%; - width: 100%; -} - - -[data-object|="unit"] .unit-ammo { - column-gap: var(--unit-aircraft-ammo-spacing); - display: none; - height: fit-content; - position: absolute; - translate: var(--unit-aircraft-ammo-x) var(--unit-aircraft-ammo-y); - width: fit-content; -} - -[data-object|="unit"] .unit-ammo>* { - background-color: white; - border: var(--unit-aircraft-ammo-border-width) solid var(--secondary-dark-steel); - border-radius: 50%; - padding: var(--unit-aircraft-ammo-radius); -} - -[data-object|="unit"] .unit-summary { - pointer-events: none; - column-gap: 6px; - color: white; - display: flex; - flex-wrap: wrap; - font-size: 11px; - font-weight: bold; - justify-content: right; - line-height: 12px; - position: absolute; - row-gap: 1px; - text-shadow: - -1px -1px 0 #000, - 1px -1px 0 #000, - -1px 1px 0 #000, - 1px 1px 0 #000; - translate: -60px 0; - width: fit-content; - z-index: 20; -} - -[data-hide-labels] [data-object|="unit"] .unit-summary { - display: none; -} - -[data-object|="unit"] .unit-summary>* { - padding: 1px; -} - -[data-object|="unit"] .unit-summary .unit-callsign { - color: white; - overflow: hidden; - text-align: right; - transform-origin: right; - white-space: nowrap; - width: 80px; -} - -[data-object|="unit"] .unit-summary .unit-callsign:hover { - direction: rtl; - overflow: visible; -} - -[data-object|="unit"]:hover .unit-ammo, -[data-object|="unit"]:hover .unit-fuel { - display: flex; -} - -[data-object|="unit"][data-is-in-hotgroup] .unit-hotgroup, -[data-object|="unit"][data-is-selected] .unit-ammo, -[data-object|="unit"][data-is-selected] .unit-fuel, -[data-object|="unit"][data-is-selected] .unit-selected-spotlight { - display: flex; -} - -[data-object|="unit"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-has-other-ammo] .unit-ammo-other { - background-color: var(--secondary-gunmetal-grey); -} - -[data-object|="unit"][data-coalition="blue"][data-is-selected] .unit-short-label { - color: var(--secondary-blue-text); -} - -[data-object|="unit"][data-coalition="blue"] .unit-fuel-level, -[data-object|="unit"][data-coalition="blue"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-coalition="blue"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-coalition="blue"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-coalition="blue"][data-has-other-ammo] .unit-ammo-other { - background-color: var(--primary-blue); -} - -[data-object|="unit"][data-coalition="blue"] .unit-vvi { - background-color: var(--secondary-blue-outline); -} - - -[data-object|="unit"][data-coalition="red"][data-is-selected] .unit-short-label { - color: var(--secondary-red-text); -} - -[data-object|="unit"][data-coalition="red"] .unit-fuel-level, -[data-object|="unit"][data-coalition="red"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-coalition="red"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-coalition="red"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-coalition="red"][data-has-other-ammo] .unit-ammo-other { - background-color: var(--primary-red); -} - -[data-object|="unit"][data-coalition="blue"] .unit-vvi { - background-color: var(--secondary-red-outline); -} - -@keyframes pulse { - 50% { - opacity: 0; - } -} - -[data-object|="unit"][data-has-low-fuel] .unit-fuel { - animation: pulse 1.5s linear infinite; -} - -[data-object|="unit"] .unit-state { - background-repeat: no-repeat; - position: absolute; - height: var(--unit-aircraft-state-height); - width: var(--unit-aircraft-state-width); - z-index: 10; -} - -[data-object|="unit"][data-state="rtb"] .unit-state { - background-image: var(--unit-aircraft-state-rtb); -} - -[data-object|="unit"][data-state="land"] .unit-state { - background-image: var(--unit-aircraft-state-rtb); -} - -[data-object|="unit"][data-state="idle"] .unit-state { - background-image: var(--unit-aircraft-state-idle); -} - -[data-object|="unit"][data-state="attack"] .unit-state { - background-image: var(--unit-aircraft-state-attack); -} - -[data-object|="unit"][data-state="follow"] .unit-state { - background-image: var(--unit-aircraft-state-follow); -} - -[data-object|="unit"][data-state="refuel"] .unit-state { - background-image: var(--unit-aircraft-state-refuel); -} - -[data-object|="unit"][data-state="human"] .unit-state { - background-image: var(--unit-aircraft-state-human); -} - -[data-object|="unit"][data-state="dcs"] .unit-state { - background-image: var(--unit-aircraft-state-dcs); -} - -/*** DEAD ***/ -[data-object|="unit-aircraft"][ data-is-dead] { - cursor: default; -} - -[data-object|="unit-aircraft"][ data-is-dead] .unit-marker { - background-image: var(--unit-aircraft-marker-neutral-dead-url); - background-position: 50% 50%; - background-size: auto 32px; -} - -[data-object|="unit-aircraft"][ data-is-dead][data-coalition="blue"] .unit-marker { - background-image: var(--unit-aircraft-marker-blue-dead-url); -} - -[data-object|="unit-aircraft"][ data-is-dead][data-coalition="red"] .unit-marker { - background-image: var(--unit-aircraft-marker-red-dead-url); -} - - -[data-object|="unit-aircraft"][data-is-dead] .unit-selected-spotlight, -[data-object|="unit-aircraft"][data-is-dead] .unit-short-label, -[data-object|="unit-aircraft"][data-is-dead] .unit-vvi, -[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup, -[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup-id, -[data-object|="unit-aircraft"][data-is-dead] .unit-state, -[data-object|="unit-aircraft"][data-is-dead] .unit-fuel, -[data-object|="unit-aircraft"][data-is-dead] .unit-ammo, -[data-object|="unit-aircraft"][data-is-dead]:hover .unit-fuel, -[data-object|="unit-aircraft"][data-is-dead]:hover .unit-ammo { - display: none !important; -} - -[data-object|="unit-aircraft"][ data-is-dead] .unit-summary>* { - display: none; -} - -[data-object|="unit-aircraft"][ data-is-dead] .unit-summary .unit-callsign { - display: block; -} \ No newline at end of file diff --git a/client/public/themes/olympus/images/buttons/emissions/attack.svg b/client/public/themes/olympus/images/buttons/emissions/attack.svg new file mode 100644 index 00000000..0846e4e6 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/emissions/attack.svg @@ -0,0 +1,44 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/emissions/defend.svg b/client/public/themes/olympus/images/buttons/emissions/defend.svg new file mode 100644 index 00000000..5c884188 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/emissions/defend.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/emissions/free.svg b/client/public/themes/olympus/images/buttons/emissions/free.svg new file mode 100644 index 00000000..f07b2db6 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/emissions/free.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/emissions/silent.svg b/client/public/themes/olympus/images/buttons/emissions/silent.svg new file mode 100644 index 00000000..f735bc21 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/emissions/silent.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/roe/designated.svg b/client/public/themes/olympus/images/buttons/roe/designated.svg new file mode 100644 index 00000000..0846e4e6 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/roe/designated.svg @@ -0,0 +1,44 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/roe/free.svg b/client/public/themes/olympus/images/buttons/roe/free.svg new file mode 100644 index 00000000..f07b2db6 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/roe/free.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/roe/hold.svg b/client/public/themes/olympus/images/buttons/roe/hold.svg new file mode 100644 index 00000000..f735bc21 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/roe/hold.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/roe/return.svg b/client/public/themes/olympus/images/buttons/roe/return.svg new file mode 100644 index 00000000..5c884188 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/roe/return.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/spawn_aircraft.svg b/client/public/themes/olympus/images/buttons/spawn/aircraft.svg similarity index 100% rename from client/public/themes/olympus/images/spawn_aircraft.svg rename to client/public/themes/olympus/images/buttons/spawn/aircraft.svg diff --git a/client/public/themes/olympus/images/spawn_ground.svg b/client/public/themes/olympus/images/buttons/spawn/ground.svg similarity index 100% rename from client/public/themes/olympus/images/spawn_ground.svg rename to client/public/themes/olympus/images/buttons/spawn/ground.svg diff --git a/client/public/themes/olympus/images/spawn_smoke.svg b/client/public/themes/olympus/images/buttons/spawn/smoke.svg similarity index 100% rename from client/public/themes/olympus/images/spawn_smoke.svg rename to client/public/themes/olympus/images/buttons/spawn/smoke.svg diff --git a/client/public/themes/olympus/images/buttons/threat/evade.svg b/client/public/themes/olympus/images/buttons/threat/evade.svg new file mode 100644 index 00000000..54d7b49f --- /dev/null +++ b/client/public/themes/olympus/images/buttons/threat/evade.svg @@ -0,0 +1,62 @@ + + + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/threat/manoeuvre.svg b/client/public/themes/olympus/images/buttons/threat/manoeuvre.svg new file mode 100644 index 00000000..fcc9376b --- /dev/null +++ b/client/public/themes/olympus/images/buttons/threat/manoeuvre.svg @@ -0,0 +1,50 @@ + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/threat/none.svg b/client/public/themes/olympus/images/buttons/threat/none.svg new file mode 100644 index 00000000..53414370 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/threat/none.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/threat/passive.svg b/client/public/themes/olympus/images/buttons/threat/passive.svg new file mode 100644 index 00000000..ac558fef --- /dev/null +++ b/client/public/themes/olympus/images/buttons/threat/passive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/airbase.svg b/client/public/themes/olympus/images/buttons/visibility/airbase.svg new file mode 100644 index 00000000..28ad42a4 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/airbase.svg @@ -0,0 +1,76 @@ + + + + + + + + image/svg+xml + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/aircraft.svg b/client/public/themes/olympus/images/buttons/visibility/aircraft.svg new file mode 100644 index 00000000..09a9e322 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/aircraft.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/dcs.svg b/client/public/themes/olympus/images/buttons/visibility/dcs.svg new file mode 100644 index 00000000..bb7bd479 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/dcs.svg @@ -0,0 +1,32 @@ + + + + + + image/svg+xml + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/groundunit-other.svg b/client/public/themes/olympus/images/buttons/visibility/groundunit-other.svg new file mode 100644 index 00000000..0a448b6f --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/groundunit-other.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/groundunit-sam.svg b/client/public/themes/olympus/images/buttons/visibility/groundunit-sam.svg new file mode 100644 index 00000000..2a568fbb --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/groundunit-sam.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/human.svg b/client/public/themes/olympus/images/buttons/visibility/human.svg new file mode 100644 index 00000000..51278e9e --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/human.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/client/public/themes/olympus/images/buttons/visibility/navyunit.svg b/client/public/themes/olympus/images/buttons/visibility/navyunit.svg new file mode 100644 index 00000000..d4ff6fec --- /dev/null +++ b/client/public/themes/olympus/images/buttons/visibility/navyunit.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/client/public/themes/olympus/images/icon_aa_blue.svg b/client/public/themes/olympus/images/icon_aa_blue.svg deleted file mode 100644 index 0cf7b80e..00000000 --- a/client/public/themes/olympus/images/icon_aa_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_aa_blue_hover.svg b/client/public/themes/olympus/images/icon_aa_blue_hover.svg deleted file mode 100644 index 083607f2..00000000 --- a/client/public/themes/olympus/images/icon_aa_blue_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aa_blue_selected.svg b/client/public/themes/olympus/images/icon_aa_blue_selected.svg deleted file mode 100644 index 8b2e45dc..00000000 --- a/client/public/themes/olympus/images/icon_aa_blue_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aa_neutral.svg b/client/public/themes/olympus/images/icon_aa_neutral.svg deleted file mode 100644 index a420833b..00000000 --- a/client/public/themes/olympus/images/icon_aa_neutral.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_aa_neutral_hover.svg b/client/public/themes/olympus/images/icon_aa_neutral_hover.svg deleted file mode 100644 index 6ec81838..00000000 --- a/client/public/themes/olympus/images/icon_aa_neutral_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aa_neutral_selected.svg b/client/public/themes/olympus/images/icon_aa_neutral_selected.svg deleted file mode 100644 index 5ea11a76..00000000 --- a/client/public/themes/olympus/images/icon_aa_neutral_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aa_red.svg b/client/public/themes/olympus/images/icon_aa_red.svg deleted file mode 100644 index 9e048861..00000000 --- a/client/public/themes/olympus/images/icon_aa_red.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_aa_red_hover.svg b/client/public/themes/olympus/images/icon_aa_red_hover.svg deleted file mode 100644 index e878c07e..00000000 --- a/client/public/themes/olympus/images/icon_aa_red_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aa_red_selected.svg b/client/public/themes/olympus/images/icon_aa_red_selected.svg deleted file mode 100644 index 7d7e78d3..00000000 --- a/client/public/themes/olympus/images/icon_aa_red_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_airbase_neutral.svg b/client/public/themes/olympus/images/icon_airbase_neutral.svg deleted file mode 100644 index 43222171..00000000 --- a/client/public/themes/olympus/images/icon_airbase_neutral.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/icon_airbase_red.svg b/client/public/themes/olympus/images/icon_airbase_red.svg deleted file mode 100644 index d95872f1..00000000 --- a/client/public/themes/olympus/images/icon_airbase_red.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_blue.svg b/client/public/themes/olympus/images/icon_aircraft_blue.svg deleted file mode 100644 index 7e547339..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_blue_hover.svg b/client/public/themes/olympus/images/icon_aircraft_blue_hover.svg deleted file mode 100644 index 0b59ac37..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_blue_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_blue_selected.svg b/client/public/themes/olympus/images/icon_aircraft_blue_selected.svg deleted file mode 100644 index 251084a6..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_blue_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_neutral.svg b/client/public/themes/olympus/images/icon_aircraft_neutral.svg deleted file mode 100644 index 981602fd..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_neutral_hover.svg b/client/public/themes/olympus/images/icon_aircraft_neutral_hover.svg deleted file mode 100644 index a35613bb..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_neutral_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_red.svg b/client/public/themes/olympus/images/icon_aircraft_red.svg deleted file mode 100644 index 5777ae70..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_red_hover.svg b/client/public/themes/olympus/images/icon_aircraft_red_hover.svg deleted file mode 100644 index d975fd7b..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_red_hover.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_red_selected.svg b/client/public/themes/olympus/images/icon_aircraft_red_selected.svg deleted file mode 100644 index 702d4c27..00000000 --- a/client/public/themes/olympus/images/icon_aircraft_red_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_bomb_blue.svg b/client/public/themes/olympus/images/icon_bomb_blue.svg deleted file mode 100644 index 136deb4f..00000000 --- a/client/public/themes/olympus/images/icon_bomb_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_bomb_neutral.svg b/client/public/themes/olympus/images/icon_bomb_neutral.svg deleted file mode 100644 index e32f31b9..00000000 --- a/client/public/themes/olympus/images/icon_bomb_neutral.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_bomb_red.svg b/client/public/themes/olympus/images/icon_bomb_red.svg deleted file mode 100644 index c86bf6f4..00000000 --- a/client/public/themes/olympus/images/icon_bomb_red.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_building_blue_hover.svg b/client/public/themes/olympus/images/icon_building_blue_hover.svg deleted file mode 100644 index f67b9fe7..00000000 --- a/client/public/themes/olympus/images/icon_building_blue_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_building_blue_selected.svg b/client/public/themes/olympus/images/icon_building_blue_selected.svg deleted file mode 100644 index ad0e3fc1..00000000 --- a/client/public/themes/olympus/images/icon_building_blue_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_building_neutral.svg b/client/public/themes/olympus/images/icon_building_neutral.svg deleted file mode 100644 index b88ef5e9..00000000 --- a/client/public/themes/olympus/images/icon_building_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_building_neutral_hover.svg b/client/public/themes/olympus/images/icon_building_neutral_hover.svg deleted file mode 100644 index 43784a42..00000000 --- a/client/public/themes/olympus/images/icon_building_neutral_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_building_neutral_selected.svg b/client/public/themes/olympus/images/icon_building_neutral_selected.svg deleted file mode 100644 index b009365c..00000000 --- a/client/public/themes/olympus/images/icon_building_neutral_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_building_red.svg b/client/public/themes/olympus/images/icon_building_red.svg deleted file mode 100644 index ff503707..00000000 --- a/client/public/themes/olympus/images/icon_building_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_building_red_hover.svg b/client/public/themes/olympus/images/icon_building_red_hover.svg deleted file mode 100644 index a5c99d6e..00000000 --- a/client/public/themes/olympus/images/icon_building_red_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_building_red_selected.svg b/client/public/themes/olympus/images/icon_building_red_selected.svg deleted file mode 100644 index 220ce1b9..00000000 --- a/client/public/themes/olympus/images/icon_building_red_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_death_blue.svg b/client/public/themes/olympus/images/icon_death_blue.svg deleted file mode 100644 index 24f20fbf..00000000 --- a/client/public/themes/olympus/images/icon_death_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_death_neutral.svg b/client/public/themes/olympus/images/icon_death_neutral.svg deleted file mode 100644 index 295d54b5..00000000 --- a/client/public/themes/olympus/images/icon_death_neutral.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_ground_blue.svg b/client/public/themes/olympus/images/icon_ground_blue.svg deleted file mode 100644 index 8b44edf7..00000000 --- a/client/public/themes/olympus/images/icon_ground_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ground_blue_hover.svg b/client/public/themes/olympus/images/icon_ground_blue_hover.svg deleted file mode 100644 index 764c9f9c..00000000 --- a/client/public/themes/olympus/images/icon_ground_blue_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ground_neutral.svg b/client/public/themes/olympus/images/icon_ground_neutral.svg deleted file mode 100644 index df956461..00000000 --- a/client/public/themes/olympus/images/icon_ground_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ground_neutral_hover.svg b/client/public/themes/olympus/images/icon_ground_neutral_hover.svg deleted file mode 100644 index fdd6e2e0..00000000 --- a/client/public/themes/olympus/images/icon_ground_neutral_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ground_neutral_selected.svg b/client/public/themes/olympus/images/icon_ground_neutral_selected.svg deleted file mode 100644 index d4651a2c..00000000 --- a/client/public/themes/olympus/images/icon_ground_neutral_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ground_red.svg b/client/public/themes/olympus/images/icon_ground_red.svg deleted file mode 100644 index bb78e1df..00000000 --- a/client/public/themes/olympus/images/icon_ground_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ground_red_hover.svg b/client/public/themes/olympus/images/icon_ground_red_hover.svg deleted file mode 100644 index 7bce4e24..00000000 --- a/client/public/themes/olympus/images/icon_ground_red_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ground_red_selected.svg b/client/public/themes/olympus/images/icon_ground_red_selected.svg deleted file mode 100644 index afe9a623..00000000 --- a/client/public/themes/olympus/images/icon_ground_red_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_hold_blue.svg b/client/public/themes/olympus/images/icon_hold_blue.svg deleted file mode 100644 index 257c167a..00000000 --- a/client/public/themes/olympus/images/icon_hold_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_hold_red.svg b/client/public/themes/olympus/images/icon_hold_red.svg deleted file mode 100644 index d2ec1a41..00000000 --- a/client/public/themes/olympus/images/icon_hold_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_missile_neutral.svg b/client/public/themes/olympus/images/icon_missile_neutral.svg deleted file mode 100644 index 73be3528..00000000 --- a/client/public/themes/olympus/images/icon_missile_neutral.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_missile_red.svg b/client/public/themes/olympus/images/icon_missile_red.svg deleted file mode 100644 index c16f8d00..00000000 --- a/client/public/themes/olympus/images/icon_missile_red.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_navyuni_blue.svg b/client/public/themes/olympus/images/icon_navyuni_blue.svg deleted file mode 100644 index e2d296d0..00000000 --- a/client/public/themes/olympus/images/icon_navyuni_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_navyunit_neutral.svg b/client/public/themes/olympus/images/icon_navyunit_neutral.svg deleted file mode 100644 index 13a87c0b..00000000 --- a/client/public/themes/olympus/images/icon_navyunit_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_navyunit_red.svg b/client/public/themes/olympus/images/icon_navyunit_red.svg deleted file mode 100644 index 91a0aff9..00000000 --- a/client/public/themes/olympus/images/icon_navyunit_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_rtb_blue.svg b/client/public/themes/olympus/images/icon_rtb_blue.svg deleted file mode 100644 index 0ddecdf6..00000000 --- a/client/public/themes/olympus/images/icon_rtb_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_rtb_neutral.svg b/client/public/themes/olympus/images/icon_rtb_neutral.svg deleted file mode 100644 index 66803354..00000000 --- a/client/public/themes/olympus/images/icon_rtb_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_sam_blue.svg b/client/public/themes/olympus/images/icon_sam_blue.svg deleted file mode 100644 index bc8729c1..00000000 --- a/client/public/themes/olympus/images/icon_sam_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_sam_neutral.svg b/client/public/themes/olympus/images/icon_sam_neutral.svg deleted file mode 100644 index 9eb5ab0b..00000000 --- a/client/public/themes/olympus/images/icon_sam_neutral.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_sam_red.svg b/client/public/themes/olympus/images/icon_sam_red.svg deleted file mode 100644 index 36aac80d..00000000 --- a/client/public/themes/olympus/images/icon_sam_red.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_ship_blue.svg b/client/public/themes/olympus/images/icon_ship_blue.svg deleted file mode 100644 index a981861f..00000000 --- a/client/public/themes/olympus/images/icon_ship_blue.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ship_blue_hover.svg b/client/public/themes/olympus/images/icon_ship_blue_hover.svg deleted file mode 100644 index 34b0fe59..00000000 --- a/client/public/themes/olympus/images/icon_ship_blue_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ship_blue_selected.svg b/client/public/themes/olympus/images/icon_ship_blue_selected.svg deleted file mode 100644 index f472cd42..00000000 --- a/client/public/themes/olympus/images/icon_ship_blue_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ship_neutral.svg b/client/public/themes/olympus/images/icon_ship_neutral.svg deleted file mode 100644 index df1643d9..00000000 --- a/client/public/themes/olympus/images/icon_ship_neutral.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ship_neutral_hover.svg b/client/public/themes/olympus/images/icon_ship_neutral_hover.svg deleted file mode 100644 index 2e332bcd..00000000 --- a/client/public/themes/olympus/images/icon_ship_neutral_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ship_neutral_selected.svg b/client/public/themes/olympus/images/icon_ship_neutral_selected.svg deleted file mode 100644 index 6a7e36e3..00000000 --- a/client/public/themes/olympus/images/icon_ship_neutral_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ship_red.svg b/client/public/themes/olympus/images/icon_ship_red.svg deleted file mode 100644 index f130f9f3..00000000 --- a/client/public/themes/olympus/images/icon_ship_red.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icon_ship_red_hover.svg b/client/public/themes/olympus/images/icon_ship_red_hover.svg deleted file mode 100644 index 7233b4e1..00000000 --- a/client/public/themes/olympus/images/icon_ship_red_hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icon_ship_red_selected.svg b/client/public/themes/olympus/images/icon_ship_red_selected.svg deleted file mode 100644 index 0c41f7c2..00000000 --- a/client/public/themes/olympus/images/icon_ship_red_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/images/icons/altitude.svg b/client/public/themes/olympus/images/icons/altitude.svg similarity index 100% rename from client/public/images/icons/altitude.svg rename to client/public/themes/olympus/images/icons/altitude.svg diff --git a/client/public/images/icons/arrow-pointer-solid.svg b/client/public/themes/olympus/images/icons/arrow-pointer-solid.svg similarity index 100% rename from client/public/images/icons/arrow-pointer-solid.svg rename to client/public/themes/olympus/images/icons/arrow-pointer-solid.svg diff --git a/client/public/images/icons/arrows-to-eye-solid.svg b/client/public/themes/olympus/images/icons/arrows-to-eye-solid.svg similarity index 100% rename from client/public/images/icons/arrows-to-eye-solid.svg rename to client/public/themes/olympus/images/icons/arrows-to-eye-solid.svg diff --git a/client/public/themes/olympus/images/check_square.svg b/client/public/themes/olympus/images/icons/check_square.svg similarity index 100% rename from client/public/themes/olympus/images/check_square.svg rename to client/public/themes/olympus/images/icons/check_square.svg diff --git a/client/public/themes/olympus/images/chevron-down.svg b/client/public/themes/olympus/images/icons/chevron-down.svg similarity index 100% rename from client/public/themes/olympus/images/chevron-down.svg rename to client/public/themes/olympus/images/icons/chevron-down.svg diff --git a/client/public/themes/olympus/images/icons/diamond.svg b/client/public/themes/olympus/images/icons/diamond.svg new file mode 100644 index 00000000..eef3c6f2 --- /dev/null +++ b/client/public/themes/olympus/images/icons/diamond.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/client/public/images/icons/echelon-lh.svg b/client/public/themes/olympus/images/icons/echelon-lh.svg similarity index 100% rename from client/public/images/icons/echelon-lh.svg rename to client/public/themes/olympus/images/icons/echelon-lh.svg diff --git a/client/public/images/icons/echelon-rh.svg b/client/public/themes/olympus/images/icons/echelon-rh.svg similarity index 100% rename from client/public/images/icons/echelon-rh.svg rename to client/public/themes/olympus/images/icons/echelon-rh.svg diff --git a/client/public/images/icons/echelon.svg b/client/public/themes/olympus/images/icons/echelon.svg similarity index 100% rename from client/public/images/icons/echelon.svg rename to client/public/themes/olympus/images/icons/echelon.svg diff --git a/client/public/images/icons/follow.svg b/client/public/themes/olympus/images/icons/follow.svg similarity index 100% rename from client/public/images/icons/follow.svg rename to client/public/themes/olympus/images/icons/follow.svg diff --git a/client/public/images/icons/formation-end.svg b/client/public/themes/olympus/images/icons/formation-end.svg similarity index 100% rename from client/public/images/icons/formation-end.svg rename to client/public/themes/olympus/images/icons/formation-end.svg diff --git a/client/public/images/icons/formation-middle.svg b/client/public/themes/olympus/images/icons/formation-middle.svg similarity index 100% rename from client/public/images/icons/formation-middle.svg rename to client/public/themes/olympus/images/icons/formation-middle.svg diff --git a/client/public/images/icons/front.svg b/client/public/themes/olympus/images/icons/front.svg similarity index 100% rename from client/public/images/icons/front.svg rename to client/public/themes/olympus/images/icons/front.svg diff --git a/client/public/images/icons/fuel.svg b/client/public/themes/olympus/images/icons/fuel.svg similarity index 100% rename from client/public/images/icons/fuel.svg rename to client/public/themes/olympus/images/icons/fuel.svg diff --git a/client/public/images/icons/gears-solid.svg b/client/public/themes/olympus/images/icons/gears-solid.svg similarity index 100% rename from client/public/images/icons/gears-solid.svg rename to client/public/themes/olympus/images/icons/gears-solid.svg diff --git a/client/public/images/icons/grip-lines-solid.svg b/client/public/themes/olympus/images/icons/grip-lines-solid.svg similarity index 100% rename from client/public/images/icons/grip-lines-solid.svg rename to client/public/themes/olympus/images/icons/grip-lines-solid.svg diff --git a/client/public/images/icons/heading.svg b/client/public/themes/olympus/images/icons/heading.svg similarity index 100% rename from client/public/images/icons/heading.svg rename to client/public/themes/olympus/images/icons/heading.svg diff --git a/client/public/images/icons/line-abreast.svg b/client/public/themes/olympus/images/icons/line-abreast.svg similarity index 100% rename from client/public/images/icons/line-abreast.svg rename to client/public/themes/olympus/images/icons/line-abreast.svg diff --git a/client/public/themes/olympus/images/map_source.svg b/client/public/themes/olympus/images/icons/map_source.svg similarity index 100% rename from client/public/themes/olympus/images/map_source.svg rename to client/public/themes/olympus/images/icons/map_source.svg diff --git a/client/public/images/pin.png b/client/public/themes/olympus/images/icons/pin.png similarity index 100% rename from client/public/images/pin.png rename to client/public/themes/olympus/images/icons/pin.png diff --git a/client/public/images/icons/ruler.svg b/client/public/themes/olympus/images/icons/ruler.svg similarity index 100% rename from client/public/images/icons/ruler.svg rename to client/public/themes/olympus/images/icons/ruler.svg diff --git a/client/public/images/icons/speed.svg b/client/public/themes/olympus/images/icons/speed.svg similarity index 100% rename from client/public/images/icons/speed.svg rename to client/public/themes/olympus/images/icons/speed.svg diff --git a/client/public/images/icons/square-check-solid.svg b/client/public/themes/olympus/images/icons/square-check-solid.svg similarity index 100% rename from client/public/images/icons/square-check-solid.svg rename to client/public/themes/olympus/images/icons/square-check-solid.svg diff --git a/client/public/images/icons/square-regular.svg b/client/public/themes/olympus/images/icons/square-regular.svg similarity index 100% rename from client/public/images/icons/square-regular.svg rename to client/public/themes/olympus/images/icons/square-regular.svg diff --git a/client/public/images/icons/sword.svg b/client/public/themes/olympus/images/icons/sword.svg similarity index 100% rename from client/public/images/icons/sword.svg rename to client/public/themes/olympus/images/icons/sword.svg diff --git a/client/public/images/icons/trail.svg b/client/public/themes/olympus/images/icons/trail.svg similarity index 100% rename from client/public/images/icons/trail.svg rename to client/public/themes/olympus/images/icons/trail.svg diff --git a/client/public/themes/olympus/images/icons_actions_180_dark.svg b/client/public/themes/olympus/images/icons_actions_180_dark.svg deleted file mode 100644 index 79e0ade7..00000000 --- a/client/public/themes/olympus/images/icons_actions_180_dark.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icons_actions_180_light.svg b/client/public/themes/olympus/images/icons_actions_180_light.svg deleted file mode 100644 index 2db2cb63..00000000 --- a/client/public/themes/olympus/images/icons_actions_180_light.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icons_actions_cancel_dark.svg b/client/public/themes/olympus/images/icons_actions_cancel_dark.svg deleted file mode 100644 index 3582a48c..00000000 --- a/client/public/themes/olympus/images/icons_actions_cancel_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_cancel_light.svg b/client/public/themes/olympus/images/icons_actions_cancel_light.svg deleted file mode 100644 index dc3335a8..00000000 --- a/client/public/themes/olympus/images/icons_actions_cancel_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_gas_dark.svg b/client/public/themes/olympus/images/icons_actions_gas_dark.svg deleted file mode 100644 index 4a5d7357..00000000 --- a/client/public/themes/olympus/images/icons_actions_gas_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_gas_light.svg b/client/public/themes/olympus/images/icons_actions_gas_light.svg deleted file mode 100644 index 14bbef19..00000000 --- a/client/public/themes/olympus/images/icons_actions_gas_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_nothing_dark.svg b/client/public/themes/olympus/images/icons_actions_nothing_dark.svg deleted file mode 100644 index f6bb0463..00000000 --- a/client/public/themes/olympus/images/icons_actions_nothing_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_nothing_light.svg b/client/public/themes/olympus/images/icons_actions_nothing_light.svg deleted file mode 100644 index 1ea95812..00000000 --- a/client/public/themes/olympus/images/icons_actions_nothing_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_rtb_dark.svg b/client/public/themes/olympus/images/icons_actions_rtb_dark.svg deleted file mode 100644 index 081bff14..00000000 --- a/client/public/themes/olympus/images/icons_actions_rtb_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_rtb_light.svg b/client/public/themes/olympus/images/icons_actions_rtb_light.svg deleted file mode 100644 index 9147bcc5..00000000 --- a/client/public/themes/olympus/images/icons_actions_rtb_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_search_dark.svg b/client/public/themes/olympus/images/icons_actions_search_dark.svg deleted file mode 100644 index 497481c1..00000000 --- a/client/public/themes/olympus/images/icons_actions_search_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_actions_search_light.svg b/client/public/themes/olympus/images/icons_actions_search_light.svg deleted file mode 100644 index 2ca59cbb..00000000 --- a/client/public/themes/olympus/images/icons_actions_search_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_form_abreast_dark.svg b/client/public/themes/olympus/images/icons_form_abreast_dark.svg deleted file mode 100644 index 513d6b25..00000000 --- a/client/public/themes/olympus/images/icons_form_abreast_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_form_abreast_light.svg b/client/public/themes/olympus/images/icons_form_abreast_light.svg deleted file mode 100644 index 0b302a04..00000000 --- a/client/public/themes/olympus/images/icons_form_abreast_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_form_admin_dark.svg b/client/public/themes/olympus/images/icons_form_admin_dark.svg deleted file mode 100644 index 44e42f62..00000000 --- a/client/public/themes/olympus/images/icons_form_admin_dark.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icons_form_admin_light.svg b/client/public/themes/olympus/images/icons_form_admin_light.svg deleted file mode 100644 index 532c523f..00000000 --- a/client/public/themes/olympus/images/icons_form_admin_light.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/icons_form_echelon_dark.svg b/client/public/themes/olympus/images/icons_form_echelon_dark.svg deleted file mode 100644 index dc4b4b60..00000000 --- a/client/public/themes/olympus/images/icons_form_echelon_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_form_echelon_light.svg b/client/public/themes/olympus/images/icons_form_echelon_light.svg deleted file mode 100644 index a788953d..00000000 --- a/client/public/themes/olympus/images/icons_form_echelon_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_form_trail_dark.svg b/client/public/themes/olympus/images/icons_form_trail_dark.svg deleted file mode 100644 index 555ea0dd..00000000 --- a/client/public/themes/olympus/images/icons_form_trail_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_form_trail_light.svg b/client/public/themes/olympus/images/icons_form_trail_light.svg deleted file mode 100644 index 0ac432f7..00000000 --- a/client/public/themes/olympus/images/icons_form_trail_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons_misc_brush_blue.svg b/client/public/themes/olympus/images/icons_misc_brush_blue.svg deleted file mode 100644 index 7ecf9816..00000000 --- a/client/public/themes/olympus/images/icons_misc_brush_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_brush_dark.svg b/client/public/themes/olympus/images/icons_misc_brush_dark.svg deleted file mode 100644 index ed925a5a..00000000 --- a/client/public/themes/olympus/images/icons_misc_brush_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_brush_light.svg b/client/public/themes/olympus/images/icons_misc_brush_light.svg deleted file mode 100644 index 74d2a691..00000000 --- a/client/public/themes/olympus/images/icons_misc_brush_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_gas_blue.svg b/client/public/themes/olympus/images/icons_misc_gas_blue.svg deleted file mode 100644 index 13afd5e5..00000000 --- a/client/public/themes/olympus/images/icons_misc_gas_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_gas_dark.svg b/client/public/themes/olympus/images/icons_misc_gas_dark.svg deleted file mode 100644 index 53bb4a3f..00000000 --- a/client/public/themes/olympus/images/icons_misc_gas_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_gas_light.svg b/client/public/themes/olympus/images/icons_misc_gas_light.svg deleted file mode 100644 index 8530905f..00000000 --- a/client/public/themes/olympus/images/icons_misc_gas_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_map_blue.svg b/client/public/themes/olympus/images/icons_misc_map_blue.svg deleted file mode 100644 index 3e233196..00000000 --- a/client/public/themes/olympus/images/icons_misc_map_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_map_dark.svg b/client/public/themes/olympus/images/icons_misc_map_dark.svg deleted file mode 100644 index 6b9a5219..00000000 --- a/client/public/themes/olympus/images/icons_misc_map_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_map_light.svg b/client/public/themes/olympus/images/icons_misc_map_light.svg deleted file mode 100644 index 8bec4777..00000000 --- a/client/public/themes/olympus/images/icons_misc_map_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_plane_blue.svg b/client/public/themes/olympus/images/icons_misc_plane_blue.svg deleted file mode 100644 index 7bf3bcd8..00000000 --- a/client/public/themes/olympus/images/icons_misc_plane_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_plane_dark.svg b/client/public/themes/olympus/images/icons_misc_plane_dark.svg deleted file mode 100644 index cec512c5..00000000 --- a/client/public/themes/olympus/images/icons_misc_plane_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_plane_light.svg b/client/public/themes/olympus/images/icons_misc_plane_light.svg deleted file mode 100644 index cf34b9c8..00000000 --- a/client/public/themes/olympus/images/icons_misc_plane_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_settings_blue.svg b/client/public/themes/olympus/images/icons_misc_settings_blue.svg deleted file mode 100644 index 2d7004c6..00000000 --- a/client/public/themes/olympus/images/icons_misc_settings_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_settings_dark.svg b/client/public/themes/olympus/images/icons_misc_settings_dark.svg deleted file mode 100644 index 04b375e4..00000000 --- a/client/public/themes/olympus/images/icons_misc_settings_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_settings_light.svg b/client/public/themes/olympus/images/icons_misc_settings_light.svg deleted file mode 100644 index 19270b5c..00000000 --- a/client/public/themes/olympus/images/icons_misc_settings_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_visible_blue.svg b/client/public/themes/olympus/images/icons_misc_visible_blue.svg deleted file mode 100644 index 66f1ae9a..00000000 --- a/client/public/themes/olympus/images/icons_misc_visible_blue.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_visible_dark.svg b/client/public/themes/olympus/images/icons_misc_visible_dark.svg deleted file mode 100644 index 0023c2c1..00000000 --- a/client/public/themes/olympus/images/icons_misc_visible_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_misc_visible_light.svg b/client/public/themes/olympus/images/icons_misc_visible_light.svg deleted file mode 100644 index 46f1b080..00000000 --- a/client/public/themes/olympus/images/icons_misc_visible_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_attack_dark.svg b/client/public/themes/olympus/images/icons_roe_attack_dark.svg deleted file mode 100644 index db976cbb..00000000 --- a/client/public/themes/olympus/images/icons_roe_attack_dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/client/public/themes/olympus/images/icons_roe_attack_light.svg b/client/public/themes/olympus/images/icons_roe_attack_light.svg deleted file mode 100644 index 06ff8bb3..00000000 --- a/client/public/themes/olympus/images/icons_roe_attack_light.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/client/public/themes/olympus/images/icons_roe_defend_dark.svg b/client/public/themes/olympus/images/icons_roe_defend_dark.svg deleted file mode 100644 index 82c305aa..00000000 --- a/client/public/themes/olympus/images/icons_roe_defend_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_defend_light.svg b/client/public/themes/olympus/images/icons_roe_defend_light.svg deleted file mode 100644 index 1d956938..00000000 --- a/client/public/themes/olympus/images/icons_roe_defend_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_free_dark.svg b/client/public/themes/olympus/images/icons_roe_free_dark.svg deleted file mode 100644 index a3b0b02f..00000000 --- a/client/public/themes/olympus/images/icons_roe_free_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_free_light.svg b/client/public/themes/olympus/images/icons_roe_free_light.svg deleted file mode 100644 index 1fdf5d13..00000000 --- a/client/public/themes/olympus/images/icons_roe_free_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_return_dark.svg b/client/public/themes/olympus/images/icons_roe_return_dark.svg deleted file mode 100644 index e42485a7..00000000 --- a/client/public/themes/olympus/images/icons_roe_return_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_return_light.svg b/client/public/themes/olympus/images/icons_roe_return_light.svg deleted file mode 100644 index 030534d7..00000000 --- a/client/public/themes/olympus/images/icons_roe_return_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_stop_dark.svg b/client/public/themes/olympus/images/icons_roe_stop_dark.svg deleted file mode 100644 index 3582a48c..00000000 --- a/client/public/themes/olympus/images/icons_roe_stop_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_stop_light.svg b/client/public/themes/olympus/images/icons_roe_stop_light.svg deleted file mode 100644 index dc3335a8..00000000 --- a/client/public/themes/olympus/images/icons_roe_stop_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_target_dark.svg b/client/public/themes/olympus/images/icons_roe_target_dark.svg deleted file mode 100644 index cb68d86b..00000000 --- a/client/public/themes/olympus/images/icons_roe_target_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_roe_target_light.svg b/client/public/themes/olympus/images/icons_roe_target_light.svg deleted file mode 100644 index a9ec508c..00000000 --- a/client/public/themes/olympus/images/icons_roe_target_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_cms_dark.svg b/client/public/themes/olympus/images/icons_threat_cms_dark.svg deleted file mode 100644 index f6f53fd5..00000000 --- a/client/public/themes/olympus/images/icons_threat_cms_dark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/client/public/themes/olympus/images/icons_threat_cms_light.svg b/client/public/themes/olympus/images/icons_threat_cms_light.svg deleted file mode 100644 index 6032f934..00000000 --- a/client/public/themes/olympus/images/icons_threat_cms_light.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/client/public/themes/olympus/images/icons_threat_defend_dark.svg b/client/public/themes/olympus/images/icons_threat_defend_dark.svg deleted file mode 100644 index 962971eb..00000000 --- a/client/public/themes/olympus/images/icons_threat_defend_dark.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/client/public/themes/olympus/images/icons_threat_defend_light.svg b/client/public/themes/olympus/images/icons_threat_defend_light.svg deleted file mode 100644 index 0e598866..00000000 --- a/client/public/themes/olympus/images/icons_threat_defend_light.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/client/public/themes/olympus/images/icons_threat_nothing_dark.svg b/client/public/themes/olympus/images/icons_threat_nothing_dark.svg deleted file mode 100644 index 3582a48c..00000000 --- a/client/public/themes/olympus/images/icons_threat_nothing_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_nothing_light.svg b/client/public/themes/olympus/images/icons_threat_nothing_light.svg deleted file mode 100644 index dc3335a8..00000000 --- a/client/public/themes/olympus/images/icons_threat_nothing_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_protect_dark.svg b/client/public/themes/olympus/images/icons_threat_protect_dark.svg deleted file mode 100644 index 97c1deb0..00000000 --- a/client/public/themes/olympus/images/icons_threat_protect_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_protect_light.svg b/client/public/themes/olympus/images/icons_threat_protect_light.svg deleted file mode 100644 index a3ae6b88..00000000 --- a/client/public/themes/olympus/images/icons_threat_protect_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_retreat_dark.svg b/client/public/themes/olympus/images/icons_threat_retreat_dark.svg deleted file mode 100644 index cb31ee40..00000000 --- a/client/public/themes/olympus/images/icons_threat_retreat_dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icons_threat_retreat_light.svg b/client/public/themes/olympus/images/icons_threat_retreat_light.svg deleted file mode 100644 index e17d43f4..00000000 --- a/client/public/themes/olympus/images/icons_threat_retreat_light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/public/themes/olympus/images/icon_airbase_blue.svg b/client/public/themes/olympus/images/markers/airbase.svg similarity index 100% rename from client/public/themes/olympus/images/icon_airbase_blue.svg rename to client/public/themes/olympus/images/markers/airbase.svg diff --git a/client/public/themes/olympus/images/markers/bullseye.svg b/client/public/themes/olympus/images/markers/bullseye.svg new file mode 100644 index 00000000..92d0b60d --- /dev/null +++ b/client/public/themes/olympus/images/markers/bullseye.svg @@ -0,0 +1,43 @@ + + + + + + + + diff --git a/client/public/images/marker-icon.png b/client/public/themes/olympus/images/markers/marker-icon.png similarity index 100% rename from client/public/images/marker-icon.png rename to client/public/themes/olympus/images/markers/marker-icon.png diff --git a/client/public/images/marker-shadow.png b/client/public/themes/olympus/images/markers/marker-shadow.png similarity index 100% rename from client/public/images/marker-shadow.png rename to client/public/themes/olympus/images/markers/marker-shadow.png diff --git a/client/public/images/icon-temporary.png b/client/public/themes/olympus/images/markers/temporary-icon.png similarity index 100% rename from client/public/images/icon-temporary.png rename to client/public/themes/olympus/images/markers/temporary-icon.png diff --git a/client/public/images/splash/splash_pic_ship.png b/client/public/themes/olympus/images/splash/1.png similarity index 100% rename from client/public/images/splash/splash_pic_ship.png rename to client/public/themes/olympus/images/splash/1.png diff --git a/client/public/themes/olympus/images/state_idle.svg b/client/public/themes/olympus/images/state_idle.svg deleted file mode 100644 index 757ee216..00000000 --- a/client/public/themes/olympus/images/state_idle.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/state_rtb.svg b/client/public/themes/olympus/images/state_rtb.svg deleted file mode 100644 index f40e2627..00000000 --- a/client/public/themes/olympus/images/state_rtb.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/state_attack.svg b/client/public/themes/olympus/images/states/attack.svg similarity index 100% rename from client/public/themes/olympus/images/state_attack.svg rename to client/public/themes/olympus/images/states/attack.svg diff --git a/client/public/themes/olympus/images/state_dcs.svg b/client/public/themes/olympus/images/states/dcs.svg similarity index 100% rename from client/public/themes/olympus/images/state_dcs.svg rename to client/public/themes/olympus/images/states/dcs.svg diff --git a/client/public/themes/olympus/images/state_follow.svg b/client/public/themes/olympus/images/states/follow.svg similarity index 100% rename from client/public/themes/olympus/images/state_follow.svg rename to client/public/themes/olympus/images/states/follow.svg diff --git a/client/public/themes/olympus/images/state_human.svg b/client/public/themes/olympus/images/states/human.svg similarity index 100% rename from client/public/themes/olympus/images/state_human.svg rename to client/public/themes/olympus/images/states/human.svg diff --git a/client/public/themes/olympus/images/icon_hold_neutral.svg b/client/public/themes/olympus/images/states/idle.svg similarity index 100% rename from client/public/themes/olympus/images/icon_hold_neutral.svg rename to client/public/themes/olympus/images/states/idle.svg diff --git a/client/public/themes/olympus/images/state_refuel.svg b/client/public/themes/olympus/images/states/refuel.svg similarity index 100% rename from client/public/themes/olympus/images/state_refuel.svg rename to client/public/themes/olympus/images/states/refuel.svg diff --git a/client/public/themes/olympus/images/icon_rtb_red.svg b/client/public/themes/olympus/images/states/rtb.svg similarity index 100% rename from client/public/themes/olympus/images/icon_rtb_red.svg rename to client/public/themes/olympus/images/states/rtb.svg diff --git a/client/public/themes/olympus/images/task_tanker.svg b/client/public/themes/olympus/images/task_tanker.svg deleted file mode 100644 index 32ee5980..00000000 --- a/client/public/themes/olympus/images/task_tanker.svg +++ /dev/null @@ -1,1256 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/icon_aircraft_neutral_selected.svg b/client/public/themes/olympus/images/units/aircraft.svg similarity index 60% rename from client/public/themes/olympus/images/icon_aircraft_neutral_selected.svg rename to client/public/themes/olympus/images/units/aircraft.svg index 8dcdef70..104f9bcf 100644 --- a/client/public/themes/olympus/images/icon_aircraft_neutral_selected.svg +++ b/client/public/themes/olympus/images/units/aircraft.svg @@ -1,4 +1,4 @@ - + diff --git a/client/public/themes/olympus/images/units/bomb.svg b/client/public/themes/olympus/images/units/bomb.svg new file mode 100644 index 00000000..a38a168e --- /dev/null +++ b/client/public/themes/olympus/images/units/bomb.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icon_death_red.svg b/client/public/themes/olympus/images/units/death.svg similarity index 58% rename from client/public/themes/olympus/images/icon_death_red.svg rename to client/public/themes/olympus/images/units/death.svg index 11b521a1..c68ab1d1 100644 --- a/client/public/themes/olympus/images/icon_death_red.svg +++ b/client/public/themes/olympus/images/units/death.svg @@ -1,3 +1,3 @@ - + diff --git a/client/public/themes/olympus/images/icon_ground_blue_selected.svg b/client/public/themes/olympus/images/units/groundunit-other.svg similarity index 56% rename from client/public/themes/olympus/images/icon_ground_blue_selected.svg rename to client/public/themes/olympus/images/units/groundunit-other.svg index c3e77fbd..6b6dcc7c 100644 --- a/client/public/themes/olympus/images/icon_ground_blue_selected.svg +++ b/client/public/themes/olympus/images/units/groundunit-other.svg @@ -1,5 +1,5 @@ - - + + diff --git a/client/public/themes/olympus/images/units/groundunit-sam.svg b/client/public/themes/olympus/images/units/groundunit-sam.svg new file mode 100644 index 00000000..996af35d --- /dev/null +++ b/client/public/themes/olympus/images/units/groundunit-sam.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/themes/olympus/images/icon_missile_blue.svg b/client/public/themes/olympus/images/units/missile.svg similarity index 68% rename from client/public/themes/olympus/images/icon_missile_blue.svg rename to client/public/themes/olympus/images/units/missile.svg index 51124e12..d7711d7c 100644 --- a/client/public/themes/olympus/images/icon_missile_blue.svg +++ b/client/public/themes/olympus/images/units/missile.svg @@ -1,5 +1,5 @@ - + diff --git a/client/public/themes/olympus/images/units/navyunit.svg b/client/public/themes/olympus/images/units/navyunit.svg new file mode 100644 index 00000000..b3b2ed1b --- /dev/null +++ b/client/public/themes/olympus/images/units/navyunit.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/client/public/themes/olympus/images/icon_building_blue.svg b/client/public/themes/olympus/images/units/static.svg similarity index 59% rename from client/public/themes/olympus/images/icon_building_blue.svg rename to client/public/themes/olympus/images/units/static.svg index 7f86143a..ead61396 100644 --- a/client/public/themes/olympus/images/icon_building_blue.svg +++ b/client/public/themes/olympus/images/units/static.svg @@ -1,4 +1,5 @@ - + + diff --git a/client/public/themes/olympus/images/visibility_aircraft_hidden.svg b/client/public/themes/olympus/images/visibility_aircraft_hidden.svg deleted file mode 100644 index 7acbb8dd..00000000 --- a/client/public/themes/olympus/images/visibility_aircraft_hidden.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/visibility_aircraft_visible.svg b/client/public/themes/olympus/images/visibility_aircraft_visible.svg deleted file mode 100644 index 000472f4..00000000 --- a/client/public/themes/olympus/images/visibility_aircraft_visible.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/visibility_ground_hidden.svg b/client/public/themes/olympus/images/visibility_ground_hidden.svg deleted file mode 100644 index 4993ba3e..00000000 --- a/client/public/themes/olympus/images/visibility_ground_hidden.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/visibility_ground_visible.svg b/client/public/themes/olympus/images/visibility_ground_visible.svg deleted file mode 100644 index 4f14666c..00000000 --- a/client/public/themes/olympus/images/visibility_ground_visible.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/visibility_navyunit_hidden.svg b/client/public/themes/olympus/images/visibility_navyunit_hidden.svg deleted file mode 100644 index 48a521bb..00000000 --- a/client/public/themes/olympus/images/visibility_navyunit_hidden.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/visibility_navyunit_visible.svg b/client/public/themes/olympus/images/visibility_navyunit_visible.svg deleted file mode 100644 index bfba32a8..00000000 --- a/client/public/themes/olympus/images/visibility_navyunit_visible.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/visibility_sam_hidden.svg b/client/public/themes/olympus/images/visibility_sam_hidden.svg deleted file mode 100644 index cb9d0a10..00000000 --- a/client/public/themes/olympus/images/visibility_sam_hidden.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/visibility_sam_visible.svg b/client/public/themes/olympus/images/visibility_sam_visible.svg deleted file mode 100644 index 4beca510..00000000 --- a/client/public/themes/olympus/images/visibility_sam_visible.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/client/public/themes/olympus/images/visibility_threat_hidden.svg b/client/public/themes/olympus/images/visibility_threat_hidden.svg deleted file mode 100644 index 2fb993f1..00000000 --- a/client/public/themes/olympus/images/visibility_threat_hidden.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/visibility_threat_visible.svg b/client/public/themes/olympus/images/visibility_threat_visible.svg deleted file mode 100644 index 6a5580de..00000000 --- a/client/public/themes/olympus/images/visibility_threat_visible.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/olympus.css b/client/public/themes/olympus/olympus.css deleted file mode 100644 index ed623daa..00000000 --- a/client/public/themes/olympus/olympus.css +++ /dev/null @@ -1,226 +0,0 @@ -:root { - - /** Colours **/ - - /*** Coalition: neutral **/ - --primary-neutral : #949ba7; - --secondary-neutral-outline : #111111; - --secondary-neutral-text : #111111; - - /*** Coalition: blue **/ - --primary-blue : #247be2; - --secondary-blue-outline : #082e44; - --secondary-blue-text : #017DC1; - - /*** Coalition: red **/ - --primary-red : #ff5858; - --secondary-red-outline : #262222; - --secondary-red-text : #D42121; - - --accent-green : #8bff63; - --accent-light-blue : #5ca7ff; - --accent-light-red : #F5B6B6; - - --background-grey : #3d4651; - --background-slate-blue : #363c43; - --background-offwhite : #f2f2f3; - --background-steel : #202831; - - --secondary-dark-steel : #181e25; - --secondary-gunmetal-grey : #2f2f2f; - --secondary-light-grey : #797e83; - --secondary-yellow : #ffd46893; - - --background-hover : #f2f2f333; - - --nav-text : #ECECEC; - - - --ol-select-secondary: #545F6C; - - - /*** General border radii **/ - - --border-radius-xs : 2px; - --border-radius-sm : 5px; - --border-radius-md : 10px; - --border-radius-lg : 15px; - - - /*** Font stuff **/ - --font-weight-bolder : 600; - - - - /*** Navbar ***/ - - --visibility-control-aircraft-visible-url: url( "/themes/olympus/images/visibility_aircraft_visible.svg" ); - --visibility-control-aircraft-hidden-url: url( "/themes/olympus/images/visibility_aircraft_hidden.svg" ); - - --visibility-control-groundunit-visible-url: url( "/themes/olympus/images/visibility_ground_visible.svg" ); - --visibility-control-groundunit-hidden-url: url( "/themes/olympus/images/visibility_ground_hidden.svg" ); - - --visibility-control-sam-visible-url: url( "/themes/olympus/images/visibility_sam_visible.svg" ); - --visibility-control-sam-hidden-url: url( "/themes/olympus/images/visibility_sam_hidden.svg" ); - - --visibility-control-navyunit-visible-url: url( "/themes/olympus/images/visibility_navyunit_visible.svg" ); - --visibility-control-navyunit-hidden-url: url( "/themes/olympus/images/visibility_navyunit_hidden.svg" ); - - --visibility-control-threat-visible-url: url( "/themes/olympus/images/visibility_threat_visible.svg" ); - --visibility-control-threat-hidden-url: url( "/themes/olympus/images/visibility_threat_hidden.svg" ); - - - - /*** Unit marker settings ***/ - - - /*** All markers **/ - --unit-border-radius: var( --border-radius-xs ); - --unit-font-size: 14px; - --unit-font-weight: bolder; - --unit-height: 32px; - --unit-label-border-width: 2px; - --unit-spotlight-fill: var( --secondary-yellow ); - --unit-spotlight-radius: 26px; - --unit-stroke-width: 3px; - --unit-width: 32px; - - - /*** Air units ***/ - --unit-aircraft-ammo-gap: calc( 2px + var( --unit-stroke-width ) ); - --unit-aircraft-ammo-border-radius: 50%; - --unit-aircraft-ammo-border-width: 2px; - --unit-aircraft-ammo-radius: 2px; - --unit-aircraft-ammo-spacing: 2px; - --unit-aircraft-ammo-x:0px; - --unit-aircraft-ammo-y:30px; - --unit-aircraft-fuel-border-width: 2px; - --unit-aircraft-fuel-height: 6px; - --unit-aircraft-fuel-width: 36px; - --unit-aircraft-fuel-x:0px; - --unit-aircraft-fuel-y:22px; - --unit-aircraft-height: 28px; - --unit-aircraft-vvi-width: 4px; - --unit-aircraft-width: var( --unit-aircraft-height ); - - --unit-aircraft-marker-height: 50px; - --unit-aircraft-marker-width: 50px; - - --unit-aircraft-marker-blue-url: url( "/themes/olympus/images/icon_aircraft_blue.svg" ); - --unit-aircraft-marker-blue-hover-url: url( "/themes/olympus/images/icon_aircraft_blue_hover.svg" ); - --unit-aircraft-marker-blue-selected-url: url( "/themes/olympus/images/icon_aircraft_blue_selected.svg" ); - --unit-aircraft-marker-blue-dead-url: url( "/themes/olympus/images/icon_death_blue.svg" ); - - --unit-aircraft-marker-neutral-url: url( "/themes/olympus/images/icon_aircraft_neutral.svg" ); - --unit-aircraft-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aircraft_neutral_hover.svg" ); - --unit-aircraft-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aircraft_neutral_selected.svg" ); - --unit-aircraft-marker-neutral-dead-url: url( "/themes/olympus/images/icon_death_neutral.svg" ); - - --unit-aircraft-marker-red-url: url( "/themes/olympus/images/icon_aircraft_red.svg" ); - --unit-aircraft-marker-red-hover-url: url( "/themes/olympus/images/icon_aircraft_red_hover.svg" ); - --unit-aircraft-marker-red-selected-url: url( "/themes/olympus/images/icon_aircraft_red_selected.svg" ); - --unit-aircraft-marker-red-dead-url: url( "/themes/olympus/images/icon_death_red.svg" ); - - - /*** Air units' states ***/ - - --unit-aircraft-state-height: 50px; - --unit-aircraft-state-width: 50px; - - --unit-aircraft-state-rtb: url( "/themes/olympus/images/state_rtb.svg" ); - --unit-aircraft-state-idle: url( "/themes/olympus/images/state_idle.svg" ); - --unit-aircraft-state-attack: url( "/themes/olympus/images/state_attack.svg" ); - --unit-aircraft-state-follow: url( "/themes/olympus/images/state_follow.svg" ); - --unit-aircraft-state-refuel: url( "/themes/olympus/images/state_refuel.svg" ); - --unit-aircraft-state-human: url( "/themes/olympus/images/state_human.svg" ); - --unit-aircraft-state-dcs: url( "/themes/olympus/images/state_dcs.svg" ); - - /*** Ground ***/ - --unit-groundunit-marker-height: 50px; - --unit-groundunit-marker-width: 50px; - - --unit-groundunit-marker-blue-url: url( "/themes/olympus/images/icon_ground_blue.svg" ); - --unit-groundunit-marker-blue-hover-url: url( "/themes/olympus/images/icon_ground_blue_hover.svg" ); - --unit-groundunit-marker-blue-selected-url: url( "/themes/olympus/images/icon_ground_blue_selected.svg" ); - - --unit-groundunit-marker-neutral-url: url( "/themes/olympus/images/icon_ground_neutral.svg" ); - --unit-groundunit-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ground_neutral_hover.svg" ); - --unit-groundunit-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ground_neutral_selected.svg" ); - - --unit-groundunit-marker-red-url: url( "/themes/olympus/images/icon_ground_red.svg" ); - --unit-groundunit-marker-red-hover-url: url( "/themes/olympus/images/icon_ground_red_hover.svg" ); - --unit-groundunit-marker-red-selected-url: url( "/themes/olympus/images/icon_ground_red_selected.svg" ); - - - /*** SAMs ***/ - --unit-sam-marker-height: 50px; - --unit-sam-marker-width: 50px; - - --unit-sam-marker-blue-url: url( "/themes/olympus/images/icon_aa_blue.svg" ); - --unit-sam-marker-blue-hover-url: url( "/themes/olympus/images/icon_aa_blue_hover.svg" ); - --unit-sam-marker-blue-selected-url: url( "/themes/olympus/images/icon_aa_blue_selected.svg" ); - - --unit-sam-marker-neutral-url: url( "/themes/olympus/images/icon_aa_neutral.svg" ); - --unit-sam-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aa_neutral_hover.svg" ); - --unit-sam-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aa_neutral_selected.svg" ); - - --unit-sam-marker-red-url: url( "/themes/olympus/images/icon_aa_red.svg" ); - --unit-sam-marker-red-hover-url: url( "/themes/olympus/images/icon_aa_red_hover.svg" ); - --unit-sam-marker-red-selected-url: url( "/themes/olympus/images/icon_aa_red_selected.svg" ); - - - /*** navyunit ***/ - --unit-navyunit-marker-height: 50px; - --unit-navyunit-marker-width: 50px; - - --unit-navyunit-marker-blue-url: url( "/themes/olympus/images/icon_ship_blue.svg" ); - --unit-navyunit-marker-blue-hover-url: url( "/themes/olympus/images/icon_ship_blue_hover.svg" ); - --unit-navyunit-marker-blue-selected-url: url( "/themes/olympus/images/icon_ship_blue_selected.svg" ); - - --unit-navyunit-marker-neutral-url: url( "/themes/olympus/images/icon_ship_neutral.svg" ); - --unit-navyunit-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ship_neutral_hover.svg" ); - --unit-navyunit-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ship_neutral_selected.svg" ); - - --unit-navyunit-marker-red-url: url( "/themes/olympus/images/icon_ship_red.svg" ); - --unit-navyunit-marker-red-hover-url: url( "/themes/olympus/images/icon_ship_red_hover.svg" ); - --unit-navyunit-marker-red-selected-url: url( "/themes/olympus/images/icon_ship_red_selected.svg" ); - - - /*** Building ***/ - --unit-building-marker-height: 50px; - --unit-building-marker-width: 50px; - - --unit-building-marker-blue-url: url( "/themes/olympus/images/icon_building_blue.svg" ); - --unit-building-marker-neutral-url: url( "/themes/olympus/images/icon_building_neutral.svg" ); - --unit-building-marker-red-url: url( "/themes/olympus/images/icon_building_red.svg" ); - - - /*** Weapons ***/ - --unit-missile-marker-height: 50px; - --unit-missile-marker-width: 50px; - - --unit-missile-marker-blue-url: url( "/themes/olympus/images/icon_missile_blue.svg" ); - --unit-missile-marker-neutral-url: url( "/themes/olympus/images/icon_missile_neutral.svg" ); - --unit-missile-marker-red-url: url( "/themes/olympus/images/icon_missile_red.svg" ); - - --unit-bomb-marker-height: 50px; - --unit-bomb-marker-width: 50px; - - --unit-bomb-marker-blue-url: url( "/themes/olympus/images/icon_bomb_blue.svg" ); - --unit-bomb-marker-neutral-url: url( "/themes/olympus/images/icon_bomb_neutral.svg" ); - --unit-bomb-marker-red-url: url( "/themes/olympus/images/icon_bomb_red.svg" ); - - - /*** Context menu ***/ - --spawn-aircraft-url: url( "/themes/olympus/images/spawn_aircraft.svg" ); - --spawn-groundunit-url: url( "/themes/olympus/images/spawn_ground.svg" ); - --spawn-smoke-url: url( "/themes/olympus/images/spawn_smoke.svg" ); - - /*** Airbase ***/ - --airbase-marker-height: 63px; - --airbase-marker-width: 63px; - - --airbase-marker-blue-url: url( "/themes/olympus/images/icon_airbase_blue.svg" ); - --airbase-marker-neutral-url: url( "/themes/olympus/images/icon_airbase_neutral.svg" ); - --airbase-marker-red-url: url( "/themes/olympus/images/icon_airbase_red.svg" ); -} \ No newline at end of file diff --git a/client/public/themes/olympus/theme.css b/client/public/themes/olympus/theme.css new file mode 100644 index 00000000..a7b402af --- /dev/null +++ b/client/public/themes/olympus/theme.css @@ -0,0 +1,79 @@ +:root { + /** Colours **/ + + /*** Coalition: neutral ***/ + --primary-neutral: #949ba7; + --secondary-neutral-outline: #111111; + --secondary-neutral-text: #111111; + --unit-background-neutral: #CFD9E8; + + /*** Coalition: blue ***/ + --primary-blue: #247be2; + --secondary-blue-outline: #082e44; + --secondary-blue-text: #017DC1; + --unit-background-blue: #3BB9FF; + + /*** Coalition: red ***/ + --primary-red: #ff5858; + --secondary-red-outline: #262222; + --secondary-red-text: #D42121; + --unit-background-red: #FF5858; + + /*** UI Colours **/ + --accent-green: #8bff63; + --accent-light-blue: #5ca7ff; + --accent-light-red: #F5B6B6; + + --background-grey: #3d4651; + --background-slate-blue: #363c43; + --background-offwhite: #f2f2f3; + --background-steel: #202831; + + --secondary-dark-steel: #181e25; + --secondary-gunmetal-grey: #2f2f2f; + --secondary-light-grey: #797e83; + --secondary-yellow: #ffd46893; + + --background-hover: #f2f2f333; + + --nav-text: #ECECEC; + + --ol-select-secondary: #545F6C; + + /*** General border radii **/ + --border-radius-xs: 2px; + --border-radius-sm: 5px; + --border-radius-md: 10px; + --border-radius-lg: 15px; + + /*** Fonts **/ + --font-weight-bolder: 600; + + /*** Unit marker settings ***/ + /*** All markers **/ + --unit-border-radius: var(--border-radius-xs); + --unit-font-size: 14px; + --unit-font-weight: bolder; + --unit-label-border-width: 2px; + --unit-spotlight-fill: var(--secondary-yellow); + --unit-spotlight-radius: 26px; + --unit-stroke-width: 3px; + --unit-height: 50px; + --unit-width: 50px; + + /*** Air units ***/ + --unit-aircraft-ammo-gap: calc(2px + var(--unit-stroke-width)); + --unit-aircraft-ammo-border-radius: 50%; + --unit-aircraft-ammo-border-width: 2px; + --unit-aircraft-ammo-radius: 2px; + --unit-aircraft-ammo-spacing: 2px; + --unit-aircraft-ammo-x: 0px; + --unit-aircraft-ammo-y: 30px; + --unit-aircraft-fuel-border-width: 2px; + --unit-aircraft-fuel-height: 6px; + --unit-aircraft-fuel-width: 36px; + --unit-aircraft-fuel-x: 0px; + --unit-aircraft-fuel-y: 22px; + --unit-aircraft-height: 28px; + --unit-aircraft-vvi-width: 4px; +} \ No newline at end of file diff --git a/client/routes/resources.js b/client/routes/resources.js new file mode 100644 index 00000000..2be3af2f --- /dev/null +++ b/client/routes/resources.js @@ -0,0 +1,10 @@ +const express = require('express'); +const router = express.Router(); + +var theme = "olympus"; + +router.get('/theme/*', function (req, res, next) { + res.redirect(req.url.replace("theme", "themes/" + theme)); +}); + +module.exports = router; diff --git a/client/src/@types/server.d.ts b/client/src/@types/server.d.ts index e46d5f8a..e1a9c3e9 100644 --- a/client/src/@types/server.d.ts +++ b/client/src/@types/server.d.ts @@ -8,7 +8,7 @@ interface AirbasesData { } interface BullseyesData { - bullseyes: {[key: string]: any}, + bullseyes: {[key: string]: {latitude: number, longitude: number, coalition: string}}, } interface LogData { diff --git a/client/src/@types/unit.d.ts b/client/src/@types/unit.d.ts index f3741e27..e6b1b345 100644 --- a/client/src/@types/unit.d.ts +++ b/client/src/@types/unit.d.ts @@ -79,4 +79,16 @@ interface GeneralSettings { prohibitAG: boolean; prohibitAfterburner: boolean; prohibitAirWpn: boolean; +} + +interface UnitIconOptions { + showState: boolean, + showVvi: boolean, + showHotgroup: boolean, + showUnitIcon: boolean, + showShortLabel: boolean, + showFuel: boolean, + showAmmo: boolean, + showSummary: boolean, + rotateToHeading: boolean } \ No newline at end of file diff --git a/client/src/aic/aic.ts b/client/src/aic/aic.ts index 770fd695..2aaf8a1c 100644 --- a/client/src/aic/aic.ts +++ b/client/src/aic/aic.ts @@ -1,4 +1,4 @@ -import { ToggleableFeature } from "../toggleablefeature"; +import { ToggleableFeature } from "../features/toggleablefeature"; import { AICFormation_Azimuth } from "./aicformation/azimuth"; import { AICFormation_Range } from "./aicformation/range"; import { AICFormation_Single } from "./aicformation/single"; diff --git a/client/src/units/unitdatatable.ts b/client/src/atc/unitdatatable.ts similarity index 97% rename from client/src/units/unitdatatable.ts rename to client/src/atc/unitdatatable.ts index e54b541c..3b0b97b8 100644 --- a/client/src/units/unitdatatable.ts +++ b/client/src/atc/unitdatatable.ts @@ -1,6 +1,6 @@ import { getUnitsManager } from ".."; import { Panel } from "../panels/panel"; -import { Unit } from "./unit"; +import { Unit } from "../units/unit"; export class UnitDataTable extends Panel { constructor(id: string) { diff --git a/client/src/controls/airbasecontextmenu.ts b/client/src/controls/airbasecontextmenu.ts index d94f17db..bb5e7f29 100644 --- a/client/src/controls/airbasecontextmenu.ts +++ b/client/src/controls/airbasecontextmenu.ts @@ -5,8 +5,7 @@ import { ContextMenu } from "./contextmenu"; export class AirbaseContextMenu extends ContextMenu { #airbase: Airbase | null = null; - constructor(id: string) - { + constructor(id: string) { super(id); document.addEventListener("contextMenuSpawnAirbase", (e: any) => { this.showSpawnMenu(); @@ -19,8 +18,7 @@ export class AirbaseContextMenu extends ContextMenu { }) } - setAirbase(airbase: Airbase) - { + setAirbase(airbase: Airbase) { this.#airbase = airbase; this.setName(airbase.getName()); this.setProperties(airbase.getProperties()); @@ -29,24 +27,21 @@ export class AirbaseContextMenu extends ContextMenu { this.enableLandButton(getUnitsManager().getSelectedUnitsType() === "Aircraft" && (getUnitsManager().getSelectedUnitsCoalition() === airbase.getCoalition() || airbase.getCoalition() === "neutral")) } - setName(airbaseName: string) - { + setName(airbaseName: string) { var nameDiv = this.getContainer()?.querySelector("#airbase-name"); if (nameDiv != null) - nameDiv.innerText = airbaseName; + nameDiv.innerText = airbaseName; } - setProperties(airbaseProperties: string[]) - { + setProperties(airbaseProperties: string[]) { this.getContainer()?.querySelector("#airbase-properties")?.replaceChildren(...airbaseProperties.map((property: string) => { var div = document.createElement("div"); div.innerText = property; return div; - }), ); + }),); } - setParkings(airbaseParkings: string[]) - { + setParkings(airbaseParkings: string[]) { this.getContainer()?.querySelector("#airbase-parking")?.replaceChildren(...airbaseParkings.map((parking: string) => { var div = document.createElement("div"); div.innerText = parking; @@ -54,22 +49,18 @@ export class AirbaseContextMenu extends ContextMenu { })); } - setCoalition(coalition: string) - { + setCoalition(coalition: string) { (this.getContainer()?.querySelector("#spawn-airbase-aircraft-button")).dataset.activeCoalition = coalition; } - enableLandButton(enableLandButton: boolean) - { + enableLandButton(enableLandButton: boolean) { this.getContainer()?.querySelector("#land-here-button")?.classList.toggle("hide", !enableLandButton); } - showSpawnMenu() - { - if (this.#airbase != null) - { + showSpawnMenu() { + if (this.#airbase != null) { setActiveCoalition(this.#airbase.getCoalition()); - getMap().showMapContextMenu({originalEvent: {x: this.getX(), y: this.getY(), latlng: this.getLatLng()}}); + getMap().showMapContextMenu({ originalEvent: { x: this.getX(), y: this.getY(), latlng: this.getLatLng() } }); getMap().getMapContextMenu().hideUpperBar(); getMap().getMapContextMenu().showSubMenu("aircraft"); getMap().getMapContextMenu().setAirbaseName(this.#airbase.getName()); diff --git a/client/src/controls/contextmenu.ts b/client/src/controls/contextmenu.ts index 9a19562f..58cf371f 100644 --- a/client/src/controls/contextmenu.ts +++ b/client/src/controls/contextmenu.ts @@ -23,28 +23,23 @@ export class ContextMenu { this.#container?.classList.toggle("hide", true); } - getContainer() - { + getContainer() { return this.#container; } - getLatLng() - { + getLatLng() { return this.#latlng; } - getX() - { + getX() { return this.#x; } - getY() - { + getY() { return this.#y; } - clip() - { + clip() { if (this.#container != null) { if (this.#x + this.#container.offsetWidth < window.innerWidth) this.#container.style.left = this.#x + "px"; diff --git a/client/src/controls/dropdown.ts b/client/src/controls/dropdown.ts index cb96e4c0..502f1481 100644 --- a/client/src/controls/dropdown.ts +++ b/client/src/controls/dropdown.ts @@ -7,17 +7,16 @@ export class Dropdown { #optionsList: string[] = []; #index: number = 0; - constructor(ID: string, callback: CallableFunction, options: string[] | null = null) - { - this.#element = document.getElementById(ID); - this.#options = this.#element.querySelector(".ol-select-options"); - this.#value = this.#element.querySelector(".ol-select-value"); + constructor(ID: string, callback: CallableFunction, options: string[] | null = null) { + this.#element = document.getElementById(ID); + this.#options = this.#element.querySelector(".ol-select-options"); + this.#value = this.#element.querySelector(".ol-select-value"); this.#defaultValue = this.#value.innerText; - this.#callback = callback; + this.#callback = callback; if (options != null) { this.setOptions(options); - } + } this.#value.addEventListener("click", (ev) => { this.#element.classList.toggle("is-open"); @@ -31,12 +30,11 @@ export class Dropdown { } }); - this.#options.classList.add( "ol-scrollable" ); + this.#options.classList.add("ol-scrollable"); } - setOptions(optionsList: string[]) - { - this.#optionsList = optionsList; + setOptions(optionsList: string[], sortAlphabetically: boolean = true) { + this.#optionsList = optionsList.sort(); this.#options.replaceChildren(...optionsList.map((option: string, idx: number) => { var div = document.createElement("div"); var button = document.createElement("button"); @@ -48,7 +46,9 @@ export class Dropdown { button.addEventListener("click", (e: MouseEvent) => { e.stopPropagation(); - this.#value.innerHTML = `
${option}
`; + this.#value = document.createElement("div"); + this.#value.classList.add("ol-ellipsed"); + this.#value.innerText = option; this.#close(); this.#callback(option, e); this.#index = idx; @@ -57,21 +57,21 @@ export class Dropdown { })); } - selectText( text:string ) { - - const index = [].slice.call( this.#options.children ).findIndex( ( opt:Element ) => opt.querySelector( "button" )?.innerText === text ); - if ( index > -1 ) { - this.selectValue( index ); + selectText(text: string) { + const index = [].slice.call(this.#options.children).findIndex((opt: Element) => opt.querySelector("button")?.innerText === text); + if (index > -1) { + this.selectValue(index); } - } - selectValue(idx: number) - { - if (idx < this.#optionsList.length) - { + selectValue(idx: number) { + if (idx < this.#optionsList.length) { var option = this.#optionsList[idx]; - this.#value.innerHTML = `
${option}
`; + var el = document.createElement("div"); + el.classList.add("ol-ellipsed"); + el.innerText = option; + this.#value.replaceChildren(); + this.#value.appendChild(el); this.#index = idx; this.#close(); this.#callback(option); @@ -91,8 +91,8 @@ export class Dropdown { } setValue(value: string) { - var index = this.#optionsList.findIndex((option) => {return option === value}); - if (index > -1) + var index = this.#optionsList.findIndex((option) => { return option === value }); + if (index > -1) this.selectValue(index); } @@ -102,21 +102,21 @@ export class Dropdown { #clip() { const options = this.#options; - const bounds = options.getBoundingClientRect(); - this.#element.dataset.position = ( bounds.bottom > window.innerHeight ) ? "top" : ""; + const bounds = options.getBoundingClientRect(); + this.#element.dataset.position = (bounds.bottom > window.innerHeight) ? "top" : ""; } #close() { - this.#element.classList.remove( "is-open" ); + this.#element.classList.remove("is-open"); this.#element.dataset.position = ""; } #open() { - this.#element.classList.add( "is-open" ); + this.#element.classList.add("is-open"); } #toggle() { - if ( this.#element.classList.contains( "is-open" ) ) { + if (this.#element.classList.contains("is-open")) { this.#close(); } else { this.#open(); diff --git a/client/src/controls/mapcontextmenu.ts b/client/src/controls/mapcontextmenu.ts index 929dad05..f381ca79 100644 --- a/client/src/controls/mapcontextmenu.ts +++ b/client/src/controls/mapcontextmenu.ts @@ -41,8 +41,7 @@ export class MapContextMenu extends ContextMenu { document.addEventListener("contextMenuDeployAircraft", () => { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); - if (this.#spawnOptions) - { + if (this.#spawnOptions) { getMap().addTemporaryMarker(this.#spawnOptions.latlng); spawnAircraft(this.#spawnOptions); } @@ -51,8 +50,7 @@ export class MapContextMenu extends ContextMenu { document.addEventListener("contextMenuDeployGroundUnit", () => { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); - if (this.#spawnOptions) - { + if (this.#spawnOptions) { getMap().addTemporaryMarker(this.#spawnOptions.latlng); spawnGroundUnit(this.#spawnOptions); } @@ -189,10 +187,8 @@ export class MapContextMenu extends ContextMenu { this.#spawnOptions.role = role; this.#resetGroundUnitType(); - const types = groundUnitsDatabase.getByRole(role).map((blueprint) => { return blueprint.label } ); - types.sort(); - - this.#groundUnitTypeDropdown.setOptions( types ); + const types = groundUnitsDatabase.getByRole(role).map((blueprint) => { return blueprint.label }); + this.#groundUnitTypeDropdown.setOptions(types); this.#groundUnitTypeDropdown.selectValue(0); this.clip(); } @@ -204,9 +200,7 @@ export class MapContextMenu extends ContextMenu { this.#groundUnitTypeDropdown.reset(); const roles = groundUnitsDatabase.getRoles(); - roles.sort(); - - this.#groundUnitRoleDropdown.setOptions( roles ); + this.#groundUnitRoleDropdown.setOptions(roles); this.clip(); } diff --git a/client/src/controls/slider.ts b/client/src/controls/slider.ts index 7cf185cc..e8070d2e 100644 --- a/client/src/controls/slider.ts +++ b/client/src/controls/slider.ts @@ -23,8 +23,7 @@ export class Slider { if (this.#container != null) { this.#display = this.#container.style.display; this.#slider = this.#container.querySelector("input"); - if (this.#slider != null) - { + if (this.#slider != null) { this.#slider.addEventListener("input", (e: any) => this.#onInput()); this.#slider.addEventListener("mousedown", (e: any) => this.#onStart()); this.#slider.addEventListener("mouseup", (e: any) => this.#onFinalize()); @@ -33,93 +32,77 @@ export class Slider { } } - show() - { + show() { if (this.#container != null) this.#container.style.display = this.#display; } - hide() - { + hide() { if (this.#container != null) this.#container.style.display = 'none'; } - setActive(newActive: boolean) - { - if (this.#container && !this.#dragged) - { + setActive(newActive: boolean) { + if (this.#container && !this.#dragged) { this.#container.classList.toggle("active", newActive); if (!newActive && this.#valueText != null) this.#valueText.innerText = "Mixed values"; } } - setMinMax(newMinValue: number, newMaxValue: number) - { + setMinMax(newMinValue: number, newMaxValue: number) { this.#minValue = newMinValue; this.#maxValue = newMaxValue; this.#updateMax(); } - setIncrement(newIncrement: number) - { + setIncrement(newIncrement: number) { this.#increment = newIncrement; this.#updateMax(); } - setValue(newValue: number) - { + setValue(newValue: number) { // Disable value setting if the user is dragging the element - if (!this.#dragged) - { + if (!this.#dragged) { this.#value = newValue; if (this.#slider != null) - this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max)); + this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max)); this.#onValue() } } - getValue() - { + getValue() { return this.#value; } - getDragged() - { + getDragged() { return this.#dragged; } - #updateMax() - { + #updateMax() { var oldValue = this.getValue(); if (this.#slider != null) this.#slider.max = String((this.#maxValue - this.#minValue) / this.#increment); this.setValue(oldValue); } - #onValue() - { + #onValue() { if (this.#valueText != null && this.#slider != null) - this.#valueText.innerHTML = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit + this.#valueText.innerText = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit this.setActive(true); } - #onInput() - { + #onInput() { this.#onValue(); } - #onStart() - { + #onStart() { this.#dragged = true; } - #onFinalize() - { + #onFinalize() { this.#dragged = false; - if (this.#slider != null) - { + if (this.#slider != null) { this.#value = this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue); this.#callback(this.getValue()); } diff --git a/client/src/controls/unitcontextmenu.ts b/client/src/controls/unitcontextmenu.ts index aaa1b205..4acbaf3e 100644 --- a/client/src/controls/unitcontextmenu.ts +++ b/client/src/controls/unitcontextmenu.ts @@ -1,4 +1,3 @@ -import { getUnitsManager } from ".."; import { deg2rad } from "../other/utils"; import { ContextMenu } from "./contextmenu"; @@ -10,21 +9,19 @@ export class UnitContextMenu extends ContextMenu { document.addEventListener("applyCustomFormation", () => { var dialog = document.getElementById("custom-formation-dialog"); - if (dialog) - { + if (dialog) { dialog.classList.add("hide"); var clock = 1; - while (clock < 8) - { - if (( dialog.querySelector(`#formation-${clock}`)).checked) + while (clock < 8) { + if ((dialog.querySelector(`#formation-${clock}`)).checked) break clock++; } var angleDeg = 360 - (clock - 1) * 45; var angleRad = deg2rad(angleDeg); - var distance = parseInt(( dialog.querySelector(`#distance`)?.querySelector("input")).value) * 0.3048; - var upDown = parseInt(( dialog.querySelector(`#up-down`)?.querySelector("input")).value) * 0.3048; - + var distance = parseInt((dialog.querySelector(`#distance`)?.querySelector("input")).value) * 0.3048; + var upDown = parseInt((dialog.querySelector(`#up-down`)?.querySelector("input")).value) * 0.3048; + // X: front-rear, positive front // Y: top-bottom, positive top // Z: left-right, positive right @@ -34,7 +31,7 @@ export class UnitContextMenu extends ContextMenu { var z = distance * Math.sin(angleRad); if (this.#customFormationCallback) - this.#customFormationCallback({"x": x, "y": y, "z": z}) + this.#customFormationCallback({ "x": x, "y": y, "z": z }) } }) } @@ -43,13 +40,16 @@ export class UnitContextMenu extends ContextMenu { this.#customFormationCallback = callback; } - setOptions(options: {[key: string]: string}, callback: CallableFunction) - { - this.getContainer()?.replaceChildren(...Object.keys(options).map((option: string, idx: number) => - { + setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) { + this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => { + const option = options[key]; var button = document.createElement("button"); - button.innerHTML = options[option]; - button.addEventListener("click", () => callback(option)); + var el = document.createElement("div"); + el.title = option.tooltip; + el.innerText = option.text; + el.id = key; + button.addEventListener("click", () => callback(key)); + button.appendChild(el); return (button); })); } diff --git a/client/src/featureswitches.ts b/client/src/features/featureswitches.ts similarity index 66% rename from client/src/featureswitches.ts rename to client/src/features/featureswitches.ts index 600a17a2..a7cf1c30 100644 --- a/client/src/featureswitches.ts +++ b/client/src/features/featureswitches.ts @@ -23,7 +23,7 @@ class FeatureSwitch { userPreference; - constructor( config:FeatureSwitchInterface ) { + constructor(config: FeatureSwitchInterface) { this.defaultEnabled = config.defaultEnabled; this.forceState = config.forceState; @@ -38,9 +38,9 @@ class FeatureSwitch { getUserPreference() { - let preferences = JSON.parse( localStorage.getItem( "featureSwitches" ) || "{}" ); + let preferences = JSON.parse(localStorage.getItem("featureSwitches") || "{}"); - return ( preferences.hasOwnProperty( this.name ) ) ? preferences[ this.name ] : this.defaultEnabled; + return (preferences.hasOwnProperty(this.name)) ? preferences[this.name] : this.defaultEnabled; } @@ -62,7 +62,7 @@ class FeatureSwitch { export class FeatureSwitches { - #featureSwitches:FeatureSwitch[] = [ + #featureSwitches: FeatureSwitch[] = [ new FeatureSwitch({ "defaultEnabled": false, @@ -70,7 +70,7 @@ export class FeatureSwitches { "label": "AIC", "name": "aic" }), - + new FeatureSwitch({ "defaultEnabled": false, "forceState": -1, @@ -78,21 +78,21 @@ export class FeatureSwitches { "name": "ai-formations", "removeArtifactsIfDisabled": false }), - + new FeatureSwitch({ "defaultEnabled": false, "forceState": 1, "label": "ATC", "name": "atc" }), - + new FeatureSwitch({ "defaultEnabled": false, "forceState": -1, "label": "Force show unit control panel", "name": "forceShowUnitControlPanel" }), - + new FeatureSwitch({ "defaultEnabled": true, "forceState": -1, @@ -112,41 +112,41 @@ export class FeatureSwitches { } - getSwitch( switchName:string ) { + getSwitch(switchName: string) { - return this.#featureSwitches.find( featureSwitch => featureSwitch.name === switchName ); + return this.#featureSwitches.find(featureSwitch => featureSwitch.name === switchName); } #testSwitches() { - for ( const featureSwitch of this.#featureSwitches ) { - if ( featureSwitch.isEnabled() ) { - if ( typeof featureSwitch.onEnabled === "function" ) { + for (const featureSwitch of this.#featureSwitches) { + if (featureSwitch.isEnabled()) { + if (typeof featureSwitch.onEnabled === "function") { featureSwitch.onEnabled(); } } else { - document.querySelectorAll( "[data-feature-switch='" + featureSwitch.name + "']" ).forEach( el => { - if ( featureSwitch.removeArtifactsIfDisabled === false ) { + document.querySelectorAll("[data-feature-switch='" + featureSwitch.name + "']").forEach(el => { + if (featureSwitch.removeArtifactsIfDisabled === false) { el.remove(); } else { - el.classList.add( "hide" ); + el.classList.add("hide"); } }); } - document.body.classList.toggle( "feature-" + featureSwitch.name, featureSwitch.isEnabled() ); + document.body.classList.toggle("feature-" + featureSwitch.name, featureSwitch.isEnabled()); } } savePreferences() { - let preferences:any = {}; + let preferences: any = {}; - for ( const featureSwitch of this.#featureSwitches ) { - preferences[ featureSwitch.name ] = featureSwitch.isEnabled(); + for (const featureSwitch of this.#featureSwitches) { + preferences[featureSwitch.name] = featureSwitch.isEnabled(); } - localStorage.setItem( "featureSwitches", JSON.stringify( preferences ) ); + localStorage.setItem("featureSwitches", JSON.stringify(preferences)); } diff --git a/client/src/toggleablefeature.ts b/client/src/features/toggleablefeature.ts similarity index 60% rename from client/src/toggleablefeature.ts rename to client/src/features/toggleablefeature.ts index 5873fb6e..09f1723e 100644 --- a/client/src/toggleablefeature.ts +++ b/client/src/features/toggleablefeature.ts @@ -1,9 +1,9 @@ export abstract class ToggleableFeature { - #status:boolean = false; + #status: boolean = false; - constructor( defaultStatus:boolean ) { + constructor(defaultStatus: boolean) { this.#status = defaultStatus; @@ -12,17 +12,17 @@ export abstract class ToggleableFeature { } - getStatus() : boolean { + getStatus(): boolean { return this.#status; } - protected onStatusUpdate() {} + protected onStatusUpdate() { } - toggleStatus( force?:boolean ) : void { + toggleStatus(force?: boolean): void { - if ( force ) { + if (force) { this.#status = force; } else { this.#status = !this.#status; diff --git a/client/src/index.ts b/client/src/index.ts index 436b3838..c2f8a1b6 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -7,10 +7,10 @@ import { UnitControlPanel } from "./panels/unitcontrolpanel"; import { MouseInfoPanel } from "./panels/mouseinfopanel"; import { AIC } from "./aic/aic"; import { ATC } from "./atc/atc"; -import { FeatureSwitches } from "./featureswitches"; +import { FeatureSwitches } from "./features/featureswitches"; import { LogPanel } from "./panels/logpanel"; import { getConfig, getPaused, setAddress, setCredentials, setPaused, startUpdate, toggleDemoEnabled } from "./server/server"; -import { UnitDataTable } from "./units/unitdatatable"; +import { UnitDataTable } from "./atc/unitdatatable"; import { keyEventWasInInput } from "./other/utils"; import { Popup } from "./popups/popup"; import { Dropdown } from "./controls/dropdown"; @@ -140,28 +140,14 @@ function setupEvents() { case "Space": setPaused(!getPaused()); break; - case "KeyW": - case "KeyA": - case "KeyS": - case "KeyD": - case "ArrowLeft": - case "ArrowRight": - case "ArrowUp": - case "ArrowDown": + case "KeyW": case "KeyA": case "KeyS": case "KeyD": + case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown": getMap().handleMapPanning(ev); break; - case "Digit1": - case "Digit2": - case "Digit3": - case "Digit4": - case "Digit5": - case "Digit6": - case "Digit7": - case "Digit8": - case "Digit9": + case "Digit1": case "Digit2": case "Digit3": case "Digit4": case "Digit5": case "Digit6": case "Digit7": case "Digit8": case "Digit9": // Using the substring because the key will be invalid when pressing the Shift key if (ev.ctrlKey && ev.shiftKey) - getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5))); + getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5))); else if (ev.ctrlKey && !ev.shiftKey) getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5))); else @@ -176,14 +162,7 @@ function setupEvents() { return; } switch (ev.code) { - case "KeyW": - case "KeyA": - case "KeyS": - case "KeyD": - case "ArrowLeft": - case "ArrowRight": - case "ArrowUp": - case "ArrowDown": + case "KeyW": case "KeyA": case "KeyS": case "KeyD": case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown": getMap().handleMapPanning(ev); break; } @@ -201,8 +180,8 @@ function setupEvents() { document.addEventListener("tryConnection", () => { const form = document.querySelector("#splash-content")?.querySelector("#authentication-form"); - const username = ( (form?.querySelector("#username"))).value; - const password = ( (form?.querySelector("#password"))).value; + const username = ((form?.querySelector("#username"))).value; + const password = ((form?.querySelector("#password"))).value; setCredentials(username, btoa("admin" + ":" + password)); /* Start periodically requesting updates */ @@ -214,6 +193,7 @@ function setupEvents() { document.addEventListener("reloadPage", () => { location.reload(); }) + } export function getMap() { diff --git a/client/src/map/boxselect.ts b/client/src/map/boxselect.ts index b285c10a..2ea92fd8 100644 --- a/client/src/map/boxselect.ts +++ b/client/src/map/boxselect.ts @@ -1,10 +1,10 @@ import { Map } from 'leaflet'; -import { Handler} 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'; +import { Bounds } from 'leaflet'; export var BoxSelect = Handler.extend({ initialize: function (map: Map) { @@ -82,12 +82,12 @@ export var BoxSelect = Handler.extend({ this._point = this._map.mouseEventToContainerPoint(e); var bounds = new Bounds(this._point, this._startPoint), - size = bounds.getSize(); + size = bounds.getSize(); if (bounds.min != undefined) DomUtil.setPosition(this._box, bounds.min); - this._box.style.width = size.x + 'px'; + this._box.style.width = size.x + 'px'; this._box.style.height = size.y + 'px'; }, @@ -113,7 +113,7 @@ export var BoxSelect = Handler.extend({ if ((e.which !== 1) && (e.button !== 0)) { return; } this._finish(); - + if (!this._moved) { return; } // Postpone to next JS tick so internal click event handling // still see it as "moved". @@ -121,8 +121,8 @@ export var BoxSelect = Handler.extend({ var bounds = new LatLngBounds( this._map.containerPointToLatLng(this._startPoint), this._map.containerPointToLatLng(this._point)); - - this._map.fire('selectionend', {selectionBounds: bounds}); + + this._map.fire('selectionend', { selectionBounds: bounds }); }, _onKeyDown: function (e: any) { diff --git a/client/src/map/clickableminimap.ts b/client/src/map/clickableminimap.ts new file mode 100644 index 00000000..00104f7e --- /dev/null +++ b/client/src/map/clickableminimap.ts @@ -0,0 +1,12 @@ +import { MiniMap, MiniMapOptions } from "leaflet-control-mini-map"; + +export class ClickableMiniMap extends MiniMap { + constructor(layer: L.TileLayer | L.LayerGroup, options?: MiniMapOptions) { + super(layer, options); + } + + getMap() { + //@ts-ignore needed to access not exported member. A bit of a hack, required to access click events //TODO: fix me + return this._miniMap; + } +} \ No newline at end of file diff --git a/client/src/map/custommarker.ts b/client/src/map/custommarker.ts new file mode 100644 index 00000000..a6ca5998 --- /dev/null +++ b/client/src/map/custommarker.ts @@ -0,0 +1,25 @@ +import { DivIcon, Map, Marker } from "leaflet"; +import { MarkerOptions } from "leaflet"; +import { LatLngExpression } from "leaflet"; + +export class CustomMarker extends Marker { + constructor(latlng: LatLngExpression, options?: MarkerOptions) { + super(latlng, options); + } + + onAdd(map: Map): this { + this.setIcon(new DivIcon()); // Default empty icon + super.onAdd(map); + this.createIcon(); + return this; + } + + onRemove(map: Map): this { + super.onRemove(map); + return this; + } + + createIcon() { + /* Overloaded by child classes */ + } +} \ No newline at end of file diff --git a/client/src/map/destinationpreviewmarker.ts b/client/src/map/destinationpreviewmarker.ts new file mode 100644 index 00000000..1146992d --- /dev/null +++ b/client/src/map/destinationpreviewmarker.ts @@ -0,0 +1,15 @@ +import { DivIcon } from "leaflet"; +import { CustomMarker } from "./custommarker"; + +export class DestinationPreviewMarker extends CustomMarker { + createIcon() { + this.setIcon(new DivIcon({ + iconSize: [52, 52], + iconAnchor: [26, 26], + className: "leaflet-destination-preview" + })); + var el = document.createElement("div"); + el.classList.add("ol-destination-preview-icon"); + this.getElement()?.appendChild(el); + } +} diff --git a/client/src/map/map.ts b/client/src/map/map.ts index a531e33a..477b8640 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -1,6 +1,4 @@ import * as L from "leaflet" -import { MiniMap, MiniMapOptions } from "leaflet-control-mini-map"; - import { getUnitsManager } from ".."; import { BoxSelect } from "./boxselect"; import { MapContextMenu, SpawnOptions } from "../controls/mapcontextmenu"; @@ -9,31 +7,22 @@ import { AirbaseContextMenu } from "../controls/airbasecontextmenu"; import { Dropdown } from "../controls/dropdown"; import { Airbase } from "../missionhandler/airbase"; import { Unit } from "../units/unit"; - -// TODO a bit of a hack, this module is provided as pure javascript only -require("../../node_modules/leaflet.nauticscale/dist/leaflet.nauticscale.js") - -export const IDLE = "IDLE"; -export const MOVE_UNIT = "MOVE_UNIT"; +import { bearing } from "../other/utils"; +import { DestinationPreviewMarker } from "./destinationpreviewmarker"; +import { TemporaryUnitMarker } from "./temporaryunitmarker"; +import { ClickableMiniMap } from "./clickableminimap"; +import { SVGInjector } from '@tanem/svg-injector' L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect); -var temporaryIcon = new L.Icon({ - iconUrl: 'images/icon-temporary.png', - iconSize: [52, 52], - iconAnchor: [26, 26] -}); +// TODO would be nice to convert to ts +require("../../public/javascripts/leaflet.nauticscale.js") -export class ClickableMiniMap extends MiniMap { - constructor(layer: L.TileLayer | L.LayerGroup, options?: MiniMapOptions) { - super(layer, options); - } - - getMap() { - //@ts-ignore needed to access not exported member. A bit of a hack, required to access click events - return this._miniMap; - } -} +/* Map constants */ +export const IDLE = "IDLE"; +export const MOVE_UNIT = "MOVE_UNIT"; +export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"]; +export const visibilityControlsTootlips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"]; export class Map extends L.Map { #state: string; @@ -51,12 +40,17 @@ export class Map extends L.Map { #miniMap: ClickableMiniMap | null = null; #miniMapLayerGroup: L.LayerGroup; #temporaryMarkers: L.Marker[] = []; + #destinationPreviewMarkers: L.Marker[] = []; + #destinationGroupRotation: number = 0; + #computeDestinationRotation: boolean = false; + #destinationRotationCenter: L.LatLng | null = null; #mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu"); #unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu"); #airbaseContextMenu: AirbaseContextMenu = new AirbaseContextMenu("airbase-contextmenu"); #mapSourceDropdown: Dropdown; + #optionButtons: { [key: string]: HTMLButtonElement[] } = {} constructor(ID: string) { /* Init the leaflet map */ @@ -67,53 +61,18 @@ export class Map extends L.Map { this.setLayer("ArcGIS Satellite"); /* Minimap */ - /* Draw the limits of the maps in the minimap*/ - var latlngs = [[ // NTTR - new L.LatLng(39.7982463, -119.985425), - new L.LatLng(34.4037128, -119.7806729), - new L.LatLng(34.3483316, -112.4529351), - new L.LatLng(39.7372411, -112.1130805), - new L.LatLng(39.7982463, -119.985425) - ], - [ // Syria - new L.LatLng(37.3630556, 29.2686111), - new L.LatLng(31.8472222, 29.8975), - new L.LatLng(32.1358333, 42.1502778), - new L.LatLng(37.7177778, 42.3716667), - new L.LatLng(37.3630556, 29.2686111) - ], - [ // Caucasus - new L.LatLng(39.6170191, 27.634935), - new L.LatLng(38.8735863, 47.1423108), - new L.LatLng(47.3907982, 49.3101946), - new L.LatLng(48.3955879, 26.7753625), - new L.LatLng(39.6170191, 27.634935) - ], - [ // Persian Gulf - new L.LatLng(32.9355285, 46.5623682), - new L.LatLng(21.729393, 47.572675), - new L.LatLng(21.8501348, 63.9734737), - new L.LatLng(33.131584, 64.7313594), - new L.LatLng(32.9355285, 46.5623682) - ], - [ // Marianas - new L.LatLng(22.09, 135.0572222), - new L.LatLng(10.5777778, 135.7477778), - new L.LatLng(10.7725, 149.3918333), - new L.LatLng(22.5127778, 149.5427778), - new L.LatLng(22.09, 135.0572222) - ] - ]; - var minimapLayer = new L.TileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { minZoom: 0, maxZoom: 13 }); this.#miniMapLayerGroup = new L.LayerGroup([minimapLayer]); - var miniMapPolyline = new L.Polyline(latlngs, { color: '#202831' }); + var miniMapPolyline = new L.Polyline(this.#getMinimapBoundaries(), { color: '#202831' }); miniMapPolyline.addTo(this.#miniMapLayerGroup); /* Scale */ //@ts-ignore TODO more hacking because the module is provided as a pure javascript module only L.control.scalenautic({ position: "topright", maxWidth: 300, nautic: true, metric: true, imperial: false }).addTo(this); + /* Map source dropdown */ + this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers()) + /* Init the state machine */ this.#state = IDLE; @@ -127,15 +86,21 @@ export class Map extends L.Map { this.on('mousedown', (e: any) => this.#onMouseDown(e)); this.on('mouseup', (e: any) => this.#onMouseUp(e)); this.on('mousemove', (e: any) => this.#onMouseMove(e)); + this.on('keydown', (e: any) => this.#updateDestinationPreview(e)); + this.on('keyup', (e: any) => this.#updateDestinationPreview(e)); + /* Event listeners */ document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => { - ev.detail._element.classList.toggle("off"); - document.body.toggleAttribute("data-hide-" + ev.detail.coalition); + const el = ev.detail._element; + el?.classList.toggle("off"); + getUnitsManager().setHiddenType(ev.detail.coalition, (el?.currentTarget as HTMLElement)?.classList.contains("off")); Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility()); }); document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => { - document.body.toggleAttribute("data-hide-" + ev.detail.category); + const el = ev.detail._element; + el?.classList.toggle("off"); + getUnitsManager().setHiddenType(ev.detail.type, !el?.classList.contains("off")); Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility()); }); @@ -144,12 +109,17 @@ export class Map extends L.Map { this.#panToUnit(this.#centerUnit); }); - this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers()) - - this.#panInterval = window.setInterval(() => { - this.panBy(new L.Point( ((this.#panLeft? -1: 0) + (this.#panRight? 1: 0)) * this.#deafultPanDelta, - ((this.#panUp? -1: 0) + (this.#panDown? 1: 0)) * this.#deafultPanDelta)); + /* Pan interval */ + this.#panInterval = window.setInterval(() => { + this.panBy(new L.Point(((this.#panLeft ? -1 : 0) + (this.#panRight ? 1 : 0)) * this.#deafultPanDelta, + ((this.#panUp ? -1 : 0) + (this.#panDown ? 1 : 0)) * this.#deafultPanDelta)); }, 20); + + /* Option buttons */ + this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => { + return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`); + }); + document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]); } setLayer(layerName: string) { @@ -205,9 +175,34 @@ export class Map extends L.Map { this.#state = state; if (this.#state === IDLE) { L.DomUtil.removeClass(this.getContainer(), 'crosshair-cursor-enabled'); + + /* Remove all the destination preview markers */ + this.#destinationPreviewMarkers.forEach((marker: L.Marker) => { + this.removeLayer(marker); + }) + this.#destinationPreviewMarkers = []; + + this.#destinationGroupRotation = 0; + this.#computeDestinationRotation = false; + this.#destinationRotationCenter = null; } else if (this.#state === MOVE_UNIT) { L.DomUtil.addClass(this.getContainer(), 'crosshair-cursor-enabled'); + + /* Remove all the exising destination preview markers */ + this.#destinationPreviewMarkers.forEach((marker: L.Marker) => { + this.removeLayer(marker); + }) + this.#destinationPreviewMarkers = []; + + if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 1 && getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) { + /* Create the unit destination preview markers */ + this.#destinationPreviewMarkers = getUnitsManager().getSelectedUnits({ excludeHumans: true }).map((unit: Unit) => { + var marker = new DestinationPreviewMarker(this.getMouseCoordinates()); + marker.addTo(this); + return marker; + }) + } } document.dispatchEvent(new CustomEvent("mapStateChanged")); } @@ -328,7 +323,6 @@ export class Map extends L.Map { if (this.#miniMap) this.setView(e.latlng); }) - } getMiniMapLayerGroup() { @@ -336,7 +330,7 @@ export class Map extends L.Map { } handleMapPanning(e: any) { - if (e.type === "keyup"){ + if (e.type === "keyup") { switch (e.code) { case "KeyA": case "ArrowLeft": @@ -356,9 +350,8 @@ export class Map extends L.Map { break; } } - else { - switch (e.code) - { + else { + switch (e.code) { case 'KeyA': case 'ArrowLeft': this.#panLeft = true; @@ -380,7 +373,7 @@ export class Map extends L.Map { } addTemporaryMarker(latlng: L.LatLng) { - var marker = new L.Marker(latlng, {icon: temporaryIcon}); + var marker = new TemporaryUnitMarker(latlng); marker.addTo(this); this.#temporaryMarkers.push(marker); } @@ -397,8 +390,7 @@ export class Map extends L.Map { i = idx; } }); - if (closest) - { + if (closest) { this.removeLayer(closest); delete this.#temporaryMarkers[i]; } @@ -433,7 +425,10 @@ export class Map extends L.Map { if (!e.originalEvent.ctrlKey) { getUnitsManager().selectedUnitsClearDestinations(); } - getUnitsManager().selectedUnitsAddDestination(e.latlng) + getUnitsManager().selectedUnitsAddDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, !e.originalEvent.shiftKey, this.#destinationGroupRotation) + this.#destinationGroupRotation = 0; + this.#destinationRotationCenter = null; + this.#computeDestinationRotation = false; } } @@ -448,6 +443,16 @@ export class Map extends L.Map { #onMouseDown(e: any) { this.hideAllContextMenus(); + + if (this.#state == MOVE_UNIT) { + this.#destinationGroupRotation = 0; + this.#destinationRotationCenter = null; + this.#computeDestinationRotation = false; + if (e.originalEvent.button == 2) { + this.#computeDestinationRotation = true; + this.#destinationRotationCenter = this.getMouseCoordinates(); + } + } } #onMouseUp(e: any) { @@ -456,6 +461,11 @@ export class Map extends L.Map { #onMouseMove(e: any) { this.#lastMousePosition.x = e.originalEvent.x; this.#lastMousePosition.y = e.originalEvent.y; + + if (this.#computeDestinationRotation && this.#destinationRotationCenter != null) + this.#destinationGroupRotation = -bearing(this.#destinationRotationCenter.lat, this.#destinationRotationCenter.lng, this.getMouseCoordinates().lat, this.getMouseCoordinates().lng); + + this.#updateDestinationPreview(e); } #onZoom(e: any) { @@ -467,4 +477,65 @@ export class Map extends L.Map { var unitPosition = new L.LatLng(unit.getFlightData().latitude, unit.getFlightData().longitude); this.setView(unitPosition, this.getZoom(), { animate: false }); } + + #getMinimapBoundaries() { + /* Draw the limits of the maps in the minimap*/ + return [[ // NTTR + new L.LatLng(39.7982463, -119.985425), + new L.LatLng(34.4037128, -119.7806729), + new L.LatLng(34.3483316, -112.4529351), + new L.LatLng(39.7372411, -112.1130805), + new L.LatLng(39.7982463, -119.985425) + ], + [ // Syria + new L.LatLng(37.3630556, 29.2686111), + new L.LatLng(31.8472222, 29.8975), + new L.LatLng(32.1358333, 42.1502778), + new L.LatLng(37.7177778, 42.3716667), + new L.LatLng(37.3630556, 29.2686111) + ], + [ // Caucasus + new L.LatLng(39.6170191, 27.634935), + new L.LatLng(38.8735863, 47.1423108), + new L.LatLng(47.3907982, 49.3101946), + new L.LatLng(48.3955879, 26.7753625), + new L.LatLng(39.6170191, 27.634935) + ], + [ // Persian Gulf + new L.LatLng(32.9355285, 46.5623682), + new L.LatLng(21.729393, 47.572675), + new L.LatLng(21.8501348, 63.9734737), + new L.LatLng(33.131584, 64.7313594), + new L.LatLng(32.9355285, 46.5623682) + ], + [ // Marianas + new L.LatLng(22.09, 135.0572222), + new L.LatLng(10.5777778, 135.7477778), + new L.LatLng(10.7725, 149.3918333), + new L.LatLng(22.5127778, 149.5427778), + new L.LatLng(22.09, 135.0572222) + ] + ]; + } + + #updateDestinationPreview(e: any) { + Object.values(getUnitsManager().selectedUnitsComputeGroupDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates(), this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => { + if (idx < this.#destinationPreviewMarkers.length) + this.#destinationPreviewMarkers[idx].setLatLng(!e.originalEvent.shiftKey ? latlng : this.getMouseCoordinates()); + }) + } + + #createOptionButton(value: string, url: string, title: string, callback: string, argument: string) { + var button = document.createElement("button"); + const img = document.createElement("img"); + img.src = `/resources/theme/images/buttons/${url}`; + img.onload = () => SVGInjector(img); + button.title = title; + button.value = value; + button.appendChild(img); + button.setAttribute("data-on-click", callback); + button.setAttribute("data-on-click-params", argument); + return button; + } } + diff --git a/client/src/map/temporaryunitmarker.ts b/client/src/map/temporaryunitmarker.ts new file mode 100644 index 00000000..904ee83d --- /dev/null +++ b/client/src/map/temporaryunitmarker.ts @@ -0,0 +1,13 @@ +import { Icon } from "leaflet"; +import { CustomMarker } from "./custommarker"; + +export class TemporaryUnitMarker extends CustomMarker { + createIcon() { + var icon = new Icon({ + iconUrl: '/resources/theme/images/markers/temporary-icon.png', + iconSize: [52, 52], + iconAnchor: [26, 26] + }); + this.setIcon(icon); + } +} \ No newline at end of file diff --git a/client/src/missionhandler/airbase.ts b/client/src/missionhandler/airbase.ts index a3ca42dc..4128001b 100644 --- a/client/src/missionhandler/airbase.ts +++ b/client/src/missionhandler/airbase.ts @@ -1,13 +1,14 @@ -import * as L from 'leaflet' +import { DivIcon } from 'leaflet'; +import { CustomMarker } from '../map/custommarker'; +import { SVGInjector } from '@tanem/svg-injector'; export interface AirbaseOptions { name: string, - position: L.LatLng, - src: string + position: L.LatLng } -export class Airbase extends L.Marker +export class Airbase extends CustomMarker { #name: string = ""; #coalition: string = ""; @@ -19,21 +20,30 @@ export class Airbase extends L.Marker super(options.position, { riseOnHover: true }); this.#name = options.name; - var icon = new L.DivIcon({ - html: `
-
-
`, + } + + createIcon() { + var icon = new DivIcon({ className: 'leaflet-airbase-marker', iconSize: [40, 40], iconAnchor: [20, 20] }); // Set the marker, className must be set to avoid white square this.setIcon(icon); + + var el = document.createElement("div"); + el.classList.add("airbase-icon"); + el.setAttribute("data-object", "airbase"); + var img = document.createElement("img"); + img.src = "/resources/theme/images/markers/airbase.svg"; + img.onload = () => SVGInjector(img); + el.appendChild(img); + this.getElement()?.appendChild(el); } setCoalition(coalition: string) { this.#coalition = coalition; - ( this.getElement()?.querySelector(".airbase")).dataset.coalition = this.#coalition; + ( this.getElement()?.querySelector(".airbase-icon")).dataset.coalition = this.#coalition; } getCoalition() diff --git a/client/src/missionhandler/bullseye.ts b/client/src/missionhandler/bullseye.ts new file mode 100644 index 00000000..b50b1a7b --- /dev/null +++ b/client/src/missionhandler/bullseye.ts @@ -0,0 +1,36 @@ +import { DivIcon } from "leaflet"; +import { CustomMarker } from "../map/custommarker"; +import { SVGInjector } from "@tanem/svg-injector"; + +export class Bullseye extends CustomMarker { + #coalition: string = ""; + + createIcon() { + var icon = new DivIcon({ + className: 'leaflet-bullseye-marker', + iconSize: [40, 40], + iconAnchor: [20, 20] + }); // Set the marker, className must be set to avoid white square + this.setIcon(icon); + + var el = document.createElement("div"); + el.classList.add("bullseye-icon"); + el.setAttribute("data-object", "bullseye"); + var img = document.createElement("img"); + img.src = "/resources/theme/images/markers/bullseye.svg"; + img.onload = () => SVGInjector(img); + el.appendChild(img); + this.getElement()?.appendChild(el); + } + + setCoalition(coalition: string) + { + this.#coalition = coalition; + ( this.getElement()?.querySelector(".bullseye-icon")).dataset.coalition = this.#coalition; + } + + getCoalition() + { + return this.#coalition; + } +} \ No newline at end of file diff --git a/client/src/missionhandler/missionhandler.ts b/client/src/missionhandler/missionhandler.ts index ba6ef35a..117ec961 100644 --- a/client/src/missionhandler/missionhandler.ts +++ b/client/src/missionhandler/missionhandler.ts @@ -1,19 +1,12 @@ -import { Marker, LatLng, Icon } from "leaflet"; +import { LatLng } from "leaflet"; import { getInfoPopup, getMap } from ".."; import { Airbase } from "./airbase"; - -var bullseyeIcons = [ - new Icon({ iconUrl: 'images/bullseye0.png', iconAnchor: [30, 30]}), - new Icon({ iconUrl: 'images/bullseye1.png', iconAnchor: [30, 30]}), - new Icon({ iconUrl: 'images/bullseye2.png', iconAnchor: [30, 30]}) -] +import { Bullseye } from "./bullseye"; export class MissionHandler { - #bullseyes : any; //TODO declare interface - #bullseyeMarkers: any; - #airbases : any; //TODO declare interface - #airbasesMarkers: {[name: string]: Airbase}; + #bullseyes : {[name: string]: Bullseye} = {}; + #airbases : {[name: string]: Airbase} = {}; #theatre : string = ""; // Time @@ -26,27 +19,48 @@ export class MissionHandler constructor() { - this.#bullseyes = undefined; - this.#bullseyeMarkers = [ - new Marker([0, 0], {icon: bullseyeIcons[0]}).addTo(getMap()), - new Marker([0, 0], {icon: bullseyeIcons[1]}).addTo(getMap()), - new Marker([0, 0], {icon: bullseyeIcons[2]}).addTo(getMap()) - ] - this.#airbasesMarkers = {}; + } update(data: BullseyesData | AirbasesData | any) { if ("bullseyes" in data) { - this.#bullseyes = data.bullseyes; - this.#drawBullseyes(); + for (let idx in data.bullseyes) + { + const bullseye = data.bullseyes[idx]; + if (!(idx in this.#bullseyes)) + this.#bullseyes[idx] = new Bullseye([0, 0]).addTo(getMap()); + + if (bullseye.latitude && bullseye.longitude && bullseye.coalition) + { + this.#bullseyes[idx].setLatLng(new LatLng(bullseye.latitude, bullseye.longitude)); + this.#bullseyes[idx].setCoalition(bullseye.coalition); + } + } } if ("airbases" in data) { - this.#airbases = data.airbases; - this.#drawAirbases(); + for (let idx in data.airbases) + { + var airbase = data.airbases[idx] + if (this.#airbases[idx] === undefined) + { + this.#airbases[idx] = new Airbase({ + position: new LatLng(airbase.latitude, airbase.longitude), + name: airbase.callsign + }).addTo(getMap()); + this.#airbases[idx].on('contextmenu', (e) => this.#onAirbaseClick(e)); + } + if (airbase.latitude && airbase.longitude && airbase.coalition) + { + this.#airbases[idx].setLatLng(new LatLng(airbase.latitude, airbase.longitude)); + this.#airbases[idx].setCoalition(airbase.coalition); + } + //this.#airbases[idx].setProperties(["Runway 1: 31L / 13R", "Runway 2: 31R / 13L", "TCN: 17X", "ILS: ---" ]); + //this.#airbases[idx].setParkings(["2x big", "5x small"]); + } } if ("mission" in data) @@ -81,7 +95,6 @@ export class MissionHandler if ( "time" in data ) { this.#updateTime = data.time; } - } getBullseyes() @@ -89,39 +102,6 @@ export class MissionHandler return this.#bullseyes; } - #drawBullseyes() - { - for (let idx in this.#bullseyes) - { - var bullseye = this.#bullseyes[idx]; - this.#bullseyeMarkers[idx].setLatLng(new LatLng(bullseye.latitude, bullseye.longitude)); - } - } - - #drawAirbases() - { - for (let idx in this.#airbases) - { - var airbase = this.#airbases[idx] - if (this.#airbasesMarkers[idx] === undefined) - { - this.#airbasesMarkers[idx] = new Airbase({ - position: new LatLng(airbase.latitude, airbase.longitude), - name: airbase.callsign, - src: "images/airbase.png"}).addTo(getMap()); - this.#airbasesMarkers[idx].on('contextmenu', (e) => this.#onAirbaseClick(e)); - } - else - { - this.#airbasesMarkers[idx].setLatLng(new LatLng(airbase.latitude, airbase.longitude)); - this.#airbasesMarkers[idx].setCoalition(airbase.coalition); - //this.#airbasesMarkers[idx].setProperties(["Runway 1: 31L / 13R", "Runway 2: 31R / 13L", "TCN: 17X", "ILS: ---" ]); - //this.#airbasesMarkers[idx].setParkings(["2x big", "5x small"]); - } - } - } - - getDate() { return this.#date; } @@ -157,7 +137,6 @@ export class MissionHandler return this.#updateTime; } - #onAirbaseClick(e: any) { getMap().showAirbaseContextMenu(e, e.sourceTarget); diff --git a/client/src/other/utils.ts b/client/src/other/utils.ts index 69c164c7..ce1ecc1f 100644 --- a/client/src/other/utils.ts +++ b/client/src/other/utils.ts @@ -11,48 +11,6 @@ export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) return brng; } - -export function ConvertDDToDMS(D: number, lng: boolean) { - var dir = D < 0 ? (lng ? "W" : "S") : lng ? "E" : "N"; - var deg = 0 | (D < 0 ? (D = -D) : D); - var min = 0 | (((D += 1e-9) % 1) * 60); - var sec = (0 | (((D * 60) % 1) * 6000)) / 100; - var dec = Math.round((sec - Math.floor(sec)) * 100); - var sec = Math.floor(sec); - if (lng) - return dir + zeroPad(deg, 3) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\""; - else - return dir + zeroPad(deg, 2) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\""; -} - - -export function dataPointMap( container:HTMLElement, data:any) { - - Object.keys( data ).forEach( ( key ) => { - - const val = "" + data[ key ]; // Ensure a string - - container.querySelectorAll( `[data-point="${key}"]`).forEach( el => { - - // We could probably have options here - if ( el instanceof HTMLInputElement ) { - el.value = val; - } else if ( el instanceof HTMLElement ) { - el.innerText = val; - } - }); - - }); - -} - - -export function deg2rad(deg: number) { - var pi = Math.PI; - return deg * (pi / 180); -} - - export function distance(lat1: number, lon1: number, lat2: number, lon2: number) { const R = 6371e3; // metres const φ1 = deg2rad(lat1); // φ, λ in radians @@ -68,6 +26,42 @@ export function distance(lat1: number, lon1: number, lat2: number, lon2: number) return d; } +export function ConvertDDToDMS(D: number, lng: boolean) { + var dir = D < 0 ? (lng ? "W" : "S") : lng ? "E" : "N"; + var deg = 0 | (D < 0 ? (D = -D) : D); + var min = 0 | (((D += 1e-9) % 1) * 60); + var sec = (0 | (((D * 60) % 1) * 6000)) / 100; + var dec = Math.round((sec - Math.floor(sec)) * 100); + var sec = Math.floor(sec); + if (lng) + return dir + zeroPad(deg, 3) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\""; + else + return dir + zeroPad(deg, 2) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\""; +} + +export function dataPointMap( container:HTMLElement, data:any) { + Object.keys( data ).forEach( ( key ) => { + const val = "" + data[ key ]; // Ensure a string + container.querySelectorAll( `[data-point="${key}"]`).forEach( el => { + // We could probably have options here + if ( el instanceof HTMLInputElement ) { + el.value = val; + } else if ( el instanceof HTMLElement ) { + el.innerText = val; + } + }); + }); +} + +export function deg2rad(deg: number) { + var pi = Math.PI; + return deg * (pi / 180); +} + +export function rad2deg(rad: number) { + var pi = Math.PI; + return rad / (pi / 180); +} export function generateUUIDv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { @@ -76,33 +70,15 @@ export function generateUUIDv4() { }); } - export function keyEventWasInInput( event:KeyboardEvent ) { - const target = event.target; - return ( target instanceof HTMLElement && ( [ "INPUT", "TEXTAREA" ].includes( target.nodeName ) ) ); - } - -export function rad2deg(rad: number) { - var pi = Math.PI; - return rad / (pi / 180); -} - - export function reciprocalHeading(heading: number): number { - - if (heading > 180) { - return heading - 180; - } - - return heading + 180; - + return heading > 180? heading - 180: heading + 180; } - export const zeroAppend = function (num: number, places: number) { var string = String(num); while (string.length < places) { @@ -111,7 +87,6 @@ export const zeroAppend = function (num: number, places: number) { return string; } - export const zeroPad = function (num: number, places: number) { var string = String(num); while (string.length < places) { @@ -120,7 +95,6 @@ export const zeroPad = function (num: number, places: number) { return string; } - export function similarity(s1: string, s2: string) { var longer = s1; var shorter = s2; @@ -160,4 +134,30 @@ export function editDistance(s1: string, s2: string) { costs[s2.length] = lastValue; } return costs[s2.length]; +} + +export function latLngToMercator(lat: number, lng: number): {x: number, y: number} { + var rMajor = 6378137; //Equatorial Radius, WGS84 + var shift = Math.PI * rMajor; + var x = lng * shift / 180; + var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180); + y = y * shift / 180; + + return {x: x, y: y}; +} + +export function mercatorToLatLng(x: number, y: number) { + var rMajor = 6378137; //Equatorial Radius, WGS84 + var shift = Math.PI * rMajor; + var lng = x / shift * 180.0; + var lat = y / shift * 180.0; + lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0); + + return { lng: lng, lat: lat }; +} + +export function createDivWithClass(className: string) { + var el = document.createElement("div"); + el.classList.add(className); + return el; } \ No newline at end of file diff --git a/client/src/panels/hotgrouppanel.ts b/client/src/panels/hotgrouppanel.ts index 8431c2ab..f0abdb85 100644 --- a/client/src/panels/hotgrouppanel.ts +++ b/client/src/panels/hotgrouppanel.ts @@ -18,14 +18,24 @@ export class HotgroupPanel extends Panel { } addHotgroup(hotgroup: number) { - const hotgroupHtml = `
-
${hotgroup}
-
- x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}` + // Hotgroup number + var hotgroupDiv = document.createElement("div"); + hotgroupDiv.classList.add("unit-hotgroup"); + var idDiv = document.createElement("div"); + idDiv.classList.add("unit-hotgroup-id"); + idDiv.innerText = String(hotgroup); + hotgroupDiv.appendChild(idDiv); + + // Hotgroup unit count + var countDiv = document.createElement("div"); + countDiv.innerText = `x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`; + var el = document.createElement("div"); + el.appendChild(hotgroupDiv); + el.appendChild(countDiv); el.classList.add("hotgroup-selector"); - el.innerHTML = hotgroupHtml; el.toggleAttribute(`data-hotgroup-${hotgroup}`, true) + this.getElement().appendChild(el); el.addEventListener("click", () => { diff --git a/client/src/panels/logpanel.ts b/client/src/panels/logpanel.ts index 44a8d5ea..367a23c0 100644 --- a/client/src/panels/logpanel.ts +++ b/client/src/panels/logpanel.ts @@ -18,7 +18,7 @@ export class LogPanel extends Panel if (parseInt(idx) >= this.#logs.length) { this.#logs.push(logs[idx]); var el = document.createElement("div"); - el.innerHTML = logs[idx]; + el.innerText = logs[idx]; el.classList.add("js-log-element", "ol-log-element"); this.getElement().appendChild(el); this.getElement().scrollTop = this.getElement().scrollHeight; diff --git a/client/src/panels/mouseinfopanel.ts b/client/src/panels/mouseinfopanel.ts index 7cfdd710..bdd38fb3 100644 --- a/client/src/panels/mouseinfopanel.ts +++ b/client/src/panels/mouseinfopanel.ts @@ -37,8 +37,8 @@ export class MouseInfoPanel extends Panel { if ( el != null ) { - var dist = distance(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng); - var bear = bearing(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng); + var dist = distance(bullseyes[idx].getLatLng().lat, bullseyes[idx].getLatLng().lng, mousePosition.lat, mousePosition.lng); + var bear = bearing(bullseyes[idx].getLatLng().lat, bullseyes[idx].getLatLng().lng, mousePosition.lat, mousePosition.lng); let bng = zeroAppend(Math.floor(bear), 3); diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index a205669e..ea90161d 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -1,3 +1,4 @@ +import { SVGInjector } from "@tanem/svg-injector"; import { getUnitsManager } from ".."; import { Dropdown } from "../controls/dropdown"; import { Slider } from "../controls/slider"; @@ -8,12 +9,12 @@ import { UnitDatabase } from "../units/unitdatabase"; import { Panel } from "./panel"; const ROEs: string[] = ["Hold", "Return", "Designated", "Free"]; -const reactionsToThreat: string[] = ["None", "Passive", "Evade"]; +const reactionsToThreat: string[] = ["None", "Manoeuvre", "Passive", "Evade"]; const emissionsCountermeasures: string[] = ["Silent", "Attack", "Defend", "Free"]; const ROEDescriptions: string[] = ["Hold (Never fire)", "Return (Only fire if fired upon)", "Designated (Attack the designated target only)", "Free (Attack anyone)"]; -const reactionsToThreatDescriptions: string[] = ["None (No reaction)", "Passive (Countermeasures only, no manoeuvre)", "Evade (Countermeasures and manoeuvers)"]; -const emissionsCountermeasuresDescriptions: string[] = ["Silent (Radar off, no countermeasures)", "Attack (Radar only for targeting, countermeasures only if attacked/locked)", "Defend (Radar for searching, jammer if locked, countermeasures inside WEZ)", "Always on (Radar and jammer always on, countermeasures when hostile detected)"]; +const reactionsToThreatDescriptions: string[] = ["None (No reaction)", "Manoeuvre (no countermeasures)", "Passive (Countermeasures only, no manoeuvre)", "Evade (Countermeasures and manoeuvers)"]; +const emissionsCountermeasuresDescriptions: string[] = ["Silent (Radar OFF, no ECM)", "Attack (Radar only for targeting, ECM only if locked)", "Defend (Radar for searching, ECM if locked)", "Always on (Radar and ECM always on)"]; const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 }; const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 }; @@ -56,15 +57,15 @@ export class UnitControlPanel extends Panel { /* Option buttons */ this.#optionButtons["ROE"] = ROEs.map((option: string, index: number) => { - return this.#createOptionButton(option, ROEDescriptions[index], () => { getUnitsManager().selectedUnitsSetROE(option); }); + return this.#createOptionButton(option, `roe/${option.toLowerCase()}.svg`, ROEDescriptions[index], () => { getUnitsManager().selectedUnitsSetROE(option); }); }); this.#optionButtons["reactionToThreat"] = reactionsToThreat.map((option: string, index: number) => { - return this.#createOptionButton(option, reactionsToThreatDescriptions[index],() => { getUnitsManager().selectedUnitsSetReactionToThreat(option); }); + return this.#createOptionButton(option, `threat/${option.toLowerCase()}.svg`, reactionsToThreatDescriptions[index],() => { getUnitsManager().selectedUnitsSetReactionToThreat(option); }); }); this.#optionButtons["emissionsCountermeasures"] = emissionsCountermeasures.map((option: string, index: number) => { - return this.#createOptionButton(option, emissionsCountermeasuresDescriptions[index],() => { getUnitsManager().selectedUnitsSetEmissionsCountermeasures(option); }); + return this.#createOptionButton(option, `emissions/${option.toLowerCase()}.svg`, emissionsCountermeasuresDescriptions[index],() => { getUnitsManager().selectedUnitsSetEmissionsCountermeasures(option); }); }); this.getElement().querySelector("#roe-buttons-container")?.append(...this.#optionButtons["ROE"]); @@ -342,10 +343,14 @@ export class UnitControlPanel extends Panel { this.#advancedSettingsDialog.classList.add("hide"); } - #createOptionButton(option: string, title: string, callback: EventListenerOrEventListenerObject) { + #createOptionButton(value: string, url: string, title: string, callback: EventListenerOrEventListenerObject) { var button = document.createElement("button"); - button.value = option; button.title = title; + button.value = value; + var img = document.createElement("img"); + img.src = `/resources/theme/images/buttons/${url}`; + img.onload = () => SVGInjector(img); + button.appendChild(img); button.addEventListener("click", callback); return button; } diff --git a/client/src/units/groundunitsdatabase.ts b/client/src/units/groundunitsdatabase.ts index 8610bf91..a880b8d6 100644 --- a/client/src/units/groundunitsdatabase.ts +++ b/client/src/units/groundunitsdatabase.ts @@ -4,6 +4,24 @@ export class GroundUnitsDatabase extends UnitDatabase { constructor() { super(); this.blueprints = { + "SA-2 SAM Battery": { + "name": "SA-2 SAM Battery", + "label": "SA-2 SAM Battery", + "shortLabel": "SA-2 SAM Battery", + "loadouts": [ + { + "fuel": 1, + "items": [ + ], + "roles": [ + "Template" + ], + "code": "", + "name": "Default" + } + ], + "filename": "" + }, "2B11 mortar": { "name": "2B11 mortar", "label": "2B11 mortar", diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index 35560fc2..d54034a7 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -4,14 +4,17 @@ import { rad2deg } from '../other/utils'; import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures } from '../server/server'; import { aircraftDatabase } from './aircraftdatabase'; import { groundUnitsDatabase } from './groundunitsdatabase'; +import { CustomMarker } from '../map/custommarker'; +import { SVGInjector } from '@tanem/svg-injector'; +import { UnitDatabase } from './unitdatabase'; var pathIcon = new Icon({ - iconUrl: 'images/marker-icon.png', - shadowUrl: 'images/marker-shadow.png', + iconUrl: '/resources/theme/images/markers/marker-icon.png', + shadowUrl: '/resources/theme/images/markers/marker-shadow.png', iconAnchor: [13, 41] }); -export class Unit extends Marker { +export class Unit extends CustomMarker { ID: number; #data: UnitData = { @@ -114,22 +117,7 @@ export class Unit extends Marker { /* Set the unit data */ this.setData(data); - /* Set the icon */ - var icon = new DivIcon({ - html: this.getMarkerHTML(), - className: 'leaflet-unit-marker', - iconAnchor: [25, 25], - iconSize: [50, 50], - }); - this.setIcon(icon); - } - - getMarkerHTML() { - return `
-
-
-
-
` + } getMarkerCategory() { @@ -137,8 +125,77 @@ export class Unit extends Marker { return ""; } - /********************** Unit data *************************/ + getDatabase(): UnitDatabase | null { + // Overloaded by child classes + return null; + } + getIconOptions(): UnitIconOptions { + // Default values, overloaded by child classes if needed + return { + showState: false, + showVvi: false, + showHotgroup: false, + showUnitIcon: true, + showShortLabel: false, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false + } + } + + setSelected(selected: boolean) { + /* Only alive units can be selected. Some units are not selectable (weapons) */ + if ((this.getBaseData().alive || !selected) && this.getSelectable() && this.getSelected() != selected) { + this.#selected = selected; + this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-selected", selected); + if (selected) + document.dispatchEvent(new CustomEvent("unitSelection", { detail: this })); + else + document.dispatchEvent(new CustomEvent("unitDeselection", { detail: this })); + this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected)); + } + } + + getSelected() { + return this.#selected; + } + + setSelectable(selectable: boolean) { + this.#selectable = selectable; + } + + getSelectable() { + return this.#selectable; + } + + setHotgroup(hotgroup: number | null) { + this.#hotgroup = hotgroup; + this.#updateMarker(); + } + + getHotgroup() { + return this.#hotgroup; + } + + setHighlighted(highlighted: boolean) { + if (this.getSelectable() && this.#highlighted != highlighted) { + this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted); + this.#highlighted = highlighted; + this.getGroupMembers().forEach((unit: Unit) => unit.setHighlighted(highlighted)); + } + } + + getHighlighted() { + return this.#highlighted; + } + + getGroupMembers() { + return Object.values(getUnitsManager().getUnits()).filter((unit: Unit) => {return unit != this && unit.getBaseData().groupName === this.getBaseData().groupName;}); + } + + /********************** Unit data *************************/ setData(data: UpdateData) { /* Check if data has changed comparing new values to old values */ const positionChanged = (data.flightData != undefined && data.flightData.latitude != undefined && data.flightData.longitude != undefined && (this.getFlightData().latitude != data.flightData.latitude || this.getFlightData().longitude != data.flightData.longitude)); @@ -237,52 +294,119 @@ export class Unit extends Marker { return this.getData().optionsData; } - setSelected(selected: boolean) { - /* Only alive units can be selected. Some units are not selectable (weapons) */ - if ((this.getBaseData().alive || !selected) && this.getSelectable() && this.getSelected() != selected) { - this.#selected = selected; - this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-selected"); - if (selected) - document.dispatchEvent(new CustomEvent("unitSelection", { detail: this })); - else - document.dispatchEvent(new CustomEvent("unitDeselection", { detail: this })); + /********************** Icon *************************/ + createIcon(): void { + /* Set the icon */ + var icon = new DivIcon({ + className: 'leaflet-unit-icon', + iconAnchor: [25, 25], + iconSize: [50, 50], + }); + this.setIcon(icon); + + var el = document.createElement("div"); + el.classList.add("unit"); + el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`); + el.setAttribute("data-coalition", this.getMissionData().coalition); + + // Generate and append elements depending on active options + // Velocity vector + if (this.getIconOptions().showVvi) { + var vvi = document.createElement("div"); + vvi.classList.add("unit-vvi"); + vvi.toggleAttribute("data-rotate-to-heading"); + el.append(vvi); } - } - getSelected() { - return this.#selected; - } + // Hotgroup indicator + if (this.getIconOptions().showHotgroup) { + var hotgroup = document.createElement("div"); + hotgroup.classList.add("unit-hotgroup"); + var hotgroupId = document.createElement("div"); + hotgroupId.classList.add("unit-hotgroup-id"); + hotgroup.appendChild(hotgroupId); + el.append(hotgroup); + } - setSelectable(selectable: boolean) { - this.#selectable = selectable; - } + // Main icon + if (this.getIconOptions().showUnitIcon) { + var unitIcon = document.createElement("div"); + unitIcon.classList.add("unit-icon"); + var img = document.createElement("img"); + img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`; + img.onload = () => SVGInjector(img); + unitIcon.appendChild(img); + unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading); + el.append(unitIcon); + } - getSelectable() { - return this.#selectable; - } + // State icon + if (this.getIconOptions().showState){ + var state = document.createElement("div"); + state.classList.add("unit-state"); + el.appendChild(state); + } - setHotgroup(hotgroup: number | null) { - this.#hotgroup = hotgroup; - } + // Short label + if (this.getIconOptions().showShortLabel) { + var shortLabel = document.createElement("div"); + shortLabel.classList.add("unit-short-label"); + shortLabel.innerText = this.getDatabase()?.getByName(this.getBaseData().name)?.shortLabel || ""; + el.append(shortLabel); + } - getHotgroup() { - return this.#hotgroup; - } + // Fuel indicator + if (this.getIconOptions().showFuel) { + var fuelIndicator = document.createElement("div"); + fuelIndicator.classList.add("unit-fuel"); + var fuelLevel = document.createElement("div"); + fuelLevel.classList.add("unit-fuel-level"); + fuelIndicator.appendChild(fuelLevel); + el.append(fuelIndicator); + } - setHighlighted(highlighted: boolean) { - this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted); - this.#highlighted = highlighted; - } + // Ammo indicator + if (this.getIconOptions().showAmmo){ + var ammoIndicator = document.createElement("div"); + ammoIndicator.classList.add("unit-ammo"); + for (let i = 0; i <= 3; i++) + ammoIndicator.appendChild(document.createElement("div")); + el.append(ammoIndicator); + } - getHighlighted() { - return this.#highlighted; + // Unit summary + if (this.getIconOptions().showSummary) { + var summary = document.createElement("div"); + summary.classList.add("unit-summary"); + var callsign = document.createElement("div"); + callsign.classList.add("unit-callsign"); + callsign.innerText = this.getBaseData().unitName; + var altitude = document.createElement("div"); + altitude.classList.add("unit-altitude"); + var speed = document.createElement("div"); + speed.classList.add("unit-speed"); + summary.appendChild(callsign); + summary.appendChild(altitude); + summary.appendChild(speed); + el.appendChild(summary); + } + + this.getElement()?.appendChild(el); } /********************** Visibility *************************/ updateVisibility() { - this.setHidden(document.body.getAttribute(`data-hide-${this.getMissionData().coalition}`) != null || - document.body.getAttribute(`data-hide-${this.getMarkerCategory()}`) != null || - !this.getBaseData().alive) + var hidden = false; + const hiddenUnits = getUnitsManager().getHiddenTypes(); + if (this.getMissionData().flags.Human && hiddenUnits.includes("human")) + hidden = true; + else if (this.getBaseData().AI == false && hiddenUnits.includes("dcs")) + hidden = true; + else if (hiddenUnits.includes(this.getMarkerCategory())) + hidden = true; + else if (hiddenUnits.includes(this.getMissionData().coalition)) + hidden = true; + this.setHidden(hidden || !this.getBaseData().alive); } setHidden(hidden: boolean) { @@ -430,18 +554,18 @@ export class Unit extends Marker { } #onContextMenu(e: any) { - var options: { [key: string]: string } = {}; + var options: {[key: string]: {text: string, tooltip: string}} = {}; - options["Center"] = `
Center map
`; + options["center-map"] = {text: "Center map", tooltip: "Center the map on the unit and follow it"}; if (getUnitsManager().getSelectedUnits().length > 0 && !(getUnitsManager().getSelectedUnits().length == 1 && (getUnitsManager().getSelectedUnits().includes(this)))) { - options['Attack'] = `
Attack
`; + options["attack"] = {text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons"}; if (getUnitsManager().getSelectedUnitsType() === "Aircraft") - options['Follow'] = `
Follow
`; + options["follow"] = {text: "Follow", tooltip: "Follow the unit at a user defined distance and position"};; } else if ((getUnitsManager().getSelectedUnits().length > 0 && (getUnitsManager().getSelectedUnits().includes(this))) || getUnitsManager().getSelectedUnits().length == 0) { if (this.getBaseData().category == "Aircraft") { - options["Refuel"] = `
Refuel
`; // TODO Add some way of knowing which aircraft can AAR + options["refuel"] = {text: "AAR Refuel", tooltip: "Refuel unit at the nearest AAR Tanker. If no tanker is available the unit will RTB."}; // TODO Add some way of knowing which aircraft can AAR } } @@ -455,28 +579,28 @@ export class Unit extends Marker { } #executeAction(e: any, action: string) { - if (action === "Center") + if (action === "center-map") getMap().centerOnUnit(this.ID); - if (action === "Attack") + if (action === "attack") getUnitsManager().selectedUnitsAttackUnit(this.ID); - else if (action === "Refuel") + else if (action === "refuel") getUnitsManager().selectedUnitsRefuel(); - else if (action === "Follow") + else if (action === "follow") this.#showFollowOptions(e); } #showFollowOptions(e: any) { - var options: { [key: string]: string } = {}; + var options: {[key: string]: {text: string, tooltip: string}} = {}; options = { - 'Trail': `
Trail
`, - 'Echelon (LH)': `
Echelon (left)
`, - 'Echelon (RH)': `
Echelon (right)
`, - 'Line abreast (LH)': `
Line abreast (left)
`, - 'Line abreast (RH)': `
Line abreast (right)
`, - 'Front': `
In front
`, - 'Diamond': `
Diamond
`, - 'Custom': `
Custom
` + 'trail': {text: "Trail", tooltip: "Follow unit in trail formation"}, + 'echelon-lh': {text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation"}, + 'echelon-rh': {text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation"}, + 'line-abreast-lh': {text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation"}, + 'line-abreast-rh': {text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation"}, + 'front': {text: "Front", tooltip: "Fly in front of unit"}, + 'diamond': {text: "Diamond", tooltip: "Follow unit in diamond formation"}, + 'custom': {text: "Custom", tooltip: "Set a custom formation position"}, } getMap().getUnitContextMenu().setOptions(options, (option: string) => { @@ -487,7 +611,7 @@ export class Unit extends Marker { } #applyFollowOptions(action: string) { - if (action === "Custom") { + if (action === "custom") { document.getElementById("custom-formation-dialog")?.classList.remove("hide"); getMap().getUnitContextMenu().setCustomFormationCallback((offset: { x: number, y: number, z: number }) => { getUnitsManager().selectedUnitsFollowUnit(this.ID, offset); @@ -543,18 +667,18 @@ export class Unit extends Marker { element.querySelector(".unit")?.toggleAttribute("data-is-dead", !this.getBaseData().alive); /* Set current unit state */ - if (this.getMissionData().flags.Human) // Unit is human + if (this.getMissionData().flags.Human) // Unit is human element.querySelector(".unit")?.setAttribute("data-state", "human"); - else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus) + else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus) element.querySelector(".unit")?.setAttribute("data-state", "dcs"); - else // Unit is under Olympus control + else // Unit is under Olympus control element.querySelector(".unit")?.setAttribute("data-state", this.getTaskData().currentState.toLowerCase()); /* Set altitude and speed */ if (element.querySelector(".unit-altitude")) (element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100)); if (element.querySelector(".unit-speed")) - (element.querySelector(".unit-speed")).innerHTML = String(Math.floor(this.getFlightData().speed * 1.94384)); + (element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384)); /* Rotate elements according to heading */ element.querySelectorAll("[data-rotate-to-heading]").forEach(el => { @@ -563,7 +687,7 @@ export class Unit extends Marker { el.setAttribute("style", currentStyle + `transform:rotate(${headingDeg}deg);`); }); - /* Turn on ordnance indicators */ + /* Turn on ammo indicators */ var hasFox1 = element.querySelector(".unit")?.hasAttribute("data-has-fox-1"); var hasFox2 = element.querySelector(".unit")?.hasAttribute("data-has-fox-2"); var hasFox3 = element.querySelector(".unit")?.hasAttribute("data-has-fox-3"); @@ -646,27 +770,25 @@ export class Unit extends Marker { } #drawTargets() { - for (let typeIndex in this.getMissionData().targets) { - for (let index in this.getMissionData().targets[typeIndex]) { - var targetData = this.getMissionData().targets[typeIndex][index]; - var target = getUnitsManager().getUnitByID(targetData.object["id_"]) - if (target != null) { - var startLatLng = new LatLng(this.getFlightData().latitude, this.getFlightData().longitude) - var endLatLng = new LatLng(target.getFlightData().latitude, target.getFlightData().longitude) + for (let index in this.getMissionData().targets) { + var targetData = this.getMissionData().targets[index]; + var target = getUnitsManager().getUnitByID(targetData.object["id_"]) + if (target != null) { + var startLatLng = new LatLng(this.getFlightData().latitude, this.getFlightData().longitude) + var endLatLng = new LatLng(target.getFlightData().latitude, target.getFlightData().longitude) - var color; - if (typeIndex === "radar") - color = "#FFFF00"; - else if (typeIndex === "visual") - color = "#FF00FF"; - else if (typeIndex === "rwr") - color = "#00FF00"; - else - color = "#FFFFFF"; - var targetPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 0.4, smoothFactor: 1 }); - targetPolyline.addTo(getMap()); - this.#targetsPolylines.push(targetPolyline) - } + var color; + if (targetData.detectionMethod === "RADAR") + color = "#FFFF00"; + else if (targetData.detectionMethod === "VISUAL") + color = "#FF00FF"; + else if (targetData.detectionMethod === "RWR") + color = "#00FF00"; + else + color = "#FFFFFF"; + var targetPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 0.4, smoothFactor: 1 }); + targetPolyline.addTo(getMap()); + this.#targetsPolylines.push(targetPolyline) } } } @@ -679,7 +801,19 @@ export class Unit extends Marker { } export class AirUnit extends Unit { - + getIconOptions() { + return { + showState: true, + showVvi: true, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: true, + showAmmo: true, + showSummary: true, + rotateToHeading: false + }; + } } export class Aircraft extends AirUnit { @@ -687,37 +821,13 @@ export class Aircraft extends AirUnit { super(ID, data); } - getMarkerHTML() { - return `
-
-
-
-
-
-
-
-
-
${aircraftDatabase.getByName(this.getBaseData().name)?.shortLabel || ""}
-
-
-
-
-
-
-
-
-
-
-
${this.getBaseData().unitName}
-
-
-
-
` - } - getMarkerCategory() { return "aircraft"; } + + getDatabase(): UnitDatabase | null { + return aircraftDatabase; + } } export class Helicopter extends AirUnit { @@ -725,7 +835,7 @@ export class Helicopter extends AirUnit { super(ID, data); } - getVisibilityCategory() { + getMarkerCategory() { return "helicopter"; } } @@ -735,24 +845,30 @@ export class GroundUnit extends Unit { super(ID, data); } - getMarkerHTML() { - var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0]; - return `
-
-
-
${role?.substring(0, 1)?.toUpperCase() || ""}
-
-
-
-
` + getIconOptions() { + return { + showState: true, + showVvi: false, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false + }; } getMarkerCategory() { // TODO this is very messy var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0]; - var markerCategory = (role === "SAM") ? "sam" : "groundunit"; + var markerCategory = (role === "SAM") ? "groundunit-sam" : "groundunit-other"; return markerCategory; } + + getDatabase(): UnitDatabase | null { + return groundUnitsDatabase; + } } export class NavyUnit extends Unit { @@ -760,6 +876,20 @@ export class NavyUnit extends Unit { super(ID, data); } + getIconOptions() { + return { + showState: true, + showVvi: false, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false + }; + } + getMarkerCategory() { return "navyunit"; } @@ -771,14 +901,19 @@ export class Weapon extends Unit { this.setSelectable(false); } - getMarkerHTML(): string { - return `
-
-
-
-
` + getIconOptions() { + return { + showState: false, + showVvi: false, + showHotgroup: false, + showUnitIcon: true, + showShortLabel: false, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: true + }; } - } export class Missile extends Weapon { diff --git a/client/src/units/unitdatabase.ts b/client/src/units/unitdatabase.ts index 9bfd0095..90d87863 100644 --- a/client/src/units/unitdatabase.ts +++ b/client/src/units/unitdatabase.ts @@ -1,21 +1,16 @@ export class UnitDatabase { - blueprints: {[key: string]: UnitBlueprint} = {}; + blueprints: { [key: string]: UnitBlueprint } = {}; - constructor() - { + constructor() { } /* Returns a list of all possible roles in a database */ - getRoles() - { + getRoles() { var roles: string[] = []; - for (let unit in this.blueprints) - { - for (let loadout of this.blueprints[unit].loadouts) - { - for (let role of loadout.roles) - { + for (let unit in this.blueprints) { + for (let loadout of this.blueprints[unit].loadouts) { + for (let role of loadout.roles) { if (role !== "" && !roles.includes(role)) roles.push(role); } @@ -25,18 +20,15 @@ export class UnitDatabase { } /* Gets a specific blueprint by name */ - getByName(name: string) - { + getByName(name: string) { if (name in this.blueprints) return this.blueprints[name]; return null; } /* Gets a specific blueprint by label */ - getByLabel(label: string) - { - for (let unit in this.blueprints) - { + getByLabel(label: string) { + for (let unit in this.blueprints) { if (this.blueprints[unit].label === label) return this.blueprints[unit]; } @@ -44,15 +36,11 @@ export class UnitDatabase { } /* Get all blueprints by role */ - getByRole(role: string) - { + getByRole(role: string) { var units = []; - for (let unit in this.blueprints) - { - for (let loadout of this.blueprints[unit].loadouts) - { - if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) - { + for (let unit in this.blueprints) { + for (let loadout of this.blueprints[unit].loadouts) { + if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) { units.push(this.blueprints[unit]) break; } @@ -62,13 +50,10 @@ export class UnitDatabase { } /* Get the names of all the loadouts for a specific unit and for a specific role */ - getLoadoutNamesByRole(name: string, role: string) - { + getLoadoutNamesByRole(name: string, role: string) { var loadouts = []; - for (let loadout of this.blueprints[name].loadouts) - { - if (loadout.roles.includes(role) || loadout.roles.includes("")) - { + for (let loadout of this.blueprints[name].loadouts) { + if (loadout.roles.includes(role) || loadout.roles.includes("")) { loadouts.push(loadout.name) } } @@ -76,10 +61,8 @@ export class UnitDatabase { } /* Get the loadout content from the unit name and loadout name */ - getLoadoutByName(name: string, loadoutName: string) - { - for (let loadout of this.blueprints[name].loadouts) - { + getLoadoutByName(name: string, loadoutName: string) { + for (let loadout of this.blueprints[name].loadouts) { if (loadout.name === loadoutName) return loadout; } diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index d3e5b88d..07f5ac9c 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -3,13 +3,14 @@ import { getHotgroupPanel, getInfoPopup, getMap, getUnitDataTable } from ".."; import { Unit } from "./unit"; import { cloneUnit } from "../server/server"; import { IDLE, MOVE_UNIT } from "../map/map"; -import { keyEventWasInInput } from "../other/utils"; +import { deg2rad, keyEventWasInInput, latLngToMercator, mercatorToLatLng } from "../other/utils"; export class UnitsManager { #units: { [ID: number]: Unit }; #copiedUnits: Unit[]; #selectionEventDisabled: boolean = false; #pasteDisabled: boolean = false; + #hiddenTypes: string[] = []; constructor() { this.#units = {}; @@ -46,7 +47,7 @@ export class UnitsManager { } getUnitsByHotgroup(hotgroup: number) { - return Object.values(this.#units).filter((unit: Unit) => {return unit.getBaseData().alive && unit.getHotgroup() == hotgroup}); + return Object.values(this.#units).filter((unit: Unit) => { return unit.getBaseData().alive && unit.getHotgroup() == hotgroup }); } addUnit(ID: number, data: UnitData) { @@ -62,6 +63,7 @@ export class UnitsManager { } update(data: UnitsData) { + var updatedUnits: Unit[] = []; Object.keys(data.units) .filter((ID: string) => !(ID in this.#units)) .reduce((timeout: number, ID: string) => { @@ -75,7 +77,29 @@ export class UnitsManager { Object.keys(data.units) .filter((ID: string) => ID in this.#units) - .forEach((ID: string) => this.#units[parseInt(ID)]?.setData(data.units[ID])); + .forEach((ID: string) => { + updatedUnits.push(this.#units[parseInt(ID)]); + this.#units[parseInt(ID)]?.setData(data.units[ID]) + }); + + this.getSelectedUnits().forEach((unit: Unit) => { + if (!updatedUnits.includes(unit)) + unit.setData({}) + }); + } + + setHiddenType(key: string, value: boolean) { + if (value) { + if (this.#hiddenTypes.includes(key)) + delete this.#hiddenTypes[this.#hiddenTypes.indexOf(key)]; + } + else + this.#hiddenTypes.push(key); + Object.values(this.getUnits()).forEach((unit: Unit) => unit.updateVisibility()); + } + + getHiddenTypes() { + return this.#hiddenTypes; } selectUnit(ID: number, deselectAllUnits: boolean = true) { @@ -96,7 +120,7 @@ export class UnitsManager { } } - getSelectedUnits(options?: {excludeHumans?: boolean}) { + getSelectedUnits(options?: { excludeHumans?: boolean }) { var selectedUnits = []; for (let ID in this.#units) { if (this.#units[ID].getSelected()) { @@ -105,7 +129,7 @@ export class UnitsManager { } if (options) { if (options.excludeHumans) - selectedUnits = selectedUnits.filter((unit: Unit) => {return !unit.getMissionData().flags.Human}); + selectedUnits = selectedUnits.filter((unit: Unit) => { return !unit.getMissionData().flags.Human }); } return selectedUnits; } @@ -162,8 +186,16 @@ export class UnitsManager { }; /*********************** Actions on selected units ************************/ - selectedUnitsAddDestination(latlng: L.LatLng) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + selectedUnitsAddDestination(latlng: L.LatLng, mantainRelativePosition: boolean, rotation: number) { + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); + + /* Compute the destination for each unit. If mantainRelativePosition is true, compute the destination so to hold the relative distances */ + var unitDestinations: { [key: number]: LatLng } = {}; + if (mantainRelativePosition) + unitDestinations = this.selectedUnitsComputeGroupDestination(latlng, rotation); + else + selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng }); + for (let idx in selectedUnits) { const unit = selectedUnits[idx]; /* If a unit is following another unit, and that unit is also selected, send the command to the followed unit */ @@ -174,14 +206,17 @@ export class UnitsManager { else unit.addDestination(latlng); } - else - unit.addDestination(latlng); + else { + if (unit.ID in unitDestinations) + unit.addDestination(unitDestinations[unit.ID]); + } + } this.#showActionMessage(selectedUnits, " new destination added"); } selectedUnitsClearDestinations() { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { const unit = selectedUnits[idx]; if (unit.getTaskData().currentState === "Follow") { @@ -197,7 +232,7 @@ export class UnitsManager { } selectedUnitsLandAt(latlng: LatLng) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].landAt(latlng); } @@ -205,21 +240,21 @@ export class UnitsManager { } selectedUnitsChangeSpeed(speedChange: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].changeSpeed(speedChange); } } selectedUnitsChangeAltitude(altitudeChange: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].changeAltitude(altitudeChange); } } selectedUnitsSetSpeed(speed: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setSpeed(speed); } @@ -227,7 +262,7 @@ export class UnitsManager { } selectedUnitsSetAltitude(altitude: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setAltitude(altitude); } @@ -235,7 +270,7 @@ export class UnitsManager { } selectedUnitsSetROE(ROE: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setROE(ROE); } @@ -243,7 +278,7 @@ export class UnitsManager { } selectedUnitsSetReactionToThreat(reactionToThreat: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setReactionToThreat(reactionToThreat); } @@ -251,7 +286,7 @@ export class UnitsManager { } selectedUnitsSetEmissionsCountermeasures(emissionCountermeasure: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setEmissionsCountermeasures(emissionCountermeasure); } @@ -260,7 +295,7 @@ export class UnitsManager { selectedUnitsAttackUnit(ID: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].attackUnit(ID); } @@ -276,7 +311,7 @@ export class UnitsManager { } selectedUnitsRefuel() { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].refuel(); } @@ -290,15 +325,15 @@ export class UnitsManager { // Y: top-bottom, positive top // Z: left-right, positive right offset = { "x": 0, "y": 0, "z": 0 }; - if (formation === "Trail") { offset.x = -50; offset.y = -30; offset.z = 0; } - else if (formation === "Echelon (LH)") { offset.x = -50; offset.y = -10; offset.z = -50; } - else if (formation === "Echelon (RH)") { offset.x = -50; offset.y = -10; offset.z = 50; } - else if (formation === "Line abreast (RH)") { offset.x = 0; offset.y = 0; offset.z = 50; } - else if (formation === "Line abreast (LH)") { offset.x = 0; offset.y = 0; offset.z = -50; } - else if (formation === "Front") { offset.x = 100; offset.y = 0; offset.z = 0; } + if (formation === "trail") { offset.x = -50; offset.y = -30; offset.z = 0; } + else if (formation === "echelon-lh") { offset.x = -50; offset.y = -10; offset.z = -50; } + else if (formation === "echelon-rh") { offset.x = -50; offset.y = -10; offset.z = 50; } + else if (formation === "line-abreast-rh") { offset.x = 0; offset.y = 0; offset.z = 50; } + else if (formation === "line-abreast-lh") { offset.x = 0; offset.y = 0; offset.z = -50; } + else if (formation === "front") { offset.x = 100; offset.y = 0; offset.z = 0; } else offset = undefined; } - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); var count = 1; var xr = 0; var yr = 1; var zr = -1; var layer = 1; @@ -309,7 +344,7 @@ export class UnitsManager { unit.followUnit(ID, { "x": offset.x * count, "y": offset.y * count, "z": offset.z * count }); else { /* More complex formations with variable offsets */ - if (formation === "Diamond") { + if (formation === "diamond") { var xl = xr * Math.cos(Math.PI / 4) - yr * Math.sin(Math.PI / 4); var yl = xr * Math.sin(Math.PI / 4) + yr * Math.cos(Math.PI / 4); unit.followUnit(ID, { "x": -yl * 50, "y": zr * 10, "z": xl * 50 }); @@ -326,14 +361,12 @@ export class UnitsManager { this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`); } - selectedUnitsSetHotgroup(hotgroup: number) - { + selectedUnitsSetHotgroup(hotgroup: number) { this.getUnitsByHotgroup(hotgroup).forEach((unit: Unit) => unit.setHotgroup(null)); this.selectedUnitsAddToHotgroup(hotgroup); } - selectedUnitsAddToHotgroup(hotgroup: number) - { + selectedUnitsAddToHotgroup(hotgroup: number) { var selectedUnits = this.getSelectedUnits(); for (let idx in selectedUnits) { selectedUnits[idx].setHotgroup(hotgroup); @@ -342,6 +375,37 @@ export class UnitsManager { getHotgroupPanel().refreshHotgroups(); } + selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number) { + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); + /* Compute the center of the group */ + var center = { x: 0, y: 0 }; + selectedUnits.forEach((unit: Unit) => { + var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude); + center.x += mercator.x / selectedUnits.length; + center.y += mercator.y / selectedUnits.length; + }); + + /* Compute the distances from the center of the group */ + var unitDestinations: { [key: number]: LatLng } = {}; + selectedUnits.forEach((unit: Unit) => { + var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude); + var distancesFromCenter = { dx: mercator.x - center.x, dy: mercator.y - center.y }; + + /* Rotate the distance according to the group rotation */ + var rotatedDistancesFromCenter: { dx: number, dy: number } = { dx: 0, dy: 0 }; + rotatedDistancesFromCenter.dx = distancesFromCenter.dx * Math.cos(deg2rad(rotation)) - distancesFromCenter.dy * Math.sin(deg2rad(rotation)); + rotatedDistancesFromCenter.dy = distancesFromCenter.dx * Math.sin(deg2rad(rotation)) + distancesFromCenter.dy * Math.cos(deg2rad(rotation)); + + /* Compute the final position of the unit */ + var destMercator = latLngToMercator(latlng.lat, latlng.lng); // Convert destination point to mercator + var unitMercator = { x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy }; // Compute final position of this unit in mercator coordinates + var unitLatLng = mercatorToLatLng(unitMercator.x, unitMercator.y); + unitDestinations[unit.ID] = new LatLng(unitLatLng.lat, unitLatLng.lng); + }); + + return unitDestinations; + } + /***********************************************/ copyUnits() { this.#copiedUnits = this.getSelectedUnits(); /* Can be applied to humans too */ diff --git a/client/views/aic.ejs b/client/views/aic/aic.ejs similarity index 100% rename from client/views/aic.ejs rename to client/views/aic/aic.ejs diff --git a/client/views/atc/addflight.ejs b/client/views/atc/addflight.ejs index 73f7c9f4..818869f0 100644 --- a/client/views/atc/addflight.ejs +++ b/client/views/atc/addflight.ejs @@ -1,5 +1,5 @@
- +
\ No newline at end of file diff --git a/client/views/atc.ejs b/client/views/atc/atc.ejs similarity index 80% rename from client/views/atc.ejs rename to client/views/atc/atc.ejs index 19046c70..65984a3a 100644 --- a/client/views/atc.ejs +++ b/client/views/atc/atc.ejs @@ -1,10 +1,10 @@ -<%- include('atc/board.ejs', { +<%- include('board.ejs', { "boardId": "strip-board-tower", "boardType": "tower", "headers": [ "Flight", "a. Alt", "alt", "a. Speed", "Speed" ] }) %> -<%- include('atc/board.ejs', { +<%- include('board.ejs', { "boardId": "strip-board-ground", "boardType": "ground", "headers": [ "Flight", "Status", "T/O Time", "TTG" ] diff --git a/client/views/unitdatatable.ejs b/client/views/atc/unitdatatable.ejs similarity index 100% rename from client/views/unitdatatable.ejs rename to client/views/atc/unitdatatable.ejs diff --git a/client/views/index.ejs b/client/views/index.ejs index afb19752..558d6b67 100644 --- a/client/views/index.ejs +++ b/client/views/index.ejs @@ -2,45 +2,37 @@ Olympus client - - + + + + - - - - - - +
- <%- include('aic.ejs') %> - <%- include('atc.ejs') %> - <%- include('contextmenus.ejs') %> - <%- include('unitcontrolpanel.ejs') %> - <%- include('unitinfopanel.ejs') %> - <%- include('mouseinfopanel.ejs') %> - <%- include('navbar.ejs') %> - <%- include('connectionstatuspanel.ejs') %> - <%- include('dialogs.ejs') %> - <%- include('unitdatatable.ejs') %> - <%- include('popups.ejs') %> - <%- include('hotgrouppanel.ejs') %> - -
- <% /* %> - <%- include('log.ejs') %> - <% */ %> + <%- include('aic/aic.ejs') %> + <%- include('atc/atc.ejs') %> + <%- include('atc/unitdatatable.ejs') %> + + <%- include('panels/unitcontrol.ejs') %> + <%- include('panels/unitinfo.ejs') %> + <%- include('panels/mouseinfo.ejs') %> + <%- include('panels/connectionstatus.ejs') %> + <%- include('panels/hotgroup.ejs') %> + <%- include('panels/navbar.ejs') %> + + <%- include('other/dialogs.ejs') %> + <%- include('other/popups.ejs') %> + <%- include('other/contextmenus.ejs') %> + +
+ diff --git a/client/views/log.ejs b/client/views/log/log.ejs similarity index 100% rename from client/views/log.ejs rename to client/views/log/log.ejs diff --git a/client/views/contextmenus.ejs b/client/views/other/contextmenus.ejs similarity index 100% rename from client/views/contextmenus.ejs rename to client/views/other/contextmenus.ejs diff --git a/client/views/dialogs.ejs b/client/views/other/dialogs.ejs similarity index 99% rename from client/views/dialogs.ejs rename to client/views/other/dialogs.ejs index 2421f78a..41ba1d34 100644 --- a/client/views/dialogs.ejs +++ b/client/views/other/dialogs.ejs @@ -67,7 +67,7 @@
-