Initial Commit

This commit is contained in:
2026-03-14 14:18:20 +01:00
commit 6bae9ddfc7
7 changed files with 410 additions and 0 deletions

Binary file not shown.

View File

@@ -0,0 +1,54 @@
/** This mixin makes a single line element fit exactly on the Roboto font for easier integration. */
ingame-ui#CustomPanel {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100% !important;
width: 100% !important;
/*border: 2px solid blue !important;*/
}
ingame-ui#CustomPanel #CustomPanelWrap {
display: flex;
flex-direction: column;
width: 100% !important;
height: 100% !important;
/*border: 2px solid red !important;*/
min-height: 0;
min-width: 0;
overflow: hidden;
align-items: stretch !important;
flex: 1 1 auto !important;
}
ingame-ui#CustomPanel #CustomPanelWrap #CustomPanelIframe {
flex: 1 1 auto !important;
border: 0;
}
ingame-ui#CustomPanel .ingameUiContent {
/*border: 2px solid green !important;*/
display: flex !important;
flex-direction: column !important;
width: 100% !important;
height: 100% !important;
min-height: 0 !important;
min-width: 0 !important;
overflow: hidden !important;
align-items: stretch !important;
flex: 1 1 auto !important;
}
ingame-ui#CustomPanel .ingameUiWrapper {
/*border: 2px solid yellow !important;*/
display: flex !important;
flex-direction: column !important;
width: 100% !important;
height: 100% !important;
min-height: 0 !important;
min-width: 0 !important;
overflow: hidden !important;
align-items: stretch !important;
flex: 1 1 auto !important;
}

View File

