mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-23 16:25:22 +03:00
Add support for OSD type variants
This commit is contained in:
parent
9ece824971
commit
e6c2e67c5b
3 changed files with 182 additions and 10 deletions
|
@ -4636,6 +4636,14 @@
|
||||||
"osdDescElementAltitude": {
|
"osdDescElementAltitude": {
|
||||||
"message": "Current altitude (flashes when above alarm threshold)"
|
"message": "Current altitude (flashes when above alarm threshold)"
|
||||||
},
|
},
|
||||||
|
"osdTextElementAltitudeVariant1Decimal": {
|
||||||
|
"message": "With 1 decimal",
|
||||||
|
"description": "One of the variants of the altitude element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementAltitudeVariantNoDecimal": {
|
||||||
|
"message": "Without decimals",
|
||||||
|
"description": "One of the variants of the altitude element of the OSD"
|
||||||
|
},
|
||||||
"osdTextElementOnTime": {
|
"osdTextElementOnTime": {
|
||||||
"message": "On time",
|
"message": "On time",
|
||||||
"description": "One of the elements of the OSD"
|
"description": "One of the elements of the OSD"
|
||||||
|
@ -4685,6 +4693,22 @@
|
||||||
"osdDescElementGPSLat": {
|
"osdDescElementGPSLat": {
|
||||||
"message": "GPS latitude coordinate"
|
"message": "GPS latitude coordinate"
|
||||||
},
|
},
|
||||||
|
"osdTextElementGPSVariant7Decimals": {
|
||||||
|
"message": "With 7 decimals",
|
||||||
|
"description": "One of the variants for the GPS element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementGPSVariant4Decimals": {
|
||||||
|
"message": "With 4 decimals",
|
||||||
|
"description": "One of the variants for the GPS element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementGPSVariantDegMinSec": {
|
||||||
|
"message": "Using degrees, minutes and seconds",
|
||||||
|
"description": "One of the variants for the GPS element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementGPSVariantOpenLocation": {
|
||||||
|
"message": "Using Open Location Code",
|
||||||
|
"description": "One of the variants for the GPS element of the OSD"
|
||||||
|
},
|
||||||
"osdTextElementDebug": {
|
"osdTextElementDebug": {
|
||||||
"message": "Debug",
|
"message": "Debug",
|
||||||
"description": "One of the elements of the OSD"
|
"description": "One of the elements of the OSD"
|
||||||
|
@ -4762,6 +4786,22 @@
|
||||||
"osdDescElementMainBattUsage": {
|
"osdDescElementMainBattUsage": {
|
||||||
"message": "Graphical representation of battery capacity usage"
|
"message": "Graphical representation of battery capacity usage"
|
||||||
},
|
},
|
||||||
|
"osdTextElementMainBattUsageVariantGraphrRemain": {
|
||||||
|
"message": "Graphical remaining",
|
||||||
|
"description": "One of the variants for the Main Battery Usage element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementMainBattUsageVariantGraphUsage": {
|
||||||
|
"message": "Graphical used",
|
||||||
|
"description": "One of the variants for the Main Battery Usage element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementMainBattUsageVariantValueRemain": {
|
||||||
|
"message": "Percentage remaining",
|
||||||
|
"description": "One of the variants for the Main Battery Usage element of the OSD"
|
||||||
|
},
|
||||||
|
"osdTextElementMainBattUsageVariantValueUsage": {
|
||||||
|
"message": "Percentage used",
|
||||||
|
"description": "One of the variants for the Main Battery Usage element of the OSD"
|
||||||
|
},
|
||||||
"osdTextElementArmedTime": {
|
"osdTextElementArmedTime": {
|
||||||
"message": "Timer: armed time",
|
"message": "Timer: armed time",
|
||||||
"description": "One of the elements of the OSD"
|
"description": "One of the elements of the OSD"
|
||||||
|
|
|
@ -449,6 +449,10 @@ button {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-osd select.osd-variant {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-osd .preview {
|
.tab-osd .preview {
|
||||||
width: 360px;
|
width: 360px;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
|
@ -296,6 +296,73 @@ OSD.initData = function() {
|
||||||
};
|
};
|
||||||
OSD.initData();
|
OSD.initData();
|
||||||
|
|
||||||
|
OSD.getVariantForPreview = function(osdData, elementName) {
|
||||||
|
return osdData.displayItems.find(element => element.name === elementName).variant;
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD.generateAltitudePreview = function(osdData) {
|
||||||
|
const unit = FONT.symbol(osdData.unit_mode === 0 ? SYM.FEET : SYM.METRE);
|
||||||
|
const variantSelected = OSD.getVariantForPreview(osdData, 'ALTITUDE');
|
||||||
|
return `${FONT.symbol(SYM.ALTITUDE)}399${variantSelected === 0? '.7' : ''}${unit}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD.generateBatteryUsagePreview = function(osdData) {
|
||||||
|
const variantSelected = OSD.getVariantForPreview(osdData, 'MAIN_BATT_USAGE');
|
||||||
|
let value;
|
||||||
|
switch (variantSelected) {
|
||||||
|
case 0:
|
||||||
|
value = FONT.symbol(SYM.PB_START) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL)
|
||||||
|
+ FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL)
|
||||||
|
+ FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_END) + FONT.symbol(SYM.PB_EMPTY)
|
||||||
|
+ FONT.symbol(SYM.PB_CLOSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
value = FONT.symbol(SYM.PB_START) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL)
|
||||||
|
+ FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_END) + FONT.symbol(SYM.PB_EMPTY)
|
||||||
|
+ FONT.symbol(SYM.PB_EMPTY) + FONT.symbol(SYM.PB_EMPTY) + FONT.symbol(SYM.PB_EMPTY) + FONT.symbol(SYM.PB_EMPTY)
|
||||||
|
+ FONT.symbol(SYM.PB_CLOSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
value = `${FONT.symbol(SYM.MAH)}67%`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
value = `${FONT.symbol(SYM.MAH)}33%`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD.generateGpsLatLongPreview = function(osdData, elementName) {
|
||||||
|
|
||||||
|
const variantSelected = OSD.getVariantForPreview(osdData, elementName);
|
||||||
|
|
||||||
|
let value;
|
||||||
|
switch (variantSelected) {
|
||||||
|
case 0:
|
||||||
|
value = elementName === 'GPS_LON' ? `${FONT.symbol(SYM.GPS_LON)}-000.0000000` : `${FONT.symbol(SYM.GPS_LAT)}-00.0000000 `;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
value = elementName === 'GPS_LON' ? `${FONT.symbol(SYM.GPS_LON)}-000.0000` : `${FONT.symbol(SYM.GPS_LAT)}-00.0000 `;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
const degreesSymbol = FONT.symbol(SYM.STICK_OVERLAY_SPRITE_HIGH);
|
||||||
|
value = elementName === 'GPS_LON' ? `${FONT.symbol(SYM.GPS_LON)}00${degreesSymbol}000'00.0"N` : `${FONT.symbol(SYM.GPS_LAT)}00${degreesSymbol}00'00.0"E `;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
value = `${FONT.symbol(SYM.GPS_SAT_L)}${FONT.symbol(SYM.GPS_SAT_R)}000000AA+BBB`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
OSD.generateTimerPreview = function(osdData, timerIndex) {
|
OSD.generateTimerPreview = function(osdData, timerIndex) {
|
||||||
let preview = '';
|
let preview = '';
|
||||||
switch (osdData.timers[timerIndex].src) {
|
switch (osdData.timers[timerIndex].src) {
|
||||||
|
@ -675,9 +742,12 @@ OSD.loadDisplayFields = function() {
|
||||||
defaultPosition: 62,
|
defaultPosition: 62,
|
||||||
draw_order: 160,
|
draw_order: 160,
|
||||||
positionable: true,
|
positionable: true,
|
||||||
|
variants: [
|
||||||
|
'osdTextElementAltitudeVariant1Decimal',
|
||||||
|
'osdTextElementAltitudeVariantNoDecimal',
|
||||||
|
],
|
||||||
preview(osdData) {
|
preview(osdData) {
|
||||||
const unit = FONT.symbol(osdData.unit_mode === 0 ? SYM.FEET : SYM.METRE);
|
return OSD.generateAltitudePreview(osdData);
|
||||||
return `${FONT.symbol(SYM.ALTITUDE)}399.7${unit}`;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ONTIME: {
|
ONTIME: {
|
||||||
|
@ -733,7 +803,15 @@ OSD.loadDisplayFields = function() {
|
||||||
defaultPosition: -1,
|
defaultPosition: -1,
|
||||||
draw_order: 830,
|
draw_order: 830,
|
||||||
positionable: true,
|
positionable: true,
|
||||||
preview: `${FONT.symbol(SYM.GPS_LON)}-000.0000000`,
|
variants: [
|
||||||
|
'osdTextElementGPSVariant7Decimals',
|
||||||
|
'osdTextElementGPSVariant4Decimals',
|
||||||
|
'osdTextElementGPSVariantDegMinSec',
|
||||||
|
'osdTextElementGPSVariantOpenLocation',
|
||||||
|
],
|
||||||
|
preview(osdData) {
|
||||||
|
return OSD.generateGpsLatLongPreview(osdData, 'GPS_LON');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
GPS_LAT: {
|
GPS_LAT: {
|
||||||
name: 'GPS_LAT',
|
name: 'GPS_LAT',
|
||||||
|
@ -742,7 +820,15 @@ OSD.loadDisplayFields = function() {
|
||||||
defaultPosition: -1,
|
defaultPosition: -1,
|
||||||
draw_order: 820,
|
draw_order: 820,
|
||||||
positionable: true,
|
positionable: true,
|
||||||
preview: `${FONT.symbol(SYM.GPS_LAT)}-00.0000000 `,
|
variants: [
|
||||||
|
'osdTextElementGPSVariant7Decimals',
|
||||||
|
'osdTextElementGPSVariant4Decimals',
|
||||||
|
'osdTextElementGPSVariantDegMinSec',
|
||||||
|
'osdTextElementGPSVariantOpenLocation',
|
||||||
|
],
|
||||||
|
preview(osdData) {
|
||||||
|
return OSD.generateGpsLatLongPreview(osdData, 'GPS_LAT');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
DEBUG: {
|
DEBUG: {
|
||||||
name: 'DEBUG',
|
name: 'DEBUG',
|
||||||
|
@ -842,10 +928,15 @@ OSD.loadDisplayFields = function() {
|
||||||
defaultPosition: -17,
|
defaultPosition: -17,
|
||||||
draw_order: 270,
|
draw_order: 270,
|
||||||
positionable: true,
|
positionable: true,
|
||||||
preview: FONT.symbol(SYM.PB_START) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL)
|
variants: [
|
||||||
+ FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL)
|
'osdTextElementMainBattUsageVariantGraphrRemain',
|
||||||
+ FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_FULL) + FONT.symbol(SYM.PB_END) + FONT.symbol(SYM.PB_EMPTY)
|
'osdTextElementMainBattUsageVariantGraphUsage',
|
||||||
+ FONT.symbol(SYM.PB_CLOSE),
|
'osdTextElementMainBattUsageVariantValueRemain',
|
||||||
|
'osdTextElementMainBattUsageVariantValueUsage',
|
||||||
|
],
|
||||||
|
preview(osdData) {
|
||||||
|
return OSD.generateBatteryUsagePreview(osdData);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ARMED_TIME: {
|
ARMED_TIME: {
|
||||||
name: 'ARMED_TIME',
|
name: 'ARMED_TIME',
|
||||||
|
@ -1195,6 +1286,7 @@ OSD.loadDisplayFields = function() {
|
||||||
|
|
||||||
OSD.constants = {
|
OSD.constants = {
|
||||||
VISIBLE: 0x0800,
|
VISIBLE: 0x0800,
|
||||||
|
VARIANTS: 0xC000,
|
||||||
VIDEO_TYPES: [
|
VIDEO_TYPES: [
|
||||||
'AUTO',
|
'AUTO',
|
||||||
'PAL',
|
'PAL',
|
||||||
|
@ -1801,7 +1893,9 @@ OSD.msp = {
|
||||||
* b: blink flag
|
* b: blink flag
|
||||||
* y: y coordinate
|
* y: y coordinate
|
||||||
* x: x coordinate
|
* x: x coordinate
|
||||||
* 0000 vbyy yyyx xxxx
|
* p: profile
|
||||||
|
* t: variant type
|
||||||
|
* ttpp vbyy yyyx xxxx
|
||||||
*/
|
*/
|
||||||
helpers: {
|
helpers: {
|
||||||
unpack: {
|
unpack: {
|
||||||
|
@ -1820,6 +1914,9 @@ OSD.msp = {
|
||||||
for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) {
|
for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) {
|
||||||
displayItem.isVisible[osd_profile] = (bits & (OSD.constants.VISIBLE << osd_profile)) !== 0;
|
displayItem.isVisible[osd_profile] = (bits & (OSD.constants.VISIBLE << osd_profile)) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayItem.variant = (bits & OSD.constants.VARIANTS) >> 14;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
displayItem.position = (bits === -1) ? defaultPosition : bits;
|
displayItem.position = (bits === -1) ? defaultPosition : bits;
|
||||||
displayItem.isVisible = [bits !== -1];
|
displayItem.isVisible = [bits !== -1];
|
||||||
|
@ -1839,13 +1936,17 @@ OSD.msp = {
|
||||||
position(displayItem) {
|
position(displayItem) {
|
||||||
const isVisible = displayItem.isVisible;
|
const isVisible = displayItem.isVisible;
|
||||||
const position = displayItem.position;
|
const position = displayItem.position;
|
||||||
|
const variant = displayItem.variant;
|
||||||
|
|
||||||
if (semver.gte(FC.CONFIG.apiVersion, "1.21.0")) {
|
if (semver.gte(FC.CONFIG.apiVersion, "1.21.0")) {
|
||||||
|
|
||||||
let packed_visible = 0;
|
let packed_visible = 0;
|
||||||
for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) {
|
for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) {
|
||||||
packed_visible |= isVisible[osd_profile] ? OSD.constants.VISIBLE << osd_profile : 0;
|
packed_visible |= isVisible[osd_profile] ? OSD.constants.VISIBLE << osd_profile : 0;
|
||||||
}
|
}
|
||||||
return packed_visible | (((position / FONT.constants.SIZES.LINE) & 0x001F) << 5) | (position % FONT.constants.SIZES.LINE);
|
const variantSelected = (variant << 14);
|
||||||
|
|
||||||
|
return packed_visible | variantSelected | (((position / FONT.constants.SIZES.LINE) & 0x001F) << 5) | (position % FONT.constants.SIZES.LINE);
|
||||||
} else {
|
} else {
|
||||||
const realPosition = position === -1 ? 0 : position;
|
const realPosition = position === -1 ? 0 : position;
|
||||||
return isVisible[0] ? realPosition : -1;
|
return isVisible[0] ? realPosition : -1;
|
||||||
|
@ -1954,6 +2055,7 @@ OSD.msp = {
|
||||||
index: j,
|
index: j,
|
||||||
draw_order: c.draw_order,
|
draw_order: c.draw_order,
|
||||||
preview: suffix ? c.preview + suffix : c.preview,
|
preview: suffix ? c.preview + suffix : c.preview,
|
||||||
|
variants: c.variants,
|
||||||
ignoreSize,
|
ignoreSize,
|
||||||
}, this.helpers.unpack.position(item, c)));
|
}, this.helpers.unpack.position(item, c)));
|
||||||
}
|
}
|
||||||
|
@ -2810,6 +2912,32 @@ TABS.osd.initialize = function(callback) {
|
||||||
|
|
||||||
const finalFieldName = titleizeField(field);
|
const finalFieldName = titleizeField(field);
|
||||||
$field.append(`<label for="${field.name}" class="char-label">${finalFieldName}</label>`);
|
$field.append(`<label for="${field.name}" class="char-label">${finalFieldName}</label>`);
|
||||||
|
|
||||||
|
|
||||||
|
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) && field.variants && field.variants.length > 0) {
|
||||||
|
|
||||||
|
const selectVariant = $('<select class="osd-variant" />')
|
||||||
|
.data('field', field)
|
||||||
|
.on("change", function() {
|
||||||
|
const fieldChanged = $(this).data('field');
|
||||||
|
fieldChanged.variant = parseInt($(this).val());
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encodeLayout(fieldChanged))
|
||||||
|
.then(function() {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const [variantIndex, variantText] of field.variants.entries()) {
|
||||||
|
selectVariant.append($('<option/>')
|
||||||
|
.val(variantIndex)
|
||||||
|
.html(i18n.getMessage(variantText)));
|
||||||
|
}
|
||||||
|
|
||||||
|
selectVariant.val(field.variant);
|
||||||
|
|
||||||
|
$field.append(selectVariant);
|
||||||
|
}
|
||||||
|
|
||||||
if (field.positionable && field.isVisible[OSD.getCurrentPreviewProfile()]) {
|
if (field.positionable && field.isVisible[OSD.getCurrentPreviewProfile()]) {
|
||||||
$field.append(
|
$field.append(
|
||||||
$(`<input type="number" class="${field.index} position"></input>`)
|
$(`<input type="number" class="${field.index} position"></input>`)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue