Skip to content

Commit a2ea72b

Browse files
authored
fix(HappyHare): Fixed animated filament position and greatly cleaned up component (#1767)
Signed off by: Paul Morgan <moggieuk@hotmail.com>
1 parent c77b649 commit a2ea72b

File tree

1 file changed

+99
-220
lines changed

1 file changed

+99
-220
lines changed

src/components/widgets/mmu/MmuFilamentStatus.vue

Lines changed: 99 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
width="14"
179179
:height="filamentRectHeight"
180180
:fill="currentGateColor"
181+
class="filament-animation"
181182
:class="tipFormingClass"
182183
/>
183184
<polygon
@@ -452,227 +453,115 @@
452453
</template>
453454

454455
<script lang="ts">
455-
import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator'
456+
import { Component, Mixins } from 'vue-property-decorator'
456457
import StateMixin from '@/mixins/state'
457458
import MmuMixin from '@/mixins/mmu'
458459
460+
const POSITIONS = {
461+
UNKNOWN: 8,
462+
BEFORE_PRE_GATE: 20,
463+
PRE_GATE: 25,
464+
AFTER_PRE_GATE: 40,
465+
BEFORE_GEAR: 50,
466+
GEAR: 55,
467+
AFTER_GEAR: 70,
468+
GATE: 85,
469+
AFTER_GATE: 100,
470+
ENCODER: 115,
471+
START_BOWDEN: 135,
472+
MID_BOWDEN: 221,
473+
END_BOWDEN: 290,
474+
EXTRUDER: 295,
475+
EXTRUDER_ENTRANCE: 308,
476+
BEFORE_TOOLHEAD: 315,
477+
TOOLHEAD: 325,
478+
COOLING_TUBE: 338,
479+
CUT_POINT: 355,
480+
NOZZLE_START: 371,
481+
} as const
482+
459483
@Component({})
460484
export default class MmuFilamentStatus extends Mixins(StateMixin, MmuMixin) {
461-
@Prop({ default: 0.7 })
462-
readonly animationTime!: number
463-
464-
@Ref('filamentRect')
465-
readonly filamentRect?: SVGElement
466-
467-
private filamentRectHeight: number = 0
468-
private tipFormingClass: string = ''
469-
470-
readonly POSITIONS = {
471-
unknown: 8,
472-
'before-pre-gate': 20,
473-
'pre-gate': 25,
474-
'after-pre-gate': 40,
475-
'before-gear': 50,
476-
gear: 55,
477-
'after-gear': 70,
478-
gate: 85,
479-
'after-gate': 100,
480-
encoder: 115,
481-
'start-bowden': 135,
482-
'mid-bowden': 221,
483-
'end-bowden': 290,
484-
extruder: 295,
485-
'extruder-entrance': 308,
486-
'before-toolhead': 315,
487-
toolhead: 325,
488-
'cooling-tube': 338,
489-
'cut-point': 355,
490-
'nozzle-start': 371,
491-
} as const
492-
493-
readonly BOWDEN_RANGE = 173 as const
494-
495-
@Watch('$typedState.printer.printer.mmu.bowden_progress')
496-
onBowdenProgress (): void {
497-
// Percentage movement in the bowden
498-
this.calcFilamentHeight(this.filamentPos)
485+
get tipFormingClass () {
486+
return this.action === this.ACTION_FORMING_TIP ? 'form-tip-effect' : ''
499487
}
500488
501-
@Watch('$typedState.printer.printer.mmu.filament_pos')
502-
onFilamentPosChanged (newPos: number): void {
503-
// Filament position state
504-
this.calcFilamentHeight(newPos)
505-
}
489+
get filamentRectHeight () {
490+
if (this.gate === this.TOOL_GATE_BYPASS) {
491+
if (this.filamentPos === this.FILAMENT_POS_EXTRUDER_ENTRY) return POSITIONS.BEFORE_TOOLHEAD
492+
if (this.filamentPos === this.FILAMENT_POS_HOMED_TS) return POSITIONS.TOOLHEAD
493+
if (this.filamentPos === this.FILAMENT_POS_IN_EXTRUDER) return POSITIONS.COOLING_TUBE
494+
if (this.filamentPos === this.FILAMENT_POS_LOADED) return POSITIONS.NOZZLE_START
506495
507-
@Watch('$typedState.printer.printer.mmu.sensors')
508-
onSensorsChanged (): void {
509-
// Update on sensor change
510-
this.calcFilamentHeight(this.filamentPos)
511-
}
496+
if (this.isSensorTriggered('toolhead')) return POSITIONS.TOOLHEAD
497+
if (this.isSensorTriggered('extruder')) return POSITIONS.EXTRUDER
498+
if (this.isSensorTriggered('mmu_gear')) return POSITIONS.AFTER_GEAR
499+
if (this.isSensorTriggered('mmu_pre_gate')) return POSITIONS.AFTER_PRE_GATE
512500
513-
@Watch('$typedState.printer.printer.mmu.action')
514-
onActionChanged (action: string): void {
515-
// Action being performed
516-
if (action === this.ACTION_FORMING_TIP) {
517-
this.tipFormingClass = 'form-tip-effect'
518-
} else {
519-
if (this.tipFormingClass) {
520-
this.$nextTick(() => {
521-
this.animateFilament(this.POSITIONS['cooling-tube'], 1)
522-
})
523-
}
524-
this.tipFormingClass = ''
501+
return POSITIONS.BEFORE_PRE_GATE
525502
}
526-
}
527503
528-
private calcFilamentHeight (filamentPos: number): void {
529-
let pos = 0
504+
if (this.filamentPos === this.FILAMENT_POS_UNLOADED) {
505+
if (this.isSensorTriggered('mmu_gear')) return POSITIONS.AFTER_GEAR
506+
if (this.isSensorTriggered('mmu_pre_gate')) return POSITIONS.AFTER_PRE_GATE
530507
531-
if (this.gate === this.TOOL_GATE_BYPASS) {
532-
// Bypass use case places more emphasis on sensors
533-
switch (filamentPos) {
534-
case this.FILAMENT_POS_EXTRUDER_ENTRY:
535-
pos = this.POSITIONS['before-toolhead']
536-
break
537-
538-
case this.FILAMENT_POS_HOMED_TS:
539-
pos = this.POSITIONS['toolhead']
540-
break
541-
542-
case this.FILAMENT_POS_IN_EXTRUDER:
543-
pos = this.POSITIONS['cooling-tube']
544-
if (
545-
this.hasSensor('toolhead') &&
546-
this.isSensorEnabled('toolhead') &&
547-
!this.isSensorTriggered('toolhead')
548-
) {
549-
pos = this.POSITIONS['before-toolhead'] // Don't show beyond toolhead sensor if not triggered
550-
}
551-
break
552-
553-
case this.FILAMENT_POS_LOADED:
554-
pos = this.POSITIONS['nozzle-start']
555-
break
556-
557-
default:
558-
// For everything else, rely on sensors
559-
if (this.isSensorTriggered('toolhead')) {
560-
pos = this.POSITIONS['toolhead']
561-
} else if (this.isSensorTriggered('extruder')) {
562-
pos = this.POSITIONS['extruder']
563-
} else if (this.isSensorTriggered('mmu_gear')) {
564-
pos = this.POSITIONS['after-gear']
565-
} else if (this.isSensorTriggered('mmu_pre_gate')) {
566-
pos = this.POSITIONS['after-pre-gate']
567-
} else {
568-
pos = this.POSITIONS['before-pre-gate']
569-
}
570-
break
571-
}
572-
} else {
573-
// Normal MMU use case leveraging state machine
574-
switch (filamentPos) {
575-
case this.FILAMENT_POS_UNLOADED:
576-
if (this.isSensorTriggered('mmu_gear')) {
577-
pos = this.POSITIONS['after-gear']
578-
} else if (this.isSensorTriggered('mmu_pre_gate')) {
579-
pos = this.POSITIONS['after-pre-gate']
580-
} else {
581-
pos = this.POSITIONS['before-pre-gate']
582-
}
583-
break
584-
585-
case this.FILAMENT_POS_HOMED_GATE:
586-
if (this.configGateHomingEndstop === 'mmu_gear') {
587-
pos = this.POSITIONS['gear']
588-
} else if (this.configGateHomingEndstop === 'mmu_gate') {
589-
pos = this.POSITIONS['gate']
590-
} else if (this.configGateHomingEndstop === 'extruder') {
591-
pos = this.POSITIONS['extruder'] // Special no-bowden case
592-
} else {
593-
pos = this.POSITIONS['after-gate']
594-
}
595-
break
596-
597-
// TODO: State not yet implmented in Happy Hare
598-
// case this.FILAMENT_POS_HOMED_ENCODER:
599-
// pos = this.POSITIONS['encoder']
600-
// break
601-
602-
case this.FILAMENT_POS_START_BOWDEN:
603-
if (this.bowdenProgress >= 0) {
604-
pos = this.POSITIONS['start-bowden'] + (this.BOWDEN_RANGE * this.bowdenProgress) / 100
605-
} else {
606-
pos = this.POSITIONS['start-bowden']
607-
}
608-
break
609-
610-
case this.FILAMENT_POS_IN_BOWDEN:
611-
if (this.bowdenProgress >= 0) {
612-
pos = this.POSITIONS['start-bowden'] + (this.BOWDEN_RANGE * this.bowdenProgress) / 100
613-
} else {
614-
pos = this.POSITIONS['mid-bowden']
615-
}
616-
break
617-
618-
case this.FILAMENT_POS_END_BOWDEN:
619-
if (
620-
this.configGateHomingEndstop === 'none' ||
621-
(this.hasSensor('toolhead') &&
622-
this.isSensorEnabled('toolhead') &&
623-
!this.configExtruderForceHoming)
624-
) {
625-
// No extruder homing will be performed so indicate at the extruder now
626-
pos = this.POSITIONS['extruder-entrance']
627-
} else {
628-
pos = this.POSITIONS['end-bowden']
629-
}
630-
break
631-
632-
case this.FILAMENT_POS_HOMED_ENTRY:
633-
pos = this.POSITIONS['extruder']
634-
break
635-
636-
case this.FILAMENT_POS_HOMED_EXTRUDER:
637-
pos = this.POSITIONS['extruder-entrance']
638-
break
639-
640-
case this.FILAMENT_POS_EXTRUDER_ENTRY:
641-
pos = this.POSITIONS['before-toolhead']
642-
break
643-
644-
case this.FILAMENT_POS_HOMED_TS:
645-
pos = this.POSITIONS['toolhead']
646-
break
647-
648-
case this.FILAMENT_POS_IN_EXTRUDER:
649-
pos = this.POSITIONS['cooling-tube']
650-
break
651-
652-
case this.FILAMENT_POS_LOADED:
653-
pos = this.POSITIONS['nozzle-start']
654-
break
655-
656-
default: // this.FILAMENT_POS_UNKNOWN
657-
pos = this.POSITIONS['unknown']
658-
}
508+
return POSITIONS.BEFORE_PRE_GATE
509+
}
510+
511+
if (this.filamentPos === this.FILAMENT_POS_HOMED_GATE) {
512+
if (this.configGateHomingEndstop === 'mmu_gear') return POSITIONS.GEAR
513+
if (this.configGateHomingEndstop === 'mmu_gate') return POSITIONS.GATE
514+
if (this.configGateHomingEndstop === 'extruder') return POSITIONS.EXTRUDER
515+
516+
return POSITIONS.AFTER_GATE
659517
}
660-
this.animateFilament(pos)
661-
}
662518
663-
private animateFilament (newHeight: number, animationTime: number = this.animationTime) {
664-
const rect = this.filamentRect
665-
if (rect) {
666-
if (animationTime > 0) {
667-
const currentHeight = parseFloat(getComputedStyle(rect).height) ?? this.POSITIONS['end-bowden']
668-
const difference = Math.abs(currentHeight - newHeight)
669-
const duration = Math.min((difference / this.BOWDEN_RANGE) * animationTime + 0.1, animationTime)
670-
rect.style.transition = `height ${duration}s ease-in`
671-
} else {
672-
rect.style.transition = 'none'
673-
}
519+
if (
520+
[this.FILAMENT_POS_START_BOWDEN, this.FILAMENT_POS_IN_BOWDEN].includes(this.filamentPos) &&
521+
this.bowdenProgress >= 0
522+
) {
523+
const bowdenRange = this.endOfBowdenPos - POSITIONS.START_BOWDEN
524+
return POSITIONS.START_BOWDEN + (bowdenRange * this.bowdenProgress) / 100
674525
}
675-
this.filamentRectHeight = newHeight
526+
527+
if (this.filamentPos === this.FILAMENT_POS_START_BOWDEN) return POSITIONS.START_BOWDEN
528+
if (this.filamentPos === this.FILAMENT_POS_IN_BOWDEN) return POSITIONS.MID_BOWDEN
529+
if (this.filamentPos === this.FILAMENT_POS_END_BOWDEN) return this.endOfBowdenPos
530+
if (this.filamentPos === this.FILAMENT_POS_HOMED_ENTRY) return POSITIONS.EXTRUDER
531+
if (this.filamentPos === this.FILAMENT_POS_HOMED_EXTRUDER) return POSITIONS.EXTRUDER_ENTRANCE
532+
if (this.filamentPos === this.FILAMENT_POS_EXTRUDER_ENTRY) return POSITIONS.BEFORE_TOOLHEAD
533+
if (this.filamentPos === this.FILAMENT_POS_HOMED_TS) return POSITIONS.TOOLHEAD
534+
if (this.filamentPos === this.FILAMENT_POS_IN_EXTRUDER) {
535+
if (this.toolheadSensor === false) return POSITIONS.BEFORE_TOOLHEAD
536+
537+
return POSITIONS.COOLING_TUBE
538+
}
539+
540+
if (this.filamentPos === this.FILAMENT_POS_LOADED) return POSITIONS.NOZZLE_START
541+
542+
return POSITIONS.UNKNOWN
543+
}
544+
545+
get endOfBowdenPos () {
546+
if (
547+
typeof this.toolheadSensor === 'boolean' &&
548+
!this.configExtruderForceHoming
549+
) return POSITIONS.END_BOWDEN
550+
551+
if (
552+
this.configExtruderHomingEndstop === 'none' ||
553+
this.configExtruderHomingEndstop === 'collision' ||
554+
this.configExtruderHomingEndstop === 'mmu_gear_touch' ||
555+
this.configExtruderHomingEndstop === 'filament_compression'
556+
) return POSITIONS.EXTRUDER_ENTRANCE
557+
558+
if (this.configExtruderHomingEndstop === 'extruder') return POSITIONS.EXTRUDER
559+
560+
return POSITIONS.END_BOWDEN
561+
}
562+
563+
get toolheadSensor () {
564+
return this.sensors['toolhead']
676565
}
677566
678567
get encoderPosText (): string {
@@ -801,10 +690,6 @@ export default class MmuFilamentStatus extends Mixins(StateMixin, MmuMixin) {
801690
get isGripped (): boolean {
802691
return (this.grip === 'Gripped' || this.servo === 'Down')
803692
}
804-
805-
mounted () {
806-
this.calcFilamentHeight(this.filamentPos)
807-
}
808693
}
809694
</script>
810695

@@ -892,16 +777,6 @@ svg text {
892777
font-weight: normal;
893778
}
894779
895-
.fade-enter-active,
896-
.fade-leave-active {
897-
transition: opacity 0.8s ease;
898-
}
899-
900-
.fade-enter,
901-
.fade-leave-to {
902-
opacity: 0;
903-
}
904-
905780
@keyframes fadeInOut {
906781
0%,
907782
100% {
@@ -961,4 +836,8 @@ svg text {
961836
.form-tip-effect {
962837
animation: form-tip 1s infinite;
963838
}
839+
840+
.filament-animation {
841+
transition: height 0.5s ease-in;
842+
}
964843
</style>

0 commit comments

Comments
 (0)