Author Topic: Fixing "next/prev_letter" hanging on certain titles.  (Read 3105 times)

Arcade-TV

  • Jr. Member
  • **
  • Posts: 17
    • View Profile
Fixing "next/prev_letter" hanging on certain titles.
« on: January 01, 2023, 04:36:53 PM »
This is my fix for AM hanging on letters when the "Title" has a different case as the previous entry, has special or numeric chars in it or other reasons as the famous "vs." or ", The" hanging.
Pre-sorting your romlists by "Title" (2nd entry in the csv file) helps.
I hope I correctly copied this from my layout file. Pls let me know otherwise.


Layout:

Code: [Select]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fixing next_letter / prev_letter /////////////////////////////////////////////////////////////////////////////////////

::current_signal <- "";

function setCurrentLetterIndex() {
    ::print("setCurrentLetterIndex()\n");
    ::print("list idx:"+fe.list.index+", currentLetterIndex:"+::currentLetterIndex+"\n");
    for(local i=0; i < ::letterIndexes.len(); i++) {
        if(::letterIndexes[i] >= fe.list.index) {
            ::currentLetterIndex = i-1;
            return;
        }
    }
    ::currentLetterIndex = (::letterIndexes.len()-1);
}

function buildLettersArray() {
    ::print("CurrentList: "+fe.list.index+" of "+fe.list.size+"\n");
    ::currentLetterIndex <- 0;
    local list_size = fe.list.size;
    local g;
    ::letterIndexes <- [];
    local l_prevLetter = "";
    for(g = 0; g < list_size; g++) {
        local l_gameTitle = fe.game_info( Info.Title, g-fe.list.index );
        local l_gameLetter = l_gameTitle.slice(0, 1);
        l_gameLetter = l_gameLetter.tolower();
        // declare any other char than a-z as numeric:
        if(l_gameLetter != "a" && l_gameLetter != "b" && l_gameLetter != "c" && l_gameLetter != "d" && l_gameLetter != "e" && l_gameLetter != "f" && l_gameLetter != "g" && l_gameLetter != "h" && l_gameLetter != "i" && l_gameLetter != "j" && l_gameLetter != "k" && l_gameLetter != "l" && l_gameLetter != "m" && l_gameLetter != "n" && l_gameLetter != "o" && l_gameLetter != "p" && l_gameLetter != "q" && l_gameLetter != "r" && l_gameLetter != "s" && l_gameLetter != "t" && l_gameLetter != "u" && l_gameLetter != "v" && l_gameLetter != "w" && l_gameLetter != "x" && l_gameLetter != "y" && l_gameLetter != "z") {
            l_gameLetter = "0";
        }
        // fill letterIndexes array:
        if(l_prevLetter != l_gameLetter) {
            ::letterIndexes.push(g-1);
            l_prevLetter = l_gameLetter;
            ::print(l_gameLetter+": "+g+"\n");
        }
    }
    setCurrentLetterIndex();
}
buildLettersArray();

::print("::currentLetterIndex: "+::currentLetterIndex+"\n");

function prevLetter() {
    if(::currentLetterIndex == 0) {
        ::currentLetterIndex = ::letterIndexes.len()-1;
    }else{
        ::currentLetterIndex--;
    }
    jumpToLetter("prev");
}

function nextLetter() {
    if(::currentLetterIndex >= ::letterIndexes.len()-1) {
        ::currentLetterIndex = 0;
    }else{
        ::currentLetterIndex++;
    }
    jumpToLetter("next");
}

function jumpToLetter(dir) {
    switch(dir) {
        case "next":
            fe.list.index = ::letterIndexes[::currentLetterIndex]+1;
            break;

        case "prev":
            fe.list.index = ::letterIndexes[::currentLetterIndex+1];
            break;
    }
}

Transition Callback:

Code: [Select]
function transition_callback(ttype, var, ttime)
{
    switch ( ttype )
    {
        case Transition.ToNewList:
            buildLettersArray();
            break;

        case Transition.EndNavigation:
            switch (::current_signal) {

                case "prev_letter":
                    setCurrentLetterIndex();
                    break;

                case "next_letter":
                    setCurrentLetterIndex();
                    break;

                case "prev_game":
                    setCurrentLetterIndex();
                    break;

                case "next_game":
                    setCurrentLetterIndex();
                    break;
            }
            break;
    }

    return false;
}

fe.add_transition_callback("transition_callback" );



onSignal:

Code: [Select]
function on_signal(str) {
   
if (str != "") {
::current_signal <- str;
    }

    case "prev_letter":
        prevLetter();
        return true;
        break;

    case "next_letter":
        nextLetter();
        return true;
        break;

    return false;
}

fe.add_signal_handler(this, "on_signal");


stamina

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Fixing "next/prev_letter" hanging on certain titles.
« Reply #1 on: January 03, 2023, 07:41:23 AM »
Hi, I also noticed buggy behaviour when using the prev/next letter custom keybindings in my gamelists.

I'm using a modified "At-the-Arcade flex" layout with a self compiled attractplus from github though. (which seems to have patched in a "case-insensitive romlist sorting" lately)

Looking at the C++ code, I found a "_sort_regexp;^(Vs\. The |The |Vs\. )" which basically chops this off game titles, before the sorting starts.

The base functionality is working fine, only displaying the "letter" images didn't account for this chopping, so I also saw several "T" images in a row, with game titles starting with "The ..."

My layout.nut fix is rather simple (just using the same regex before slicing in the first Letter image):

Code: [Select]
fe.add_ticks_callback( "letter_tick" );
function letter_tick( ttime )
{
  glob_time = ttime;
  if( glob_time - rtime > glob_delay ) {
    letters.visible = false; // hide letter search if present
  }
  if( trigger_letter == true ) {
    local firstl = fe.game_info(Info.Title).tolower();
    local ex = regexp("^vs\\. the |^the |^vs\\. ");
    local res = ex.search(firstl)
    if (res != null) {
      firstl = firstl.slice(res.end,firstl.len());
    }
    if( my_config["letters_type"] != "No" ) {
      if( my_config["letters_type"] == "Default" ) {
        letters.file_name = FeConfigDirectory + "gtc-common/letters/default/" + firstl.slice(0,1) + ".png";
      } else {//by system display name
        letters.file_name = FeConfigDirectory + "gtc-common/letters/" + fe.displays[fe.list.display_index].name + "/" + firstl.slice(0,1) + ".png";
      }
      letters.visible = true;
    }
    trigger_letter = false;
  }
}

greetz, stamina