OpenFunscripter / OFS

A tool to create funscripts
GNU General Public License v3.0
90 stars 39 forks source link

lua api help #6

Closed SleepyPrince closed 3 years ago

SleepyPrince commented 3 years ago

I am trying to write an extension to filter script actions, which the following actions seem to require more code than expected (or maybe I am just not familiar with lua). Maybe more lua api functions can be added to make life easier.

  1. the RemoveAction function shifts the script.actions indexes. Here's the code I am using to remove multiple selected actions, please let me know if there is an easier way.

    local script = ofs.Script(ofs.ActiveIdx())
    if ofs.HasSelection(script) then
    local to_delete = {}
    for idx, action in ipairs(script.actions) do
        if action.selected then
            table.insert(to_delete, idx-#to_delete)
        end
    end
    
    for i, idx in ipairs(to_delete) do
        ofs.RemoveAction(script, script.actions[idx])
    end
    ofs.Commit(script)
    end
  2. I am trying to add some functions that I feel is missing for funscript editing. For example to toggle selection of action at/closest to cursor. Here's the code I came up with.

    function toggle_select(val)
    local script = ofs.Script(ofs.ActiveIdx())
    if #script.actions > 0 then
        local t = player.CurrentTime()*1000
        local closest = player.Duration()*1000
        local i = nil
        for idx, action in ipairs(script.actions) do
            local diff = math.abs(t-action.at)
            if diff < closest then
                closest = diff
                i = idx
            else
                break
            end
        end
        script.actions[i].selected = val
        ofs.Commit(script)
    end
    end

    I tried using ClosestActionAfter and ClosestActionBefore, but it still requires quite a few if to find the closest action, and if the cursor is on an action, the 2 functions give you the index of after and before the current action.

  3. OFS could directly return a table of selected indexes instead of having to use for...if script.actions[idx].selected (this is very minor)

  4. There is a typo in the lua api reference, where ofs.SameLine() has a lowercase L.

  5. One more thing, if an extension gui is opened for a long time (maybe 30mins?), it will eventually encounter stack overflow.

OpenFunscripter commented 3 years ago
  1. No right now that's the best way to do it. I could imagine adding something like below where you mark actions for deletion and then delete them with another call. Let me know if you think this would be better.

    local script = ofs.Script(ofs.ActiveIdx())
    if ofs.HasSelection(script) then
    for idx, action in ipairs(script.actions) do
        if action.selected then
           action.delete = true
        end
    end
    ofs.DeleteMarked(script)
    ofs.Commit(script)
    end
  2. I'll add another function ofs.ClosestAction(script, time) for that.

  3. I guess but I don't see a major benefit. Is this below what you had in mind? I can add that.

    local script = ofs.Script(ofs.ActiveIdx())
    local indices = ofs.SelectedIndices(script)
    for i, selectedIdx in ipairs(indices) do
    local action = script.actions[selectedIdx]
    -- do something with action
    end
  4. Thanks fixed

  5. Damn will have troubleshoot that thanks for reporting.

SleepyPrince commented 3 years ago
  1. I am ok with this implementation or just ofs.DeleteSelected(script) would also be fine.
  2. Thanks, how about adding this function (toggle closest action) directly in OFS under Select?
  3. That's what I have in mind, but I am on the fence whether this shall be added to satisfy my laziness :)
OpenFunscripter commented 3 years ago
  1. Alright since it's simpler and requires less documentation I'll add ofs.RemoveSelected(script).
  2. Why do you want this? I'm asking because alot of the key bindings will already default to the closest point if no selection is made and if it's not for moving or deleting why do you want to toggle select the closest point?
SleepyPrince commented 3 years ago
  1. Since you have added ofs.ClosestAction, I can create this feature with keybindings in lua.

btw, is there any plan on adding the scrubbing/dragging through the action background? Scrubbing the timeline is less accurate when I just want to move "a page" or so. Double clicking the background to move will cancel current selection unless ctrl is held.

p.s. Thanks for adding keybinding to reload extensions

SleepyPrince commented 3 years ago

OpenFunscripter.exe.25552.dmp.zip

This seems to crash OFS when triggering toggle_select() when the cursor is not on an action.

function init()
end

function update(delta)
end

function gui()
    if ofs.Button("Toggle") then
        toggle_select()
    end
end

function toggle_select()
    local script = ofs.Script(ofs.ActiveIdx())
    local idx = ofs.ClosestAction(script, player.CurrentTime())
end
OpenFunscripter commented 3 years ago

btw, is there any plan on adding the scrubbing/dragging through the action background? Scrubbing the timeline is less accurate when I just want to move "a page" or so. Double clicking the background to move will cancel current selection unless ctrl is held.

You mean like auto scrolling left/right when you hit the borders during a selection?

This seems to crash OFS when triggering toggle_select() when the cursor is not on an action.

The crash you experienced was just a failed assertion which in this case isn't actually a big deal. But there was an error in the implementation which is fixed now. sorry. 😔

When you compile OFS yourself you should create a release build (unless you're debugging) because the debug builds contain all sorts of assertions and other stuff which can crash if there's no debugger attached.

You can also download bleeding edge release builds here: https://github.com/OpenFunscripter/OFS/actions/workflows/cmake_build.yml Each successfull run produces a zipped windows build.

SleepyPrince commented 3 years ago

You mean like auto scrolling left/right when you hit the borders during a selection?

That's one way but what I thinking is panning the action timeline in general.

OpenFunscripter commented 3 years ago

I created a new release. I added the panning aswell.

https://github.com/OpenFunscripter/OFS/releases/tag/1.4.1