@@ -0,0 +1,247 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/SCSS/common.css" />
<link rel="stylesheet" href="CustomPanel.css" />
<script type="text/javascript" src="/JS/coherent.js"></script>
<script type="text/javascript" src="/JS/common.js"></script>
<script type="text/javascript" src="/JS/dataStorage.js"></script>
<script type="text/javascript" src="/JS/buttons.js"></script>
<script type="text/javascript" src="/JS/Services/ToolBarPanels.js"></script>
<script type="text/javascript" src="/Pages/VCockpit/Instruments/Shared/BaseInstrument.js"></script>
<script type="text/javascript" src="/JS/simvar.js"></script>
<link rel="import" href="/templates/NewPushButton/NewPushButton.html" />
<link rel="import" href="/templates/ToggleButton/toggleButton.html" />
<link rel="import" href="/templates/tabMenu/tabMenu.html" />
<link rel="import" href="/templates/ingameUi/ingameUi.html" />
<link rel="import" href="/templates/ingameUiHeader/ingameUiHeader.html" />
<link rel="import" href="/templates/NewListButton/NewListButton.html" />
<link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
<style>
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
#map {
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
}
</style>
<style>
.rotate-north {
top: .5em;
right: .5em;
}
</style>
</head>
<body class="border-box">
<ingamepanel-custom>
<ingame-ui id="CustomPanel" panel-id="PANEL_CUSTOM_PANEL" title="New Title" class="ingameUiFrame"
content-fit="true" min-width="160" min-height="90">
<div id="CustomPanelWrap">
<div id="map" class="map" tabindex="0"></div>
</div>
</ingame-ui>
</ingamepanel-custom>
<script>
var center_player = true;
window.app = {};
var app = window.app;
app.center_on_player = function (opt_options) {
var options = opt_options || {};
var button = document.createElement('button');
button.innerHTML = 'P';
// var this_ = this;
var action = function () {
center_player = true;
};
button.addEventListener('click', action, false);
button.addEventListener('touchstart', action, false);
var element = document.createElement('div');
element.className = 'rotate-north ol-unselectable ol-control';
element.appendChild(button);
ol.control.Control.call(this, {
element: element,
target: options.target
});
};
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point([0, 0])
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({
anchor: [0.5, 0.5],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAABYgAAAWIBXyfQUwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAUfSURBVHic7ZtvaJVVHMc/d+5Puf44KQ3LrNUsG/SH2V6oSRFUkAqVi16UkEFQEIPeaAz780IY+CKCerEgX2hGrAzBRQOZZVlIzIaJlWS6IPvH0Izpps7dXvx+Z+fs7t7Hp3uf85zN3S883N09v/M739/3ec55zu93npshDK4HngOagQqgF9gM9AfikyqeBgaBbM4xDDwfkFcqeBi4gAT8PfAKsAE4oP8bBR4Lxs4zMsBPSKDbgWrn3AzgAz13TG0vOdyJBHgOmJPnfB0wojb3pEWqIq2OgJv18yjwd57zJ4HD+veCVBiRrgDmlh+MsBnSzyrPXMaQpgCTEmUBQhMIjbIAoQmERlmA0ARCoyxAaAKhURYgNIHQKAsQmkBolAUITWC6oAnoQ6o9+yLs9qlNn7aZ8pgJbALOI4H9C6yOsF+tNllts0l9TEksR0pcpuz9KXBjjHbzkKKpaXcUeMgTRy+YBXQgJe4s8Bewpgg/K4HfsEJ0AtckxNEbVgLHSY50UmJ6xzzgE/zdtsuxewpmOKVWOY5CBtnOcieut4ArPPR1OfA6sq+QBU4D65BNlSBoAD7HXpUDwL0p9HsX8K3T7zdAYwr9jqEKUX5YCZxBrkx1RJukUQm0YjdZzwHtQI3vjpcAh7Dqfwnc7rvTCNQDuxw+PwMP+OioFlHY7OyeRMb+ZNnEbAEGsDvMHcBVSTl/FPgVq/JO5AWHyYa5wBYsz9+BJyaVw5SQyAXzekulgKKH7K1AD1a9H4ClCZGaD7wALIqwWQS8qLZJYCkSg4mnB4lxAiqRR9sZNTwLvEHpj5WrgbXAbuzV2BNhv0dtLmibteqjFNQgsZzFPrbXITEDcBM2V09iYVENrELygCHHrzl6I9r25rEfUl+rKG2t0YjEZvz2ocvpr7G5+ksUVyXKIGuEd7Bzhzn6gY1AG/EFaNM2/Tm+BrSPJRT3CK5AYjRL971g38tZXITDhcjtdSSH6Alk4rzPIdpCfAFa9HsGSYTeVZ9uH0e074VF8F6sPkZwHNbHbDwbmVH3YtNU857fTiRdzVfFKUYAFzVIur0FSYRcMQ4h43puzBjqnbaxBLhMO+/EZmPumG4Frr1Ip6UK4GIWIvQuxl+EEf3fGqIz0lgCVADLkFv5FOOD/hFJgG65CFEXSQrgYj5yAdyJ3Mz2nciFq8xpEylAIxLcsRyHA4gYy/4HORe+BHDRiCyA/mA89+NIncJwHyeAqdi+CRzMaTgIbAUeofTCQxoCGMxAOG9l4nvJB5FYTQFnbPHhjqPPkJeaa0sk4iJNAVzUIrF0Y5945viiUk9uRF5V7QE+BP5MkEBonAbe1+M64CngQSQ/aEuTSKg7IBLTfm+wLEBoAtMFNwD7kfG9I8Juh9rs1zaXBJqRcloW+Aep6xfC3WpjSnDN3tl5xpPYxOUX4I4YbRqw22DDwDPe2HlEBsnOTKLyFfl/JlMIs7GluVFkeTtl5qtq4GPsaquD4n4BUqVtjZ+PSHf3qWi8il1StybgrxW7hN2QgD/v6EbIro9hmyFeaWu9+uwugVde+BhXJms8UeD8HOBZ5DWYU3psRyrAheYJ4yvxrfDcQoEv1COFiRXA/Xn6fVyPUaSw0YWU175Dc3Zf8CHAqH42AW8jQS/IsTmMBNil31cgAt2m7ZqA15Atri7s5OdVjKTQzsTa/nlko+Nl5DlfCA1qsxtbqHGPdm+sE8RM4D3kjZFtSP5dV4SfOm27Ddne2gxcmRDHMfwHd9m82DeavcwAAAAASUVORK5CYII=',
}))
});
iconFeature.setStyle(iconStyle);
var vectorSource = new ol.source.Vector({
features: [iconFeature]
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
const defaultInteractions = ol.interaction.defaults();
const mouseWheelInteraction = defaultInteractions.getArray().find(el => el instanceof ol.interaction.MouseWheelZoom);
mouseWheelInteraction.setMouseAnchor(false);
var osm = new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://tile.osmand.net/hd/{z}/{x}/{y}.png',
crossOrigin: null,
tileSize: 1024,
attributions: ol.source.OSM.ATTRIBUTION,
})
});
ol.inherits(app.center_on_player, ol.control.Control);
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: {
collapsible: false
}
}).extend([
new app.center_on_player()
]),
interactions: defaultInteractions,
layers: [
osm,
vectorLayer
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 12,
zoomFactor: 2,
})
});
let sse = new EventSource("http://127.0.0.1:9000/sse");
let device_info = undefined;
sse.addEventListener("device-info", (event) => {
let data = JSON.parse(event.data);
device_info = data;
});
let btn = {
val: 0,
};
btn.tip = function () {
return (this.val & 1) == 1;
};
btn.a = function () {
return (this.val & 2) == 2;
};
btn.b = function () {
return (this.val & 4) == 4;
};
let oldx = undefined;
let oldy = undefined;
sse.addEventListener("state", (event) => {
if (typeof device_info === "undefined") {
return;
}
let data = JSON.parse(event.data);
let x = (device_info.max_y - data.y) / device_info.max_y;
let y = data.x / device_info.max_x;
if (typeof oldx === "undefined") {
oldx = x;
oldy = y;
}
let dx = oldx - x;
let dy = oldy - y;
btn.val = data.pen_buttons;
if (btn.tip()) {
if (btn.a()) {
let zoom = map.getView().getZoom();
map.getView().setZoom(zoom + (dy * 10));
} else if (btn.b()) {
center_player = true;
} else {
center_player = false;
console.log("tip");
var center = map.getView().getCenter();
var resolution = map.getView().getResolution();
map.getView().setCenter([center[0] + dx * 600 * resolution, center[1] + -dy * 800 * resolution]);
}
}
oldx = x;
oldy = y;
});
map.on('pointerdrag', () => {
console.log("dragging");
center_player = false;
});
setInterval(() => {
if (typeof SimVar === "undefined") { return; }
let lon = SimVar.GetSimVarValue("PLANE LONGITUDE", "radians") * (180 / Math.PI);
let lat = SimVar.GetSimVarValue("PLANE LATITUDE", "radians") * (180 / Math.PI);
let modifiedCoordinate = ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857');
let angle = SimVar.GetSimVarValue("PLANE HEADING DEGREES TRUE", "radians");
iconFeature.getGeometry().setCoordinates(modifiedCoordinate);
iconStyle.getImage().setRotation(angle);
if (center_player) {
map.getView().setCenter(modifiedCoordinate);
}
}, 250);
</script>
</body>
</html>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 296.999 296.999" style="enable-background:new 0 0 296.999 296.999;" xml:space="preserve">
<g>
<path d="M296.617,267.291L265.83,159.396c-1.222-4.281-5.133-7.232-9.583-7.232h-70.799c14.204-19.17,28.03-44.434,28.03-70.154
c0-35.842-29.148-65.002-64.977-65.002c-35.83,0-64.979,29.16-64.979,65.002c0,25.721,13.826,50.984,28.031,70.154h-70.8
c-4.45,0-8.361,2.951-9.583,7.232L0.383,267.291c-0.857,3.006-0.256,6.242,1.628,8.738c1.883,2.496,4.828,3.963,7.955,3.963
h277.068c3.127,0,6.072-1.467,7.955-3.963C296.873,273.533,297.474,270.297,296.617,267.291z M148.501,36.939
c24.838,0,45.046,20.219,45.046,45.07c0,33.348-31.124,68.463-45.046,82.502c-13.923-14.039-45.048-49.154-45.048-82.502
C103.453,57.158,123.662,36.939,148.501,36.939z M128.117,172.097c7.473,8.078,13.078,13.07,13.797,13.705
c1.883,1.656,4.234,2.486,6.587,2.486c2.353,0,4.705-0.83,6.587-2.486c0.719-0.635,6.324-5.627,13.796-13.705h79.843l2.77,9.707
l-38.549,32.125l-167.9-30.527l3.227-11.305H128.117z M76.247,260.06v-50.727l116.744,21.227l-35.401,29.5H76.247z M39.552,202.662
l16.763,3.047v54.352H23.174L39.552,202.662z M188.724,260.06l68.753-57.295l16.349,57.295H188.724z"/>
<path d="M175.311,82.01c0-14.861-12.027-26.951-26.811-26.951c-14.784,0-26.813,12.09-26.813,26.951
c0,14.859,12.028,26.951,26.813,26.951C163.284,108.961,175.311,96.869,175.311,82.01z M141.62,82.01
c0-3.871,3.087-7.02,6.881-7.02c3.793,0,6.879,3.148,6.879,7.02s-3.086,7.02-6.879,7.02C144.707,89.029,141.62,85.881,141.62,82.01
z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

