-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "LK_TimelineNavigator" -- ************************************************** -- General information about this script -- ************************************************** LK_TimelineNavigator = {} function LK_TimelineNavigator:Name() return "Timeline Navigator" end function LK_TimelineNavigator:Version() return "2.2" end function LK_TimelineNavigator:UILabel() return "Timeline Navigator" end function LK_TimelineNavigator:Creator() return "Lukas Krepel, Frame Order - Original by Stan" end function LK_TimelineNavigator:Description() return "Move the timeline cursor by specified amount of frames or time intervals and jump to document markers. Press <"..self.previousMarkerShortcut.."/"..self.nextMarkerShortcut.."> to jump to previous/next marker." end function LK_TimelineNavigator:ColorizeIcon() return true end -- ************************************************** -- Is Relevant / Is Enabled -- ************************************************** function LK_TimelineNavigator:IsRelevant(moho) if MohoMode ~= nil then if not MohoMode.keys then return false end end return true end function LK_TimelineNavigator:IsEnabled(moho) return true end -- ************************************************** -- Keyboard/Mouse Control -- ************************************************** function LK_TimelineNavigator:OnMouseDown(moho, mouseEvent) if Syn_ScrubWorkspace ~= nil then Syn_ScrubWorkspace:OnMouseDown(moho, mouseEvent) end end function LK_TimelineNavigator:OnMouseMoved(moho, mouseEvent) if Syn_ScrubWorkspace ~= nil then Syn_ScrubWorkspace:OnMouseMoved(moho, mouseEvent) end end function LK_TimelineNavigator:OnMouseUp(moho, mouseEvent) if Syn_ScrubWorkspace ~= nil then Syn_ScrubWorkspace:OnMouseUp(moho, mouseEvent) end end function LK_TimelineNavigator:OnKeyDown(moho, keyEvent) if keyEvent.key == self.nextMarkerShortcut then self:GoToNextmarker(moho, false) end if keyEvent.key == self.previousMarkerShortcut then self:GoToNextmarker(moho, true) end end -- ************************************************** -- Recurring Values -- ************************************************** LK_TimelineNavigator.frames = 1 LK_TimelineNavigator.seconds = 1 LK_TimelineNavigator.timeMinutes = 0 LK_TimelineNavigator.timeSeconds = 0 LK_TimelineNavigator.timeFrames = 0 LK_TimelineNavigator.previousMarkerShortcut = "," LK_TimelineNavigator.nextMarkerShortcut = "." LK_TimelineNavigator.markerLevelOptions = { "Document", "Layer" } -- * TODO: Both / Parent / Any layer ? -- ************************************************** -- Tool options - create and respond to tool's UI -- ************************************************** LK_TimelineNavigator.FRAMES_BACK = MOHO.MSG_BASE LK_TimelineNavigator.FRAMES_INPUT = MOHO.MSG_BASE + 1 LK_TimelineNavigator.FRAMES_FORWARD = MOHO.MSG_BASE + 2 LK_TimelineNavigator.SECONDS_BACK = MOHO.MSG_BASE + 3 LK_TimelineNavigator.SECONDS_INPUT = MOHO.MSG_BASE + 4 LK_TimelineNavigator.SECONDS_FORWARD = MOHO.MSG_BASE + 5 LK_TimelineNavigator.TIME_MINUTES_INPUT = MOHO.MSG_BASE + 6 LK_TimelineNavigator.TIME_SECONDS_INPUT = MOHO.MSG_BASE + 7 LK_TimelineNavigator.TIME_FRAMES_INPUT = MOHO.MSG_BASE + 8 LK_TimelineNavigator.TIME_GO = MOHO.MSG_BASE + 9 LK_TimelineNavigator.GO_TO_FRAME_ZERO = MOHO.MSG_BASE + 10 LK_TimelineNavigator.PREV_MARKER = MOHO.MSG_BASE + 13 LK_TimelineNavigator.NEXT_MARKER = MOHO.MSG_BASE + 14 LK_TimelineNavigator.GO_TO_DOCUMENT_START = MOHO.MSG_BASE + 15 LK_TimelineNavigator.GO_TO_DOCUMENT_END = MOHO.MSG_BASE + 16 LK_TimelineNavigator.SET_MARKER_LEVEL = MOHO.MSG_BASE + 17 -- * 17 to 30 LK_TimelineNavigator.GO_TO_MARKER = MOHO.MSG_BASE + 30 -- * 30 to x function LK_TimelineNavigator:LoadPrefs(prefs) self.markerLevel = prefs:GetString("LK_TimelineNavigator.markerLevel", self.markerLevelOptions[1]) self.frames = prefs:GetInt("LK_TimelineNavigator.frames", 1) self.seconds = prefs:GetInt("LK_TimelineNavigator.seconds", 1) self.timeMinutes = prefs:GetInt("LK_TimelineNavigator.timeMinutes", 0) self.timeSeconds = prefs:GetInt("LK_TimelineNavigator.timeSeconds", 0) self.timeFrames = prefs:GetInt("LK_TimelineNavigator.timeFrames", 0) end function LK_TimelineNavigator:SavePrefs(prefs) prefs:SetString("LK_TimelineNavigator.markerLevel", self.markerLevel) prefs:SetInt("LK_TimelineNavigator.frames", self.frames) prefs:SetInt("LK_TimelineNavigator.seconds", self.seconds) prefs:SetInt("LK_TimelineNavigator.timeMinutes", self.timeMinutes) prefs:SetInt("LK_TimelineNavigator.timeSeconds", self.timeSeconds) prefs:SetInt("LK_TimelineNavigator.timeFrames", self.timeFrames) end function LK_TimelineNavigator:ResetPrefs(prefs) self.markerLevel = self.markerLevelOptions[1] self.frames = 1 self.seconds = 1 self.timeMinutes = 0 self.timeSeconds = 0 self.timeFrames = 0 end -- ************************************************** -- Tool Panel Layout -- ************************************************** function LK_TimelineNavigator:DoLayout(moho, layout) self.markerChannel = moho.layer.fTimelineMarkers -- *** Move x amount of frames left/right: FO_Utilities:Divider(layout, "Move frame(s)", true) layout:AddPadding(-15) self.framesInput = LM.GUI.TextControl(48, '1', self.FRAMES_INPUT, LM.GUI.FIELD_UINT) layout:AddChild(self.framesInput) layout:AddPadding(-15) self.framesBackButton = LM.GUI.ImageButton("ScriptResources/FO_icons/arrow_left", "Back", false, self.FRAMES_BACK, true) layout:AddChild(self.framesBackButton) self.framesForwardButton = LM.GUI.ImageButton("ScriptResources/FO_icons/arrow_right", "Forward", false, self.FRAMES_FORWARD, true) layout:AddChild(self.framesForwardButton) -- *** Move x amount of seconds left/right: FO_Utilities:Divider(layout, "Move second(s)") layout:AddPadding(-15) self.secondsInput = LM.GUI.TextControl(48, '1', self.SECONDS_INPUT, LM.GUI.FIELD_UFLOAT) layout:AddChild(self.secondsInput) layout:AddPadding(-15) self.secondsBackButton = LM.GUI.ImageButton("ScriptResources/FO_icons/arrow_left", "Back", false, self.SECONDS_BACK, true) layout:AddChild(self.secondsBackButton) self.secondsForwardButton = LM.GUI.ImageButton("ScriptResources/FO_icons/arrow_right", "Forward", false, self.SECONDS_FORWARD, true) layout:AddChild(self.secondsForwardButton) -- *** Go to specified timecode or frame: FO_Utilities:Divider(layout, "Go to (MM:SS:FF)") self.timeMinutesInput = LM.GUI.TextControl(28, '0', self.TIME_MINUTES_INPUT, LM.GUI.FIELD_UINT) layout:AddChild(self.timeMinutesInput) layout:AddPadding(-15) layout:AddChild(LM.GUI.StaticText(':')) layout:AddPadding(-19) self.timeSecondsInput = LM.GUI.TextControl(28, '0', self.TIME_SECONDS_INPUT, LM.GUI.FIELD_UINT) layout:AddChild(self.timeSecondsInput) layout:AddPadding(-15) layout:AddChild(LM.GUI.StaticText(':')) layout:AddPadding(-19) self.timeFramesInput = LM.GUI.TextControl(28, '0', self.TIME_FRAMES_INPUT, LM.GUI.FIELD_UINT) layout:AddChild(self.timeFramesInput) layout:AddPadding(-15) self.goButton = LM.GUI.ImageButton("ScriptResources/FO_icons/Set", "Go", false, self.TIME_GO, true) layout:AddChild(self.goButton) -- ******************************* -- *** Go to Markers: *** -- ******************************* FO_Utilities:Divider(layout, "Go to Markers") -- *** Level Dropdown: -- * Level Dropdown: if self.markerLevel == "" then -- * Prefs bugfix self.markerLevel = self.markerLevelOptions[1] end self.levelPopup = LM.GUI.PopupMenu(75, false) layout:AddChild(self.levelPopup) layout:AddPadding(-14) -- * Marker Dropdown: self.markerPopup = LM.GUI.PopupMenu(200, false) layout:AddChild(self.markerPopup) -- * Previous/Next Marker: self.prevMarkerButton = LM.GUI.ImageButton("ScriptResources/FO_icons/timeline_marker_prev", "Back", false, self.PREV_MARKER, true) layout:AddChild(self.prevMarkerButton) layout:AddPadding(-14) self.nextMarkerButton = LM.GUI.ImageButton("ScriptResources/FO_icons/timeline_marker_next", "Forward", false, self.NEXT_MARKER, true) layout:AddChild(self.nextMarkerButton) end function LK_TimelineNavigator:UpdateWidgets(moho) if moho:IsPlaying() then return end FO_Utilities.tinyUI = false self.framesInput:SetValue(self.frames) self.secondsInput:SetValue(self.seconds) self.timeMinutesInput:SetValue(self.timeMinutes) self.timeSecondsInput:SetValue(self.timeSeconds) self.timeFramesInput:SetValue(self.timeFrames) if self.markerLevel == "Document" then self.markerChannel = moho.document.fTimelineMarkers else self.markerChannel = moho.layer.fTimelineMarkers end -- *** Marker Dropdown: local markerChannel = self.markerChannel local markerLabel = "" if moho.frame == 0 then markerLabel = " - Zero" elseif moho.frame == moho.document:StartFrame() then markerLabel = " - Start" elseif moho.frame == moho.document:EndFrame() then markerLabel = " - End" elseif markerChannel:HasKey(moho.frame) then markerLabel = markerChannel:GetValue(moho.frame) markerLabel = string.gsub(markerLabel, "\n", " ") markerLabel = " - "..markerLabel if markerChannel:GetValue(moho.frame) == "" then local markerInterp = MOHO.InterpSetting:new_local() markerChannel:GetKeyInterp(moho.frame, markerInterp) markerLabel = " - "..FO_Utilities.colorNames[markerInterp.tags] end end local menuLabel = moho.frame..markerLabel self.markerMenu = LM.GUI.Menu(menuLabel) -- *** Dropdown items: -- * Zero: self.markerMenu:AddItem("0 - Zero", 0, self.GO_TO_FRAME_ZERO) -- * Start: local startFrame = moho.document:StartFrame().." - Start" self.markerMenu:AddItem(startFrame, 0, self.GO_TO_DOCUMENT_START) self.markerMenu:AddItem("---", 0, 0) -- * Markers: local markers = {} for i = 1, markerChannel:CountKeys()-1 do local markerFrame = markerChannel:GetKeyWhen(i) local markerLabel = markerChannel:GetValueByID(i) markerLabel = string.gsub(markerLabel, "\n", " ") if markerLabel == "" then local markerInterp = MOHO.InterpSetting:new_local() markerChannel:GetKeyInterp(markerChannel:GetKeyWhen(i), markerInterp) markerLabel = FO_Utilities.colorNames[markerInterp.tags] end local marker = markerFrame.." - "..markerLabel table.insert(markers, marker) end local i for i = 1, #markers do local file = markers[i] self.markerMenu:AddItem((tostring(markers[i])), 0, (self.GO_TO_MARKER + i)) end if #markers ~= 0 then self.markerMenu:AddItem("---", 0, 0) end -- * End: local endFrame = moho.document:EndFrame().." - End" self.markerMenu:AddItem(endFrame, 0, self.GO_TO_DOCUMENT_END) -- *** Checks: self.markerMenu:SetChecked(self.GO_TO_DOCUMENT_START, moho.document:StartFrame() == moho.frame) for i = 1, markerChannel:CountKeys()-1 do local markerFrame = markerChannel:GetKeyWhen(i) self.markerMenu:SetChecked(self.GO_TO_MARKER + i, moho.frame == markerFrame) end self.markerMenu:SetChecked(self.GO_TO_DOCUMENT_END, moho.document:EndFrame() == moho.frame) -- * Set menu to dropdown: self.markerPopup:SetMenu(self.markerMenu) self.markerPopup:Redraw() -- * Level Menu: self.levelMenu = LM.GUI.Menu(self.markerLevel) for i = 1, #self.markerLevelOptions do local option = self.markerLevelOptions[i] self.levelMenu:AddItem(option, 0, self.SET_MARKER_LEVEL+i) self.levelMenu:SetChecked(self.SET_MARKER_LEVEL+i, self.markerLevel == option) end self.levelPopup:SetMenu(self.levelMenu) self.levelPopup:Redraw() end function LK_TimelineNavigator:HandleMessage(moho, view, msg) local curFrame = moho.frame local fps = moho.document:Fps() self.frames = self.framesInput:IntValue() self.seconds = self.secondsInput:FloatValue() self.timeMinutes = self.timeMinutesInput:IntValue() self.timeSeconds = LM.Clamp(self.timeSecondsInput:IntValue(), 0, 59) self.timeFrames = self.timeFramesInput:IntValue() if msg == self.GO_TO_FRAME_ZERO then moho:SetCurFrame(0) elseif msg == self.GO_TO_DOCUMENT_START then moho:SetCurFrame(moho.document:StartFrame()) elseif msg == self.GO_TO_DOCUMENT_END then moho:SetCurFrame(moho.document:EndFrame()) elseif msg >= self.GO_TO_MARKER then local option = msg - self.GO_TO_MARKER moho:SetCurFrame(self.markerChannel:GetKeyWhen(option)) elseif msg == self.PREV_LAYER_MARKER then self:GoToNextLayerMarker(moho, true) elseif msg == self.NEXT_LAYER_MARKER then self:GoToNextLayerMarker(moho, false) elseif msg == self.PREV_MARKER then self:GoToNextmarker(moho, true) elseif msg == self.NEXT_MARKER then self:GoToNextmarker(moho, false) elseif msg == self.FRAMES_BACK then local newFrame = curFrame - self.frames if newFrame < 0 then newFrame = 0 end moho:SetCurFrame(newFrame) elseif msg == self.FRAMES_FORWARD then moho:SetCurFrame(curFrame + self.frames) elseif msg == self.SECONDS_BACK then local frames = self.seconds * fps local newFrame = curFrame - math.floor(frames) if newFrame < 0 then newFrame = 0 end moho:SetCurFrame(newFrame) elseif msg == self.SECONDS_FORWARD then local frames = self.seconds * fps moho:SetCurFrame(curFrame + math.floor(frames)) elseif msg == self.TIME_GO then local newFrame = (self.timeMinutes * 60 * fps) + (self.timeSeconds * fps) + self.timeFrames moho:SetCurFrame(newFrame) elseif msg == self.TIME_SECONDS_INPUT then self.timeSecondsInput:SetValue(LM.Clamp(self.timeSecondsInput:IntValue(), 0, 59)) elseif msg >= self.SET_MARKER_LEVEL and msg < self.GO_TO_MARKER then local option = msg - self.SET_MARKER_LEVEL self.markerLevel = self.markerLevelOptions[option] self:UpdateWidgets(moho) end end function LK_TimelineNavigator:GoToNextmarker(moho, backwards) backwards = backwards or false local markerFrames = {} local markerChannel = self.markerChannel -- * TODO table.insert(markerFrames, moho.document:StartFrame()) table.insert(markerFrames, moho.document:EndFrame()) for markerID = 1, markerChannel:CountKeys()-1 do local markerFrame = markerChannel:GetKeyWhen(markerID) table.insert(markerFrames, markerFrame) local interp = MOHO.InterpSetting:new_local() markerChannel:GetKeyInterp(markerFrame, interp) if interp.hold > 0 then local holdEndFrame = markerFrame + interp.hold table.insert(markerFrames, holdEndFrame) end end local gotoFrame if backwards then gotoFrame = -1000000000 else gotoFrame = 1000000000 end for i = 1, #markerFrames do local markerFrame = markerFrames[i] if backwards then if markerFrame < moho.frame and gotoFrame < markerFrame then gotoFrame = markerFrame end else if markerFrame > moho.frame and gotoFrame > markerFrame then gotoFrame = markerFrame end end end if gotoFrame == -1000000000 or gotoFrame == 1000000000 then return end moho:SetCurFrame(gotoFrame) end
TimelineNavigator
Listed
Author: Lukas
View Script
Script type: Tool
Uploaded: Jun 25 2022, 03:42
Last modified: Sep 05 2023, 12:58
Jump through the timeline by amount of frames/times or to document/layer markers

Use keyboard shortcuts , and . to jump from marker to marker. It also jumps to marker ends if you're using hold interpolation on the marker keys and document start/end frames.
Based on Stan's Timeline Navigator tool.
Changelog:
- v2.0 Initial release
- v2.1 Fixed LK_Powertool error
- v2.2 Fixed MohoMode error
This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 585

TimelineNavigator
Listed
Author: Lukas
View Script
Script type: Tool
Uploaded: Jun 25 2022, 03:42
Last modified: Sep 05 2023, 12:58
Jump through the timeline by amount of frames/times or to document/layer markers

Use keyboard shortcuts , and . to jump from marker to marker. It also jumps to marker ends if you're using hold interpolation on the marker keys and document start/end frames.
Based on Stan's Timeline Navigator tool.
Changelog:
- v2.0 Initial release
- v2.1 Fixed LK_Powertool error
- v2.2 Fixed MohoMode error
This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 585