Untitled

 avatar
unknown
plain_text
2 months ago
6.7 kB
3
Indexable
    def animate(self):
        if self._destroyed:
            return
            
        current_time = time.time()
        
        # Update can_press status
        if not self.can_press and current_time - self.last_press_time >= self.cooldown_period:
            self.can_press = True
        
        # Handle fill level animation
        if self.target_fill_level != self.fill_level:
            diff = self.target_fill_level - self.fill_level
            self.fill_level += diff * 0.2
            
            if abs(diff) < 0.5:
                self.fill_level = self.target_fill_level
        
        # Handle press animation
        if self.press_animation_active:
            if self.is_pressed:
                self.press_scale = max(self.PRESS_SCALE_MIN, self.press_scale - self.SCALE_STEP)
                if self.press_scale == self.PRESS_SCALE_MIN:
                    self.press_animation_active = self.is_pressed
            else:
                self.press_scale = min(self.PRESS_SCALE_MAX, self.press_scale + self.SCALE_STEP)
                if self.press_scale == self.PRESS_SCALE_MAX:
                    self.press_animation_active = False
        
        # Handle pulse animation during servo active state
        if self.servo_active:
            if self.pulse_growing:
                self.pulse_scale = min(self.PULSE_MAX, self.pulse_scale + self.PULSE_STEP)
                if self.pulse_scale >= self.PULSE_MAX:
                    self.pulse_growing = False
            else:
                self.pulse_scale = max(self.PULSE_MIN, self.pulse_scale - self.PULSE_STEP)
                if self.pulse_scale <= self.PULSE_MIN:
                    self.pulse_growing = True
        else:
            self.pulse_scale = 1.0
        
        # Apply combined scale
        final_scale = self.press_scale * self.pulse_scale
        
        # Only redraw if there's been a change
        if self.press_animation_active or self.servo_active or self.target_fill_level != self.fill_level:
            self.draw(scale=final_scale)
        
        self.after(16, self.animate)  # ~60 FPS

    def handle_manual_fill(self):
        """Handle manual filling of the bin with improved feedback"""
        # Find turntable controller
        turntable = None
        root = self.winfo_toplevel()
        for widget in root.winfo_children():
            if isinstance(widget, ctk.CTkFrame):
                for child in widget.winfo_children():
                    if isinstance(child, ClassificationPrompt):
                        turntable = child.turntable
                        break
                if turntable:
                    break

        if not turntable or not turntable.is_initialized:
            return

        # Check if any other bin is currently active
        for instance in self._instances:
            if instance != self and instance.servo_active:
                return  # Prevent activation if another bin is active

        if self.servo_active:
            # If servo is already open, close it
            self.close_servo(turntable)
        else:
            # Start the filling process
            self.start_filling_process(turntable)

    def start_filling_process(self, turntable):
        """Start the bin filling process with visual feedback"""
        try:
            # Move to bin position
            target_position = turntable.positions[self.bin_id]
            steps, direction = turntable._calculate_steps(target_position)
            turntable._move_motor(steps, direction)
            turntable.current_position = target_position
            
            # Open servo and start visual feedback
            if hasattr(turntable, 'hardware'):
                turntable.hardware.servo_motor.angle = 90
                self.servo_active = True
                self.servo_start_time = time.time()
                
                # Start auto-close timer
                self.servo_timer = self.after(
                    int(self.SERVO_OPEN_TIME * 1000),
                    lambda: self.close_servo(turntable)
                )
        except Exception as e:
            print(f"Error in fill process: {e}")
            self.close_servo(turntable)

    def close_servo(self, turntable):
        """Close the servo and update fill level"""
        try:
            # Cancel any pending timer
            if hasattr(self, 'servo_timer'):
                self.after_cancel(self.servo_timer)
                self.servo_timer = None
            
            # Close servo
            if hasattr(turntable, 'hardware'):
                turntable.hardware.servo_motor.angle = 0
                self.servo_active = False
                
                # Wait for contents to settle
                time.sleep(0.5)
                
                # Measure fill level
                readings = turntable.hardware.get_measurements()
                closest_reading, percentage = turntable.hardware.process_readings(readings)
                
                if percentage is not None:
                    turntable.hardware.update_fill_level(self.bin_id, percentage)
                    self.set_fill_level(percentage)
                    CircularProgress.update_all_instances()
        
        except Exception as e:
            print(f"Error closing servo: {e}")
            # Ensure servo is closed on error
            try:
                if hasattr(turntable, 'hardware'):
                    turntable.hardware.servo_motor.angle = 0
                    self.servo_active = False
            except:
                pass

    def on_press(self, event):
        # First check if settings menu is open
        root = self.winfo_toplevel()
        for widget in root.winfo_children():
            if isinstance(widget, ctk.CTkFrame):
                for child in widget.winfo_children():
                    if isinstance(child, SettingsMenu) and child.is_open:
                        return
        
        # Check if this instance is in reset mode
        if hasattr(self, 'is_reset_mode') and self.is_reset_mode:
            return
            
        current_time = time.time()
        if current_time - self.last_press_time >= self.cooldown_period and self.can_press:
            self.is_pressed = True
            self.press_animation_active = True
            self.last_press_time = current_time
            self.can_press = False
            
            # Handle manual fill behavior
            self.handle_manual_fill()
Leave a Comment