Other scrolling method - fix hack (#122)
* other method: leave scrolling to icon updating function downside: scroll can lag behind the selected entry if going too fast * bring back looping so scrolling doesnt lag behind as much when going out of bounds only about a second lag, then a second again for icons to load * this method doesnt need to know the ids * fix memory leak * optimize for invisibility * fix lockup when install checking threads are finished * less magic, again make icon loading functions/numbers more general * increase wait time for fastcroll to give people more time to react, and to prevent some lag for the loading function
This commit is contained in:
185
source/loading.c
185
source/loading.c
@@ -167,89 +167,45 @@ Result load_entries(const char * loading_path, Entry_List_s * list, EntryMode mo
|
||||
return res;
|
||||
}
|
||||
|
||||
static void small_load(Entry_List_s * current_list)
|
||||
void load_icons_first(Entry_List_s * list, bool silent)
|
||||
{
|
||||
DEBUG("small load\n");
|
||||
|
||||
ssize_t * icons_ids = (ssize_t *)current_list->icons_ids;
|
||||
ssize_t * assoc_entry_ids = (ssize_t *)current_list->assoc_entry_ids;
|
||||
ssize_t id = current_list->texture_id_offset;
|
||||
for(int i = 0; i < current_list->entries_count; i++, id++)
|
||||
{
|
||||
Entry_s current_entry = current_list->entries[i];
|
||||
load_smdh_icon(current_entry, id);
|
||||
icons_ids[i] = id;
|
||||
assoc_entry_ids[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
static void first_load(Entry_List_s * current_list)
|
||||
{
|
||||
DEBUG("first load\n");
|
||||
|
||||
ssize_t * above_icons_ids = current_list->icons_ids[ICONS_ABOVE];
|
||||
ssize_t * visible_icons_ids = current_list->icons_ids[ICONS_VISIBLE];
|
||||
ssize_t * under_icons_ids = current_list->icons_ids[ICONS_UNDER];
|
||||
|
||||
ssize_t * above_assoc_ids = current_list->assoc_entry_ids[ICONS_ABOVE];
|
||||
ssize_t * visible_assoc_ids = current_list->assoc_entry_ids[ICONS_VISIBLE];
|
||||
ssize_t * under_assoc_ids = current_list->assoc_entry_ids[ICONS_UNDER];
|
||||
|
||||
ssize_t id = current_list->texture_id_offset;
|
||||
int starti = current_list->scroll;
|
||||
|
||||
memset(visible_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t));
|
||||
for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++)
|
||||
{
|
||||
if(i >= current_list->entries_count) break;
|
||||
|
||||
Entry_s current_entry = current_list->entries[i];
|
||||
load_smdh_icon(current_entry, id);
|
||||
visible_icons_ids[i-starti] = id;
|
||||
visible_assoc_ids[i-starti] = i;
|
||||
}
|
||||
|
||||
memset(above_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t));
|
||||
starti -= ENTRIES_PER_SCREEN;
|
||||
for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++)
|
||||
{
|
||||
if(i >= current_list->entries_count) break;
|
||||
int used_i = i;
|
||||
if(i < 0)
|
||||
used_i = current_list->entries_count + i;
|
||||
|
||||
Entry_s current_entry = current_list->entries[used_i];
|
||||
load_smdh_icon(current_entry, id);
|
||||
above_icons_ids[i-starti] = id;
|
||||
above_assoc_ids[i-starti] = used_i;
|
||||
}
|
||||
|
||||
memset(under_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t));
|
||||
starti += ENTRIES_PER_SCREEN*2;
|
||||
for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++)
|
||||
{
|
||||
int used_i = i;
|
||||
if(i >= current_list->entries_count)
|
||||
used_i = i - current_list->entries_count;
|
||||
|
||||
Entry_s current_entry = current_list->entries[used_i];
|
||||
load_smdh_icon(current_entry, id);
|
||||
under_icons_ids[i-starti] = id;
|
||||
under_assoc_ids[i-starti] = used_i;
|
||||
}
|
||||
}
|
||||
|
||||
void load_icons_first(Entry_List_s * current_list, bool silent)
|
||||
{
|
||||
if(current_list == NULL || current_list->entries == NULL) return;
|
||||
if(list == NULL || list->entries == NULL) return;
|
||||
|
||||
if(!silent)
|
||||
draw_install(INSTALL_LOADING_ICONS);
|
||||
|
||||
if(current_list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT)
|
||||
small_load(current_list); // if the list is one that doesnt need swapping, load everything at once
|
||||
int starti = 0, endi = 0;
|
||||
|
||||
if(list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT)
|
||||
{
|
||||
DEBUG("small load\n");
|
||||
// if the list is one that doesnt need swapping, load everything at once
|
||||
endi = list->entries_count;
|
||||
}
|
||||
else
|
||||
first_load(current_list);
|
||||
{
|
||||
DEBUG("extended load\n");
|
||||
// otherwise, load around to prepare for swapping
|
||||
starti = list->scroll - ENTRIES_PER_SCREEN*ICONS_VISIBLE;
|
||||
endi = starti + ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT;
|
||||
}
|
||||
|
||||
ssize_t * icon_ids = (ssize_t *)list->icons_ids;
|
||||
ssize_t id = list->texture_id_offset;
|
||||
|
||||
memset(icon_ids, 0, ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT*sizeof(ssize_t));
|
||||
for(int i = starti; i < endi; i++, id++)
|
||||
{
|
||||
int offset = i;
|
||||
if(offset < 0)
|
||||
offset += list->entries_count;
|
||||
if(offset >= list->entries_count)
|
||||
offset -= list->entries_count;
|
||||
|
||||
Entry_s current_entry = list->entries[offset];
|
||||
load_smdh_icon(current_entry, id);
|
||||
icon_ids[i-starti] = id;
|
||||
}
|
||||
}
|
||||
|
||||
static void reverse(ssize_t a[], int sz) {
|
||||
@@ -269,18 +225,71 @@ static void rotate(ssize_t array[], int size, int amt) {
|
||||
reverse(array, size-1);
|
||||
}
|
||||
|
||||
void handle_scrolling(Entry_List_s * list)
|
||||
{
|
||||
// Scroll the menu up or down if the selected theme is out of its bounds
|
||||
//----------------------------------------------------------------
|
||||
if(list->entries_count > ENTRIES_PER_SCREEN)
|
||||
{
|
||||
for(int i = 0; i < list->entries_count; i++)
|
||||
{
|
||||
int change = 0;
|
||||
|
||||
if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->previous_scroll < ENTRIES_PER_SCREEN && list->selected_entry >= list->entries_count - ENTRIES_PER_SCREEN)
|
||||
{
|
||||
list->scroll = list->entries_count - ENTRIES_PER_SCREEN;
|
||||
}
|
||||
else if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->selected_entry < ENTRIES_PER_SCREEN && list->previous_selected >= list->entries_count - ENTRIES_PER_SCREEN)
|
||||
{
|
||||
list->scroll = 0;
|
||||
}
|
||||
else if(list->selected_entry == list->previous_selected+1 && list->selected_entry == list->scroll+ENTRIES_PER_SCREEN)
|
||||
{
|
||||
change = 1;
|
||||
}
|
||||
else if(list->selected_entry == list->previous_selected-1 && list->selected_entry == list->scroll-1)
|
||||
{
|
||||
change = -1;
|
||||
}
|
||||
else if(list->selected_entry == list->previous_selected+ENTRIES_PER_SCREEN || list->selected_entry >= list->scroll + ENTRIES_PER_SCREEN)
|
||||
{
|
||||
change = ENTRIES_PER_SCREEN;
|
||||
}
|
||||
else if(list->selected_entry == list->previous_selected-ENTRIES_PER_SCREEN || list->selected_entry < list->scroll)
|
||||
{
|
||||
change = -ENTRIES_PER_SCREEN;
|
||||
}
|
||||
|
||||
list->scroll += change;
|
||||
|
||||
if(list->scroll < 0)
|
||||
list->scroll = 0;
|
||||
else if(list->scroll > list->entries_count - ENTRIES_PER_SCREEN)
|
||||
list->scroll = list->entries_count - ENTRIES_PER_SCREEN;
|
||||
|
||||
if(!change)
|
||||
list->previous_selected = list->selected_entry;
|
||||
else
|
||||
list->previous_selected += change;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
}
|
||||
|
||||
static void load_icons(Entry_List_s * current_list)
|
||||
{
|
||||
if(current_list == NULL || current_list->entries == NULL)
|
||||
return;
|
||||
|
||||
handle_scrolling(current_list);
|
||||
|
||||
if(current_list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT || current_list->previous_scroll == current_list->scroll)
|
||||
return; // return if the list is one that doesnt need swapping, or if nothing changed
|
||||
|
||||
#define SIGN(x) (x > 0 ? 1 : ((x < 0) ? -1 : 0))
|
||||
|
||||
int delta = current_list->scroll - current_list->previous_scroll;
|
||||
if(abs(delta) >= current_list->entries_count - ENTRIES_PER_SCREEN*2)
|
||||
if(abs(delta) >= current_list->entries_count - ENTRIES_PER_SCREEN*(ICONS_OFFSET_AMOUNT-1))
|
||||
delta = -SIGN(delta) * (current_list->entries_count - abs(delta));
|
||||
|
||||
int starti = current_list->scroll;
|
||||
@@ -300,27 +309,23 @@ static void load_icons(Entry_List_s * current_list)
|
||||
#define LAST(arr) arr[ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT - 1]
|
||||
|
||||
ssize_t * icons_ids = (ssize_t *)current_list->icons_ids;
|
||||
ssize_t * assoc_entry_ids = (ssize_t *)current_list->assoc_entry_ids;
|
||||
|
||||
for(int i = starti; i != endi; i++, ctr++)
|
||||
{
|
||||
ssize_t id = 0;
|
||||
int offset = i;
|
||||
ssize_t * assoc = NULL;
|
||||
|
||||
rotate(icons_ids, 3*ENTRIES_PER_SCREEN, -1*SIGN(delta));
|
||||
rotate(icons_ids, ICONS_OFFSET_AMOUNT*ENTRIES_PER_SCREEN, -1*SIGN(delta));
|
||||
|
||||
if(delta > 0)
|
||||
{
|
||||
id = LAST(icons_ids);
|
||||
assoc = &LAST(assoc_entry_ids);
|
||||
offset += ENTRIES_PER_SCREEN*2 - delta;
|
||||
offset += ENTRIES_PER_SCREEN*ICONS_UNDER - delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = FIRST(icons_ids);
|
||||
assoc = &FIRST(assoc_entry_ids);
|
||||
offset -= ENTRIES_PER_SCREEN;
|
||||
offset -= ENTRIES_PER_SCREEN*ICONS_VISIBLE;
|
||||
i -= 2; //i-- twice to counter the i++, needed only for this case
|
||||
}
|
||||
|
||||
@@ -331,7 +336,6 @@ static void load_icons(Entry_List_s * current_list)
|
||||
|
||||
entries[ctr] = ¤t_list->entries[offset];
|
||||
ids[ctr] = id;
|
||||
*assoc = id;
|
||||
}
|
||||
|
||||
#undef FIRST
|
||||
@@ -341,9 +345,13 @@ static void load_icons(Entry_List_s * current_list)
|
||||
svcSleepThread(1e6);
|
||||
for(int i = 0; i < abs(delta); i++)
|
||||
load_smdh_icon(*entries[i], ids[i]);
|
||||
|
||||
free(entries);
|
||||
free(ids);
|
||||
|
||||
current_list->previous_scroll = current_list->scroll;
|
||||
}
|
||||
|
||||
static bool loading_icons = false;
|
||||
void load_icons_thread(void * void_arg)
|
||||
{
|
||||
Thread_Arg_s * arg = (Thread_Arg_s *)void_arg;
|
||||
@@ -352,11 +360,8 @@ void load_icons_thread(void * void_arg)
|
||||
{
|
||||
svcWaitSynchronization(update_request, U64_MAX);
|
||||
svcClearEvent(update_request);
|
||||
if(loading_icons) continue;
|
||||
loading_icons = true;
|
||||
volatile Entry_List_s * current_list = *(volatile Entry_List_s **)arg->thread_arg[0];
|
||||
load_icons((Entry_List_s *)current_list);
|
||||
loading_icons = false;
|
||||
}
|
||||
while(arg->run_thread);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user