|
178 | 178 | width="14" |
179 | 179 | :height="filamentRectHeight" |
180 | 180 | :fill="currentGateColor" |
| 181 | + class="filament-animation" |
181 | 182 | :class="tipFormingClass" |
182 | 183 | /> |
183 | 184 | <polygon |
|
452 | 453 | </template> |
453 | 454 |
|
454 | 455 | <script lang="ts"> |
455 | | -import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator' |
| 456 | +import { Component, Mixins } from 'vue-property-decorator' |
456 | 457 | import StateMixin from '@/mixins/state' |
457 | 458 | import MmuMixin from '@/mixins/mmu' |
458 | 459 |
|
| 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 | +
|
459 | 483 | @Component({}) |
460 | 484 | 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' : '' |
499 | 487 | } |
500 | 488 |
|
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 |
506 | 495 |
|
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 |
512 | 500 |
|
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 |
525 | 502 | } |
526 | | - } |
527 | 503 |
|
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 |
530 | 507 |
|
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 |
659 | 517 | } |
660 | | - this.animateFilament(pos) |
661 | | - } |
662 | 518 |
|
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 |
674 | 525 | } |
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'] |
676 | 565 | } |
677 | 566 |
|
678 | 567 | get encoderPosText (): string { |
@@ -801,10 +690,6 @@ export default class MmuFilamentStatus extends Mixins(StateMixin, MmuMixin) { |
801 | 690 | get isGripped (): boolean { |
802 | 691 | return (this.grip === 'Gripped' || this.servo === 'Down') |
803 | 692 | } |
804 | | -
|
805 | | - mounted () { |
806 | | - this.calcFilamentHeight(this.filamentPos) |
807 | | - } |
808 | 693 | } |
809 | 694 | </script> |
810 | 695 |
|
@@ -892,16 +777,6 @@ svg text { |
892 | 777 | font-weight: normal; |
893 | 778 | } |
894 | 779 |
|
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 | | -
|
905 | 780 | @keyframes fadeInOut { |
906 | 781 | 0%, |
907 | 782 | 100% { |
@@ -961,4 +836,8 @@ svg text { |
961 | 836 | .form-tip-effect { |
962 | 837 | animation: form-tip 1s infinite; |
963 | 838 | } |
| 839 | +
|
| 840 | +.filament-animation { |
| 841 | + transition: height 0.5s ease-in; |
| 842 | +} |
964 | 843 | </style> |
0 commit comments