Integrated eslint and reformatted all of the JS/TS
This commit is contained in:
82
.eslintrc.yml
Normal file
82
.eslintrc.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
env:
|
||||
es2021: true
|
||||
node: true
|
||||
browser: true
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:@typescript-eslint/recommended
|
||||
overrides: []
|
||||
parser: "@typescript-eslint/parser"
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
plugins:
|
||||
- "@typescript-eslint"
|
||||
globals:
|
||||
Vue: readonly
|
||||
THREE: readonly
|
||||
SvelteComponents: readonly
|
||||
$: readonly
|
||||
Clusterize: readonly
|
||||
SockJS: readonly
|
||||
rules:
|
||||
indent:
|
||||
- off
|
||||
"@typescript-eslint/indent":
|
||||
- error
|
||||
- 4
|
||||
linebreak-style:
|
||||
- error
|
||||
- unix
|
||||
quotes:
|
||||
- error
|
||||
- double
|
||||
- allowTemplateLiterals: true
|
||||
avoidEscape: true
|
||||
semi:
|
||||
- error
|
||||
- always
|
||||
"@typescript-eslint/no-explicit-any":
|
||||
- off
|
||||
"@typescript-eslint/no-unused-vars":
|
||||
- error
|
||||
- argsIgnorePattern: _.*
|
||||
no-unused-vars:
|
||||
- error
|
||||
no-trailing-spaces:
|
||||
- error
|
||||
key-spacing:
|
||||
- error
|
||||
space-before-blocks:
|
||||
- error
|
||||
block-spacing:
|
||||
- error
|
||||
brace-style:
|
||||
- error
|
||||
curly:
|
||||
- error
|
||||
keyword-spacing:
|
||||
- error
|
||||
"@typescript-eslint/no-var-requires":
|
||||
- off
|
||||
no-multiple-empty-lines:
|
||||
- error
|
||||
- max: 1
|
||||
func-call-spacing:
|
||||
- error
|
||||
- never
|
||||
padding-line-between-statements:
|
||||
- error
|
||||
- blankLine: always
|
||||
prev: function
|
||||
next: function
|
||||
no-var:
|
||||
- error
|
||||
no-unused-expressions:
|
||||
- error
|
||||
prefer-const:
|
||||
- error
|
||||
prefer-template:
|
||||
- error
|
||||
template-curly-spacing:
|
||||
- error
|
||||
2914
package-lock.json
generated
2914
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,14 @@
|
||||
"postinstall": "cd src/svelte-components && npm i"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.36.1",
|
||||
"@typescript-eslint/parser": "^5.36.1",
|
||||
"browserify": "^17.0.0",
|
||||
"eslint": "^8.23.0",
|
||||
"eslint-config-standard-with-typescript": "^22.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.2.5",
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"jshint": "^2.13.4",
|
||||
"jstransformer-escape-html": "^1.1.0",
|
||||
"jstransformer-scss": "^2.0.0",
|
||||
|
||||
@@ -1,32 +1,6 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
const api = require("./api");
|
||||
const merge = require("lodash.merge");
|
||||
|
||||
const config_defaults = require("../resources/onefinity_defaults.json");
|
||||
@@ -38,34 +12,32 @@ const variant_defaults = {
|
||||
journeyman_x50: require("../resources/onefinity_journeyman_x50_defaults.json")
|
||||
};
|
||||
|
||||
const api = require('./api');
|
||||
|
||||
module.exports = {
|
||||
template: '#admin-general-view-template',
|
||||
props: ['config', 'state'],
|
||||
template: "#admin-general-view-template",
|
||||
props: ["config", "state"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
confirmReset: false,
|
||||
autoCheckUpgrade: true,
|
||||
reset_variant: ''
|
||||
}
|
||||
reset_variant: ""
|
||||
};
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.autoCheckUpgrade = this.config.admin['auto-check-upgrade']
|
||||
this.autoCheckUpgrade = this.config.admin["auto-check-upgrade"];
|
||||
},
|
||||
|
||||
methods: {
|
||||
backup: function () {
|
||||
document.getElementById('download-target').src = '/api/config/download';
|
||||
document.getElementById("download-target").src = "/api/config/download";
|
||||
},
|
||||
|
||||
restore_config: function () {
|
||||
// If we don't reset the form the browser may cache file if name is same
|
||||
// even if contents have changed
|
||||
$('.restore-config')[0].reset();
|
||||
$('.restore-config input').click();
|
||||
$(".restore-config")[0].reset();
|
||||
$(".restore-config input").click();
|
||||
},
|
||||
|
||||
restore: function (e) {
|
||||
@@ -85,13 +57,16 @@ module.exports = {
|
||||
}
|
||||
|
||||
try {
|
||||
await api.put('config/save', config);
|
||||
this.$dispatch('update');
|
||||
SvelteComponents.showDialog("Message", { title: "Success", message: "Configuration restored" })
|
||||
await api.put("config/save", config);
|
||||
this.$dispatch("update");
|
||||
SvelteComponents.showDialog("Message", {
|
||||
title: "Success",
|
||||
message: "Configuration restored"
|
||||
});
|
||||
} catch (error) {
|
||||
api.alert('Restore failed', error);
|
||||
}
|
||||
api.alert("Restore failed", error);
|
||||
}
|
||||
};
|
||||
|
||||
fileReader.readAsText(files[0]);
|
||||
},
|
||||
@@ -104,40 +79,45 @@ module.exports = {
|
||||
);
|
||||
|
||||
try {
|
||||
await api.put('config/save', config)
|
||||
await api.put("config/save", config);
|
||||
this.confirmReset = false;
|
||||
this.$dispatch('update');
|
||||
SvelteComponents.showDialog("Message", { title: "Success", message: "Configuration restored" })
|
||||
this.$dispatch("update");
|
||||
SvelteComponents.showDialog("Message", {
|
||||
title: "Success",
|
||||
message: "Configuration restored"
|
||||
});
|
||||
} catch (err) {
|
||||
api.alert('Restore failed');
|
||||
console.error('Restore failed', err);
|
||||
api.alert("Restore failed");
|
||||
console.error("Restore failed", err);
|
||||
}
|
||||
},
|
||||
|
||||
check: function () {
|
||||
this.$dispatch('check')
|
||||
this.$dispatch("check");
|
||||
},
|
||||
|
||||
upgrade: function () {
|
||||
this.$dispatch('upgrade')
|
||||
this.$dispatch("upgrade");
|
||||
},
|
||||
|
||||
upload_firmware: function () {
|
||||
// If we don't reset the form the browser may cache file if name is same
|
||||
// even if contents have changed
|
||||
$('.upload-firmware')[0].reset();
|
||||
$('.upload-firmware input').click();
|
||||
$(".upload-firmware")[0].reset();
|
||||
$(".upload-firmware input").click();
|
||||
},
|
||||
|
||||
upload: function (e) {
|
||||
var files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) return;
|
||||
this.$dispatch('upload', files[0]);
|
||||
const files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
this.$dispatch("upload", files[0]);
|
||||
},
|
||||
|
||||
change_auto_check_upgrade: function () {
|
||||
this.config.admin['auto-check-upgrade'] = this.autoCheckUpgrade;
|
||||
this.$dispatch('config-changed');
|
||||
this.config.admin["auto-check-upgrade"] = this.autoCheckUpgrade;
|
||||
this.$dispatch("config-changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,77 +1,37 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
|
||||
function api_cb(method, url, data, config) {
|
||||
config = $.extend({
|
||||
type: method,
|
||||
url: '/api/' + url,
|
||||
dataType: 'json',
|
||||
cache: false
|
||||
}, config);
|
||||
|
||||
if (typeof data == 'object') {
|
||||
config.data = JSON.stringify(data);
|
||||
config.contentType = 'application/json; charset=utf-8';
|
||||
}
|
||||
|
||||
var d = $.Deferred();
|
||||
|
||||
$.ajax(config).success(function (data, status, xhr) {
|
||||
d.resolve(data, status, xhr);
|
||||
|
||||
}).error(function (xhr, status, error) {
|
||||
var text = xhr.responseText;
|
||||
try {text = $.parseJSON(xhr.responseText)} catch(e) {}
|
||||
if (!text) text = error;
|
||||
|
||||
d.reject(text, xhr, status, error);
|
||||
console.debug('API Error: ' + url + ': ' + text);
|
||||
async function callApi(method, url, body) {
|
||||
try {
|
||||
const response = await fetch(`/api/${url}`, {
|
||||
method,
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body
|
||||
});
|
||||
|
||||
return d.promise();
|
||||
}
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
throw new Error(await response.text());
|
||||
} catch (error) {
|
||||
console.debug(`API Error: ${url}: ${error}`);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get: function (url, config) {
|
||||
return api_cb('GET', url, undefined, config);
|
||||
get: function (url) {
|
||||
return callApi("GET", url);
|
||||
},
|
||||
|
||||
|
||||
put: function(url, data, config) {
|
||||
return api_cb('PUT', url, data, config);
|
||||
put: function(url, body = undefined) {
|
||||
return callApi("PUT", url, body);
|
||||
},
|
||||
|
||||
|
||||
post: function(url, data, config) {
|
||||
return api_cb('POST', url, data, config);
|
||||
},
|
||||
|
||||
|
||||
upload: function(url, data, config) {
|
||||
config = $.extend({
|
||||
processData: false,
|
||||
contentType: false,
|
||||
cache: false,
|
||||
data: data
|
||||
}, config);
|
||||
|
||||
return api_cb('PUT', url, undefined, config);
|
||||
},
|
||||
|
||||
|
||||
'delete': function (url, config) {
|
||||
return api_cb('DELETE', url, undefined, config);
|
||||
},
|
||||
|
||||
|
||||
alert: function (msg, error) {
|
||||
if (typeof error != 'undefined') {
|
||||
if (typeof error.message != 'undefined')
|
||||
msg += '\n' + error.message;
|
||||
else msg += '\n' + JSON.stringify(error);
|
||||
delete: function (url) {
|
||||
return callApi("DELETE", url);
|
||||
}
|
||||
|
||||
alert(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,8 +23,7 @@ function is_newer_version(current, latest) {
|
||||
const patch = latestParts[3] - currentParts[3];
|
||||
|
||||
// If current is a pre-release, and latest is a release
|
||||
const betaToRelease =
|
||||
latestParts[4].length === 0 && currentParts[4].length > 0;
|
||||
const betaToRelease = latestParts[4].length === 0 && currentParts[4].length > 0;
|
||||
|
||||
switch (true) {
|
||||
case major > 0:
|
||||
@@ -41,24 +40,36 @@ function is_newer_version(current, latest) {
|
||||
function is_object(o) {
|
||||
return o !== null && typeof o == "object";
|
||||
}
|
||||
|
||||
function is_array(o) {
|
||||
return Array.isArray(o);
|
||||
}
|
||||
|
||||
function update_array(dst, src) {
|
||||
while (dst.length) dst.pop();
|
||||
for (var i = 0; i < src.length; i++) Vue.set(dst, i, src[i]);
|
||||
while (dst.length) {
|
||||
dst.pop();
|
||||
}
|
||||
|
||||
for (let i = 0; i < src.length; i++) {
|
||||
Vue.set(dst, i, src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function hasOwnProperty(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
|
||||
function update_object(dst, src, remove) {
|
||||
var props, index, key, value;
|
||||
let props, index, key, value;
|
||||
|
||||
if (remove) {
|
||||
props = Object.getOwnPropertyNames(dst);
|
||||
|
||||
for (index in props) {
|
||||
key = props[index];
|
||||
if (!src.hasOwnProperty(key)) Vue.delete(dst, key);
|
||||
if (!hasOwnProperty(src, key)) {
|
||||
Vue.delete(dst, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,11 +78,13 @@ function update_object(dst, src, remove) {
|
||||
key = props[index];
|
||||
value = src[key];
|
||||
|
||||
if (is_array(value) && dst.hasOwnProperty(key) && is_array(dst[key]))
|
||||
if (is_array(value) && hasOwnProperty(dst, key) && is_array(dst[key])) {
|
||||
update_array(dst[key], value);
|
||||
else if (is_object(value) && dst.hasOwnProperty(key) && is_object(dst[key]))
|
||||
} else if (is_object(value) && hasOwnProperty(dst, key) && is_object(dst[key])) {
|
||||
update_object(dst[key], value, remove);
|
||||
else Vue.set(dst, key, value);
|
||||
} else {
|
||||
Vue.set(dst, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +194,9 @@ module.exports = new Vue({
|
||||
|
||||
error: function (msg) {
|
||||
// Honor user error blocking
|
||||
if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000)
|
||||
if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait at least 1 sec to pop up repeated errors
|
||||
if (1 < msg.repeat && Date.now() - msg.ts < 1000) {
|
||||
@@ -225,9 +239,12 @@ module.exports = new Vue({
|
||||
this.errorShow = false;
|
||||
},
|
||||
|
||||
toggle_video: function (e) {
|
||||
if (this.video_size == "small") this.video_size = "large";
|
||||
else if (this.video_size == "large") this.video_size = "small";
|
||||
toggle_video: function () {
|
||||
if (this.video_size == "small") {
|
||||
this.video_size = "large";
|
||||
} else if (this.video_size == "large") {
|
||||
this.video_size = "small";
|
||||
}
|
||||
cookie.set("video-size", this.video_size);
|
||||
},
|
||||
|
||||
@@ -238,8 +255,11 @@ module.exports = new Vue({
|
||||
},
|
||||
|
||||
estop: function () {
|
||||
if (this.state.xx == "ESTOPPED") api.put("clear");
|
||||
else api.put("estop");
|
||||
if (this.state.xx == "ESTOPPED") {
|
||||
api.put("clear");
|
||||
} else {
|
||||
api.put("estop");
|
||||
}
|
||||
},
|
||||
|
||||
upgrade_confirmed: async function () {
|
||||
@@ -302,8 +322,10 @@ module.exports = new Vue({
|
||||
if (!this.checkedUpgrade) {
|
||||
this.checkedUpgrade = true;
|
||||
|
||||
var check = this.config.admin["auto-check-upgrade"];
|
||||
if (typeof check == "undefined" || check) this.$emit("check");
|
||||
const check = this.config.admin["auto-check-upgrade"];
|
||||
if (typeof check == "undefined" || check) {
|
||||
this.$emit("check");
|
||||
}
|
||||
}
|
||||
|
||||
SvelteComponents.handleConfigUpdate(this.config);
|
||||
@@ -328,10 +350,7 @@ module.exports = new Vue({
|
||||
if (typeof this.sid == "undefined") {
|
||||
this.sid = e.data.sid;
|
||||
} else if (this.sid != e.data.sid) {
|
||||
if (
|
||||
typeof this.hostname !== "undefined" &&
|
||||
location.hostname !== "localhost"
|
||||
) {
|
||||
if (this.hostname && location.hostname !== "localhost") {
|
||||
location.hostname = this.hostname;
|
||||
}
|
||||
|
||||
@@ -362,16 +381,18 @@ module.exports = new Vue({
|
||||
},
|
||||
|
||||
parse_hash: function () {
|
||||
var hash = location.hash.substr(1);
|
||||
const hash = location.hash.substr(1);
|
||||
|
||||
if (!hash.trim().length) {
|
||||
location.hash = "control";
|
||||
return;
|
||||
}
|
||||
|
||||
var parts = hash.split(":");
|
||||
const parts = hash.split(":");
|
||||
|
||||
if (parts.length == 2) this.index = parts[1];
|
||||
if (parts.length == 2) {
|
||||
this.index = parts[1];
|
||||
}
|
||||
|
||||
this.currentView = parts[0];
|
||||
},
|
||||
@@ -402,12 +423,17 @@ module.exports = new Vue({
|
||||
},
|
||||
|
||||
close_messages: function (action) {
|
||||
if (action == "stop") api.put("stop");
|
||||
if (action == "continue") api.put("unpause");
|
||||
if (action == "stop") {
|
||||
api.put("stop");
|
||||
}
|
||||
|
||||
if (action == "continue") {
|
||||
api.put("unpause");
|
||||
}
|
||||
|
||||
// Acknowledge messages
|
||||
if (this.state.messages.length) {
|
||||
var id = this.state.messages.slice(-1)[0].id;
|
||||
const id = this.state.messages.slice(-1)[0].id;
|
||||
api.put("message/" + id + "/ack");
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,65 +1,37 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#axis-control-template',
|
||||
props: ['axes', 'colors', 'enabled', 'adjust', 'step'],
|
||||
|
||||
template: "#axis-control-template",
|
||||
props: ["axes", "colors", "enabled", "adjust", "step"],
|
||||
|
||||
methods: {
|
||||
jog: function (axis, ring, direction) {
|
||||
var value = direction * this.value(ring);
|
||||
this.$dispatch(this.step ? 'step' : 'jog', this.axes[axis], value);
|
||||
const value = direction * this.value(ring);
|
||||
this.$dispatch(this.step ? "step" : "jog", this.axes[axis], value);
|
||||
},
|
||||
|
||||
back2zero: function(axis0,axis1) {
|
||||
this.$dispatch('back2zero',this.axes[axis0],this.axes[axis1])
|
||||
this.$dispatch("back2zero",this.axes[axis0],this.axes[axis1]);
|
||||
},
|
||||
|
||||
|
||||
release: function (axis) {
|
||||
if (!this.step) this.$dispatch('jog', this.axes[axis], 0)
|
||||
if (!this.step) {
|
||||
this.$dispatch("jog", this.axes[axis], 0);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
value: function (ring) {
|
||||
var adjust = [0.01, 0.1, 1][this.adjust];
|
||||
if (this.step) return adjust * [0.1, 1, 10, 100][ring];
|
||||
const adjust = [0.01, 0.1, 1][this.adjust];
|
||||
if (this.step) {
|
||||
return adjust * [0.1, 1, 10, 100][ring];
|
||||
}
|
||||
return adjust * [0.1, 0.25, 0.5, 1][ring];
|
||||
},
|
||||
|
||||
|
||||
text: function (ring) {
|
||||
var value = this.value(ring) * (this.step ? 1 : 100);
|
||||
let value = this.value(ring) * (this.step ? 1 : 100);
|
||||
value = parseFloat(value.toFixed(3));
|
||||
return value + (this.step ? '' : '%');
|
||||
return value + (this.step ? "" : "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,17 +1,40 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
props: ['state', 'config'],
|
||||
props: ["state", "config"],
|
||||
|
||||
computed: {
|
||||
metric: function () { this.$root.display_units === "METRIC" },
|
||||
x: function () { return this._compute_axis('x') },
|
||||
y: function () { return this._compute_axis('y') },
|
||||
z: function () { return this._compute_axis('z') },
|
||||
a: function () { return this._compute_axis('a') },
|
||||
b: function () { return this._compute_axis('b') },
|
||||
c: function () { return this._compute_axis('c') },
|
||||
axes: function () { return this._compute_axes() }
|
||||
metric: function () {
|
||||
return this.$root.display_units === "METRIC";
|
||||
},
|
||||
|
||||
x: function () {
|
||||
return this._compute_axis("x");
|
||||
},
|
||||
|
||||
y: function () {
|
||||
return this._compute_axis("y");
|
||||
},
|
||||
|
||||
z: function () {
|
||||
return this._compute_axis("z");
|
||||
},
|
||||
|
||||
a: function () {
|
||||
return this._compute_axis("a");
|
||||
},
|
||||
|
||||
b: function () {
|
||||
return this._compute_axis("b");
|
||||
},
|
||||
|
||||
c: function () {
|
||||
return this._compute_axis("c");
|
||||
},
|
||||
|
||||
axes: function () {
|
||||
return this._compute_axes();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -22,98 +45,115 @@ module.exports = {
|
||||
},
|
||||
|
||||
_length_str: function (value) {
|
||||
return this._convert_length(value).toLocaleString() +
|
||||
(this.metric ? ' mm' : ' in');
|
||||
return this._convert_length(value).toLocaleString() + (this.metric ? " mm" : " in");
|
||||
},
|
||||
|
||||
_compute_axis: function (axis) {
|
||||
var abs = this.state[axis + 'p'] || 0;
|
||||
var off = this.state['offset_' + axis];
|
||||
var motor_id = this._get_motor_id(axis);
|
||||
var motor = motor_id == -1 ? {} : this.config.motors[motor_id];
|
||||
var enabled = typeof motor.enabled != 'undefined' && motor.enabled;
|
||||
var homingMode = motor['homing-mode']
|
||||
var homed = this.state[motor_id + 'homed'];
|
||||
var min = this.state[motor_id + 'tn'];
|
||||
var max = this.state[motor_id + 'tm'];
|
||||
var dim = max - min;
|
||||
var pathMin = this.state['path_min_' + axis];
|
||||
var pathMax = this.state['path_max_' + axis];
|
||||
var pathDim = pathMax - pathMin;
|
||||
var under = pathMin + off < min;
|
||||
var over = max < pathMax + off;
|
||||
var klass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis;
|
||||
var state = 'UNHOMED';
|
||||
var icon = 'question-circle';
|
||||
var fault = this.state[motor_id + 'df'] & 0x1f;
|
||||
var shutdown = this.state.power_shutdown;
|
||||
var title;
|
||||
var ticon = 'question-circle';
|
||||
var tstate = 'NO FILE';
|
||||
var toolmsg;
|
||||
var tklass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis;
|
||||
const abs = this.state[`${axis}p`] || 0;
|
||||
const off = this.state[`offset_${axis}`];
|
||||
const motor_id = this._get_motor_id(axis);
|
||||
const motor = motor_id == -1 ? {} : this.config.motors[motor_id];
|
||||
const enabled = typeof motor.enabled != "undefined" && motor.enabled;
|
||||
const homingMode = motor["homing-mode"];
|
||||
const homed = this.state[`${motor_id}homed`];
|
||||
const min = this.state[`${motor_id}tn`];
|
||||
const max = this.state[`${motor_id}tm`];
|
||||
const dim = max - min;
|
||||
const pathMin = this.state[`path_min_${axis}`];
|
||||
const pathMax = this.state[`path_max_${axis}`];
|
||||
const pathDim = pathMax - pathMin;
|
||||
const under = pathMin + off < min;
|
||||
const over = max < pathMax + off;
|
||||
let klass = `${homed ? "homed" : "unhomed"} axis-${axis}`;
|
||||
let state = "UNHOMED";
|
||||
let icon = "question-circle";
|
||||
const fault = this.state[`${motor_id}df`] & 0x1f;
|
||||
const shutdown = this.state.power_shutdown;
|
||||
let title;
|
||||
let ticon = "question-circle";
|
||||
let tstate = "NO FILE";
|
||||
let toolmsg;
|
||||
let tklass = `${homed ? "homed" : "unhomed"} axis-${axis}`;
|
||||
|
||||
if (fault || shutdown) {
|
||||
state = shutdown ? 'SHUTDOWN' : 'FAULT';
|
||||
klass += ' error';
|
||||
icon = 'exclamation-circle';
|
||||
state = shutdown ? "SHUTDOWN" : "FAULT";
|
||||
klass += " error";
|
||||
icon = "exclamation-circle";
|
||||
} else if (homed) {
|
||||
state = 'HOMED';
|
||||
icon = 'check-circle';
|
||||
state = "HOMED";
|
||||
icon = "check-circle";
|
||||
}
|
||||
|
||||
if (0 < dim && dim < pathDim) {
|
||||
tstate = 'NO FIT';
|
||||
tklass += ' error';
|
||||
ticon = 'ban';
|
||||
tstate = "NO FIT";
|
||||
tklass += " error";
|
||||
ticon = "ban";
|
||||
} else {
|
||||
if (over || under) {
|
||||
tstate = over ? 'OVER' : 'UNDER';
|
||||
tklass += ' warn';
|
||||
ticon = 'exclamation-circle';
|
||||
tstate = over ? "OVER" : "UNDER";
|
||||
tklass += " warn";
|
||||
ticon = "exclamation-circle";
|
||||
} else {
|
||||
tstate = 'OK';
|
||||
ticon = 'check-circle';
|
||||
tstate = "OK";
|
||||
ticon = "check-circle";
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case 'UNHOMED': title = 'Click the home button to home axis.'; break;
|
||||
case 'HOMED': title = 'Axis successfuly homed.'; break;
|
||||
case 'FAULT':
|
||||
title = 'Motor driver fault. A potentially damaging electrical ' +
|
||||
'condition was detected and the motor driver was shutdown. ' +
|
||||
'Please power down the controller and check your motor cabling. ' +
|
||||
'See the "Motor Faults" table on the "Indicators" tab for more ' +
|
||||
'information.';
|
||||
case "UNHOMED":
|
||||
title = "Click the home button to home axis.";
|
||||
break;
|
||||
|
||||
case 'SHUTDOWN':
|
||||
title = 'Motor power fault. All motors in shutdown. ' +
|
||||
'See the "Power Faults" table on the "Indicators" tab for more ' +
|
||||
'information. Reboot controller to reset.';
|
||||
case "HOMED":
|
||||
title = "Axis successfuly homed.";
|
||||
break;
|
||||
|
||||
case "FAULT":
|
||||
title = [
|
||||
`Motor driver fault. A potentially damaging electrical`,
|
||||
`condition was detected and the motor driver was shutdown.`,
|
||||
`Please power down the controller and check your motor cabling.`,
|
||||
`See the "Motor Faults" table on the "Indicators" tab for more`,
|
||||
`information.`,
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
case "SHUTDOWN":
|
||||
title = [
|
||||
`Motor power fault. All motors in shutdown.`,
|
||||
`See the "Power Faults" table on the "Indicators" tab for more`,
|
||||
`information. Reboot controller to reset.`
|
||||
].join(" ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (tstate) {
|
||||
case 'OVER':
|
||||
toolmsg = 'Caution: The current tool path file would move ' +
|
||||
this._length_str(pathMax + off - max) + ' above axis limit with the current offset.';
|
||||
case "OVER":
|
||||
toolmsg = [
|
||||
`Caution: The current tool path file would move`,
|
||||
`${this._length_str(pathMax + off - max)}`,
|
||||
`above axis limit with the current offset.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
case 'UNDER':
|
||||
toolmsg = 'Caution: The current tool path file would move ' +
|
||||
this._length_str(min - pathMin - off) + ' below limit with the current offset.';
|
||||
case "UNDER":
|
||||
toolmsg = [
|
||||
`Caution: The current tool path file would move`,
|
||||
`${this._length_str(min - pathMin - off)}`,
|
||||
`below limit with the current offset.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
case 'NO FIT':
|
||||
toolmsg = 'Warning: The current tool path dimensions (' +
|
||||
this._length_str(pathDim) + ') exceed axis dimensions (' +
|
||||
this._length_str(dim) + ') by ' +
|
||||
this._length_str(pathDim - dim) + '.';
|
||||
case "NO FIT":
|
||||
toolmsg = [
|
||||
`Warning: The current tool path dimensions`,
|
||||
`(${this._length_str(pathDim)}) exceed axis dimensions`,
|
||||
`(${this._length_str(dim)}) by ${this._length_str(pathDim - dim)}.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
default:
|
||||
toolmsg = 'Tool path ' + axis + ' dimensions OK.';
|
||||
toolmsg = `Tool path ${axis} dimensions OK.`;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -139,44 +179,64 @@ module.exports = {
|
||||
tstate: tstate,
|
||||
toolmsg: toolmsg,
|
||||
tklass: tklass
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_get_motor_id: function (axis) {
|
||||
for (var i = 0; i < this.config.motors.length; i++) {
|
||||
var motor = this.config.motors[i];
|
||||
if (motor.axis.toLowerCase() == axis) return i;
|
||||
for (let i = 0; i < this.config.motors.length; i++) {
|
||||
const motor = this.config.motors[i];
|
||||
if (motor.axis.toLowerCase() == axis) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
},
|
||||
|
||||
_compute_axes: function () {
|
||||
var homed = false;
|
||||
let homed = false;
|
||||
|
||||
for (var name of 'xyzabc') {
|
||||
var axis = this[name];
|
||||
for (const name of "xyzabc") {
|
||||
const axis = this[name];
|
||||
|
||||
if (!axis.enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!axis.homed) {
|
||||
homed = false; break;
|
||||
}
|
||||
|
||||
if (!axis.enabled) continue
|
||||
if (!axis.homed) { homed = false; break }
|
||||
homed = true;
|
||||
}
|
||||
|
||||
var error = false;
|
||||
var warn = false;
|
||||
let error = false;
|
||||
let warn = false;
|
||||
|
||||
if (homed)
|
||||
for (name of 'xyzabc') {
|
||||
axis = this[name];
|
||||
if (homed) {
|
||||
for (const name of "xyzabc") {
|
||||
const axis = this[name];
|
||||
|
||||
if (!axis.enabled) continue;
|
||||
if (axis.klass.indexOf('error') != -1) error = true;
|
||||
if (axis.klass.indexOf('warn') != -1) warn = true;
|
||||
if (!axis.enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var klass = homed ? 'homed' : 'unhomed';
|
||||
if (error) klass += ' error';
|
||||
else if (warn) klass += ' warn';
|
||||
if (axis.klass.indexOf("error") != -1) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (axis.klass.indexOf("warn") != -1) {
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let klass = homed ? "homed" : "unhomed";
|
||||
if (error) {
|
||||
klass += " error";
|
||||
} else if (warn) {
|
||||
klass += " warn";
|
||||
}
|
||||
|
||||
if (!homed && this.ask_home) {
|
||||
this.ask_home = false;
|
||||
@@ -188,7 +248,7 @@ module.exports = {
|
||||
return {
|
||||
homed: homed,
|
||||
klass: klass
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,87 +1,72 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
function _msg_equal(a, b) {
|
||||
return a.level == b.level && a.source == b.source && a.where == b.where &&
|
||||
a.msg == b.msg;
|
||||
return a.level == b.level
|
||||
&& a.source == b.source
|
||||
&& a.where == b.where
|
||||
&&a.msg == b.msg;
|
||||
}
|
||||
|
||||
|
||||
// Shared among all instances
|
||||
var messages = [];
|
||||
|
||||
const messages = [];
|
||||
|
||||
module.exports = {
|
||||
template: '#console-template',
|
||||
|
||||
template: "#console-template",
|
||||
|
||||
data: function () {
|
||||
return {messages: messages}
|
||||
return {
|
||||
messages
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
log: function (msg) {
|
||||
// There may be multiple instances of this module so ignore messages
|
||||
// that have already been processed.
|
||||
if (msg.logged) return;
|
||||
if (msg.logged) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.logged = true;
|
||||
|
||||
// Make sure we have a message level
|
||||
msg.level = msg.level || 'info';
|
||||
msg.level = msg.level || "info";
|
||||
|
||||
// Add to message log and count and collapse repeats
|
||||
var repeat = messages.length && _msg_equal(msg, messages[0]);
|
||||
if (repeat) messages[0].repeat++;
|
||||
else {
|
||||
const repeat = messages.length && _msg_equal(msg, messages[0]);
|
||||
if (repeat) {
|
||||
messages[0].repeat++;
|
||||
} else {
|
||||
msg.repeat = msg.repeat || 1;
|
||||
messages.unshift(msg);
|
||||
while (256 < messages.length) messages.pop();
|
||||
while (256 < messages.length) {
|
||||
messages.pop();
|
||||
}
|
||||
}
|
||||
msg.ts = Date.now();
|
||||
|
||||
// Write message to browser console for debugging
|
||||
var text = JSON.stringify(msg);
|
||||
if (msg.level == 'error' || msg.level == 'critical') console.error(text);
|
||||
else if (msg.level == 'warning') console.warn(text);
|
||||
else if (msg.level == 'debug' && console.debug) console.debug(text);
|
||||
else console.log(text);
|
||||
const text = JSON.stringify(msg);
|
||||
if (msg.level == "error" || msg.level == "critical") {
|
||||
console.error(text);
|
||||
} else if (msg.level == "warning") {
|
||||
console.warn(text);
|
||||
} else if (msg.level == "debug" && console.debug) {
|
||||
console.debug(text);
|
||||
} else {
|
||||
console.log(text);
|
||||
}
|
||||
|
||||
// Event on errors
|
||||
if (msg.level == 'error' || msg.level == 'critical')
|
||||
this.$dispatch('error', msg);
|
||||
if (msg.level == "error" || msg.level == "critical") {
|
||||
this.$dispatch("error", msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
clear: function () {messages.splice(0, messages.length);},
|
||||
clear: function () {
|
||||
messages.splice(0, messages.length);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
var api = require('./api');
|
||||
var cookie = require('./cookie')('bbctrl-');
|
||||
const api = require("./api");
|
||||
const cookie = require("./cookie")("bbctrl-");
|
||||
|
||||
module.exports = {
|
||||
template: '#control-view-template',
|
||||
props: ['config', 'template', 'state'],
|
||||
template: "#control-view-template",
|
||||
props: ["config", "template", "state"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
current_time: "",
|
||||
mach_units: this.$root.state.metric ? "METRIC" : "IMPERIAL",
|
||||
mdi: '',
|
||||
mdi: "",
|
||||
last_file: undefined,
|
||||
last_file_time: undefined,
|
||||
toolpath: {},
|
||||
toolpath_progress: 0,
|
||||
axes: 'xyzabc',
|
||||
axes: "xyzabc",
|
||||
history: [],
|
||||
speed_override: 1,
|
||||
feed_override: 1,
|
||||
@@ -34,20 +34,20 @@ module.exports = {
|
||||
large: 5,
|
||||
}
|
||||
},
|
||||
jog_incr: localStorage.getItem("jog_incr") || 'small',
|
||||
jog_step: cookie.get_bool('jog-step'),
|
||||
jog_adjust: parseInt(cookie.get('jog-adjust', 2)),
|
||||
jog_incr: localStorage.getItem("jog_incr") || "small",
|
||||
jog_step: cookie.get_bool("jog-step"),
|
||||
jog_adjust: parseInt(cookie.get("jog-adjust", 2)),
|
||||
deleteGCode: false,
|
||||
tab: 'auto',
|
||||
tab: "auto",
|
||||
ask_home: true,
|
||||
showGcodeMessage: false
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
'axis-control': require('./axis-control'),
|
||||
'path-viewer': require('./path-viewer'),
|
||||
'gcode-viewer': require('./gcode-viewer')
|
||||
"axis-control": require("./axis-control"),
|
||||
"path-viewer": require("./path-viewer"),
|
||||
"gcode-viewer": require("./gcode-viewer")
|
||||
},
|
||||
|
||||
watch: {
|
||||
@@ -55,31 +55,31 @@ module.exports = {
|
||||
localStorage.setItem("jog_incr", value);
|
||||
},
|
||||
|
||||
'state.metric': {
|
||||
"state.metric": {
|
||||
handler: function (metric) {
|
||||
this.mach_units = metric
|
||||
? 'METRIC'
|
||||
: 'IMPERIAL';
|
||||
? "METRIC"
|
||||
: "IMPERIAL";
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
'state.line': function () {
|
||||
if (this.mach_state != 'HOMING') {
|
||||
this.$broadcast('gcode-line', this.state.line);
|
||||
"state.line": function () {
|
||||
if (this.mach_state != "HOMING") {
|
||||
this.$broadcast("gcode-line", this.state.line);
|
||||
}
|
||||
},
|
||||
|
||||
'state.selected_time': function () {
|
||||
"state.selected_time": function () {
|
||||
this.load();
|
||||
},
|
||||
|
||||
jog_step: function () {
|
||||
cookie.set_bool('jog-step', this.jog_step);
|
||||
cookie.set_bool("jog-step", this.jog_step);
|
||||
},
|
||||
|
||||
jog_adjust: function () {
|
||||
cookie.set('jog-adjust', this.jog_adjust);
|
||||
cookie.set("jog-adjust", this.jog_adjust);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -99,63 +99,61 @@ module.exports = {
|
||||
},
|
||||
|
||||
mach_state: function () {
|
||||
var cycle = this.state.cycle;
|
||||
var state = this.state.xx;
|
||||
const cycle = this.state.cycle;
|
||||
const state = this.state.xx;
|
||||
|
||||
if (typeof cycle != 'undefined' && state != 'ESTOPPED' &&
|
||||
(cycle == 'jogging' || cycle == 'homing')) {
|
||||
if (state != "ESTOPPED" && (cycle == "jogging" || cycle == "homing")) {
|
||||
return cycle.toUpperCase();
|
||||
}
|
||||
|
||||
return state || ''
|
||||
return state || "";
|
||||
},
|
||||
|
||||
pause_reason: function () {
|
||||
return this.state.pr
|
||||
return this.state.pr;
|
||||
},
|
||||
|
||||
is_running: function () {
|
||||
return this.mach_state == 'RUNNING' || this.mach_state == 'HOMING';
|
||||
return this.mach_state == "RUNNING" || this.mach_state == "HOMING";
|
||||
},
|
||||
|
||||
is_stopping: function () {
|
||||
return this.mach_state == 'STOPPING'
|
||||
return this.mach_state == "STOPPING";
|
||||
},
|
||||
|
||||
is_holding: function () {
|
||||
return this.mach_state == 'HOLDING'
|
||||
return this.mach_state == "HOLDING";
|
||||
},
|
||||
|
||||
is_ready: function () {
|
||||
return this.mach_state == 'READY'
|
||||
return this.mach_state == "READY";
|
||||
},
|
||||
|
||||
is_idle: function () {
|
||||
return this.state.cycle == 'idle'
|
||||
return this.state.cycle == "idle";
|
||||
},
|
||||
|
||||
is_paused: function () {
|
||||
return this.is_holding &&
|
||||
(this.pause_reason == 'User pause' ||
|
||||
this.pause_reason == 'Program pause')
|
||||
return this.is_holding && (this.pause_reason == "User pause" || this.pause_reason == "Program pause");
|
||||
},
|
||||
|
||||
can_mdi: function () {
|
||||
return this.is_idle || this.state.cycle == 'mdi'
|
||||
return this.is_idle || this.state.cycle == "mdi";
|
||||
},
|
||||
|
||||
can_set_axis: function () {
|
||||
return this.is_idle
|
||||
return this.is_idle;
|
||||
|
||||
// TODO allow setting axis position during pause
|
||||
return this.is_idle || this.is_paused
|
||||
// return this.is_idle || this.is_paused;
|
||||
},
|
||||
|
||||
message: function () {
|
||||
if (this.mach_state == 'ESTOPPED') {
|
||||
if (this.mach_state == "ESTOPPED") {
|
||||
return this.state.er;
|
||||
}
|
||||
|
||||
if (this.mach_state == 'HOLDING') {
|
||||
if (this.mach_state == "HOLDING") {
|
||||
return this.state.pr;
|
||||
}
|
||||
|
||||
@@ -163,15 +161,15 @@ module.exports = {
|
||||
return this.state.messages.slice(-1)[0].text;
|
||||
}
|
||||
|
||||
return '';
|
||||
return "";
|
||||
},
|
||||
|
||||
highlight_state: function () {
|
||||
return this.mach_state == 'ESTOPPED' || this.mach_state == 'HOLDING';
|
||||
return this.mach_state == "ESTOPPED" || this.mach_state == "HOLDING";
|
||||
},
|
||||
|
||||
plan_time: function () {
|
||||
return this.state.plan_time
|
||||
return this.state.plan_time;
|
||||
},
|
||||
|
||||
plan_time_remaining: function () {
|
||||
@@ -179,16 +177,16 @@ module.exports = {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.toolpath.time - this.plan_time
|
||||
return this.toolpath.time - this.plan_time;
|
||||
},
|
||||
|
||||
eta: function () {
|
||||
if (this.mach_state != 'RUNNING') {
|
||||
return '';
|
||||
if (this.mach_state != "RUNNING") {
|
||||
return "";
|
||||
}
|
||||
|
||||
var remaining = this.plan_time_remaining;
|
||||
var d = new Date();
|
||||
const remaining = this.plan_time_remaining;
|
||||
const d = new Date();
|
||||
d.setSeconds(d.getSeconds() + remaining);
|
||||
return d.toLocaleString();
|
||||
},
|
||||
@@ -198,16 +196,16 @@ module.exports = {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var p = this.plan_time / this.toolpath.time;
|
||||
return p < 1 ? p : 1;
|
||||
const p = this.plan_time / this.toolpath.time;
|
||||
return Math.max(1, p);
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
jog: function (axis, power) {
|
||||
var data = { ts: new Date().getTime() };
|
||||
const data = { ts: new Date().getTime() };
|
||||
data[axis] = power;
|
||||
api.put('jog', data);
|
||||
api.put("jog", data);
|
||||
},
|
||||
|
||||
back2zero: function (axis0, axis1) {
|
||||
@@ -243,19 +241,19 @@ module.exports = {
|
||||
|
||||
methods: {
|
||||
getJogIncrStyle(value) {
|
||||
const weight = `font-weight:${this.jog_incr === value ? 'bold' : 'normal'}`;
|
||||
const weight = `font-weight:${this.jog_incr === value ? "bold" : "normal"}`;
|
||||
const color = this.jog_incr === value ? "color:#0078e7" : "";
|
||||
|
||||
return [weight, color].join(';');
|
||||
return [weight, color].join(";");
|
||||
},
|
||||
|
||||
jog_fn: function (x_jog, y_jog, z_jog, a_jog) {
|
||||
const amount = this.jog_incr_amounts[this.display_units][this.jog_incr];
|
||||
|
||||
var xcmd = "X" + x_jog * amount;
|
||||
var ycmd = "Y" + y_jog * amount;
|
||||
var zcmd = "Z" + z_jog * amount;
|
||||
var acmd = "A" + a_jog * amount;
|
||||
const xcmd = `X${x_jog * amount}`;
|
||||
const ycmd = `Y${y_jog * amount}`;
|
||||
const zcmd = `Z${z_jog * amount}`;
|
||||
const acmd = `A${a_jog * amount}`;
|
||||
|
||||
this.send(`
|
||||
G91
|
||||
@@ -265,12 +263,12 @@ module.exports = {
|
||||
},
|
||||
|
||||
send: function (msg) {
|
||||
this.$dispatch('send', msg)
|
||||
this.$dispatch("send", msg);
|
||||
},
|
||||
|
||||
load: function () {
|
||||
var file_time = this.state.selected_time;
|
||||
var file = this.state.selected;
|
||||
const file_time = this.state.selected_time;
|
||||
const file = this.state.selected;
|
||||
if (this.last_file == file && this.last_file_time == file_time) {
|
||||
return;
|
||||
}
|
||||
@@ -278,8 +276,8 @@ module.exports = {
|
||||
this.last_file = file;
|
||||
this.last_file_time = file_time;
|
||||
|
||||
this.$broadcast('gcode-load', file);
|
||||
this.$broadcast('gcode-line', this.state.line);
|
||||
this.$broadcast("gcode-load", file);
|
||||
this.$broadcast("gcode-line", this.state.line);
|
||||
this.toolpath_progress = 0;
|
||||
this.load_toolpath(file, file_time);
|
||||
},
|
||||
@@ -297,8 +295,8 @@ module.exports = {
|
||||
const toolpath = await api.get(`path/${file}`);
|
||||
this.toolpath_progress = toolpath.progress;
|
||||
|
||||
if (toolpath.progress === 1 || typeof toolpath.progress == 'undefined') {
|
||||
this.showGcodeMessage = false
|
||||
if (toolpath.progress === 1 || typeof toolpath.progress == "undefined") {
|
||||
this.showGcodeMessage = false;
|
||||
|
||||
if (toolpath.bounds) {
|
||||
toolpath.filename = file;
|
||||
@@ -306,9 +304,9 @@ module.exports = {
|
||||
this.toolpath = toolpath;
|
||||
|
||||
const state = this.$root.state;
|
||||
for (let axis of 'xyzabc') {
|
||||
Vue.set(state, 'path_min_' + axis, toolpath.bounds.min[axis]);
|
||||
Vue.set(state, 'path_max_' + axis, toolpath.bounds.max[axis]);
|
||||
for (const axis of "xyzabc") {
|
||||
Vue.set(state, `path_min_${axis}`, toolpath.bounds.min[axis]);
|
||||
Vue.set(state, `path_max_${axis}`, toolpath.bounds.max[axis]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,13 +320,13 @@ module.exports = {
|
||||
this.history.unshift(this.mdi);
|
||||
}
|
||||
|
||||
this.mdi = '';
|
||||
this.mdi = "";
|
||||
},
|
||||
|
||||
mdi_start_pause: function () {
|
||||
if (this.state.xx == 'RUNNING') {
|
||||
if (this.state.xx == "RUNNING") {
|
||||
this.pause();
|
||||
} else if (this.state.xx == 'STOPPING' || this.state.xx == 'HOLDING') {
|
||||
} else if (this.state.xx == "STOPPING" || this.state.xx == "HOLDING") {
|
||||
this.unpause();
|
||||
} else {
|
||||
this.submit_mdi();
|
||||
@@ -339,11 +337,11 @@ module.exports = {
|
||||
this.mdi = this.history[index];
|
||||
},
|
||||
|
||||
open: function (e) {
|
||||
open: function () {
|
||||
// If we don't reset the form the browser may cache file if name is same
|
||||
// even if contents have changed
|
||||
$('.gcode-file-input')[0].reset();
|
||||
$('.gcode-file-input input').click();
|
||||
$(".gcode-file-input")[0].reset();
|
||||
$(".gcode-file-input input").click();
|
||||
},
|
||||
|
||||
upload: async function (e) {
|
||||
@@ -371,42 +369,42 @@ module.exports = {
|
||||
file,
|
||||
onComplete: () => {
|
||||
this.last_file_time = undefined; // Force reload
|
||||
this.$broadcast('gcode-reload', file.name);
|
||||
this.$broadcast("gcode-reload", file.name);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
delete_current: function () {
|
||||
if (this.state.selected) {
|
||||
api.delete('file/' + this.state.selected);
|
||||
api.delete(`file/${this.state.selected}`);
|
||||
}
|
||||
|
||||
this.deleteGCode = false;
|
||||
},
|
||||
|
||||
delete_all: function () {
|
||||
api.delete('file');
|
||||
api.delete("file");
|
||||
this.deleteGCode = false;
|
||||
},
|
||||
|
||||
home: function (axis) {
|
||||
this.ask_home = false;
|
||||
|
||||
if (typeof axis == 'undefined') {
|
||||
api.put('home');
|
||||
} else if (this[axis].homingMode != 'manual') {
|
||||
api.put('home/' + axis);
|
||||
if (typeof axis == "undefined") {
|
||||
api.put("home");
|
||||
} else if (this[axis].homingMode != "manual") {
|
||||
api.put(`home/${axis}`);
|
||||
} else {
|
||||
SvelteComponents.showDialog("ManualHomeAxis", { axis });
|
||||
}
|
||||
},
|
||||
|
||||
set_home: function (axis, position) {
|
||||
api.put('home/' + axis + '/set', { position: parseFloat(position) });
|
||||
api.put(`home/${axis}/set`, { position: parseFloat(position) });
|
||||
},
|
||||
|
||||
unhome: function (axis) {
|
||||
api.put('home/' + axis + '/clear');
|
||||
api.put(`home/${axis}/clear`);
|
||||
},
|
||||
|
||||
show_set_position: function (axis) {
|
||||
@@ -422,11 +420,11 @@ module.exports = {
|
||||
},
|
||||
|
||||
set_position: function (axis, position) {
|
||||
api.put('position/' + axis, { 'position': parseFloat(position) });
|
||||
api.put(`position/${axis}`, { "position": parseFloat(position) });
|
||||
},
|
||||
|
||||
zero_all: function () {
|
||||
for (var axis of 'xyzabc') {
|
||||
for (const axis of "xyzabc") {
|
||||
if (this[axis].enabled) {
|
||||
this.zero(axis);
|
||||
}
|
||||
@@ -434,7 +432,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
zero: function (axis) {
|
||||
if (typeof axis == 'undefined') {
|
||||
if (typeof axis == "undefined") {
|
||||
this.zero_all();
|
||||
} else {
|
||||
this.set_position(axis, 0);
|
||||
@@ -442,9 +440,9 @@ module.exports = {
|
||||
},
|
||||
|
||||
start_pause: function () {
|
||||
if (this.state.xx == 'RUNNING') {
|
||||
if (this.state.xx == "RUNNING") {
|
||||
this.pause();
|
||||
} else if (this.state.xx == 'STOPPING' || this.state.xx == 'HOLDING') {
|
||||
} else if (this.state.xx == "STOPPING" || this.state.xx == "HOLDING") {
|
||||
this.unpause();
|
||||
} else {
|
||||
this.start();
|
||||
@@ -452,45 +450,45 @@ module.exports = {
|
||||
},
|
||||
|
||||
start: function () {
|
||||
api.put('start')
|
||||
api.put("start");
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
api.put('pause')
|
||||
api.put("pause");
|
||||
},
|
||||
|
||||
unpause: function () {
|
||||
api.put('unpause')
|
||||
api.put("unpause");
|
||||
},
|
||||
|
||||
optional_pause: function () {
|
||||
api.put('pause/optional')
|
||||
api.put("pause/optional");
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
api.put('stop')
|
||||
api.put("stop");
|
||||
},
|
||||
|
||||
step: function () {
|
||||
api.put('step')
|
||||
api.put("step");
|
||||
},
|
||||
|
||||
override_feed: function () {
|
||||
api.put('override/feed/' + this.feed_override)
|
||||
api.put(`override/feed/${this.feed_override}`);
|
||||
},
|
||||
|
||||
override_speed: function () {
|
||||
api.put('override/speed/' + this.speed_override)
|
||||
api.put(`override/speed/${this.speed_override}`);
|
||||
},
|
||||
|
||||
current: function (axis, value) {
|
||||
var x = value / 32.0;
|
||||
if (this.state[axis + 'pl'] == x) {
|
||||
const x = value / 32.0;
|
||||
if (this.state[`${axis}pl`] == x) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = {};
|
||||
data[axis + 'pl'] = x;
|
||||
const data = {};
|
||||
data[`${axis}pl`] = x;
|
||||
this.send(JSON.stringify(data));
|
||||
},
|
||||
|
||||
@@ -499,5 +497,5 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
mixins: [require('./axis-vars')]
|
||||
}
|
||||
mixins: [require("./axis-vars")]
|
||||
};
|
||||
|
||||
@@ -1,69 +1,49 @@
|
||||
/******************************************************************************\
|
||||
|
||||
Copyright 2018. Buildbotics LLC
|
||||
All Rights Reserved.
|
||||
|
||||
For information regarding this software email:
|
||||
Joseph Coffland
|
||||
joseph@buildbotics.com
|
||||
|
||||
This software is free software: you clan redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation, either version 2.1 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This software is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the C! library. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = function (prefix) {
|
||||
if (typeof prefix == 'undefined') prefix = '';
|
||||
if (typeof prefix == "undefined") {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
var cookie = {
|
||||
const cookie = {
|
||||
get: function (name, defaultValue) {
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
name = prefix + name + '=';
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const ca = decodedCookie.split(";");
|
||||
name = `${prefix + name}=`;
|
||||
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1);
|
||||
if (!c.indexOf(name)) return c.substring(name.length, c.length);
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == " ") {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (!c.indexOf(name)) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
|
||||
set: function (name, value, days) {
|
||||
var offset = 2147483647; // Max value
|
||||
if (typeof days != 'undefined') offset = days * 24 * 60 * 60 * 1000;
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + offset);
|
||||
var expires = 'expires=' + d.toUTCString();
|
||||
document.cookie = prefix + name + '=' + value + ';' + expires + ';path=/';
|
||||
},
|
||||
let offset = 2147483647; // Max value
|
||||
if (typeof days != "undefined") {
|
||||
offset = days * 24 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + offset);
|
||||
const expires = `expires=${d.toUTCString()}`;
|
||||
document.cookie = `${prefix}${name}=${value};${expires};path=/`;
|
||||
},
|
||||
|
||||
set_bool: function (name, value) {
|
||||
cookie.set(name, value ? 'true' : 'false');
|
||||
cookie.set(name, value ? "true" : "false");
|
||||
},
|
||||
|
||||
|
||||
get_bool: function (name, defaultValue) {
|
||||
return cookie.get(name, defaultValue ? 'true' : 'false') == 'true';
|
||||
}
|
||||
return cookie.get(name, defaultValue ? "true" : "false") == "true";
|
||||
}
|
||||
};
|
||||
|
||||
return cookie;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,97 +1,76 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
var api = require('./api');
|
||||
|
||||
|
||||
var entityMap = {
|
||||
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
||||
'/': '/', '`': '`', '=': '='}
|
||||
"use strict";
|
||||
|
||||
const entityMap = {
|
||||
"&": "&", "<": "<", ">": ">", '"': """, "'": "'",
|
||||
"/": "/", "`": "`", "=": "="};
|
||||
|
||||
function escapeHTML(s) {
|
||||
return s.replace(/[&<>"'`=\/]/g, function (c) {return entityMap[c]})
|
||||
return s.replace(/[&<>"'`=\\/]/g, function (c) {
|
||||
return entityMap[c];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
template: '#gcode-viewer-template',
|
||||
|
||||
template: "#gcode-viewer-template",
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
empty: true,
|
||||
file: '',
|
||||
file: "",
|
||||
line: -1,
|
||||
scrolling: false
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
'gcode-load': function (file) {this.load(file)},
|
||||
'gcode-clear': function () {this.clear()},
|
||||
'gcode-reload': function (file) {this.reload(file)},
|
||||
'gcode-line': function (line) {this.update_line(line)}
|
||||
"gcode-load": function (file) {
|
||||
this.load(file);
|
||||
},
|
||||
"gcode-clear": function () {
|
||||
this.clear();
|
||||
},
|
||||
"gcode-reload": function (file) {
|
||||
this.reload(file);
|
||||
},
|
||||
"gcode-line": function (line) {
|
||||
this.update_line(line);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ready: function () {
|
||||
this.clusterize = new Clusterize({
|
||||
rows: [],
|
||||
scrollElem: $(this.$el).find('.clusterize-scroll')[0],
|
||||
contentElem: $(this.$el).find('.clusterize-content')[0],
|
||||
no_data_text: 'GCode view...',
|
||||
scrollElem: $(this.$el).find(".clusterize-scroll")[0],
|
||||
contentElem: $(this.$el).find(".clusterize-content")[0],
|
||||
no_data_text: "GCode view...",
|
||||
callbacks: {clusterChanged: this.highlight}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
attached: function () {
|
||||
if (typeof this.clusterize != 'undefined')
|
||||
if (typeof this.clusterize != "undefined") {
|
||||
this.clusterize.refresh(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
load: async function(file) {
|
||||
if (file == this.file) return;
|
||||
if (file == this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
this.file = file;
|
||||
|
||||
if (!file) return;
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/file/${file}?${Math.random()}`);
|
||||
const text = await response.text();
|
||||
|
||||
if (text.length > 20e6) {
|
||||
this.clusterize.update(['File is large - gcode view disabled']);
|
||||
this.clusterize.update(["File is large - gcode view disabled"]);
|
||||
} else {
|
||||
const lines = escapeHTML(text.trimRight())
|
||||
.split(/[\r\n]/)
|
||||
@@ -105,64 +84,77 @@ module.exports = {
|
||||
Vue.nextTick(this.update_line);
|
||||
},
|
||||
|
||||
|
||||
clear: function () {
|
||||
this.empty = true;
|
||||
this.file = '';
|
||||
this.file = "";
|
||||
this.line = -1;
|
||||
this.clusterize.clear();
|
||||
},
|
||||
|
||||
|
||||
reload: function (file) {
|
||||
if (file != this.file) return;
|
||||
if (file != this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
this.load(file);
|
||||
},
|
||||
|
||||
|
||||
highlight: function () {
|
||||
var e = $(this.$el).find('.highlight');
|
||||
if (e.length) e.removeClass('highlight');
|
||||
let e = $(this.$el).find(".highlight");
|
||||
if (e.length) {
|
||||
e.removeClass("highlight");
|
||||
}
|
||||
|
||||
e = $(this.$el).find('.ln' + this.line);
|
||||
if (e.length) e.addClass('highlight');
|
||||
e = $(this.$el).find(`.ln${this.line}`);
|
||||
if (e.length) {
|
||||
e.addClass("highlight");
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
update_line: function(line) {
|
||||
if (typeof line != 'undefined') {
|
||||
if (this.line == line) return;
|
||||
if (typeof line != "undefined") {
|
||||
if (this.line == line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.line = line;
|
||||
} else {
|
||||
line = this.line;
|
||||
}
|
||||
|
||||
} else line = this.line;
|
||||
const totalLines = this.clusterize.getRowsAmount();
|
||||
|
||||
var totalLines = this.clusterize.getRowsAmount();
|
||||
if (line <= 0) {
|
||||
line = 1;
|
||||
}
|
||||
|
||||
if (line <= 0) line = 1;
|
||||
if (totalLines < line) line = totalLines;
|
||||
if (totalLines < line) {
|
||||
line = totalLines;
|
||||
}
|
||||
|
||||
var e = $(this.$el).find('.clusterize-scroll');
|
||||
const e = $(this.$el).find(".clusterize-scroll");
|
||||
|
||||
var lineHeight = e[0].scrollHeight / totalLines;
|
||||
var linesPerPage = Math.floor(e[0].clientHeight / lineHeight);
|
||||
var current = e[0].scrollTop / lineHeight;
|
||||
var target = line - 1 - Math.floor(linesPerPage / 2);
|
||||
const lineHeight = e[0].scrollHeight / totalLines;
|
||||
const linesPerPage = Math.floor(e[0].clientHeight / lineHeight);
|
||||
const current = e[0].scrollTop / lineHeight;
|
||||
const target = line - 1 - Math.floor(linesPerPage / 2);
|
||||
|
||||
// Update scroll position
|
||||
if (!this.scrolling) {
|
||||
if (target < current - 20 || current + 20 < target)
|
||||
if (target < current - 20 || current + 20 < target) {
|
||||
e[0].scrollTop = target * lineHeight;
|
||||
|
||||
else {
|
||||
} else {
|
||||
this.scrolling = true;
|
||||
e.animate({scrollTop: target * lineHeight}, {
|
||||
complete: function () {this.scrolling = false}.bind(this)
|
||||
})
|
||||
complete: function () {
|
||||
this.scrolling = false;
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Vue.nextTick(this.highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,65 +1,44 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
var modbus = require('./modbus.js');
|
||||
"use strict";
|
||||
|
||||
const modbus = require("./modbus.js");
|
||||
|
||||
module.exports = {
|
||||
template: '#indicators-template',
|
||||
props: ['state'],
|
||||
|
||||
template: "#indicators-template",
|
||||
props: ["state"],
|
||||
|
||||
computed: {
|
||||
modbus_status: function () {return modbus.status_to_string(this.state.mx)},
|
||||
|
||||
modbus_status: function () {
|
||||
return modbus.status_to_string(this.state.mx);
|
||||
},
|
||||
|
||||
sense_error: function () {
|
||||
var error = '';
|
||||
let error = "";
|
||||
|
||||
if (this.state.motor_voltage_sense_error) error += 'Motor voltage\n';
|
||||
if (this.state.motor_current_sense_error) error += 'Motor current\n';
|
||||
if (this.state.load1_sense_error) error += 'Load 1\n';
|
||||
if (this.state.load2_sense_error) error += 'Load 2\n';
|
||||
if (this.state.vdd_current_sense_error) error += 'Vdd current\n';
|
||||
if (this.state.motor_voltage_sense_error) {
|
||||
error += "Motor voltage\n";
|
||||
}
|
||||
if (this.state.motor_current_sense_error) {
|
||||
error += "Motor current\n";
|
||||
}
|
||||
if (this.state.load1_sense_error) {
|
||||
error += "Load 1\n";
|
||||
}
|
||||
if (this.state.load2_sense_error) {
|
||||
error += "Load 2\n";
|
||||
}
|
||||
if (this.state.vdd_current_sense_error) {
|
||||
error += "Vdd current\n";
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
is_motor_enabled: function (motor) {
|
||||
return typeof this.state[motor + 'me'] != 'undefined' &&
|
||||
this.state[motor + 'me'];
|
||||
return typeof this.state[`${motor}me`] != "undefined" && this.state[`${motor}me`];
|
||||
},
|
||||
|
||||
|
||||
get_min_pin: function (motor) {
|
||||
switch (motor) {
|
||||
case 0: return 3;
|
||||
@@ -69,7 +48,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get_max_pin: function (motor) {
|
||||
switch (motor) {
|
||||
case 0: return 4;
|
||||
@@ -79,29 +57,38 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
motor_fault_class: function (motor, bit) {
|
||||
if (typeof motor == 'undefined') {
|
||||
var status = this.state['fa'];
|
||||
if (typeof status == 'undefined') return 'fa-question';
|
||||
return 'fa-thumbs-' + (status ? 'down error' : 'up success')
|
||||
if (typeof motor == "undefined") {
|
||||
const status = this.state["fa"];
|
||||
|
||||
if (typeof status == "undefined") {
|
||||
return "fa-question";
|
||||
}
|
||||
|
||||
var flags = this.state[motor + 'df'];
|
||||
if (typeof flags == 'undefined') return 'fa-question';
|
||||
return (flags & (1 << bit)) ? 'fa-thumbs-down error' :
|
||||
'fa-thumbs-up success';
|
||||
return `fa-thumbs-${status ? "down error" : "up success"}`;
|
||||
}
|
||||
|
||||
const flags = this.state[`${motor}df`];
|
||||
|
||||
if (typeof flags == "undefined") {
|
||||
return "fa-question";
|
||||
}
|
||||
|
||||
return (flags & (1 << bit)) ? "fa-thumbs-down error" :
|
||||
"fa-thumbs-up success";
|
||||
},
|
||||
|
||||
|
||||
motor_reset: function (motor) {
|
||||
if (typeof motor == 'undefined') {
|
||||
var cmd = '';
|
||||
for (var i = 0; i < 4; i++)
|
||||
cmd += '\\$' + i + 'df=0\n';
|
||||
this.$dispatch('send', cmd);
|
||||
if (typeof motor == "undefined") {
|
||||
let cmd = "";
|
||||
for (let i = 0; i < 4; i++) {
|
||||
cmd += `\\$${i}df=0\n`;
|
||||
}
|
||||
|
||||
} else this.$dispatch('send', '\\$' + motor + 'df=0');
|
||||
this.$dispatch("send", cmd);
|
||||
} else {
|
||||
this.$dispatch("send", `\\$${motor}df=0`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,177 +1,155 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: "#io-indicator-template",
|
||||
props: ['name', 'state'],
|
||||
|
||||
props: ["name", "state"],
|
||||
|
||||
computed: {
|
||||
klass: function () {
|
||||
if (this.name == 'min-switch-0') return this.get_motor_min_class(0);
|
||||
if (this.name == 'min-switch-1') return this.get_motor_min_class(1);
|
||||
if (this.name == 'min-switch-2') return this.get_motor_min_class(2);
|
||||
if (this.name == 'min-switch-3') return this.get_motor_min_class(3);
|
||||
if (this.name == 'max-switch-0') return this.get_motor_max_class(0);
|
||||
if (this.name == 'max-switch-1') return this.get_motor_max_class(1);
|
||||
if (this.name == 'max-switch-2') return this.get_motor_max_class(2);
|
||||
if (this.name == 'max-switch-3') return this.get_motor_max_class(3);
|
||||
if (this.name == 'estop') return this.get_input_class('ew', 'et');
|
||||
if (this.name == 'probe') return this.get_input_class('pw', 'pt');
|
||||
if (this.name == 'load-1') return this.get_output_class('1');
|
||||
if (this.name == 'load-2') return this.get_output_class('2');
|
||||
if (this.name == 'fault') return this.get_output_class('f');
|
||||
if (this.name == 'tool-enable-mode') return this.get_output_class('e');
|
||||
if (this.name == 'tool-direction-mode') return this.get_output_class('d');
|
||||
},
|
||||
|
||||
|
||||
tooltip: function () {
|
||||
if (this.name == 'min-switch-0') return this.get_motor_min_tooltip(0);
|
||||
if (this.name == 'min-switch-1') return this.get_motor_min_tooltip(1);
|
||||
if (this.name == 'min-switch-2') return this.get_motor_min_tooltip(2);
|
||||
if (this.name == 'min-switch-3') return this.get_motor_min_tooltip(3);
|
||||
if (this.name == 'max-switch-0') return this.get_motor_max_tooltip(0);
|
||||
if (this.name == 'max-switch-1') return this.get_motor_max_tooltip(1);
|
||||
if (this.name == 'max-switch-2') return this.get_motor_max_tooltip(2);
|
||||
if (this.name == 'max-switch-3') return this.get_motor_max_tooltip(3);
|
||||
if (this.name == 'estop') return this.get_input_tooltip('ew', 'et');
|
||||
if (this.name == 'probe') return this.get_input_tooltip('pw', 'pt');
|
||||
if (this.name == 'load-1') return this.get_output_tooltip('1');
|
||||
if (this.name == 'load-2') return this.get_output_tooltip('2');
|
||||
if (this.name == 'fault') return this.get_output_tooltip('f');
|
||||
if (this.name == 'tool-direction-mode')
|
||||
return this.get_output_tooltip('d');
|
||||
if (this.name == 'tool-enable-mode')
|
||||
return this.get_output_tooltip('e');
|
||||
switch (this.name) {
|
||||
case "min-switch-0": return this.get_motor_min_class(0);
|
||||
case "min-switch-1": return this.get_motor_min_class(1);
|
||||
case "min-switch-2": return this.get_motor_min_class(2);
|
||||
case "min-switch-3": return this.get_motor_min_class(3);
|
||||
case "max-switch-0": return this.get_motor_max_class(0);
|
||||
case "max-switch-1": return this.get_motor_max_class(1);
|
||||
case "max-switch-2": return this.get_motor_max_class(2);
|
||||
case "max-switch-3": return this.get_motor_max_class(3);
|
||||
case "estop": return this.get_input_class("ew", "et");
|
||||
case "probe": return this.get_input_class("pw", "pt");
|
||||
case "load-1": return this.get_output_class("1");
|
||||
case "load-2": return this.get_output_class("2");
|
||||
case "fault": return this.get_output_class("f");
|
||||
case "tool-enable-mode": return this.get_output_class("e");
|
||||
case "tool-direction-mode": return this.get_output_class("d");
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: function () {
|
||||
switch (this.name) {
|
||||
case "min-switch-0": return this.get_motor_min_tooltip(0);
|
||||
case "min-switch-1": return this.get_motor_min_tooltip(1);
|
||||
case "min-switch-2": return this.get_motor_min_tooltip(2);
|
||||
case "min-switch-3": return this.get_motor_min_tooltip(3);
|
||||
case "max-switch-0": return this.get_motor_max_tooltip(0);
|
||||
case "max-switch-1": return this.get_motor_max_tooltip(1);
|
||||
case "max-switch-2": return this.get_motor_max_tooltip(2);
|
||||
case "max-switch-3": return this.get_motor_max_tooltip(3);
|
||||
case "estop": return this.get_input_tooltip("ew", "et");
|
||||
case "probe": return this.get_input_tooltip("pw", "pt");
|
||||
case "load-1": return this.get_output_tooltip("1");
|
||||
case "load-2": return this.get_output_tooltip("2");
|
||||
case "fault": return this.get_output_tooltip("f");
|
||||
case "tool-direction-mode": return this.get_output_tooltip("d");
|
||||
case "tool-enable-mode": return this.get_output_tooltip("e");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
get_io_state_class: function (active, state) {
|
||||
if (typeof active == 'undefined' || typeof state == 'undefined')
|
||||
return 'fa-exclamation-triangle warn';
|
||||
if (typeof active == "undefined" || typeof state == "undefined") {
|
||||
return "fa-exclamation-triangle warn";
|
||||
}
|
||||
|
||||
if (state == 2) return 'fa-circle-o';
|
||||
if (state == 2) {
|
||||
return "fa-circle-o";
|
||||
}
|
||||
|
||||
return (state ? 'fa-plus-circle' : 'fa-minus-circle') + ' ' +
|
||||
(active ? 'active' : 'inactive');
|
||||
const icon = state ? "fa-plus-circle" : "fa-minus-circle";
|
||||
return `${icon} ${active ? "active" : "inactive"}`;
|
||||
},
|
||||
|
||||
|
||||
get_input_active: function (stateCode, typeCode) {
|
||||
var type = this.state[typeCode];
|
||||
var state = this.state[stateCode];
|
||||
const type = this.state[typeCode];
|
||||
const state = this.state[stateCode];
|
||||
|
||||
if (type == 1) return !state; // Normally open
|
||||
else if (type == 2) return state; // Normally closed
|
||||
if (type == 1) {
|
||||
return !state; // Normally open
|
||||
} else if (type == 2) {
|
||||
return state; // Normally closed
|
||||
}
|
||||
|
||||
return false
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
get_input_class: function (stateCode, typeCode) {
|
||||
return this.get_io_state_class(this.get_input_active(stateCode, typeCode),
|
||||
this.state[stateCode]);
|
||||
return this.get_io_state_class(this.get_input_active(stateCode, typeCode), this.state[stateCode]);
|
||||
},
|
||||
|
||||
|
||||
get_output_class: function (output) {
|
||||
return this.get_io_state_class(this.state[output + 'oa'],
|
||||
this.state[output + 'os']);
|
||||
return this.get_io_state_class(this.state[`${output}oa`], this.state[`${output}os`]);
|
||||
},
|
||||
|
||||
|
||||
get_motor_min_class: function (motor) {
|
||||
return this.get_input_class(motor + 'lw', motor + 'ls');
|
||||
return this.get_input_class(`${motor}lw`, `${motor}ls`);
|
||||
},
|
||||
|
||||
|
||||
get_motor_max_class: function (motor) {
|
||||
return this.get_input_class(motor + 'xw', motor + 'xs');
|
||||
return this.get_input_class(`${motor}xw`, `${motor}xs`);
|
||||
},
|
||||
|
||||
|
||||
get_tooltip: function (mode, active, state) {
|
||||
if (typeof mode == 'undefined' || typeof active == 'undefined' ||
|
||||
typeof state == 'undefined') return 'Invalid';
|
||||
if (typeof mode == "undefined" || typeof active == "undefined" || typeof state == "undefined") {
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
if (state == 0) state = 'Lo/Gnd';
|
||||
else if (state == 1) state = 'Hi/+3.3v';
|
||||
else if (state == 2) state = 'Tristated';
|
||||
else return 'Invalid';
|
||||
if (state == 0) {
|
||||
state = "Lo/Gnd";
|
||||
} else if (state == 1) {
|
||||
state = "Hi/+3.3v";
|
||||
} else if (state == 2) {
|
||||
state = "Tristated";
|
||||
} else {
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
return 'Mode: ' + mode + '\nActive: ' + (active ? 'True' : 'False') +
|
||||
'\nLevel: ' + state;
|
||||
return `Mode: ${mode}\nActive: ${active ? "True" : "False"}\nLevel: ${state}`;
|
||||
},
|
||||
|
||||
|
||||
get_input_tooltip: function (stateCode, typeCode) {
|
||||
var type = this.state[typeCode];
|
||||
if (type == 0) return 'Disabled';
|
||||
else if (type == 1) type = 'Normally open';
|
||||
else if (type == 2) type = 'Normally closed';
|
||||
let type = this.state[typeCode];
|
||||
if (type == 0) {
|
||||
return "Disabled";
|
||||
} else if (type == 1) {
|
||||
type = "Normally open";
|
||||
} else if (type == 2) {
|
||||
type = "Normally closed";
|
||||
}
|
||||
|
||||
var active = this.get_input_active(stateCode, typeCode);
|
||||
var state = this.state[stateCode];
|
||||
const active = this.get_input_active(stateCode, typeCode);
|
||||
const state = this.state[stateCode];
|
||||
|
||||
return this.get_tooltip(type, active, state);
|
||||
},
|
||||
|
||||
|
||||
get_output_tooltip: function (output) {
|
||||
var mode = this.state[output + 'om'];
|
||||
if (mode == 0) return 'Disabled';
|
||||
else if (mode == 1) mode = 'Lo/Hi';
|
||||
else if (mode == 2) mode = 'Hi/Lo';
|
||||
else if (mode == 3) mode = 'Tri/Lo';
|
||||
else if (mode == 4) mode = 'Tri/Hi';
|
||||
else if (mode == 5) mode = 'Lo/Tri';
|
||||
else if (mode == 6) mode = 'Hi/Tri';
|
||||
else mode = undefined;
|
||||
let mode = this.state[`${output}om`];
|
||||
|
||||
var active = this.state[output + 'oa'];
|
||||
var state = this.state[output + 'os'];
|
||||
switch (mode) {
|
||||
case 0: return "Disabled";
|
||||
case 1: mode = "Lo/Hi"; break;
|
||||
case 2: mode = "Hi/Lo"; break;
|
||||
case 3: mode = "Tri/Lo"; break;
|
||||
case 4: mode = "Tri/Hi"; break;
|
||||
case 5: mode = "Lo/Tri"; break;
|
||||
case 6: mode = "Hi/Tri"; break;
|
||||
default:
|
||||
mode = undefined;
|
||||
}
|
||||
|
||||
const active = this.state[`${output}oa`];
|
||||
const state = this.state[`${output}os`];
|
||||
|
||||
return this.get_tooltip(mode, active, state);
|
||||
},
|
||||
|
||||
|
||||
get_motor_min_tooltip: function (motor) {
|
||||
return this.get_input_tooltip(motor + 'lw', motor + 'ls');
|
||||
return this.get_input_tooltip(`${motor}lw`, `${motor}ls`);
|
||||
},
|
||||
|
||||
|
||||
get_motor_max_tooltip: function (motor) {
|
||||
return this.get_input_tooltip(motor + 'xw', motor + 'xs');
|
||||
return this.get_input_tooltip(`${motor}xw`, `${motor}xs`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,42 +1,13 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#io-view-template',
|
||||
props: ['config', 'template', 'state'],
|
||||
|
||||
template: "#io-view-template",
|
||||
props: ["config", "template", "state"],
|
||||
|
||||
events: {
|
||||
'input-changed': function() {
|
||||
this.$dispatch('config-changed');
|
||||
"input-changed": function() {
|
||||
this.$dispatch("config-changed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
104
src/js/main.js
104
src/js/main.js
@@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
function cookie_get(name) {
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
name = name + '=';
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const ca = decodedCookie.split(";");
|
||||
name = `${name}=`;
|
||||
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == " ") {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
@@ -18,101 +18,101 @@ function cookie_get(name) {
|
||||
}
|
||||
|
||||
function cookie_set(name, value, days) {
|
||||
var d = new Date();
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
var expires = 'expires=' + d.toUTCString();
|
||||
document.cookie = name + '=' + value + ';' + expires + ';path=/';
|
||||
const expires = `expires=${d.toUTCString()}`;
|
||||
document.cookie = `${name}=${value};${expires};path=/`;
|
||||
}
|
||||
|
||||
var uuid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+';
|
||||
const uuid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+";
|
||||
|
||||
function uuid(length) {
|
||||
if (typeof length == 'undefined') {
|
||||
if (typeof length == "undefined") {
|
||||
length = 52;
|
||||
}
|
||||
|
||||
var s = '';
|
||||
for (var i = 0; i < length; i++) {
|
||||
let s = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
s += uuid_chars[Math.floor(Math.random() * uuid_chars.length)];
|
||||
}
|
||||
|
||||
return s
|
||||
return s;
|
||||
}
|
||||
|
||||
$(function () {
|
||||
if (typeof cookie_get('client-id') == 'undefined') {
|
||||
cookie_set('client-id', uuid(), 10000);
|
||||
if (typeof cookie_get("client-id") == "undefined") {
|
||||
cookie_set("client-id", uuid(), 10000);
|
||||
}
|
||||
|
||||
// Register global components
|
||||
Vue.component('templated-input', require('./templated-input'));
|
||||
Vue.component('message', require('./message'));
|
||||
Vue.component('indicators', require('./indicators'));
|
||||
Vue.component('io-indicator', require('./io-indicator'));
|
||||
Vue.component('console', require('./console'));
|
||||
Vue.component('unit-value', require('./unit-value'));
|
||||
Vue.component("templated-input", require("./templated-input"));
|
||||
Vue.component("message", require("./message"));
|
||||
Vue.component("indicators", require("./indicators"));
|
||||
Vue.component("io-indicator", require("./io-indicator"));
|
||||
Vue.component("console", require("./console"));
|
||||
Vue.component("unit-value", require("./unit-value"));
|
||||
|
||||
Vue.filter('number', function (value) {
|
||||
Vue.filter("number", function (value) {
|
||||
if (isNaN(value)) {
|
||||
return 'NaN';
|
||||
return "NaN";
|
||||
}
|
||||
|
||||
return value.toLocaleString();
|
||||
});
|
||||
|
||||
Vue.filter('percent', function (value, precision) {
|
||||
if (typeof value == 'undefined') {
|
||||
return '';
|
||||
Vue.filter("percent", function (value, precision) {
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeof precision == 'undefined') {
|
||||
if (typeof precision == "undefined") {
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
return (value * 100.0).toFixed(precision) + '%';
|
||||
return `${(value * 100.0).toFixed(precision)}%`;
|
||||
});
|
||||
|
||||
Vue.filter('non_zero_percent', function (value, precision) {
|
||||
Vue.filter("non_zero_percent", function (value, precision) {
|
||||
if (!value) {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeof precision == 'undefined') {
|
||||
if (typeof precision == "undefined") {
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
return (value * 100.0).toFixed(precision) + '%';
|
||||
return `${(value * 100.0).toFixed(precision)}%`;
|
||||
});
|
||||
|
||||
Vue.filter('fixed', function (value, precision) {
|
||||
if (typeof value == 'undefined') {
|
||||
return '0';
|
||||
Vue.filter("fixed", function (value, precision) {
|
||||
if (typeof value == "undefined") {
|
||||
return "0";
|
||||
}
|
||||
|
||||
return parseFloat(value).toFixed(precision)
|
||||
return parseFloat(value).toFixed(precision);
|
||||
});
|
||||
|
||||
Vue.filter('upper', function (value) {
|
||||
if (typeof value == 'undefined') {
|
||||
return '';
|
||||
Vue.filter("upper", function (value) {
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return value.toUpperCase()
|
||||
return value.toUpperCase();
|
||||
});
|
||||
|
||||
Vue.filter('time', function (value, precision) {
|
||||
Vue.filter("time", function (value, precision) {
|
||||
if (isNaN(value)) {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
if (isNaN(precision)) {
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
var MIN = 60;
|
||||
var HR = MIN * 60;
|
||||
var DAY = HR * 24;
|
||||
var parts = [];
|
||||
const MIN = 60;
|
||||
const HR = MIN * 60;
|
||||
const DAY = HR * 24;
|
||||
const parts = [];
|
||||
|
||||
if (DAY <= value) {
|
||||
parts.push(Math.floor(value / DAY));
|
||||
@@ -133,16 +133,16 @@ $(function () {
|
||||
|
||||
parts.push(value);
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
parts[i] = parts[i].toFixed(i == parts.length - 1 ? precision : 0);
|
||||
if (i && parts[i] < 10) {
|
||||
parts[i] = '0' + parts[i];
|
||||
parts[i] = `0${parts[i]}`;
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(':');
|
||||
return parts.join(":");
|
||||
});
|
||||
|
||||
// Vue app
|
||||
require('./app');
|
||||
require("./app");
|
||||
});
|
||||
|
||||
@@ -1,35 +1,7 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#message-template',
|
||||
template: "#message-template",
|
||||
|
||||
props: {
|
||||
show: {
|
||||
@@ -44,4 +16,4 @@ module.exports = {
|
||||
twoWay: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,48 +1,20 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '#modbus-reg-view-template',
|
||||
props: ['index', 'model', 'template', 'enable'],
|
||||
|
||||
template: "#modbus-reg-view-template",
|
||||
props: ["index", "model", "template", "enable"],
|
||||
|
||||
computed: {
|
||||
has_user_value: function () {
|
||||
var type = this.model['reg-type'];
|
||||
return type.indexOf('write') != -1 || type.indexOf('fixed') != -1;
|
||||
const type = this.model["reg-type"];
|
||||
return type.indexOf("write") != -1 || type.indexOf("fixed") != -1;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
change: function () {this.$dispatch('input-changed')}
|
||||
change: function () {
|
||||
this.$dispatch("input-changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,35 +1,7 @@
|
||||
/******************************************************************************\
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
// Must match modbus.c
|
||||
var exports = {
|
||||
const exports = {
|
||||
DISCONNECTED: 0,
|
||||
OK: 1,
|
||||
CRC: 2,
|
||||
@@ -37,15 +9,15 @@ var exports = {
|
||||
TIMEDOUT: 4
|
||||
};
|
||||
|
||||
|
||||
exports.status_to_string =
|
||||
function (status) {
|
||||
if (status == exports.OK) return 'Ok';
|
||||
if (status == exports.CRC) return 'CRC error';
|
||||
if (status == exports.INVALID) return 'Invalid response';
|
||||
if (status == exports.TIMEDOUT) return 'Timedout';
|
||||
return 'Disconnected';
|
||||
switch (status) {
|
||||
case exports.OK: return "Ok";
|
||||
case exports.CRC: return "CRC error";
|
||||
case exports.INVALID: return "Invalid response";
|
||||
case exports.TIMEDOUT: return "Timedout";
|
||||
default: return "Disconnected";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = exports;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#motor-view-template',
|
||||
props: ['index', 'config', 'template', 'state'],
|
||||
template: "#motor-view-template",
|
||||
props: ["index", "config", "template", "state"],
|
||||
|
||||
computed: {
|
||||
metric: function () {
|
||||
@@ -10,7 +10,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
is_slave: function () {
|
||||
for (var i = 0; i < this.index; i++) {
|
||||
for (let i = 0; i < this.index; i++) {
|
||||
if (this.motor.axis == this.config.motors[i].axis) {
|
||||
return true;
|
||||
}
|
||||
@@ -20,76 +20,76 @@ module.exports = {
|
||||
},
|
||||
|
||||
motor: function () {
|
||||
return this.config.motors[this.index]
|
||||
return this.config.motors[this.index];
|
||||
},
|
||||
|
||||
invalidMaxVelocity: function () {
|
||||
return this.maxMaxVelocity < this.motor['max-velocity'];
|
||||
return this.maxMaxVelocity < this.motor["max-velocity"];
|
||||
},
|
||||
|
||||
maxMaxVelocity: function () {
|
||||
return 1 * (15 * this.umPerStep / this.motor['microsteps']).toFixed(3);
|
||||
return 1 * (15 * this.umPerStep / this.motor["microsteps"]).toFixed(3);
|
||||
},
|
||||
|
||||
ustepPerSec: function () {
|
||||
return this.rpm * this.stepsPerRev * this.motor['microsteps'] / 60;
|
||||
return this.rpm * this.stepsPerRev * this.motor["microsteps"] / 60;
|
||||
},
|
||||
|
||||
rpm: function () {
|
||||
return 1000 * this.motor['max-velocity'] / this.motor['travel-per-rev'];
|
||||
return 1000 * this.motor["max-velocity"] / this.motor["travel-per-rev"];
|
||||
},
|
||||
|
||||
gForce: function () {
|
||||
return this.motor['max-accel'] * 0.0283254504
|
||||
return this.motor["max-accel"] * 0.0283254504;
|
||||
},
|
||||
|
||||
gForcePerMin: function () {
|
||||
return this.motor['max-jerk'] * 0.0283254504
|
||||
return this.motor["max-jerk"] * 0.0283254504;
|
||||
},
|
||||
|
||||
stepsPerRev: function () {
|
||||
return 360 / this.motor['step-angle']
|
||||
return 360 / this.motor["step-angle"];
|
||||
},
|
||||
|
||||
umPerStep: function () {
|
||||
return this.motor['travel-per-rev'] * this.motor['step-angle'] / 0.36
|
||||
return this.motor["travel-per-rev"] * this.motor["step-angle"] / 0.36;
|
||||
},
|
||||
|
||||
milPerStep: function () {
|
||||
return this.umPerStep / 25.4
|
||||
return this.umPerStep / 25.4;
|
||||
},
|
||||
|
||||
invalidStallVelocity: function () {
|
||||
if (!this.motor['homing-mode'].startsWith('stall-')) {
|
||||
if (!this.motor["homing-mode"].startsWith("stall-")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.maxStallVelocity < this.motor['search-velocity'];
|
||||
return this.maxStallVelocity < this.motor["search-velocity"];
|
||||
},
|
||||
|
||||
stallRPM: function () {
|
||||
var v = this.motor['search-velocity'];
|
||||
return 1000 * v / this.motor['travel-per-rev'];
|
||||
const v = this.motor["search-velocity"];
|
||||
return 1000 * v / this.motor["travel-per-rev"];
|
||||
},
|
||||
|
||||
maxStallVelocity: function () {
|
||||
var maxRate = 900000 / this.motor['stall-sample-time'];
|
||||
var ustep = this.motor['stall-microstep'];
|
||||
var angle = this.motor['step-angle'];
|
||||
var travel = this.motor['travel-per-rev'];
|
||||
var maxStall = maxRate * 60 / 360 / 1000 * angle / ustep * travel;
|
||||
const maxRate = 900000 / this.motor["stall-sample-time"];
|
||||
const ustep = this.motor["stall-microstep"];
|
||||
const angle = this.motor["step-angle"];
|
||||
const travel = this.motor["travel-per-rev"];
|
||||
const maxStall = maxRate * 60 / 360 / 1000 * angle / ustep * travel;
|
||||
|
||||
return 1 * maxStall.toFixed(3);
|
||||
},
|
||||
|
||||
stallUStepPerSec: function () {
|
||||
var ustep = this.motor['stall-microstep'];
|
||||
const ustep = this.motor["stall-microstep"];
|
||||
return this.stallRPM * this.stepsPerRev * ustep / 60;
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
'input-changed': function () {
|
||||
"input-changed": function () {
|
||||
Vue.nextTick(function () {
|
||||
// Limit max-velocity
|
||||
if (this.invalidMaxVelocity) {
|
||||
@@ -101,8 +101,8 @@ module.exports = {
|
||||
this.$set('motor["search-velocity"]', this.maxStallVelocity);
|
||||
}
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
}.bind(this))
|
||||
this.$dispatch("config-changed");
|
||||
}.bind(this));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ module.exports = {
|
||||
return true;
|
||||
}
|
||||
|
||||
return templ.hmodes.indexOf(this.motor['homing-mode']) != -1;
|
||||
return templ.hmodes.indexOf(this.motor["homing-mode"]) != -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
421
src/js/orbit.js
421
src/js/orbit.js
@@ -7,7 +7,7 @@
|
||||
* @author jcoffland / https://buildbotics.com/
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
// This set of controls performs orbiting, dollying (zooming), and panning.
|
||||
// Unlike TrackballControls, it maintains the "up" direction object.up
|
||||
@@ -17,8 +17,42 @@
|
||||
// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
|
||||
// Pan - right mouse, or arrow keys / touch: two-finger move
|
||||
|
||||
const OrbitControls = function (object, domElement) {
|
||||
// internals
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const scope = this;
|
||||
|
||||
const changeEvent = {type: "change"};
|
||||
const startEvent = {type: "start"};
|
||||
const endEvent = {type: "end"};
|
||||
|
||||
const STATE = {
|
||||
NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4
|
||||
};
|
||||
|
||||
let state = STATE.NONE;
|
||||
const EPS = 0.000001;
|
||||
|
||||
// current position in spherical coordinates
|
||||
const spherical = new THREE.Spherical();
|
||||
const sphericalDelta = new THREE.Spherical();
|
||||
|
||||
let scale = 1;
|
||||
const panOffset = new THREE.Vector3();
|
||||
let zoomChanged = false;
|
||||
|
||||
const rotateStart = new THREE.Vector2();
|
||||
const rotateEnd = new THREE.Vector2();
|
||||
const rotateDelta = new THREE.Vector2();
|
||||
|
||||
const panStart = new THREE.Vector2();
|
||||
const panEnd = new THREE.Vector2();
|
||||
const panDelta = new THREE.Vector2();
|
||||
|
||||
const dollyStart = new THREE.Vector2();
|
||||
const dollyEnd = new THREE.Vector2();
|
||||
const dollyDelta = new THREE.Vector2();
|
||||
|
||||
var OrbitControls = function (object, domElement) {
|
||||
this.object = object;
|
||||
this.domElement = domElement != undefined ? domElement : document;
|
||||
|
||||
@@ -85,16 +119,19 @@ var OrbitControls = function (object, domElement) {
|
||||
this.zoom0 = this.object.zoom;
|
||||
|
||||
// public methods
|
||||
this.getPolarAngle = function () {return spherical.phi}
|
||||
this.getAzimuthalAngle = function () {return spherical.theta}
|
||||
this.getPolarAngle = function () {
|
||||
return spherical.phi;
|
||||
};
|
||||
|
||||
this.getAzimuthalAngle = function () {
|
||||
return spherical.theta;
|
||||
};
|
||||
|
||||
this.saveState = function () {
|
||||
scope.target0.copy(scope.target);
|
||||
scope.position0.copy(scope.object.position);
|
||||
scope.zoom0 = scope.object.zoom;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.reset = function () {
|
||||
scope.target.copy(scope.target0);
|
||||
@@ -106,22 +143,20 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.update();
|
||||
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.update = function () {
|
||||
var offset = new THREE.Vector3();
|
||||
const offset = new THREE.Vector3();
|
||||
|
||||
// so camera.up is the orbit axis
|
||||
var quat = new THREE.Quaternion()
|
||||
.setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
|
||||
var quatInverse = quat.clone().inverse();
|
||||
const quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
|
||||
const quatInverse = quat.clone().inverse();
|
||||
|
||||
var lastPosition = new THREE.Vector3();
|
||||
var lastQuaternion = new THREE.Quaternion();
|
||||
const lastPosition = new THREE.Vector3();
|
||||
const lastQuaternion = new THREE.Quaternion();
|
||||
|
||||
return function update() {
|
||||
var position = scope.object.position;
|
||||
const position = scope.object.position;
|
||||
|
||||
offset.copy(position).sub(scope.target);
|
||||
|
||||
@@ -131,28 +166,24 @@ var OrbitControls = function (object, domElement) {
|
||||
// angle from z-axis around y-axis
|
||||
spherical.setFromVector3(offset);
|
||||
|
||||
if (scope.autoRotate && state == STATE.NONE)
|
||||
if (scope.autoRotate && state == STATE.NONE) {
|
||||
rotateLeft(getAutoRotationAngle());
|
||||
}
|
||||
|
||||
spherical.theta += sphericalDelta.theta;
|
||||
spherical.phi += sphericalDelta.phi;
|
||||
|
||||
// restrict theta to be between desired limits
|
||||
spherical.theta =
|
||||
Math.max(scope.minAzimuthAngle,
|
||||
Math.min(scope.maxAzimuthAngle, spherical.theta));
|
||||
spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));
|
||||
|
||||
// restrict phi to be between desired limits
|
||||
spherical.phi =
|
||||
Math.max(scope.minPolarAngle,
|
||||
Math.min(scope.maxPolarAngle, spherical.phi));
|
||||
spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
|
||||
|
||||
spherical.makeSafe();
|
||||
spherical.radius *= scale;
|
||||
|
||||
// restrict radius to be between desired limits
|
||||
spherical.radius =
|
||||
Math.max(10, Math.min(scope.object.far * 0.8, spherical.radius));
|
||||
spherical.radius = Math.max(10, Math.min(scope.object.far * 0.8, spherical.radius));
|
||||
|
||||
// move target to panned location
|
||||
scope.target.add(panOffset);
|
||||
@@ -178,9 +209,10 @@ var OrbitControls = function (object, domElement) {
|
||||
// update condition is:
|
||||
// min(camera displacement, camera rotation in radians)^2 > EPS
|
||||
// using small-angle approximation cos(x/2) = 1 - x^2 / 8
|
||||
if (zoomChanged || scale != 1 ||
|
||||
lastPosition.distanceToSquared(scope.object.position) > EPS ||
|
||||
8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
|
||||
if (zoomChanged
|
||||
|| scale != 1
|
||||
|| lastPosition.distanceToSquared(scope.object.position) > EPS
|
||||
|| 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
|
||||
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
@@ -193,187 +225,150 @@ var OrbitControls = function (object, domElement) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}()
|
||||
|
||||
};
|
||||
}();
|
||||
|
||||
this.dispose = function () {
|
||||
scope.domElement.removeEventListener('contextmenu', onContextMenu, false);
|
||||
scope.domElement.removeEventListener('mousedown', onMouseDown, false);
|
||||
scope.domElement.removeEventListener('wheel', onMouseWheel, false);
|
||||
scope.domElement.removeEventListener('touchstart', onTouchStart, false);
|
||||
scope.domElement.removeEventListener('touchend', onTouchEnd, false);
|
||||
scope.domElement.removeEventListener('touchmove', onTouchMove, false);
|
||||
document.removeEventListener('mousemove', onMouseMove, false);
|
||||
document.removeEventListener('mouseup', onMouseUp, false);
|
||||
window.removeEventListener('keydown', onKeyDown, false);
|
||||
}
|
||||
|
||||
|
||||
// internals
|
||||
var scope = this;
|
||||
|
||||
var changeEvent = {type: 'change'};
|
||||
var startEvent = {type: 'start'};
|
||||
var endEvent = {type: 'end'};
|
||||
|
||||
var STATE = {
|
||||
NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4
|
||||
scope.domElement.removeEventListener("contextmenu", onContextMenu, false);
|
||||
scope.domElement.removeEventListener("mousedown", onMouseDown, false);
|
||||
scope.domElement.removeEventListener("wheel", onMouseWheel, false);
|
||||
scope.domElement.removeEventListener("touchstart", onTouchStart, false);
|
||||
scope.domElement.removeEventListener("touchend", onTouchEnd, false);
|
||||
scope.domElement.removeEventListener("touchmove", onTouchMove, false);
|
||||
document.removeEventListener("mousemove", onMouseMove, false);
|
||||
document.removeEventListener("mouseup", onMouseUp, false);
|
||||
window.removeEventListener("keydown", onKeyDown, false);
|
||||
};
|
||||
|
||||
var state = STATE.NONE;
|
||||
var EPS = 0.000001;
|
||||
|
||||
// current position in spherical coordinates
|
||||
var spherical = new THREE.Spherical();
|
||||
var sphericalDelta = new THREE.Spherical();
|
||||
|
||||
var scale = 1;
|
||||
var panOffset = new THREE.Vector3();
|
||||
var zoomChanged = false;
|
||||
|
||||
var rotateStart = new THREE.Vector2();
|
||||
var rotateEnd = new THREE.Vector2();
|
||||
var rotateDelta = new THREE.Vector2();
|
||||
|
||||
var panStart = new THREE.Vector2();
|
||||
var panEnd = new THREE.Vector2();
|
||||
var panDelta = new THREE.Vector2();
|
||||
|
||||
var dollyStart = new THREE.Vector2();
|
||||
var dollyEnd = new THREE.Vector2();
|
||||
var dollyDelta = new THREE.Vector2();
|
||||
|
||||
|
||||
function getAutoRotationAngle() {
|
||||
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
|
||||
}
|
||||
|
||||
function getZoomScale() {
|
||||
return Math.pow(0.95, scope.zoomSpeed);
|
||||
}
|
||||
|
||||
function getZoomScale() {return Math.pow(0.95, scope.zoomSpeed)}
|
||||
function rotateLeft(angle) {sphericalDelta.theta -= angle}
|
||||
function rotateUp(angle) {sphericalDelta.phi -= angle}
|
||||
function rotateLeft(angle) {
|
||||
sphericalDelta.theta -= angle;
|
||||
}
|
||||
|
||||
function rotateUp(angle) {
|
||||
sphericalDelta.phi -= angle;
|
||||
}
|
||||
|
||||
var panLeft = function () {
|
||||
var v = new THREE.Vector3();
|
||||
const panLeft = function () {
|
||||
const v = new THREE.Vector3();
|
||||
|
||||
return function panLeft(distance, objectMatrix) {
|
||||
v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix
|
||||
v.multiplyScalar(-distance);
|
||||
panOffset.add(v);
|
||||
}
|
||||
}()
|
||||
};
|
||||
}();
|
||||
|
||||
|
||||
var panUp = function () {
|
||||
var v = new THREE.Vector3();
|
||||
const panUp = function () {
|
||||
const v = new THREE.Vector3();
|
||||
|
||||
return function panUp(distance, objectMatrix) {
|
||||
if (scope.screenSpacePanning) v.setFromMatrixColumn(objectMatrix, 1);
|
||||
else {
|
||||
if (scope.screenSpacePanning) {
|
||||
v.setFromMatrixColumn(objectMatrix, 1);
|
||||
} else {
|
||||
v.setFromMatrixColumn(objectMatrix, 0);
|
||||
v.crossVectors(scope.object.up, v);
|
||||
}
|
||||
|
||||
v.multiplyScalar(distance);
|
||||
panOffset.add(v);
|
||||
}
|
||||
}()
|
||||
|
||||
};
|
||||
}();
|
||||
|
||||
function unknownCamera() {
|
||||
console.warn('WARNING: OrbitControls.js encountered an unknown camera ' +
|
||||
'type - pan & zoom disabled.');
|
||||
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan & zoom disabled.");
|
||||
scope.enablePan = false;
|
||||
scope.enableZoom = false;
|
||||
}
|
||||
|
||||
|
||||
// deltaX and deltaY are in pixels; right and down are positive
|
||||
var pan = function () {
|
||||
var offset = new THREE.Vector3();
|
||||
const pan = function () {
|
||||
const offset = new THREE.Vector3();
|
||||
|
||||
return function pan(deltaX, deltaY) {
|
||||
var element = scope.domElement === document ?
|
||||
scope.domElement.body : scope.domElement;
|
||||
const element = scope.domElement === document
|
||||
? scope.domElement.body
|
||||
: scope.domElement;
|
||||
|
||||
if (scope.object.isPerspectiveCamera) {
|
||||
// perspective
|
||||
offset.copy(scope.object.position).sub(scope.target);
|
||||
var targetDistance = offset.length();
|
||||
let targetDistance = offset.length();
|
||||
|
||||
// half of the fov is center to top of screen
|
||||
targetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0);
|
||||
|
||||
// we use only clientHeight here so aspect ratio does not distort speed
|
||||
panLeft(2 * deltaX * targetDistance / element.clientHeight,
|
||||
scope.object.matrix);
|
||||
panUp(2 * deltaY * targetDistance / element.clientHeight,
|
||||
scope.object.matrix);
|
||||
panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
|
||||
panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
|
||||
|
||||
} else if (scope.object.isOrthographicCamera) {
|
||||
// orthographic
|
||||
panLeft(deltaX * (scope.object.right - scope.object.left) /
|
||||
scope.object.zoom / element.clientWidth, scope.object.matrix);
|
||||
panUp(deltaY * (scope.object.top - scope.object.bottom) /
|
||||
scope.object.zoom / element.clientHeight, scope.object.matrix);
|
||||
panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
|
||||
panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
|
||||
|
||||
} else unknownCamera();
|
||||
} else {
|
||||
unknownCamera();
|
||||
}
|
||||
}()
|
||||
|
||||
};
|
||||
}();
|
||||
|
||||
function dollyIn(dollyScale) {
|
||||
if (scope.object.isPerspectiveCamera) scale /= dollyScale;
|
||||
|
||||
else if (scope.object.isOrthographicCamera) {
|
||||
if (scope.object.isPerspectiveCamera) {
|
||||
scale /= dollyScale;
|
||||
} else if (scope.object.isOrthographicCamera) {
|
||||
scope.object.zoom =
|
||||
Math.max(scope.minZoom,
|
||||
Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
|
||||
scope.object.updateProjectionMatrix();
|
||||
zoomChanged = true;
|
||||
|
||||
} else unknownCamera();
|
||||
} else {
|
||||
unknownCamera();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function dollyOut(dollyScale) {
|
||||
if (scope.object.isPerspectiveCamera) scale *= dollyScale;
|
||||
|
||||
else if (scope.object.isOrthographicCamera) {
|
||||
if (scope.object.isPerspectiveCamera) {
|
||||
scale *= dollyScale;
|
||||
} else if (scope.object.isOrthographicCamera) {
|
||||
scope.object.zoom =
|
||||
Math.max(scope.minZoom,
|
||||
Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
|
||||
scope.object.updateProjectionMatrix();
|
||||
zoomChanged = true;
|
||||
|
||||
} else unknownCamera();
|
||||
} else {
|
||||
unknownCamera();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// event callbacks - update the object state
|
||||
function handleMouseDownRotate(event) {
|
||||
rotateStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
|
||||
function handleMouseDownDolly(event) {
|
||||
dollyStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
|
||||
function handleMouseDownPan(event) {
|
||||
panStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
|
||||
function handleMouseMoveRotate(event) {
|
||||
rotateEnd.set(event.clientX, event.clientY);
|
||||
rotateDelta.subVectors(rotateEnd, rotateStart)
|
||||
.multiplyScalar(scope.rotateSpeed);
|
||||
|
||||
var element = scope.domElement === document ?
|
||||
const element = scope.domElement === document ?
|
||||
scope.domElement.body : scope.domElement;
|
||||
|
||||
// yes, height
|
||||
@@ -385,19 +380,20 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleMouseMoveDolly(event) {
|
||||
dollyEnd.set(event.clientX, event.clientY);
|
||||
dollyDelta.subVectors(dollyEnd, dollyStart);
|
||||
|
||||
if (dollyDelta.y > 0) dollyIn(getZoomScale());
|
||||
else if (dollyDelta.y < 0) dollyOut(getZoomScale());
|
||||
if (dollyDelta.y > 0) {
|
||||
dollyIn(getZoomScale());
|
||||
} else if (dollyDelta.y < 0) {
|
||||
dollyOut(getZoomScale());
|
||||
}
|
||||
|
||||
dollyStart.copy(dollyEnd);
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleMouseMovePan(event) {
|
||||
panEnd.set(event.clientX, event.clientY);
|
||||
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
|
||||
@@ -406,18 +402,16 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleMouseUp(event) {}
|
||||
|
||||
|
||||
function handleMouseWheel(event) {
|
||||
if (event.deltaY < 0) dollyOut(getZoomScale());
|
||||
else if (event.deltaY > 0) dollyIn(getZoomScale());
|
||||
if (event.deltaY < 0) {
|
||||
dollyOut(getZoomScale());
|
||||
} else if (event.deltaY > 0) {
|
||||
dollyIn(getZoomScale());
|
||||
}
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleKeyDown(event) {
|
||||
switch (event.keyCode) {
|
||||
case scope.keys.UP:
|
||||
@@ -442,35 +436,32 @@ var OrbitControls = function (object, domElement) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleTouchStartRotate(event) {
|
||||
rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
}
|
||||
|
||||
|
||||
function handleTouchStartDollyPan(event) {
|
||||
if (scope.enableZoom) {
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
const dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
dollyStart.set(0, distance);
|
||||
}
|
||||
|
||||
if (scope.enablePan) {
|
||||
var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
|
||||
var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
|
||||
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
|
||||
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
|
||||
panStart.set(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleTouchMoveRotate(event) {
|
||||
rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
rotateDelta.subVectors(rotateEnd, rotateStart)
|
||||
.multiplyScalar(scope.rotateSpeed);
|
||||
|
||||
var element = scope.domElement === document ?
|
||||
const element = scope.domElement === document ?
|
||||
scope.domElement.body : scope.domElement;
|
||||
|
||||
// yes, height
|
||||
@@ -480,12 +471,11 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleTouchMoveDollyPan(event) {
|
||||
if (scope.enableZoom) {
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
const dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
dollyEnd.set(0, distance);
|
||||
dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
|
||||
@@ -493,10 +483,9 @@ var OrbitControls = function (object, domElement) {
|
||||
dollyStart.copy(dollyEnd);
|
||||
}
|
||||
|
||||
|
||||
if (scope.enablePan) {
|
||||
var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
|
||||
var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
|
||||
const x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX);
|
||||
const y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY);
|
||||
|
||||
panEnd.set(x, y);
|
||||
panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
|
||||
@@ -507,82 +496,94 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.update();
|
||||
}
|
||||
|
||||
|
||||
function handleTouchEnd(event) {}
|
||||
|
||||
|
||||
// event handlers - listen for events and reset state
|
||||
function onMouseDown(event) {
|
||||
if (!scope.enabled) return;
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
switch (event.button) {
|
||||
case scope.mouseButtons.ORBIT:
|
||||
if (!scope.enableRotate) return;
|
||||
if (!scope.enableRotate) {
|
||||
return;
|
||||
}
|
||||
handleMouseDownRotate(event);
|
||||
state = STATE.ROTATE;
|
||||
break;
|
||||
|
||||
case scope.mouseButtons.ZOOM:
|
||||
if (!scope.enableZoom) return;
|
||||
if (!scope.enableZoom) {
|
||||
return;
|
||||
}
|
||||
handleMouseDownDolly(event);
|
||||
state = STATE.DOLLY;
|
||||
break;
|
||||
|
||||
case scope.mouseButtons.PAN:
|
||||
if (!scope.enablePan) return;
|
||||
if (!scope.enablePan) {
|
||||
return;
|
||||
}
|
||||
handleMouseDownPan(event);
|
||||
state = STATE.PAN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (state != STATE.NONE) {
|
||||
document.addEventListener('mousemove', onMouseMove, false);
|
||||
document.addEventListener('mouseup', onMouseUp, false);
|
||||
document.addEventListener("mousemove", onMouseMove, false);
|
||||
document.addEventListener("mouseup", onMouseUp, false);
|
||||
scope.dispatchEvent(startEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onMouseMove(event) {
|
||||
if (!scope.enabled) return;
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
switch (state) {
|
||||
case STATE.ROTATE:
|
||||
if (!scope.enableRotate) return;
|
||||
if (!scope.enableRotate) {
|
||||
return;
|
||||
}
|
||||
handleMouseMoveRotate(event);
|
||||
break;
|
||||
|
||||
case STATE.DOLLY:
|
||||
if (!scope.enableZoom) return;
|
||||
if (!scope.enableZoom) {
|
||||
return;
|
||||
}
|
||||
handleMouseMoveDolly(event);
|
||||
break;
|
||||
|
||||
case STATE.PAN:
|
||||
if (!scope.enablePan) return;
|
||||
if (!scope.enablePan) {
|
||||
return;
|
||||
}
|
||||
handleMouseMovePan(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp() {
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
function onMouseUp(event) {
|
||||
if (!scope.enabled) return;
|
||||
|
||||
handleMouseUp(event);
|
||||
document.removeEventListener('mousemove', onMouseMove, false);
|
||||
document.removeEventListener('mouseup', onMouseUp, false);
|
||||
document.removeEventListener("mousemove", onMouseMove, false);
|
||||
document.removeEventListener("mouseup", onMouseUp, false);
|
||||
scope.dispatchEvent(endEvent);
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
|
||||
function onMouseWheel(event) {
|
||||
if (!scope.enabled || !scope.enableZoom ||
|
||||
(state != STATE.NONE && state != STATE.ROTATE)) return;
|
||||
(state != STATE.NONE && state != STATE.ROTATE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -591,28 +592,34 @@ var OrbitControls = function (object, domElement) {
|
||||
scope.dispatchEvent(endEvent);
|
||||
}
|
||||
|
||||
|
||||
function onKeyDown(event) {
|
||||
if (!scope.enabled || !scope.enableKeys || !scope.enablePan) return;
|
||||
if (!scope.enabled || !scope.enableKeys || !scope.enablePan) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleKeyDown(event);
|
||||
}
|
||||
|
||||
|
||||
function onTouchStart(event) {
|
||||
if (!scope.enabled) return;
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
switch (event.touches.length) {
|
||||
case 1: // one-fingered touch: rotate
|
||||
if (!scope.enableRotate) return;
|
||||
if (!scope.enableRotate) {
|
||||
return;
|
||||
}
|
||||
handleTouchStartRotate(event);
|
||||
state = STATE.TOUCH_ROTATE;
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly-pan
|
||||
if (!scope.enableZoom && !scope.enablePan) return;
|
||||
if (!scope.enableZoom && !scope.enablePan) {
|
||||
return;
|
||||
}
|
||||
handleTouchStartDollyPan(event);
|
||||
state = STATE.TOUCH_DOLLY_PAN;
|
||||
break;
|
||||
@@ -620,27 +627,38 @@ var OrbitControls = function (object, domElement) {
|
||||
default: state = STATE.NONE;
|
||||
}
|
||||
|
||||
if (state != STATE.NONE) scope.dispatchEvent(startEvent);
|
||||
if (state != STATE.NONE) {
|
||||
scope.dispatchEvent(startEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onTouchMove(event) {
|
||||
if (!scope.enabled) return;
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
switch (event.touches.length) {
|
||||
case 1: // one-fingered touch: rotate
|
||||
if (!scope.enableRotate) return;
|
||||
if (state != STATE.TOUCH_ROTATE) return; // is this needed?
|
||||
if (!scope.enableRotate) {
|
||||
return;
|
||||
}
|
||||
if (state != STATE.TOUCH_ROTATE) {
|
||||
return;
|
||||
} // is this needed?
|
||||
|
||||
handleTouchMoveRotate(event);
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly-pan
|
||||
if (!scope.enableZoom && !scope.enablePan) return;
|
||||
if (state != STATE.TOUCH_DOLLY_PAN) return; // is this needed?
|
||||
if (!scope.enableZoom && !scope.enablePan) {
|
||||
return;
|
||||
}
|
||||
if (state != STATE.TOUCH_DOLLY_PAN) {
|
||||
return;
|
||||
} // is this needed?
|
||||
|
||||
handleTouchMoveDollyPan(event);
|
||||
break;
|
||||
@@ -649,33 +667,32 @@ var OrbitControls = function (object, domElement) {
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchEnd() {
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
function onTouchEnd(event) {
|
||||
if (!scope.enabled) return;
|
||||
|
||||
handleTouchEnd(event);
|
||||
scope.dispatchEvent(endEvent);
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
|
||||
function onContextMenu(event) {
|
||||
if (!scope.enabled) return;
|
||||
if (!scope.enabled) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
|
||||
scope.domElement.addEventListener('contextmenu', onContextMenu, false);
|
||||
scope.domElement.addEventListener('mousedown', onMouseDown, false);
|
||||
scope.domElement.addEventListener('wheel', onMouseWheel, false);
|
||||
scope.domElement.addEventListener('touchstart', onTouchStart, false);
|
||||
scope.domElement.addEventListener('touchend', onTouchEnd, false);
|
||||
scope.domElement.addEventListener('touchmove', onTouchMove, false);
|
||||
window .addEventListener('keydown', onKeyDown, false);
|
||||
scope.domElement.addEventListener("contextmenu", onContextMenu, false);
|
||||
scope.domElement.addEventListener("mousedown", onMouseDown, false);
|
||||
scope.domElement.addEventListener("wheel", onMouseWheel, false);
|
||||
scope.domElement.addEventListener("touchstart", onTouchStart, false);
|
||||
scope.domElement.addEventListener("touchend", onTouchEnd, false);
|
||||
scope.domElement.addEventListener("touchmove", onTouchMove, false);
|
||||
window.addEventListener("keydown", onKeyDown, false);
|
||||
|
||||
this.update(); // force an update at start
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
OrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype);
|
||||
OrbitControls.prototype.constructor = OrbitControls;
|
||||
|
||||
@@ -1,58 +1,32 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
Copyright 2018. Buildbotics LLC
|
||||
All Rights Reserved.
|
||||
|
||||
For information regarding this software email:
|
||||
Joseph Coffland
|
||||
joseph@buildbotics.com
|
||||
|
||||
This software is free software: you clan redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation, either version 2.1 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This software is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the C! library. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
var orbit = require('./orbit');
|
||||
var cookie = require('./cookie')('bbctrl-');
|
||||
var font = require('./helvetiker_regular.typeface.json')
|
||||
const orbit = require("./orbit");
|
||||
const cookie = require("./cookie")("bbctrl-");
|
||||
const font = require("./helvetiker_regular.typeface.json");
|
||||
|
||||
module.exports = {
|
||||
template: '#path-viewer-template',
|
||||
props: ['toolpath'],
|
||||
template: "#path-viewer-template",
|
||||
props: ["toolpath"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
enabled: false,
|
||||
loading: false,
|
||||
dirty: true,
|
||||
snapView: cookie.get('snap-view', 'isometric'),
|
||||
small: cookie.get_bool('small-path-view', true),
|
||||
surfaceMode: 'cut',
|
||||
showPath: cookie.get_bool('show-path', true),
|
||||
showTool: cookie.get_bool('show-tool', true),
|
||||
showBBox: cookie.get_bool('show-bbox', true),
|
||||
showAxes: cookie.get_bool('show-axes', true),
|
||||
showIntensity: cookie.get_bool('show-intensity', false)
|
||||
}
|
||||
snapView: cookie.get("snap-view", "isometric"),
|
||||
small: cookie.get_bool("small-path-view", true),
|
||||
surfaceMode: "cut",
|
||||
showPath: cookie.get_bool("show-path", true),
|
||||
showTool: cookie.get_bool("show-tool", true),
|
||||
showBBox: cookie.get_bool("show-bbox", true),
|
||||
showAxes: cookie.get_bool("show-axes", true),
|
||||
showIntensity: cookie.get_bool("show-intensity", false)
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
target: function () {
|
||||
return $(this.$el).find('.path-viewer-content')[0]
|
||||
return $(this.$el).find(".path-viewer-content")[0];
|
||||
},
|
||||
|
||||
webglAvailable: function() {
|
||||
@@ -69,61 +43,64 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
toolpath: function () {Vue.nextTick(this.update)},
|
||||
surfaceMode: function (mode) {this.update_surface_mode(mode)},
|
||||
toolpath: function () {
|
||||
Vue.nextTick(this.update);
|
||||
},
|
||||
|
||||
surfaceMode: function (mode) {
|
||||
this.update_surface_mode(mode);
|
||||
},
|
||||
|
||||
small: function (enable) {
|
||||
cookie.set_bool('small-path-view', enable);
|
||||
Vue.nextTick(this.update_view)
|
||||
cookie.set_bool("small-path-view", enable);
|
||||
Vue.nextTick(this.update_view);
|
||||
},
|
||||
|
||||
|
||||
showPath: function (enable) {
|
||||
cookie.set_bool('show-path', enable);
|
||||
this.set_visible(this.pathView, enable)
|
||||
cookie.set_bool("show-path", enable);
|
||||
this.set_visible(this.pathView, enable);
|
||||
},
|
||||
|
||||
|
||||
showTool: function (enable) {
|
||||
cookie.set_bool('show-tool', enable);
|
||||
this.set_visible(this.toolView, enable)
|
||||
cookie.set_bool("show-tool", enable);
|
||||
this.set_visible(this.toolView, enable);
|
||||
},
|
||||
|
||||
|
||||
showAxes: function (enable) {
|
||||
cookie.set_bool('show-axes', enable);
|
||||
this.set_visible(this.axesView, enable)
|
||||
cookie.set_bool("show-axes", enable);
|
||||
this.set_visible(this.axesView, enable);
|
||||
},
|
||||
|
||||
|
||||
showIntensity: function (enable) {
|
||||
cookie.set_bool('show-intensity', enable);
|
||||
Vue.nextTick(this.update)
|
||||
cookie.set_bool("show-intensity", enable);
|
||||
Vue.nextTick(this.update);
|
||||
},
|
||||
|
||||
|
||||
showBBox: function (enable) {
|
||||
cookie.set_bool('show-bbox', enable);
|
||||
cookie.set_bool("show-bbox", enable);
|
||||
this.set_visible(this.bboxView, enable);
|
||||
this.set_visible(this.envelopeView, enable);
|
||||
},
|
||||
|
||||
|
||||
x: function () {this.axis_changed()},
|
||||
y: function () {this.axis_changed()},
|
||||
z: function () {this.axis_changed()}
|
||||
x: function () {
|
||||
this.axis_changed();
|
||||
},
|
||||
|
||||
y: function () {
|
||||
this.axis_changed();
|
||||
},
|
||||
|
||||
z: function () {
|
||||
this.axis_changed();
|
||||
}
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.graphics();
|
||||
Vue.nextTick(this.update);
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
update: async function () {
|
||||
if (!this.webglAvailable) {
|
||||
@@ -140,7 +117,9 @@ module.exports = {
|
||||
this.draw_loading();
|
||||
}
|
||||
|
||||
if (!this.enabled || !this.toolpath.filename) return;
|
||||
if (!this.enabled || !this.toolpath.filename) {
|
||||
return;
|
||||
}
|
||||
|
||||
async function get(url) {
|
||||
const response = await fetch(`${url}?${Math.random()}`);
|
||||
@@ -150,11 +129,11 @@ module.exports = {
|
||||
}
|
||||
|
||||
const [positions, speeds] = await Promise.all([
|
||||
get('/api/path/' + this.toolpath.filename + '/positions'),
|
||||
get('/api/path/' + this.toolpath.filename + '/speeds')
|
||||
get(`/api/path/${this.toolpath.filename}/positions`),
|
||||
get(`/api/path/${this.toolpath.filename}/speeds`)
|
||||
]);
|
||||
|
||||
this.positions = positions
|
||||
this.positions = positions;
|
||||
this.speeds = speeds;
|
||||
this.loading = false;
|
||||
|
||||
@@ -166,22 +145,22 @@ module.exports = {
|
||||
this.update_view();
|
||||
},
|
||||
|
||||
|
||||
update_surface_mode: function (mode) {
|
||||
if (!this.enabled) return;
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.surfaceMaterial != 'undefined') {
|
||||
this.surfaceMaterial.wireframe = mode == 'wire';
|
||||
if (typeof this.surfaceMaterial != "undefined") {
|
||||
this.surfaceMaterial.wireframe = mode == "wire";
|
||||
this.surfaceMaterial.needsUpdate = true;
|
||||
}
|
||||
|
||||
this.set_visible(this.surfaceMesh, mode == 'cut' || mode == 'wire');
|
||||
this.set_visible(this.workpieceMesh, mode == 'solid');
|
||||
this.set_visible(this.surfaceMesh, mode == "cut" || mode == "wire");
|
||||
this.set_visible(this.workpieceMesh, mode == "solid");
|
||||
},
|
||||
|
||||
|
||||
load_surface: function (surface) {
|
||||
if (typeof surface == 'undefined') {
|
||||
if (typeof surface == "undefined") {
|
||||
this.vertices = undefined;
|
||||
this.normals = undefined;
|
||||
return;
|
||||
@@ -191,30 +170,35 @@ module.exports = {
|
||||
|
||||
// Expand normals
|
||||
this.normals = [];
|
||||
for (var i = 0; i < surface.normals.length / 3; i++)
|
||||
for (var j = 0; j < 3; j++)
|
||||
for (var k = 0; k < 3; k++)
|
||||
for (let i = 0; i < surface.normals.length / 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
for (let k = 0; k < 3; k++) {
|
||||
this.normals.push(surface.normals[i * 3 + k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
set_visible: function (target, visible) {
|
||||
if (typeof target != 'undefined') target.visible = visible;
|
||||
if (typeof target != "undefined") {
|
||||
target.visible = visible;
|
||||
}
|
||||
this.dirty = true;
|
||||
},
|
||||
|
||||
|
||||
get_dims: function () {
|
||||
var t = $(this.target);
|
||||
var width = t.innerWidth();
|
||||
var height = t.innerHeight();
|
||||
const t = $(this.target);
|
||||
const width = t.innerWidth();
|
||||
const height = t.innerHeight();
|
||||
return {width: width, height: height};
|
||||
},
|
||||
|
||||
|
||||
update_view: function () {
|
||||
if (!this.enabled) return;
|
||||
var dims = this.get_dims();
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dims = this.get_dims();
|
||||
|
||||
this.camera.aspect = dims.width / dims.height;
|
||||
this.camera.updateProjectionMatrix();
|
||||
@@ -229,47 +213,59 @@ module.exports = {
|
||||
this.dirty = true;
|
||||
},
|
||||
|
||||
|
||||
update_tool: function (tool) {
|
||||
if (!this.enabled) return;
|
||||
if (typeof tool == 'undefined') tool = this.toolView;
|
||||
if (typeof tool == 'undefined') return;
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof tool == "undefined") {
|
||||
tool = this.toolView;
|
||||
}
|
||||
|
||||
if (typeof tool == "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
tool.position.x = this.x.pos;
|
||||
tool.position.y = this.y.pos;
|
||||
tool.position.z = this.z.pos;
|
||||
},
|
||||
|
||||
|
||||
update_envelope: function (envelope) {
|
||||
if (!this.enabled || !this.axes.homed) return;
|
||||
if (typeof envelope == 'undefined') envelope = this.envelopeView;
|
||||
if (typeof envelope == 'undefined') return;
|
||||
if (!this.enabled || !this.axes.homed) {
|
||||
return;
|
||||
}
|
||||
|
||||
var min = new THREE.Vector3();
|
||||
var max = new THREE.Vector3();
|
||||
if (typeof envelope == "undefined") {
|
||||
envelope = this.envelopeView;
|
||||
}
|
||||
|
||||
for (var axis of 'xyz') {
|
||||
if (typeof envelope == "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const min = new THREE.Vector3();
|
||||
const max = new THREE.Vector3();
|
||||
|
||||
for (const axis of "xyz") {
|
||||
min[axis] = this[axis].min - this[axis].off;
|
||||
max[axis] = this[axis].max - this[axis].off;
|
||||
}
|
||||
|
||||
var bounds = new THREE.Box3(min, max);
|
||||
const bounds = new THREE.Box3(min, max);
|
||||
if (bounds.isEmpty()) {
|
||||
envelope.geometry = this.create_empty_geom();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
envelope.geometry = this.create_bbox_geom(bounds);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
axis_changed: function () {
|
||||
this.update_tool();
|
||||
this.update_envelope();
|
||||
this.dirty = true;
|
||||
},
|
||||
|
||||
|
||||
graphics: function () {
|
||||
if (!this.webglAvailable) {
|
||||
return;
|
||||
@@ -283,7 +279,7 @@ module.exports = {
|
||||
this.target.appendChild(this.renderer.domElement);
|
||||
|
||||
} catch (e) {
|
||||
console.log('WebGL not supported: ', e);
|
||||
console.log("WebGL not supported: ", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -295,15 +291,13 @@ module.exports = {
|
||||
// Lighting
|
||||
this.ambient = new THREE.AmbientLight(0xffffff, 0.5);
|
||||
|
||||
var keyLight = new THREE.DirectionalLight
|
||||
(new THREE.Color('hsl(30, 100%, 75%)'), 0.75);
|
||||
const keyLight = new THREE.DirectionalLight(new THREE.Color("hsl(30, 100%, 75%)"), 0.75);
|
||||
keyLight.position.set(-100, 0, 100);
|
||||
|
||||
var fillLight = new THREE.DirectionalLight
|
||||
(new THREE.Color('hsl(240, 100%, 75%)'), 0.25);
|
||||
const fillLight = new THREE.DirectionalLight(new THREE.Color("hsl(240, 100%, 75%)"), 0.25);
|
||||
fillLight.position.set(100, 0, 100);
|
||||
|
||||
var backLight = new THREE.DirectionalLight(0xffffff, 0.5);
|
||||
const backLight = new THREE.DirectionalLight(0xffffff, 0.5);
|
||||
backLight.position.set(100, 0, -100).normalize();
|
||||
|
||||
this.lights = new THREE.Group();
|
||||
@@ -322,7 +316,7 @@ module.exports = {
|
||||
this.controls.enableZoom = true;
|
||||
|
||||
// Move lights with scene
|
||||
this.controls.addEventListener('change', function (scope) {
|
||||
this.controls.addEventListener("change", function (scope) {
|
||||
return function () {
|
||||
keyLight.position.copy(scope.camera.position);
|
||||
fillLight.position.copy(scope.camera.position);
|
||||
@@ -331,17 +325,16 @@ module.exports = {
|
||||
fillLight.lookAt(scope.controls.target);
|
||||
backLight.lookAt(scope.controls.target);
|
||||
scope.dirty = true;
|
||||
}
|
||||
}(this))
|
||||
};
|
||||
}(this));
|
||||
|
||||
// Events
|
||||
window.addEventListener('resize', this.update_view, false);
|
||||
window.addEventListener("resize", this.update_view, false);
|
||||
|
||||
// Start it
|
||||
this.render();
|
||||
},
|
||||
|
||||
|
||||
create_surface_material: function () {
|
||||
return new THREE.MeshPhongMaterial({
|
||||
specular: 0x111111,
|
||||
@@ -351,11 +344,10 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
draw_loading: function () {
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
var geometry = new THREE.TextGeometry('Loading 3D View...', {
|
||||
const geometry = new THREE.TextGeometry("Loading 3D View...", {
|
||||
font: new THREE.Font(font),
|
||||
size: 40,
|
||||
height: 5,
|
||||
@@ -367,8 +359,7 @@ module.exports = {
|
||||
});
|
||||
geometry.computeBoundingBox();
|
||||
|
||||
var center = geometry.center();
|
||||
var mesh = new THREE.Mesh(geometry, this.surfaceMaterial);
|
||||
const mesh = new THREE.Mesh(geometry, this.surfaceMaterial);
|
||||
|
||||
this.scene.add(mesh);
|
||||
this.scene.add(this.ambient);
|
||||
@@ -376,21 +367,22 @@ module.exports = {
|
||||
this.update_view();
|
||||
},
|
||||
|
||||
|
||||
draw_workpiece: function (scene, material) {
|
||||
if (typeof this.workpiece == 'undefined') return;
|
||||
if (typeof this.workpiece == "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
var min = this.workpiece.min;
|
||||
var max = this.workpiece.max;
|
||||
let min = this.workpiece.min;
|
||||
let max = this.workpiece.max;
|
||||
|
||||
min = new THREE.Vector3(min[0], min[1], min[2]);
|
||||
max = new THREE.Vector3(max[0], max[1], max[2]);
|
||||
var dims = max.clone().sub(min);
|
||||
const dims = max.clone().sub(min);
|
||||
|
||||
var geometry = new THREE.BoxGeometry(dims.x, dims.y, dims.z)
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
const geometry = new THREE.BoxGeometry(dims.x, dims.y, dims.z);
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
|
||||
var offset = dims.clone();
|
||||
const offset = dims.clone();
|
||||
offset.divideScalar(2);
|
||||
offset.add(min);
|
||||
|
||||
@@ -403,16 +395,15 @@ module.exports = {
|
||||
return mesh;
|
||||
},
|
||||
|
||||
|
||||
draw_surface: function (scene, material) {
|
||||
if (typeof this.vertices == 'undefined') return;
|
||||
if (typeof this.vertices == "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
|
||||
geometry.addAttribute
|
||||
('position', new THREE.Float32BufferAttribute(this.vertices, 3));
|
||||
geometry.addAttribute
|
||||
('normal', new THREE.Float32BufferAttribute(this.normals, 3));
|
||||
geometry.addAttribute("position", new THREE.Float32BufferAttribute(this.vertices, 3));
|
||||
geometry.addAttribute("normal", new THREE.Float32BufferAttribute(this.normals, 3));
|
||||
|
||||
geometry.computeBoundingSphere();
|
||||
geometry.computeBoundingBox();
|
||||
@@ -420,15 +411,16 @@ module.exports = {
|
||||
return new THREE.Mesh(geometry, material);
|
||||
},
|
||||
|
||||
|
||||
draw_tool: function (scene, bbox) {
|
||||
// Tool size is relative to bounds
|
||||
var size = bbox.getSize(new THREE.Vector3());
|
||||
var length = (size.x + size.y + size.z) / 24;
|
||||
const size = bbox.getSize(new THREE.Vector3());
|
||||
let length = (size.x + size.y + size.z) / 24;
|
||||
|
||||
if (length < 1) length = 1;
|
||||
if (length < 1) {
|
||||
length = 1;
|
||||
}
|
||||
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
const material = new THREE.MeshPhongMaterial({
|
||||
transparent: true,
|
||||
opacity: 0.75,
|
||||
specular: 0x161616,
|
||||
@@ -436,30 +428,33 @@ module.exports = {
|
||||
color: 0xffa500 // Orange
|
||||
});
|
||||
|
||||
var geometry = new THREE.CylinderGeometry(length / 2, 0, length, 128);
|
||||
const geometry = new THREE.CylinderGeometry(length / 2, 0, length, 128);
|
||||
geometry.translate(0, length / 2, 0);
|
||||
geometry.rotateX(0.5 * Math.PI);
|
||||
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
this.update_tool(mesh);
|
||||
mesh.visible = this.showTool;
|
||||
scene.add(mesh);
|
||||
return mesh;
|
||||
},
|
||||
|
||||
|
||||
draw_axis: function (axis, up, length, radius) {
|
||||
var color;
|
||||
let color;
|
||||
|
||||
if (axis == 0) color = 0xff0000; // Red
|
||||
else if (axis == 1) color = 0x00ff00; // Green
|
||||
else if (axis == 2) color = 0x0000ff; // Blue
|
||||
if (axis == 0) {
|
||||
color = 0xff0000;
|
||||
} else if (axis == 1) {
|
||||
color = 0x00ff00;
|
||||
} else if (axis == 2) {
|
||||
color = 0x0000ff;
|
||||
}
|
||||
|
||||
var group = new THREE.Group();
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
const group = new THREE.Group();
|
||||
const material = new THREE.MeshPhongMaterial({
|
||||
specular: 0x161616, shininess: 10, color: color
|
||||
});
|
||||
var geometry = new THREE.CylinderGeometry(radius, radius, length, 128);
|
||||
let geometry = new THREE.CylinderGeometry(radius, radius, length, 128);
|
||||
geometry.translate(0, -length / 2, 0);
|
||||
group.add(new THREE.Mesh(geometry, material));
|
||||
|
||||
@@ -467,28 +462,35 @@ module.exports = {
|
||||
geometry.translate(0, -length - radius, 0);
|
||||
group.add(new THREE.Mesh(geometry, material));
|
||||
|
||||
if (axis == 0) group.rotateZ((up ? 0.5 : 1.5) * Math.PI);
|
||||
else if (axis == 1) group.rotateX((up ? 0 : 1 ) * Math.PI);
|
||||
else if (axis == 2) group.rotateX((up ? 1.5 : 0.5) * Math.PI);
|
||||
if (axis == 0) {
|
||||
group.rotateZ((up ? 0.5 : 1.5) * Math.PI);
|
||||
} else if (axis == 1) {
|
||||
group.rotateX((up ? 0 : 1 ) * Math.PI);
|
||||
} else if (axis == 2) {
|
||||
group.rotateX((up ? 1.5 : 0.5) * Math.PI);
|
||||
}
|
||||
|
||||
return group;
|
||||
},
|
||||
|
||||
|
||||
draw_axes: function (scene, bbox) {
|
||||
var size = bbox.getSize(new THREE.Vector3());
|
||||
var length = (size.x + size.y + size.z) / 3;
|
||||
const size = bbox.getSize(new THREE.Vector3());
|
||||
let length = (size.x + size.y + size.z) / 3;
|
||||
length /= 10;
|
||||
|
||||
if (length < 1) length = 1;
|
||||
if (length < 1) {
|
||||
length = 1;
|
||||
}
|
||||
|
||||
var radius = length / 20;
|
||||
const radius = length / 20;
|
||||
|
||||
var group = new THREE.Group();
|
||||
const group = new THREE.Group();
|
||||
|
||||
for (var axis = 0; axis < 3; axis++)
|
||||
for (var up = 0; up < 2; up++)
|
||||
for (let axis = 0; axis < 3; axis++) {
|
||||
for (let up = 0; up < 2; up++) {
|
||||
group.add(this.draw_axis(axis, up, length, radius));
|
||||
}
|
||||
}
|
||||
|
||||
group.visible = this.showAxes;
|
||||
scene.add(group);
|
||||
@@ -496,40 +498,42 @@ module.exports = {
|
||||
return group;
|
||||
},
|
||||
|
||||
|
||||
get_color: function (speed) {
|
||||
if (isNaN(speed)) return [255, 0, 0]; // Rapid
|
||||
if (isNaN(speed)) {
|
||||
return [255, 0, 0];
|
||||
} // Rapid
|
||||
|
||||
let intensity = speed / this.toolpath.maxSpeed;
|
||||
if (typeof speed == "undefined" || !this.showIntensity) {
|
||||
intensity = 1;
|
||||
}
|
||||
|
||||
var intensity = speed / this.toolpath.maxSpeed;
|
||||
if (typeof speed == 'undefined' || !this.showIntensity) intensity = 1;
|
||||
return [0, 255 * intensity, 127 * (1 - intensity)];
|
||||
},
|
||||
|
||||
|
||||
draw_path: function (scene) {
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
var material =
|
||||
new THREE.LineBasicMaterial({
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
const material = new THREE.LineBasicMaterial({
|
||||
vertexColors: THREE.VertexColors,
|
||||
linewidth: 1.5
|
||||
});
|
||||
|
||||
var positions = new THREE.Float32BufferAttribute(this.positions, 3);
|
||||
geometry.addAttribute('position', positions);
|
||||
const positions = new THREE.Float32BufferAttribute(this.positions, 3);
|
||||
geometry.addAttribute("position", positions);
|
||||
|
||||
var colors = [];
|
||||
for (var i = 0; i < this.speeds.length; i++) {
|
||||
var color = this.get_color(this.speeds[i]);
|
||||
let colors = [];
|
||||
for (let i = 0; i < this.speeds.length; i++) {
|
||||
const color = this.get_color(this.speeds[i]);
|
||||
Array.prototype.push.apply(colors, color);
|
||||
}
|
||||
|
||||
colors = new THREE.Uint8BufferAttribute(colors, 3, true);
|
||||
geometry.addAttribute('color', colors);
|
||||
geometry.addAttribute("color", colors);
|
||||
|
||||
geometry.computeBoundingSphere();
|
||||
geometry.computeBoundingBox();
|
||||
|
||||
var line = new THREE.Line(geometry, material);
|
||||
const line = new THREE.Line(geometry, material);
|
||||
|
||||
line.visible = this.showPath;
|
||||
scene.add(line);
|
||||
@@ -537,17 +541,15 @@ module.exports = {
|
||||
return line;
|
||||
},
|
||||
|
||||
|
||||
create_empty_geom: function () {
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute('position',
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute("position",
|
||||
new THREE.Float32BufferAttribute([], 3));
|
||||
return geometry;
|
||||
},
|
||||
|
||||
|
||||
create_bbox_geom: function (bbox) {
|
||||
var vertices = [];
|
||||
const vertices = [];
|
||||
|
||||
if (!bbox.isEmpty()) {
|
||||
// Top
|
||||
@@ -581,19 +583,18 @@ module.exports = {
|
||||
vertices.push(bbox.min.x, bbox.max.y, bbox.max.z);
|
||||
}
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
|
||||
geometry.addAttribute('position',
|
||||
geometry.addAttribute("position",
|
||||
new THREE.Float32BufferAttribute(vertices, 3));
|
||||
|
||||
return geometry;
|
||||
},
|
||||
|
||||
|
||||
draw_bbox: function (scene, bbox) {
|
||||
var geometry = this.create_bbox_geom(bbox);
|
||||
var material = new THREE.LineBasicMaterial({color: 0xffffff});
|
||||
var line = new THREE.LineSegments(geometry, material);
|
||||
const geometry = this.create_bbox_geom(bbox);
|
||||
const material = new THREE.LineBasicMaterial({color: 0xffffff});
|
||||
const line = new THREE.LineSegments(geometry, material);
|
||||
|
||||
line.visible = this.showBBox;
|
||||
|
||||
@@ -602,11 +603,10 @@ module.exports = {
|
||||
return line;
|
||||
},
|
||||
|
||||
|
||||
draw_envelope: function (scene) {
|
||||
var geometry = this.create_empty_geom();
|
||||
var material = new THREE.LineBasicMaterial({color: 0x00f7ff});
|
||||
var line = new THREE.LineSegments(geometry, material);
|
||||
const geometry = this.create_empty_geom();
|
||||
const material = new THREE.LineBasicMaterial({color: 0x00f7ff});
|
||||
const line = new THREE.LineSegments(geometry, material);
|
||||
|
||||
line.visible = this.showBBox;
|
||||
|
||||
@@ -616,7 +616,6 @@ module.exports = {
|
||||
return line;
|
||||
},
|
||||
|
||||
|
||||
draw: function (scene) {
|
||||
// Lights
|
||||
scene.add(this.ambient);
|
||||
@@ -629,7 +628,7 @@ module.exports = {
|
||||
this.update_surface_mode(this.surfaceMode);
|
||||
|
||||
// Compute bounding box
|
||||
var bbox = this.get_model_bounds();
|
||||
const bbox = this.get_model_bounds();
|
||||
|
||||
// Tool, axes & bounds
|
||||
this.toolView = this.draw_tool(scene, bbox);
|
||||
@@ -638,10 +637,12 @@ module.exports = {
|
||||
this.envelopeView = this.draw_envelope(scene);
|
||||
},
|
||||
|
||||
|
||||
render: function () {
|
||||
window.requestAnimationFrame(this.render);
|
||||
if (typeof this.scene == 'undefined') return;
|
||||
|
||||
if (typeof this.scene == "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.controls.update() || this.dirty) {
|
||||
this.dirty = false;
|
||||
@@ -649,14 +650,13 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get_model_bounds: function () {
|
||||
var bbox = new THREE.Box3(new THREE.Vector3(0, 0, 0),
|
||||
const bbox = new THREE.Box3(new THREE.Vector3(0, 0, 0),
|
||||
new THREE.Vector3(0.00001, 0.00001, 0.00001));
|
||||
|
||||
function add(o) {
|
||||
if (typeof o != 'undefined') {
|
||||
var oBBox = new THREE.Box3();
|
||||
if (typeof o != "undefined") {
|
||||
const oBBox = new THREE.Box3();
|
||||
oBBox.setFromObject(o);
|
||||
bbox.union(oBBox);
|
||||
}
|
||||
@@ -669,45 +669,53 @@ module.exports = {
|
||||
return bbox;
|
||||
},
|
||||
|
||||
|
||||
snap: function (view) {
|
||||
if (this.loading) return;
|
||||
if (view != this.snapView) {
|
||||
this.snapView = view;
|
||||
cookie.set('snap-view', view);
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bbox = this.get_model_bounds();
|
||||
if (view != this.snapView) {
|
||||
this.snapView = view;
|
||||
cookie.set("snap-view", view);
|
||||
}
|
||||
|
||||
const bbox = this.get_model_bounds();
|
||||
this.controls.reset();
|
||||
bbox.getCenter(this.controls.target);
|
||||
this.update_view();
|
||||
|
||||
// Compute new camera position
|
||||
var center = bbox.getCenter(new THREE.Vector3());
|
||||
var offset = new THREE.Vector3();
|
||||
const center = bbox.getCenter(new THREE.Vector3());
|
||||
const offset = new THREE.Vector3();
|
||||
|
||||
switch (view) {
|
||||
case "isometric": offset.y -= 1; offset.z += 1; break;
|
||||
case "front": offset.y -= 1; break;
|
||||
case "back": offset.y += 1; break;
|
||||
case "left": offset.x -= 1; break;
|
||||
case "right": offset.x += 1; break;
|
||||
case "top": offset.z += 1; break;
|
||||
case "bottom": offset.z -= 1; break;
|
||||
}
|
||||
|
||||
if (view == 'isometric') {offset.y -= 1; offset.z += 1;}
|
||||
if (view == 'front') offset.y -= 1;
|
||||
if (view == 'back') offset.y += 1;
|
||||
if (view == 'left') offset.x -= 1;
|
||||
if (view == 'right') offset.x += 1;
|
||||
if (view == 'top') offset.z += 1;
|
||||
if (view == 'bottom') offset.z -= 1;
|
||||
offset.normalize();
|
||||
|
||||
// Initial camera position
|
||||
var position = new THREE.Vector3().copy(center).add(offset);
|
||||
const position = new THREE.Vector3().copy(center).add(offset);
|
||||
this.camera.position.copy(position);
|
||||
this.camera.lookAt(center); // Get correct camera orientation
|
||||
|
||||
var theta = this.camera.fov / 180 * Math.PI; // View angle
|
||||
var cameraLine = new THREE.Line3(center, position);
|
||||
var cameraUp = new THREE.Vector3().copy(this.camera.up)
|
||||
const theta = this.camera.fov / 180 * Math.PI; // View angle
|
||||
const cameraLine = new THREE.Line3(center, position);
|
||||
const cameraUp = new THREE.Vector3()
|
||||
.copy(this.camera.up)
|
||||
.applyQuaternion(this.camera.quaternion);
|
||||
var cameraLeft =
|
||||
new THREE.Vector3().copy(offset).cross(cameraUp).normalize();
|
||||
const cameraLeft = new THREE.Vector3()
|
||||
.copy(offset)
|
||||
.cross(cameraUp)
|
||||
.normalize();
|
||||
|
||||
var corners = [
|
||||
const corners = [
|
||||
new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.min.z),
|
||||
new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.max.z),
|
||||
new THREE.Vector3(bbox.min.x, bbox.max.y, bbox.min.z),
|
||||
@@ -716,39 +724,37 @@ module.exports = {
|
||||
new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.max.z),
|
||||
new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.min.z),
|
||||
new THREE.Vector3(bbox.max.x, bbox.max.y, bbox.max.z),
|
||||
]
|
||||
];
|
||||
|
||||
var dist = this.camera.near; // Min camera dist
|
||||
let dist = this.camera.near; // Min camera dist
|
||||
|
||||
for (var i = 0; i < corners.length; i++) {
|
||||
for (let i = 0; i < corners.length; i++) {
|
||||
// Project on to camera line
|
||||
var p1 = cameraLine
|
||||
.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
const p1 = cameraLine.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
|
||||
// Compute distance from projection to center
|
||||
var d = p1.distanceTo(center);
|
||||
if (cameraLine.closestPointToPointParameter(p1, false) < 0) d = -d;
|
||||
let d = p1.distanceTo(center);
|
||||
if (cameraLine.closestPointToPointParameter(p1, false) < 0) {
|
||||
d = -d;
|
||||
}
|
||||
|
||||
// Compute up line
|
||||
var up =
|
||||
new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraUp));
|
||||
const up = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraUp));
|
||||
|
||||
// Project on to up line
|
||||
var p2 = up.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
const p2 = up.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
|
||||
// Compute length
|
||||
var l = p1.distanceTo(p2);
|
||||
let l = p1.distanceTo(p2);
|
||||
|
||||
// Update min camera distance
|
||||
dist = Math.max(dist, d + l / Math.tan(theta / 2));
|
||||
|
||||
// Compute left line
|
||||
var left =
|
||||
new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraLeft));
|
||||
const left = new THREE.Line3(p1, new THREE.Vector3().copy(p1).add(cameraLeft));
|
||||
|
||||
// Project on to left line
|
||||
var p3 =
|
||||
left.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
const p3 = left.closestPointToPoint(corners[i], false, new THREE.Vector3());
|
||||
|
||||
// Compute length
|
||||
l = p1.distanceTo(p3);
|
||||
@@ -761,6 +767,5 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mixins: [require('./axis-vars')]
|
||||
}
|
||||
mixins: [require("./axis-vars")]
|
||||
};
|
||||
|
||||
113
src/js/sock.js
113
src/js/sock.js
@@ -1,38 +1,16 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
const Sock = function (url, retry, timeout) {
|
||||
if (!(this instanceof Sock)) {
|
||||
return new Sock(url, retry);
|
||||
}
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
var Sock = function (url, retry, timeout) {
|
||||
if (!(this instanceof Sock)) return new Sock(url, retry);
|
||||
|
||||
if (typeof retry == 'undefined') retry = 2000;
|
||||
if (typeof timeout == 'undefined') timeout = 16000;
|
||||
if (typeof retry == "undefined") {
|
||||
retry = 2000;
|
||||
}
|
||||
if (typeof timeout == "undefined") {
|
||||
timeout = 16000;
|
||||
}
|
||||
|
||||
this.url = url;
|
||||
this.retry = retry;
|
||||
@@ -41,87 +19,88 @@ var Sock = function (url, retry, timeout) {
|
||||
this.count = 0;
|
||||
|
||||
this.connect();
|
||||
}
|
||||
};
|
||||
|
||||
Sock.prototype.onmessage = function () {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
Sock.prototype.onmessage = function () {}
|
||||
Sock.prototype.onopen = function () {}
|
||||
Sock.prototype.onclose = function () {}
|
||||
Sock.prototype.onopen = function () {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
Sock.prototype.onclose = function () {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
Sock.prototype.connect = function () {
|
||||
console.debug('connecting to', this.url);
|
||||
console.debug("connecting to", this.url);
|
||||
this.close();
|
||||
|
||||
this._sock = new SockJS(this.url);
|
||||
|
||||
this._sock.onmessage = function (e) {
|
||||
console.debug('msg:', e.data);
|
||||
this.heartbeat('msg');
|
||||
console.debug("msg:", e.data);
|
||||
this.heartbeat("msg");
|
||||
this.onmessage(e);
|
||||
}.bind(this);
|
||||
|
||||
|
||||
this._sock.onopen = function () {
|
||||
console.debug('connected');
|
||||
this.heartbeat('open');
|
||||
console.debug("connected");
|
||||
this.heartbeat("open");
|
||||
this.onopen();
|
||||
}.bind(this);
|
||||
|
||||
|
||||
this._sock.onclose = function () {
|
||||
console.debug('disconnected');
|
||||
console.debug("disconnected");
|
||||
this._cancel_timeout();
|
||||
|
||||
this.onclose();
|
||||
if (typeof this._sock != 'undefined')
|
||||
if (typeof this._sock != "undefined") {
|
||||
setTimeout(this.connect.bind(this), this.retry);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Sock.prototype._timedout = function () {
|
||||
// Divide timeout so slow browser doesn't trigger timeouts when the
|
||||
// connection is good.
|
||||
if (this.divisions <= ++this.count) {
|
||||
console.debug('connection timedout');
|
||||
console.debug("connection timedout");
|
||||
this._timeout = undefined;
|
||||
this._sock.close();
|
||||
|
||||
} else this._set_timeout();
|
||||
}
|
||||
|
||||
} else {
|
||||
this._set_timeout();
|
||||
}
|
||||
};
|
||||
|
||||
Sock.prototype._cancel_timeout = function () {
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = undefined;
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Sock.prototype._set_timeout = function () {
|
||||
this._timeout = setTimeout(this._timedout.bind(this),
|
||||
this.timeout / this.divisions);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Sock.prototype.heartbeat = function (msg) {
|
||||
//console.debug('heartbeat ' + new Date().toLocaleTimeString() + ' ' + msg);
|
||||
Sock.prototype.heartbeat = function () {
|
||||
this._cancel_timeout();
|
||||
this._set_timeout();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Sock.prototype.close = function () {
|
||||
if (typeof this._sock != 'undefined') {
|
||||
var sock = this._sock;
|
||||
if (typeof this._sock != "undefined") {
|
||||
const sock = this._sock;
|
||||
this._sock = undefined;
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Sock.prototype.send = function (msg) {
|
||||
this._sock.send(msg);
|
||||
};
|
||||
|
||||
Sock.prototype.send = function (msg) {this._sock.send(msg)}
|
||||
|
||||
|
||||
module.exports = Sock
|
||||
module.exports = Sock;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '#templated-input-template',
|
||||
props: ['name', 'model', 'template'],
|
||||
template: "#templated-input-template",
|
||||
props: ["name", "model", "template"],
|
||||
|
||||
data: function () {
|
||||
return { view: '' }
|
||||
return { view: "" };
|
||||
},
|
||||
|
||||
computed: {
|
||||
@@ -33,10 +33,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
title: function () {
|
||||
var s = `Default :${this.template.default} ${(this.template.unit || '')}`;
|
||||
let s = `Default :${this.template.default} ${(this.template.unit || "")}`;
|
||||
|
||||
if (typeof this.template.help != 'undefined') {
|
||||
s = this.template.help + '\n' + s;
|
||||
if (typeof this.template.help != "undefined") {
|
||||
s = `${this.template.help}\n${s}`;
|
||||
}
|
||||
|
||||
return s;
|
||||
@@ -45,7 +45,7 @@ module.exports = {
|
||||
|
||||
watch: {
|
||||
_view: function () {
|
||||
this.view = this._view
|
||||
this.view = this._view;
|
||||
},
|
||||
|
||||
view: function () {
|
||||
@@ -58,12 +58,12 @@ module.exports = {
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.view = this._view
|
||||
this.view = this._view;
|
||||
},
|
||||
|
||||
methods: {
|
||||
change: function () {
|
||||
this.$dispatch('input-changed')
|
||||
this.$dispatch("input-changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,39 +1,12 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
|
||||
This file ("the software") is free software: you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License,
|
||||
version 2 as published by the Free Software Foundation. You should
|
||||
have received a copy of the GNU General Public License, version 2
|
||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The software is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the software. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict';
|
||||
|
||||
const api = require('./api');
|
||||
const modbus = require('./modbus.js');
|
||||
const api = require("./api");
|
||||
const modbus = require("./modbus.js");
|
||||
const merge = require("lodash.merge");
|
||||
|
||||
module.exports = {
|
||||
template: '#tool-view-template',
|
||||
props: ['config', 'template', 'state'],
|
||||
template: "#tool-view-template",
|
||||
props: ["config", "template", "state"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
@@ -110,20 +83,22 @@ module.exports = {
|
||||
unsupported: true
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
'modbus-reg': require('./modbus-reg.js')
|
||||
"modbus-reg": require("./modbus-reg.js")
|
||||
},
|
||||
|
||||
watch: {
|
||||
'state.mr': function () { this.value = this.state.mr }
|
||||
"state.mr": function () {
|
||||
this.value = this.state.mr;
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
'input-changed': function () {
|
||||
this.$dispatch('config-changed');
|
||||
"input-changed": function () {
|
||||
this.$dispatch("config-changed");
|
||||
|
||||
return false;
|
||||
},
|
||||
@@ -135,19 +110,19 @@ module.exports = {
|
||||
|
||||
computed: {
|
||||
regs_tmpl: function () {
|
||||
return this.template['modbus-spindle'].regs;
|
||||
return this.template["modbus-spindle"].regs;
|
||||
},
|
||||
|
||||
tool_type: function () {
|
||||
return this.config.tool['tool-type'].toUpperCase();
|
||||
return this.config.tool["tool-type"].toUpperCase();
|
||||
},
|
||||
|
||||
selected_tool: function () {
|
||||
return this.config.tool['selected-tool'];
|
||||
return this.config.tool["selected-tool"];
|
||||
},
|
||||
|
||||
is_pwm_spindle: function () {
|
||||
return this.selected_tool == 'pwm';
|
||||
return this.selected_tool == "pwm";
|
||||
},
|
||||
|
||||
is_modbus: function () {
|
||||
@@ -170,13 +145,13 @@ module.exports = {
|
||||
|
||||
methods: {
|
||||
change_selected_tool: function () {
|
||||
const selectedToolSettings = this.config['selected-tool-settings'] || {};
|
||||
const selectedToolSettings = this.config["selected-tool-settings"] || {};
|
||||
const settings = selectedToolSettings[this.selected_tool] || {};
|
||||
this.config.tool = merge({}, this.config.tool, settings['tool']);
|
||||
this.config['pwm-spindle'] = merge({}, this.config['pwm-spindle'], settings['pwm-spindle']);
|
||||
this.config['modbus-spindle'] = merge({}, this.config['modbus-spindle'], settings['modbus-spindle']);
|
||||
this.config.tool = merge({}, this.config.tool, settings["tool"]);
|
||||
this.config["pwm-spindle"] = merge({}, this.config["pwm-spindle"], settings["pwm-spindle"]);
|
||||
this.config["modbus-spindle"] = merge({}, this.config["modbus-spindle"], settings["modbus-spindle"]);
|
||||
|
||||
const tool = this.toolList.find(tool => tool.id == this.config.tool['selected-tool']);
|
||||
const tool = this.toolList.find(tool => tool.id == this.config.tool["selected-tool"]);
|
||||
this.config.tool["tool-type"] = tool.type || tool.name;
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
@@ -207,71 +182,71 @@ module.exports = {
|
||||
},
|
||||
|
||||
get_reg_type: function (reg) {
|
||||
return this.regs_tmpl.template['reg-type'].values[this.state[reg + 'vt']];
|
||||
return this.regs_tmpl.template["reg-type"].values[this.state[`${reg}vt`]];
|
||||
},
|
||||
|
||||
get_reg_addr: function (reg) {
|
||||
return this.state[reg + 'va'];
|
||||
return this.state[`${reg}va`];
|
||||
},
|
||||
|
||||
get_reg_value: function (reg) {
|
||||
return this.state[reg + 'vv'];
|
||||
return this.state[`${reg}vv`];
|
||||
},
|
||||
|
||||
get_reg_fails: function (reg) {
|
||||
const fails = this.state[reg + 'vr']
|
||||
return fails == 255 ? 'Max' : fails;
|
||||
const fails = this.state[`${reg}vr`];
|
||||
return fails == 255 ? "Max" : fails;
|
||||
},
|
||||
|
||||
show_modbus_field: function (key) {
|
||||
return key != 'regs' &&
|
||||
(key != 'multi-write' || this.tool_type == 'CUSTOM MODBUS VFD');
|
||||
return key != "regs" && (key != "multi-write" || this.tool_type == "CUSTOM MODBUS VFD");
|
||||
},
|
||||
|
||||
read: function (e) {
|
||||
e.preventDefault();
|
||||
api.put('modbus/read', { address: this.address });
|
||||
api.put("modbus/read", { address: this.address });
|
||||
},
|
||||
|
||||
write: function (e) {
|
||||
e.preventDefault();
|
||||
api.put('modbus/write', { address: this.address, value: this.value });
|
||||
api.put("modbus/write", { address: this.address, value: this.value });
|
||||
},
|
||||
|
||||
customize: function (e) {
|
||||
e.preventDefault();
|
||||
this.config.tool['tool-type'] = 'Custom Modbus VFD';
|
||||
this.config.tool["tool-type"] = "Custom Modbus VFD";
|
||||
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
const reg = this.regs_tmpl.index[i];
|
||||
regs[i]['reg-type'] = this.get_reg_type(reg);
|
||||
regs[i]['reg-addr'] = this.get_reg_addr(reg);
|
||||
regs[i]['reg-value'] = this.get_reg_value(reg);
|
||||
regs[i]["reg-type"] = this.get_reg_type(reg);
|
||||
regs[i]["reg-addr"] = this.get_reg_addr(reg);
|
||||
regs[i]["reg-value"] = this.get_reg_value(reg);
|
||||
}
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
clear: function (e) {
|
||||
e.preventDefault();
|
||||
this.config.tool['tool-type'] = 'Custom Modbus VFD';
|
||||
this.config.tool["tool-type"] = "Custom Modbus VFD";
|
||||
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
regs[i]['reg-type'] = 'disabled';
|
||||
regs[i]['reg-addr'] = 0;
|
||||
regs[i]['reg-value'] = 0;
|
||||
regs[i]["reg-type"] = "disabled";
|
||||
regs[i]["reg-addr"] = 0;
|
||||
regs[i]["reg-value"] = 0;
|
||||
}
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
reset_failures: function (e) {
|
||||
e.preventDefault();
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
for (let reg = 0; reg < regs.length; reg++)
|
||||
this.$dispatch('send', '\$' + reg + 'vr=0');
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let reg = 0; reg < regs.length; reg++) {
|
||||
this.$dispatch("send", `$${reg}vr=0`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '{{text}}<span class="unit">{{metric ? unit : iunit}}</span>',
|
||||
props: ['value', 'precision', 'unit', 'iunit', 'scale'],
|
||||
props: ["value", "precision", "unit", "iunit", "scale"],
|
||||
|
||||
computed: {
|
||||
metric: {
|
||||
@@ -14,9 +14,9 @@ module.exports = {
|
||||
},
|
||||
|
||||
text: function () {
|
||||
var value = this.value;
|
||||
if (typeof value == 'undefined') {
|
||||
return '';
|
||||
let value = this.value;
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!this.metric) {
|
||||
@@ -28,20 +28,20 @@ module.exports = {
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
if (typeof this.precision == 'undefined') {
|
||||
if (typeof this.precision == "undefined") {
|
||||
this.precision = 0;
|
||||
}
|
||||
|
||||
if (typeof this.unit == 'undefined') {
|
||||
this.unit = 'mm';
|
||||
if (typeof this.unit == "undefined") {
|
||||
this.unit = "mm";
|
||||
}
|
||||
|
||||
if (typeof this.iunit == 'undefined') {
|
||||
this.iunit = 'in';
|
||||
if (typeof this.iunit == "undefined") {
|
||||
this.iunit = "in";
|
||||
}
|
||||
|
||||
if (typeof this.scale == 'undefined') {
|
||||
if (typeof this.scale == "undefined") {
|
||||
this.scale = 25.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
9
src/js/utils.js
Normal file
9
src/js/utils.js
Normal file
@@ -0,0 +1,9 @@
|
||||
function clickFileInput(formClass) {
|
||||
const form = document.querySelector(`.${formClass}`);
|
||||
form.reset();
|
||||
form.querySelector("input").click();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clickFileInput
|
||||
};
|
||||
@@ -99,20 +99,26 @@
|
||||
{#each $networkInfo.wifi.networks as network}
|
||||
<Item
|
||||
class="wifi-network"
|
||||
on:SMUI:action={() => onNetworkSelected(network)}
|
||||
on:SMUI:action={() =>
|
||||
onNetworkSelected(network)}
|
||||
>
|
||||
<Graphic
|
||||
class="strength {$networkInfo.wifi.ssid === network.Name
|
||||
class="strength {$networkInfo.wifi
|
||||
.ssid === network.Name
|
||||
? 'active'
|
||||
: ''}"
|
||||
>
|
||||
<span class="fa fa-wifi background" />
|
||||
<span
|
||||
class="fa fa-wifi"
|
||||
style={getWifiStrengthStyle(network)}
|
||||
style={getWifiStrengthStyle(
|
||||
network
|
||||
)}
|
||||
/>
|
||||
</Graphic>
|
||||
<Text style="margin-right: 20px;">{network.Name}</Text>
|
||||
<Text style="margin-right: 20px;"
|
||||
>{network.Name}</Text
|
||||
>
|
||||
{#if network.Encryption !== "Open"}
|
||||
<Meta>
|
||||
<span class="fa fa-lock" />
|
||||
|
||||
@@ -66,21 +66,21 @@
|
||||
</fieldset>
|
||||
|
||||
<p>
|
||||
Lower <tt>max-deviation</tt> to follow the programmed path more precisely but
|
||||
at a slower speed.
|
||||
Lower <tt>max-deviation</tt> to follow the programmed path more precisely
|
||||
but at a slower speed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In order to improve traversal speed, the path planner may merge consecutive
|
||||
moves or round off sharp corners if doing so would deviate from the program
|
||||
path by less than <tt>max-deviation</tt>.
|
||||
In order to improve traversal speed, the path planner may merge
|
||||
consecutive moves or round off sharp corners if doing so would deviate
|
||||
from the program path by less than <tt>max-deviation</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
GCode commands
|
||||
<a href={`${gcodeURL}#gcode:g61`} target="_blank">G61, G61.1</a>
|
||||
and <a href={`${gcodeURL}#gcode:g64`} target="_blank"> G64</a> also affect path
|
||||
planning accuracy.
|
||||
and <a href={`${gcodeURL}#gcode:g64`} target="_blank"> G64</a> also affect
|
||||
path planning accuracy.
|
||||
</p>
|
||||
|
||||
<h2>Cornering Speed (Advanced)</h2>
|
||||
@@ -91,7 +91,7 @@
|
||||
<p>
|
||||
Junction acceleration limits the cornering speed the planner will allow.
|
||||
Increasing this value will allow for faster traversal of corners but may
|
||||
cause the planner to violate axis jerk limits and stall the motors. Use with
|
||||
caution.
|
||||
cause the planner to violate axis jerk limits and stall the motors. Use
|
||||
with caution.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import TextField from "@smui/textfield";
|
||||
import MessageDialog from "$dialogs/MessageDialog.svelte";
|
||||
@@ -88,7 +93,11 @@
|
||||
<Button>
|
||||
<Label>Cancel</Label>
|
||||
</Button>
|
||||
<Button defaultAction on:click={onConfirm} disabled={hostname.length === 0}>
|
||||
<Button
|
||||
defaultAction
|
||||
on:click={onConfirm}
|
||||
disabled={hostname.length === 0}
|
||||
>
|
||||
<Label>Confirm & Reboot</Label>
|
||||
</Button>
|
||||
</Actions>
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
axis: string;
|
||||
};
|
||||
|
||||
const SetAxisPositionDialogProps = writable<SetAxisPositionDialogPropsType>();
|
||||
const SetAxisPositionDialogProps =
|
||||
writable<SetAxisPositionDialogPropsType>();
|
||||
type SetAxisPositionDialogPropsType = {
|
||||
open: boolean;
|
||||
axis: string;
|
||||
@@ -190,12 +191,14 @@
|
||||
);
|
||||
|
||||
keyboardObserver = new MutationObserver(() => {
|
||||
const open = virtualKeyboard.getAttribute("_state") === "open";
|
||||
const open =
|
||||
virtualKeyboard.getAttribute("_state") === "open";
|
||||
const keyboardHeight = Number.parseFloat(
|
||||
virtualKeyboardOverlay.style.height
|
||||
);
|
||||
|
||||
const dialogContainers = document.querySelectorAll<HTMLDivElement>(
|
||||
const dialogContainers =
|
||||
document.querySelectorAll<HTMLDivElement>(
|
||||
".mdc-dialog .mdc-dialog__container"
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
|
||||
export let open;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import TextField from "@smui/textfield";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import { ControllerMethods } from "$lib/RegisterControllerMethods";
|
||||
@@ -21,9 +26,10 @@
|
||||
aria-labelledby="manual-home-axis-dialog-title"
|
||||
aria-describedby="manual-home-axis-dialog-content"
|
||||
>
|
||||
<Title id="manual-home-axis-dialog-title"
|
||||
>Manually Home {axis.toUpperCase()} Axis</Title
|
||||
>
|
||||
<Title id="manual-home-axis-dialog-title">
|
||||
Manually Home {axis.toUpperCase()} Axis
|
||||
</Title>
|
||||
|
||||
<Content id="manual-home-axis-dialog-content">
|
||||
<p>Set axis absolute position</p>
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
|
||||
export let open: boolean;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"1/16 in",
|
||||
"1/32 in",
|
||||
];
|
||||
|
||||
const metricBits: `${number} mm`[] = [
|
||||
"12 mm",
|
||||
"10 mm",
|
||||
@@ -289,17 +290,21 @@
|
||||
|
||||
<Content id="probe-dialog-content" style="overflow: visible;">
|
||||
<div class="steps">
|
||||
<p><b>Step {steps.indexOf(currentStep) + 1} of {steps.length}</b></p>
|
||||
<p>
|
||||
<b>Step {steps.indexOf(currentStep) + 1} of {steps.length}</b>
|
||||
</p>
|
||||
<ul>
|
||||
{#each steps as step}
|
||||
<li class:active={currentStep === step}>{stepLabels[step]}</li>
|
||||
<li class:active={currentStep === step}>
|
||||
{stepLabels[step]}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
{#if currentStep === "CheckProbe"}
|
||||
Attach the probe magnet to the collet, then touch the probe block to the
|
||||
bit.
|
||||
Attach the probe magnet to the collet, then touch the probe
|
||||
block to the bit.
|
||||
{:else if currentStep === "BitDimensions"}
|
||||
<TextFieldWithOptions
|
||||
label="Cutter diameter"
|
||||
@@ -313,13 +318,17 @@
|
||||
/>
|
||||
{:else if currentStep === "PlaceProbeBlock"}
|
||||
{#if probeType === "xyz"}
|
||||
Place the probe block face up, on the lower-left corner of your
|
||||
workpiece.
|
||||
Place the probe block face up, on the lower-left corner of
|
||||
your workpiece.
|
||||
{:else}
|
||||
Place the probe block face down, with the bit above the recess.
|
||||
Place the probe block face down, with the bit above the
|
||||
recess.
|
||||
{/if}
|
||||
|
||||
<p>The probing procedure will begin as soon as you click 'Next'.</p>
|
||||
<p>
|
||||
The probing procedure will begin as soon as you click
|
||||
'Next'.
|
||||
</p>
|
||||
{:else if currentStep === "Probe"}
|
||||
Probing in progress...
|
||||
{:else if currentStep === "Done"}
|
||||
@@ -327,7 +336,9 @@
|
||||
Could not find the probe block during probing!
|
||||
|
||||
<p>
|
||||
Make sure the tip of the bit is less than {metric ? "25mm" : "1 in"}
|
||||
Make sure the tip of the bit is less than {metric
|
||||
? "25mm"
|
||||
: "1 in"}
|
||||
above the probe block, and try again.
|
||||
</p>
|
||||
{:else}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script type="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import Radio from "@smui/radio";
|
||||
import FormField from "@smui/form-field";
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import TextField from "@smui/textfield";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import { ControllerMethods } from "$lib/RegisterControllerMethods";
|
||||
@@ -35,9 +40,10 @@
|
||||
aria-labelledby="set-axis-position-dialog-title"
|
||||
aria-describedby="set-axis-position-dialog-content"
|
||||
>
|
||||
<Title id="set-axis-position-dialog-title"
|
||||
>Set {axis.toUpperCase()} Axis Position</Title
|
||||
>
|
||||
<Title id="set-axis-position-dialog-title">
|
||||
Set {axis.toUpperCase()} Axis Position
|
||||
</Title>
|
||||
|
||||
<Content id="set-axis-position-dialog-content">
|
||||
<TextField
|
||||
label="Position"
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import TextField from "@smui/textfield";
|
||||
import CircularProgress from "@smui/circular-progress";
|
||||
@@ -131,24 +136,27 @@
|
||||
<Content id="set-time-dialog-content">
|
||||
{#if loading}
|
||||
<div style="display: flex; justify-content: center">
|
||||
<CircularProgress style="height: 32px; width: 32px;" indeterminate />
|
||||
<CircularProgress
|
||||
style="height: 32px; width: 32px;"
|
||||
indeterminate
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
{#if networkTimeSynchronized}
|
||||
<p>
|
||||
Because this controller is connected to the internet, the time is
|
||||
managed automatically, and cannot be manually set.
|
||||
Because this controller is connected to the internet, the
|
||||
time is managed automatically, and cannot be manually set.
|
||||
</p>
|
||||
{:else}
|
||||
<p>
|
||||
Because this controller is not connected to the internet, you can
|
||||
manually set the time.
|
||||
Because this controller is not connected to the internet,
|
||||
you can manually set the time.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note: any time the controller is turned off, the time will need to be
|
||||
reset. If you connect the controller to the internet, the time will be
|
||||
managed automatically.
|
||||
Note: any time the controller is turned off, the time will
|
||||
need to be reset. If you connect the controller to the
|
||||
internet, the time will be managed automatically.
|
||||
</p>
|
||||
|
||||
<Label>Date & Time</Label>
|
||||
@@ -156,7 +164,10 @@
|
||||
bind:value
|
||||
use={[
|
||||
InitialFocus,
|
||||
[virtualKeyboardChange, (newValue) => (value = newValue)],
|
||||
[
|
||||
virtualKeyboardChange,
|
||||
(newValue) => (value = newValue),
|
||||
],
|
||||
]}
|
||||
label="Time"
|
||||
type="datetime-local"
|
||||
@@ -166,8 +177,8 @@
|
||||
{/if}
|
||||
|
||||
<p>
|
||||
To display your local time correctly, the controller must know what
|
||||
timezone it is in.
|
||||
To display your local time correctly, the controller must know
|
||||
what timezone it is in.
|
||||
</p>
|
||||
|
||||
<div class="timezones-container" style="margin-top: 20px;">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import * as Api from "$lib/api"
|
||||
import * as Api from "$lib/api";
|
||||
|
||||
export let open;
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import LinearProgress from "@smui/linear-progress";
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Dialog, { Title, Content, Actions, InitialFocus } from "@smui/dialog";
|
||||
import Dialog, {
|
||||
Title,
|
||||
Content,
|
||||
Actions,
|
||||
InitialFocus,
|
||||
} from "@smui/dialog";
|
||||
import Button, { Label } from "@smui/button";
|
||||
import TextField from "@smui/textfield";
|
||||
import Icon from "@smui/textfield/icon";
|
||||
@@ -60,7 +65,10 @@
|
||||
bind:value={password}
|
||||
use={[
|
||||
InitialFocus,
|
||||
[virtualKeyboardChange, (newValue) => (password = newValue)],
|
||||
[
|
||||
virtualKeyboardChange,
|
||||
(newValue) => (password = newValue),
|
||||
],
|
||||
]}
|
||||
label="Password"
|
||||
spellcheck="false"
|
||||
@@ -72,7 +80,9 @@
|
||||
slot="trailingIcon"
|
||||
on:click={() => (showPassword = !showPassword)}
|
||||
>
|
||||
<Icon class={`fa ${showPassword ? "fa-eye-slash" : "fa-eye"}`} />
|
||||
<Icon
|
||||
class={`fa ${showPassword ? "fa-eye-slash" : "fa-eye"}`}
|
||||
/>
|
||||
</div>
|
||||
<HelperText persistent slot="helper">
|
||||
Wifi passwords must be 8 to 128 characters
|
||||
@@ -82,7 +92,8 @@
|
||||
|
||||
<p>
|
||||
<em>
|
||||
Clicking {connectOrDisconnect} will reboot the controller to apply the changes.
|
||||
Clicking {connectOrDisconnect} will reboot the controller to apply
|
||||
the changes.
|
||||
</em>
|
||||
</p>
|
||||
</Content>
|
||||
@@ -95,7 +106,8 @@
|
||||
<Button
|
||||
defaultAction
|
||||
on:click={onConfirm}
|
||||
disabled={needPassword && (password.length < 8 || password.length > 128)}
|
||||
disabled={needPassword &&
|
||||
(password.length < 8 || password.length > 128)}
|
||||
>
|
||||
<Label>{connectOrDisconnect} & Reboot</Label>
|
||||
</Button>
|
||||
|
||||
@@ -31,15 +31,15 @@ const empty: NetworkInfo = {
|
||||
ssid: "",
|
||||
networks: []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const networkInfo = writable<NetworkInfo>(empty);
|
||||
|
||||
export function processNetworkInfo(rawNetworkInfo: NetworkInfo) {
|
||||
const now = Date.now();
|
||||
const networksByName: Record<string, WifiNetwork> = {}
|
||||
const networksByName: Record<string, WifiNetwork> = {};
|
||||
|
||||
for (let network of rawNetworkInfo.wifi.networks) {
|
||||
for (const network of rawNetworkInfo.wifi.networks) {
|
||||
if (network.Name) {
|
||||
network.lastSeen = now;
|
||||
network.active = rawNetworkInfo.wifi.ssid === network.Name;
|
||||
@@ -53,7 +53,7 @@ export function processNetworkInfo(rawNetworkInfo: NetworkInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
for (let network of Object.values(networksByName)) {
|
||||
for (const network of Object.values(networksByName)) {
|
||||
if (network.lastSeen - now > 30000) {
|
||||
delete networksByName[network.Name];
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
type NumberWithUnit = {
|
||||
value: number,
|
||||
metric: boolean,
|
||||
toMetric: () => number;
|
||||
}
|
||||
|
||||
function numberWithUnitToMetric() {
|
||||
return this.metric ? this.value : this.value * 25.4;
|
||||
}
|
||||
@@ -38,12 +32,13 @@ function formatFraction(value: number) {
|
||||
export const numberWithUnit = {
|
||||
regex: /^\s*(?:(\d+)\s*\/\s*(\d+)|(\d*\.\d+)|(\d+(?:\.\d+)?))\s*("|in|inch|inches|mm|millimeters)\s*$/,
|
||||
parse: function (str: string) {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [, numerator, denominator, decimal1, decimal2, unit]: any = str?.match(numberWithUnit.regex) ?? [];
|
||||
|
||||
numerator = Number.parseFloat(numerator)
|
||||
denominator = Number.parseFloat(denominator)
|
||||
decimal1 = Number.parseFloat(decimal1)
|
||||
decimal2 = Number.parseFloat(decimal2)
|
||||
numerator = Number.parseFloat(numerator);
|
||||
denominator = Number.parseFloat(denominator);
|
||||
decimal1 = Number.parseFloat(decimal1);
|
||||
decimal2 = Number.parseFloat(decimal2);
|
||||
|
||||
const metric = (unit ?? "").includes("m");
|
||||
|
||||
@@ -81,10 +76,10 @@ export const numberWithUnit = {
|
||||
return "";
|
||||
|
||||
case value.metric:
|
||||
return `${value.value} mm`
|
||||
return `${value.value} mm`;
|
||||
|
||||
default:
|
||||
return `${formatFraction(value.value)} in`
|
||||
return `${formatFraction(value.value)} in`;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,36 +6,36 @@ async function doFetch(method: HttpMethod, url: string, data: any, config: Reque
|
||||
...config,
|
||||
method,
|
||||
cache: "no-cache",
|
||||
body: (typeof data === 'object')
|
||||
body: (typeof data === "object")
|
||||
? JSON.stringify(data)
|
||||
: undefined,
|
||||
headers: (typeof data === 'object')
|
||||
headers: (typeof data === "object")
|
||||
? {
|
||||
"Content-Type": 'application/json; charset=utf-8'
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
}
|
||||
: {}
|
||||
});
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.debug('API Error: ' + url + ': ' + error);
|
||||
console.debug(`API Error: ${url}: ${error}`);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(url: string, config: RequestInit = {}) {
|
||||
return doFetch('GET', url, undefined, config);
|
||||
return doFetch("GET", url, undefined, config);
|
||||
}
|
||||
|
||||
export async function PUT(url: string, data: any = undefined, config: RequestInit = {}) {
|
||||
return doFetch('PUT', url, data, config);
|
||||
return doFetch("PUT", url, data, config);
|
||||
}
|
||||
|
||||
export async function POST(url: string, data: any = undefined, config: RequestInit = {}) {
|
||||
return doFetch('POST', url, data, config);
|
||||
return doFetch("POST", url, data, config);
|
||||
}
|
||||
|
||||
export async function DELETE(url: string, config = {}) {
|
||||
return doFetch('DELETE', url, undefined, config);
|
||||
return doFetch("DELETE", url, undefined, config);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import 'polyfill-object.fromentries';
|
||||
import "polyfill-object.fromentries";
|
||||
import matchAll from "string.prototype.matchall";
|
||||
|
||||
matchAll.shim();
|
||||
|
||||
import AdminNetworkView from '$components/AdminNetworkView.svelte';
|
||||
import SettingsView from '$components/SettingsView.svelte';
|
||||
import AdminNetworkView from "$components/AdminNetworkView.svelte";
|
||||
import SettingsView from "$components/SettingsView.svelte";
|
||||
import DialogHost, { showDialog } from "$dialogs/DialogHost.svelte";
|
||||
import { handleConfigUpdate, setDisplayUnits } from '$lib/ConfigStore';
|
||||
import { handleConfigUpdate, setDisplayUnits } from "$lib/ConfigStore";
|
||||
import { handleControllerStateUpdate } from "$lib/ControllerState";
|
||||
import { registerControllerMethods } from "$lib/RegisterControllerMethods";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user