Run shortcut, store "2". next run, read "2" and go to "3" instead - i.e. "incremental shortcut"

ok i’m ready to ask for advice and show what i’m working with…

the issue is that when i reverse direction (instead of going nextSlice, i go prevSlice) - the first time the shortcut is run, it displays the exact same slice. and if i go from prevSlice to nextSlice - the first run displays the exact same slice.

how do i solve this logic? since on nextSlice, the preferences.sliceCounter.value is increased by +1, and by prevSlice, the preferences.sliceCounter.value is increased by -1, i need it to be able to detect, “previous movement was next” == if running prevSlice, act as if sliceCounter actually provided -1 (i.e. nextSlice set it to 4, prevSlice should start as if it’s 3.) or prevSlice set it to 2, and nextSlice should then be 3.

apart from this logic issue, the script works beautifully.

-- Function to select the next slice
function selectNextSliceInOriginalSample()
  local instrument = renoise.song().selected_instrument
  local sample = instrument.samples[renoise.song().selected_sample_index]
  local sliceMarkers = sample.slice_markers
  local sampleLength = sample.sample_buffer.number_of_frames

  if #sliceMarkers < 2 or not sample.sample_buffer.has_sample_data then
    renoise.app():show_status("Not enough slice markers or sample data is unavailable.")
    return
  end

  local currentSliceIndex = preferences.sliceCounter.value
  local nextSliceIndex = currentSliceIndex + 1
  if nextSliceIndex > #sliceMarkers then
    nextSliceIndex = 1
  end

  local thisSlice = sliceMarkers[currentSliceIndex]
  local nextSlice = sliceMarkers[nextSliceIndex]

  local thisSlicePadding = (currentSliceIndex == 1 and thisSlice < 1000) and thisSlice or math.max(thisSlice - 1000, 1)
  local nextSlicePadding = (nextSliceIndex == 1) and math.min(nextSlice + sampleLength, sampleLength) or math.min(nextSlice + 1354, sampleLength)

  renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR
  sample.sample_buffer.display_range = {thisSlicePadding, nextSlicePadding}
  sample.sample_buffer.display_length = nextSlicePadding - thisSlicePadding

  renoise.app():show_status(string.format("Slice Info - Current index: %d, Next index: %d, Slice Start: %d, Slice End: %d", currentSliceIndex, nextSliceIndex, thisSlicePadding, nextSlicePadding))
  
  preferences.sliceCounter.value = nextSliceIndex
end


-- Function to select the previous slice with proper handling of slice wrapping
function selectPreviousSliceInOriginalSample()
  local instrument = renoise.song().selected_instrument
  local sample = instrument.samples[renoise.song().selected_sample_index]
  local sliceMarkers = sample.slice_markers
  local sampleLength = sample.sample_buffer.number_of_frames
  
  if #sliceMarkers < 2 or not sample.sample_buffer.has_sample_data then
    renoise.app():show_status("Not enough slice markers or sample data is unavailable.")
    return
  end
  
  local currentSliceIndex = preferences.sliceCounter.value
  local previousSliceIndex = currentSliceIndex - 1
  
  if previousSliceIndex < 1 then
    previousSliceIndex = #sliceMarkers  -- Wrap to the last slice
  end

  local previousSlice = sliceMarkers[previousSliceIndex]
  local nextSliceIndex = previousSliceIndex == #sliceMarkers and 1 or previousSliceIndex + 1
  local nextSlice = sliceMarkers[nextSliceIndex]

  -- Calculate the padding for display
  local previousSlicePadding = math.max(previousSlice - 1000, 1)
  local nextSlicePadding = math.min(nextSlice + 1354, sampleLength)

  -- Adjust for wraparound display issue when navigating from first to last slice
  if previousSliceIndex == #sliceMarkers and currentSliceIndex == 1 then
    nextSlicePadding = sampleLength
  end

  -- Set display parameters in the sample editor
  renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR
  sample.sample_buffer.display_range = {previousSlicePadding, nextSlicePadding}
  sample.sample_buffer.display_length = nextSlicePadding - previousSlicePadding

  -- Show status and update slice counter
  renoise.app():show_status(string.format("Slice Info - Previous index: %d, Current index: %d, Slice Start: %d, Slice End: %d",
                                          previousSliceIndex, nextSliceIndex, previousSlicePadding, nextSlicePadding))
  
  preferences.sliceCounter.value = previousSliceIndex
end

-- Function to reset the slice counter
function resetSliceCounter()
  preferences.sliceCounter.value = 1
  renoise.app():show_status("Slice counter reset to 1. Will start from the first slice.")
  selectNextSliceInOriginalSample()
end

-- Keybindings
renoise.tool():add_keybinding{name="Global:Paketti:Select Padded Slice Next Slice", invoke=selectNextSliceInOriginalSample}
renoise.tool():add_keybinding{name="Global:Paketti:Select Padded Slice Previous", invoke=function() selectPreviousSliceInOriginalSample() end}
renoise.tool():add_keybinding{name="Global:Paketti:Reset Slice Counter", invoke=resetSliceCounter}

Padded slice from original sample

i tried a preferences.slicePreviousDirection and setting it to “0” for “previous” and “1” for “next”. but i couldn’t figure out the logic. please help?

p.s. if anyone is wondering what this is, it lets you trim and tweak the slicings so that they hit where they’re supposed to.
and while i like the idea for my own use, there was a request for it from 2022 - and maybe some other years too. Mappable shortcuts to navigate through slice markers (i’m yet to finish going through all the 7300+ ideas and suggestions i’ve archived as PDF per thread, i think i’ve gone through 300 right now.