mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 14:33:22 +00:00
UI improvements, save build feature partial implementation
This commit is contained in:
@@ -23,11 +23,13 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="bg"></div>
|
||||
<shipyard-menu></shipyard-menu>
|
||||
<shipyard-header></shipyard-header>
|
||||
<div id="main" ui-view ng-click="bgClicked($event)"></div>
|
||||
|
||||
<footer>
|
||||
<div class="right">Version <%= version %> - <%= date %></div>
|
||||
<div class="right">
|
||||
<a href="https://github.com/cmmcleod/ed-shipyard" target="_blank" title="Shipyard Github Project">Version <%= version %> - <%= date %></a>
|
||||
</div>
|
||||
<div class="left">
|
||||
Coriolis Shipyard was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes.<br>
|
||||
It is not endorsed by nor reflects the views or opinions of Frontier Developments and no employee of Frontier Developments was involved in the making of it.
|
||||
|
||||
@@ -1,44 +1,9 @@
|
||||
angular.module('app', ['ui.router', 'shipyard', 'ngLodash', 'app.templates'])
|
||||
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider) {
|
||||
$locationProvider.html5Mode(true);
|
||||
$stateProvider
|
||||
.state('outfit', {
|
||||
url: '/outfit/:shipId/:code?bn',
|
||||
params: {
|
||||
// TODO: fix below, default, squash false not working
|
||||
//shipId: { value: 'sidewinder', squash: false }, // Allow 'shipId' parameter to default to
|
||||
code: { value: null, squash: true } // Allow 'code' parameter to be empty/optional
|
||||
},
|
||||
templateUrl: 'views/page-outfit.html',
|
||||
controller: 'OutfitController',
|
||||
resolve: {
|
||||
shipId: ['$stateParams',function ($p) { // Ensure ship exists before loading controller
|
||||
if (!DB.ships[$p.shipId]) {
|
||||
throw { type: 404, message: 'Ship "' + $p.shipId + '" does not exist'};
|
||||
}
|
||||
}]
|
||||
}
|
||||
})
|
||||
.state('shipyard', { url: '/', templateUrl: 'views/page-shipyard.html', controller: 'ShipyardController' })
|
||||
.state('error', { params: {type:null, message:null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController' })
|
||||
.state('notfound', { url: '*path', templateUrl: 'views/page-error.html', controller: 'ErrorController' });
|
||||
|
||||
}])
|
||||
.config(['$provide',function($provide) {
|
||||
// Global Error Handler, redirects uncaught errors to the error page
|
||||
$provide.decorator('$exceptionHandler', ['$delegate', '$injector', function ($delegate, $injector) {
|
||||
return function(exception, cause) {
|
||||
$injector.get('$state').go('error', { details: exception }, {location:false, reload:true}); // Go to error state, reload the controller, keep the current URL
|
||||
$delegate(exception, cause);
|
||||
};
|
||||
}]);
|
||||
}])
|
||||
.run(['$rootScope','$document','$state','commonArray','shipPurpose','shipSize','hardPointClass','internalGroupMap','hardpointsGroupMap', function ($rootScope, $doc, $state, CArr, shipPurpose, sz, hpc, igMap, hgMap) {
|
||||
|
||||
// Redirect any state transition errors to the error controller/state
|
||||
$rootScope.$on('$stateChangeError', function(e, toState, toParams, fromState, fromParams, error){
|
||||
e.preventDefault();
|
||||
$state.go('error',error, {location:false, reload:true}); // Go to error state, reload the controller, keep the current URL
|
||||
$state.go('error', error, {location:false, reload:true}); // Go to error state, reload the controller, keep the current URL
|
||||
});
|
||||
|
||||
// Global Reference variables
|
||||
@@ -47,7 +12,7 @@ angular.module('app', ['ui.router', 'shipyard', 'ngLodash', 'app.templates'])
|
||||
$rootScope.SZ = sz;
|
||||
$rootScope.HPC = hpc;
|
||||
$rootScope.igMap = igMap;
|
||||
window.hgmap = $rootScope.hgMap = hgMap;
|
||||
$rootScope.hgMap = hgMap;
|
||||
$rootScope.ships = DB.ships;
|
||||
$rootScope.title = 'Coriolis';
|
||||
|
||||
@@ -61,11 +26,16 @@ angular.module('app', ['ui.router', 'shipyard', 'ngLodash', 'app.templates'])
|
||||
|
||||
// Global Event Listeners
|
||||
$doc.bind('keyup', function (e) {
|
||||
$rootScope.$broadcast('keyup', e);
|
||||
if(e.keyCode == 27) { // Escape Key
|
||||
$rootScope.$broadcast('close', e);
|
||||
$rootScope.$apply();
|
||||
} else {
|
||||
$rootScope.$broadcast('keyup', e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.bgClicked = function (e) {
|
||||
$rootScope.$broadcast('bgClicked', e);
|
||||
$rootScope.$broadcast('close', e);
|
||||
}
|
||||
|
||||
}]);
|
||||
|
||||
56
app/js/config.js
Normal file
56
app/js/config.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Sets up the routes and handlers before the Angular app is kicked off.
|
||||
*/
|
||||
angular.module('app').config(['$provide','$stateProvider', '$urlRouterProvider', '$locationProvider', function ($provide, $stateProvider, $urlRouterProvider, $locationProvider) {
|
||||
// Use HTML5 push and replace state if possible
|
||||
$locationProvider.html5Mode(true);
|
||||
/**
|
||||
* Set up all states and their routes.
|
||||
*/
|
||||
$stateProvider
|
||||
.state('outfit', {
|
||||
url: '/outfit/:shipId/:code?bn',
|
||||
params: {
|
||||
// TODO: Squash:false not working due to UI-router issue
|
||||
shipId: { value: 'sidewinder', squash: false}, // Allow 'shipId' parameter to default to
|
||||
code: { value: undefined, squash: true } // Allow 'code' parameter to be empty/optional
|
||||
},
|
||||
templateUrl: 'views/page-outfit.html',
|
||||
controller: 'OutfitController',
|
||||
resolve: {
|
||||
shipId: ['$stateParams',function ($p) { // Ensure ship exists before loading controller
|
||||
if (!DB.ships[$p.shipId]) {
|
||||
throw { type: 'no-ship', message: $p.shipId };
|
||||
}
|
||||
}]
|
||||
}
|
||||
})
|
||||
.state('shipyard', { url: '/', templateUrl: 'views/page-shipyard.html', controller: 'ShipyardController' })
|
||||
.state('error', { params: {type:null, message:null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController' })
|
||||
|
||||
// Redirects
|
||||
$urlRouterProvider.when('/outfit','/outfit/sidewinder/');
|
||||
|
||||
/**
|
||||
* 404 Handler - Keep current URL/ do not redirect, change to error state.
|
||||
*/
|
||||
$urlRouterProvider.otherwise(function ($injector, $location) {
|
||||
// Go to error state, reload the controller, keep the current URL
|
||||
$injector.get('$state').go('error', { type: 404, message: null, details: null }, {location:false, reload:true});
|
||||
return $location.path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Global Error Handler. Decorates the existing error handler such that it
|
||||
* redirects uncaught errors to the error page.
|
||||
*
|
||||
*/
|
||||
$provide.decorator('$exceptionHandler', ['$delegate', '$injector', function ($delegate, $injector) {
|
||||
return function(exception, cause) {
|
||||
// Go to error state, reload the controller, keep the current URL
|
||||
$injector.get('$state').go('error', { details: exception }, {location:false, reload:true});
|
||||
$delegate(exception, cause);
|
||||
};
|
||||
}]);
|
||||
|
||||
}]);
|
||||
@@ -1,15 +1,29 @@
|
||||
angular.module('app')
|
||||
.controller('ErrorController', ['$rootScope','$scope','$stateParams', '$location', function ($rootScope, $scope, $p, $location) {
|
||||
$rootScope.title = 'Error';
|
||||
$scope.path = $location.path();
|
||||
$scope.type = $p.type || 'unknown';
|
||||
|
||||
if ($p.path) { // If path is specified, 404
|
||||
$scope.type = 404; // Deep Space Image...
|
||||
$scope.message = ""
|
||||
$scope.path = $p.path;
|
||||
} else {
|
||||
$scope.type = $p.type || 'unknown';
|
||||
$scope.message = $p.message || "Uh, this is bad..";
|
||||
$scope.path = $location.path();
|
||||
switch ($scope.type) {
|
||||
case 404:
|
||||
$scope.msgPre = 'Page';
|
||||
$scope.msgHighlight = $scope.path;
|
||||
$scope.msgPost = 'Not Found';
|
||||
$scope.image = 'deep-space';
|
||||
break;
|
||||
case 'no-ship':
|
||||
$scope.msgPre = 'Ship';
|
||||
$scope.msgHighlight = $p.message;
|
||||
$scope.msgPost = 'does not exist';
|
||||
$scope.image = 'thargoid';
|
||||
break;
|
||||
case 'build-fail':
|
||||
$scope.msgPre = 'Build Failure!';
|
||||
$scope.image = 'ship-explode';
|
||||
break;
|
||||
default:
|
||||
$scope.msgPre = "Uh, this is bad..";
|
||||
$scope.image = 'thargoid';
|
||||
}
|
||||
|
||||
}]);
|
||||
@@ -1,7 +1,8 @@
|
||||
angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$state', '$stateParams', 'Ship', 'Components', 'Serializer', 'Persist', function ($rootScope, $scope, $state, $p, Ship, Components, Serializer, Persist) {
|
||||
var data = DB.ships[$p.shipId];
|
||||
var data = DB.ships[$p.shipId]; // Retrieve the basic ship properties, slots and defaults
|
||||
var ship = new Ship($p.shipId, data.properties, data.slots); // Create a new Ship instance
|
||||
|
||||
// Update the ship instance with the code (if provided) or the 'factory' defaults.
|
||||
if ($p.code) {
|
||||
Serializer.toShip(ship, $p.code); // Populate components from 'code' URL param
|
||||
$scope.code = $p.code;
|
||||
@@ -10,7 +11,7 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
}
|
||||
|
||||
$scope.buildName = $p.bn;
|
||||
$rootScope.title = ship.name + $scope.buildName? ' - ' + $scope.buildName: '';
|
||||
$rootScope.title = ship.name + ($scope.buildName? ' - ' + $scope.buildName: '');
|
||||
$scope.ship = ship;
|
||||
$scope.pp = ship.common[0]; // Power Plant
|
||||
$scope.th = ship.common[1]; // Thruster
|
||||
@@ -23,11 +24,17 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
$scope.internal = ship.internal;
|
||||
$scope.availCS = Components.forShip(ship.id);
|
||||
$scope.selectedSlot = null;
|
||||
$scope.lastSaveCode = Persist.getBuild(ship.id, $scope.buildName);
|
||||
$scope.savedCode = Persist.getBuild(ship.id, $scope.buildName);
|
||||
|
||||
// for debugging
|
||||
window.myScope = $scope;
|
||||
|
||||
/**
|
||||
* 'Opens' a select for component selection.
|
||||
*
|
||||
* @param {[type]} e The event object
|
||||
* @param {[type]} slot The slot that is being 'opened' for selection
|
||||
*/
|
||||
$scope.selectSlot = function(e, slot) {
|
||||
e.stopPropagation();
|
||||
if ($scope.selectedSlot == slot) {
|
||||
@@ -37,6 +44,14 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the ships build with the selected component for the
|
||||
* specified slot. Prevents the click event from propagation.
|
||||
*
|
||||
* @param {string} type Shorthand key/string for identifying the slot & component type
|
||||
* @param {[type]} slot The slot object belonging to the ship instance
|
||||
* @param {[type]} e The event object
|
||||
*/
|
||||
$scope.select = function(type, slot, e) {
|
||||
e.stopPropagation();
|
||||
if (e.srcElement.id) {
|
||||
@@ -54,7 +69,6 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
$scope.selectedSlot = null;
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
$state.go('outfit', {shipId: ship.id, code: $scope.code, bn: $scope.buildName}, {location:'replace', notify:false});
|
||||
$scope.canSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,21 +76,28 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
* Reload the build from the last save.
|
||||
*/
|
||||
$scope.reloadBuild = function() {
|
||||
if ($scope.buildName && $scope.lastSaveCode) {
|
||||
Serializer.toShip(ship, $scope.lastSaveCode); // Repopulate with components from last save
|
||||
$scope.code = $scope.lastSaveCode;
|
||||
$state.go('outfit', {shipId: ship.id, code: $scope.lastSaveCode, bn: $scope.buildName}, {location:'replace', notify:false});
|
||||
if ($scope.buildName && $scope.savedCode) {
|
||||
Serializer.toShip(ship, $scope.savedCode); // Repopulate with components from last save
|
||||
$scope.code = $scope.savedCode;
|
||||
$state.go('outfit', {shipId: ship.id, code: $scope.savedCode, bn: $scope.buildName}, {location:'replace', notify:false});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the current build. Will replace the saved build if there is one
|
||||
* for this ship & with the exact name.
|
||||
*/
|
||||
$scope.saveBuild = function() {
|
||||
if ($scope.code && $scope.code != $scope.lastSaveCode) {
|
||||
if($scope.code != $scope.savedCode) {
|
||||
Persist.saveBuild(ship.id, $scope.buildName, $scope.code);
|
||||
$scope.lastSaveCode = $scope.code;
|
||||
$rootScope.$broadcast('buildSaved', ship.id, $scope.buildName, $scope.code);
|
||||
$scope.savedCode = $scope.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently delete the current build and redirect/reload this controller
|
||||
* with the 'factory' build of the current ship.
|
||||
*/
|
||||
$scope.deleteBuild = function() {
|
||||
Persist.deleteBuild(ship.id, $scope.buildName);
|
||||
$rootScope.$broadcast('buildDeleted', $scope.saveName, ship.id);
|
||||
@@ -84,17 +105,20 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s
|
||||
}
|
||||
|
||||
$rootScope.$on('keyup', function (e, keyEvent) {
|
||||
if(keyEvent.keyCode == 27) { // on Escape
|
||||
$scope.selectedSlot = null;
|
||||
$scope.$apply();
|
||||
}
|
||||
else if(keyEvent.keycode == 83 && keyEvent.ctrlKey){ // CTRL + S
|
||||
// CTRL + S or CMD + S will override the default and save the build is possible
|
||||
if (keyEvent.keycode == 83 && keyEvent.ctrlKey) {
|
||||
e.preventDefault();
|
||||
$scope.saveBuild();
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('bgClicked', function (e, keyEvent) {
|
||||
// Hide any open menu/slot/etc if escape key is pressed
|
||||
$rootScope.$on('escape', function (e, keyEvent) {
|
||||
$scope.selectedSlot = null;
|
||||
$scope.$apply();
|
||||
});
|
||||
// Hide any open menu/slot/etc if the background is clicked
|
||||
$rootScope.$on('close', function (e, keyEvent) {
|
||||
$scope.selectedSlot = null;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
angular.module('app')
|
||||
.controller('ShipyardController', ['$rootScope', function ($rootScope) {
|
||||
angular.module('app').controller('ShipyardController', ['$rootScope', function ($rootScope) {
|
||||
$rootScope.title = 'Coriolis - Shipyard';
|
||||
}]);
|
||||
37
app/js/directives/directive-header.js
Normal file
37
app/js/directives/directive-header.js
Normal file
@@ -0,0 +1,37 @@
|
||||
angular.module('app').directive('shipyardHeader', ['$rootScope', 'Persist', function ($rootScope, Persist) {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'views/_header.html',
|
||||
scope: true,
|
||||
link: function (scope) {
|
||||
scope.openedMenu = null;
|
||||
scope.ships = DB.ships;
|
||||
scope.allBuilds = Persist.builds;
|
||||
scope.bs = Persist.state;
|
||||
console.log(scope);
|
||||
|
||||
$rootScope.$on('$stateChangeStart',function(){
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
$rootScope.$on('close', function (e, keyEvent) {
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
scope.openMenu = function (menu) {
|
||||
if(menu == scope.openedMenu) {
|
||||
scope.openedMenu = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (menu == 'b' && !scope.bs.hasBuilds) {
|
||||
scope.openedMenu = null;
|
||||
return;
|
||||
}
|
||||
scope.openedMenu = menu;
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,13 +0,0 @@
|
||||
angular.module('app').directive('shipyardMenu', function () {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'views/menu.html',
|
||||
link: function () {
|
||||
|
||||
// TODO: Saved Ships: load, save, save as, delete, export
|
||||
// TODO: Links: github, forum, etc
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* [description]
|
||||
*/
|
||||
angular.module('app').service('Persist', ['lodash', function (_) {
|
||||
var LS_KEY = 'builds';
|
||||
|
||||
@@ -9,6 +12,9 @@ angular.module('app').service('Persist', ['lodash', function (_) {
|
||||
this.builds = {};
|
||||
}
|
||||
|
||||
this.state = {
|
||||
hasBuilds: Object.keys(this.builds).length > 0
|
||||
}
|
||||
/**
|
||||
* Persist a ship build in local storage.
|
||||
*
|
||||
@@ -22,7 +28,9 @@ angular.module('app').service('Persist', ['lodash', function (_) {
|
||||
}
|
||||
|
||||
this.builds[shipId][name] = code;
|
||||
localStorage.setItem(LS_KEY, angular.toJson(this.builds)); // Persist updated build collection to localstorage
|
||||
this.state.hasBuilds = true;
|
||||
// Persist updated build collection to localstorage
|
||||
localStorage.setItem(LS_KEY, angular.toJson(this.builds));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,11 +56,15 @@ angular.module('app').service('Persist', ['lodash', function (_) {
|
||||
* @param {string} name The name of the build
|
||||
*/
|
||||
this.deleteBuild = function (shipId, name) {
|
||||
delete build[shipId][name];
|
||||
if (Object.keys(build[shipId]).length == 0) {
|
||||
delete build[shipId];
|
||||
if(this.builds[shipId][name]) {
|
||||
delete this.builds[shipId][name];
|
||||
if (Object.keys(this.builds[shipId]).length == 0) {
|
||||
delete this.builds[shipId];
|
||||
this.state.hasBuilds = Object.keys(this.builds).length > 0;
|
||||
}
|
||||
// Persist updated build collection to localstorage
|
||||
localStorage.setItem(LS_KEY, angular.toJson(this.builds));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}]);
|
||||
}]);
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* information or behavoir in Elite Dangerous.
|
||||
*
|
||||
* This file contains values and functions that can be reused across the app.
|
||||
*
|
||||
* @requires ngLodash is a dependency of this module.
|
||||
*/
|
||||
angular.module('shipyard', [])
|
||||
angular.module('shipyard', ['ngLodash'])
|
||||
.value('commonArray', [
|
||||
'Power Plant',
|
||||
'Thrusters',
|
||||
@@ -67,42 +69,39 @@ angular.module('shipyard', [])
|
||||
'Large',
|
||||
'Huge'
|
||||
])
|
||||
.factory('calcJumpRange', function() {
|
||||
/**
|
||||
* Calculate the maximum single jump range based on mass and a specific FSD
|
||||
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
|
||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||
* @param {number} fuel Optional - The fuel consumed during the jump (must be less than the drives max fuel per jump)
|
||||
* @return {number} Distance in Light Years
|
||||
*/
|
||||
return function(mass, fsd, fuel) {
|
||||
/**
|
||||
* Calculate the maximum single jump range based on mass and a specific FSD
|
||||
*
|
||||
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
|
||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||
* @param {number} fuel Optional - The fuel consumed during the jump (must be less than the drives max fuel per jump)
|
||||
* @return {number} Distance in Light Years
|
||||
*/
|
||||
.value('calcJumpRange', function(mass, fsd, fuel) {
|
||||
return Math.pow(Math.min(fuel || Infinity, fsd.maxfuel) / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass;
|
||||
};
|
||||
})
|
||||
.factory('calcShieldStrength', function() {
|
||||
/**
|
||||
* Calculate the a ships shield strength based on mass, shield generator and shield boosters used.
|
||||
*
|
||||
* @private
|
||||
* @param {number} mass Current mass of the ship
|
||||
* @param {number} shields Base Shield strength MJ for ship
|
||||
* @param {object} sg The shield generator used
|
||||
* @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any)
|
||||
* @return {number} Approximate shield strengh in MJ
|
||||
*/
|
||||
return function (mass, shields, sg, multiplier) {
|
||||
if (!sg) {
|
||||
return 0;
|
||||
}
|
||||
if (mass <= sg.minmass) {
|
||||
return shields * multiplier * sg.minmul;
|
||||
}
|
||||
if (mass < sg.optmass) {
|
||||
return shields * multiplier * (sg.minmul + (mass - sg.minmass) / (sg.optmass - sg.minmass) * (sg.optmul - sg.minmul));
|
||||
}
|
||||
if (mass < sg.maxmass) {
|
||||
return shields * multiplier * (sg.optmul + (mass - sg.optmass) / (sg.maxmass - sg.optmass) * (sg.maxmul - sg.optmul));
|
||||
}
|
||||
return shields * multiplier * sg.maxmul;
|
||||
/**
|
||||
* Calculate the a ships shield strength based on mass, shield generator and shield boosters used.
|
||||
*
|
||||
* @private
|
||||
* @param {number} mass Current mass of the ship
|
||||
* @param {number} shields Base Shield strength MJ for ship
|
||||
* @param {object} sg The shield generator used
|
||||
* @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any)
|
||||
* @return {number} Approximate shield strengh in MJ
|
||||
*/
|
||||
.value('calcShieldStrength', function (mass, shields, sg, multiplier) {
|
||||
if (!sg) {
|
||||
return 0;
|
||||
}
|
||||
if (mass <= sg.minmass) {
|
||||
return shields * multiplier * sg.minmul;
|
||||
}
|
||||
if (mass < sg.optmass) {
|
||||
return shields * multiplier * (sg.minmul + (mass - sg.minmass) / (sg.optmass - sg.minmass) * (sg.optmul - sg.minmul));
|
||||
}
|
||||
if (mass < sg.maxmass) {
|
||||
return shields * multiplier * (sg.optmul + (mass - sg.optmass) / (sg.maxmass - sg.optmass) * (sg.maxmul - sg.optmul));
|
||||
}
|
||||
return shields * multiplier * sg.maxmul;
|
||||
});
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
@import 'fonts';
|
||||
@import 'utilities';
|
||||
@import 'icons';
|
||||
|
||||
@import 'header';
|
||||
@import 'shipyard';
|
||||
@import 'list';
|
||||
@import 'slot';
|
||||
@import 'ship';
|
||||
@import 'outfit';
|
||||
@import 'select';
|
||||
@import 'charts';
|
||||
@import 'meters';
|
||||
@import 'error';
|
||||
|
||||
|
||||
html, body {
|
||||
@@ -65,44 +66,19 @@ body {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: @bg;
|
||||
margin: 0;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
font-family: @fTitle;
|
||||
vertical-align: middle;
|
||||
|
||||
a {
|
||||
vertical-align: middle;
|
||||
color: @warning;
|
||||
|
||||
&:visited {
|
||||
color: @warning;
|
||||
}
|
||||
&:hover {
|
||||
color: teal;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3em;
|
||||
display: inline-block;
|
||||
margin:0px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
a, a:visited {
|
||||
color: @fg;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
font-size: 0.3em;
|
||||
font-size: 0.6em;
|
||||
color: #999;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header, footer {
|
||||
footer {
|
||||
.right {
|
||||
float: right;
|
||||
text-align: right;
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
@disabled: #888;
|
||||
@primary-disabled: darken(@primary, @disabledDarken);
|
||||
@secondary-disabled: darken(@primary, @disabledDarken);
|
||||
@warning-disabled: darken(@primary, @disabledDarken);
|
||||
@secondary-disabled: darken(@secondary, @disabledDarken);
|
||||
@warning-disabled: darken(@warning, @disabledDarken);
|
||||
|
||||
@bgBlack: rgba(0,0,0,0.6);
|
||||
@bgBlack: rgba(0,0,0,0.9);
|
||||
|
||||
@primary-bg: fadeout(darken(@primary, 45%), 30%);
|
||||
@secondary-bg: fadeout(darken(@secondary, @bgDarken), @bgTransparency); // Brown background
|
||||
|
||||
10
app/less/error.less
Normal file
10
app/less/error.less
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
.error {
|
||||
width: 50%;
|
||||
margin: 10% auto;
|
||||
text-align: center;
|
||||
|
||||
small {
|
||||
color: @primary-disabled;
|
||||
}
|
||||
}
|
||||
85
app/less/header.less
Normal file
85
app/less/header.less
Normal file
@@ -0,0 +1,85 @@
|
||||
header {
|
||||
background-color: @bg;
|
||||
margin: 0;
|
||||
padding: 0 1em;
|
||||
height: 4em;
|
||||
line-height: 4em;
|
||||
font-family: @fTitle;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
.user-select-none();
|
||||
|
||||
.menu {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.menu-header {
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
padding : 0 1em;
|
||||
cursor: pointer;
|
||||
color: @warning;
|
||||
|
||||
&.disabled {
|
||||
color: @warning-disabled;
|
||||
cursor: default;
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover, &.selected {
|
||||
background-color: @bgBlack;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
width: 200%;
|
||||
font-family: @fStandard;
|
||||
position: absolute;
|
||||
padding: 0 1em 1em 0;
|
||||
overflow: hidden;
|
||||
background-color: @bgBlack;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 0.5em;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
margin-left: 1em;
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
a {
|
||||
vertical-align: middle;
|
||||
color: @warning;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
|
||||
&:visited {
|
||||
color: @warning;
|
||||
}
|
||||
&:hover {
|
||||
color: teal;
|
||||
}
|
||||
&.active {
|
||||
color: @primary;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3em;
|
||||
display: inline-block;
|
||||
margin:0px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,24 @@
|
||||
|
||||
#overview {
|
||||
margin: 0px auto;
|
||||
text-align: center;
|
||||
|
||||
h1 {
|
||||
font-family: @fTitle;
|
||||
margin: 5px 0;
|
||||
color: @primary;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
#build {
|
||||
float: right;
|
||||
line-height: 2em;
|
||||
|
||||
input {
|
||||
background: @primary-bg;
|
||||
color: @fg;
|
||||
border: none;
|
||||
font-size: 0.8em;
|
||||
line-height: 2em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
.slot-group {
|
||||
float: left;
|
||||
margin: 0 5px;
|
||||
background-color: @bgBlack;
|
||||
.user-select-none();
|
||||
cursor: default;
|
||||
|
||||
|
||||
21
app/views/_header.html
Normal file
21
app/views/_header.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<header>
|
||||
<div class="l" style="margin-right: 2em;"><a ui-sref="shipyard" class="logo shipyard"></a></div>
|
||||
|
||||
<div class="l menu">
|
||||
<div class="menu-header" ng-class="{selected: openedMenu=='b', disabled: !bs.hasBuilds}" ng-click="openMenu('b')">Builds</div>
|
||||
<div class="menu-list" ng-if="openedMenu=='b'">
|
||||
<ul class="left" ng-repeat="(shipId,builds) in allBuilds">
|
||||
{{ships[shipId].properties.name}}
|
||||
<li ng-repeat="(name, build) in builds">
|
||||
<a ui-sref-active="active" ui-sref="outfit({shipId:shipId, code:build, bn:name})" ng-bind="name"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="r">
|
||||
<a class="logo github" href="https://github.com/cmmcleod/ed-shipyard" target="_blank" title="Shipyard Github Project"></a>
|
||||
<a class="logo reddit" href="#" target="_blank" title="Reddit Thread"></a>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
@@ -1,11 +0,0 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<a ui-sref="shipyard" class="logo shipyard"></a>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<a class="logo github" href="https://github.com/cmmcleod/ed-shipyard" target="_blank" title="Shipyard Github Project"></a>
|
||||
<a class="logo reddit" href="#" target="_blank" title="Reddit Thread"></a>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
@@ -1,12 +1,14 @@
|
||||
<div class="error">
|
||||
<h1>
|
||||
<span ng-if="msgPre">{{msgPre}}</span>
|
||||
<small ng-if="msgHighlight">{{msgHighlight}}</small>
|
||||
<span ng-if="msgPost">{{msgPost}}</span>
|
||||
</h1>
|
||||
|
||||
<!-- TODO: add awesome relevant SVG based on code /-->
|
||||
|
||||
<div>
|
||||
<h1>Error {{type}}</h1>
|
||||
<h2 ng-bind="message"></h2>
|
||||
|
||||
<p ng-if="path" ng-bind="path"></p>
|
||||
<p ng-if="path" ng-bind="path"></p>
|
||||
<p ng-if="type" ng-bind="type"></p>
|
||||
</div>
|
||||
|
||||
<!-- TODO: formatting /-->
|
||||
<!-- TODO: add awesome relevant SVG based on code /-->
|
||||
<!-- TODO: Add github issue link /-->
|
||||
@@ -124,16 +124,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="build">
|
||||
<h1 ng-bind="ship.name"></h1>
|
||||
<input ng-model="buildName" placeholder="Build Name" />
|
||||
<button ng-click="saveBuild()" ng-disabled="code == lastSaveCode">Save</button>
|
||||
<button ng-click="reloadBuild()" ng-disabled="!lastSaveCode || code == lastSaveCode">Reload</button>
|
||||
<button ui-sref="outfit({shipId: ship.id,code:null})" ng-disabled="!code">Clear</button>
|
||||
<button ng-click="deleteBuild()" ng-disabled="!lastSaveCode">Delete</button>
|
||||
</div>
|
||||
|
||||
<div id="summary">
|
||||
<div id="overview" class="list">
|
||||
<h1 ng-bind="ship.name"></h1>
|
||||
<div id="build">
|
||||
<input ng-model="buildName" placeholder="Enter Build Name" />
|
||||
<button ng-click="saveBuild()" ng-disabled="code == savedCode">Save</button>
|
||||
<button ng-click="reloadBuild()" ng-disabled="!savedCode || code == savedCode">Reload</button>
|
||||
<button ui-sref="outfit({shipId: ship.id,code:null})" ng-disabled="!code">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="header">Maneuverability</div>
|
||||
<div class="summary">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"dependencies": {
|
||||
"d3": "~3.5.5",
|
||||
"ng-lodash": "~0.2.0",
|
||||
"angular-ui-router": "0.2.14"
|
||||
"angular-ui-router": "^0.2.14"
|
||||
},
|
||||
"overrides": {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user