|
|
|
05-20-2018, 12:02 AM
|
#1
|
Human being with feelings
Join Date: Apr 2016
Posts: 39
|
Possible Bug In GetItemEditingTime2() [No Bug]
Hello everybody, I'm trying to write a shuffle editing script and had it working relatively well by comparing the item's "D_POSITION" over each frame to get a "moving state". However, there were problems with undo so I've opted to use GetItemEditingTime2() instead.
The function is great and is incredibly useful. It fixed my issues with undo easily, but, it doesn't handle quick twitch moves. In the gif below I click the item, get the desired item pickup/drop, then a slow item move performs as expected. However during a quick move, GetItemEditingTime2() does not update, there's a certain move rate where it will kick in, but that rate is still too slow imo. Shouldn't GetItemEditingTime2() return once on the frame of a mouse down?
(also something cool to have would be on_undo()/on_redo functions that perform like reaper.GetProjectStateChangeCount())
Last edited by ausbaxter; 05-26-2018 at 09:54 PM.
|
|
|
05-20-2018, 08:50 AM
|
#2
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
I only use the D_POSITION value from the GetMediaItemInfo_Value function. No problem with that.
Note that shuffle items scripts already exists : https://forum.cockos.com/showthread.php?t=159961
I even have other shuffle scripts with different shuffling algorithm like setting iems 1 2 3 4 5 6 to items 1 6 2 5 3 4 etc... :P
Also some with grouped items support.
|
|
|
05-20-2018, 11:10 AM
|
#3
|
Human being with feelings
Join Date: Apr 2016
Posts: 39
|
Hey X-Raym
I use those scripts daily .
Note that this isn't an item order shuffler. Its a "shuffle editing" deferred script ala Pro Tools. Basically an item move + edge offset. I hope I didn't miss the equivalent script you mention, but I checked the entirety of the actions list (reapack and sws installed) and didn't find one providing this function.
D_POSITION is fine for latching on an "item move" state and then having a timer wait after a stop in movement before committing the edit. But the script couldn't distinguish between the movement of the item due to an undo and an actual user moving the item with their cursor.
ItemEditingTime2() allows you (well ideally) to get a good pseudo mouse down/up event, and informs you of the type of edit being performed (move,fade,edge,etc) pretty powerful. But I'm thinking there's some sort of bug because the item edit state isn't reported effectively on quick moves. A simple click-release seems to report it on initial frame, but again it depends on the speed of the item edit itself whether it gets reported successfully or not.
|
|
|
05-20-2018, 11:56 AM
|
#4
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
In fact I made scripts to ripple edit from item edges
https://forum.cockos.com/showthread.php?t=157698
but it works differently that yours. Your solution seems more intuitive (the kind of Mouse Mofidier we would want !).
I'm really not use to the problematic functions you are talking, I think you are the only one who really explored it so far ^^
Any code snippet to share ?
|
|
|
05-20-2018, 01:45 PM
|
#5
|
Human being with feelings
Join Date: Apr 2016
Posts: 39
|
This is the full script, it should work as desired aside from the item drag speed issue. I wish we could assign deferred scripts to mouse modifier drag contexts! This is just a standard toggle.
I'm not sure if I like the deletion behavior when moving the item beyond its original bounds, maybe using item fades like protools will be nicer in general?
There shouldn't be any issues except for the return value of GetItemEditingTime2 although that may be foolishly hopeful lol
Code:
ripple_all_tracks_check = reaper.GetToggleCommandState(40311) --ripple all tracks check
ripple_one_track_check = reaper.GetToggleCommandState(40310) --ripple all tracks check
auto_cross_fade_off = 41119
auto_cross_fade_on = 41118
ripple_one_track = 40310
ripple_all_tracks = 40311
ripple_off = 40309
remove_item = 40006
deselect_items = 40289
function HandleItemMovement()
current_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
current_state = reaper.GetProjectStateChangeCount(0) --used to apply shuffle offset
t,s,current_edit = reaper.GetItemEditingTime2()
if init == false then
--[[
if current_edit ~= previous_edit then
if current_edit == 4 then
reaper.ShowConsoleMsg("Item Pickup Registered\n")
elseif current_edit == 0 then
reaper.ShowConsoleMsg("Item Dropped\n")
end
end]]
if current_edit == 4 then
not_moving = false
new_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
elseif current_edit == 1 then --edges are resizing make sure to update position
original_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
elseif current_edit == 0 then
not_moving = false
end
if current_edit == 0 and previous_edit == 4 and current_state ~= previous_state and not_moving == false and item == previous_item and current_pos ~= original_pos then
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock()
--reaper.ShowConsoleMsg("Shuffle Offset\n")
not_moving = true
length = reaper.GetMediaItemInfo_Value(item, "D_LENGTH")
offset = new_pos - original_pos
offset_length = offset + length
reaper.SetMediaItemInfo_Value(item, "D_POSITION", original_pos)
reaper.SetMediaItemInfo_Value(item, "D_LENGTH", offset_length)
reaper.SetMediaItemInfo_Value(item, "B_LOOPSRC", 1)
reaper.ApplyNudge(0,0,4,1,offset,false,0)
reaper.UpdateItemInProject(item)
new_pos = original_pos
if current_pos + length < original_pos then --delete
--reaper.ShowConsoleMsg("DELETE")
--not the best, want to preserve fades maybe
reaper.Undo_DoUndo2(0)
item_idx = reaper.GetMediaItemInfo_Value(item, "IP_ITEMNUMBER")
reaper.Main_OnCommand(deselect_items,0)
reaper.SetMediaItemInfo_Value(reaper.GetTrackMediaItem(reaper.GetMediaItemTrack(item),item_idx-1), "B_UISEL", 1)
reaper.Main_OnCommand(remove_item,0)
end
reaper.Undo_EndBlock("Shuffle Item",-1)
reaper.UpdateArrange()
end
end
previous_item = item
previous_pos = current_pos
previous_state = current_state
previous_edit = current_edit
--init is set to false here as at this point all variables have been initialized
init = false
end
init = true
function main()
--get item to compare to previous and track initially selected single item
if reaper.CountSelectedMediaItems(0) == 1 then
item = reaper.GetSelectedMediaItem(0,0)
if init then original_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION") end
else
item = nil
end
--get new item and store start
if item ~= nil then
if init == false then
if item ~= prev_item then
original_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
end
end
HandleItemMovement()
end
prev_item = item
reaper.defer(main)
end
--don't force ripple state when script is toggled off
function RestoreRippleState()
local cmd_id
if ripple_all_tracks_check == 1 then cmd_id = ripple_all_tracks
elseif ripple_one_track_check == 1 then cmd_id = ripple_one_track
elseif ripple_all_tracks_check == 0 and ripple_one_track_check == 0 then cmd_id = ripple_off end
reaper.Main_OnCommand(cmd_id, 0)
end
--ran when toggle is off
function exitnow()
RestoreRippleState()
is_new_value,filename,sectionID,cmdID,mode,resolution,val = reaper.get_action_context()
reaper.SetToggleCommandState(sectionID, cmdID, 0)
reaper.RefreshToolbar2(sectionID, cmdID)
reaper.Main_OnCommand(auto_cross_fade_on,0)
gfx.quit()
end
reaper.atexit(exitnow)
is_new_value,filename,sectionID,cmdID,mode,resolution,val = reaper.get_action_context()
reaper.SetToggleCommandState(sectionID, cmdID, 1)
reaper.RefreshToolbar2(sectionID, cmdID)
reaper.Main_OnCommand(auto_cross_fade_off,0)
reaper.Main_OnCommand(ripple_one_track,0)
main()
And then here is a script that you can use to see how GetItemEditTime2() works
Code:
function test_defer()
t,s,e = reaper.GetItemEditingTime2()
i = reaper.GetSelectedMediaItem(0,0)
if t ~= p_t then
reaper.ShowConsoleMsg("Time:\t" .. t .. "\nItem:\t" .. tostring(s) .. "\tvs\t" .. tostring(i) .. "\nEdit:\t" .. e .. "\t(1 = edge sizing, 2 fade change, 4 item move)\n" .. "*Item is PCM_Source not Mediaitem :( " .. "\n\n")
end
p_t = t
reaper.defer(test_defer)
end
function exit() gfx.quit() end
reaper.atexit(exit)
test_defer()
Last edited by ausbaxter; 05-20-2018 at 11:05 PM.
Reason: Now updates item position when performing edge edits
|
|
|
05-20-2018, 02:12 PM
|
#6
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
Intersting function, I wonder how usable it is.
What the basic idea to find which fades or wich edges has been edited ?
|
|
|
05-20-2018, 03:34 PM
|
#7
|
Human being with feelings
Join Date: Apr 2016
Posts: 39
|
You'd have to look at "D_POSITION" and "D_LENGTH" when GetItemEditTime2() returned the pseudo mouse up. if D_POSITION ~= original position then its a leading edge edit. If D_POSITION == original position and D_LENGTH ~= original length then its a tail edge edit. With fades you'd just check the corresponding fade in/out lengths, my way around that is to ensure that auto fades is off when the script is running.
I think the function would be incredibly useful if the values returned reliably. It provides a way to create mouse down and up events within the reaper main window (although only when dealing with items).
Try moving some items around at different speeds when running the small script in the previous post. You'll notice at a certain speed the pseudo mouse down event isn't triggered on item selection but once the speed of the cursor returns below that invisible movement rate threshold. It's clearly for performance, but I can't see the reason for not being able to get that value on the frame of an item selection, that seems to be the desired effect.
*Edit
Also, reaper.GetProjectStateChangeCount will update at every state change event, so you can use that as a filter with some other logic if you want to deal with things other than items. I had to use it in combination with GetItemEditTime to allow for every other edit function to perform as normal, but allowing item moves to perform the shuffle edit.
|
|
|
05-25-2018, 05:01 AM
|
#8
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
A bit of background: this function is used by the video component to determine what video to display during edits (it'll show you the edit time).
Also a side note: it won't return the edge time exactly, it adjusts it slightly to ensure proper video behavior.
I think the issue you're having is that you get a mousedown/move/mouseup in between your defer() calls, so GetItemEditingTime2() misses that edit (because when you call it, the edit is no longer happening).
|
|
|
05-26-2018, 10:05 PM
|
#9
|
Human being with feelings
Join Date: Apr 2016
Posts: 39
|
Thanks Justin for the clarification. Good to know the background for the function, it's the only way I was able to use lua to get the desired functionality. I was super close to using python.
For those who may be wondering, the problem was not with GetItemEditingTime2(), the rate at which defer is called is variable. (idk how I didn't know that before, seems pretty obvious now) So defer would defer (hehe) its calls as an optimization measure I imagine. And if you were quick enough defer would skip over the edit or miss the initial click on an item.
Still an issue but if you aren't prone to quick-twitch edits the script is still quite usable.
May put this up on reapack in the future.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 07:56 PM.
|