diff --git a/locales/en/messages.json b/locales/en/messages.json index 4a89176c..f9113c2e 100644 --- a/locales/en/messages.json +++ b/locales/en/messages.json @@ -4657,6 +4657,14 @@ "osdDescElementAltitude": { "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": { "message": "On time", "description": "One of the elements of the OSD" @@ -4706,6 +4714,22 @@ "osdDescElementGPSLat": { "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": { "message": "Debug", "description": "One of the elements of the OSD" @@ -4783,6 +4807,22 @@ "osdDescElementMainBattUsage": { "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": { "message": "Timer: armed time", "description": "One of the elements of the OSD" diff --git a/src/css/tabs/osd.css b/src/css/tabs/osd.css index b152bb88..f8cc3ea6 100644 --- a/src/css/tabs/osd.css +++ b/src/css/tabs/osd.css @@ -449,6 +449,10 @@ button { border-radius: 3px; } +.tab-osd select.osd-variant { + max-width: 100%; +} + .tab-osd .preview { width: 360px; float: left; diff --git a/src/js/tabs/osd.js b/src/js/tabs/osd.js index b6cf6469..9cb90997 100644 --- a/src/js/tabs/osd.js +++ b/src/js/tabs/osd.js @@ -296,6 +296,73 @@ OSD.initData = function() { }; 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) { let preview = ''; switch (osdData.timers[timerIndex].src) { @@ -675,9 +742,12 @@ OSD.loadDisplayFields = function() { defaultPosition: 62, draw_order: 160, positionable: true, + variants: [ + 'osdTextElementAltitudeVariant1Decimal', + 'osdTextElementAltitudeVariantNoDecimal', + ], preview(osdData) { - const unit = FONT.symbol(osdData.unit_mode === 0 ? SYM.FEET : SYM.METRE); - return `${FONT.symbol(SYM.ALTITUDE)}399.7${unit}`; + return OSD.generateAltitudePreview(osdData); }, }, ONTIME: { @@ -734,7 +804,15 @@ OSD.loadDisplayFields = function() { defaultPosition: -1, draw_order: 830, 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: { name: 'GPS_LAT', @@ -743,7 +821,15 @@ OSD.loadDisplayFields = function() { defaultPosition: -1, draw_order: 820, positionable: true, - preview: `${FONT.symbol(SYM.GPS_LAT)}-00.0000000 `, + variants: [ + 'osdTextElementGPSVariant7Decimals', + 'osdTextElementGPSVariant4Decimals', + 'osdTextElementGPSVariantDegMinSec', + 'osdTextElementGPSVariantOpenLocation', + ], + preview(osdData) { + return OSD.generateGpsLatLongPreview(osdData, 'GPS_LAT'); + }, }, DEBUG: { name: 'DEBUG', @@ -843,10 +929,15 @@ OSD.loadDisplayFields = function() { defaultPosition: -17, draw_order: 270, positionable: true, - preview: 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), + variants: [ + 'osdTextElementMainBattUsageVariantGraphrRemain', + 'osdTextElementMainBattUsageVariantGraphUsage', + 'osdTextElementMainBattUsageVariantValueRemain', + 'osdTextElementMainBattUsageVariantValueUsage', + ], + preview(osdData) { + return OSD.generateBatteryUsagePreview(osdData); + }, }, ARMED_TIME: { name: 'ARMED_TIME', @@ -1205,6 +1296,7 @@ OSD.loadDisplayFields = function() { OSD.constants = { VISIBLE: 0x0800, + VARIANTS: 0xC000, VIDEO_TYPES: [ 'AUTO', 'PAL', @@ -1812,7 +1904,9 @@ OSD.msp = { * b: blink flag * y: y coordinate * x: x coordinate - * 0000 vbyy yyyx xxxx + * p: profile + * t: variant type + * ttpp vbyy yyyx xxxx */ helpers: { unpack: { @@ -1831,6 +1925,9 @@ OSD.msp = { for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) { displayItem.isVisible[osd_profile] = (bits & (OSD.constants.VISIBLE << osd_profile)) !== 0; } + + displayItem.variant = (bits & OSD.constants.VARIANTS) >> 14; + } else { displayItem.position = (bits === -1) ? defaultPosition : bits; displayItem.isVisible = [bits !== -1]; @@ -1850,13 +1947,17 @@ OSD.msp = { position(displayItem) { const isVisible = displayItem.isVisible; const position = displayItem.position; + const variant = displayItem.variant; + if (semver.gte(FC.CONFIG.apiVersion, "1.21.0")) { let packed_visible = 0; for (let osd_profile = 0; osd_profile < OSD.getNumberOfProfiles(); osd_profile++) { 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 { const realPosition = position === -1 ? 0 : position; return isVisible[0] ? realPosition : -1; @@ -1965,6 +2066,7 @@ OSD.msp = { index: j, draw_order: c.draw_order, preview: suffix ? c.preview + suffix : c.preview, + variants: c.variants, ignoreSize, }, this.helpers.unpack.position(item, c))); } @@ -2821,6 +2923,32 @@ TABS.osd.initialize = function(callback) { const finalFieldName = titleizeField(field); $field.append(``); + + + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) && field.variants && field.variants.length > 0) { + + const selectVariant = $('`)