refactor: split ExtruderControlPanel.vue in multiple SFC (#1565)

This commit is contained in:
Stefan Dej 2023-09-24 01:16:59 +02:00 committed by GitHub
parent 79014acf7f
commit 890b9969ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 892 additions and 802 deletions

View File

@ -59,7 +59,7 @@
<v-icon>{{ mdiMenuDown }}</v-icon>
</v-btn>
<v-dialog v-model="paramsDialog">
<panel :title="macro.name" :card-class="`macro-params-mobile-${macro.name}`" :margin-bottom="0">
<panel :title="macro.name" :card-class="`macro-params-mobile-${macro.name}`" :margin-bottom="false">
<template #buttons>
<v-btn icon tile @click="paramsDialog = false">
<v-icon>{{ mdiCloseThick }}</v-icon>
@ -101,6 +101,8 @@ import BaseMixin from '@/components/mixins/base'
import { GuiMacrosStateMacrogroupMacro } from '@/store/gui/macros/types'
import { mdiCloseThick, mdiMenuDown, mdiRefresh } from '@mdi/js'
import Panel from '@/components/ui/Panel.vue'
import { TranslateResult } from 'vue-i18n'
import { PrinterStateMacro } from '@/store/printer/types'
interface param {
type: 'int' | 'double' | 'string' | null
@ -128,13 +130,13 @@ export default class MacroButton extends Mixins(BaseMixin) {
private paramsDialog = false
@Prop({ required: true })
declare readonly macro: GuiMacrosStateMacrogroupMacro
declare readonly macro: GuiMacrosStateMacrogroupMacro | PrinterStateMacro
@Prop({ default: 'primary' })
declare readonly color: string
@Prop({ default: null })
declare readonly alias: string
declare readonly alias: string | TranslateResult
@Prop({ default: false })
declare readonly disabled: boolean

View File

@ -53,6 +53,7 @@ import Component from 'vue-class-component'
import { Mixins, Prop, Watch } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { mdiChevronDown, mdiChevronUp, mdiRestart } from '@mdi/js'
import { TranslateResult } from 'vue-i18n'
@Component
export default class NumberInput extends Mixins(BaseMixin) {
@ -65,48 +66,23 @@ export default class NumberInput extends Mixins(BaseMixin) {
private invalidChars: string[] = ['e', 'E', '+']
// input field name and identifier
@Prop({ type: String, required: true })
declare readonly label: string
@Prop({ type: String, required: true })
declare readonly param: string
@Prop({ required: true }) declare readonly label: TranslateResult | string
@Prop({ type: String, required: true }) declare readonly param: string
// props defining incoming data
@Prop({ type: Number, required: true })
declare readonly target: number
@Prop({ type: Number, required: false })
declare readonly defaultValue: number
@Prop({ type: Number, required: true }) declare readonly target: number
@Prop({ type: Number, required: false }) declare readonly defaultValue: number
// props for internal processing
@Prop({ type: Number, required: true })
declare readonly min: number
@Prop({ type: Number, default: null })
declare readonly max: number | null
@Prop({ type: Number, required: true })
declare readonly dec: number
@Prop({ type: Number, required: false, default: 1 })
declare readonly step: number
@Prop({ type: String, required: false })
declare readonly unit: string
@Prop({ type: Number, required: true }) declare readonly min: number
@Prop({ default: null }) declare readonly max: number | null
@Prop({ type: Number, required: true }) declare readonly dec: number
@Prop({ type: Number, required: false, default: 1 }) declare readonly step: number
@Prop({ type: String, required: false }) declare readonly unit: string
// spinner related props
@Prop({ type: Boolean, required: false, default: false })
declare readonly hasSpinner: boolean
@Prop({ type: Number, required: false, default: 1 })
declare readonly spinnerFactor: number
@Prop({ type: Boolean, required: false, default: false }) declare readonly hasSpinner: boolean
@Prop({ type: Number, required: false, default: 1 }) declare readonly spinnerFactor: number
// props for general internal behaviour
@Prop({ type: Boolean, required: false, default: false })
declare readonly disabled: boolean
@Prop({ type: Boolean, required: false, default: false })
declare readonly outputErrorMsg: boolean
@Prop({ type: Boolean, required: false, default: false }) declare readonly disabled: boolean
@Prop({ type: Boolean, required: false, default: false }) declare readonly outputErrorMsg: boolean
created(): void {
this.value = this.target.toString()

View File

@ -47,6 +47,10 @@ export default class BaseMixin extends Vue {
return this.klipperReadyForGui && ['printing', 'paused'].includes(this.printer_state)
}
get printerIsPrintingOnly() {
return this.klipperReadyForGui && this.printer_state === 'printing'
}
get printerPowerDevice(): string {
let deviceName = this.$store.state.gui.uiSettings.powerDeviceName ?? null
if (deviceName === null) deviceName = 'printer'

View File

@ -0,0 +1,40 @@
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
@Component
export default class ExtruderMixin extends Vue {
get activeExtruder(): string {
return this.$store.state.printer.toolhead?.extruder
}
get activeExtruderSettings(): any {
return this.$store.state.printer.configfile?.settings?.[this.activeExtruder]
}
get filamentDiameter(): number {
return this.activeExtruderSettings?.filament_diameter ?? 1.75
}
get nozzleDiameter(): number {
return this.activeExtruderSettings?.nozzle_diameter ?? 0.4
}
get feedamount(): number {
return parseFloat(this.$store.state.gui.control.extruder.feedamount)
}
get feedrate(): number {
return parseFloat(this.$store.state.gui.control.extruder.feedrate)
}
get extrudeFactor() {
return this.$store.state.printer?.gcode_move?.extrude_factor ?? 1
}
get extrudePossible(): boolean {
return this.$store.getters['printer/getExtrudePossible']
}
get minExtrudeTemp(): number {
return this.activeExtruderSettings?.min_extrude_temp ?? 170
}
}

View File

@ -0,0 +1,42 @@
<template>
<v-container v-if="showEstimatedExtrusion" class="pa-0 ma-0 pb-1">
<div style="font-size: 0.8em" class="text--disabled text-caption font-weight-light d-flex justify-center">
<span>
{{ $t('Panels.ExtruderControlPanel.EstimatedExtrusion') }} ~ {{ extrudedLength }} mm @
{{ volumetricFlow }} mm³/s -
<v-icon x-small style="opacity: 0.4; margin-top: -2px">
{{ mdiDiameterVariant }}
</v-icon>
{{ nozzleDiameter }} mm
</span>
</div>
</v-container>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { mdiDiameterVariant } from '@mdi/js'
import ExtruderMixin from '@/components/mixins/extruder'
@Component({})
export default class PressureAdvanceSettings extends Mixins(BaseMixin, ExtruderMixin) {
mdiDiameterVariant = mdiDiameterVariant
get showEstimatedExtrusion() {
return this.$store.state.gui.control.extruder.showEstimatedExtrusionInfo ?? true
}
get extrudedLength(): number {
return Math.round(
this.feedamount *
this.extrudeFactor *
(Math.pow(this.filamentDiameter, 2) / Math.pow(this.nozzleDiameter, 2))
)
}
get volumetricFlow(): number {
return Math.round(Math.pow(this.filamentDiameter / 2, 2) * Math.PI * this.feedrate * 10) / 10
}
}
</script>

View File

@ -0,0 +1,320 @@
<template>
<responsive :breakpoints="{ large: (el) => el.width >= 640 }">
<template #default="{ el }">
<v-container>
<v-row>
<v-col>
<number-input
:label="$t('Panels.ExtruderControlPanel.FilamentLength')"
param="feedamount"
:target="feedamount"
:disabled="printerIsPrintingOnly"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="100"
:step="0.01"
:min="0.01"
:max="maxExtrudeOnlyDistance"
:dec="2"
unit="mm"
:submit-on-blur="true"
@submit="setFeedamount" />
<v-item-group class="_btn-group pt-3">
<v-btn
v-for="value in feedamountsSorted"
:key="value"
:disabled="printerIsPrintingOnly"
dense
class="_btn-qs flex-grow-1 px-0"
@click="setFeedamount({ value })">
{{ value }}
</v-btn>
</v-item-group>
</v-col>
<v-col>
<number-input
:label="$t('Panels.ExtruderControlPanel.ExtrusionFeedrate')"
param="feedrate"
:target="feedrate"
:disabled="printerIsPrintingOnly"
:has-spinner="true"
:output-error-msg="true"
:spinner-factor="100"
:step="0.01"
:min="0.01"
:max="null"
:dec="2"
type="number"
unit="mm/s"
@submit="setFeedrate" />
<v-item-group class="_btn-group pt-3">
<v-btn
v-for="value in feedratesSorted"
:key="value"
:disabled="printerIsPrintingOnly"
dense
class="_btn-qs flex-grow-1 px-0"
@click="setFeedrate({ value })">
{{ value }}
</v-btn>
</v-item-group>
</v-col>
<!-- EXTRUDE AND RETRACT BUTTON LARGE SIZED PANEL -->
<v-col v-if="el.is.large" class="col-3 d-flex align-center flex-column justify-center">
<!-- RETRACT -->
<v-tooltip left :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="mb-4" v-on="on">
<v-btn
:loading="loadings.includes('btnRetract')"
:disabled="!extrudePossible || tooLargeExtrusion || printerIsPrintingOnly"
small
class="_btn-extruder-cmd"
@click="sendRetract()">
<v-icon small class="mr-1">{{ mdiArrowUpBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Retract') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}: {{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
<!-- EXTRUDE -->
<v-tooltip left :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div v-on="on">
<v-btn
:loading="loadings.includes('btnDetract')"
:disabled="!extrudePossible || tooLargeExtrusion || printerIsPrintingOnly"
small
class="_btn-extruder-cmd"
@click="sendExtrude()">
<v-icon small class="mr-1">{{ mdiArrowDownBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Extrude') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}: {{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
</v-col>
</v-row>
<!-- EXTRUDE AND RETRACT BUTTON SMALL AND MEDIUM SIZED PANEL -->
<v-row v-if="!el.is.large">
<v-col class="pa-0">
<div class="d-flex justify-space-around">
<div class="d-flex align-center">
<!-- RETRACT -->
<v-tooltip top :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="pt-1 pb-2 px-3" v-on="on">
<v-btn
:loading="loadings.includes('btnRetract')"
:disabled="
!extrudePossible || tooLargeExtrusion || printerIsPrintingOnly
"
small
class="_btn-extruder-cmd"
@click="sendRetract()">
<v-icon small class="mr-1">{{ mdiArrowUpBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Retract') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
<!-- EXTRUDE -->
<v-tooltip top :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="pt-1 pb-2 px-3" v-on="on">
<v-btn
:loading="loadings.includes('btnDetract')"
:disabled="
!extrudePossible || tooLargeExtrusion || printerIsPrintingOnly
"
small
class="_btn-extruder-cmd"
@click="sendExtrude()">
<v-icon small class="mr-1">{{ mdiArrowDownBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Extrude') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
</div>
</div>
</v-col>
</v-row>
</v-container>
</template>
</responsive>
</template>
<script lang="ts">
import { mdiArrowDownBold, mdiArrowUpBold, mdiPrinter3dNozzle } from '@mdi/js'
import { Component, Mixins, Watch } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import NumberInput from '@/components/inputs/NumberInput.vue'
import Responsive from '@/components/ui/Responsive.vue'
import ToolSlider from '@/components/inputs/ToolSlider.vue'
import ExtruderMixin from '@/components/mixins/extruder'
@Component({
components: {
NumberInput,
Responsive,
ToolSlider,
},
})
export default class ExtruderControlPanel extends Mixins(BaseMixin, ExtruderMixin) {
mdiArrowDownBold = mdiArrowDownBold
mdiArrowUpBold = mdiArrowUpBold
mdiPrinter3dNozzle = mdiPrinter3dNozzle
get feedamounts(): number[] {
return this.$store.state.gui.control.extruder?.feedamounts ?? []
}
get feedrates(): number[] {
return this.$store.state.gui.control.extruder?.feedrates ?? []
}
get feedamountsSorted(): number[] {
return [...this.feedamounts].sort((a, b) => {
return b - a
})
}
get feedratesSorted(): number[] {
return [...this.feedrates].sort((a, b) => {
return b - a
})
}
setFeedamount(params: { value: number }): void {
this.$store.dispatch('gui/saveSetting', { name: 'control.extruder.feedamount', value: params.value })
}
setFeedrate(params: { value: number }): void {
this.$store.dispatch('gui/saveSetting', { name: 'control.extruder.feedrate', value: params.value })
}
get maxExtrudeOnlyDistance(): number {
return this.activeExtruderSettings?.max_extrude_only_distance ?? 50
}
get tooLargeExtrusion(): boolean {
return this.feedamount * this.extrudeFactor > this.maxExtrudeOnlyDistance
}
@Watch('maxExtrudeOnlyDistance', { immediate: true })
onMaxExtrudeOnlyDistanceChange(): void {
/**
* If, while switching from ex. A to ex. B, the feedamount
* from ex. an exceeds the maxExtrudeOnlyDistance of ex. B,
* set the feedamount to maxExtrudeOnlyDistance of ex. B
*/
if (this.feedamount > this.maxExtrudeOnlyDistance) {
this.setFeedamount({ value: this.maxExtrudeOnlyDistance })
}
}
sendRetract(): void {
const gcode = `M83\nG1 E-${this.feedamount} F${this.feedrate * 60}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode }, { loading: 'btnRetract' })
}
sendExtrude(): void {
const gcode = `M83\nG1 E${this.feedamount} F${this.feedrate * 60}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode }, { loading: 'btnDetract' })
}
}
</script>
<style lang="scss" scoped>
._btn-group {
border-radius: 4px;
display: inline-flex;
flex-wrap: nowrap;
max-width: 100%;
min-width: 100%;
width: 100%;
.v-btn {
border-radius: 0;
border-color: rgba(255, 255, 255, 0.12);
border-style: solid;
border-width: thin;
box-shadow: none;
height: 28px;
opacity: 0.8;
min-width: auto !important;
}
.v-btn:first-child {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
.v-btn:last-child {
border-top-right-radius: inherit;
border-bottom-right-radius: inherit;
}
.v-btn:not(:first-child) {
border-left-width: 0;
}
}
._btn-qs {
font-size: 0.8rem !important;
max-height: 24px;
}
._btn-extruder-cmd {
min-width: 135px !important;
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<v-item-group v-if="toolchangeMacros.length > 1" class="_btn-group py-0 px-3 mt-3">
<extruder-control-panel-tools-item v-for="macro in toolchangeMacros" :key="macro.name" :macro="macro" />
</v-item-group>
</template>
<script lang="ts">
import { mdiPrinter3dNozzle } from '@mdi/js'
import { Component, Mixins } from 'vue-property-decorator'
import { PrinterStateMacro, PrinterStateToolchangeMacro } from '@/store/printer/types'
import BaseMixin from '@/components/mixins/base'
import ControlMixin from '@/components/mixins/control'
@Component({})
export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin) {
mdiPrinter3dNozzle = mdiPrinter3dNozzle
get macros() {
return this.$store.getters['printer/getMacros']
}
get toolchangeMacros(): PrinterStateToolchangeMacro[] {
return this.macros
.filter((macro: PrinterStateMacro) => macro.name.toUpperCase().match(/^T\d+/))
.sort((a: PrinterStateMacro, b: PrinterStateMacro) => {
const numberA = parseInt(a.name.slice(1))
const numberB = parseInt(b.name.slice(1))
return numberA - numberB
})
}
}
</script>
<style lang="scss" scoped>
._btn-group {
border-radius: 4px;
display: inline-flex;
flex-wrap: nowrap;
max-width: 100%;
min-width: 100%;
width: 100%;
.v-btn {
border-radius: 0;
border-color: rgba(255, 255, 255, 0.12);
border-style: solid;
border-width: thin;
box-shadow: none;
height: 28px;
opacity: 0.8;
min-width: auto !important;
}
.v-btn:first-child {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
.v-btn:last-child {
border-top-right-radius: inherit;
border-bottom-right-radius: inherit;
}
.v-btn:not(:first-child) {
border-left-width: 0;
}
}
</style>

View File

@ -0,0 +1,45 @@
<template>
<v-btn
:class="buttonClass"
:disabled="printerIsPrintingOnly"
:style="buttonStyle"
dense
class="flex-grow-1 px-0"
@click="doSend(macro.name)">
{{ macro.name }}
</v-btn>
</template>
<script lang="ts">
import { Component, Mixins, Prop } from 'vue-property-decorator'
import { PrinterStateMacro } from '@/store/printer/types'
import BaseMixin from '@/components/mixins/base'
import ControlMixin from '@/components/mixins/control'
@Component({
components: {},
})
export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin) {
@Prop({ type: Object }) macro!: PrinterStateMacro
get active() {
return this.macro.variables.active ?? false
}
get color() {
return this.macro.variables.color ?? this.macro.variables.colour ?? null
}
get buttonClass() {
return {
'primary--text': this.active,
}
}
get buttonStyle() {
return {
'background-color': '#' + this.color,
}
}
}
</script>

View File

@ -0,0 +1,27 @@
<template>
<v-container class="pb-1">
<tool-slider
:label="$t('Panels.ExtruderControlPanel.ExtrusionFactor')"
:icon="mdiPrinter3dNozzleOutline"
:target="extrudeFactor"
:min="1"
:max="200"
:multi="100"
:step="1"
:has-input-field="true"
command="M221"
attribute-name="S" />
</v-container>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { mdiPrinter3dNozzleOutline } from '@mdi/js'
import ExtruderMixin from '@/components/mixins/extruder'
@Component({})
export default class PressureAdvanceSettings extends Mixins(BaseMixin, ExtruderMixin) {
mdiPrinter3dNozzleOutline = mdiPrinter3dNozzleOutline
}
</script>

View File

@ -0,0 +1,148 @@
<template>
<div v-if="existsFirmwareRetraction">
<v-divider />
<v-container>
<responsive
:breakpoints="{
small: (el) => el.width <= 350,
}">
<template #default="{ el }">
<v-row>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.RetractLength')"
param="RETRACT_LENGTH"
:target="retractLength"
:default-value="defaultRetractLength"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:step="0.01"
:min="0"
:max="null"
:dec="2"
unit="mm"
@submit="sendCmd" />
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.RetractSpeed')"
param="RETRACT_SPEED"
:target="retractSpeed"
:default-value="defaultRetractSpeed"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="5"
:step="1"
:min="1"
:max="null"
:dec="0"
unit="mm/s"
@submit="sendCmd" />
</v-col>
</v-row>
<v-row>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="
$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.UnretractExtraLength')
"
param="UNRETRACT_EXTRA_LENGTH"
:target="unretractExtraLength"
:default-value="defaultUnretractExtraLength"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:step="0.01"
:min="0"
:max="null"
:dec="2"
unit="mm"
@submit="sendCmd" />
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.UnretractSpeed')"
param="UNRETRACT_SPEED"
:target="unretractSpeed"
:default-value="defaultUnretractSpeed"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="5"
:step="1"
:min="1"
:max="null"
:dec="0"
unit="mm/s"
@submit="sendCmd" />
</v-col>
</v-row>
</template>
</responsive>
</v-container>
</div>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { Debounce } from 'vue-debounce-decorator'
import BaseMixin from '@/components/mixins/base'
import Panel from '@/components/ui/Panel.vue'
import NumberInput from '@/components/inputs/NumberInput.vue'
import Responsive from '@/components/ui/Responsive.vue'
import ControlMixin from '@/components/mixins/control'
@Component({
components: { Panel, NumberInput, Responsive },
})
export default class FirmwareRetractionSettings extends Mixins(BaseMixin, ControlMixin) {
get retractLength(): number {
return Math.floor((this.$store.state.printer?.firmware_retraction?.retract_length ?? 0) * 100) / 100
}
get retractSpeed(): number {
return Math.trunc(this.$store.state.printer?.firmware_retraction?.retract_speed ?? 20)
}
get unretractExtraLength(): number {
return Math.floor((this.$store.state.printer?.firmware_retraction?.unretract_extra_length ?? 0) * 100) / 100
}
get unretractSpeed(): number {
return Math.trunc(this.$store.state.printer?.firmware_retraction?.unretract_speed ?? 10)
}
get defaultRetractLength(): number {
return (
Math.floor(
(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.retract_length ?? 0) * 100
) / 100
)
}
get defaultRetractSpeed(): number {
return Math.trunc(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.retract_speed ?? 20)
}
get defaultUnretractExtraLength(): number {
return (
Math.floor(
(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.unretract_extra_length ?? 0) *
100
) / 100
)
}
get defaultUnretractSpeed(): number {
return Math.trunc(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.unretract_speed ?? 0)
}
@Debounce(500)
sendCmd(params: { name: string; value: number }): void {
const gcode = `SET_RETRACTION ${params.name}=${params.value}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode })
}
}
</script>

View File

@ -0,0 +1,144 @@
<template>
<div v-if="show">
<v-divider />
<v-container>
<responsive
:breakpoints="{
small: (el) => el.width <= 350,
medium: (el) => el.width > 350 && el.width <= 500,
}">
<template #default="{ el }">
<v-row>
<v-col v-if="allExtruders.length > 1" :class="{ 'col-12': el.is.small || el.is.medium }">
<div class="d-flex align-center">
<v-btn
v-if="selectedExtruder !== activeExtruder"
icon
plain
@click="resetToActiveExtruder">
<v-icon>{{ mdiRestart }}</v-icon>
</v-btn>
<v-select
v-model="selectedExtruder"
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.Extruder')"
:items="allExtruders"
:value="activeExtruder"
hide-details
outlined
dense />
</div>
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.Advance')"
param="ADVANCE"
:target="pressureAdvance"
:default-value="defaultPressureAdvance"
:extruder="selectedExtruder"
:output-error-msg="true"
:has-spinner="true"
:min="0"
:max="null"
:step="0.001"
:dec="3"
unit="s"
@submit="sendCmd" />
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.SmoothTime')"
param="SMOOTH_TIME"
:target="smoothTime"
:default-value="defaultSmoothTime"
:extruder="selectedExtruder"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:min="0"
:max="0.2"
:step="0.001"
:dec="3"
unit="s"
@submit="sendCmd" />
</v-col>
</v-row>
</template>
</responsive>
</v-container>
</div>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { Debounce } from 'vue-debounce-decorator'
import BaseMixin from '@/components/mixins/base'
import NumberInput from '@/components/inputs/NumberInput.vue'
import Panel from '@/components/ui/Panel.vue'
import Responsive from '@/components/ui/Responsive.vue'
import { mdiRestart } from '@mdi/js'
@Component({
components: { NumberInput, Panel, Responsive },
})
export default class PressureAdvanceSettings extends Mixins(BaseMixin) {
mdiRestart = mdiRestart
private extruders: string[] = []
private selectedExtruder = ''
resetToActiveExtruder(): void {
this.selectedExtruder = this.$store.state.printer.toolhead?.extruder
}
get show(): boolean {
return !(this.$store.getters['printer/getExtruderSteppers'].length > 0)
}
get allExtruders(): string[] {
Object.keys(this.$store.state.printer).forEach((e) => {
if (e.startsWith('extruder') && !this.extruders.includes(e)) this.extruders.push(e)
})
this.extruders.length === 1 ? this.resetToActiveExtruder() : {}
return this.extruders
}
get activeExtruder(): string {
this.resetToActiveExtruder()
return this.$store.state.printer.toolhead?.extruder
}
get pressureAdvance(): number {
return Math.floor((this.$store.state.printer?.[this.selectedExtruder]?.pressure_advance ?? 0) * 1000) / 1000
}
get smoothTime(): number {
return Math.floor((this.$store.state.printer?.[this.selectedExtruder]?.smooth_time ?? 0.04) * 1000) / 1000
}
get defaultPressureAdvance(): number {
return (
Math.floor(
(this.$store.state.printer.configfile?.settings?.[this.selectedExtruder]?.pressure_advance ?? 0) * 1000
) / 1000
)
}
get defaultSmoothTime(): number {
return (
Math.floor(
(this.$store.state.printer.configfile?.settings?.[this.selectedExtruder]
?.pressure_advance_smooth_time ?? 0.04) * 1000
) / 1000
)
}
@Debounce(500)
sendCmd(params: { name: string; value: number }): void {
const gcode = `SET_PRESSURE_ADVANCE EXTRUDER=${this.selectedExtruder} ${params.name}=${params.value}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode })
}
}
</script>

View File

@ -1,10 +1,11 @@
<template>
<panel
v-if="klipperReadyForGui && extruders.length"
v-if="showPanel"
:icon="mdiPrinter3dNozzle"
:title="$t('Panels.ExtruderControlPanel.Headline').toString()"
:title="$t('Panels.ExtruderControlPanel.Headline')"
:collapsible="true"
card-class="extruder-control-panel">
card-class="extruder-control-panel"
class="pb-1">
<!-- PANEL-HEADER 3-DOT-MENU -->
<template #buttons>
<v-menu v-if="showFilamentMacros" :offset-y="true" :close-on-content-click="false" left>
@ -21,8 +22,8 @@
<div v-on="on">
<macro-button
:macro="unloadFilamentMacro"
:alias="$t('Panels.ExtruderControlPanel.UnloadFilament').toString()"
:disabled="!canExecuteUnloadMacro || isPrinting"
:alias="$t('Panels.ExtruderControlPanel.UnloadFilament')"
:disabled="!canExecuteUnloadMacro || printerIsPrintingOnly"
color="#272727" />
</div>
</template>
@ -39,8 +40,8 @@
<div v-on="on">
<macro-button
:macro="loadFilamentMacro"
:alias="$t('Panels.ExtruderControlPanel.LoadFilament').toString()"
:disabled="!canExecuteLoadMacro || isPrinting"
:alias="$t('Panels.ExtruderControlPanel.LoadFilament')"
:disabled="!canExecuteLoadMacro || printerIsPrintingOnly"
color="#272727" />
</div>
</template>
@ -53,319 +54,55 @@
</v-list>
</v-menu>
</template>
<responsive :breakpoints="{ large: (el) => el.width >= 640 }">
<template #default="{ el }">
<!-- TOOL SELECTOR BUTTONS -->
<v-container v-if="toolchangeMacros.length > 1" class="pb-1">
<v-item-group class="_btn-group py-0">
<v-btn
v-for="tool in toolchangeMacros"
:key="tool.name"
:class="tool.active ? 'primary--text' : {}"
:disabled="isPrinting"
:style="{ 'background-color': '#' + tool.color }"
dense
class="flex-grow-1 px-0"
@click="doSend(tool.name)">
{{ tool.name }}
</v-btn>
</v-item-group>
</v-container>
<!-- EXTRUSION FACTOR SLIDER -->
<v-container class="pb-1">
<tool-slider
:label="$t('Panels.ExtruderControlPanel.ExtrusionFactor').toString()"
:icon="mdiPrinter3dNozzleOutline"
:target="extrudeFactor"
:min="1"
:max="200"
:multi="100"
:step="1"
:has-input-field="true"
command="M221"
attribute-name="S"></tool-slider>
</v-container>
<!-- PRESSURE ADVANCE SETTINGS -->
<template v-if="!(extruderSteppers.length > 0)">
<v-divider></v-divider>
<pressure-advance-settings></pressure-advance-settings>
</template>
<!-- FIRMWARE RETRACTION SETTINGS -->
<template v-if="existsFirmwareRetraction">
<v-divider></v-divider>
<firmware-retraction-settings></firmware-retraction-settings>
</template>
<v-divider class="pb-1"></v-divider>
<!-- EXTRUDER INPUTS AND QUICKSELECTS -->
<v-container>
<v-row>
<v-col>
<number-input
:label="$t('Panels.ExtruderControlPanel.FilamentLength').toString()"
param="feedamount"
:target="feedamount"
:disabled="isPrinting"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="100"
:step="0.01"
:min="0.01"
:max="maxExtrudeOnlyDistance"
:dec="2"
unit="mm"
:submit-on-blur="true"
@submit="setFeedamount"></number-input>
<v-item-group class="_btn-group pt-3">
<v-btn
v-for="value in feedamountsSorted"
:key="value"
:disabled="isPrinting"
dense
class="_btn-qs flex-grow-1 px-0"
@click="setFeedamount({ value })">
{{ value }}
</v-btn>
</v-item-group>
</v-col>
<v-col>
<number-input
:label="$t('Panels.ExtruderControlPanel.ExtrusionFeedrate').toString()"
param="feedrate"
:target="feedrate"
:disabled="isPrinting"
:has-spinner="true"
:output-error-msg="true"
:spinner-factor="100"
:step="0.01"
:min="0.01"
:max="null"
:dec="2"
type="number"
unit="mm/s"
@submit="setFeedrate"></number-input>
<v-item-group class="_btn-group pt-3">
<v-btn
v-for="value in feedratesSorted"
:key="value"
:disabled="isPrinting"
dense
class="_btn-qs flex-grow-1 px-0"
@click="setFeedrate({ value })">
{{ value }}
</v-btn>
</v-item-group>
</v-col>
<!-- EXTRUDE AND RETRACT BUTTON LARGE SIZED PANEL -->
<v-col v-if="el.is.large" class="col-3 d-flex align-center flex-column justify-center">
<!-- RETRACT -->
<v-tooltip left :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="mb-4" v-on="on">
<v-btn
:loading="loadings.includes('btnRetract')"
:disabled="!extrudePossible || tooLargeExtrusion || isPrinting"
small
class="_btn-extruder-cmd"
@click="sendRetract()">
<v-icon small class="mr-1">{{ mdiArrowUpBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Retract') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
<!-- EXTRUDE -->
<v-tooltip left :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div v-on="on">
<v-btn
:loading="loadings.includes('btnDetract')"
:disabled="!extrudePossible || tooLargeExtrusion || isPrinting"
small
class="_btn-extruder-cmd"
@click="sendExtrude()">
<v-icon small class="mr-1">{{ mdiArrowDownBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Extrude') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}: {{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
</v-col>
</v-row>
<!-- EXTRUDE AND RETRACT BUTTON SMALL AND MEDIUM SIZED PANEL -->
<v-row v-if="!el.is.large" :class="{ 'pb-1': !showEstimatedExtrusion }">
<v-col class="pa-0">
<div class="d-flex justify-space-around">
<div class="d-flex align-center">
<!-- RETRACT -->
<v-tooltip top :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="pt-1 pb-2 px-3" v-on="on">
<v-btn
:loading="loadings.includes('btnRetract')"
:disabled="!extrudePossible || tooLargeExtrusion || isPrinting"
small
class="_btn-extruder-cmd"
@click="sendRetract()">
<v-icon small class="mr-1">{{ mdiArrowUpBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Retract') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}:
{{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
<!-- EXTRUDE -->
<v-tooltip top :disabled="extrudePossible && !tooLargeExtrusion" color="secondary">
<template #activator="{ on }">
<div class="pt-1 pb-2 px-3" v-on="on">
<v-btn
:loading="loadings.includes('btnDetract')"
:disabled="!extrudePossible || tooLargeExtrusion || isPrinting"
small
class="_btn-extruder-cmd"
@click="sendExtrude()">
<v-icon small class="mr-1">{{ mdiArrowDownBold }}</v-icon>
{{ $t('Panels.ExtruderControlPanel.Extrude') }}
</v-btn>
</div>
</template>
<span v-show="!extrudePossible">
{{ $t('Panels.ExtruderControlPanel.ExtruderTempTooLow') }}
{{ minExtrudeTemp }} °C
</span>
<span v-show="tooLargeExtrusion">
{{ $t('Panels.ExtruderControlPanel.TooLargeExtrusion') }}
<br />
{{ $t('Panels.ExtruderControlPanel.Requested') }}:
{{ feedamount * extrudeFactor }} mm
<br />
{{ $t('Panels.ExtruderControlPanel.Allowed') }}:
{{ maxExtrudeOnlyDistance }} mm
</span>
</v-tooltip>
</div>
</div>
</v-col>
</v-row>
</v-container>
<!-- EXTRUSION ESTIMATION NOTE -->
<v-container v-if="showEstimatedExtrusion" class="pa-0 ma-0 pb-2">
<div
v-if="filamentDiameter && nozzleDiameter"
style="font-size: 0.8em"
class="text--disabled text-caption font-weight-light d-flex justify-center">
<span>
{{ $t('Panels.ExtruderControlPanel.EstimatedExtrusion') }} ~ {{ extrudedLength }} mm @
{{ volumetricFlow }} mm³/s -
<v-icon x-small style="opacity: 0.4; margin-top: -2px">
{{ mdiDiameterVariant }}
</v-icon>
{{ nozzleDiameter }} mm
</span>
</div>
</v-container>
</template>
</responsive>
<!-- TOOL SELECTOR BUTTONS -->
<extruder-control-panel-tools />
<!-- EXTRUSION FACTOR SLIDER -->
<extrusion-factor-settings />
<!-- PRESSURE ADVANCE SETTINGS -->
<pressure-advance-settings />
<!-- FIRMWARE RETRACTION SETTINGS -->
<firmware-retraction-settings />
<v-divider class="pb-1" />
<!-- EXTRUDER INPUTS AND QUICKSELECTS -->
<extruder-control-panel-control />
<!-- EXTRUSION ESTIMATION NOTE -->
<estimated-extrusion-output />
</panel>
</template>
<script lang="ts">
import {
mdiArrowDownBold,
mdiArrowUpBold,
mdiPrinter3dNozzle,
mdiPrinter3dNozzleOutline,
mdiDotsVertical,
mdiDiameterVariant,
} from '@mdi/js'
import { Component, Mixins, Watch } from 'vue-property-decorator'
import {
PrinterStateExtruder,
PrinterStateExtruderStepper,
PrinterStateMacro,
PrinterStateToolchangeMacro,
} from '@/store/printer/types'
import BaseMixin from '../mixins/base'
import ControlMixin from '../mixins/control'
import NumberInput from '@/components/inputs/NumberInput.vue'
import { mdiPrinter3dNozzle, mdiDotsVertical } from '@mdi/js'
import { Component, Mixins } from 'vue-property-decorator'
import { PrinterStateExtruder, PrinterStateMacro } from '@/store/printer/types'
import BaseMixin from '@/components/mixins/base'
import ControlMixin from '@/components/mixins/control'
import Panel from '@/components/ui/Panel.vue'
import PressureAdvanceSettings from '@/components/panels/ExtruderSettings/PressureAdvanceSettings.vue'
import FirmwareRetractionSettings from '@/components/panels/ExtruderSettings/FirmwareRetractionSettings.vue'
import Responsive from '@/components/ui/Responsive.vue'
import ToolSlider from '@/components/inputs/ToolSlider.vue'
import ExtruderMixin from '@/components/mixins/extruder'
@Component({
components: {
Panel,
PressureAdvanceSettings,
FirmwareRetractionSettings,
NumberInput,
Responsive,
ToolSlider,
},
})
export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin) {
mdiArrowUpBold = mdiArrowUpBold
mdiArrowDownBold = mdiArrowDownBold
export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin, ExtruderMixin) {
mdiPrinter3dNozzle = mdiPrinter3dNozzle
mdiPrinter3dNozzleOutline = mdiPrinter3dNozzleOutline
mdiDotsVertical = mdiDotsVertical
mdiDiameterVariant = mdiDiameterVariant
private heatWaitGcodes = ['printer.extruder.can_extrude', 'TEMPERATURE_WAIT', 'M109']
get isPrinting(): boolean {
return ['printing'].includes(this.printer_state)
get showPanel(): boolean {
return this.klipperReadyForGui && this.extruders.length > 0
}
get macros() {
return this.$store.getters['printer/getMacros']
}
get toolchangeMacros(): PrinterStateToolchangeMacro[] {
return this.$store.getters['printer/getToolchangeMacros']
}
get loadFilamentMacro() {
get loadFilamentMacro(): PrinterStateMacro | undefined {
return this.macros.find((macro: PrinterStateMacro) => macro.name.toUpperCase() === 'LOAD_FILAMENT')
}
get unloadFilamentMacro() {
get unloadFilamentMacro(): PrinterStateMacro | undefined {
return this.macros.find((macro: PrinterStateMacro) => macro.name.toUpperCase() === 'UNLOAD_FILAMENT')
}
@ -376,13 +113,13 @@ export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin
get canExecuteLoadMacro(): boolean {
if (this.extrudePossible) return true
return this.heatWaitGcodes.some((gcode) => this.loadFilamentMacro.prop.gcode.includes(gcode))
return this.heatWaitGcodes.some((gcode) => this.loadFilamentMacro?.prop.gcode.includes(gcode))
}
get canExecuteUnloadMacro(): boolean {
if (this.extrudePossible) return true
return this.heatWaitGcodes.some((gcode) => this.unloadFilamentMacro.prop.gcode.includes(gcode))
return this.heatWaitGcodes.some((gcode) => this.unloadFilamentMacro?.prop.gcode.includes(gcode))
}
get showFilamentMacros(): boolean {
@ -392,162 +129,5 @@ export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin
get extruders(): PrinterStateExtruder[] {
return this.$store.getters['printer/getExtruders']
}
get extruderSteppers(): PrinterStateExtruderStepper[] {
return this.$store.getters['printer/getExtruderSteppers']
}
get activeExtruder(): string {
return this.$store.state.printer.toolhead?.extruder
}
get filamentDiameter(): number {
return this.$store.state.printer.configfile?.settings?.[this.activeExtruder]?.filament_diameter ?? 1.75
}
get nozzleDiameter(): number {
return this.$store.state.printer.configfile?.settings?.[this.activeExtruder]?.nozzle_diameter ?? 0.4
}
get feedamounts(): number[] {
return this.$store.state.gui.control.extruder?.feedamounts ?? []
}
get feedrates(): number[] {
return this.$store.state.gui.control.extruder?.feedrates ?? []
}
get feedamountsSorted(): number[] {
return [...this.feedamounts].sort((a, b) => {
return b - a
})
}
get feedratesSorted(): number[] {
return [...this.feedrates].sort((a, b) => {
return b - a
})
}
get feedamount(): number {
return parseFloat(this.$store.state.gui.control.extruder.feedamount)
}
setFeedamount(params: { value: number }): void {
this.$store.dispatch('gui/saveSetting', { name: 'control.extruder.feedamount', value: params.value })
}
get feedrate(): number {
return parseFloat(this.$store.state.gui.control.extruder.feedrate)
}
setFeedrate(params: { value: number }): void {
this.$store.dispatch('gui/saveSetting', { name: 'control.extruder.feedrate', value: params.value })
}
get extrudePossible(): boolean {
return this.$store.getters['printer/getExtrudePossible']
}
get minExtrudeTemp(): number {
return this.$store.state.printer.configfile?.settings?.[this.activeExtruder]?.min_extrude_temp ?? 170
}
get maxExtrudeOnlyDistance(): number {
return this.$store.state.printer.configfile?.settings?.[this.activeExtruder]?.max_extrude_only_distance ?? 50
}
get tooLargeExtrusion(): boolean {
return this.feedamount * this.extrudeFactor > this.maxExtrudeOnlyDistance
}
get extrudedLength(): number {
return Math.round(
this.feedamount *
this.extrudeFactor *
(Math.pow(this.filamentDiameter, 2) / Math.pow(this.nozzleDiameter, 2))
)
}
get volumetricFlow(): number {
return Math.round(Math.pow(this.filamentDiameter / 2, 2) * Math.PI * this.feedrate * 10) / 10
}
get extrudeFactor() {
return this.$store.state.printer?.gcode_move?.extrude_factor ?? 1
}
get showEstimatedExtrusion() {
return this.$store.state.gui.control.extruder.showEstimatedExtrusionInfo
}
@Watch('maxExtrudeOnlyDistance', { immediate: true })
onMaxExtrudeOnlyDistanceChange(): void {
/**
* If, while switching from ex. A to ex. B, the feedamount
* from ex. A exceeds the maxExtrudeOnlyDistance of ex. B,
* set the feedamount to maxExtrudeOnlyDistance of ex. B
*/
if (this.feedamount > this.maxExtrudeOnlyDistance) {
this.setFeedamount({ value: this.maxExtrudeOnlyDistance })
}
}
sendRetract(): void {
const gcode = `M83\nG1 E-${this.feedamount} F${this.feedrate * 60}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode }, { loading: 'btnRetract' })
}
sendExtrude(): void {
const gcode = `M83\nG1 E${this.feedamount} F${this.feedrate * 60}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode }, { loading: 'btnDetract' })
}
}
</script>
<style lang="scss" scoped>
._btn-group {
border-radius: 4px;
display: inline-flex;
flex-wrap: nowrap;
max-width: 100%;
min-width: 100%;
width: 100%;
.v-btn {
border-radius: 0;
border-color: rgba(255, 255, 255, 0.12);
border-style: solid;
border-width: thin;
box-shadow: none;
height: 28px;
opacity: 0.8;
min-width: auto !important;
}
.v-btn:first-child {
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
.v-btn:last-child {
border-top-right-radius: inherit;
border-bottom-right-radius: inherit;
}
.v-btn:not(:first-child) {
border-left-width: 0;
}
}
._btn-qs {
font-size: 0.8rem !important;
max-height: 24px;
}
._btn-extruder-cmd {
min-width: 135px !important;
}
</style>

View File

@ -1,152 +0,0 @@
<template>
<v-container>
<responsive
:breakpoints="{
small: (el) => el.width <= 350,
}">
<template #default="{ el }">
<v-row>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="
$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.RetractLength').toString()
"
param="RETRACT_LENGTH"
:target="retractLength"
:default-value="defaultRetractLength"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:step="0.01"
:min="0"
:max="null"
:dec="2"
unit="mm"
@submit="sendCmd"></number-input>
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="
$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.RetractSpeed').toString()
"
param="RETRACT_SPEED"
:target="retractSpeed"
:default-value="defaultRetractSpeed"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="5"
:step="1"
:min="1"
:max="null"
:dec="0"
unit="mm/s"
@submit="sendCmd"></number-input>
</v-col>
</v-row>
<v-row>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="
$t(
'Panels.ExtruderControlPanel.FirmwareRetractionSettings.UnretractExtraLength'
).toString()
"
param="UNRETRACT_EXTRA_LENGTH"
:target="unretractExtraLength"
:default-value="defaultUnretractExtraLength"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:step="0.01"
:min="0"
:max="null"
:dec="2"
unit="mm"
@submit="sendCmd"></number-input>
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="
$t('Panels.ExtruderControlPanel.FirmwareRetractionSettings.UnretractSpeed').toString()
"
param="UNRETRACT_SPEED"
:target="unretractSpeed"
:default-value="defaultUnretractSpeed"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="5"
:step="1"
:min="1"
:max="null"
:dec="0"
unit="mm/s"
@submit="sendCmd"></number-input>
</v-col>
</v-row>
</template>
</responsive>
</v-container>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { Debounce } from 'vue-debounce-decorator'
import BaseMixin from '@/components/mixins/base'
import Panel from '@/components/ui/Panel.vue'
import NumberInput from '@/components/inputs/NumberInput.vue'
import Responsive from '@/components/ui/Responsive.vue'
@Component({
components: { Panel, NumberInput, Responsive },
})
export default class FirmwareRetractionSettings extends Mixins(BaseMixin) {
get retractLength(): number {
return Math.floor((this.$store.state.printer?.firmware_retraction?.retract_length ?? 0) * 100) / 100
}
get retractSpeed(): number {
return Math.trunc(this.$store.state.printer?.firmware_retraction?.retract_speed ?? 20)
}
get unretractExtraLength(): number {
return Math.floor((this.$store.state.printer?.firmware_retraction?.unretract_extra_length ?? 0) * 100) / 100
}
get unretractSpeed(): number {
return Math.trunc(this.$store.state.printer?.firmware_retraction?.unretract_speed ?? 10)
}
get defaultRetractLength(): number {
return (
Math.floor(
(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.retract_length ?? 0) * 100
) / 100
)
}
get defaultRetractSpeed(): number {
return Math.trunc(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.retract_speed ?? 20)
}
get defaultUnretractExtraLength(): number {
return (
Math.floor(
(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.unretract_extra_length ?? 0) *
100
) / 100
)
}
get defaultUnretractSpeed(): number {
return Math.trunc(this.$store.state.printer?.configfile?.settings?.firmware_retraction?.unretract_speed ?? 0)
}
@Debounce(500)
sendCmd(params: { name: string; value: number }): void {
const gcode = `SET_RETRACTION ${params.name}=${params.value}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode })
}
}
</script>

View File

@ -1,133 +0,0 @@
<template>
<v-container>
<responsive
:breakpoints="{
small: (el) => el.width <= 350,
medium: (el) => el.width > 350 && el.width <= 500,
}">
<template #default="{ el }">
<v-row>
<v-col v-if="allExtruders.length > 1" :class="{ 'col-12': el.is.small || el.is.medium }">
<div class="d-flex align-center">
<v-btn v-if="selectedExtruder !== activeExtruder" icon plain @click="resetToActiveExtruder">
<v-icon>{{ mdiRestart }}</v-icon>
</v-btn>
<v-select
v-model="selectedExtruder"
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.Extruder').toString()"
:items="allExtruders"
:value="activeExtruder"
hide-details
outlined
dense></v-select>
</div>
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.Advance').toString()"
param="ADVANCE"
:target="pressureAdvance"
:default-value="defaultPressureAdvance"
:extruder="selectedExtruder"
:output-error-msg="true"
:has-spinner="true"
:min="0"
:max="null"
:step="0.001"
:dec="3"
unit="s"
@submit="sendCmd"></number-input>
</v-col>
<v-col :class="{ 'col-12': el.is.small }">
<number-input
:label="$t('Panels.ExtruderControlPanel.PressureAdvanceSettings.SmoothTime').toString()"
param="SMOOTH_TIME"
:target="smoothTime"
:default-value="defaultSmoothTime"
:extruder="selectedExtruder"
:output-error-msg="true"
:has-spinner="true"
:spinner-factor="10"
:min="0"
:max="0.2"
:step="0.001"
:dec="3"
unit="s"
@submit="sendCmd"></number-input>
</v-col>
</v-row>
</template>
</responsive>
</v-container>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { Debounce } from 'vue-debounce-decorator'
import BaseMixin from '@/components/mixins/base'
import NumberInput from '@/components/inputs/NumberInput.vue'
import Panel from '@/components/ui/Panel.vue'
import Responsive from '@/components/ui/Responsive.vue'
import { mdiRestart } from '@mdi/js'
@Component({
components: { NumberInput, Panel, Responsive },
})
export default class PressureAdvanceSettings extends Mixins(BaseMixin) {
mdiRestart = mdiRestart
private extruders: string[] = []
private selectedExtruder = ''
resetToActiveExtruder(): void {
this.selectedExtruder = this.$store.state.printer.toolhead?.extruder
}
get allExtruders(): string[] {
Object.keys(this.$store.state.printer).forEach((e) => {
if (e.startsWith('extruder') && !this.extruders.includes(e)) this.extruders.push(e)
})
this.extruders.length === 1 ? this.resetToActiveExtruder() : {}
return this.extruders
}
get activeExtruder(): string {
this.resetToActiveExtruder()
return this.$store.state.printer.toolhead?.extruder
}
get pressureAdvance(): number {
return Math.floor((this.$store.state.printer?.[this.selectedExtruder]?.pressure_advance ?? 0) * 1000) / 1000
}
get smoothTime(): number {
return Math.floor((this.$store.state.printer?.[this.selectedExtruder]?.smooth_time ?? 0.04) * 1000) / 1000
}
get defaultPressureAdvance(): number {
return (
Math.floor(
(this.$store.state.printer.configfile?.settings?.[this.selectedExtruder]?.pressure_advance ?? 0) * 1000
) / 1000
)
}
get defaultSmoothTime(): number {
return (
Math.floor(
(this.$store.state.printer.configfile?.settings?.[this.selectedExtruder]
?.pressure_advance_smooth_time ?? 0.04) * 1000
) / 1000
)
}
@Debounce(500)
sendCmd(params: { name: string; value: number }): void {
const gcode = `SET_PRESSURE_ADVANCE EXTRUDER=${this.selectedExtruder} ${params.name}=${params.value}`
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
this.$socket.emit('printer.gcode.script', { script: gcode })
}
}
</script>

View File

@ -772,28 +772,6 @@ export const getters: GetterTree<PrinterState, RootState> = {
return output
},
getToolchangeMacros: (state, getters) => {
const macros = getters['getMacros']
const tools: PrinterStateToolchangeMacro[] = []
macros
.filter((macro: any) => macro.name.toUpperCase().match(/^T\d+/))
.forEach((macro: any) =>
tools.push({
name: macro.name,
active: macro.variables.active ?? false,
color: macro.variables.color ?? macro.variables.colour ?? null,
})
)
return tools.sort((a, b) => {
const numberA = parseInt(a.name.slice(1))
const numberB = parseInt(b.name.slice(1))
return numberA - numberB
})
},
getKinematics: (state) => {
if (!state.configfile?.settings?.printer) return false