-- WARNING: This script requires AE_Utilities.lua of version 1.11 or later! -- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "DV_TweenMachine" -- ************************************************** -- General information about this script -- ************************************************** DV_TweenMachine = {} function DV_TweenMachine:Name() return self:Localize("Name") end function DV_TweenMachine:Version() return "1.0" end function DV_TweenMachine:Description() return self:Localize("Description") end function DV_TweenMachine:Creator() return "davood tabatabei davoodice,thanks to A.Evseeva, Stan, Lukas Krepel" end function DV_TweenMachine:UILabel() return self:Localize("UILabel") end function DV_TweenMachine:ColorizeIcon() return true end function DV_TweenMachine:LoadPrefs(prefs) self.applyToChildLayers = prefs:GetBool("DV_TweenMachine.applyToChildLayers", true) self.timelinevisibleOnly = prefs:GetBool("DV_TweenMachine.timelinevisibleOnly", false) self.applyToRefs = prefs:GetBool("DV_TweenMachine.applyToRefs", false) self.precalcCycles = prefs:GetBool("DV_TweenMachine.precalcCycles", true) self.ignoreStringChannels = prefs:GetBool("DV_TweenMachine.ignoreStringChannels", false) self.ignoreHiddenBones = prefs:GetBool("DV_TweenMachine.ignoreHiddenBones", true) self.trackAnimOption = prefs:GetString("DV_TweenMachine.trackAnimOption", "active") self.ifEqual = prefs:GetBool("DV_TweenMachine.ifEqual", false) self.selectedBonesOnly = prefs:GetBool("DV_TweenMachine.selectedBonesOnly", false) self.useStepIntervals = prefs:GetBool("DV_TweenMachine.useStepIntervals", false) self.previewSlider = prefs:GetBool("DV_TweenMachine.previewSlider", true) end function DV_TweenMachine:SavePrefs(prefs) prefs:SetBool("DV_TweenMachine.applyToChildLayers", self.applyToChildLayers) prefs:SetBool("DV_TweenMachine.timelinevisibleOnly", self.timelinevisibleOnly) prefs:SetBool("DV_TweenMachine.applyToRefs", self.applyToRefs) prefs:SetBool("DV_TweenMachine.precalcCycles", self.precalcCycles) prefs:SetBool("DV_TweenMachine.ignoreStringChannels", self.ignoreStringChannels) prefs:SetBool("DV_TweenMachine.ignoreHiddenBones", self.ignoreHiddenBones) prefs:SetString("DV_TweenMachine.trackAnimOption", self.trackAnimOption) prefs:SetBool("DV_TweenMachine.ifEqual", self.ifEqual) prefs:SetBool("DV_TweenMachine.selectedBonesOnly", self.selectedBonesOnly) prefs:SetBool("DV_TweenMachine.useStepIntervals", self.useStepIntervals) prefs:SetBool("DV_TweenMachine.previewSlider", self.previewSlider) end function DV_TweenMachine:ResetPrefs() self.applyToChildLayers = false self.timelinevisibleOnly = false self.applyToRefs = false self.precalcCycles = false self.ignoreStringChannels = true self.ignoreHiddenBones = true self.ifEqual = true self.selectedBonesOnly = true self.useStepIntervals = false self.previewSlider = false end -- ************************************************** -- Is Relevant / Is Enabled -- ************************************************** function DV_TweenMachine:IsRelevant(moho) if MohoMode ~= nil then return not MohoMode.vanilla end return true end function DV_TweenMachine:IsEnabled(moho) return true end -- ************************************************** -- Include Bone Select tool mouse functions -- ************************************************** function DV_TweenMachine:OnMouseDown(moho, mouseEvent) LM_SelectBone:OnMouseDown(moho, mouseEvent) end function DV_TweenMachine:OnMouseUp(moho, mouseEvent) LM_SelectBone:OnMouseUp(moho, mouseEvent) end function DV_TweenMachine:OnMouseMoved(moho, mouseEvent) LM_SelectBone:OnMouseMoved(moho, mouseEvent) end -- ************************************************** -- Tool level variables to bind UI -- ************************************************** -- * Settings: DV_TweenMachine.NumberOFButtons = 13 DV_TweenMachine.presetButton={0,5,10,15,50,80,85,90,95,100,105,110,115} DV_TweenMachine.applyToChildLayers = false DV_TweenMachine.timelinevisibleOnly = false DV_TweenMachine.applyToRefs = false DV_TweenMachine.precalcCycles = false DV_TweenMachine.ignoreStringChannels = true DV_TweenMachine.ignoreHiddenBones = true DV_TweenMachine.ifEqual = true DV_TweenMachine.selectedBonesOnly = true DV_TweenMachine.useStepIntervals = false DV_TweenMachine.previewSlider = false -- * Slider: DV_TweenMachine.sliderVal = 0 DV_TweenMachine.slidertextVal = 0 DV_TweenMachine.tweenButton = {} -- DV_TweenMachine.currentPercentage = 0 -- ************************************************** -- Tool options - create and respond to tool's UI -- ************************************************** -- * Settings: DV_TweenMachine.APPLY_TO_CHILD_LAYERS = MOHO.MSG_BASE + 1 DV_TweenMachine.TIMELINEVISIBLE_ONLY = MOHO.MSG_BASE + 2 DV_TweenMachine.APPLY_TO_REFS = MOHO.MSG_BASE + 3 DV_TweenMachine.PRECALC_CYCLES = MOHO.MSG_BASE + 4 DV_TweenMachine.IGNORE_STRING_CHANNELS = MOHO.MSG_BASE + 5 DV_TweenMachine.IGNORE_HIDDEN_BONES = MOHO.MSG_BASE + 6 DV_TweenMachine.SELECTED_BONES_ONLY = MOHO.MSG_BASE + 7 DV_TweenMachine.USE_STEP_INTERVALS = MOHO.MSG_BASE + 8 DV_TweenMachine.EQUALCHECK = MOHO.MSG_BASE + 9 DV_TweenMachine.PREVIEWSLIDERCHECK = MOHO.MSG_BASE + 10 DV_TweenMachine.TOGGLE_ACCURATE_SLIDER_PREVIEW = MOHO.MSG_BASE + 11 -- * Slider: DV_TweenMachine.SLIDER_DRAG = MOHO.MSG_BASE + 12 DV_TweenMachine.SLIDER_DRAG_TEXT_INPUT = MOHO.MSG_BASE + 13 DV_TweenMachine.BUTTON_MSG = MOHO.MSG_BASE + 100 DV_TweenMachine.ALT_BUTTON_MSG = MOHO.MSG_BASE + 200 DV_TweenMachine.TWEEK_PLUS = MOHO.MSG_BASE + 14 DV_TweenMachine.TWEEK_PLUS_ALT = MOHO.MSG_BASE + 15 DV_TweenMachine.TWEEK_MINUS = MOHO.MSG_BASE + 16 DV_TweenMachine.TWEEK_MINUS_ALT = MOHO.MSG_BASE + 17 DV_TweenMachine.SLIDER_OK = MOHO.MSG_BASE + 18 function DV_TweenMachine:DoLayout(moho, layout) -- * Tween machine: -- self.twname = LM.GUI.StaticText(self:Localize("Tween Machine:")) -- layout:AddChild(self.twname) -- * Settings dropdown: self.settingsMenu = LM.GUI.Menu(self:Localize("Settings")) self.settingsMenu_popup = LM.GUI.PopupMenu(100, false) self.settingsMenu_popup:SetMenu(self.settingsMenu) self.settingsMenu:AddItem(self:Localize("ApplyToChildLayers"), 0, self.APPLY_TO_CHILD_LAYERS) -- self.settingsMenu:AddItem(self:Localize("Timeline-visible Child Layers Only"), 0, self.TIMELINEVISIBLE_ONLY) -- self.settingsMenu:AddItem(self:Localize("ApplyToRefs"), 0, self.APPLY_TO_REFS) -- self.settingsMenu:AddItem(self:Localize("PrecalcCycles"), 0, self.PRECALC_CYCLES) -- self.settingsMenu:AddItem(self:Localize("IgnoreStringChannels"), 0, self.IGNORE_STRING_CHANNELS) self.settingsMenu:AddItem(self:Localize("IgnoreHiddenBones"), 0, self.IGNORE_HIDDEN_BONES) self.settingsMenu:AddItem(self:Localize("SelectedBonesOnly"), 0, self.SELECTED_BONES_ONLY) -- self.settingsMenu:AddItem(self:Localize("Use step intervals"), 0, self.USE_STEP_INTERVALS) -- self.settingsMenu:AddItem(self:Localize("Set key even if value does not change"), 0, self.EQUALCHECK) -- self.settingsMenu:AddItem(self:Localize("Preview toolbar (disable if scrubbing/playback is slow)"), 0, self.PREVIEWSLIDERCHECK) -- self.settingsMenu:AddItem(self:Localize("Less accurate toolbar preview (uses current layer's keys only, faster)"), 0, self.TOGGLE_ACCURATE_SLIDER_PREVIEW) layout:AddChild(self.settingsMenu_popup) self.settingsMenu_popup:SetToolTip(self:Localize("settingsMenuTooltip")) -- * buttons for i=1 , self.NumberOFButtons do local btnName = LM.GUI.Button("", self.BUTTON_MSG + i) self.tweenButton[i]=btnName self.tweenButton[i]:SetLabel(self.presetButton[i]) layout:AddChild(self.tweenButton[i]) btnName:SetAlternateMessage(self.ALT_BUTTON_MSG + i) end self.tweekMinus = LM.GUI.Button("", self.TWEEK_MINUS) self.tweekMinus:SetLabel("<<") layout:AddChild(self.tweekMinus) self.tweekMinus:SetAlternateMessage(self.TWEEK_MINUS_ALT) self.tweekPlus = LM.GUI.Button("", self.TWEEK_PLUS) self.tweekPlus:SetLabel(">>") layout:AddChild(self.tweekPlus) self.tweekPlus:SetAlternateMessage(self.TWEEK_PLUS_ALT) -- * Slider: local sliderSize = 200 self.slider = LM.GUI.Slider(sliderSize,false,false, self.SLIDER_DRAG) layout:AddChild(self.slider) self.slider:SetRange(-15,115) self.slider:SetNumTicks(3) self.slider:SetShowTicks(true) self.slider:SetSnapToTicks(false) -- * Slider text input: self.slidertext = LM.GUI.TextControl(30, "0", self.SLIDER_DRAG_TEXT_INPUT, LM.GUI.FIELD_INT, MOHO.Localize("")) self.slidertext:SetWheelInc(1) layout:AddChild(self.slidertext) layout:AddPadding(-15) self.perc = LM.GUI.StaticText(self:Localize("%")) layout:AddChild(self.perc) self.sliderOK = LM.GUI.Button(self:Localize("OK"), self.SLIDER_OK) layout:AddChild(self.sliderOK) end -- ************************************************** -- Find key -- ************************************************** function DV_TweenMachine:FindKey(channels, start_frame, end_frame, moho) local found_key = false local layer = moho.layer local timing_offset local increment if end_frame > start_frame then increment = 1 else increment = -1 end if layer.TotalTimingOffset ~= nil then timing_offset = layer:TotalTimingOffset() else timing_offset = 0 end -- * Go through next/previous frames and stop when a keyframe is found for frame = start_frame, end_frame, increment do for i, channel in ipairs(channels) do if channel.HasKey ~= nil and channel:HasKey(frame) then found_key = true break end end if found_key then return frame-timing_offset end end return 0 end function DV_TweenMachine:UpdateWidgets(moho) self.slider:SetValue(self.sliderVal) self.slidertext:SetValue(self.slidertextVal) -- * Update slider: --local preview = true -- if( true) then -- self.currentPercentage = 0 -- if(not self.slider:IsMouseDragging()) then -- local layer = moho.layer -- local current_frame -- if moho.layerFrame ~= nil then -- current_frame = moho.layerFrame -- else -- current_frame = moho.frame -- end -- -- * Get channels: -- local channels = {} -- channels = self:GetChannels(moho) -- -- * Check whether there are any keys to the left of the cursor -- local prevKey = self:FindKey(channels, current_frame-1, 0, moho) -- local nextKey = self:FindKey(channels, current_frame, moho.document:AnimDuration(), moho) -- if current_frame > moho.document:AnimDuration() then -- nextKey = current_frame -- end -- if nextKey ~= 0 then -- -- * -- local range = math.abs(nextKey-prevKey) -- currentPercentage = (current_frame-prevKey)/range*100 -- self.sliderVal = currentPercentage -- self.slidertextVal = currentPercentage -- else -- if prevKey ~= nextKey then -- currentPercentage = 100 -- end -- end -- end -- self.slidertextVal = currentPercentage -- self.sliderVal = currentPercentage -- -- * -- self.slider:SetValue(self.sliderVal) -- self.slidertext:SetValue(self.slidertextVal) -- end -- * Update menu: self.settingsMenu:SetEnabled(self.TOGGLE_ACCURATE_SLIDER_PREVIEW, self.previewSlider) -- * self.settingsMenu:SetChecked(self.APPLY_TO_CHILD_LAYERS, self.applyToChildLayers) self.settingsMenu:SetChecked(self.TIMELINEVISIBLE_ONLY, self.timelinevisibleOnly) self.settingsMenu:SetChecked(self.APPLY_TO_REFS, self.applyToRefs) self.settingsMenu:SetChecked(self.PRECALC_CYCLES, self.precalcCycles) self.settingsMenu:SetChecked(self.IGNORE_STRING_CHANNELS, self.ignoreStringChannels) self.settingsMenu:SetChecked(self.IGNORE_HIDDEN_BONES, self.ignoreHiddenBones) self.settingsMenu:SetChecked(self.SELECTED_BONES_ONLY, self.selectedBonesOnly) self.settingsMenu:SetChecked(self.USE_STEP_INTERVALS, self.useStepIntervals) self.settingsMenu:SetChecked(self.EQUALCHECK, self.ifEqual) self.settingsMenu:SetChecked(self.PREVIEWSLIDERCHECK, self.previewSlider) end function DV_TweenMachine:HandleMessage(moho, view, msg) if msg == self.SLIDER_DRAG then if not self.undoPrepped then moho.document:PrepMultiUndo() moho.document:SetDirty() self.undoPrepped = true end self.slidertext:SetValue(self.slider:Value()) self.slidertextVal = self.slider:Value() if(not self.slider:IsMouseDragging()) then self.sliderVal = self.slider:Value() self:SetKeyTween(moho, self.slider:Value()) moho.layer:UpdateCurFrame() self.undoPrepped = false moho:UpdateUI() end elseif msg == self.SLIDER_DRAG_TEXT_INPUT then self.slidertextVal = self.slidertext:Value() self.sliderVal = self.slidertext:Value() moho.document:PrepMultiUndo() moho.document:SetDirty() self:SetKeyTween(moho, self.slidertext:Value()) moho:UpdateUI() moho.layer:UpdateCurFrame() self.sliderVal = self.slider:Value() elseif msg == self.APPLY_TO_CHILD_LAYERS then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.applyToChildLayers = self.settingsMenu:IsChecked(self.APPLY_TO_CHILD_LAYERS) elseif msg == self.TIMELINEVISIBLE_ONLY then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.timelinevisibleOnly = self.settingsMenu:IsChecked(self.TIMELINEVISIBLE_ONLY) elseif msg == self.APPLY_TO_REFS then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.applyToRefs = self.settingsMenu:IsChecked(self.APPLY_TO_REFS) elseif msg == self.PRECALC_CYCLES then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.precalcCycles = self.settingsMenu:IsChecked(self.PRECALC_CYCLES) elseif msg == self.IGNORE_STRING_CHANNELS then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.ignoreStringChannels = self.settingsMenu:IsChecked(self.IGNORE_STRING_CHANNELS) elseif msg == self.IGNORE_HIDDEN_BONES then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.ignoreHiddenBones = self.settingsMenu:IsChecked(self.IGNORE_HIDDEN_BONES) elseif msg == self.SELECTED_BONES_ONLY then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.selectedBonesOnly = self.settingsMenu:IsChecked(self.SELECTED_BONES_ONLY) elseif msg == self.USE_STEP_INTERVALS then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.useStepIntervals = self.settingsMenu:IsChecked(self.USE_STEP_INTERVALS) elseif msg == self.EQUALCHECK then self.settingsMenu:SetChecked(msg, not self.settingsMenu:IsChecked(msg)) self.ifEqual = self.settingsMenu:IsChecked(msg) elseif msg >= self.BUTTON_MSG and msg <= self.BUTTON_MSG+50 then local val = self.presetButton[msg-self.BUTTON_MSG] self:SetKeyTween(moho, val) self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg >= self.ALT_BUTTON_MSG and msg <= self.ALT_BUTTON_MSG+50 then local val = -self.presetButton[msg-self.ALT_BUTTON_MSG] self:SetKeyTween(moho, val) self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg == self.TWEEK_PLUS then local val = self.slidertextVal+1 self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val self:SetKeyTween(moho, val) moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg == self.TWEEK_PLUS_ALT then local val = self.slidertextVal+2 self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val self:SetKeyTween(moho, val) moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg == self.TWEEK_MINUS then local val = self.slidertextVal-1 self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val self:SetKeyTween(moho, val) moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg == self.TWEEK_MINUS_ALT then local val = self.slidertextVal-2 self.slidertext:SetValue(val) self.slidertextVal = val self.sliderVal = val self:SetKeyTween(moho, val) moho:UpdateUI() moho.layer:UpdateCurFrame() elseif msg == self.SLIDER_OK then self.sliderVal = self.slidertext:Value() moho.document:PrepMultiUndo() moho.document:SetDirty() self:SetKeyTween(moho,self.slidertext:Value()) moho:UpdateUI() moho.layer:UpdateCurFrame() self.sliderVal = self.slider:Value() end end function DV_TweenMachine:DrawMe(moho, view) LM_TransformLayer:DrawMe(moho, view) end -- ************************************************** -- Get channels that are supposed to be excluded -- ************************************************** function DV_TweenMachine:CollectExcludeChannels(moho, layer) local exclude_channels = {} if moho:LayerAsBone(layer) then if self.ignoreHiddenBones or self.selectedBonesOnly then local skel = moho:LayerAsBone(layer):Skeleton() if skel:CountBones() > 0 then local maxChannel = layer:CountChannels()-1 local chInfo = MOHO.MohoLayerChannel:new_local() local absNumber = 0 for i=1, maxChannel do layer:GetChannelInfo(i, chInfo) local name = chInfo.name:Buffer() if string.sub(name, 1, 5) == "Bone " and chInfo.subChannelCount == skel:CountBones() then for j=0, skel:CountBones()-1 do if(self.ignoreHiddenBones and skel:Bone(j).fHidden) or (self.selectedBonesOnly and not skel:Bone(j).fSelected) then local hiddenChannel = layer:Channel(i,j,moho.document) table.insert(exclude_channels, tostring(hiddenChannel)) end end end absNumber = absNumber + chInfo.subChannelCount end end end end return exclude_channels end -- ************************************************** -- ??? Don't quite understand this AE_ function. What is track animation? -- ************************************************** function DV_TweenMachine:CheckChannelForAddKeyTween(moho, channel, channelFrame) --if channel:HasKey(channelFrame) then return false end if self.ignoreStringChannels and channel:ChannelType() == MOHO.CHANNEL_STRING then return false end if not self.precalcCycles and self:IsCycled(moho,channel,channelFrame) > 0 then return false end if self.precalcCycles and self:IsCycled(moho,channel,channelFrame) > 0 then return true end --check track anim option menu and return false if condition not met if self.trackAnimOption == "active" and channel:Duration() < channelFrame then return false end if self.trackAnimOption == "long" and channel:Duration() <= 1 then return false end if self.trackAnimOption == "any" and channel:Duration() < 1 then return false end --if self.getFromKey == self.PREVIOUS_KEY and (not self.useStepIntervals) and channel:GetKeyInterpModeByID(channel:GetClosestKeyID(channelFrame)) == MOHO.INTERP_STEP then return false end return true end function DV_TweenMachine:CheckChannelForAddKey(moho, channel, channelFrame) --davoodice if channel:HasKey(channelFrame) then return false end if self.ignoreStringChannels and channel:ChannelType() == MOHO.CHANNEL_STRING then return false end if not self.precalcCycles and self:IsCycled(moho,channel,channelFrame) > 0 then return false end if self.precalcCycles and self:IsCycled(moho,channel,channelFrame) > 0 then return true end --check track anim option menu and return false if condition not met if self.trackAnimOption == "active" and channel:Duration() < channelFrame then return false end if self.trackAnimOption == "long" and channel:Duration() <= 1 then return false end if self.trackAnimOption == "any" and channel:Duration() < 1 then return false end --if self.getFromKey == self.PREVIOUS_KEY and (not self.useStepIntervals) and channel:GetKeyInterpModeByID(channel:GetClosestKeyID(channelFrame)) == MOHO.INTERP_STEP then return false end return true end -- ************************************************** -- Get channels used for tween -- ************************************************** function DV_TweenMachine:GetChannels(moho) local channels = {} local layersCollection = self:GetSelectedLayers(moho) for id, layer in pairs(layersCollection) do if (not self.selectedBonesOnly) or moho:LayerAsBone(layer) then local exclude_channels = self:CollectExcludeChannels(moho, layer) local curFrame = layer:TotalTimingOffset() + moho.frame if curFrame == 0 then return end for subId, id, channel, chInfo in AE_Utilities:IterateAllChannels(moho, layer) do if not(table.contains(exclude_channels, tostring(channel))) then if self:CheckChannelForAddKeyTween(moho, channel, curFrame) then local derivedChannel = AE_Utilities:GetDerivedChannel(moho, channel) table.insert(channels, derivedChannel) end end end end end return channels end -- ************************************************** -- Get layer channels only -- ************************************************** function DV_TweenMachine:LayerChannels(moho) local layerChannels = {} local chInfo = MOHO.MohoLayerChannel:new_local() for i = 0, moho.layer:CountChannels()-1 do moho.layer:GetChannelInfo(i, chInfo) if not chInfo.selectionBased then for j=0, chInfo.subChannelCount-1 do local subChannel = moho.layer:Channel(i, j, moho.document) local channel = nil if subChannel:ChannelType() == MOHO.CHANNEL_VAL then channel = moho:ChannelAsAnimVal(subChannel) elseif subChannel:ChannelType() == MOHO.CHANNEL_VEC2 then channel = moho:ChannelAsAnimVec2(subChannel) elseif subChannel:ChannelType() == MOHO.CHANNEL_VEC3 then channel = moho:ChannelAsAnimVec3(subChannel) elseif subChannel:ChannelType() == MOHO.CHANNEL_BOOL then channel = moho:ChannelAsAnimBool(subChannel) elseif subChannel:ChannelType() == MOHO.CHANNEL_COLOR then channel = moho:ChannelAsAnimColor(subChannel) elseif subChannel:ChannelType() == MOHO.CHANNEL_STRING then channel = moho:ChannelAsAnimString(subChannel) end -- do something with it if channel then table.insert(layerChannels, channel) end end end end return layerChannels end -- ************************************************** -- Set a key at a certain percentage -- ************************************************** function DV_TweenMachine:SetKeyTween(moho, percentage,tweek) tweek = false if(tweek) then self:SetKey(moho) end percentage =percentage or 100 local layersCollection = self:GetSelectedLayers(moho) local previousMarkerTime = moho.frame if self.getFromKey == self.PREVIOUSMARKER_VALUES then markerChannel = moho.document.fTimelineMarkers previousMarkerTime = markerChannel:GetClosestKeyID(moho.frame - 1) previousMarkerTime = markerChannel:GetKeyWhen(previousMarkerTime) end for id, layer in pairs(layersCollection) do if (not self.selectedBonesOnly) or moho:LayerAsBone(layer) then local exclude_channels = self:CollectExcludeChannels(moho, layer) local curFrame = layer:TotalTimingOffset() + moho.frame if curFrame == 0 then return end for subId, id, channel, chInfo in AE_Utilities:IterateAllChannels(moho, layer) do if not(table.contains(exclude_channels, tostring(channel))) then if self:CheckChannelForAddKeyTween(moho, channel, curFrame) then local derivedChannel = AE_Utilities:GetDerivedChannel(moho, channel) --local fromFrame = curFrame local fromFrameP = curFrame local fromFrameN = curFrame local keyID = channel:GetClosestKeyID(curFrame) local pID = keyID local nID = keyID + 1 if(channel:HasKey(curFrame) and not tweek) then pID = keyID - 1 nID = keyID + 1 end -- if self.getFromKey == self.NEXT_KEY then keyID = keyID + 1 end -- if self.getFromKey == self.ZEROFRAME_VALUES then keyID = 0 end -- if self.getFromKey == self.PREVIOUSMARKER_VALUES then -- keyID = channel:GetClosestKeyID(layer:TotalTimingOffset() + previousMarkerTime) -- end if keyID < channel:CountKeys() then fromFrameP = channel:GetKeyWhen(pID) -- * Fix if nID == channel:CountKeys() then return end fromFrameN = channel:GetKeyWhen(nID) --print(fromFrameP.." "..fromFrameN) local valP = derivedChannel:GetValue(fromFrameP) local valN = derivedChannel:GetValue(fromFrameN) if derivedChannel.AreDimensionsSplit and channel:AreDimensionsSplit() then for sss = 0, 2 do local subChannel = derivedChannel:DimensionChannel(sss) if subChannel then local valPs = subChannel:GetValue(fromFrameP) local valNs = subChannel:GetValue(fromFrameN) if(valPs~= nil and valNs ~= nil) then local vals = (valNs - valPs) * percentage/100 + valPs -- local oldval = derivedChannel:GetValue(curFrame) subChannel:SetValue(curFrame, vals) end -- local val = subChannel:GetValue(fromFrame) -- local oldval = subChannel:GetValue(curFrame) -- if self.ifEqual or not AE_Utilities:IsEqualValues(subChannel, val, oldval) then -- subChannel:SetValue(curFrame, val) -- end end end else --local val = derivedChannel:GetValue(fromFrame) if(valP~= nil and valN ~= nil and type(valP)~= "boolean" and type(valN)~= "boolean") then local val = (valN - valP) * percentage/100 + valP --local oldval = derivedChannel:GetValue(curFrame) derivedChannel:SetValue(curFrame, val) end end end end end end end end end function DV_TweenMachine:SetKey(moho) local layersCollection = self:GetSelectedLayers(moho) local previousMarkerTime = moho.frame if self.getFromKey == self.PREVIOUSMARKER_VALUES then markerChannel = moho.document.fTimelineMarkers previousMarkerTime = markerChannel:GetClosestKeyID(moho.frame - 1) previousMarkerTime = markerChannel:GetKeyWhen(previousMarkerTime) end for id, layer in pairs(layersCollection) do if (not self.selectedBonesOnly) or moho:LayerAsBone(layer) then local exclude_channels = self:CollectExcludeChannels(moho, layer) local curFrame = layer:TotalTimingOffset() + moho.frame if curFrame == 0 then return end for subId, id, channel, chInfo in AE_Utilities:IterateAllChannels(moho, layer) do if not(table.contains(exclude_channels, tostring(channel))) then if self:CheckChannelForAddKey(moho, channel, curFrame) and chInfo.channelID ~= CHANNEL_DOC_MARKERS and chInfo.channelID ~= CHANNEL_LAYER_MARKERS then local derivedChannel = AE_Utilities:GetDerivedChannel(moho, channel) local fromFrame = curFrame local keyID = channel:GetClosestKeyID(curFrame) --davoodice modify for accpet key if exist key in current frame if(channel:HasKey(curFrame)) then keyID = keyID - 1 end if (self.getFromKey == self.NEXT_KEY and channel:HasKey(curFrame)) then keyID = keyID + 2 elseif self.getFromKey == self.NEXT_KEY then keyID = keyID + 1 end if self.getFromKey == self.ZEROFRAME_VALUES then keyID = 0 end if self.getFromKey == self.PREVIOUSMARKER_VALUES then keyID = channel:GetClosestKeyID(layer:TotalTimingOffset() + previousMarkerTime) end --if(self.getFromKey == self.PREVIOUS_KEY ) then keyID = keyID - 1 end if keyID < channel:CountKeys() then if self.getFromKey ~= self.CURRENT_VALUES then fromFrame = channel:GetKeyWhen(keyID) end if derivedChannel.AreDimensionsSplit and channel:AreDimensionsSplit() then for sss = 0, 2 do local subChannel = derivedChannel:DimensionChannel(sss) if subChannel then local val = subChannel:GetValue(fromFrame) local oldval = subChannel:GetValue(curFrame) if self.ifEqual or not AE_Utilities:IsEqualValues(subChannel, val, oldval) then subChannel:SetValue(curFrame, val) end end end else local val = derivedChannel:GetValue(fromFrame) local oldval = derivedChannel:GetValue(curFrame) if self.ifEqual or not AE_Utilities:IsEqualValues(derivedChannel, val, oldval) then derivedChannel:SetValue(curFrame, val) end end end end end end end end end --------------------------------------------------------------------------------------------------------------------- -- ************************************************** -- Get all selected layers -- ************************************************** function DV_TweenMachine:GetSelectedLayers(moho) local layersCollection = AE_Utilities:MohoListToTable(moho.document, moho.document.CountSelectedLayers, moho.document.GetSelectedLayer) if not self.applyToChildLayers then return layersCollection end table.sort(layersCollection, function(a,b) return (moho.document:LayerAbsoluteID(a)<moho.document:LayerAbsoluteID(b)) end) local childLayersCollection = {} for i, layer in AE_Utilities:IterateAllLayers(moho, moho.document:LayerAbsoluteID(layersCollection[1])) do if not self.timelinevisibleOnly or layer:IsShownOnTimeline() then for j,parentLayer in pairs(layersCollection) do if AE_Utilities:IsAncestor(parentLayer, layer) then table.insert(childLayersCollection, layer) break end end end end if not self.applyToRefs then for i, layer in pairs(childLayersCollection) do if layer:IsReferencedLayer() then table.remove(childLayersCollection, i) end end end return childLayersCollection end -- ************************************************** -- Get a channel's frame value if it's cycled -- ************************************************** function DV_TweenMachine:GetCycledValue(moho, channel, frame) local keyID = self:IsCycled(moho,channel, frame) if keyID <= 0 then return channel:GetValue(frame) end local interp = MOHO.InterpSetting:new_local() channel:GetKeyInterpByID(keyID, interp) local keyTime = channel:GetKeyWhen(keyID) local absCycle = interp.val2 > 0 and interp.val2 or keyTime - interp.val1 local timeDistance = frame - keyTime local referenceTime = timeDistance % (keyTime - absCycle + 1) + absCycle - 1 local referenceValue = channel:GetValue(referenceTime) if not interp:IsAdditiveCycle() then return referenceValue end local offset = channel:GetValue(keyTime) - channel:GetValue(absCycle - 1) local numOffsets = math.floor((timeDistance-1)/(keyTime - absCycle + 1))+1 return (offset * numOffsets + referenceValue) end -- ************************************************** -- Check if a frame on a channel is cycled -- ************************************************** function DV_TweenMachine:IsCycled(moho,channel,frame) if channel:HasKey(frame) then return 0 end local keyID = channel:GetClosestKeyID(frame) if channel:GetKeyInterpModeByID(keyID) == MOHO.INTERP_CYCLE then return keyID end if channel:GetKeyInterpModeByID(keyID) == MOHO.INTERP_NOISY then return keyID end if channel:GetKeyInterpModeByID(keyID) == MOHO.INTERP_BOUNCE then return keyID end if channel:GetKeyInterpModeByID(keyID) == MOHO.INTERP_ELASTIC then return keyID end return 0 end -- ************************************************** -- Check if a table contains an element -- ************************************************** function table.contains(t, element) if not t then return false end for _, value in pairs(t) do if value == element then return true end end return false end -- ************************************************** -- Localization -- ************************************************** function DV_TweenMachine:Localize(text) local fileWord = MOHO.Localize("/Menus/File/File=File") local phrase = {} phrase["Name"] = "DV_Tween Machine" phrase["Description"] = "Tween Machine" phrase["UILabel"] = "DV Tween Machine" phrase["Settings"] = "Settings" phrase["SettingsTooltip"] = "Which layers and channels to include for all operations" phrase["ApplyToChildLayers"] = "Include Child layers" phrase["ApplyToRefs"] = "Include Referenced layers" phrase["PrecalcCycles"] = "Include Cycles" phrase["SelectedBonesOnly"] = "Apply to Selected bones only" phrase["IgnoreStringChannels"] = "Ignore string channels" phrase["IgnoreHiddenBones"] = "Ignore hidden bones" if fileWord == "Файл" then phrase["Name"] = "ИнÑтрументы ключей" phrase["Description"] = "ИнÑтрументы ключей" phrase["UILabel"] = "ИнÑтрументы ключей" phrase["Settings"] = "Settings" phrase["SettingsTooltip"] = "Which layers and channels to include for all operations" phrase["ApplyToChildLayers"] = "Дочерние Ñлои" phrase["ApplyToRefs"] = "РеференÑÑ‹" phrase["PrecalcCycles"] = "Циклы" phrase["IgnoreStringChannels"] = "Игнорировать Ñтрочные каналы" phrase["IgnoreHiddenBones"] = "Игнорировать ÑпрÑтанные коÑти" phrase["ChildLayersTooltip"] = "Обрабатывать вÑÑŽ иерархию дочерних Ñлоев каждого выбранного ÑлоÑ" end return phrase[text] or text; end
DV Tween Machine
Listed
Author: davoodice
View Script
Script type: Tool
Uploaded: Mar 13 2022, 01:21
help to create break down keyframes for bone or layer transform
for mor information go to this link
you need AE_utility to use this script.
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: 224

DV Tween Machine
Listed
Author: davoodice
View Script
Script type: Tool
Uploaded: Mar 13 2022, 01:21
help to create break down keyframes for bone or layer transform
for mor information go to this link
you need AE_utility to use this script.
you need AE_utility to use this script.
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: 224