8000 Fix seg fault when GUI nodes get collected by trying to find another … · TinyCircuits/micropython@68f815b · GitHub
[go: up one dir, main page]

Skip to content

Commit 68f815b

Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ engine_node_base_t *focused_gui_node_base = NULL;
1414
bool gui_focused = false;
1515

1616

17+
vector2_class_obj_t *resolve_gui_node_position(engine_node_base_t *gui_node_base){
18+
if(mp_obj_is_type(focused_gui_node_base, &engine_gui_bitmap_button_2d_node_class_type)){
19+
return ((engine_gui_bitmap_button_2d_node_class_obj_t*)gui_node_base->node)->position;
20+
}else{
21+
return ((engine_gui_button_2d_node_class_obj_t*)gui_node_base->node)->position;
22+
}
23+
}
24+
25+
1726
void engine_gui_reset(){
1827
focused_gui_node_base = NULL;
1928
gui_focused = false;
@@ -140,12 +149,7 @@ void engine_gui_select_closest(bool (direction_check)(float)){
140149
}
141150

142151
// Get the position of the currently focused GUI node
143-
vector2_class_obj_t *focused_gui_position = NULL;
144-
if(mp_obj_is_type(focused_gui_node_base, &engine_gui_bitmap_button_2d_node_class_type)){
145-
focused_gui_position = ((engine_gui_bitmap_button_2d_node_class_obj_t*)focused_gui_node_base->node)->position;
146-
}else{
147-
focused_gui_position = ((engine_gui_button_2d_node_class_obj_t*)focused_gui_node_base->node)->position;
148-
}
152+
vector2_class_obj_t *focused_gui_position = resolve_gui_node_position(focused_gui_node_base);
149153

150154
// Setup for looping through all GUI nodes and finding closest
151155
linked_list *gui_list = engine_collections_get_gui_list();
@@ -162,18 +166,11 @@ void engine_gui_select_closest(bool (direction_check)(float)){
162166
continue;
163167
}
164168

165-
// Get the node base of the currently looping
166-
// through node
169+
// Get the node base of the currently looping through node
167170
engine_node_base_t *searching_gui_node_base = current_gui_list_node->object;
168171

169-
// Get the position of the currently focused
170-
// GUI node
171-
vector2_class_obj_t *searching_gui_position = NULL;
172-
if(mp_obj_is_type(searching_gui_node_base, &engine_gui_bitmap_button_2d_node_class_type)){
173-
searching_gui_position = ((engine_gui_bitmap_button_2d_node_class_obj_t*)searching_gui_node_base->node)->position;
174-
}else{
175-
searching_gui_position = ((engine_gui_button_2d_node_class_obj_t*)searching_gui_node_base->node)->position;
176-
}
172+
// Get the position of the current GUI node
173+
vector2_class_obj_t *searching_gui_position = resolve_gui_node_position(searching_gui_node_base);
177174

178175
// Get the angle between the focused node and
179176
// the node we looped to now
@@ -209,6 +206,48 @@ void engine_gui_select_closest(bool (direction_check)(float)){
209206
}
210207

211208

209+
void engine_gui_clear_focused(){
210+
// If the GUI layer is focused, find a new node when
211+
// the current focused node is to be cleared (likely gc'ed)
212+
if(gui_focused){
213+
linked_list *gui_list = engine_collections_get_gui_list();
214+
linked_list_node *current_gui_list_node = gui_list->start;
215+
216+
// Get the position of the currently focused GUI node
217+
vector2_class_obj_t *focused_gui_position = resolve_gui_node_position(focused_gui_node_base);
218+
219+
engine_node_base_t *closest_gui_node_base = NULL;
220+
float shortest_distance = FLT_MAX;
221+
222+
while(current_gui_list_node != NULL){
223+
engine_node_base_t *searching_gui_node_base = current_gui_list_node->object;
224+
vector2_class_obj_t *searching_gui_position = resolve_gui_node_position(searching_gui_node_base);
225+
226+
float distance = engine_math_distance_between(focused_gui_position->x.value, focused_gui_position->y.value, searching_gui_position->x.value, searching_gui_position->y.value);
227+
228+
// If the distance is closer than the last one
229+
// we compared to, set it as the closest. Make
230+
// sure not comparing focused vs. focused
231+
if(distance < shortest_distance && focused_gui_node_base != searching_gui_node_base){
232+
shortest_distance = distance;
233+
closest_gui_node_base = searching_gui_node_base;
234+
}
235+
236+
current_gui_list_node = current_gui_list_node->next;
237+
}
238+
239+
// Check if we found an alternative, node, focus it if we did
240+
if(closest_gui_node_base != NULL){
241+
engine_gui_focus_node(closest_gui_node_base);
242+
}else{
243+
focused_gui_node_base = NULL;
244+
}
245+
}else{
246+
focused_gui_node_base = NULL;
247+
}
248+
}
249+
250+
212251
void engine_gui_tick(){
213252
// Every tick, see if the button to toggle GUI focus was pressed.
214253
// If the GUI toggle button is 0 that means None was set for the
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void engine_gui_focus_node(engine_node_base_t *gui_node);
1111
bool engine_gui_get_focus();
1212
void engine_gui_toggle_focus();
1313
engine_node_base_t *engine_gui_get_focused();
14-
14+
void engine_gui_clear_focused();
1515
void engine_gui_tick();
1616

1717
#endif // ENGINE_GUI_H
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ mp_obj_t gui_bitmap_button_2d_node_class_del(mp_obj_t self_in){
164164

165165
engine_node_base_t *node_base = self_in;
166166
engine_gui_bitmap_button_2d_node_class_obj_t *gui_button = node_base->node;
167+
168+
// If this node is focused but being deleted, tell the GUI engine
169+
if(gui_button->focused) engine_gui_clear_focused();
170+
167171
engine_collections_untrack_gui(gui_button->gui_list_node);
168172

169173
node_base_del(self_in);
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ mp_obj_t gui_button_2d_node_class_del(mp_obj_t self_in){
172172

173173
engine_node_base_t *node_base = self_in;
174174
engine_gui_button_2d_node_class_obj_t *gui_button = node_base->node;
175+
176+
// If this node is focused but being deleted, tell the GUI engine
177+
if(gui_button->focused) engine_gui_clear_focused();
178+
175179
engine_collections_untrack_gui(gui_button->gui_list_node);
176180

177181
node_base_del(self_in);