Added units switching
Added layer reordering Fixed a few issues related to non-millimeter units Edge/End components were incorrectly named, whoops
This commit is contained in:
parent
ef79e6891b
commit
ce1e31432f
8
TODO.md
8
TODO.md
@ -1,20 +1,16 @@
|
||||
ToDo
|
||||
====
|
||||
|
||||
Must have
|
||||
----
|
||||
- Implement switching units
|
||||
- Re-ordering of the layers (preferably drag/drop)
|
||||
|
||||
Should have
|
||||
----
|
||||
- Render width and height of the boards in the previews
|
||||
- Material usage overview
|
||||
- Generate cutting list
|
||||
- Support for fractional inches (see, not all europeans look down on freedom units!)
|
||||
- Save/load via URL (MessagePack encoded Base64 in URL)
|
||||
|
||||
Nice to have
|
||||
----
|
||||
- Render width and height of the boards in the previews (simplified version implemented, moved to Nice to have)
|
||||
- More advanced options, like custom direction per strip and mixing multiple edge grain boards with different layers for the end grain board (the code is half prepared for this by having the boards array encapsulating the layers, though it's all hardcoded to board[0] now)
|
||||
- 3D effect for previews emulating thickness / crosscut width
|
||||
- Make it a tiny bit prettier overall
|
||||
|
10
src/App.vue
10
src/App.vue
@ -17,7 +17,7 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="file" id="loadFile" accept=".json" />
|
||||
<input type="file" ref="loadFile" accept=".json" />
|
||||
<button @click="load()">Load</button>
|
||||
</p>
|
||||
</div>
|
||||
@ -35,10 +35,10 @@
|
||||
|
||||
<div class="app-preview">
|
||||
<h1>Edge grain</h1>
|
||||
<EndGrainPreview :scale="1" />
|
||||
<EdgeGrainPreview :scale="1" />
|
||||
|
||||
<h1>End grain</h1>
|
||||
<EdgeGrainPreview :scale="1" />
|
||||
<EndGrainPreview :scale="1" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -80,7 +80,7 @@ export default {
|
||||
|
||||
load()
|
||||
{
|
||||
const loadFile = document.getElementById("loadFile").files[0];
|
||||
const loadFile = this.$refs.loadFile.files[0];
|
||||
if (!loadFile)
|
||||
return;
|
||||
|
||||
@ -139,7 +139,7 @@ h1
|
||||
}
|
||||
}
|
||||
|
||||
.about, .todo
|
||||
.about
|
||||
{
|
||||
width: 30em;
|
||||
}
|
||||
|
@ -1,27 +1,19 @@
|
||||
<template>
|
||||
<div class="preview">
|
||||
<div class="dimensions">Dimensions: {{ display(boardWidth) }} x {{ display(boardHeight) }} x {{ display(settings.boardThickness) }}</div>
|
||||
|
||||
<svg
|
||||
:width="viewportWidth"
|
||||
:height="viewportHeight"
|
||||
:viewBox="viewBox">
|
||||
<defs>
|
||||
<g id="strip">
|
||||
<rect
|
||||
v-for="(layer, index) in layers"
|
||||
:width="toPixels(settings.boardThickness)"
|
||||
:height="toPixels(layer.width)"
|
||||
x="0"
|
||||
:y="getLayerOffset(index)"
|
||||
:style="getLayerStyle(index)" />
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<use
|
||||
v-for="(strip, index) in stripsPerBoard"
|
||||
xlink:href="#strip"
|
||||
:x="index * settings.boardThickness"
|
||||
y="0"
|
||||
:transform="getLayerTransform(index)" />
|
||||
<rect
|
||||
v-for="(layer, index) in layers"
|
||||
:width="toPixels(settings.boardLength)"
|
||||
:height="toPixels(layer.width)"
|
||||
x="0"
|
||||
:y="getLayerOffset(index)"
|
||||
:style="getLayerStyle(index)" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
@ -40,20 +32,7 @@ export default {
|
||||
wood() { return this.$store.state.wood; },
|
||||
layers() { return this.$store.state.boards[0].layers; },
|
||||
|
||||
stripsPerBoard()
|
||||
{
|
||||
const stripAndKerf = this.settings.crosscutWidth + this.settings.bladeKerf;
|
||||
if (stripAndKerf === 0)
|
||||
return 0;
|
||||
|
||||
return Math.floor((this.settings.boardLength + this.settings.bladeKerf) / stripAndKerf);
|
||||
},
|
||||
|
||||
boardWidth()
|
||||
{
|
||||
const boardWidth = this.stripsPerBoard * this.settings.boardThickness;
|
||||
return this.toPixels(boardWidth);
|
||||
},
|
||||
boardWidth() { return this.settings.boardLength; },
|
||||
|
||||
boardHeight()
|
||||
{
|
||||
@ -62,9 +41,19 @@ export default {
|
||||
.reduce((accumulator, currentValue) => accumulator + currentValue);
|
||||
},
|
||||
|
||||
viewportWidth() { return Math.floor(this.boardWidth * this.scale); },
|
||||
viewportHeight() { return Math.floor(this.boardHeight * this.scale); },
|
||||
viewBox() { return '0 0 ' + this.boardWidth + ' ' + this.boardHeight; }
|
||||
boardPixelWidth()
|
||||
{
|
||||
return this.toPixels(this.boardWidth);
|
||||
},
|
||||
|
||||
boardPixelHeight()
|
||||
{
|
||||
return this.toPixels(this.boardHeight);
|
||||
},
|
||||
|
||||
viewportWidth() { return Math.floor(this.boardPixelWidth * this.scale); },
|
||||
viewportHeight() { return Math.floor(this.boardPixelHeight * this.scale); },
|
||||
viewBox() { return '0 0 ' + this.boardPixelWidth + ' ' + this.boardPixelHeight; }
|
||||
},
|
||||
|
||||
|
||||
@ -74,6 +63,11 @@ export default {
|
||||
return units.toPixels(value, this.settings.units);
|
||||
},
|
||||
|
||||
display(value)
|
||||
{
|
||||
return units.display(value, this.settings.units);
|
||||
},
|
||||
|
||||
getLayerOffset(index)
|
||||
{
|
||||
if (index < 0 || index >= this.layers.length)
|
||||
@ -84,7 +78,7 @@ export default {
|
||||
for (let i = 0; i < index; i++)
|
||||
offset += this.layers[i].width;
|
||||
|
||||
return offset;
|
||||
return this.toPixels(offset);
|
||||
},
|
||||
|
||||
getLayerStyle(index)
|
||||
@ -101,14 +95,6 @@ export default {
|
||||
: '';
|
||||
|
||||
return 'fill: ' + this.wood[woodIndex].color + borderStyle;
|
||||
},
|
||||
|
||||
getLayerTransform(index)
|
||||
{
|
||||
if (!this.settings.alternateDirection || (index % 2) == 0)
|
||||
return '';
|
||||
|
||||
return 'scale(1, -1) translate(0, -' + this.boardHeight + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,29 @@
|
||||
<template>
|
||||
<div class="preview">
|
||||
<div class="dimensions">Dimensions: {{ display(boardWidth) }} x {{ display(boardHeight) }} x {{ display(settings.crosscutWidth) }}</div>
|
||||
|
||||
<svg
|
||||
:width="viewportWidth"
|
||||
:height="viewportHeight"
|
||||
:viewBox="viewBox">
|
||||
<defs>
|
||||
<g id="strip">
|
||||
<rect
|
||||
v-for="(layer, index) in layers"
|
||||
:width="toPixels(settings.boardThickness)"
|
||||
:height="toPixels(layer.width)"
|
||||
x="0"
|
||||
:y="getLayerOffset(index)"
|
||||
:style="getLayerStyle(index)" />
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<rect
|
||||
v-for="(layer, index) in layers"
|
||||
:width="toPixels(settings.boardLength)"
|
||||
:height="toPixels(layer.width)"
|
||||
x="0"
|
||||
:y="getLayerOffset(index)"
|
||||
:style="getLayerStyle(index)" />
|
||||
<use
|
||||
v-for="(strip, index) in stripsPerBoard"
|
||||
xlink:href="#strip"
|
||||
:x="toPixels(index * settings.boardThickness)"
|
||||
y="0"
|
||||
:transform="getLayerTransform(index)" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
@ -30,7 +42,19 @@ export default {
|
||||
wood() { return this.$store.state.wood; },
|
||||
layers() { return this.$store.state.boards[0].layers; },
|
||||
|
||||
boardWidth() { return this.toPixels(this.settings.boardLength); },
|
||||
stripsPerBoard()
|
||||
{
|
||||
const stripAndKerf = this.settings.crosscutWidth + this.settings.bladeKerf;
|
||||
if (stripAndKerf === 0)
|
||||
return 0;
|
||||
|
||||
return Math.floor((this.settings.boardLength + this.settings.bladeKerf) / stripAndKerf);
|
||||
},
|
||||
|
||||
boardWidth()
|
||||
{
|
||||
return this.stripsPerBoard * this.settings.boardThickness;
|
||||
},
|
||||
|
||||
boardHeight()
|
||||
{
|
||||
@ -39,9 +63,19 @@ export default {
|
||||
.reduce((accumulator, currentValue) => accumulator + currentValue);
|
||||
},
|
||||
|
||||
viewportWidth() { return Math.floor(this.boardWidth * this.scale); },
|
||||
viewportHeight() { return Math.floor(this.boardHeight * this.scale); },
|
||||
viewBox() { return '0 0 ' + this.boardWidth + ' ' + this.boardHeight; }
|
||||
boardPixelWidth()
|
||||
{
|
||||
return this.toPixels(this.boardWidth);
|
||||
},
|
||||
|
||||
boardPixelHeight()
|
||||
{
|
||||
return this.toPixels(this.boardHeight);
|
||||
},
|
||||
|
||||
viewportWidth() { return Math.floor(this.boardPixelWidth * this.scale); },
|
||||
viewportHeight() { return Math.floor(this.boardPixelHeight * this.scale); },
|
||||
viewBox() { return '0 0 ' + this.boardPixelWidth + ' ' + this.boardPixelHeight; }
|
||||
},
|
||||
|
||||
|
||||
@ -51,6 +85,11 @@ export default {
|
||||
return units.toPixels(value, this.settings.units);
|
||||
},
|
||||
|
||||
display(value)
|
||||
{
|
||||
return units.display(value, this.settings.units);
|
||||
},
|
||||
|
||||
getLayerOffset(index)
|
||||
{
|
||||
if (index < 0 || index >= this.layers.length)
|
||||
@ -61,7 +100,7 @@ export default {
|
||||
for (let i = 0; i < index; i++)
|
||||
offset += this.layers[i].width;
|
||||
|
||||
return offset;
|
||||
return this.toPixels(offset);
|
||||
},
|
||||
|
||||
getLayerStyle(index)
|
||||
@ -78,6 +117,14 @@ export default {
|
||||
: '';
|
||||
|
||||
return 'fill: ' + this.wood[woodIndex].color + borderStyle;
|
||||
},
|
||||
|
||||
getLayerTransform(index)
|
||||
{
|
||||
if (!this.settings.alternateDirection || (index % 2) == 0)
|
||||
return '';
|
||||
|
||||
return 'scale(1, -1) translate(0, -' + this.boardPixelHeight + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,18 @@
|
||||
<button @click="addLayer()">Add layer</button>
|
||||
</div>
|
||||
|
||||
<div class="hint">
|
||||
Tip: click and drag the layer number to move a layer
|
||||
</div>
|
||||
|
||||
|
||||
<span class="header"> </span>
|
||||
<span class="header">Wood type</span>
|
||||
<span class="header">Width</span>
|
||||
<span class="header"> </span>
|
||||
|
||||
<template v-for="(layer, index) in layers">
|
||||
<div class="index">{{ index + 1 }}</div>
|
||||
<div class="index" :class="{ dropTargetAbove: dropTarget === index, dropTargetBelow: dropTarget === layers.length && index === layers.length - 1 }" :ref="'layer' + index" @mousedown.prevent="startDrag(index)">{{ index + 1 }}</div>
|
||||
<select v-model="layer.wood" class="wood">
|
||||
<option v-for="(item, index) in wood" :value="index">{{ item.name }}</option>
|
||||
</select>
|
||||
@ -27,6 +32,15 @@
|
||||
import { units } from '../lib/units';
|
||||
|
||||
export default {
|
||||
data()
|
||||
{
|
||||
return {
|
||||
dragIndex: null,
|
||||
dropTarget: null
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
settings() { return this.$store.state.settings; },
|
||||
wood() { return this.$store.state.wood; },
|
||||
@ -51,6 +65,91 @@ export default {
|
||||
removeLayer(index)
|
||||
{
|
||||
this.$store.commit('removeLayer', { board: 0, layer: index });
|
||||
},
|
||||
|
||||
|
||||
startDrag(index)
|
||||
{
|
||||
this.dragIndex = index;
|
||||
this.dropTarget = index;
|
||||
|
||||
const dragMouseMove = (event) =>
|
||||
{
|
||||
this.dropTarget = this.getTargetLayer(event.pageY);
|
||||
};
|
||||
|
||||
let dragMouseUp;
|
||||
dragMouseUp = () =>
|
||||
{
|
||||
document.removeEventListener('mousemove', dragMouseMove);
|
||||
document.removeEventListener('mouseup', dragMouseUp);
|
||||
|
||||
if (this.dragIndex !== this.dropTarget)
|
||||
this.$store.commit('moveLayer', { board: 0, from: this.dragIndex, to: this.dropTarget });
|
||||
|
||||
this.dropTarget = null;
|
||||
this.dragIndex = null;
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', dragMouseMove);
|
||||
document.addEventListener('mouseup', dragMouseUp);
|
||||
},
|
||||
|
||||
|
||||
getTargetLayer(yPos)
|
||||
{
|
||||
if (this.layers.length == 0)
|
||||
return null;
|
||||
|
||||
const firstLayer = this.getPageOffsetRect(this.$refs.layer0);
|
||||
const lastLayer = this.getPageOffsetRect(this.$refs['layer' + (this.layers.length - 1)]);
|
||||
|
||||
// On or above the first item
|
||||
if (yPos <= firstLayer.bottom)
|
||||
return 0;
|
||||
|
||||
// Below the last item
|
||||
if (yPos >= lastLayer.bottom)
|
||||
return this.layers.length;
|
||||
|
||||
// On the last item
|
||||
if (yPos >= lastLayer.top)
|
||||
return this.layers.length - 1;
|
||||
|
||||
// Check the previous target first, as it is most likely unchanged due to how
|
||||
// often mouseMove events occur
|
||||
if (this.dropTarget !== null && this.dropTarget > 0 && this.dropTarget < this.layers.length - 1)
|
||||
{
|
||||
const currentTarget = this.getPageOffsetRect(this.$refs['layer' + this.dropTarget]);
|
||||
if (yPos >= currentTarget.top && yPos < currentTarget.bottom)
|
||||
return this.dropTarget;
|
||||
}
|
||||
|
||||
// Just loop through all the layers, there shouldn't be enough to warrant anything more efficient
|
||||
for (let i = 1; i < this.layers.length - 1; i++)
|
||||
{
|
||||
const testTarget = this.getPageOffsetRect(this.$refs['layer' + i]);
|
||||
if (yPos >= testTarget.top && yPos < testTarget.bottom)
|
||||
return i;
|
||||
}
|
||||
|
||||
// This should never occur, so it probably will!
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
getPageOffsetRect(element)
|
||||
{
|
||||
const clientRect = element.getBoundingClientRect();
|
||||
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
return {
|
||||
top: clientRect.top + scrollTop,
|
||||
left: clientRect.left + scrollLeft,
|
||||
right: clientRect.right + scrollLeft,
|
||||
bottom: clientRect.bottom + scrollTop
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,6 +162,30 @@ export default {
|
||||
grid-template-columns: 3em 20em 5em 3em;
|
||||
grid-column-gap: 1em;
|
||||
|
||||
.hint
|
||||
{
|
||||
color: #808080;
|
||||
text-align: center;
|
||||
|
||||
grid-column: 1 / 5;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.index
|
||||
{
|
||||
cursor: pointer;
|
||||
|
||||
&.dropTargetAbove
|
||||
{
|
||||
border-top: solid 1px black;
|
||||
}
|
||||
|
||||
&.dropTargetBelow
|
||||
{
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
}
|
||||
|
||||
.add
|
||||
{
|
||||
grid-column: 2 / 5;
|
||||
|
@ -3,10 +3,11 @@
|
||||
<h2>Designer</h2>
|
||||
|
||||
<label for="units">Units</label>
|
||||
<select id="units" disabled>
|
||||
<select id="units" :value="settings.units" @change="$store.commit('updateSettings', { units: $event.target.value })">
|
||||
<option value="mm">Millimeters</option>
|
||||
<option value="cm">Centimeters</option>
|
||||
<option value="inch">Inches (fractional)</option>
|
||||
<option value="inchdecimal">Inches (decimal)</option>
|
||||
<!--<option value="inchfractional">Inches (fractional)</option>-->
|
||||
</select>
|
||||
|
||||
<label for="borders">Show borders</label>
|
||||
|
@ -5,9 +5,16 @@ const pixelsPerMillimeter = 1;
|
||||
|
||||
|
||||
const units = {
|
||||
convert(value, fromUnits, toUnits)
|
||||
{
|
||||
const millimeters = this.toMillimeters(value, fromUnits);
|
||||
return this.fromMillimeters(millimeters, toUnits);
|
||||
},
|
||||
|
||||
|
||||
toPixels(value, units)
|
||||
{
|
||||
return this.toMillimeters(value, units) * pixelsPerMillimeter;
|
||||
return Math.ceil(this.toMillimeters(value, units) * pixelsPerMillimeter);
|
||||
},
|
||||
|
||||
|
||||
@ -17,7 +24,7 @@ const units = {
|
||||
{
|
||||
case 'mm': return value;
|
||||
case 'cm': return value * millimetersPerCentimeter;
|
||||
case 'inch': return value * millimetersPerInch;
|
||||
case 'inchdecimal': return value * millimetersPerInch;
|
||||
}
|
||||
|
||||
console.error('Invalid units type: ' + units);
|
||||
@ -31,11 +38,35 @@ const units = {
|
||||
{
|
||||
case 'mm': return value;
|
||||
case 'cm': return value / millimetersPerCentimeter;
|
||||
case 'inch': return value / millimetersPerInch;
|
||||
case 'inchdecimal': return value / millimetersPerInch;
|
||||
}
|
||||
|
||||
console.error('Invalid units type: ' + units);
|
||||
return 0;
|
||||
},
|
||||
|
||||
|
||||
display(value, units)
|
||||
{
|
||||
const displayValue = this.limitDecimals(value, 3);
|
||||
|
||||
switch (units)
|
||||
{
|
||||
case 'mm': return displayValue + ' mm';
|
||||
case 'cm': return displayValue + ' cm';
|
||||
case 'inchdecimal': return displayValue + ' inch';
|
||||
}
|
||||
|
||||
console.error('Invalid units type: ' + units);
|
||||
return displayValue;
|
||||
},
|
||||
|
||||
|
||||
limitDecimals(value, decimals)
|
||||
{
|
||||
// toFixed turns it into a string and pads it with zeroes
|
||||
const power = Math.pow(10, decimals);
|
||||
return Math.round(value * power) / power;
|
||||
}
|
||||
};
|
||||
|
||||
|
89
src/store.js
89
src/store.js
@ -25,12 +25,12 @@ function parseFloatDef(value)
|
||||
export default createStore({
|
||||
state: {
|
||||
settings: {
|
||||
units: 'mm',
|
||||
units: 'cm',
|
||||
borders: false,
|
||||
boardThickness: 20,
|
||||
boardLength: 700,
|
||||
bladeKerf: 3.5,
|
||||
crosscutWidth: 30,
|
||||
boardThickness: 2,
|
||||
boardLength: 70,
|
||||
bladeKerf: 0.35,
|
||||
crosscutWidth: 3,
|
||||
|
||||
alternateDirection: true
|
||||
},
|
||||
@ -50,20 +50,14 @@ export default createStore({
|
||||
boards: [
|
||||
{
|
||||
layers: [
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 },
|
||||
{ wood: 0, width: 20 },
|
||||
{ wood: 1, width: 20 }
|
||||
{ wood: 8, width: 1 },
|
||||
{ wood: 1, width: 1.5 },
|
||||
{ wood: 8, width: 2 },
|
||||
{ wood: 1, width: 2 },
|
||||
{ wood: 8, width: 15 },
|
||||
{ wood: 1, width: 2 },
|
||||
{ wood: 8, width: 1.5 },
|
||||
{ wood: 1, width: 1 }
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -86,10 +80,43 @@ export default createStore({
|
||||
if (payload.board < 0 || payload.board >= state.boards.length)
|
||||
return;
|
||||
|
||||
if (payload.layer < 0 || payload.layer >= state.boards[payload.board].length)
|
||||
const board = state.boards[payload.board];
|
||||
|
||||
if (payload.layer < 0 || payload.layer >= board.layers.length)
|
||||
return;
|
||||
|
||||
state.boards[payload.board].layers.splice(payload.layer, 1);
|
||||
board.layers.splice(payload.layer, 1);
|
||||
},
|
||||
|
||||
moveLayer(state, payload)
|
||||
{
|
||||
if (payload.board < 0 || payload.board >= state.boards.length)
|
||||
return;
|
||||
|
||||
const board = state.boards[payload.board];
|
||||
|
||||
if (payload.from < 0 || payload.from >= board.layers.length)
|
||||
return;
|
||||
|
||||
if (payload.to < 0 || payload.to > board.layers.length)
|
||||
return;
|
||||
|
||||
if (payload.to == board.layers.length)
|
||||
{
|
||||
// Move to end
|
||||
board.layers.push(board.layers[payload.from]);
|
||||
board.layers.splice(payload.from, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const item = board.layers[payload.from];
|
||||
board.layers.splice(payload.from, 1);
|
||||
|
||||
if (payload.to > payload.from)
|
||||
payload.to--;
|
||||
|
||||
board.layers.splice(payload.to, 0, item);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -124,7 +151,27 @@ export default createStore({
|
||||
|
||||
updateSettings(state, payload)
|
||||
{
|
||||
const oldUnits = state.settings.units;
|
||||
|
||||
mergeObject(payload, state.settings);
|
||||
|
||||
if (oldUnits !== state.settings.units)
|
||||
{
|
||||
// Convert the settings
|
||||
state.settings.boardThickness = units.limitDecimals(units.convert(state.settings.boardThickness, oldUnits, state.settings.units), 3);
|
||||
state.settings.boardLength = units.limitDecimals(units.convert(state.settings.boardLength, oldUnits, state.settings.units), 3);
|
||||
state.settings.bladeKerf = units.limitDecimals(units.convert(state.settings.bladeKerf, oldUnits, state.settings.units), 3);
|
||||
state.settings.crosscutWidth = units.limitDecimals(units.convert(state.settings.crosscutWidth, oldUnits, state.settings.units), 3);
|
||||
|
||||
// Convert the layers
|
||||
state.boards.forEach(board =>
|
||||
{
|
||||
board.layers.forEach(layer =>
|
||||
{
|
||||
layer.width = units.limitDecimals(units.convert(layer.width, oldUnits, state.settings.units), 3);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user