-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "AE_ResetLayerTransform" -- ************************************************** -- General information about this script -- ************************************************** AE_ResetLayerTransform = {} function AE_ResetLayerTransform:Name() return "Reset Layer Transform" end function AE_ResetLayerTransform:Version() return "2.3" end function AE_ResetLayerTransform:UILabel() return "Reset Layer Transform" end function AE_ResetLayerTransform:Creator() return "Alexandra Evseeva" end function AE_ResetLayerTransform:Description() return "Set layer translation, scale and rotation Z to default values, saving vertices and child layers unmoved." end -- ************************************************** -- Recurring values -- ************************************************** -- AE_ResetLayerTransform.value1 = false -- ************************************************** -- Is Enabled -- ************************************************** function AE_ResetLayerTransform:IsEnabled(moho) return true end -- ************************************************** -- The guts of this script -- ************************************************** function AE_ResetLayerTransform:IsKeyframe(moho, frame, actionName) local skel = moho:Skeleton() for b = 0, skel:CountBones() - 1 do for i, j in pairs({'fAnimPos', 'fAnimAngle', 'fAnimScale'}) do local channel = skel:Bone(b)[j] if actionName then channel = channel:ActionByName(actionName) end if channel and channel:HasKey(frame) then return true end end end return false end function AE_ResetLayerTransform:NearestAngle(oldAngle, newAngle, toPrint) --if toPrint then print(oldAngle, " ", newAngle) end local dist = newAngle - oldAngle if math.abs(dist) < math.pi then return newAngle end --if toPrint then print(dist) end if math.abs(dist) >= (2 * math.pi) then dist = (dist % (2 * math.pi))*(dist/math.abs(dist)) end --if toPrint then print(dist) end if math.abs(dist) > math.pi then local absDist = math.abs(dist) - (math.pi * 2) dist = absDist * (dist/math.abs(dist)) end --if toPrint then print(dist) end return (oldAngle + dist) end function AE_ResetLayerTransform:ApplyBoneTransform(moho, skel, boneID, mainMatrix, oldMatrixes, frame, actionName) -- apply to called bone if not actionName then actionName = '' end local oldMatrix = oldMatrixes[boneID][actionName][frame] if not oldMatrix then return end local tempMatrix = LM.Matrix:new_local() tempMatrix:Set(mainMatrix) tempMatrix:Multiply(oldMatrix) local newMatrix = LM.Matrix:new_local() newMatrix:Set(tempMatrix) local parentID = skel:Bone(boneID).fAnimParent:GetValue(0) if parentID > -1 then local parentMatrix = AE_Utilities:GetGlobalBoneMatrix(moho, skel, skel:Bone(parentID), frame, actionName) tempMatrix:Set(parentMatrix) tempMatrix:Invert() tempMatrix:Multiply(newMatrix) newMatrix:Set(tempMatrix) end local p, r, s = AE_Utilities:Matrix2transform(newMatrix, false, true) -- apply p, r, s to the bone itself if frame == 0 then -- set p, r and length skel:Bone(boneID).fAnimPos:SetValue(0, p) local oldAngle = skel:Bone(boneID).fAnimAngle:GetValue(0) -- get nearest angle r = self:NearestAngle(oldAngle, r) skel:Bone(boneID).fAnimAngle:SetValue(0, r) skel:Bone(boneID).fLength = skel:Bone(boneID).fLength * s.x else -- set p, r, s if channel has corresponding key in called frame local channel = skel:Bone(boneID).fAnimPos if actionName ~= '' then channel = channel:ActionByName(actionName) end if channel and channel:HasKey(frame) then channel = moho:ChannelAsAnimVec2(channel) channel:SetValue(frame, p) end local channel = skel:Bone(boneID).fAnimAngle if actionName ~= '' then channel = channel:ActionByName(actionName) end if channel and channel:HasKey(frame) then channel = moho:ChannelAsAnimVal(channel) local oldAngle = channel:GetValue(frame) r = self:NearestAngle(oldAngle, r) channel:SetValue(frame, r) end -- do nothing with scale end skel:UpdateBoneMatrix(boneID) -- and then apply recursive method to bones children for i = 0, skel:CountBones() - 1 do if skel:Bone(i).fAnimParent:GetValue(0) == boneID then self:ApplyBoneTransform(moho, skel, i, mainMatrix, oldMatrixes, frame, actionName) end end end function AE_ResetLayerTransform:Run(moho) moho.document:PrepUndo(moho.layer) moho.document:SetDirty() self:Eval(moho, moho.layer) end function AE_ResetLayerTransform:Eval(moho, mainLayer) local printOutput = false --output calculated values for debug local mainMatrix = LM.Matrix:new_local() mainLayer:GetLayerTransform(moho.layerFrame, mainMatrix, moho.document) if not mainLayer:Parent() then local cameraMatrix = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.frame, cameraMatrix) cameraMatrix:Invert() cameraMatrix:Multiply(mainMatrix) mainMatrix:Set(cameraMatrix) if printOutput then AE_Utilities:Matrix2transform(cameraMatrix,printOutput) end end if mainLayer:LayerType() == MOHO.LT_VECTOR then local mesh = moho:LayerAsVector(mainLayer):Mesh() for p = 0, mesh:CountPoints()-1 do local point = mesh:Point(p) local currentPos = point.fAnimPos:GetValue(moho.layerFrame) mainMatrix:Transform(currentPos) point.fAnimPos:SetValue(moho.layerFrame, currentPos) if mainLayer.fFlipH:GetValue(moho.layerFrame) or mainLayer.fFlipV:GetValue(moho.layerFrame) then for c = 0, point:CountCurves() - 1 do local curve, pointID = point:Curve(c) local inOffset = curve:GetOffset(pointID, moho.layerFrame, true) local outOffset = curve:GetOffset(pointID, moho.layerFrame, false) curve:SetOffset(pointID, -inOffset, moho.layerFrame, true) curve:SetOffset(pointID, -outOffset, moho.layerFrame, false) end end if moho.layerFrame == 0 then for k = 1, point.fAnimPos:CountKeys()-1 do currentPos = point.fAnimPos:GetValueByID(k) mainMatrix:Transform(currentPos) point.fAnimPos:SetValueByID(k, currentPos) local layerFrame = point.fAnimPos:GetKeyWhen(k) if mainLayer.fFlipH:GetValue(0) or mainLayer.fFlipV:GetValue(0) then for c = 0, point:CountCurves() - 1 do local curve, pointID = point:Curve(c) local inOffset = curve:GetOffset(pointID, layerFrame, true) local outOffset = curve:GetOffset(pointID, layerFrame, false) curve:SetOffset(pointID, -inOffset, layerFrame, true) curve:SetOffset(pointID, -outOffset, layerFrame, false) end end end for a = 0, point.fAnimPos:CountActions() - 1 do local track = moho:ChannelAsAnimVec2(point.fAnimPos:Action(a)) for k = 1, track:CountKeys()-1 do currentPos = track:GetValueByID(k) mainMatrix:Transform(currentPos) track:SetValueByID(k, currentPos) end --if layer was flipped need to invert offsets for all the actions too. But I am too lazy to do it. end end end elseif mainLayer:IsGroupType() then local group = moho:LayerAsGroup(mainLayer) for ch = 0, group:CountLayers()-1 do local childLayer = group:Layer(ch) local childMatrix = LM.Matrix:new_local() childLayer:GetLayerTransform(moho.layerFrame, childMatrix, moho.document) local resultMatrix = LM.Matrix:new_local() resultMatrix:Set(mainMatrix) resultMatrix:Multiply(childMatrix) local translation, rotationZ, scale, flip = AE_Utilities:Matrix2transform(resultMatrix, printOutput) childLayer.fTranslation:SetValue(moho.layerFrame, translation) childLayer.fRotationZ:SetValue(moho.layerFrame, rotationZ) childLayer.fScale:SetValue(moho.layerFrame, scale) childLayer.fFlipH:SetValue(moho.layerFrame, flip) end if mainLayer:IsBoneType() and moho:Skeleton():CountBones() > 0 then local returnFrame = moho.frame local skel = moho:Skeleton() local oldMatrixes = {} -- here goes collecting of bone matrixes: from fMovedMatrix with mainline frames -- and from AE_Utilities:GetGlobalBoneMatrix with action timelines -- AE_Utilities:GetGlobalBoneMatrix does not work fine for now and may have to be replaced -- with AE_Utilities:GetGlobalBonePRS. But its return have to be converted into matrix anyway -- course all the matrixes are multiplied with mainMatrix, produced with layer transform -- so it would be better to update AE_Utilities:GetGlobalBoneMatrix -- making it work with AE_Utilities:GetGlobalBonePRS or fixing it any other way to produce correct results local rootBones = {} for i = 0, skel:CountBones() -1 do if skel:Bone(i).fAnimParent:GetValue(0) == -1 then table.insert(rootBones, skel:Bone(i)) end oldMatrixes[i] = {} oldMatrixes[i][''] = {} for a = 0, mainLayer:CountActions()-1 do local actionName = mainLayer:ActionName(a) oldMatrixes[i][actionName] = {} end end for f = 0, moho.document:AnimDuration() do if f== 0 then -- save rest matrix into table for b = 0, skel:CountBones()-1 do local tempMatrix = LM.Matrix:new_local() tempMatrix:Set(skel:Bone(b).fRestMatrix) oldMatrixes[b][''][0] = tempMatrix end elseif self:IsKeyframe(moho, f) then -- save moved matrix into table moho:SetCurFrame(f) for b = 0, skel:CountBones()-1 do skel:UpdateBoneMatrix(b) local tempMatrix = LM.Matrix:new_local() tempMatrix:Set(skel:Bone(b).fMovedMatrix) oldMatrixes[b][''][f] = tempMatrix end end end for a = 0, mainLayer:CountActions() - 1 do local actionName = mainLayer:ActionName(a) for f = 1, mainLayer:ActionDuration(actionName) do if self:IsKeyframe(moho, f, actionName) then -- save moved matrix into table for b = 0, skel:CountBones()-1 do --skel:UpdateBoneMatrix(b) local tempMatrix = LM.Matrix:new_local() --tempMatrix:Set(skel:Bone(b).fMovedMatrix) tempMatrix:Set(AE_Utilities:GetGlobalBoneMatrix(moho, skel, skel:Bone(b), f, actionName)) oldMatrixes[b][actionName][f] = tempMatrix end end end end -- iterate once again from root bones to their children for f = 0, moho.document:AnimDuration() do if f== 0 then for i, bone in pairs(rootBones) do -- call recursive bone method self:ApplyBoneTransform(moho, skel, skel:BoneID(bone), mainMatrix, oldMatrixes, f) end else moho:SetCurFrame(f) for i, bone in pairs(rootBones) do -- call recursive bone method self:ApplyBoneTransform(moho, skel, skel:BoneID(bone), mainMatrix, oldMatrixes, f) end end end for a = 0, mainLayer:CountActions() - 1 do local actionName = mainLayer:ActionName(a) mainLayer:ActivateAction(actionName) for f = 1, mainLayer:ActionDuration(actionName) do --moho:SetCurFrame(f) for i, bone in pairs(rootBones) do -- call recursive bone method self:ApplyBoneTransform(moho, skel, skel:BoneID(bone), mainMatrix, oldMatrixes, f, actionName) end end end mainLayer:ActivateAction(nil) moho:SetCurFrame(returnFrame) end else return end local pos = LM.Vector3:new_local() mainLayer.fTranslation:SetValue(moho.layerFrame, pos) mainLayer.fRotationZ:SetValue(moho.layerFrame, 0) local scale = LM.Vector3:new_local() scale:Set(1,1,1) mainLayer.fScale:SetValue(moho.layerFrame, scale) mainLayer.fFlipH:SetValue(moho.layerFrame, false) mainLayer.fFlipV:SetValue(moho.layerFrame, false) end
Reset layer transform
Listed
Author: A.Evseeva
View Script
Script type: Button/Menu
Uploaded: Jan 18 2021, 01:15
Last modified: Feb 01 2022, 04:48
Resets transform moving it to direct child layers
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: 1265
Reset layer transform
Listed
Author: A.Evseeva
View Script
Script type: Button/Menu
Uploaded: Jan 18 2021, 01:15
Last modified: Feb 01 2022, 04:48
Resets transform moving it to direct child layers
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: 1265