mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-16 21:05:28 +03:00
sync
This commit is contained in:
parent
278e25a872
commit
06f643812d
30 changed files with 1280 additions and 1143 deletions
|
@ -128,6 +128,22 @@
|
|||
"message": "<span style=\"color: red\">Failed</span> to close serial port"
|
||||
},
|
||||
|
||||
"usbDeviceOpened": {
|
||||
"message": "USB device <span style=\"color: green\">successfully</span> opened with ID: $1"
|
||||
},
|
||||
"usbDeviceOpenFail": {
|
||||
"message": "<span style=\"color: red\">Failed</span> to open USB device!"
|
||||
},
|
||||
"usbDeviceClosed": {
|
||||
"message": "USB device <span style=\"color: green\">successfully</span> closed"
|
||||
},
|
||||
"usbDeviceCloseFail": {
|
||||
"message": "<span style=\"color: red\">Failed</span> to close USB device"
|
||||
},
|
||||
"usbDeviceUdevNotice": {
|
||||
"message": "Are <strong>udev rules</strong> installed correctly? See docs for instructions"
|
||||
},
|
||||
|
||||
"noConfigurationReceived": {
|
||||
"message": "No configuration received within <span style=\"color: red\">10 seconds</span>, communication <span style=\"color: red\">failed</span>"
|
||||
},
|
||||
|
@ -190,26 +206,18 @@
|
|||
"message": "Cycle Time:"
|
||||
},
|
||||
|
||||
"please_grant_usb_permissions": {
|
||||
"message": "Please click on <strong>\"Request Optional Permissions\"</strong> button to grant application <strong style=\"color: red\">required</strong> <strong>USB</strong> access"
|
||||
"dfu_connect_message": {
|
||||
"message": "Please use the Firmware Flasher to access DFU devices"
|
||||
},
|
||||
"usb_permissions_granted": {
|
||||
"message": "Optional <strong>USB</strong> permissions <strong style=\"color: #57a929\">granted</strong>"
|
||||
|
||||
"dfu_erased_kilobytes": {
|
||||
"message": "Erased $1 kB of flash <span style=\"color: green\">successfully</span>"
|
||||
},
|
||||
|
||||
"eeprom_saved_ok": {
|
||||
"message": "EEPROM <span style=\"color: #57a929\">saved</span>"
|
||||
},
|
||||
|
||||
"default_optional_permissions_head": {
|
||||
"message": "Optional USB Permissions"
|
||||
},
|
||||
"default_optional_permissions_text": {
|
||||
"message": "Due to addition of <strong>Naze32PRO</strong> to the supported hardware family, Configurator <strong style=\"color: red\">requires</strong> USB access to allow firmware flashing via DFU"
|
||||
},
|
||||
"default_request_optional_permissions": {
|
||||
"message": "Request Optional Permissions"
|
||||
},
|
||||
"defaultWelcomeText": {
|
||||
"message": "Welcome to <strong>Cleanflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller.<br /><br />The application supports all hardware that can run cleanflight (<a href=\"http://seriouslypro.com/spracingf3\" target=\"_blank\">SPRacingF3</a>, <a href=\"http://www.immersionrc.com/fpv-products/vortex-racing-quad/\" target=\"_blank\">Vortex</a>, <a href=\"https://github.com/TauLabs/TauLabs/wiki/Sparky\" target=\"_blank\">Sparky</a>, <a href=\"http://www.readymaderc.com/store/index.php?main_page=product_info&cPath=76_156&products_id=4221\" target=\"_blank\">DoDo</a>, <a href=\"https://www.openpilot.org/product/coptercontrol/\" target=\"_blank\">CC3D/EVO</a>, <a href=\"http://www.multiwiicopter.com/products/paris-air-hero-32-naze\" target=\"_blank\">Air Hero 32</a>, <a href=\"http://www.readytoflyquads.com/flight-controllers/flip-series\" target=\"_blank\">Flip32/+/Deluxe</a>, <a href=\"http://multirotormania.com/129-dragonfly32\" target=\"_blank\">DragonFly32</a>, <a href=\"http://www.goodluckbuy.com/micro-quadcopter-flight-driver-controller-9dof-9-axis-altitude-sensor-stm32f103.html\" target=\"_blank\">CJMCU Microquad</a>, Chebuzz F3, <a href=\"http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF254044\" target=\"_blank\">STM32F3Discovery</a>, <a href=\"http://www.overskyrc.com/hermit-micro-fpv-brushless-quadcopter-145mm-98g-fully-assembled-p-621.html\" target=\"_blank\">Hermit</a>, <a href=\"http://rcexplorer.se/blog/2015/05/introducing-the-naze32-tricopter-frame/\" target=\"_blank\">Naze32 Tricopter Frame</a>, <a href=\"http://www.2dogrc.com/skyline-32-naze-32-bit-flight-controller-acro-version.html\" target=\"_blank\">Skyline32</a>, <a href=\"http://abusemark.com/store/index.php?main_page=index&cPath=1\" target=\"_blank\">Naze/32/Mini/Pro</a>/<a href=\"http://www.massiverc.com/PrestaShop/en/574-massive-acro-blackbox-flight-control-board.html\" target=\"_blank\">Blackbox</a> etc)<br /><br />The firmware source code can be downloaded from <a href=\"https://github.com/cleanflight/cleanflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/cleanflight/cleanflight/releases\" title=\"www.github.com\" target=\"_blank\">here</a>, development builds available <a href=\"http://cleanflight.memoryleaks.org/builds/\" target=\"_blank\">here</a><br /><br />Latest <strong>CP210x Drivers</strong> can be downloaded from <a href=\"http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx\" title=\"http://www.silabs.com/\" target=\"_blank\">here</a><br />"
|
||||
},
|
||||
|
@ -1129,7 +1137,8 @@
|
|||
"message": "Warning"
|
||||
},
|
||||
"firmwareFlasherWarningText": {
|
||||
"message": "Please do <span style=\"color: red\">not</span> try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher.<br />Do <span style=\"color: red\">not</span> <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br /><span style=\"color: #57a929\">Note: </span>STM32 bootloader is stored in ROM, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br /><span style=\"color: red\">Note: </span>Make sure you have a backup; some upgrades/downgrades will wipe your configuration.<br /><span style=\"color: #57a929\">Note:</span> If you have problems flashing try disconnecting all cables from your FC.<br /><br /><span style=\"color: #57a929\">Note: </span>If you have lost comminication with your board then power off the board, jumper the bootloader pins, power on, enable 'No reboot sequence', enable 'Full chip erase', re-flash, then power off, remove bootloader jumper, power on and connect (For all firmware except OPBL firmware)."
|
||||
"message": "Please do <span style=\"color: red\">not</span> try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher.<br />Do <span style=\"color: red\">not</span> <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br /><span style=\"color: green\">Note: </span>STM32 bootloader is stored in ROM, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br /><span style=\"color: red\">Note: </span>Make sure you have a backup; some upgrades/downgrades will wipe your configuration.<br /><span style=\"color: green\">Note:</span> If you have problems flashing try disconnecting all cables from your FC.<br /><br /><span style=\"color: green\">Note: </span>If you have lost comminication with your board then power off the board, jumper the bootloader pins, power on, enable 'No reboot sequence', enable 'Full chip erase', re-flash, then power off, remove bootloader jumper, power on and connect (For all firmware except OPBL firmware)."
|
||||
>>>>>>> cleanflight/development
|
||||
},
|
||||
"firmwareFlasherButtonLeave": {
|
||||
"message": "Leave Firmware Flasher"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var CONFIGURATOR = {
|
||||
'releaseDate': 1443815435720, // new Date().getTime() - Fri Oct 02 2015 20:50:49 GMT+0100 (GMT Daylight Time)
|
||||
'releaseDate': 1446278768375, // new Date().getTime() - Fri Oct 02 2015 20:50:49 GMT+0100 (GMT Daylight Time)
|
||||
|
||||
// all versions are specified and compared using semantic versioning http://semver.org/
|
||||
'apiVersionAccepted': '1.2.0',
|
||||
|
|
|
@ -10,7 +10,6 @@ var GUI_control = function () {
|
|||
this.active_tab;
|
||||
this.tab_switch_in_progress = false;
|
||||
this.operating_system;
|
||||
this.optional_usb_permissions = false; // controlled by usb permissions code
|
||||
this.interval_array = [];
|
||||
this.timeout_array = [];
|
||||
this.defaultAllowedTabsWhenDisconnected = [
|
||||
|
|
4
js/libraries/jquery-2.1.3.min.js
vendored
4
js/libraries/jquery-2.1.3.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -16,13 +16,13 @@ THREE.SpriteCanvasMaterial = function ( parameters ) {
|
|||
};
|
||||
|
||||
THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
|
||||
THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;
|
||||
|
||||
THREE.SpriteCanvasMaterial.prototype.clone = function () {
|
||||
|
||||
var material = new THREE.SpriteCanvasMaterial();
|
||||
|
||||
THREE.Material.prototype.clone.call( this, material );
|
||||
|
||||
material.copy( this );
|
||||
material.color.copy( this.color );
|
||||
material.program = this.program;
|
||||
|
||||
|
@ -58,12 +58,14 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
_viewportWidth = _canvasWidth,
|
||||
_viewportHeight = _canvasHeight,
|
||||
|
||||
pixelRatio = 1,
|
||||
|
||||
_context = _canvas.getContext( '2d', {
|
||||
alpha: parameters.alpha === true
|
||||
} ),
|
||||
|
||||
_clearColor = new THREE.Color( 0x000000 ),
|
||||
_clearAlpha = 0,
|
||||
_clearAlpha = parameters.alpha === true ? 0 : 1,
|
||||
|
||||
_contextGlobalAlpha = 1,
|
||||
_contextGlobalCompositeOperation = 0,
|
||||
|
@ -122,12 +124,6 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
this.domElement = _canvas;
|
||||
|
||||
this.devicePixelRatio = parameters.devicePixelRatio !== undefined
|
||||
? parameters.devicePixelRatio
|
||||
: self.devicePixelRatio !== undefined
|
||||
? self.devicePixelRatio
|
||||
: 1;
|
||||
|
||||
this.autoClear = true;
|
||||
this.sortObjects = true;
|
||||
this.sortElements = true;
|
||||
|
@ -141,17 +137,43 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// WebGLRenderer compatibility
|
||||
|
||||
this.supportsVertexTextures = function () {};
|
||||
this.setFaceCulling = function () {};
|
||||
|
||||
// API
|
||||
|
||||
this.getContext = function () {
|
||||
|
||||
return _context;
|
||||
|
||||
};
|
||||
|
||||
this.getContextAttributes = function () {
|
||||
|
||||
return _context.getContextAttributes();
|
||||
|
||||
};
|
||||
|
||||
this.getPixelRatio = function () {
|
||||
|
||||
return pixelRatio;
|
||||
|
||||
};
|
||||
|
||||
this.setPixelRatio = function ( value ) {
|
||||
|
||||
if ( value !== undefined ) pixelRatio = value;
|
||||
|
||||
};
|
||||
|
||||
this.setSize = function ( width, height, updateStyle ) {
|
||||
|
||||
_canvasWidth = width * this.devicePixelRatio;
|
||||
_canvasHeight = height * this.devicePixelRatio;
|
||||
_canvasWidth = width * pixelRatio;
|
||||
_canvasHeight = height * pixelRatio;
|
||||
|
||||
_canvas.width = _canvasWidth;
|
||||
_canvas.height = _canvasHeight;
|
||||
|
@ -166,7 +188,7 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
_clipBox.min.set( -_canvasWidthHalf, -_canvasHeightHalf ),
|
||||
_clipBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
|
||||
_clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
|
||||
|
||||
_clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
|
||||
|
@ -186,11 +208,11 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
this.setViewport = function ( x, y, width, height ) {
|
||||
|
||||
_viewportX = x * this.devicePixelRatio;
|
||||
_viewportY = y * this.devicePixelRatio;
|
||||
_viewportX = x * pixelRatio;
|
||||
_viewportY = y * pixelRatio;
|
||||
|
||||
_viewportWidth = width * this.devicePixelRatio;
|
||||
_viewportHeight = height * this.devicePixelRatio;
|
||||
_viewportWidth = width * pixelRatio;
|
||||
_viewportHeight = height * pixelRatio;
|
||||
|
||||
};
|
||||
|
||||
|
@ -240,17 +262,17 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
_clearBox.expandByScalar( 2 );
|
||||
|
||||
_clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;
|
||||
_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf;
|
||||
_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value !
|
||||
_clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;
|
||||
_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf;
|
||||
_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value !
|
||||
|
||||
if ( _clearAlpha < 1 ) {
|
||||
|
||||
_context.clearRect(
|
||||
_clearBox.min.x | 0,
|
||||
_clearBox.min.y | 0,
|
||||
_clearBox.max.y | 0,
|
||||
( _clearBox.max.x - _clearBox.min.x ) | 0,
|
||||
( _clearBox.max.y - _clearBox.min.y ) | 0
|
||||
( _clearBox.min.y - _clearBox.max.y ) | 0
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -264,9 +286,9 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
_context.fillRect(
|
||||
_clearBox.min.x | 0,
|
||||
_clearBox.min.y | 0,
|
||||
_clearBox.max.y | 0,
|
||||
( _clearBox.max.x - _clearBox.min.x ) | 0,
|
||||
( _clearBox.max.y - _clearBox.min.y ) | 0
|
||||
( _clearBox.min.y - _clearBox.max.y ) | 0
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -496,33 +518,20 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
var texture = material.map;
|
||||
|
||||
if ( texture !== null && texture.image !== undefined ) {
|
||||
|
||||
if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
|
||||
|
||||
if ( texture.image.width > 0 ) {
|
||||
|
||||
textureToPattern( texture );
|
||||
|
||||
}
|
||||
|
||||
texture.addEventListener( 'update', onTextureUpdate );
|
||||
|
||||
}
|
||||
if ( texture !== null ) {
|
||||
|
||||
var pattern = _patterns[ texture.id ];
|
||||
|
||||
if ( pattern !== undefined ) {
|
||||
if ( pattern === undefined || pattern.version !== texture.version ) {
|
||||
|
||||
setFillStyle( pattern );
|
||||
|
||||
} else {
|
||||
|
||||
setFillStyle( 'rgba( 0, 0, 0, 1 )' );
|
||||
pattern = textureToPattern( texture );
|
||||
_patterns[ texture.id ] = pattern;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
if ( pattern.canvas !== undefined ) {
|
||||
|
||||
setFillStyle( pattern.canvas );
|
||||
|
||||
var bitmap = texture.image;
|
||||
|
||||
|
@ -544,6 +553,8 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
_context.fillRect( ox, oy, sx, sy );
|
||||
_context.restore();
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// no texture
|
||||
|
@ -704,7 +715,9 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
if ( material.map !== null ) {
|
||||
|
||||
if ( material.map.mapping instanceof THREE.UVMapping ) {
|
||||
var mapping = material.map.mapping;
|
||||
|
||||
if ( mapping === THREE.UVMapping ) {
|
||||
|
||||
_uvs = element.uvs;
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map );
|
||||
|
@ -713,7 +726,7 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
} else if ( material.envMap !== null ) {
|
||||
|
||||
if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
|
||||
if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) {
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv1x = 0.5 * _normal.x + 0.5;
|
||||
|
@ -729,25 +742,8 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
|
||||
|
||||
} else if ( material.envMap.mapping instanceof THREE.SphericalRefractionMapping ) {
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv1x = - 0.5 * _normal.x + 0.5;
|
||||
_uv1y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv2x = - 0.5 * _normal.x + 0.5;
|
||||
_uv2y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv3x = - 0.5 * _normal.x + 0.5;
|
||||
_uv3y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
_color.copy( material.color );
|
||||
|
@ -826,18 +822,18 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
function onTextureUpdate ( event ) {
|
||||
|
||||
textureToPattern( event.target );
|
||||
|
||||
}
|
||||
|
||||
function textureToPattern( texture ) {
|
||||
|
||||
if ( texture instanceof THREE.CompressedTexture ) return;
|
||||
if ( texture.version === 0 ||
|
||||
texture instanceof THREE.CompressedTexture ||
|
||||
texture instanceof THREE.DataTexture ) {
|
||||
|
||||
var repeatX = texture.wrapS === THREE.RepeatWrapping;
|
||||
var repeatY = texture.wrapT === THREE.RepeatWrapping;
|
||||
return {
|
||||
canvas: undefined,
|
||||
version: texture.version
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var image = texture.image;
|
||||
|
||||
|
@ -849,45 +845,51 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
context.setTransform( 1, 0, 0, - 1, 0, image.height );
|
||||
context.drawImage( image, 0, 0 );
|
||||
|
||||
_patterns[ texture.id ] = _context.createPattern(
|
||||
canvas, repeatX === true && repeatY === true
|
||||
? 'repeat'
|
||||
: repeatX === true && repeatY === false
|
||||
? 'repeat-x'
|
||||
: repeatX === false && repeatY === true
|
||||
? 'repeat-y'
|
||||
: 'no-repeat'
|
||||
);
|
||||
var repeatX = texture.wrapS === THREE.RepeatWrapping;
|
||||
var repeatY = texture.wrapT === THREE.RepeatWrapping;
|
||||
|
||||
var repeat = 'no-repeat';
|
||||
|
||||
if ( repeatX === true && repeatY === true ) {
|
||||
|
||||
repeat = 'repeat';
|
||||
|
||||
} else if ( repeatX === true ) {
|
||||
|
||||
repeat = 'repeat-x';
|
||||
|
||||
} else if ( repeatY === true ) {
|
||||
|
||||
repeat = 'repeat-y';
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
canvas: _context.createPattern( canvas, repeat ),
|
||||
version: texture.version
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
|
||||
|
||||
if ( texture instanceof THREE.DataTexture ) return;
|
||||
|
||||
if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
|
||||
|
||||
if ( texture.image !== undefined && texture.image.width > 0 ) {
|
||||
|
||||
textureToPattern( texture );
|
||||
|
||||
}
|
||||
|
||||
texture.addEventListener( 'update', onTextureUpdate );
|
||||
|
||||
}
|
||||
|
||||
var pattern = _patterns[ texture.id ];
|
||||
|
||||
if ( pattern !== undefined ) {
|
||||
if ( pattern === undefined || pattern.version !== texture.version ) {
|
||||
|
||||
setFillStyle( pattern );
|
||||
pattern = textureToPattern( texture );
|
||||
_patterns[ texture.id ] = pattern;
|
||||
|
||||
}
|
||||
|
||||
if ( pattern.canvas !== undefined ) {
|
||||
|
||||
setFillStyle( pattern.canvas );
|
||||
|
||||
} else {
|
||||
|
||||
setFillStyle( 'rgba(0,0,0,1)' );
|
||||
setFillStyle( 'rgba( 0, 0, 0, 1)' );
|
||||
_context.fill();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ THREE.RenderableObject = function () {
|
|||
|
||||
this.object = null;
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -33,6 +34,7 @@ THREE.RenderableFace = function () {
|
|||
this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
|
||||
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -68,6 +70,7 @@ THREE.RenderableLine = function () {
|
|||
this.material = null;
|
||||
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -87,6 +90,7 @@ THREE.RenderableSprite = function () {
|
|||
this.scale = new THREE.Vector2();
|
||||
|
||||
this.material = null;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -102,10 +106,6 @@ THREE.Projector = function () {
|
|||
|
||||
_renderData = { objects: [], lights: [], elements: [] },
|
||||
|
||||
_vA = new THREE.Vector3(),
|
||||
_vB = new THREE.Vector3(),
|
||||
_vC = new THREE.Vector3(),
|
||||
|
||||
_vector3 = new THREE.Vector3(),
|
||||
_vector4 = new THREE.Vector4(),
|
||||
|
||||
|
@ -145,7 +145,7 @@ THREE.Projector = function () {
|
|||
|
||||
this.pickingRay = function ( vector, camera ) {
|
||||
|
||||
console.error( 'THREE.Projector: .pickingRay() has been removed.' );
|
||||
console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
|
||||
|
||||
};
|
||||
|
||||
|
@ -247,6 +247,7 @@ THREE.Projector = function () {
|
|||
_line.v1.copy( v1 );
|
||||
_line.v2.copy( v2 );
|
||||
_line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
|
||||
_line.renderOrder = object.renderOrder;
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
|
@ -271,19 +272,21 @@ THREE.Projector = function () {
|
|||
_face.v2.copy( v2 );
|
||||
_face.v3.copy( v3 );
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
_face.renderOrder = object.renderOrder;
|
||||
|
||||
// use first vertex normal as face normal
|
||||
|
||||
_face.normalModel.fromArray( normals, a * 3 );
|
||||
_face.normalModel.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
for ( var i = 0; i < 3; i ++ ) {
|
||||
|
||||
var offset = arguments[ i ] * 3;
|
||||
var normal = _face.vertexNormalsModel[ i ];
|
||||
|
||||
normal.set( normals[ offset ], normals[ offset + 1 ], normals[ offset + 2 ] );
|
||||
normal.fromArray( normals, arguments[ i ] * 3 );
|
||||
normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
var offset2 = arguments[ i ] * 2;
|
||||
|
||||
var uv = _face.uvs[ i ];
|
||||
uv.set( uvs[ offset2 ], uvs[ offset2 + 1 ] );
|
||||
uv.fromArray( uvs, arguments[ i ] * 2 );
|
||||
|
||||
}
|
||||
|
||||
|
@ -322,7 +325,7 @@ THREE.Projector = function () {
|
|||
_renderData.elements.length = 0;
|
||||
|
||||
if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
|
||||
if ( camera.parent === undefined ) camera.updateMatrixWorld();
|
||||
if ( camera.parent === null ) camera.updateMatrixWorld();
|
||||
|
||||
_viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
|
||||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
|
||||
|
@ -344,7 +347,9 @@ THREE.Projector = function () {
|
|||
|
||||
} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
|
||||
|
||||
if ( object.material.visible === false ) return;
|
||||
var material = object.material;
|
||||
|
||||
if ( material.visible === false ) return;
|
||||
|
||||
if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
|
||||
|
||||
|
@ -352,17 +357,10 @@ THREE.Projector = function () {
|
|||
_object.id = object.id;
|
||||
_object.object = object;
|
||||
|
||||
if ( object.renderDepth !== null ) {
|
||||
|
||||
_object.z = object.renderDepth;
|
||||
|
||||
} else {
|
||||
|
||||
_vector3.setFromMatrixPosition( object.matrixWorld );
|
||||
_vector3.applyProjection( _viewProjectionMatrix );
|
||||
_object.z = _vector3.z;
|
||||
|
||||
}
|
||||
_object.renderOrder = object.renderOrder;
|
||||
|
||||
_renderData.objects.push( _object );
|
||||
|
||||
|
@ -396,7 +394,7 @@ THREE.Projector = function () {
|
|||
if ( geometry instanceof THREE.BufferGeometry ) {
|
||||
|
||||
var attributes = geometry.attributes;
|
||||
var offsets = geometry.offsets;
|
||||
var groups = geometry.groups;
|
||||
|
||||
if ( attributes.position === undefined ) continue;
|
||||
|
||||
|
@ -432,20 +430,19 @@ THREE.Projector = function () {
|
|||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
if ( geometry.index !== null ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
var indices = geometry.index.array;
|
||||
|
||||
if ( offsets.length > 0 ) {
|
||||
if ( groups.length > 0 ) {
|
||||
|
||||
for ( var o = 0; o < offsets.length; o ++ ) {
|
||||
for ( var o = 0; o < groups.length; o ++ ) {
|
||||
|
||||
var offset = offsets[ o ];
|
||||
var index = offset.index;
|
||||
var group = groups[ o ];
|
||||
|
||||
for ( var i = offset.start, l = offset.start + offset.count; i < l; i += 3 ) {
|
||||
for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushTriangle( indices[ i ] + index, indices[ i + 1 ] + index, indices[ i + 2 ] + index );
|
||||
renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
|
@ -479,13 +476,40 @@ THREE.Projector = function () {
|
|||
|
||||
_normalMatrix.getNormalMatrix( _modelMatrix );
|
||||
|
||||
var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
|
||||
var material = object.material;
|
||||
|
||||
var isFaceMaterial = material instanceof THREE.MeshFaceMaterial;
|
||||
var objectMaterials = isFaceMaterial === true ? object.material : null;
|
||||
|
||||
for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
var vertex = vertices[ v ];
|
||||
renderList.pushVertex( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
_vector3.copy( vertex );
|
||||
|
||||
if ( material.morphTargets === true ) {
|
||||
|
||||
var morphTargets = geometry.morphTargets;
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
|
||||
|
||||
var influence = morphInfluences[ t ];
|
||||
|
||||
if ( influence === 0 ) continue;
|
||||
|
||||
var target = morphTargets[ t ];
|
||||
var targetVertex = target.vertices[ v ];
|
||||
|
||||
_vector3.x += ( targetVertex.x - vertex.x ) * influence;
|
||||
_vector3.y += ( targetVertex.y - vertex.y ) * influence;
|
||||
_vector3.z += ( targetVertex.z - vertex.z ) * influence;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );
|
||||
|
||||
}
|
||||
|
||||
|
@ -493,7 +517,7 @@ THREE.Projector = function () {
|
|||
|
||||
var face = faces[ f ];
|
||||
|
||||
var material = isFaceMaterial === true
|
||||
material = isFaceMaterial === true
|
||||
? objectMaterials.materials[ face.materialIndex ]
|
||||
: object.material;
|
||||
|
||||
|
@ -505,58 +529,15 @@ THREE.Projector = function () {
|
|||
var v2 = _vertexPool[ face.b ];
|
||||
var v3 = _vertexPool[ face.c ];
|
||||
|
||||
if ( material.morphTargets === true ) {
|
||||
|
||||
var morphTargets = geometry.morphTargets;
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
var v1p = v1.position;
|
||||
var v2p = v2.position;
|
||||
var v3p = v3.position;
|
||||
|
||||
_vA.set( 0, 0, 0 );
|
||||
_vB.set( 0, 0, 0 );
|
||||
_vC.set( 0, 0, 0 );
|
||||
|
||||
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
|
||||
|
||||
var influence = morphInfluences[ t ];
|
||||
|
||||
if ( influence === 0 ) continue;
|
||||
|
||||
var targets = morphTargets[ t ].vertices;
|
||||
|
||||
_vA.x += ( targets[ face.a ].x - v1p.x ) * influence;
|
||||
_vA.y += ( targets[ face.a ].y - v1p.y ) * influence;
|
||||
_vA.z += ( targets[ face.a ].z - v1p.z ) * influence;
|
||||
|
||||
_vB.x += ( targets[ face.b ].x - v2p.x ) * influence;
|
||||
_vB.y += ( targets[ face.b ].y - v2p.y ) * influence;
|
||||
_vB.z += ( targets[ face.b ].z - v2p.z ) * influence;
|
||||
|
||||
_vC.x += ( targets[ face.c ].x - v3p.x ) * influence;
|
||||
_vC.y += ( targets[ face.c ].y - v3p.y ) * influence;
|
||||
_vC.z += ( targets[ face.c ].z - v3p.z ) * influence;
|
||||
|
||||
}
|
||||
|
||||
v1.position.add( _vA );
|
||||
v2.position.add( _vB );
|
||||
v3.position.add( _vC );
|
||||
|
||||
renderList.projectVertex( v1 );
|
||||
renderList.projectVertex( v2 );
|
||||
renderList.projectVertex( v3 );
|
||||
|
||||
}
|
||||
|
||||
if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
|
||||
|
||||
var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
|
||||
|
||||
if ( side !== THREE.DoubleSide ) {
|
||||
|
||||
if ( side === THREE.FrontSide && visible === false ) continue;
|
||||
if ( side === THREE.BackSide && visible === true ) continue;
|
||||
|
||||
}
|
||||
|
||||
_face = getNextFaceInPool();
|
||||
|
@ -611,6 +592,7 @@ THREE.Projector = function () {
|
|||
_face.material = material;
|
||||
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
_face.renderOrder = object.renderOrder;
|
||||
|
||||
_renderData.elements.push( _face );
|
||||
|
||||
|
@ -634,9 +616,9 @@ THREE.Projector = function () {
|
|||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
if ( geometry.index !== null ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
var indices = geometry.index.array;
|
||||
|
||||
for ( var i = 0, l = indices.length; i < l; i += 2 ) {
|
||||
|
||||
|
@ -646,7 +628,7 @@ THREE.Projector = function () {
|
|||
|
||||
} else {
|
||||
|
||||
var step = object.mode === THREE.LinePieces ? 2 : 1;
|
||||
var step = object instanceof THREE.LineSegments ? 2 : 1;
|
||||
|
||||
for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
|
||||
|
||||
|
@ -669,8 +651,7 @@ THREE.Projector = function () {
|
|||
v1 = getNextVertexInPool();
|
||||
v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
|
||||
|
||||
// Handle LineStrip and LinePieces
|
||||
var step = object.mode === THREE.LinePieces ? 2 : 1;
|
||||
var step = object instanceof THREE.LineSegments ? 2 : 1;
|
||||
|
||||
for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
|
@ -697,6 +678,7 @@ THREE.Projector = function () {
|
|||
_line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
|
||||
|
||||
_line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
|
||||
_line.renderOrder = object.renderOrder;
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
|
@ -731,6 +713,7 @@ THREE.Projector = function () {
|
|||
_sprite.x = _vector4.x * invW;
|
||||
_sprite.y = _vector4.y * invW;
|
||||
_sprite.z = _vector4.z;
|
||||
_sprite.renderOrder = object.renderOrder;
|
||||
_sprite.object = object;
|
||||
|
||||
_sprite.rotation = object.rotation;
|
||||
|
@ -816,7 +799,7 @@ THREE.Projector = function () {
|
|||
var line = new THREE.RenderableLine();
|
||||
_linePool.push( line );
|
||||
_linePoolLength ++;
|
||||
_lineCount ++
|
||||
_lineCount ++;
|
||||
return line;
|
||||
|
||||
}
|
||||
|
@ -832,7 +815,7 @@ THREE.Projector = function () {
|
|||
var sprite = new THREE.RenderableSprite();
|
||||
_spritePool.push( sprite );
|
||||
_spritePoolLength ++;
|
||||
_spriteCount ++
|
||||
_spriteCount ++;
|
||||
return sprite;
|
||||
|
||||
}
|
||||
|
@ -845,7 +828,11 @@ THREE.Projector = function () {
|
|||
|
||||
function painterSort( a, b ) {
|
||||
|
||||
if ( a.z !== b.z ) {
|
||||
if ( a.renderOrder !== b.renderOrder ) {
|
||||
|
||||
return a.renderOrder - b.renderOrder;
|
||||
|
||||
} else if ( a.z !== b.z ) {
|
||||
|
||||
return b.z - a.z;
|
||||
|
||||
|
|
1579
js/libraries/three/three.min.js
vendored
1579
js/libraries/three/three.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
var usbDevices = {
|
||||
STM32DFU: {'vendorId': 1155, 'productId': 57105}
|
||||
};
|
||||
|
||||
var PortHandler = new function () {
|
||||
this.initial_ports = false;
|
||||
this.port_detected_callbacks = [];
|
||||
this.port_removed_callbacks = [];
|
||||
this.dfu_available = false;
|
||||
};
|
||||
|
||||
PortHandler.initialize = function () {
|
||||
|
@ -131,30 +136,32 @@ PortHandler.check = function () {
|
|||
self.initial_ports = current_ports;
|
||||
}
|
||||
|
||||
if (GUI.optional_usb_permissions) {
|
||||
check_usb_devices();
|
||||
}
|
||||
self.check_usb_devices();
|
||||
|
||||
GUI.updateManualPortVisibility();
|
||||
setTimeout(function () {
|
||||
self.check();
|
||||
}, 250);
|
||||
});
|
||||
};
|
||||
|
||||
function check_usb_devices() {
|
||||
PortHandler.check_usb_devices = function (callback) {
|
||||
chrome.usb.getDevices(usbDevices.STM32DFU, function (result) {
|
||||
if (result.length) {
|
||||
if (!$("div#port-picker #port [value='DFU']").length) {
|
||||
$('div#port-picker #port').append('<option value="DFU">DFU</option>');
|
||||
$('div#port-picker #port').append($('<option/>', {value: "DFU", text: "DFU", data: {isDFU: true}}));
|
||||
$('div#port-picker #port').val('DFU');
|
||||
}
|
||||
self.dfu_available = true;
|
||||
} else {
|
||||
if ($("div#port-picker #port [value='DFU']").length) {
|
||||
$("div#port-picker #port [value='DFU']").remove();
|
||||
}
|
||||
self.dfu_available = false;
|
||||
}
|
||||
|
||||
if(callback) callback(self.dfu_available);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
PortHandler.update_port_select = function (ports) {
|
||||
|
|
|
@ -100,6 +100,14 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
|
|||
serial.send(bufferOut, function () {
|
||||
serial.disconnect(function (result) {
|
||||
if (result) {
|
||||
// delay to allow board to boot in bootloader mode
|
||||
// required to detect if a DFU device appears
|
||||
setTimeout(function() {
|
||||
// refresh device list
|
||||
PortHandler.check_usb_devices(function(dfu_available) {
|
||||
if(dfu_available) {
|
||||
STM32DFU.connect(usbDevices.STM32DFU, hex, options);
|
||||
} else {
|
||||
serial.connect(port, {bitrate: self.baud, parityBit: 'even', stopBits: 'one'}, function (openInfo) {
|
||||
if (openInfo) {
|
||||
self.initialize();
|
||||
|
@ -108,6 +116,9 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
|
|||
GUI.log('<span style="color: red">Failed</span> to open serial port');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
} else {
|
||||
GUI.connect_lock = false;
|
||||
}
|
||||
|
|
|
@ -61,13 +61,26 @@ var STM32DFU_protocol = function () {
|
|||
dfuUPLOAD_IDLE: 9, // The device is processing an upload operation. Expecting DFU_UPLOAD requests.
|
||||
dfuERROR: 10 // An error has occurred. Awaiting the DFU_CLRSTATUS request.
|
||||
};
|
||||
|
||||
// Assume 2 kB page size (STM32F303)
|
||||
// Cannot read chip ID using DFU protocol and Chrome doesn't provide the interface
|
||||
// description string with flash page size information (at least on Linux anyway)
|
||||
this.page_size = 2048;
|
||||
};
|
||||
|
||||
STM32DFU_protocol.prototype.connect = function (device, hex, callback) {
|
||||
STM32DFU_protocol.prototype.connect = function (device, hex, options, callback) {
|
||||
var self = this;
|
||||
self.hex = hex;
|
||||
self.callback = callback;
|
||||
|
||||
self.options = {
|
||||
erase_chip: false
|
||||
};
|
||||
|
||||
if (options.erase_chip) {
|
||||
self.options.erase_chip = true;
|
||||
}
|
||||
|
||||
// reset and set some variables before we start
|
||||
self.upload_time_start = new Date().getTime();
|
||||
self.verify_hex = [];
|
||||
|
@ -89,12 +102,35 @@ STM32DFU_protocol.prototype.connect = function (device, hex, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
STM32DFU_protocol.prototype.checkChromeError = function() {
|
||||
if (chrome.runtime.lastError) {
|
||||
if(chrome.runtime.lastError.message)
|
||||
console.log(chrome.runtime.lastError.message);
|
||||
else
|
||||
console.log(chrome.runtime.lastError);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
STM32DFU_protocol.prototype.openDevice = function (device) {
|
||||
var self = this;
|
||||
|
||||
chrome.usb.openDevice(device, function (handle) {
|
||||
if(self.checkChromeError()) {
|
||||
console.log('Failed to open USB device!');
|
||||
GUI.log(chrome.i18n.getMessage('usbDeviceOpenFail'));
|
||||
if(GUI.operating_system === 'Linux') {
|
||||
GUI.log(chrome.i18n.getMessage('usbDeviceUdevNotice'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.handle = handle;
|
||||
|
||||
GUI.log(chrome.i18n.getMessage('usbDeviceOpened', handle.handle.toString()));
|
||||
console.log('Device opened with Handle ID: ' + handle.handle);
|
||||
self.claimInterface(0);
|
||||
});
|
||||
|
@ -104,6 +140,12 @@ STM32DFU_protocol.prototype.closeDevice = function () {
|
|||
var self = this;
|
||||
|
||||
chrome.usb.closeDevice(this.handle, function closed() {
|
||||
if(self.checkChromeError()) {
|
||||
console.log('Failed to close USB device!');
|
||||
GUI.log(chrome.i18n.getMessage('usbDeviceCloseFail'));
|
||||
}
|
||||
|
||||
GUI.log(chrome.i18n.getMessage('usbDeviceClosed'));
|
||||
console.log('Device closed with Handle ID: ' + self.handle.handle);
|
||||
|
||||
self.handle = null;
|
||||
|
@ -139,6 +181,8 @@ STM32DFU_protocol.prototype.resetDevice = function (callback) {
|
|||
};
|
||||
|
||||
STM32DFU_protocol.prototype.controlTransfer = function (direction, request, value, _interface, length, data, callback) {
|
||||
var self = this;
|
||||
|
||||
if (direction == 'in') {
|
||||
// data is ignored
|
||||
chrome.usb.controlTransfer(this.handle, {
|
||||
|
@ -150,6 +194,9 @@ STM32DFU_protocol.prototype.controlTransfer = function (direction, request, valu
|
|||
'index': _interface,
|
||||
'length': length
|
||||
}, function (result) {
|
||||
if(self.checkChromeError()) {
|
||||
console.log('USB transfer failed!');
|
||||
}
|
||||
if (result.resultCode) console.log(result.resultCode);
|
||||
|
||||
var buf = new Uint8Array(result.data);
|
||||
|
@ -174,6 +221,9 @@ STM32DFU_protocol.prototype.controlTransfer = function (direction, request, valu
|
|||
'index': _interface,
|
||||
'data': arrayBuf
|
||||
}, function (result) {
|
||||
if(self.checkChromeError()) {
|
||||
console.log('USB transfer failed!');
|
||||
}
|
||||
if (result.resultCode) console.log(result.resultCode);
|
||||
|
||||
callback(result);
|
||||
|
@ -217,7 +267,7 @@ STM32DFU_protocol.prototype.loadAddress = function (address, callback) {
|
|||
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
||||
callback(data);
|
||||
} else {
|
||||
console.log('Failed to execure address load');
|
||||
console.log('Failed to execute address load');
|
||||
self.upload_procedure(99);
|
||||
}
|
||||
});
|
||||
|
@ -256,6 +306,8 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
|||
});
|
||||
break;
|
||||
case 2:
|
||||
// erase
|
||||
if (self.options.erase_chip) {
|
||||
// full chip erase
|
||||
console.log('Executing global chip erase');
|
||||
$('span.progressLabel').text('Erasing ...');
|
||||
|
@ -281,7 +333,59 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
|||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// local erase
|
||||
|
||||
var max_address = self.hex.data[self.hex.data.length - 1].address + self.hex.data[self.hex.data.length - 1].bytes - 0x8000000,
|
||||
erase_pages_n = Math.ceil(max_address / self.page_size),
|
||||
page = 0;
|
||||
|
||||
$('span.progressLabel').text('Erasing ...');
|
||||
console.log('Executing local chip erase');
|
||||
console.log('Erasing. page: 0x00 - 0x' + erase_pages_n.toString(16));
|
||||
|
||||
var erase_page = function() {
|
||||
var page_addr = page * self.page_size + 0x8000000;
|
||||
var cmd = [0x41, page_addr & 0xff, (page_addr >> 8) & 0xff, (page_addr >> 16) & 0xff, (page_addr >> 24) & 0xff];
|
||||
|
||||
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, cmd, function () {
|
||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||
if (data[4] == self.state.dfuDNBUSY) { // completely normal
|
||||
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
|
||||
|
||||
setTimeout(function () {
|
||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
||||
// update progress bar
|
||||
self.progress_bar_e.val((page + 1) / erase_pages_n * 100);
|
||||
page++;
|
||||
|
||||
if(page == erase_pages_n) {
|
||||
console.log("Erase: complete");
|
||||
GUI.log(chrome.i18n.getMessage('dfu_erased_kilobytes', (erase_pages_n * self.page_size / 1024).toString()));
|
||||
self.upload_procedure(4);
|
||||
}
|
||||
else
|
||||
erase_page();
|
||||
} else {
|
||||
console.log('Failed to erase page 0x' + self.current_page.toString(16));
|
||||
self.upload_procedure(99);
|
||||
}
|
||||
});
|
||||
}, delay);
|
||||
} else {
|
||||
console.log('Failed to initiate page erase, page 0x' + self.current_page.toString(16));
|
||||
self.upload_procedure(99);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// start
|
||||
erase_page();
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// upload
|
||||
// we dont need to clear the state as we are already using DFU_DNLOAD
|
||||
|
@ -296,9 +400,6 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
|||
var bytes_flashed_total = 0; // used for progress bar
|
||||
var wBlockNum = 2; // required by DFU
|
||||
|
||||
// start
|
||||
self.loadAddress(address, write);
|
||||
|
||||
var write = function () {
|
||||
if (bytes_flashed < self.hex.data[flashing_block].bytes) {
|
||||
var bytes_to_write = ((bytes_flashed + 2048) <= self.hex.data[flashing_block].bytes) ? 2048 : (self.hex.data[flashing_block].bytes - bytes_flashed);
|
||||
|
@ -353,6 +454,10 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start
|
||||
self.loadAddress(address, write);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
// verify
|
||||
|
@ -463,13 +568,13 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
|||
});
|
||||
}
|
||||
|
||||
// start
|
||||
clear_before_leave();
|
||||
break;
|
||||
case 99:
|
||||
// cleanup
|
||||
self.releaseInterface(0);
|
||||
|
||||
GUI.connect_lock = false;
|
||||
|
||||
var timeSpent = new Date().getTime() - self.upload_time_start;
|
||||
|
||||
console.log('Script finished after: ' + (timeSpent / 1000) + ' seconds');
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
$(document).ready(function () {
|
||||
|
||||
GUI.updateManualPortVisibility = function(){
|
||||
if ($('div#port-picker #port option:selected').data().isManual) {
|
||||
var selected_port = $('div#port-picker #port option:selected');
|
||||
if (selected_port.data().isManual) {
|
||||
$('#port-override-option').show();
|
||||
}
|
||||
else {
|
||||
$('#port-override-option').hide();
|
||||
}
|
||||
if (selected_port.data().isDFU) {
|
||||
$('select#baud').hide();
|
||||
}
|
||||
else {
|
||||
$('select#baud').show();
|
||||
}
|
||||
};
|
||||
|
||||
GUI.updateManualPortVisibility();
|
||||
|
@ -33,8 +40,10 @@ $(document).ready(function () {
|
|||
var selected_port = $('div#port-picker #port option:selected').data().isManual ?
|
||||
$('#port-override').val() :
|
||||
String($('div#port-picker #port').val());
|
||||
|
||||
if (selected_port != '0' && selected_port != 'DFU') {
|
||||
if (selected_port === 'DFU') {
|
||||
GUI.log(chrome.i18n.getMessage('dfu_connect_message'));
|
||||
}
|
||||
else if (selected_port != '0') {
|
||||
if (!clicks) {
|
||||
console.log('Connecting to: ' + selected_port);
|
||||
GUI.connecting_to = selected_port;
|
||||
|
|
36
js/usb.js
36
js/usb.js
|
@ -1,36 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var usbDevices = {
|
||||
STM32DFU: {'vendorId': 1155, 'productId': 57105}
|
||||
};
|
||||
var usbPermissions = {permissions: [{'usbDevices': [usbDevices.STM32DFU]}]};
|
||||
|
||||
function check_usb_permissions(callback) {
|
||||
chrome.permissions.contains(usbPermissions, function (result) {
|
||||
if (result) {
|
||||
GUI.optional_usb_permissions = true;
|
||||
} else {
|
||||
console.log('Optional USB permissions: missing');
|
||||
GUI.log(chrome.i18n.getMessage('please_grant_usb_permissions'));
|
||||
|
||||
// display optional usb permissions request box
|
||||
$('div.optional_permissions').show();
|
||||
|
||||
// UI hooks
|
||||
document.getElementById("requestOptionalPermissions").addEventListener('click', function () {
|
||||
chrome.permissions.request(usbPermissions, function (result) {
|
||||
if (result) {
|
||||
GUI.log(chrome.i18n.getMessage('usb_permissions_granted'));
|
||||
$('div.optional_permissions').hide();
|
||||
|
||||
GUI.optional_usb_permissions = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"minimum_chrome_version": "38",
|
||||
"version": "0.66.0",
|
||||
"version": "0.67.0",
|
||||
"author": "Hydra",
|
||||
"name": "cleanflight - Configurator Redesign",
|
||||
"short_name": "cleanflightRed",
|
||||
|
@ -31,10 +31,8 @@
|
|||
"fileSystem",
|
||||
"fileSystem.write",
|
||||
"fileSystem.retainEntries",
|
||||
"notifications"
|
||||
],
|
||||
|
||||
"optional_permissions": [
|
||||
"notifications",
|
||||
"alwaysOnTopWindows",
|
||||
{"usbDevices": [
|
||||
{"vendorId": 1155, "productId": 57105}
|
||||
]}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"DbgName": "Material.003",
|
||||
"colorEmissive": [0.0,0.0,0.0],
|
||||
"mapDiffuse": "fallback.png",
|
||||
"opacity": 0.0,
|
||||
"opacity": 1.0,
|
||||
"specularCoef": 50,
|
||||
"shading": "phong",
|
||||
"mapDiffuseWrap": ["RepeatWrapping","RepeatWrapping"],
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -315,10 +315,10 @@ def render_vtail
|
|||
m.draw_body 100,180,140,160
|
||||
m.draw_body 100,180,60,160
|
||||
m.end_body
|
||||
m.draw_circle 140,160,"1",Model::CW,Model::SE
|
||||
m.draw_circle 160,40,"2",Model::CCW,Model::NE
|
||||
m.draw_circle 60,160,"3",Model::CCW,Model::SW
|
||||
m.draw_circle 40,40,"4",Model::CW,Model::NW
|
||||
m.draw_circle 140,160,"1",Model::CCW,Model::SE
|
||||
m.draw_circle 160,40,"2",Model::CW,Model::NE
|
||||
m.draw_circle 60,160,"3",Model::CW,Model::SW
|
||||
m.draw_circle 40,40,"4",Model::CCW,Model::NW
|
||||
m.draw_dirn
|
||||
m.close
|
||||
end
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
background-color: #ececec;
|
||||
}
|
||||
|
||||
|
||||
.tab-configuration .number span {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
|
|
@ -320,10 +320,15 @@ elems.forEach(function(html) {
|
|||
if (!$(this).hasClass('locked')) {
|
||||
if (!GUI.connect_lock) { // button disabled while flashing is in progress
|
||||
if (parsed_hex != false) {
|
||||
var options = {};
|
||||
|
||||
if ($('input.erase_chip').is(':checked')) {
|
||||
options.erase_chip = true;
|
||||
}
|
||||
|
||||
if (String($('div#port-picker #port').val()) != 'DFU') {
|
||||
if (String($('div#port-picker #port').val()) != '0') {
|
||||
var options = {},
|
||||
port = String($('div#port-picker #port').val()),
|
||||
var port = String($('div#port-picker #port').val()),
|
||||
baud;
|
||||
|
||||
switch (GUI.operating_system) {
|
||||
|
@ -345,10 +350,6 @@ elems.forEach(function(html) {
|
|||
options.reboot_baud = parseInt($('div#port-picker #baud').val());
|
||||
}
|
||||
|
||||
if ($('input.erase_chip').is(':checked')) {
|
||||
options.erase_chip = true;
|
||||
}
|
||||
|
||||
if ($('input.flash_manual_baud').is(':checked')) {
|
||||
baud = parseInt($('#flash_manual_baud_rate').val());
|
||||
}
|
||||
|
@ -360,7 +361,7 @@ elems.forEach(function(html) {
|
|||
GUI.log('<span style="color: red">Please select valid serial port</span>');
|
||||
}
|
||||
} else {
|
||||
STM32DFU.connect(usbDevices.STM32DFU, parsed_hex);
|
||||
STM32DFU.connect(usbDevices.STM32DFU, parsed_hex, options);
|
||||
}
|
||||
} else {
|
||||
$('span.progressLabel').text(chrome.i18n.getMessage('firmwareFlasherFirmwareNotLoaded'));
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
<div class="tab-landing">
|
||||
<div class="section optional_permissions">
|
||||
<div class="title" i18n="default_optional_permissions_head"></div>
|
||||
<p i18n="default_optional_permissions_text"></p>
|
||||
<a id="requestOptionalPermissions" href="#" i18n="default_request_optional_permissions"></a>
|
||||
<div class="clear-both"></div>
|
||||
</div>
|
||||
|
||||
<div class="row welcome_and_sponsors">
|
||||
<div class="left">
|
||||
<div class="section welcome">
|
||||
|
@ -61,6 +54,9 @@
|
|||
<p>
|
||||
• <a href="http://www.overskyrc.com" title="www.overskyrc.com" target="_blank">OverSkyRC</a><br />
|
||||
</p>
|
||||
<p>
|
||||
• <a href="http://multirotormania.com" title="multirotormania.com" target="_blank">Multi Rotor Mania</a><br />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -89,7 +89,6 @@ table.ports tr:first-child td:last-child { border-top-right-radius: 0px; }
|
|||
background-color: #dedcdc;
|
||||
}
|
||||
|
||||
|
||||
.tab-ports .require-support {
|
||||
display:none;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ margin-bottom:10px;
|
|||
.attitude_info dd {
|
||||
width:50%;
|
||||
float:left;
|
||||
}
|
||||
|
||||
|
||||
#interactive_block a.reset {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue