logarrhythmic / karaOK

Aegisub KFX library
28 stars 7 forks source link

Giving table of nil modifierFunctions to ln.wave.transform produces invalid ASS #6

Closed petzku closed 4 years ago

petzku commented 4 years ago

Issue

I ran into this issue with a mistake in my code, effectively doing the following:

waveX = ln.wave.new(); waveX.addWaveform("sine", 2000, 1, 0) --code once
ln.wave.transform(waveX, {"1a"}, nil, nil, nil, 3, nil, {nil}) --inside template

This produces transforms like \t(0,1,1.00,\1a()), which are clearly invalid. Also, style-resetting tags inside \t:s don't behave nicely, apparently applying to the whole line at once, even before the transform's start time.

So I tested a few things. The following:

waveX = ln.wave.new(); waveX.addWaveform("sine", 2000, 1, 0) --code once
function scalefilter(x) return 100 + 10*x end --code once
ln.wave.transform(waveX, {"shad", "fscx", "fscy"}, nil, nil, nil, 3, nil, {nil, scalefilter, scalefilter}) --template

errors with

    File "inline expression `return (ln.wave.transform(waveX, {"shad", "fscx", "fscy"}, nil, nil, nil, 3, nil, {nil, scalefilter, scalefilter}));`", line 1
<main>
    File "[...]\Aegisub\automation\include\ln\kara.lua", line 777
transform
    File "[...]\Aegisub\automation\include\ln\kara.lua", line 250
calcTable
attempt to call a nil value

If the order is switched, i.e.

ln.wave.transform(waveX, {"fscx", "fscy", "shad"}, nil, nil, nil, 3, nil, {scalefilter, scalefilter, nil})

it works, but uses scalefilter for \shad as well: \t(0,1,1.00,\fscx100.00\fscy100.00\shad100.00)\t(0,26,0.97,\fscx103.83\fscy103.83\shad103.83).

If the nil is given as the second function, it errors with the same attempt to call a nil value again.

If we define another filter function, we can notice some more interesting behaviour:

waveX = ln.wave.new(); waveX.addWaveform("sine", 2000, 1, 0) --code once
function scalefilter(x) return 100 + 10*x end --code once
function shadfilter(x) return 3*x end --code once
ln.wave.transform(waveX, {"shad", "fscx", "fscy"}, nil, nil, nil, 3, nil, {shadfilter, scalefilter, nil}) --template

In this case, \fscy is modified by shadfilter: \t(0,1,1.00,\shad0.00\fscx100.00\fscy0.00)\t(0,26,0.97,\shad1.15\fscx103.83\fscy1.15).

Proposal

Allow for nil to be used as a special value inside the modifierFunctions table, effectively working as just a passthrough: function (x) return x end. This is already the behaviour when nil is given as the whole parameter. The same should probably be done if passed a table with less functions than we have transforming tags.

petzku commented 4 years ago

I should note, the behaviour for nil at the end of the table is currently exactly the same as if those elements simply didn't exist.

petzku commented 4 years ago

Apparently the nil-at-end-of-table part is simply a part of lua (love that language), and the way wave.transform repeats the modifierFunctions when it doesn't have enough is actually documented behaviour.

The initial issue seems to be mostly fixed with the new call syntax as of c88e223, but some bugs remain with the old syntax. I'm working on a fixing PR currently.