mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
More AIC work so I don't lose it. (Best commit message ever.)
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"",
|
||||
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
|
||||
"start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"",
|
||||
"watch": "watchify .\\src\\index.ts --debug -p [ tsify --noImplicitAny ] -o .\\public\\javascripts\\bundle.js"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.9 KiB |
@@ -1,7 +1,7 @@
|
||||
|
||||
/* Page style */
|
||||
body {
|
||||
display: flex;
|
||||
display: grid;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -43,6 +43,33 @@ body {
|
||||
}
|
||||
|
||||
|
||||
/**************************************/
|
||||
|
||||
.olympus-dialog {
|
||||
align-self: center;
|
||||
background:white;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-self: center;
|
||||
padding:10px;
|
||||
position:absolute;
|
||||
width:fit-content;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.olympus-dialog-close {
|
||||
cursor:pointer;
|
||||
position:absolute;
|
||||
right:10px;
|
||||
top:5px;
|
||||
}
|
||||
|
||||
.olympus-dialog-header {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
|
||||
/**************************************/
|
||||
|
||||
.control-panel {
|
||||
@@ -69,29 +96,49 @@ body {
|
||||
/***** AIC *****/
|
||||
|
||||
#aic-control-panel {
|
||||
color:white;
|
||||
left: 550px;
|
||||
}
|
||||
|
||||
.aic-enabled #aic-control-panel .olympus-button {
|
||||
#aic-control-panel .olympus-button {
|
||||
filter:invert(100%);
|
||||
}
|
||||
|
||||
|
||||
#aic-formation-panel {
|
||||
#aic-toolbox, #aic-callsign-panel {
|
||||
align-items: flex-start;
|
||||
align-self: center;
|
||||
background:#eaeaea;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
display:none;
|
||||
justify-self: left;
|
||||
padding:10px;
|
||||
position:absolute;
|
||||
}
|
||||
|
||||
.aic-enabled #aic-formation-panel {
|
||||
.aic-panel {
|
||||
background:#eaeaea;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
justify-self: left;
|
||||
padding:5px 10px;
|
||||
}
|
||||
|
||||
.aic-enabled #aic-toolbox, .aic-enabled #aic-callsign-panel {
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aic-enabled #aic-callsign-panel {
|
||||
align-self: auto;
|
||||
top: 100px;
|
||||
}
|
||||
|
||||
.aic-panel h2 {
|
||||
font-size:90%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#aic-callsign-display {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#aic-formation-list {
|
||||
@@ -102,16 +149,95 @@ body {
|
||||
|
||||
#aic-formation-list > div {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-top:1em;
|
||||
margin-top:10px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
#aic-formation-list .aic-formation-image img {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 10px;
|
||||
max-width: 75px;
|
||||
max-width: 50px;
|
||||
}
|
||||
|
||||
#aic-formation-list .aic-formation-name {
|
||||
font-size:90%;
|
||||
}
|
||||
|
||||
#aic-formation-list .aic-formation-descriptor {
|
||||
background:white;
|
||||
border-radius: 10px;
|
||||
left:100px;
|
||||
padding:5px;
|
||||
position:absolute;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
#aic-teleprompt {
|
||||
background-color: white;
|
||||
border:2px solid black;
|
||||
border-radius: 10px;
|
||||
bottom: 50px;
|
||||
color: black;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
justify-self: center;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.aic-enabled #aic-teleprompt {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
#aic-descriptor {
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-section {
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
margin:0 10px;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-section-label {
|
||||
background-color:#eaeaea;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
padding:.25em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-components {
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-components .aic-descriptor-component {
|
||||
margin:0 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-component-label {
|
||||
display:none;
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-component-value:after {
|
||||
content:",";
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-component:last-of-type .aic-descriptor-component-value:after {
|
||||
content:";";
|
||||
}
|
||||
|
||||
#aic-descriptor .aic-descriptor-section:last-of-type .aic-descriptor-component:last-of-type .aic-descriptor-component-value:after {
|
||||
content:".";
|
||||
}
|
||||
|
||||
|
||||
@@ -162,4 +288,12 @@ body {
|
||||
#unit-control-panel {
|
||||
top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.hide {
|
||||
display:none !important;
|
||||
}
|
||||
@@ -1,37 +1,79 @@
|
||||
interface AICFormation {
|
||||
"descriptor" : string,
|
||||
"icon" : string,
|
||||
"label" : string,
|
||||
"name" : string
|
||||
}
|
||||
import { AICFormation } from "./AICFormation";
|
||||
import { AICFormation_Azimuth } from "./AICFormation/Azimuth";
|
||||
import { AICFormation_Range } from "./AICFormation/Range";
|
||||
import { AICFormation_Single } from "./AICFormation/Single";
|
||||
import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection";
|
||||
// import { AICFormationDescriptor } from "./aicformationdescriptor"
|
||||
|
||||
|
||||
export class AIC {
|
||||
|
||||
#status:boolean = true;
|
||||
|
||||
#formations:AICFormation[] = [{
|
||||
"descriptor" : "group, single, Bullseye, <bearing>, <range>, <altitude>, tracks <N|NE|E|SE|S|SW|W|NW>, <bogey|hostile>",
|
||||
"icon" : "single.png",
|
||||
"label" : "Single",
|
||||
"name" : "single"
|
||||
}, {
|
||||
"descriptor" : "",
|
||||
"icon" : "azimuth.png",
|
||||
"label" : "Azimuth",
|
||||
"name" : "azimuth"
|
||||
}, {
|
||||
"descriptor" : "",
|
||||
"icon" : "range.png",
|
||||
"label" : "Range",
|
||||
"name" : "range"
|
||||
}];
|
||||
#formations = [
|
||||
|
||||
new AICFormation_Single(),
|
||||
new AICFormation_Range(),
|
||||
new AICFormation_Azimuth()
|
||||
|
||||
];
|
||||
|
||||
|
||||
constructor() {
|
||||
|
||||
this.#onStatusUpdate();
|
||||
|
||||
// This feels kind of dirty
|
||||
let $aicFormationList = document.getElementById( "aic-formation-list" );
|
||||
|
||||
if ( $aicFormationList ) {
|
||||
|
||||
this.getFormations().forEach( formation => {
|
||||
|
||||
// Image
|
||||
let $imageDiv = document.createElement( "div" );
|
||||
$imageDiv.classList.add( "aic-formation-image" );
|
||||
|
||||
let $img = document.createElement( "img" );
|
||||
$img.src = "images/formations/" + formation.icon;
|
||||
|
||||
$imageDiv.appendChild( $img );
|
||||
|
||||
// Name
|
||||
let $nameDiv = document.createElement( "div" );
|
||||
$nameDiv.classList.add( "aic-formation-name" );
|
||||
$nameDiv.innerText = formation.label;
|
||||
|
||||
// Wrapper
|
||||
let $wrapperDiv = document.createElement( "div" );
|
||||
$wrapperDiv.dataset.formationName = formation.name;
|
||||
$wrapperDiv.appendChild( $imageDiv )
|
||||
$wrapperDiv.appendChild( $nameDiv );
|
||||
$wrapperDiv.addEventListener( "click", ( ev ) => {
|
||||
|
||||
const controlTypeInput = document.querySelector( "input[type='radio'][name='control-type']:checked" );
|
||||
|
||||
let controlTypeValue:any = ( controlTypeInput instanceof HTMLInputElement && [ "broadcast", "tactical" ].indexOf( controlTypeInput.value ) > -1 ) ? controlTypeInput.value : "broadcast";
|
||||
|
||||
// TODO: make this not an "any"
|
||||
const output:any = formation.getDescriptor({
|
||||
"aicCallsign" : "Magic",
|
||||
"bullseyeName" : "Bullseye",
|
||||
"control" : controlTypeValue,
|
||||
"numGroups" : formation.numGroups
|
||||
});
|
||||
|
||||
this.updateTeleprompt( output );
|
||||
|
||||
});
|
||||
|
||||
// Add to DOM
|
||||
$aicFormationList?.appendChild( $wrapperDiv );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -67,4 +109,80 @@ export class AIC {
|
||||
|
||||
}
|
||||
|
||||
|
||||
toggleHelp() {
|
||||
document.getElementById( "aic-help" )?.classList.toggle( "hide" );
|
||||
}
|
||||
|
||||
//*
|
||||
updateTeleprompt<T extends AICFormationDescriptorSection>( descriptor:T[] ) {
|
||||
|
||||
let $teleprompt = document.getElementById( "aic-teleprompt" );
|
||||
|
||||
if ( $teleprompt instanceof HTMLElement ) {
|
||||
|
||||
// Clean slate
|
||||
while ( $teleprompt.childNodes.length > 0 ) {
|
||||
$teleprompt.childNodes[0].remove();
|
||||
}
|
||||
|
||||
function newDiv() {
|
||||
return document.createElement( "div" );
|
||||
}
|
||||
|
||||
// Wrapper
|
||||
let $descriptor = newDiv();
|
||||
$descriptor.id = "aic-descriptor";
|
||||
|
||||
for ( const section of descriptor ) {
|
||||
|
||||
if ( section.omitSection ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let $section = newDiv();
|
||||
$section.classList.add( "aic-descriptor-section" );
|
||||
|
||||
let $sectionLabel = newDiv();
|
||||
$sectionLabel.classList.add( "aic-descriptor-section-label" );
|
||||
$sectionLabel.innerText = section.label;
|
||||
$section.appendChild( $sectionLabel );
|
||||
|
||||
|
||||
let $components = newDiv();
|
||||
$components.classList.add( "aic-descriptor-components" );
|
||||
|
||||
for ( const component of section.getComponents() ) {
|
||||
|
||||
let $component = newDiv();
|
||||
$component.classList.add( "aic-descriptor-component" );
|
||||
|
||||
let $componentLabel = newDiv();
|
||||
$componentLabel.classList.add( "aic-descriptor-component-label" );
|
||||
$componentLabel.innerText = component.label;
|
||||
|
||||
let $componentValue = newDiv();
|
||||
$componentValue.classList.add( "aic-descriptor-component-value" );
|
||||
$componentValue.innerText = component.value;
|
||||
|
||||
$component.appendChild( $componentLabel );
|
||||
$component.appendChild( $componentValue );
|
||||
|
||||
$components.appendChild( $component );
|
||||
|
||||
}
|
||||
|
||||
$section.appendChild( $components );
|
||||
$descriptor.appendChild( $section );
|
||||
|
||||
}
|
||||
|
||||
$teleprompt.appendChild( $descriptor );
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//*/
|
||||
|
||||
}
|
||||
@@ -11,8 +11,8 @@ import { MissionData } from "./missiondata/missiondata";
|
||||
import { UnitControlPanel } from "./panels/unitcontrolpanel";
|
||||
import { MouseInfoPanel } from "./panels/mouseInfoPanel";
|
||||
import { Slider } from "./controls/slider";
|
||||
import { AIC } from "./aic/AIC";
|
||||
|
||||
import { AIC } from "./aic/aic";
|
||||
|
||||
/* TODO: should this be a class? */
|
||||
var map: Map;
|
||||
@@ -41,6 +41,7 @@ var deadVisibilityButton: Button;
|
||||
|
||||
var aic: AIC;
|
||||
var aicToggleButton: Button;
|
||||
var aicHelpButton: Button;
|
||||
|
||||
var altitudeSlider: Slider;
|
||||
var airspeedSlider: Slider;
|
||||
@@ -84,11 +85,31 @@ function setup() {
|
||||
|
||||
/* AIC */
|
||||
aic = new AIC();
|
||||
|
||||
setupAICFormations( aic );
|
||||
|
||||
aicToggleButton = new Button( "toggle-aic-button", ["images/buttons/ai-full.svg"], () => {
|
||||
aicToggleButton = new Button( "toggle-aic-button", ["images/buttons/radar.svg"], () => {
|
||||
aic.toggleStatus();
|
||||
});
|
||||
|
||||
aicHelpButton = new Button( "aic-help-button", [ "images/buttons/question-mark.svg" ], () => {
|
||||
aic.toggleHelp();
|
||||
});
|
||||
|
||||
|
||||
/* Generic clicks */
|
||||
|
||||
document.addEventListener( "click", ( ev ) => {
|
||||
|
||||
if ( ev instanceof PointerEvent && ev.target instanceof HTMLElement ) {
|
||||
|
||||
if ( ev.target.classList.contains( "olympus-dialog-close" ) ) {
|
||||
ev.target.closest( "div.olympus-dialog" )?.classList.add( "hide" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
/* Default values */
|
||||
@@ -226,55 +247,4 @@ export function getUnitControlSliders() {
|
||||
}
|
||||
|
||||
|
||||
function setupAICFormations( aic:AIC ) {
|
||||
let $aicFormationList = document.getElementById( "aic-formation-list" );
|
||||
|
||||
if ( $aicFormationList ) {
|
||||
|
||||
/* // Example display
|
||||
<div>
|
||||
<div class="aic-formation-image">
|
||||
<img src="images/formations/azimuth.png" />
|
||||
</div>
|
||||
<div class="aic-formation-name">Azimuth</div>
|
||||
<div class="aic-formation-descriptor">(instructions)</div>
|
||||
</div>
|
||||
//*/
|
||||
|
||||
aic.getFormations().forEach( formation => {
|
||||
|
||||
// Image
|
||||
let imageDiv = document.createElement( "div" );
|
||||
imageDiv.classList.add( "aic-formation-image" );
|
||||
|
||||
let img = document.createElement( "img" );
|
||||
img.src = "images/formations/" + formation.icon;
|
||||
|
||||
imageDiv.appendChild( img );
|
||||
|
||||
// Name
|
||||
let nameDiv = document.createElement( "div" );
|
||||
nameDiv.classList.add( "aic-formation-name" );
|
||||
nameDiv.innerText = formation.label;
|
||||
|
||||
// Descriptor
|
||||
let descriptorDiv = document.createElement( "div" );
|
||||
descriptorDiv.classList.add( "aic-formation-descriptor" );
|
||||
descriptorDiv.innerText = formation.descriptor;
|
||||
|
||||
// Wrapper
|
||||
let wrapperDiv = document.createElement( "div" );
|
||||
wrapperDiv.dataset.formationName = formation.name;
|
||||
wrapperDiv.appendChild( imageDiv )
|
||||
wrapperDiv.appendChild( nameDiv );
|
||||
wrapperDiv.appendChild( descriptorDiv );
|
||||
|
||||
// Add to DOM
|
||||
$aicFormationList?.appendChild( wrapperDiv );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = setup;
|
||||
@@ -1,3 +1,37 @@
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const λ1 = deg2rad(lon1); // φ, λ in radians
|
||||
const λ2 = deg2rad(lon2);
|
||||
const y = Math.sin(λ2 - λ1) * Math.cos(φ2);
|
||||
const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2 - λ1);
|
||||
const θ = Math.atan2(y, x);
|
||||
const brng = (rad2deg(θ) + 360) % 360; // in degrees
|
||||
|
||||
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 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
|
||||
@@ -13,27 +47,24 @@ export function distance(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
return d;
|
||||
}
|
||||
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const λ1 = deg2rad(lon1); // φ, λ in radians
|
||||
const λ2 = deg2rad(lon2);
|
||||
const y = Math.sin(λ2 - λ1) * Math.cos(φ2);
|
||||
const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2 - λ1);
|
||||
const θ = Math.atan2(y, x);
|
||||
const brng = (rad2deg(θ) + 360) % 360; // in degrees
|
||||
|
||||
return brng;
|
||||
export function rad2deg(rad: number) {
|
||||
var pi = Math.PI;
|
||||
return rad / (pi / 180);
|
||||
}
|
||||
|
||||
export const zeroPad = function (num: number, places: number) {
|
||||
var string = String(num);
|
||||
while (string.length < places) {
|
||||
string += "0";
|
||||
|
||||
export function reciprocalHeading( heading:number ): number {
|
||||
|
||||
if ( heading > 180 ) {
|
||||
return heading - 180;
|
||||
}
|
||||
return string;
|
||||
|
||||
return heading + 180;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export const zeroAppend = function (num: number, places: number) {
|
||||
var string = String(num);
|
||||
while (string.length < places) {
|
||||
@@ -42,25 +73,11 @@ export const zeroAppend = function (num: number, places: number) {
|
||||
return string;
|
||||
}
|
||||
|
||||
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 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 const zeroPad = function (num: number, places: number) {
|
||||
var string = String(num);
|
||||
while (string.length < places) {
|
||||
string += "0";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
@@ -1,3 +1,17 @@
|
||||
<div class="olympus-panel control-panel control-panel-top" id="aic-control-panel">
|
||||
<div class="olympus-button" id="toggle-aic-button"></div>
|
||||
</div>
|
||||
<div class="olympus-button" id="aic-help-button"></div>
|
||||
</div>
|
||||
|
||||
<div id="aic-help" class="olympus-dialog hide">
|
||||
<div class="olympus-dialog-close">×</div>
|
||||
<div class="olympus-dialog-header">AIC Help</div>
|
||||
<div class="olympus-dialog-content">
|
||||
<p>How to be a good AIC and get people to do stuff good, too.</p>
|
||||
<div style="align-items: center; background:black; color:white; display:flex; height:250px; justify-content: center; justify-self: center; width:450px;">
|
||||
<div>[DCS with Volvo video]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="aic-teleprompt"></div>
|
||||
@@ -1,7 +1,33 @@
|
||||
<div id="aic-formation-panel" class="control-panel">
|
||||
<div id="aic-callsign-panel" class="control-panel">
|
||||
|
||||
<div class="aic-panel">
|
||||
<h2>My callsign</h2>
|
||||
<div>Magic</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="aic-toolbox" class="control-panel">
|
||||
|
||||
<div>Formations</div>
|
||||
<div id="aic-control-type" class="aic-panel">
|
||||
<h2>Control</h2>
|
||||
<div>
|
||||
<input type="radio" name="control-type" id="control-type-broadcast" value="broadcast" checked="checked" />
|
||||
<label for="control-type-broadcast">Broadcast</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" name="control-type" id="control-type-tactical" value="tactical" />
|
||||
<label for="control-type-tactical">Tactical</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="aic-formation-panel" class="aic-panel">
|
||||
|
||||
<h2>Formations</h2>
|
||||
|
||||
<div id="aic-formation-list"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="aic-formation-list"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user