1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-23 00:05:19 +03:00

Merge pull request #2159 from iNavFlight/MrD_Remove-switch-indicators-in-favour-of-custom-OSD-elements

Enhance OSD Custom Elements
This commit is contained in:
Darren Lines 2024-09-17 13:21:01 +01:00 committed by GitHub
commit 3c6197d037
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 490 additions and 259 deletions

View file

@ -599,7 +599,7 @@ var FC = {
this.FW_APPROACH = new FwApproachCollection(); this.FW_APPROACH = new FwApproachCollection();
this.OSD_CUSTOM_ELEMENTS = { this.OSD_CUSTOM_ELEMENTS = {
settings: {customElementsCount: 0, customElementTextSize: 0}, settings: {customElementsCount: 0, customElementTextSize: 0, customElementParts: 0},
items: [], items: [],
}; };

View file

@ -238,7 +238,8 @@ var MSPCodes = {
MSP2_ADSB_VEHICLE_LIST: 0x2090, MSP2_ADSB_VEHICLE_LIST: 0x2090,
MSP2_INAV_CUSTOM_OSD_ELEMENTS: 0x2100, MSP2_INAV_CUSTOM_OSD_ELEMENTS: 0x2100,
MSP2_INAV_SET_CUSTOM_OSD_ELEMENTS: 0x2101, MSP2_INAV_CUSTOM_OSD_ELEMENT: 0x2101,
MSP2_INAV_SET_CUSTOM_OSD_ELEMENTS: 0x2102,
MSP2_INAV_SERVO_CONFIG: 0x2200, MSP2_INAV_SERVO_CONFIG: 0x2200,
MSP2_INAV_SET_SERVO_CONFIG: 0x2201, MSP2_INAV_SET_SERVO_CONFIG: 0x2201,

View file

@ -1544,51 +1544,54 @@ var mspHelper = (function () {
break; break;
case MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENTS: case MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENTS:
FC.OSD_CUSTOM_ELEMENTS .items = []; FC.OSD_CUSTOM_ELEMENTS.items = [];
var index = 0; let settingsIdx = 0;
if(data.byteLength == 0){ if(data.byteLength == 0) {
FC.OSD_CUSTOM_ELEMENTS .settings.customElementsCount = 0; FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount = 0;
FC.OSD_CUSTOM_ELEMENTS .settings.customElementTextSize = 0; FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize = 0;
FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts = 0;
return; return;
} }
FC.OSD_CUSTOM_ELEMENTS .settings.customElementsCount = data.getUint8(index++); FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount = data.getUint8(settingsIdx++);
FC.OSD_CUSTOM_ELEMENTS .settings.customElementTextSize = data.getUint8(index++); FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize = data.getUint8(settingsIdx++);
FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts = data.getUint8(settingsIdx++);
break;
case MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENT:
var customElement = {
customElementItems: [],
customElementVisibility: {type: 0, value: 0},
customElementText: [],
};
for (i = 0; i < FC.OSD_CUSTOM_ELEMENTS .settings.customElementsCount; i++){ let index = 0;
var customElement = {
customElementItems: [],
customElementVisibility: {type: 0, value: 0},
customElementText: [],
};
for (let ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS .settings.customElementsCount; ii++){ for (let ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; ii++) {
var customElementPart = {type: 0, value: 0,}; var customElementPart = {type: 0, value: 0,};
customElementPart.type = data.getUint8(index++); customElementPart.type = data.getUint8(index++);
customElementPart.value = data.getUint16(index, true); customElementPart.value = data.getUint16(index, true);
index += 2;
customElement.customElementItems.push(customElementPart);
}
customElement.customElementVisibility.type = data.getUint8(index++);
customElement.customElementVisibility.value = data.getUint16(index, true);
index += 2; index += 2;
customElement.customElementItems.push(customElementPart);
for (let ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS .settings.customElementTextSize; ii++){
var char = data.getUint8(index++);
if(char === 0){
index += (FC.OSD_CUSTOM_ELEMENTS .settings.customElementTextSize - 1) - ii;
break;
}
customElement.customElementText[ii] = char;
}
customElement.customElementText = String.fromCharCode(...customElement.customElementText);
FC.OSD_CUSTOM_ELEMENTS .items.push(customElement)
} }
customElement.customElementVisibility.type = data.getUint8(index++);
customElement.customElementVisibility.value = data.getUint16(index, true);
index += 2;
for (let ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize; ii++) {
var char = data.getUint8(index++);
if(char === 0) {
index += (FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize - 1) - ii;
break;
}
customElement.customElementText[ii] = char;
}
customElement.customElementText = String.fromCharCode(...customElement.customElementText);
FC.OSD_CUSTOM_ELEMENTS.items.push(customElement);
break; break;
case MSPCodes.MSP2_INAV_GPS_UBLOX_COMMAND: case MSPCodes.MSP2_INAV_GPS_UBLOX_COMMAND:
// Just and ACK from the fc. // Just and ACK from the fc.
@ -2475,7 +2478,17 @@ var mspHelper = (function () {
}; };
self.loadOsdCustomElements = function (callback) { self.loadOsdCustomElements = function (callback) {
MSP.send_message(MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENTS, false, false, callback); MSP.send_message(MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENTS, false, false, nextCustomOSDElement);
var cosdeIdx = 0;
function nextCustomOSDElement() {
if (cosdeIdx < FC.OSD_CUSTOM_ELEMENTS .settings.customElementsCount - 1) {
MSP.send_message(MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENT, [cosdeIdx++], false, nextCustomOSDElement);
} else {
MSP.send_message(MSPCodes.MSP2_INAV_CUSTOM_OSD_ELEMENT, [cosdeIdx++], false, callback);
}
}
} }
self.sendModeRanges = function (onCompleteCallback) { self.sendModeRanges = function (onCompleteCallback) {

View file

@ -3628,6 +3628,9 @@
"osd_custom_element_settings": { "osd_custom_element_settings": {
"message": "Custom OSD elements" "message": "Custom OSD elements"
}, },
"osd_custom_element_settings_HELP": {
"message": "You can find the icon numbers by clicking this help button."
},
"custom_element": { "custom_element": {
"message": "Custom element" "message": "Custom element"
}, },
@ -4243,6 +4246,9 @@
"osdPanServoOffcentreWarning_HELP": { "osdPanServoOffcentreWarning_HELP": {
"message": "Degrees either side of the pan servo centre; where it is assumed camera is wanted to be facing forwards, but isn't at 0. If in this range and not 0 for longer than 10 seconds, the pan servo offset OSD element will blink. 0 means the warning is disabled." "message": "Degrees either side of the pan servo centre; where it is assumed camera is wanted to be facing forwards, but isn't at 0. If in this range and not 0 for longer than 10 seconds, the pan servo offset OSD element will blink. 0 means the warning is disabled."
}, },
"osdGroupOSDCustomElements": {
"message": "OSD Custom Elements"
},
"osdGroupGVars": { "osdGroupGVars": {
"message": "Global Variables" "message": "Global Variables"
}, },
@ -4333,6 +4339,9 @@
"osd_switch_indicator_settings": { "osd_switch_indicator_settings": {
"message": "Switch Indicator Settings" "message": "Switch Indicator Settings"
}, },
"osd_switch_indicator_settings_HELP": {
"message": "It is recommended to use the Custom OSD Elements as a replacemtent for switch indicators. They are much more powerful. Click to see an example."
},
"osd_switch_indicators_align_left": { "osd_switch_indicators_align_left": {
"message": "Align switch names to left of switches" "message": "Align switch names to left of switches"
}, },

View file

@ -301,8 +301,10 @@
</label> </label>
</div> </div>
</div> </div>
<div class="gui_box grey switch-indicator-container"> <div class="gui_box grey switch-indicator-container">
<div class="gui_box_titlebar"> <div class="gui_box_titlebar">
<a href="https://github.com/iNavFlight/inav/wiki/OSD-custom-messages" target="_blank"></a><div for="osd_switch_indicator_settings" class="helpicon cf_tip" data-i18n_title="osd_switch_indicator_settings_HELP"></div></a>
<div class="spacer_box_title" data-i18n="osd_switch_indicator_settings"></div> <div class="spacer_box_title" data-i18n="osd_switch_indicator_settings"></div>
</div> </div>
<div class="spacer_box settings"> <div class="spacer_box settings">
@ -336,9 +338,9 @@
</div> </div>
</div> </div>
<div class="gui_box grey custom-element-container"> <div class="gui_box grey custom-element-container">
<div class="gui_box_titlebar"> <div class="gui_box_titlebar">
<a href="https://github.com/iNavFlight/inav-configurator/resources/osd/INAV%20Character%20Map.md" target="_blank"><div for="osd_custom_element_settings" class="helpicon cf_tip" data-i18n_title="osd_custom_element_settings_HELP"></div></a>
<div class="spacer_box_title" data-i18n="osd_custom_element_settings"></div> <div class="spacer_box_title" data-i18n="osd_custom_element_settings"></div>
</div> </div>
<div class="spacer_box settings" id="osdCustomElements"></div> <div class="spacer_box settings" id="osdCustomElements"></div>

View file

@ -19,6 +19,7 @@ const { globalSettings } = require('./../js/globalSettings');
const { PortHandler } = require('./../js/port_handler'); const { PortHandler } = require('./../js/port_handler');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const jBox = require('./../js/libraries/jBox/jBox.min'); const jBox = require('./../js/libraries/jBox/jBox.min');
const { Console } = require('console');
var SYM = SYM || {}; var SYM = SYM || {};
@ -554,6 +555,7 @@ OSD.DjiElements = {
"VTX", "VTX",
"CRSF", "CRSF",
"SwitchIndicators", "SwitchIndicators",
"OSDCustomElements",
"GVars", "GVars",
"PIDs", "PIDs",
"PIDOutputs", "PIDOutputs",
@ -1877,6 +1879,67 @@ OSD.constants = {
} }
] ]
}, },
{
name: 'osdGroupOSDCustomElements',
items: [
{
name: 'CUSTOM_ELEMENT_1',
id: 147,
min_version: '7.1.0',
positionable: true,
preview: "CE_1",
},
{
name: 'CUSTOM_ELEMENT_2',
id: 148,
min_version: '7.1.0',
positionable: true,
preview: "CE_2",
},
{
name: 'CUSTOM_ELEMENT_3',
id: 149,
min_version: '7.1.0',
positionable: true,
preview: "CE_3",
},
{
name: 'CUSTOM_ELEMENT_4',
id: 154,
min_version: '8.0.0',
positionable: true,
preview: "CE_4",
},
{
name: 'CUSTOM_ELEMENT_5',
id: 155,
min_version: '8.0.0',
positionable: true,
preview: "CE_5",
},
{
name: 'CUSTOM_ELEMENT_6',
id: 156,
min_version: '8.0.0',
positionable: true,
preview: "CE_6",
},
{
name: 'CUSTOM_ELEMENT_7',
id: 157,
min_version: '8.0.0',
positionable: true,
preview: "CE_7",
},
{
name: 'CUSTOM_ELEMENT_8',
id: 158,
min_version: '8.0.0',
positionable: true,
preview: "CE_8",
},
]
},
{ {
name: 'osdGroupGVars', name: 'osdGroupGVars',
items: [ items: [
@ -1903,27 +1966,6 @@ OSD.constants = {
id: 116, id: 116,
positionable: true, positionable: true,
preview: 'G3:30126' preview: 'G3:30126'
},
{
name: 'CUSTOM ELEMENT 1',
id: 147,
min_version: '7.1.0',
positionable: true,
preview: "CE_1",
},
{
name: 'CUSTOM ELEMENT 2',
id: 148,
min_version: '7.1.0',
positionable: true,
preview: "CE_2",
},
{
name: 'CUSTOM ELEMENT 3',
id: 149,
min_version: '7.1.0',
positionable: true,
preview: "CE_3",
} }
] ]
}, },
@ -2953,176 +2995,178 @@ OSD.GUI.updatePreviews = function() {
// buffer the preview; // buffer the preview;
OSD.data.preview = []; OSD.data.preview = [];
// clear the buffer if (OSD.data.display_size != undefined) {
for (let i = 0; i < OSD.data.display_size.total; i++) { // clear the buffer
OSD.data.preview.push([null, ' '.charCodeAt(0)]); for (let i = 0; i < OSD.data.display_size.total; i++) {
}; OSD.data.preview.push([null, ' '.charCodeAt(0)]);
};
// draw all the displayed items and the drag and drop preview images // draw all the displayed items and the drag and drop preview images
for (var ii = 0; ii < OSD.data.items.length; ii++) { for (var ii = 0; ii < OSD.data.items.length; ii++) {
var item = OSD.get_item(ii); var item = OSD.get_item(ii);
if (!item || !OSD.is_item_displayed(item, OSD.data.groups[item.id])) { if (!item || !OSD.is_item_displayed(item, OSD.data.groups[item.id])) {
continue;
}
var itemData = OSD.data.items[ii];
if (!itemData.isVisible) {
continue;
}
if (itemData.x >= OSD.data.display_size.x)
{
continue;
}
// DJI HD FPV: Hide elements that only appear in craft name
if (OSD.DjiElements.craftNameElements.includes(item.name) &&
$('#djiUnsupportedElements').find('input').is(':checked')) {
continue;
}
var j = (itemData.position >= 0) ? itemData.position : itemData.position + OSD.data.display_size.total;
// create the preview image
item.preview_img = new Image();
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
// fill the screen buffer
var preview = OSD.get_item_preview(item);
if (!preview) {
continue;
}
var x = 0;
var y = 0;
for (let i = 0; i < preview.length; i++) {
var charCode = preview.charCodeAt(i);
if (charCode == '\n'.charCodeAt(0)) {
x = 0;
y++;
continue; continue;
} }
var previewPos = j + x + (y * OSD.data.display_size.x); var itemData = OSD.data.items[ii];
if (previewPos >= OSD.data.preview.length) { if (!itemData.isVisible) {
// Character is outside the viewport continue;
}
if (itemData.x >= OSD.data.display_size.x)
{
continue;
}
// DJI HD FPV: Hide elements that only appear in craft name
if (OSD.DjiElements.craftNameElements.includes(item.name) &&
$('#djiUnsupportedElements').find('input').is(':checked')) {
continue;
}
var j = (itemData.position >= 0) ? itemData.position : itemData.position + OSD.data.display_size.total;
// create the preview image
item.preview_img = new Image();
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
// fill the screen buffer
var preview = OSD.get_item_preview(item);
if (!preview) {
continue;
}
var x = 0;
var y = 0;
for (let i = 0; i < preview.length; i++) {
var charCode = preview.charCodeAt(i);
if (charCode == '\n'.charCodeAt(0)) {
x = 0;
y++;
continue;
}
var previewPos = j + x + (y * OSD.data.display_size.x);
if (previewPos >= OSD.data.preview.length) {
// Character is outside the viewport
x++;
continue;
}
// test if this position already has a character placed
if (OSD.data.preview[previewPos][0] !== null) {
// if so set background color to red to show user double usage of position
OSD.data.preview[previewPos] = [item, charCode, 'red'];
} else {
OSD.data.preview[previewPos] = [item, charCode];
}
// draw the preview
var img = new Image();
img.src = FONT.draw(charCode);
ctx.drawImage(img, x*FONT.constants.SIZES.CHAR_WIDTH, y*FONT.constants.SIZES.CHAR_HEIGHT);
x++; x++;
continue;
} }
// test if this position already has a character placed item.preview_img.src = canvas.toDataURL('image/png');
if (OSD.data.preview[previewPos][0] !== null) { // Required for NW.js - Otherwise the <img /> will
// if so set background color to red to show user double usage of position // consume drag/drop events.
OSD.data.preview[previewPos] = [item, charCode, 'red']; item.preview_img.style.pointerEvents = 'none';
}
var centerPosition = (OSD.data.display_size.x * OSD.data.display_size.y / 2);
if (OSD.data.display_size.y % 2 == 0) {
centerPosition += Math.floor(OSD.data.display_size.x / 2);
}
let hudCenterPosition = centerPosition - (OSD.constants.VIDEO_COLS[video_type] * $('#osd_horizon_offset').val());
// artificial horizon
if ($('input[name="ARTIFICIAL_HORIZON"]').prop('checked')) {
for (let i = 0; i < 9; i++) {
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 4 + i, SYM.AH_BAR9_0 + 4);
}
}
// crosshairs
if ($('input[name="CROSSHAIRS"]').prop('checked')) {
let crsHNumber = Settings.getInputValue('osd_crosshairs_style');
if (crsHNumber == 1) {
// AIRCRAFT style
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 2, SYM.AH_AIRCRAFT0);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_AIRCRAFT1);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_AIRCRAFT2);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_AIRCRAFT3);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 2, SYM.AH_AIRCRAFT4);
} else if ((crsHNumber > 1) && (crsHNumber < 8)) {
// TYPES 3 to 8 (zero indexed)
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_CROSSHAIRS[crsHNumber][0]);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_CROSSHAIRS[crsHNumber][1]);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_CROSSHAIRS[crsHNumber][2]);
} else { } else {
OSD.data.preview[previewPos] = [item, charCode]; // DEFAULT or unknown style
} OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_CENTER_LINE);
// draw the preview OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_CROSSHAIRS[crsHNumber]);
var img = new Image(); OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_CENTER_LINE_RIGHT);
img.src = FONT.draw(charCode);
ctx.drawImage(img, x*FONT.constants.SIZES.CHAR_WIDTH, y*FONT.constants.SIZES.CHAR_HEIGHT);
x++;
}
item.preview_img.src = canvas.toDataURL('image/png');
// Required for NW.js - Otherwise the <img /> will
// consume drag/drop events.
item.preview_img.style.pointerEvents = 'none';
}
var centerPosition = (OSD.data.display_size.x * OSD.data.display_size.y / 2);
if (OSD.data.display_size.y % 2 == 0) {
centerPosition += Math.floor(OSD.data.display_size.x / 2);
}
let hudCenterPosition = centerPosition - (OSD.constants.VIDEO_COLS[video_type] * $('#osd_horizon_offset').val());
// artificial horizon
if ($('input[name="ARTIFICIAL_HORIZON"]').prop('checked')) {
for (let i = 0; i < 9; i++) {
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 4 + i, SYM.AH_BAR9_0 + 4);
}
}
// crosshairs
if ($('input[name="CROSSHAIRS"]').prop('checked')) {
let crsHNumber = Settings.getInputValue('osd_crosshairs_style');
if (crsHNumber == 1) {
// AIRCRAFT style
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 2, SYM.AH_AIRCRAFT0);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_AIRCRAFT1);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_AIRCRAFT2);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_AIRCRAFT3);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 2, SYM.AH_AIRCRAFT4);
} else if ((crsHNumber > 1) && (crsHNumber < 8)) {
// TYPES 3 to 8 (zero indexed)
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_CROSSHAIRS[crsHNumber][0]);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_CROSSHAIRS[crsHNumber][1]);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_CROSSHAIRS[crsHNumber][2]);
} else {
// DEFAULT or unknown style
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - 1, SYM.AH_CENTER_LINE);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition, SYM.AH_CROSSHAIRS[crsHNumber]);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + 1, SYM.AH_CENTER_LINE_RIGHT);
}
}
// sidebars
if ($('input[name="HORIZON_SIDEBARS"]').prop('checked')) {
var hudwidth = OSD.constants.AHISIDEBARWIDTHPOSITION;
var hudheight = OSD.constants.AHISIDEBARHEIGHTPOSITION;
for (let i = -hudheight; i <= hudheight; i++) {
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - hudwidth + (i * FONT.constants.SIZES.LINE), SYM.AH_DECORATION);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + hudwidth + (i * FONT.constants.SIZES.LINE), SYM.AH_DECORATION);
}
// AH level indicators
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - hudwidth + 1, SYM.AH_LEFT);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + hudwidth - 1, SYM.AH_RIGHT);
}
OSD.GUI.updateMapPreview(centerPosition, 'MAP_NORTH', 'N', SYM.HOME);
OSD.GUI.updateMapPreview(centerPosition, 'MAP_TAKEOFF', 'T', SYM.HOME);
OSD.GUI.updateMapPreview(centerPosition, 'RADAR', null, SYM.DIR_TO_HOME);
// render
var $preview = $('.display-layout .preview').empty();
var $row = $('<div class="row"/>');
for (let i = 0; i < OSD.data.display_size.total;) {
var charCode = OSD.data.preview[i];
var colorStyle = '';
if (typeof charCode === 'object') {
var item = OSD.data.preview[i][0];
charCode = OSD.data.preview[i][1];
if (OSD.data.preview[i][2] !== undefined) {
// if third field is set it contains a background color
colorStyle = 'style="background-color: ' + OSD.data.preview[i][2] + ';"';
} }
} }
var $img = $('<div class="char"' + colorStyle + '><img src=' + FONT.draw(charCode) + '></img></div>')
.on('mouseenter', OSD.GUI.preview.onMouseEnter)
.on('mouseleave', OSD.GUI.preview.onMouseLeave)
.on('dragover', OSD.GUI.preview.onDragOver)
.on('dragleave', OSD.GUI.preview.onDragLeave)
.on('drop', OSD.GUI.preview.onDrop)
.data('item', item)
.data('position', i);
// Required for NW.js - Otherwise the <img /> will
// consume drag/drop events.
$img.find('img').css('pointer-events', 'none');
if (item && item.positionable !== false) {
var nameKey = 'osdElement_' + item.name;
var nameMessage = i18n.getMessage(nameKey);
if (!nameMessage) { // sidebars
nameMessage = inflection.titleize(item.name); if ($('input[name="HORIZON_SIDEBARS"]').prop('checked')) {
var hudwidth = OSD.constants.AHISIDEBARWIDTHPOSITION;
var hudheight = OSD.constants.AHISIDEBARHEIGHTPOSITION;
for (let i = -hudheight; i <= hudheight; i++) {
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - hudwidth + (i * FONT.constants.SIZES.LINE), SYM.AH_DECORATION);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + hudwidth + (i * FONT.constants.SIZES.LINE), SYM.AH_DECORATION);
} }
// AH level indicators
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition - hudwidth + 1, SYM.AH_LEFT);
OSD.GUI.checkAndProcessSymbolPosition(hudCenterPosition + hudwidth - 1, SYM.AH_RIGHT);
}
$img.addClass('field-' + item.id) OSD.GUI.updateMapPreview(centerPosition, 'MAP_NORTH', 'N', SYM.HOME);
OSD.GUI.updateMapPreview(centerPosition, 'MAP_TAKEOFF', 'T', SYM.HOME);
OSD.GUI.updateMapPreview(centerPosition, 'RADAR', null, SYM.DIR_TO_HOME);
// render
var $preview = $('.display-layout .preview').empty();
var $row = $('<div class="row"/>');
for (let i = 0; i < OSD.data.display_size.total;) {
var charCode = OSD.data.preview[i];
var colorStyle = '';
if (typeof charCode === 'object') {
var item = OSD.data.preview[i][0];
charCode = OSD.data.preview[i][1];
if (OSD.data.preview[i][2] !== undefined) {
// if third field is set it contains a background color
colorStyle = 'style="background-color: ' + OSD.data.preview[i][2] + ';"';
}
}
var $img = $('<div class="char"' + colorStyle + '><img src=' + FONT.draw(charCode) + '></img></div>')
.on('mouseenter', OSD.GUI.preview.onMouseEnter)
.on('mouseleave', OSD.GUI.preview.onMouseLeave)
.on('dragover', OSD.GUI.preview.onDragOver)
.on('dragleave', OSD.GUI.preview.onDragLeave)
.on('drop', OSD.GUI.preview.onDrop)
.data('item', item) .data('item', item)
.prop('draggable', true) .data('position', i);
.on('dragstart', OSD.GUI.preview.onDragStart) // Required for NW.js - Otherwise the <img /> will
.prop('title', nameMessage); // consume drag/drop events.
} $img.find('img').css('pointer-events', 'none');
if (item && item.positionable !== false) {
var nameKey = 'osdElement_' + item.name;
var nameMessage = i18n.getMessage(nameKey);
$row.append($img); if (!nameMessage) {
if (++i % OSD.data.display_size.x == 0) { nameMessage = inflection.titleize(item.name);
$preview.append($row); }
$row = $('<div class="row"/>');
$img.addClass('field-' + item.id)
.data('item', item)
.prop('draggable', true)
.on('dragstart', OSD.GUI.preview.onDragStart)
.prop('title', nameMessage);
}
$row.append($img);
if (++i % OSD.data.display_size.x == 0) {
$preview.append($row);
$row = $('<div class="row"/>');
}
} }
} }
}; };
@ -3290,6 +3334,7 @@ TABS.osd = {};
TABS.osd.initialize = function (callback) { TABS.osd.initialize = function (callback) {
mspHelper.loadServoMixRules(); mspHelper.loadServoMixRules();
mspHelper.loadLogicConditions();
if (GUI.active_tab != 'osd') { if (GUI.active_tab != 'osd') {
GUI.active_tab = 'osd'; GUI.active_tab = 'osd';
@ -3338,7 +3383,7 @@ TABS.osd.initialize = function (callback) {
let testExp = new RegExp('^[A-Za-z0-9]'); let testExp = new RegExp('^[A-Za-z0-9]');
let testText = $(this).val(); let testText = $(this).val();
if (testExp.test(testText.slice(-1))) { if (testExp.test(testText.slice(-1))) {
$(this).val(testText.toUpperCase()); $(this).val(testText.toUpperCase().slice(0, 4));
} else { } else {
$(this).val(testText.slice(0, -1)); $(this).val(testText.slice(0, -1));
} }
@ -3495,30 +3540,49 @@ function createCustomElements(){
var customElementTable = $('<table>').addClass('osdCustomElement_main_table'); var customElementTable = $('<table>').addClass('osdCustomElement_main_table');
var customElementRowType = $('<tr>').data('row', i); var customElementRowType = $('<tr>').data('row', i);
var customElementRowValue = $('<tr>').data('row', i); var customElementRowValue = $('<tr>').data('row', i);
var customElementLabel = $('<tr>'); var customElementLabel = $('<tr>');
customElementLabel.append($('<td>').attr('colspan', 2).append($('<span>').html(i18n.getMessage("custom_element") + ' ' + (i + 1))));
for(var ii = 0; ii < 3; ii++){ for(var ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; ii++){
var select = $('<select>').addClass('osdCustomElement-' + i + '-part-' + ii + '-type').data('valueCellClass', 'osdCustomElement-' + i + '-part-' + ii + '-value').html(` var select = $('<select>').addClass('osdCustomElement-' + i + '-part-' + ii + '-type').data('valueCellClass', 'osdCustomElement-' + i + '-part-' + ii + '-value').html(`
<option value="0">none</option> <option value="0">none</option>
<option data-value="text" value="1">Text</option> <option data-value="text" value="1">Text</option>
<option data-value="ico" value="2">Icon Static</option> <option data-value="ico" value="2">Icon Static</option>
<option data-value="ico_gv" value="3">Icon Global Variable</option> <option data-value="ico_gv" value="3">Icon from Global Variable</option>
<option data-value="gv" value="4">Global Variable 00000</option> <option data-value="ico_lc" value="4">Icon from Logic Condition</option>
<option data-value="gv" value="5">Global Variable 000.00</option> <option data-value="gv" value="5">Global Variable 0</option>
<option data-value="gv" value="6">Global Variable 000</option> <option data-value="gv" value="6">Global Variable 00</option>
<option data-value="gv" value="7">Global Variable 0.0</option> <option data-value="gv" value="7">Global Variable 000</option>
<option data-value="gv" value="8">Global Variable 0000</option>
<option data-value="gv" value="9">Global Variable 00000</option>
<option data-value="gv" value="10">Global Variable 0.0</option>
<option data-value="gv" value="11">Global Variable 00.0</option>
<option data-value="gv" value="12">Global Variable 00.00</option>
<option data-value="gv" value="13">Global Variable 000.0</option>
<option data-value="gv" value="14">Global Variable 000.00</option>
<option data-value="gv" value="15">Global Variable 0000.0</option>
<option data-value="lc" value="16">Logic Condition 0</option>
<option data-value="lc" value="17">Logic Condition 00</option>
<option data-value="lc" value="18">Logic Condition 000</option>
<option data-value="lc" value="19">Logic Condition 0000</option>
<option data-value="lc" value="20">Logic Condition 00000</option>
<option data-value="lc" value="21">Logic Condition 0.0</option>
<option data-value="lc" value="22">Logic Condition 00.0</option>
<option data-value="lc" value="23">Logic Condition 00.00</option>
<option data-value="lc" value="24">Logic Condition 000.0</option>
<option data-value="lc" value="25">Logic Condition 000.00</option>
<option data-value="lc" value="26">Logic Condition 0000.0</option>
`); `);
customElementRowType.append($('<td>').append(select)); customElementRowType.append($('<td>').append(select));
customElementRowValue.append($('<td>').addClass('osdCustomElement-' + i + '-part-' + ii + '-value').append( customElementRowValue.append($('<td>').addClass('osdCustomElement-' + i + '-part-' + ii + '-value').append(
$('<input>').addClass('value').addClass('text').attr('type', 'text').attr('maxlength', FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize).hide() $('<input>').addClass('value').addClass('text').attr('type', 'text').attr('maxlength', FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize).hide()).append(
).append( $('<input>').addClass('value').addClass('ico').attr('min', 1).attr('max', 255).hide()).append(
$('<input>').addClass('value').addClass('ico').attr('min', 1).attr('max', 255).hide() $('<select>').addClass('value').addClass('ico_gv').html(getGVoptions()).hide()).append(
).append( $('<select>').addClass('value').addClass('ico_lc').html(getLCoptions()).hide()).append(
$('<select>').addClass('value').addClass('ico_gv').html(getGVoptions()).hide() $('<select>').addClass('value').addClass('gv').html(getGVoptions()).hide()).append(
).append( $('<select>').addClass('value').addClass('lc').html(getLCoptions()).hide()
$('<select>').addClass('value').addClass('gv').html(getGVoptions()).hide()
)); ));
select.change(function(){ select.change(function(){
@ -3526,6 +3590,7 @@ function createCustomElements(){
var valueBlock = $('.' + $(this).data('valueCellClass')) var valueBlock = $('.' + $(this).data('valueCellClass'))
valueBlock.find('.value').hide(); valueBlock.find('.value').hide();
valueBlock.find('.' + dataValue).show(); valueBlock.find('.' + dataValue).show();
updateOSDCustomElementsDisplay();
}); });
} }
@ -3548,9 +3613,7 @@ function createCustomElements(){
valueBlock.find('.' + dataValue).show(); valueBlock.find('.' + dataValue).show();
}); });
customElementLabel.append($('<td>').attr('colspan', 2).append($('<span>').html(i18n.getMessage("custom_element") + ' ' + (i + 1)))); customElementTable.append(customElementLabel).append(customElementRowType).append(customElementRowValue);
customElementTable.append(customElementRowType).append(customElementRowValue).append(customElementLabel);
label.append(customElementTable); label.append(customElementTable);
customElementsContainer.append(label); customElementsContainer.append(label);
} }
@ -3559,27 +3622,145 @@ function createCustomElements(){
customElementsInitCallback(); customElementsInitCallback();
} }
function updateOSDCustomElementsDisplay() {
let foundOSDCustomElements = 0;
let generalGroup = OSD.constants.ALL_DISPLAY_GROUPS.filter(function(e) {
return e.name == "osdGroupOSDCustomElements";
})[0];
for (var i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount; i++) {
if ($('.osdCustomElement-' + i + '-part-0-type').val() != undefined) {
for (let si = 0; si < generalGroup.items.length; si++) {
if (generalGroup.items[si].name == "CUSTOM_ELEMENT_" + (i + 1)) {
let preview = "";
foundOSDCustomElements++;
for (let ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; ii++) {
var typeCell = $('.osdCustomElement-' + i + '-part-' + ii + '-type');
var valueCell = $('.osdCustomElement-' + i + '-part-' + ii + '-value');
switch (parseInt(typeCell.val())) {
case 1:
preview += valueCell.find('.text').val();
break;
case 2:
preview += FONT.symbol("0x" + parseInt(valueCell.find('.ico').val()).toString(16).toUpperCase());
break;
case 3:
preview += FONT.symbol(SYM.HOME);
break;
case 4:
preview += FONT.symbol(SYM.HOME);
break;
case 5:
case 16:
preview += " 2";
break;
case 6:
case 17:
preview += " 57";
break;
case 7:
case 18:
preview += " 316";
break;
case 8:
case 19:
preview += " 6926";
break;
case 9:
case 20:
preview += " 36520";
break;
case 10:
case 21:
preview += " " + FONT.embed_dot("1.6");
break;
case 11:
case 22:
preview += " " + FONT.embed_dot("21.4");
break;
case 12:
case 23:
preview += " " + FONT.embed_dot("34.26");
break;
case 13:
case 24:
preview += " " + FONT.embed_dot("315.7");
break;
case 14:
case 25:
preview += " " + FONT.embed_dot("562.46");
break;
case 15:
case 26:
preview += " " + FONT.embed_dot("4629.1");
break;
}
}
preview = preview.trim();
if (preview == "") {
preview = "CE_" + (i + 1);
}
generalGroup.items[si].preview = preview;
}
}
}
if (foundOSDCustomElements >= FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount) {
break;
}
}
OSD.GUI.updatePreviews();
}
function fillCustomElementsValues() { function fillCustomElementsValues() {
for (var i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount; i++) { for (var i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementsCount; i++) {
for (var ii = 0; ii < 3; ii++) { for (var ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; ii++) {
$('.osdCustomElement-' + i + '-part-' + ii + '-type').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].type).trigger('change'); $('.osdCustomElement-' + i + '-part-' + ii + '-type').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].type).trigger('change');
var valueCell = $('.osdCustomElement-' + i + '-part-' + ii + '-value'); var valueCell = $('.osdCustomElement-' + i + '-part-' + ii + '-value');
switch (FC.OSD_CUSTOM_ELEMENTS .items[i].customElementItems[ii].type){ switch (FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].type){
case 1: case 1:
valueCell.find('.text').val(FC.OSD_CUSTOM_ELEMENTS .items[i].customElementText).trigger('change'); valueCell.find('.text').val(FC.OSD_CUSTOM_ELEMENTS .items[i].customElementText).trigger('change');
break; break;
case 2: case 2:
valueCell.find('.ico').val(FC.OSD_CUSTOM_ELEMENTS .items[i].customElementItems[ii].value).trigger('change'); valueCell.find('.ico').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].value).trigger('change');
break; break;
case 3: case 3:
valueCell.find('.ico_gv').val(FC.OSD_CUSTOM_ELEMENTS .items[i].customElementItems[ii].value).trigger('change'); valueCell.find('.ico_gv').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].value).trigger('change');
break; break;
case 4: case 4:
valueCell.find('.ico_lc').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].value).trigger('change');
break;
case 5: case 5:
case 6: case 6:
case 7: case 7:
valueCell.find('.gv').val(FC.OSD_CUSTOM_ELEMENTS .items[i].customElementItems[ii].value).trigger('change'); case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
valueCell.find('.gv').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].value).trigger('change');
break;
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
valueCell.find('.lc').val(FC.OSD_CUSTOM_ELEMENTS.items[i].customElementItems[ii].value).trigger('change');
break; break;
} }
} }
@ -3617,7 +3798,7 @@ function customElementsInitCallback() {
} }
function customElementNormaliseRow(row){ function customElementNormaliseRow(row){
for(var i = 0; i < 3; i++){ for(var i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; i++){
var elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type'); var elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type');
var valueCell = $('.' + elementType.data('valueCellClass')); var valueCell = $('.' + elementType.data('valueCellClass'));
@ -3628,15 +3809,15 @@ function customElementNormaliseRow(row){
break; break;
case 2: case 2:
valueCell.find('.ico').val(valueCell.find('.ico').val() > 255 ? 255 : valueCell.find('.ico').val()); valueCell.find('.ico').val(valueCell.find('.ico').val() > 255 ? 255 : valueCell.find('.ico').val());
valueCell.find('.ico').val(valueCell.find('.ico').val() < 1 ? 1 : valueCell.find('.ico').val()); valueCell.find('.ico').val((valueCell.find('.ico').val() != '' && valueCell.find('.ico').val() < 1 )? 1 : valueCell.find('.ico').val());
} }
} }
updateOSDCustomElementsDisplay();
} }
function customElementDisableNonValidOptionsRow(row){ function customElementDisableNonValidOptionsRow(row) {
var selectedTextIndex = false; var selectedTextIndex = false;
for(let i = 0; i < 3; i++){ for(let i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; i++){
let elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type'); let elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type');
if(parseInt(elementType.val()) === 1) if(parseInt(elementType.val()) === 1)
@ -3646,7 +3827,7 @@ function customElementDisableNonValidOptionsRow(row){
} }
} }
for(let i = 0; i < 3; i++){ for(let i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; i++){
let elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type'); let elementType = $('.osdCustomElement-' + row + '-part-' + i + '-type');
if(i !== selectedTextIndex && selectedTextIndex !== false){ if(i !== selectedTextIndex && selectedTextIndex !== false){
elementType.find('option[value="1"]').attr('disabled', 'disabled'); elementType.find('option[value="1"]').attr('disabled', 'disabled');
@ -3657,13 +3838,12 @@ function customElementDisableNonValidOptionsRow(row){
} }
function customElementGetDataForRow(row){ function customElementGetDataForRow(row){
var data = []; var data = [];
data.push8(row); data.push8(row);
var text = ""; var text = "";
for(var ii = 0; ii < 3; ii++){ for(var ii = 0; ii < FC.OSD_CUSTOM_ELEMENTS.settings.customElementParts; ii++){
var elementType = $('.osdCustomElement-' + row + '-part-' + ii + '-type'); var elementType = $('.osdCustomElement-' + row + '-part-' + ii + '-type');
var valueCell = $('.' + elementType.data('valueCellClass')); var valueCell = $('.' + elementType.data('valueCellClass'));
var partValue = 0; var partValue = 0;
@ -3679,11 +3859,34 @@ function customElementGetDataForRow(row){
partValue = parseInt(valueCell.find('.ico_gv').find(':selected').val()); partValue = parseInt(valueCell.find('.ico_gv').find(':selected').val());
break; break;
case 4: case 4:
partValue = parseInt(valueCell.find('.ico_lc').find(':selected').val());
break;
case 5: case 5:
case 6: case 6:
case 7: case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
partValue = parseInt(valueCell.find('.gv').find(':selected').val()); partValue = parseInt(valueCell.find('.gv').find(':selected').val());
break; break;
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
partValue = parseInt(valueCell.find('.lc').find(':selected').val());
break;
} }
data.push8(parseInt(elementType.val())); data.push8(parseInt(elementType.val()));
@ -3705,7 +3908,9 @@ function customElementGetDataForRow(row){
data.push8(parseInt(elementVisibilityType.val())); data.push8(parseInt(elementVisibilityType.val()));
data.push16(visibilityValue); data.push16(visibilityValue);
for(var i = 0; i < FC.OSD_CUSTOM_ELEMENTS .settings.customElementTextSize; i++){ console.log("Saving osd custom data for number " + row + " | data: " + data);
for(var i = 0; i < FC.OSD_CUSTOM_ELEMENTS.settings.customElementTextSize; i++){
if(i < text.length){ if(i < text.length){
data.push8(text.charCodeAt(i)) data.push8(text.charCodeAt(i))
}else{ }else{
@ -3718,21 +3923,22 @@ function customElementGetDataForRow(row){
function getGVoptions(){ function getGVoptions(){
var result = ''; var result = '';
for(var i = 0; i < 8; i++){ for(var i = 0; i < 8; i++) {
result += `<option value="` + i + `">GV `+i+`</option>`; result += `<option value="` + i + `">GV ` + i + `</option>`;
} }
return result; return result;
} }
function getLCoptions(){ function getLCoptions(){
var result = ''; var result = '';
for(var i = 0; i < 64; i++){ for(var i = 0; i < FC.LOGIC_CONDITIONS.getMaxLogicConditionCount(); i++) {
result += `<option value="` + i + `">LC `+i+`</option>`; if (FC.LOGIC_CONDITIONS.isEnabled(i)) {
result += `<option value="` + i + `">LC ` + i + `</option>`;
}
} }
return result; return result;
} }
function refreshOSDSwitchIndicators() { function refreshOSDSwitchIndicators() {
let group = OSD.constants.ALL_DISPLAY_GROUPS.filter(function(e) { let group = OSD.constants.ALL_DISPLAY_GROUPS.filter(function(e) {
return e.name == "osdGroupSwitchIndicators"; return e.name == "osdGroupSwitchIndicators";