29
layout.json Normal file
View File

@@ -0,0 +1,29 @@
{
"content": [
{
"path": "html_ui/InGamePanels/CustomPanel/CustomPanel.css",
"size": 1009,
"date": 132441482909180874
},
{
"path": "html_ui/InGamePanels/CustomPanel/CustomPanel.html",
"size": 3119,
"date": 132440507097241168
},
{
"path": "html_ui/InGamePanels/CustomPanel/CustomPanel.js",
"size": 5517,
"date": 132442481411972180
},
{
"path": "html_ui/Textures/Menu/toolbar/ICON_TOOLBAR_MAXIMUS_CUSTOM_PANEL.svg",
"size": 702,
"date": 132401952992678246
},
{
"path": "InGamePanels/maximus-ingamepanels-custom.spb",
"size": 806,
"date": 132453435271410222
}
]
}

29
manifest.json Normal file
View File

@@ -0,0 +1,29 @@
{
"dependencies": [
{
"name": "fs-base-propdefs",
"package_version": "0.1.2"
},
{
"name": "fs-base-ui",
"package_version": "0.1.10"
},
{
"name": "asobo-vcockpits-core",
"package_version": "0.1.12"
}
],
"content_type": "",
"title": "Custom In-Game Panel",
"manufacturer": "Maximus",
"creator": "Maximus",
"package_version": "2.0.0",
"minimum_game_version": "1.8.3",
"release_notes": {
"neutral": {
"LastUpdate": "",
"OlderHistory": ""
}
},
"total_package_size": "00000000000000014353"
}