rafaskb/typing-label

Inconsistent events ordering

Opened this issue · 2 comments

I have several issues using both events and delay (WAIT=X).

With following test code :

long timeBase = System.currentTimeMillis();
TypingLabel tl = new TypingLabel("Hello{WAIT=5}{EVENT=on}{WAIT=5}{EVENT=off}bye", skin);
tl.setTypingListener(new TypingAdapter(){
    @Override
    public void onChar(Character ch) {
        System.out.println((System.currentTimeMillis() - timeBase) + " " + ch);
    }
    @Override
    public void event(String event) {
        System.out.println((System.currentTimeMillis() - timeBase) + " " + event);
    }
});

It produces following trace:

109 e
143 l
176 l
209 on
209 off
209 o
243 b
10343 y
10376 e

As you can see :

  • First character 'H' is missing
  • 'on' and 'off' events appears at the same time
  • last letter of "Hello" appears after events (minor issue)
  • letter 'b' appear too soon

Can confirm that I can reproduce this.

We can look in the code for this snippet here:

            // Notify listener about char progression
            int nextIndex = rawCharIndex == 0 ? 0 : MathUtils.clamp(rawCharIndex, 0, getText().length - 1);
            Character nextChar = nextIndex == 0 ? null : getText().charAt(nextIndex);
            if(nextChar != null && listener != null) {
                listener.onChar(nextChar);
            }

// Notify listener about char progression
int nextIndex = rawCharIndex == 0 ? 0 : MathUtils.clamp(rawCharIndex, 0, getText().length - 1);
Character nextChar = nextIndex == 0 ? null : getText().charAt(nextIndex);
if(nextChar != null && listener != null) {
listener.onChar(nextChar);
}

It actually seems 'intended' - the onChar is fired whenever the index is incremented (nextIndex instead of something current). If we assume we start at 0, and only pass in the next character, we are indeed not receiving the event for index 0.

I was able to obtain:

133 H
166 e
198 l
233 on
233 off
233 l
266 o
10366 b
10416 y

With a change to listener.onChar(nextChar);. of:
listener.onChar(getText().charAt(rawCharIndex-1));

Also, the last character is missing, due to my change (previously, it was missing the first 😺 )

I believe I have fixed this in TextraTypist, but it was a beast to rewrite the various involved code, and I still am not sure I handled everything 100% correctly in all cases. I remember going back and forth between missing the first character and missing the last character... I also remember effects being especially tricky to line up with where their tags were. My solution involved, to some extent, tracking raw character position in the String with tag markup, and handling priority relative to those positions, while the displayed glyphs were essentially separate.