commit
50b46c3c97
|
@ -93,6 +93,9 @@
|
|||
"tabTransponder": {
|
||||
"message": "Race Transponder"
|
||||
},
|
||||
"tabOsd": {
|
||||
"message": "OSD"
|
||||
},
|
||||
"tabGPS": {
|
||||
"message": "GPS"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<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="227 -351.2 595.3 841.9" style="enable-background:new 227 -351.2 595.3 841.9;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#818181;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M677.5,19.8h-13.3v94.8h10.2c13.9,0,24.1-4,30.5-12.1c6.5-8.1,9.7-20.4,9.7-37c0-15.5-3.1-27-9.2-34.5
|
||||
C699.3,23.5,690,19.8,677.5,19.8z"/>
|
||||
<path class="st0" d="M369.2,17.7c-22.9,0-34.4,16.5-34.4,49.5c0,32.7,11.4,49.1,34.1,49.1c11.6,0,20.1-4,25.7-11.9
|
||||
c5.6-7.9,8.4-20.3,8.4-37.1c0-16.9-2.8-29.4-8.5-37.4C388.9,21.7,380.4,17.7,369.2,17.7z"/>
|
||||
<path class="st0" d="M726.8-134.3H321.9c-36.3,0-65.9,29.5-65.9,65.9V207c0,36.3,29.5,65.9,65.9,65.9h404.9
|
||||
c36.3,0,65.9-29.5,65.9-65.9V-68.4C792.7-104.8,763.1-134.3,726.8-134.3z M430.3,132.1c-14,14.8-34.4,22.2-61.3,22.2
|
||||
c-26.5,0-46.9-7.4-61-22.3c-14.2-14.9-21.2-36.6-21.2-65c0-28.1,7-49.7,21.1-64.5c14.1-14.8,34.5-22.3,61.4-22.3
|
||||
c26.9,0,47.3,7.4,61.2,22.1c13.9,14.7,20.8,36.4,20.8,64.9C451.2,95.7,444.2,117.3,430.3,132.1z M525.5,36.8
|
||||
c3.4,2.6,12.7,7.4,27.9,14.3c14.6,6.6,24.7,13.6,30.4,21.1c5.7,7.5,8.5,17,8.5,28.4c0,10.5-2.7,19.8-8,27.9c-5.3,8.1-13,14.5-23,19
|
||||
c-10,4.5-21.8,6.8-35.3,6.8c-11.3,0-20.7-0.8-28.3-2.4s-15.6-4.3-23.8-8.3V103c8.7,4.5,17.8,8,27.2,10.5c9.4,2.5,18,3.8,25.9,3.8
|
||||
c6.8,0,11.8-1.2,14.9-3.5c3.1-2.3,4.7-5.4,4.7-9.1c0-2.3-0.6-4.3-1.9-6.1s-3.3-3.5-6.1-5.3c-2.8-1.8-10.3-5.4-22.5-10.9
|
||||
c-11-5-19.3-9.9-24.8-14.6c-5.5-4.7-9.6-10.1-12.3-16.2c-2.7-6.1-4-13.3-4-21.6c0-15.6,5.7-27.7,17-36.4
|
||||
c11.3-8.7,26.9-13.1,46.7-13.1c17.5,0,35.4,4,53.6,12.1l-14,35.3c-15.8-7.2-29.5-10.9-41-10.9c-5.9,0-10.3,1-13,3.1s-4,4.7-4,7.8
|
||||
C520.4,31.2,522.1,34.2,525.5,36.8z M738.8,129.1c-15.5,15.3-37.4,22.9-65.5,22.9h-54.7V-17.1H677c27.2,0,48.1,6.9,62.9,20.8
|
||||
c14.8,13.9,22.2,33.9,22.2,60.2C762.1,92.1,754.3,113.8,738.8,129.1z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<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="227 -351.2 595.3 841.9" style="enable-background:new 227 -351.2 595.3 841.9;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M677.5,19.8h-13.3v94.8h10.2c13.9,0,24.1-4,30.5-12.1c6.5-8.1,9.7-20.4,9.7-37c0-15.5-3.1-27-9.2-34.5
|
||||
C699.3,23.5,690,19.8,677.5,19.8z"/>
|
||||
<path class="st0" d="M369.2,17.7c-22.9,0-34.4,16.5-34.4,49.5c0,32.7,11.4,49.1,34.1,49.1c11.6,0,20.1-4,25.7-11.9
|
||||
c5.6-7.9,8.4-20.3,8.4-37.1c0-16.9-2.8-29.4-8.5-37.4C388.9,21.7,380.4,17.7,369.2,17.7z"/>
|
||||
<path class="st0" d="M726.8-134.3H321.9c-36.3,0-65.9,29.5-65.9,65.9V207c0,36.3,29.5,65.9,65.9,65.9h404.9
|
||||
c36.3,0,65.9-29.5,65.9-65.9V-68.4C792.7-104.8,763.1-134.3,726.8-134.3z M430.3,132.1c-14,14.8-34.4,22.2-61.3,22.2
|
||||
c-26.5,0-46.9-7.4-61-22.3c-14.2-14.9-21.2-36.6-21.2-65c0-28.1,7-49.7,21.1-64.5c14.1-14.8,34.5-22.3,61.4-22.3
|
||||
c26.9,0,47.3,7.4,61.2,22.1c13.9,14.7,20.8,36.4,20.8,64.9C451.2,95.7,444.2,117.3,430.3,132.1z M525.5,36.8
|
||||
c3.4,2.6,12.7,7.4,27.9,14.3c14.6,6.6,24.7,13.6,30.4,21.1c5.7,7.5,8.5,17,8.5,28.4c0,10.5-2.7,19.8-8,27.9c-5.3,8.1-13,14.5-23,19
|
||||
c-10,4.5-21.8,6.8-35.3,6.8c-11.3,0-20.7-0.8-28.3-2.4s-15.6-4.3-23.8-8.3V103c8.7,4.5,17.8,8,27.2,10.5c9.4,2.5,18,3.8,25.9,3.8
|
||||
c6.8,0,11.8-1.2,14.9-3.5c3.1-2.3,4.7-5.4,4.7-9.1c0-2.3-0.6-4.3-1.9-6.1s-3.3-3.5-6.1-5.3c-2.8-1.8-10.3-5.4-22.5-10.9
|
||||
c-11-5-19.3-9.9-24.8-14.6c-5.5-4.7-9.6-10.1-12.3-16.2c-2.7-6.1-4-13.3-4-21.6c0-15.6,5.7-27.7,17-36.4
|
||||
c11.3-8.7,26.9-13.1,46.7-13.1c17.5,0,35.4,4,53.6,12.1l-14,35.3c-15.8-7.2-29.5-10.9-41-10.9c-5.9,0-10.3,1-13,3.1s-4,4.7-4,7.8
|
||||
C520.4,31.2,522.1,34.2,525.5,36.8z M738.8,129.1c-15.5,15.3-37.4,22.9-65.5,22.9h-54.7V-17.1H677c27.2,0,48.1,6.9,62.9,20.8
|
||||
c14.8,13.9,22.2,33.9,22.2,60.2C762.1,92.1,754.3,113.8,738.8,129.1z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 303 KiB |
|
@ -20,6 +20,7 @@ var GUI_control = function () {
|
|||
this.defaultAllowedTabsWhenConnected = [
|
||||
'failsafe',
|
||||
'transponder',
|
||||
'osd',
|
||||
'adjustments',
|
||||
'auxiliary',
|
||||
'cli',
|
||||
|
@ -239,8 +240,7 @@ GUI_control.prototype.tab_switch_cleanup = function (callback) {
|
|||
}
|
||||
};
|
||||
|
||||
GUI_control.prototype.content_ready = function (callback) {
|
||||
|
||||
GUI_control.prototype.switchery = function() {
|
||||
$('.togglesmall').each(function(index, elem) {
|
||||
var switchery = new Switchery(elem, {
|
||||
size: 'small',
|
||||
|
@ -275,6 +275,11 @@ GUI_control.prototype.content_ready = function (callback) {
|
|||
});
|
||||
$(elem).removeClass('togglemedium');
|
||||
});
|
||||
};
|
||||
|
||||
GUI_control.prototype.content_ready = function (callback) {
|
||||
|
||||
this.switchery();
|
||||
|
||||
if (CONFIGURATOR.connectionValid) {
|
||||
// Build link to in-use CF version documentation
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* jQuery throttle / debounce - v1.1 - 3/7/2010
|
||||
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
|
21
js/msp.js
21
js/msp.js
|
@ -40,7 +40,12 @@ var MSP_codes = {
|
|||
MSP_SET_BLACKBOX_CONFIG: 81,
|
||||
MSP_TRANSPONDER_CONFIG: 82,
|
||||
MSP_SET_TRANSPONDER_CONFIG: 83,
|
||||
|
||||
MSP_OSD_CONFIG: 84,
|
||||
MSP_SET_OSD_CONFIG: 85,
|
||||
MSP_OSD_CHAR_READ: 86,
|
||||
MSP_OSD_CHAR_WRITE: 87,
|
||||
MSP_VTX_CONFIG: 88,
|
||||
MSP_SET_VTX_CONFIG: 89,
|
||||
MSP_PID_ADVANCED_CONFIG: 90,
|
||||
MSP_SET_PID_ADVANCED_CONFIG: 91,
|
||||
MSP_FILTER_CONFIG: 92,
|
||||
|
@ -1063,6 +1068,20 @@ var MSP = {
|
|||
case MSP_codes.MSP_SET_FAILSAFE_CONFIG:
|
||||
console.log('Failsafe config saved');
|
||||
break;
|
||||
case MSP_codes.MSP_OSD_CONFIG:
|
||||
break;
|
||||
case MSP_codes.MSP_SET_OSD_CONFIG:
|
||||
console.log('OSD config set');
|
||||
break;
|
||||
case MSP_codes.MSP_OSD_CHAR_READ:
|
||||
break;
|
||||
case MSP_codes.MSP_OSD_CHAR_WRITE:
|
||||
console.log('OSD char uploaded');
|
||||
break;
|
||||
case MSP_codes.MSP_VTX_CONFIG:
|
||||
break;
|
||||
case MSP_codes.MSP_SET_VTX_CONFIG:
|
||||
break;
|
||||
default:
|
||||
console.log('Unknown code detected: ' + code);
|
||||
} else {
|
||||
|
|
31
main.css
31
main.css
|
@ -798,6 +798,14 @@ li.active .ic_transponder {
|
|||
background-image: url(images/icons/cf_icon_transponder_white.svg);
|
||||
}
|
||||
|
||||
.ic_osd {
|
||||
background-image: url(images/icons/icon_osd.svg);
|
||||
background-position-y: 4px;
|
||||
}
|
||||
|
||||
.ic_osd:hover, li.active .ic_osd {
|
||||
background-image: url(images/icons/icon_osd_white.svg);
|
||||
}
|
||||
|
||||
/* SPARE Tab-Icons */
|
||||
.ic_failsafe {
|
||||
|
@ -1439,7 +1447,7 @@ dialog {
|
|||
/* fixing padding for all Tabs*/
|
||||
.tab-setup, .tab-landing, .tab-adjustments, .tab-auxiliary, .tab-cli, .tab-configuration, .tab-failsafe, .tab-onboard_logging,
|
||||
.tab-firmware_flasher, .tab-gps, .tab-help, .tab-led-strip, .tab-logging, .tab-modes, .tab-motors, .tab-pid_tuning,
|
||||
.tab-ports, .tab-receiver, .tab-sensors, .tab-servos {
|
||||
.tab-ports, .tab-receiver, .tab-sensors, .tab-servos, .tab-osd {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
@ -1574,9 +1582,6 @@ dialog {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Battery element styling*/
|
||||
|
||||
#quad-status_wrapper {
|
||||
|
@ -1686,6 +1691,22 @@ dialog {
|
|||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: .5em .75em;
|
||||
border-radius: 4px;
|
||||
background-color: #ccc;
|
||||
color: #666;
|
||||
border: 1px solid #ddd;
|
||||
font-family: 'open_sanssemibold', Arial;
|
||||
font-size: 10pt;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.active {
|
||||
background-color: #ffbb00;
|
||||
border: 1px solid #dba718;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 1055px) , only screen and (max-device-width: 1055px) {
|
||||
|
@ -1801,4 +1822,4 @@ input {
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<link type="text/css" rel="stylesheet" href="./tabs/adjustments.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./tabs/auxiliary.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./tabs/failsafe.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./tabs/osd.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./tabs/transponder.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./css/opensans_webfontkit/fonts.css" media="all" />
|
||||
<link type="text/css" rel="stylesheet" href="./css/dropdown-lists/css/style_lists.css" media="all" />
|
||||
|
@ -45,6 +46,7 @@
|
|||
<script type="text/javascript" src="./js/libraries/jbox/jBox.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/switchery/switchery.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/bluebird.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery.ba-throttle-debounce.min.js"></script>
|
||||
<script type="text/javascript" src="./js/injected_methods.js"></script>
|
||||
<script type="text/javascript" src="./js/port_handler.js"></script>
|
||||
<script type="text/javascript" src="./js/port_usage.js"></script>
|
||||
|
@ -81,6 +83,7 @@
|
|||
<script type="text/javascript" src="./tabs/onboard_logging.js"></script>
|
||||
<script type="text/javascript" src="./tabs/firmware_flasher.js"></script>
|
||||
<script type="text/javascript" src="./tabs/failsafe.js"></script>
|
||||
<script type="text/javascript" src="./tabs/osd.js"></script>
|
||||
<script type="text/javascript" src="./tabs/transponder.js"></script>
|
||||
<title></title>
|
||||
</head>
|
||||
|
@ -215,6 +218,7 @@
|
|||
<li class="tab_servos"><a href="#" i18n="tabServos" class="tabicon ic_servo" title="Servos"></a></li>
|
||||
<li class="tab_gps"><a href="#" i18n="tabGPS" class="tabicon ic_gps" title="GPS"></a></li>
|
||||
<li class="tab_motors"><a href="#" i18n="tabMotorTesting" class="tabicon ic_motor" title="Motors"></a></li>
|
||||
<li class="tab_osd"><a href="#" i18n="tabOsd" class="tabicon ic_osd" title="Osd"></a></li>
|
||||
<li class="tab_transponder"><a href="#" i18n="tabTransponder" class="tabicon ic_transponder" title="Transponder"></a></li>
|
||||
<li class="tab_led_strip"><a href="#" i18n="tabLedStrip" class="tabicon ic_led" title="LED Strip"></a></li>
|
||||
<li class="tab_sensors"><a href="#" i18n="tabRawSensorData" class="tabicon ic_sensors" title="Sensors"></a></li>
|
||||
|
|
3
main.js
3
main.js
|
@ -126,6 +126,9 @@ $(document).ready(function () {
|
|||
case 'transponder':
|
||||
TABS.transponder.initialize(content_ready);
|
||||
break;
|
||||
case 'osd':
|
||||
TABS.osd.initialize(content_ready);
|
||||
break;
|
||||
case 'setup':
|
||||
TABS.setup.initialize(content_ready);
|
||||
break;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,344 @@
|
|||
.tab-osd .info {
|
||||
margin: 10px 0 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-osd .info .progressLabel {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
line-height: 24px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
/* text-shadow: 1px 0px 2px rgba(0, 0, 0, 0.9);*/
|
||||
}
|
||||
|
||||
.darkgrey {
|
||||
background-color: #575757;
|
||||
}
|
||||
|
||||
.tab-osd .spacer_box_title {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.tab-osd .info {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.info .progressLabel a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.info .progressLabel a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.info .progress {
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.info .progress {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.info .progress::-webkit-progress-bar {
|
||||
background-color: #4f4f4f;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0px 0px 5px #2f2f2f;
|
||||
}
|
||||
|
||||
.info .progress::-webkit-progress-value {
|
||||
background-color: #F86008;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info .progress.valid::-webkit-progress-bar {
|
||||
background-color: #56ac1d;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info .progress.valid::-webkit-progress-value {
|
||||
background-color: #56ac1d;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info .progress.invalid::-webkit-progress-bar {
|
||||
background-color: #A62E32;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info .progress.invalid::-webkit-progress-value {
|
||||
background-color: #A62E32;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tab-osd ul li {
|
||||
list-style: initial;
|
||||
list-style-type: circle;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.tab-osd .options {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
line-height: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tab-osd td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tab-osd .options label input {
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.tab-osd .options label span {
|
||||
font-weight: bold;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.tab-osd .options select {
|
||||
width: 300px;
|
||||
height: 20px;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.tab-osd .options .releases select {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.tab-osd .option.releases {
|
||||
margin: 0 0 2px 0;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tab-osd .options .description {
|
||||
position: relative;
|
||||
left: 0px;
|
||||
font-style: italic;
|
||||
color: #818181;
|
||||
}
|
||||
|
||||
.tab-osd .cf_table td:last-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tab-osd .options .flash_on_connect_wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-osd .options .manual_baud_rate select {
|
||||
width: 75px;
|
||||
margin-left: 19px;
|
||||
}
|
||||
|
||||
.tab-osd .release_info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-osd .release_info .title {
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
border-bottom: 1px solid silver;
|
||||
background-color: #3f4241;
|
||||
}
|
||||
|
||||
.tab-osd .release_info .target {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.tab-osd .release_info p {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tab-osd .release_info p a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-osd .release_info p a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.tab-osd .release_info .notes {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tab-osd .git_info {
|
||||
display: none;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.tab-osd .git_info .title {
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
border-bottom: 1px solid silver;
|
||||
background-color: #3f4241;
|
||||
}
|
||||
|
||||
.tab-osd .git_info p {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tab-osd .git_info p a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-osd .git_info p a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.tab-osd .buttons {
|
||||
width: calc(100% - 20px);
|
||||
margin-top: 10px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a {
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0 10px 0 0;
|
||||
padding: 0 15px 0 15px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 1px solid silver;
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a:hover {
|
||||
background-color: #dedcdc;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a.flash_font.locked {
|
||||
background-color: #b8b8b8;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a.flash_font.locked:hover {
|
||||
cursor: default;
|
||||
background-color: #b8b8b8;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a.load_remote_file.locked {
|
||||
background-color: #b8b8b8;
|
||||
}
|
||||
|
||||
.tab-osd .buttons a.load_remote_file.locked:hover {
|
||||
cursor: default;
|
||||
background-color: #b8b8b8;
|
||||
}
|
||||
|
||||
.tab-osd .buttons .back {
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tab-osd .btn .disabled {
|
||||
cursor: default;
|
||||
color: #fff;
|
||||
background-color: #AFAFAF;
|
||||
border: none;
|
||||
pointer-events: none;
|
||||
text-shadow: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.tab-osd .display-layout label {
|
||||
margin: .25em .1em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tab-osd .display-layout input {
|
||||
margin: .1em 1em;
|
||||
}
|
||||
|
||||
.tab-osd .display-layout input.position{
|
||||
width: 5em;
|
||||
border-bottom: 1px solid #ccc
|
||||
}
|
||||
|
||||
.tab-osd .hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-osd .note {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.tab-osd .col {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tab-osd .left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tab-osd .right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.tab-osd .preview {
|
||||
background: url(/images/osd-bg-1.png);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.tab-osd .preview .char {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tab-osd .preview .char[draggable="true"] {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.tab-osd .preview .row {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.tab-osd .content_wrapper {
|
||||
height: calc(100% - 41px);
|
||||
}
|
||||
|
||||
.tab-osd .content_toolbar {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tab-osd .content_toolbar button {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 4px 10px !important;
|
||||
font-family: 'open_sanssemibold', Arial;
|
||||
font-size: 9pt !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fontbuttons {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1055px) , only screen and (max-device-width: 1055px) {
|
||||
.tab-osd .content_wrapper {
|
||||
height: calc(100% - 30px);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<div class="tab-osd toolbar_fixed_bottom">
|
||||
<div class="content_wrapper">
|
||||
<h1 class="tab_title">
|
||||
OSD
|
||||
<div class="fontbuttons supported hide">
|
||||
<button data-font-file="default">Default</button>
|
||||
<button data-font-file="bold">Bold</button>
|
||||
<button data-font-file="large">Large</button>
|
||||
<button class="load_font_file">Open Font File</button>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<div class="unsupported hide">
|
||||
<p class="note">Your flight controller isn't responding to OSD commands. This probably means that it does not have an integrated BetaFlight OSD.</p>
|
||||
<p class="note">Note that some flight controllers have an onboard <a href="https://www.youtube.com/watch?v=ikKH_6SQ-Tk" target="_blank">MinimOSD</a> that can be flashed and configured with <a href="https://github.com/ShikOfTheRa/scarab-osd/releases/latest" target="_blank">scarab-osd</a>, however the MinimOSD cannot be configured through this interface.</p>
|
||||
</div>
|
||||
<div class="supported hide">
|
||||
<div class="display-layout">
|
||||
<div class="col left">
|
||||
<div class="video-types">
|
||||
</div>
|
||||
<div class="display-fields">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col right">
|
||||
<div class="preview">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-preview"></div>
|
||||
|
||||
<div class="info"><a name="progressbar"></a>
|
||||
<progress class="progress" value="0" min="0" max="100"></progress>
|
||||
<span class="progressLabel"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content_toolbar supported hide">
|
||||
<button class="save active">Save Layout</button>
|
||||
<button class="flash_font active">Upload Font</button>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,660 @@
|
|||
'use strict';
|
||||
|
||||
var SYM = SYM || {};
|
||||
SYM.VOLT = 0x00;
|
||||
SYM.RSSI = 0x01;
|
||||
SYM.AH_RIGHT = 0x02;
|
||||
SYM.AH_LEFT = 0x03;
|
||||
SYM.THR = 0x04;
|
||||
SYM.THR1 = 0x05;
|
||||
SYM.FLY_M = 0x9C;
|
||||
SYM.ON_M = 0x9B;
|
||||
SYM.AH_CENTER_LINE = 0x26;
|
||||
SYM.AH_CENTER_LINE_RIGHT = 0x27;
|
||||
SYM.AH_CENTER = 0x7E;
|
||||
SYM.AH_BAR9_0 = 0x80;
|
||||
SYM.AH_DECORATION = 0x13;
|
||||
SYM.LOGO = 0xA0;
|
||||
|
||||
var FONT = FONT || {};
|
||||
|
||||
FONT.initData = function() {
|
||||
if (FONT.data) {
|
||||
return;
|
||||
}
|
||||
FONT.data = {
|
||||
// default font file name
|
||||
loaded_font_file: 'default',
|
||||
// array of arry of image bytes ready to upload to fc
|
||||
characters_bytes: [],
|
||||
// array of array of image bits by character
|
||||
characters: [],
|
||||
// an array of base64 encoded image strings by character
|
||||
character_image_urls: []
|
||||
}
|
||||
};
|
||||
|
||||
FONT.constants = {
|
||||
SIZES: {
|
||||
/** NVM ram size for one font char, actual character bytes **/
|
||||
MAX_NVM_FONT_CHAR_SIZE: 54,
|
||||
/** NVM ram field size for one font char, last 10 bytes dont matter **/
|
||||
MAX_NVM_FONT_CHAR_FIELD_SIZE: 64,
|
||||
CHAR_HEIGHT: 18,
|
||||
CHAR_WIDTH: 12,
|
||||
LINE: 30
|
||||
},
|
||||
COLORS: {
|
||||
// black
|
||||
0: 'rgba(0, 0, 0, 1)',
|
||||
// also the value 3, could yield transparent according to
|
||||
// https://www.sparkfun.com/datasheets/BreakoutBoards/MAX7456.pdf
|
||||
1: 'rgba(255, 255, 255, 0)',
|
||||
// white
|
||||
2: 'rgba(255,255,255, 1)'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Each line is composed of 8 asci 1 or 0, representing 1 bit each for a total of 1 byte per line
|
||||
*/
|
||||
FONT.parseMCMFontFile = function(data) {
|
||||
var data = data.split("\n");
|
||||
// clear local data
|
||||
FONT.data.characters.length = 0;
|
||||
FONT.data.characters_bytes.length = 0;
|
||||
FONT.data.character_image_urls.length = 0;
|
||||
// make sure the font file is valid
|
||||
if (data.shift().trim() != 'MAX7456') {
|
||||
var msg = 'that font file doesnt have the MAX7456 header, giving up';
|
||||
console.debug(msg);
|
||||
Promise.reject(msg);
|
||||
}
|
||||
var character_bits = [];
|
||||
var character_bytes = [];
|
||||
// hexstring is for debugging
|
||||
FONT.data.hexstring = [];
|
||||
var pushChar = function() {
|
||||
FONT.data.characters_bytes.push(character_bytes);
|
||||
FONT.data.characters.push(character_bits);
|
||||
FONT.draw(FONT.data.characters.length-1);
|
||||
//$log.debug('parsed char ', i, ' as ', character);
|
||||
character_bits = [];
|
||||
character_bytes = [];
|
||||
};
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var line = data[i];
|
||||
// hexstring is for debugging
|
||||
FONT.data.hexstring.push('0x' + parseInt(line, 2).toString(16));
|
||||
// every 64 bytes (line) is a char, we're counting chars though, which are 2 bits
|
||||
if (character_bits.length == FONT.constants.SIZES.MAX_NVM_FONT_CHAR_FIELD_SIZE * (8 / 2)) {
|
||||
pushChar()
|
||||
}
|
||||
for (var y = 0; y < 8; y = y + 2) {
|
||||
var v = parseInt(line.slice(y, y+2), 2);
|
||||
character_bits.push(v);
|
||||
}
|
||||
character_bytes.push(parseInt(line, 2));
|
||||
}
|
||||
// push the last char
|
||||
pushChar();
|
||||
return FONT.data.characters;
|
||||
};
|
||||
|
||||
|
||||
FONT.openFontFile = function($preview) {
|
||||
return new Promise(function(resolve) {
|
||||
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: [{extensions: ['mcm']}]}, function (fileEntry) {
|
||||
FONT.data.loaded_font_file = fileEntry.name;
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
return;
|
||||
}
|
||||
fileEntry.file(function (file) {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function(e) {
|
||||
if (e.total != 0 && e.total == e.loaded) {
|
||||
FONT.parseMCMFontFile(e.target.result);
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
console.error('could not load whole font file');
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* returns a canvas image with the character on it
|
||||
*/
|
||||
var drawCanvas = function(charAddress) {
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
// TODO: do we want to be able to set pixel size? going to try letting the consumer scale the image.
|
||||
var pixelSize = pixelSize || 1;
|
||||
var width = pixelSize * FONT.constants.SIZES.CHAR_WIDTH;
|
||||
var height = pixelSize * FONT.constants.SIZES.CHAR_HEIGHT;
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
for (var y = 0; y < height; y++) {
|
||||
for (var x = 0; x < width; x++) {
|
||||
if (!(charAddress in FONT.data.characters)) {
|
||||
console.log('charAddress', charAddress, ' is not in ', FONT.data.characters.length);
|
||||
}
|
||||
var v = FONT.data.characters[charAddress][(y*width)+x];
|
||||
ctx.fillStyle = FONT.constants.COLORS[v];
|
||||
ctx.fillRect(x, y, pixelSize, pixelSize);
|
||||
}
|
||||
}
|
||||
return canvas;
|
||||
};
|
||||
|
||||
FONT.draw = function(charAddress) {
|
||||
var cached = FONT.data.character_image_urls[charAddress];
|
||||
if (!cached) {
|
||||
cached = FONT.data.character_image_urls[charAddress] = drawCanvas(charAddress).toDataURL('image/png');
|
||||
}
|
||||
return cached;
|
||||
};
|
||||
|
||||
FONT.msp = {
|
||||
encode: function(charAddress) {
|
||||
return [charAddress].concat(FONT.data.characters_bytes[charAddress].slice(0,FONT.constants.SIZES.MAX_NVM_FONT_CHAR_SIZE));
|
||||
}
|
||||
};
|
||||
|
||||
FONT.upload = function($progress) {
|
||||
return Promise.mapSeries(FONT.data.characters, function(data, i) {
|
||||
$progress.val((i / FONT.data.characters.length) * 100);
|
||||
return MSP.promise(MSP_codes.MSP_OSD_CHAR_WRITE, FONT.msp.encode(i));
|
||||
})
|
||||
.then(function() {
|
||||
return MSP.promise(MSP_codes.MSP_SET_REBOOT);
|
||||
});
|
||||
};
|
||||
|
||||
FONT.preview = function($el) {
|
||||
$el.empty()
|
||||
for (var i = 0; i < SYM.LOGO; i++) {
|
||||
var url = FONT.data.character_image_urls[i];
|
||||
$el.append('<img src="'+url+'" title="0x'+i.toString(16)+'"></img>');
|
||||
}
|
||||
};
|
||||
|
||||
FONT.symbol = function(hexVal) {
|
||||
return String.fromCharCode(hexVal);
|
||||
};
|
||||
|
||||
var OSD = OSD || {};
|
||||
|
||||
// parsed fc output and output to fc, used by to OSD.msp.encode
|
||||
OSD.initData = function() {
|
||||
OSD.data = {
|
||||
video_system: null,
|
||||
display_items: [],
|
||||
last_positions: {},
|
||||
preview: []
|
||||
};
|
||||
};
|
||||
OSD.initData();
|
||||
|
||||
OSD.constants = {
|
||||
VIDEO_TYPES: [
|
||||
'AUTO',
|
||||
'PAL',
|
||||
'NTSC'
|
||||
],
|
||||
VIDEO_LINES: {
|
||||
PAL: 16,
|
||||
NTSC: 13
|
||||
},
|
||||
VIDEO_BUFFER_CHARS: {
|
||||
PAL: 480,
|
||||
NTSC: 390
|
||||
},
|
||||
AHISIDEBARWIDTHPOSITION: 7,
|
||||
AHISIDEBARHEIGHTPOSITION: 3,
|
||||
// order matters, so these are going in an array... pry could iterate the example map instead
|
||||
DISPLAY_FIELDS: [
|
||||
{
|
||||
name: 'MAIN_BATT_VOLTAGE',
|
||||
default_position: -29,
|
||||
positionable: true,
|
||||
preview: FONT.symbol(SYM.VOLT) + '16.8'
|
||||
},
|
||||
{
|
||||
name: 'RSSI_VALUE',
|
||||
default_position: -59,
|
||||
positionable: true,
|
||||
preview: FONT.symbol(SYM.RSSI) + '99'
|
||||
},
|
||||
{
|
||||
name: 'TIMER',
|
||||
default_position: -39,
|
||||
positionable: true,
|
||||
preview: FONT.symbol(SYM.ON_M) + ' 11:11'
|
||||
},
|
||||
{
|
||||
name: 'THROTTLE_POS',
|
||||
default_position: -9,
|
||||
positionable: true,
|
||||
preview: FONT.symbol(SYM.THR) + FONT.symbol(SYM.THR1) + ' 0'
|
||||
},
|
||||
{
|
||||
name: 'CPU_LOAD',
|
||||
default_position: 26,
|
||||
positionable: true,
|
||||
preview: '15'
|
||||
},
|
||||
{
|
||||
name: 'VTX_CHANNEL',
|
||||
default_position: 1,
|
||||
positionable: true
|
||||
},
|
||||
{
|
||||
name: 'VOLTAGE_WARNING',
|
||||
default_position: -80,
|
||||
positionable: true,
|
||||
preview: 'LOW VOLTAGE'
|
||||
},
|
||||
{
|
||||
name: 'ARMED',
|
||||
default_position: -107,
|
||||
positionable: true,
|
||||
preview: 'ARMED'
|
||||
},
|
||||
{
|
||||
name: 'DISARMED',
|
||||
default_position: -109,
|
||||
positionable: true,
|
||||
preview: 'DISARMED'
|
||||
},
|
||||
{
|
||||
name: 'ARTIFICIAL_HORIZON',
|
||||
default_position: -1,
|
||||
positionable: false
|
||||
},
|
||||
{
|
||||
name: 'HORIZON_SIDEBARS',
|
||||
default_position: -1,
|
||||
positionable: false
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
OSD.updateDisplaySize = function() {
|
||||
var video_type = OSD.constants.VIDEO_TYPES[OSD.data.video_system];
|
||||
if (video_type == 'AUTO') {
|
||||
video_type = 'PAL';
|
||||
}
|
||||
// compute the size
|
||||
OSD.data.display_size = {
|
||||
x: 30,
|
||||
y: OSD.constants.VIDEO_LINES[video_type],
|
||||
total: null
|
||||
};
|
||||
};
|
||||
|
||||
OSD.msp = {
|
||||
encodeOther: function() {
|
||||
return [-1, OSD.data.video_system];
|
||||
},
|
||||
encode: function(display_item) {
|
||||
return [
|
||||
display_item.index,
|
||||
specificByte(display_item.position, 0),
|
||||
specificByte(display_item.position, 1)
|
||||
];
|
||||
},
|
||||
// Currently only parses MSP_MAX_OSD responses, add a switch on payload.code if more codes are handled
|
||||
decode: function(payload) {
|
||||
var view = payload.data;
|
||||
var d = OSD.data;
|
||||
d.compiled_in = view.getUint8(0, 1);
|
||||
d.video_system = view.getUint8(1, 1);
|
||||
d.display_items = [];
|
||||
// start at the offset from the other fields
|
||||
for (var i = 2; i < view.byteLength; i = i + 2) {
|
||||
var v = view.getInt16(i, 1)
|
||||
var j = d.display_items.length;
|
||||
var c = OSD.constants.DISPLAY_FIELDS[j];
|
||||
d.display_items.push({
|
||||
name: c.name,
|
||||
index: j,
|
||||
position: v,
|
||||
positionable: c.positionable,
|
||||
preview: c.preview
|
||||
});
|
||||
}
|
||||
OSD.updateDisplaySize();
|
||||
}
|
||||
};
|
||||
|
||||
OSD.GUI = {};
|
||||
OSD.GUI.preview = {
|
||||
onDragStart: function(e) {
|
||||
var ev = e.originalEvent;
|
||||
ev.dataTransfer.setData("text/plain", ev.target.id);
|
||||
ev.dataTransfer.setDragImage($(this).data('field').preview_img, 6, 9);
|
||||
},
|
||||
onDragOver: function(e) {
|
||||
var ev = e.originalEvent;
|
||||
ev.preventDefault();
|
||||
ev.dataTransfer.dropEffect = "move"
|
||||
$(this).css({
|
||||
background: 'rgba(0,0,0,.5)'
|
||||
});
|
||||
},
|
||||
onDragLeave: function(e) {
|
||||
// brute force unstyling on drag leave
|
||||
$(this).removeAttr('style');
|
||||
},
|
||||
onDrop: function(e) {
|
||||
var ev = e.originalEvent;
|
||||
var position = $(this).removeAttr('style').data('position');
|
||||
if (position > OSD.data.display_size.total/2) {
|
||||
position = position - OSD.data.display_size.total;
|
||||
}
|
||||
var field_id = parseInt(ev.dataTransfer.getData('text').split('field-')[1])
|
||||
$('input.'+field_id+'.position').val(position).change();
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
TABS.osd = {};
|
||||
TABS.osd.initialize = function (callback) {
|
||||
var self = this;
|
||||
|
||||
if (GUI.active_tab != 'osd') {
|
||||
GUI.active_tab = 'osd';
|
||||
}
|
||||
|
||||
$('#content').load("./tabs/osd.html", function () {
|
||||
// translate to user-selected language
|
||||
localize();
|
||||
|
||||
// 2 way binding... sorta
|
||||
function updateOsdView() {
|
||||
// ask for the OSD config data
|
||||
MSP.promise(MSP_codes.MSP_OSD_CONFIG)
|
||||
.then(function(info) {
|
||||
if (!info.length) {
|
||||
$('.unsupported').fadeIn();
|
||||
return;
|
||||
}
|
||||
$('.supported').fadeIn();
|
||||
OSD.msp.decode(info);
|
||||
// video mode
|
||||
var $videoTypes = $('.video-types').empty();
|
||||
for (var i = 0; i < OSD.constants.VIDEO_TYPES.length; i++) {
|
||||
var type = OSD.constants.VIDEO_TYPES[i];
|
||||
var $checkbox = $('<label/>').append($('<input name="video_system" type="radio"/>'+type+'</label>')
|
||||
.prop('checked', i === OSD.data.video_system)
|
||||
.data('type', type)
|
||||
.data('type', i)
|
||||
);
|
||||
$videoTypes.append($checkbox);
|
||||
}
|
||||
$videoTypes.find(':radio').click(function(e) {
|
||||
OSD.data.video_system = $(this).data('type');
|
||||
MSP.promise(MSP_codes.MSP_SET_OSD_CONFIG, OSD.msp.encodeOther())
|
||||
.then(function() {
|
||||
updateOsdView();
|
||||
});
|
||||
});
|
||||
|
||||
// display fields on/off and position
|
||||
var $displayFields = $('.display-fields').empty();
|
||||
for (let field of OSD.data.display_items) {
|
||||
var checked = (-1 != field.position) ? 'checked' : '';
|
||||
var $field = $('<div class="display-field"/>');
|
||||
$field.append(
|
||||
$('<input type="checkbox" name="'+field.name+'" class="togglesmall"></input>')
|
||||
.data('field', field)
|
||||
.attr('checked', field.position != -1)
|
||||
.change(function(e) {
|
||||
var field = $(this).data('field');
|
||||
var $position = $(this).parent().find('.position.'+field.name);
|
||||
if (field.position == -1) {
|
||||
$position.show();
|
||||
field.position = OSD.data.last_positions[field.name]
|
||||
}
|
||||
else {
|
||||
$position.hide();
|
||||
OSD.data.last_positions[field.name] = field.position
|
||||
field.position = -1
|
||||
}
|
||||
MSP.promise(MSP_codes.MSP_SET_OSD_CONFIG, OSD.msp.encode(field))
|
||||
.then(function() {
|
||||
updateOsdView();
|
||||
});
|
||||
})
|
||||
);
|
||||
$field.append('<label for="'+field.name+'">'+field.name+'</label>');
|
||||
if (field.positionable && field.position != -1) {
|
||||
$field.append(
|
||||
$('<input type="number" class="'+field.index+' position"></input>')
|
||||
.data('field', field)
|
||||
.val(field.position)
|
||||
.change($.debounce(250, function(e) {
|
||||
var field = $(this).data('field');
|
||||
var position = parseInt($(this).val());
|
||||
field.position = position;
|
||||
MSP.promise(MSP_codes.MSP_SET_OSD_CONFIG, OSD.msp.encode(field))
|
||||
.then(function() {
|
||||
updateOsdView();
|
||||
});
|
||||
}))
|
||||
);
|
||||
}
|
||||
$displayFields.append($field);
|
||||
}
|
||||
GUI.switchery();
|
||||
// buffer the preview
|
||||
OSD.data.preview = [];
|
||||
OSD.data.display_size.total = OSD.data.display_size.x * OSD.data.display_size.y;
|
||||
// clear the buffer
|
||||
for(var 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
|
||||
for(let field of OSD.data.display_items) {
|
||||
if (!field.preview || field.position == -1) { continue; }
|
||||
var j = (field.position >= 0) ? field.position : field.position + OSD.data.display_size.total;
|
||||
// create the preview image
|
||||
field.preview_img = new Image();
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext("2d");
|
||||
// fill the screen buffer
|
||||
for(var i = 0; i < field.preview.length; i++) {
|
||||
var charCode = field.preview.charCodeAt(i);
|
||||
OSD.data.preview[j++] = [field, charCode];
|
||||
// draw the preview
|
||||
var img = new Image();
|
||||
img.src = FONT.draw(charCode);
|
||||
ctx.drawImage(img, i*12, 0);
|
||||
}
|
||||
field.preview_img.src = canvas.toDataURL('image/png');
|
||||
}
|
||||
// logo
|
||||
var x = 160;
|
||||
for (var i = 1; i < 5; i++) {
|
||||
for (var j = 3; j < 27; j++)
|
||||
OSD.data.preview[i * 30 + j] = [{name: 'LOGO', positionable: false}, x++];
|
||||
}
|
||||
var centerishPosition = 194;
|
||||
// artificial horizon
|
||||
if ($('input[name="ARTIFICIAL_HORIZON"]').prop('checked')) {
|
||||
for (var i = 0; i < 9; i++) {
|
||||
OSD.data.preview[centerishPosition - 4 + i] = SYM.AH_BAR9_0 + 4;
|
||||
}
|
||||
OSD.data.preview[centerishPosition - 1] = SYM.AH_CENTER_LINE;
|
||||
OSD.data.preview[centerishPosition + 1] = SYM.AH_CENTER_LINE_RIGHT;
|
||||
OSD.data.preview[centerishPosition] = SYM.AH_CENTER;
|
||||
}
|
||||
// sidebars
|
||||
if ($('input[name="HORIZON_SIDEBARS"]').prop('checked')) {
|
||||
var hudwidth = OSD.constants.AHISIDEBARWIDTHPOSITION;
|
||||
var hudheight = OSD.constants.AHISIDEBARHEIGHTPOSITION;
|
||||
for (var i = -hudheight; i <= hudheight; i++) {
|
||||
OSD.data.preview[centerishPosition - hudwidth + (i * FONT.constants.SIZES.LINE)] = SYM.AH_DECORATION;
|
||||
OSD.data.preview[centerishPosition + hudwidth + (i * FONT.constants.SIZES.LINE)] = SYM.AH_DECORATION;
|
||||
}
|
||||
// AH level indicators
|
||||
OSD.data.preview[centerishPosition-hudwidth+1] = SYM.AH_LEFT;
|
||||
OSD.data.preview[centerishPosition+hudwidth-1] = SYM.AH_RIGHT;
|
||||
}
|
||||
// render
|
||||
var $preview = $('.display-layout .preview').empty();
|
||||
var $row = $('<div class="row"/>');
|
||||
for(var i = 0; i < OSD.data.display_size.total;) {
|
||||
var charCode = OSD.data.preview[i];
|
||||
if (typeof charCode === 'object') {
|
||||
var field = OSD.data.preview[i][0];
|
||||
var charCode = OSD.data.preview[i][1];
|
||||
}
|
||||
var $img = $('<div class="char"><img src='+FONT.draw(charCode)+'></img></div>')
|
||||
.on('dragover', OSD.GUI.preview.onDragOver)
|
||||
.on('dragleave', OSD.GUI.preview.onDragLeave)
|
||||
.on('drop', OSD.GUI.preview.onDrop)
|
||||
.data('position', i);
|
||||
if (field && field.positionable) {
|
||||
$img
|
||||
.attr('id', 'field-'+field.index)
|
||||
.data('field', field)
|
||||
.prop('draggable', true)
|
||||
.on('dragstart', OSD.GUI.preview.onDragStart);
|
||||
}
|
||||
else {
|
||||
}
|
||||
$row.append($img);
|
||||
if (++i % OSD.data.display_size.x == 0) {
|
||||
$preview.append($row);
|
||||
$row = $('<div class="row"/>');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('button.save').click(function() {
|
||||
var self = this;
|
||||
MSP.promise(MSP_codes.MSP_EEPROM_WRITE);
|
||||
var oldText = $(this).text();
|
||||
$(this).html("Saved");
|
||||
setTimeout(function () {
|
||||
$(self).html(oldText);
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
// font preview window
|
||||
var $preview = $('.font-preview');
|
||||
|
||||
// init structs once, also clears current font
|
||||
FONT.initData();
|
||||
|
||||
var $fontPicker = $('.fontbuttons button');
|
||||
$fontPicker.click(function(e) {
|
||||
if (!$(this).data('font-file')) { return; }
|
||||
$fontPicker.removeClass('active');
|
||||
$(this).addClass('active');
|
||||
$.get('/resources/osd/' + $(this).data('font-file') + '.mcm', function(data) {
|
||||
FONT.parseMCMFontFile(data);
|
||||
FONT.preview($preview);
|
||||
updateOsdView();
|
||||
});
|
||||
});
|
||||
|
||||
// load the first font when we change tabs
|
||||
$fontPicker.first().click();
|
||||
|
||||
$('button.load_font_file').click(function() {
|
||||
$fontPicker.removeClass('active');
|
||||
FONT.openFontFile().then(function() {
|
||||
FONT.preview($preview);
|
||||
updateOsdView();
|
||||
});
|
||||
});
|
||||
|
||||
// font upload
|
||||
$('button.flash_font').click(function () {
|
||||
if (!GUI.connect_lock) { // button disabled while flashing is in progress
|
||||
$('.progressLabel').text('Uploading...');
|
||||
FONT.upload($('.progress').val(0)).then(function() {
|
||||
var msg = 'Uploaded all ' + FONT.data.characters.length + ' characters';
|
||||
console.log(msg);
|
||||
$('.progressLabel').text(msg);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', 'span.progressLabel a.save_font', function () {
|
||||
chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'baseflight', accepts: [{extensions: ['mcm']}]}, function (fileEntry) {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.fileSystem.getDisplayPath(fileEntry, function (path) {
|
||||
console.log('Saving firmware to: ' + path);
|
||||
|
||||
// check if file is writable
|
||||
chrome.fileSystem.isWritableEntry(fileEntry, function (isWritable) {
|
||||
if (isWritable) {
|
||||
var blob = new Blob([intel_hex], {type: 'text/plain'});
|
||||
|
||||
fileEntry.createWriter(function (writer) {
|
||||
var truncated = false;
|
||||
|
||||
writer.onerror = function (e) {
|
||||
console.error(e);
|
||||
};
|
||||
|
||||
writer.onwriteend = function() {
|
||||
if (!truncated) {
|
||||
// onwriteend will be fired again when truncation is finished
|
||||
truncated = true;
|
||||
writer.truncate(blob.size);
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
writer.write(blob);
|
||||
}, function (e) {
|
||||
console.error(e);
|
||||
});
|
||||
} else {
|
||||
console.log('You don\'t have write permissions for this file, sorry.');
|
||||
GUI.log('You don\'t have <span style="color: red">write permissions</span> for this file');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(document).keypress(function (e) {
|
||||
if (e.which == 13) { // enter
|
||||
// Trigger regular Flashing sequence
|
||||
$('a.flash_font').click();
|
||||
}
|
||||
});
|
||||
|
||||
GUI.content_ready(callback);
|
||||
});
|
||||
};
|
||||
|
||||
TABS.osd.cleanup = function (callback) {
|
||||
PortHandler.flush_callbacks();
|
||||
|
||||
// unbind "global" events
|
||||
$(document).unbind('keypress');
|
||||
$(document).off('click', 'span.progressLabel a');
|
||||
|
||||
if (callback) callback();
|
||||
};
|
Loading…
Reference in New Issue