@@ -28,7 +28,7 @@ def compute_angle_to_object(from_obj, to_obj):
2828dy = to_y - from_y
2929
3030# Calculate angle (0° = UP, 90° = RIGHT, 180° = DOWN, 270° = LEFT)
31- angle_rad = math .atan2 (- dx ,dy )#-dx, dy aligns UP with 0°, clockwise
31+ angle_rad = math .atan2 (dx ,- dy )#Fixed for correct convention
3232angle_deg = math .degrees (angle_rad )
3333return (angle_deg + 360 )% 360 # Normalize to [0, 360)
3434
@@ -41,19 +41,67 @@ def is_object_in_focus_group(focus_group, obj):
4141return True
4242return False
4343
44- def find_closest_obj_in_direction (focus_group ,current_focused ,direction_degrees ,angle_tolerance = 45 ):
44+ def get_closest_edge_point_and_distance (from_x ,from_y ,obj ,direction_degrees ,debug = False ):
45+ """
46+ Calculate the distance to the closest edge point on obj, and check if its angle is within the direction cone.
47+ Returns (distance, closest_x, closest_y, angle_deg) or None if not in direction or inside.
48+ """
49+ x = obj .get_x ()
50+ y = obj .get_y ()
51+ width = obj .get_width ()
52+ height = obj .get_height ()
53+ right = x + width
54+ bottom = y + height
55+
56+ # Clamp to the rect bounds to find closest point
57+ closest_x = max (x ,min (from_x ,right ))
58+ closest_y = max (y ,min (from_y ,bottom ))
59+
60+ # Compute vector to closest point
61+ dx = closest_x - from_x
62+ dy = closest_y - from_y
63+
64+ # If closest point is the from point, the from is inside the obj, skip
65+ if dx == 0 and dy == 0 :
66+ if debug :
67+ print (f" Skipping{ obj } because current center is inside the object." )
68+ return None
69+
70+ # Compute distance
71+ distance = math .sqrt (dx ** 2 + dy ** 2 )
72+
73+ # Compute angle to the closest point (using same convention)
74+ angle_rad = math .atan2 (dx ,- dy )# Fixed
75+ angle_deg = math .degrees (angle_rad )
76+ angle_deg = (angle_deg + 360 )% 360
77+
78+ # Check if in direction cone (±45°)
79+ angle_diff = min ((angle_deg - direction_degrees )% 360 , (direction_degrees - angle_deg )% 360 )
80+ if angle_diff > 45 :
81+ if debug :
82+ print (f"{ obj } at ({ x } ,{ y } ) size ({ width } x{ height } ): closest point ({ closest_x :.1f} ,{ closest_y :.1f} ), angle{ angle_deg :.1f} °, diff{ angle_diff :.1f} ° > 45°, skipped" )
83+ return None
84+
85+ if debug :
86+ print (f"{ obj } at ({ x } ,{ y } ) size ({ width } x{ height } ): closest point ({ closest_x :.1f} ,{ closest_y :.1f} ), angle{ angle_deg :.1f} °, distance{ distance :.1f} , diff{ angle_diff :.1f} °" )
87+
88+ return distance ,closest_x ,closest_y ,angle_deg
89+
90+ def find_closest_obj_in_direction (focus_group ,current_focused ,direction_degrees ,debug = False ):
4591"""
4692 Find the closest object in the specified direction from the current focused object.
4793 Only considers objects that are in the focus_group (including children of any object).
94+ Uses closest edge point for distance to handle object sizes intuitively.
4895 Direction is in degrees: 0° = UP, 90° = RIGHT, 180° = DOWN, 270° = LEFT (clockwise).
49- Returns the closest objectwithin ±angle_tolerance of direction_degrees, or None.
96+ Returns the closest object or None.
5097 """
5198if not current_focused :
5299print ("No current focused object." )
53100return None
54101
55- print (f"Current focused object:{ current_focused } " )
56- print (f"Default focus group has{ focus_group .get_obj_count ()} items" )
102+ if debug :
103+ print (f"Current focused object:{ current_focused } " )
104+ print (f"Default focus group has{ focus_group .get_obj_count ()} items" )
57105
58106closest_obj = None
59107min_distance = float ('inf' )
@@ -68,19 +116,14 @@ def process_object(obj, depth=0):
68116
69117# Check if the object is in the focus group and evaluate it
70118if is_object_in_focus_group (focus_group ,obj ):
71- # Compute angle to the object
72- angle_deg = compute_angle_to_object (current_focused ,obj )
73-
74- # Check if object is in the desired direction (within ±angle_tolerance)
75- angle_diff = min ((angle_deg - direction_degrees )% 360 , (direction_degrees - angle_deg )% 360 )
76- if angle_diff <= angle_tolerance :
77- # Calculate Euclidean distance
78- obj_x ,obj_y = get_object_center (obj )
79- distance = math .sqrt ((obj_x - current_x )** 2 + (obj_y - current_y )** 2 )
80- # Update closest object if this one is closer
119+ result = get_closest_edge_point_and_distance (current_x ,current_y ,obj ,direction_degrees ,debug )
120+ if result :
121+ distance ,closest_x ,closest_y ,angle_deg = result
81122if distance < min_distance :
82123min_distance = distance
83124closest_obj = obj
125+ if debug :
126+ print (f" Updated closest:{ obj } , distance{ distance :.1f} , angle{ angle_deg :.1f} °" )
84127
85128# Process children regardless of parent's focus group membership
86129for childnr in range (obj .get_child_count ()):
@@ -125,7 +168,7 @@ def move_focus_direction(angle):
125168if isinstance (current_focused ,lv .keyboard ):
126169print ("focus is on a keyboard, which has its own move_focus_direction: NOT moving" )
127170return
128- o = find_closest_obj_in_direction (focus_group ,current_focused ,angle )
171+ o = find_closest_obj_in_direction (focus_group ,current_focused ,angle , True )
129172if o :
130173print ("move_focus_direction: moving focus to:" )
131174mpos .util .print_lvgl_widget (o )