AE_Utilities = {} AE_Utilities.constructionTime = true function AE_Utilities:Version() return "1.43" end function AE_Utilities:GetBezierValue(curve, pointNum, frame, prePoint, getModifiedPoints) local curvature = curve:GetCurvature(pointNum, frame) local weight = curve:GetWeight(pointNum, frame, prePoint) local offset = curve:GetOffset(pointNum, frame, prePoint) local pointToRange = function(p) if curve.fClosed then if p < 0 then p = curve:CountPoints()-1 end if p >= curve:CountPoints() then p = 0 end else if p < 0 then p = 0 end if p >= curve:CountPoints() then p = curve:CountPoints()-1 end end return p end local postPointNum = pointToRange(pointNum + 1) local prePointNum = pointToRange(pointNum - 1) local secondPointNum = postPointNum if prePoint then secondPointNum = prePointNum end if secondPointNum == pointNum then if getModifiedPoints then return curve:Point(pointNum).fPos else return curve:Point(pointNum).fAnimPos:GetValue(frame) end end local N = curve:Point(postPointNum).fAnimPos:GetValue(frame) - curve:Point(prePointNum).fAnimPos:GetValue(frame) if getModifiedPoints then N = curve:Point(postPointNum).fPos - curve:Point(prePointNum).fPos end N:NormMe() if prePoint then N = N*-1 end local L = (curve:Point(secondPointNum).fAnimPos:GetValue(frame) - curve:Point(pointNum).fAnimPos:GetValue(frame)):Mag() if getModifiedPoints then L = (curve:Point(secondPointNum).fPos - curve:Point(pointNum).fPos):Mag() end L = L * curvature * weight local vec = N * L vec:Rotate(offset) if getModifiedPoints then return curve:Point(pointNum).fPos + vec else return curve:Point(pointNum).fAnimPos:GetValue(frame) + vec end end function AE_Utilities:GetAngleBetween(vec1, vec2) v1 = vec1:Norm() v2 = vec2:Norm() local angle = v1:Dot(v2) if (angle > 1.0) then angle = 0 elseif (angle < -1.0) then angle = math.pi else angle = math.acos(angle) end local norm = v1:Cross(v2) if (norm.z < 0.0) then angle = -angle end return angle end function AE_Utilities:SumActionInfluences(moho, frame, derivedChannel, layer) local sum = 0 if derivedChannel:ChannelType() == MOHO.CHANNEL_VEC2 then sum = LM.Vector2:new_local() end local defaultValue = derivedChannel:GetValue(0) local parentSceleton = self:FindControllingSkeleton(moho, layer) if not parentSceleton then return 0 end for actID = 0, derivedChannel:CountActions()-1 do local actName = derivedChannel:ActionName(actID) local actChannel = self:GetDerivedChannel(moho, derivedChannel:Action(actID)) local boneName = actName if string.sub(boneName, string.len(boneName)-1) == " 2" then boneName = string.sub(boneName, 1, string.len(boneName)-2) end local smartBone = parentSceleton:BoneByName(boneName) if smartBone and actName ~= layer:CurrentAction() then local boneTrack = smartBone.fAnimAngle:ActionByName(actName) if boneTrack and boneTrack ~= actChannel then local curSmartboneValue = smartBone.fAnimAngle:GetValue(frame) -- bad for nested smartbones curSmartboneValue = smartBone.fAngle -- better for nested smartbones local smartBoneFrame, smartBoneSubFrame = self:FindSmartBoneFrame(curSmartboneValue, moho:ChannelAsAnimVal(boneTrack)) if(smartBoneFrame>0 or smartBoneSubFrame ~= smartBoneFrame) then local nextVal = actChannel:GetValue(smartBoneFrame) - defaultValue if smartBoneSubFrame == 0 and smartBoneSubFrame ~= smartBoneFrame then nextVal = (actChannel:GetValue(1) - defaultValue)*smartBoneSubFrame end sum = sum + nextVal end end end end return sum end function AE_Utilities:FindSmartBoneFrame(angle, smartBoneTrack, ignoreZeroFrame) --ignoreZeroFrame and startFrame added for KuzmaProduction; Remove if work incorrect local foundFrame = -1 local foundSubFrame = -1 local defAngle = smartBoneTrack:GetValue(0) if not ignoreZeroFrame and defAngle == angle then return 0,0 end local startFrame = 1 if smartBoneTrack:Duration()>1 then startFrame = 2 end for f=startFrame, smartBoneTrack:Duration() do local curVal = smartBoneTrack:GetValue(f) local preVal = smartBoneTrack:GetValue(f-1) if ((curVal-angle)*(preVal-angle)) <= 0 then foundFrame = f-1 foundSubFrame = f-1+(angle-preVal)/(curVal-preVal) if foundSubFrame == f then foundFrame = f end --print("between ", preVal*180/math.pi, " and ", curVal*180/math.pi) end if f==smartBoneTrack:Duration() and foundFrame == -1 and math.abs(curVal-angle)<math.abs(preVal-angle) then foundFrame = f foundSubFrame = f end end if smartBoneTrack:Duration() == 1 then return foundFrame, foundSubFrame end return foundFrame, foundSubFrame end function AE_Utilities:FindControllingSkeleton(moho, layer) local boneLayer = nil if layer:LayerType() == MOHO.LT_BONE then boneLayer = moho:LayerAsBone(layer) return boneLayer:Skeleton(), boneLayer end local parent = layer while parent:Parent() do parent = parent:Parent() if parent:LayerType() == MOHO.LT_BONE then local boneLayer = moho:LayerAsBone(parent) if boneLayer and boneLayer:Skeleton():CountBones()>0 then return boneLayer:Skeleton(), boneLayer end end end if boneLayer then return boneLayer:Skeleton(), boneLayer end return nil end ----------------------------------------------------------------------------------- -------------------------- Added in version 1.1 ----------------------------------- ----------------------------------------------------------------------------------- function AE_Utilities:GetDerivedChannel(moho, chan, onlyMath) local chanType = chan:ChannelType() if chanType == MOHO.CHANNEL_VAL then return moho:ChannelAsAnimVal(chan), MOHO.CHANNEL_VAL elseif chanType == MOHO.CHANNEL_VEC2 then return moho:ChannelAsAnimVec2(chan), MOHO.CHANNEL_VEC2 elseif chanType == MOHO.CHANNEL_VEC3 then return moho:ChannelAsAnimVec3(chan), MOHO.CHANNEL_VEC3 elseif onlyMath then return nil elseif chanType == MOHO.CHANNEL_COLOR then return moho:ChannelAsAnimColor(chan), MOHO.CHANNEL_COLOR elseif chanType == MOHO.CHANNEL_BOOL then return moho:ChannelAsAnimBool(chan), MOHO.CHANNEL_BOOL elseif chanType == MOHO.CHANNEL_STRING then return moho:ChannelAsAnimString(chan), MOHO.CHANNEL_STRING end return nil end function AE_Utilities:IsAncestor(parentLayer, childLayer) while childLayer do if childLayer == parentLayer then return true end childLayer = childLayer:Parent() end return false end function AE_Utilities:IterateLayerSubChannels(moho, layer) local GetCombinedChannel = function(layer) local maxChannel = layer:CountChannels()-1 local chInfo = MOHO.MohoLayerChannel:new_local() for i=0, maxChannel do layer:GetChannelInfo(i, chInfo) if chInfo.channelID == CHANNEL_LAYER_ALL then return chInfo.subChannelCount, i end end return nil end local subChannelCount, combChannelNo = GetCombinedChannel(layer) if not subChannelCount then return end local iterateFn = function(condition, counter) counter = counter + 1 if counter < subChannelCount then local channel = layer:Channel(combChannelNo, counter, moho.document) local chInfo = MOHO.MohoLayerChannel:new_local() layer:GetChannelInfo(counter, chInfo) return counter, channel, chInfo end end return iterateFn, subChannelCount, -1 end function AE_Utilities:IterateAllLayers(moho, from, to) local iterateLayersFn = function(condition, counter) counter = counter + 1 if not condition or counter <= condition then local layer = moho.document:LayerByAbsoluteID(counter) if layer then return counter, layer end end end return iterateLayersFn, to, (from and from-1 or -1) end function AE_Utilities:IterateMohoList(obj, countFn, getFn) local iteratorFn = function(condition, counter) counter = counter + 1 if counter < countFn(obj) then local entity = getFn(obj,counter) return counter, entity end end return iteratorFn, nil, -1 end function AE_Utilities:MohoListToTable(obj, countFn, getFn) local collection = {} for i, entity in self:IterateMohoList(obj, countFn, getFn) do table.insert(collection, entity) end return collection end function AE_Utilities:IterateAllChannels(moho, layer) local chInfo = MOHO.MohoLayerChannel:new_local() local channelCounter = 0 local maxChannel = layer:CountChannels()-6 --exсlude 5 last channels: all and camera tracks layer:GetChannelInfo(0, chInfo) local iterateFn = function(condition, subCounter) subCounter = subCounter + 1 if subCounter >= chInfo.subChannelCount then repeat channelCounter = channelCounter + 1 if channelCounter <= maxChannel then layer:GetChannelInfo(channelCounter, chInfo) subCounter = 0 end until channelCounter > maxChannel or ( chInfo.subChannelCount > 0 and not chInfo.selectionBased) end if channelCounter <= maxChannel then local channel = layer:Channel(channelCounter, subCounter, moho.document) return subCounter, channelCounter, channel, chInfo end end return iterateFn, nil, -1 end ----------------------------------------------------------------------------------- -------------------------- Added in version 1.11 ---------------------------------- ----------------------------------------------------------------------------------- function AE_Utilities:IsEqualValues(channel, val1, val2, accuracy) accuracy = accuracy or 0.0000001 local chanType = channel:ChannelType() if chanType == MOHO.CHANNEL_VAL then return (math.abs(val1 - val2) < accuracy) elseif chanType == MOHO.CHANNEL_VEC2 then return (((val1-val2):Mag()) < accuracy) elseif chanType == MOHO.CHANNEL_VEC3 then return (((val1-val2):Mag()) < accuracy) elseif chanType == MOHO.CHANNEL_COLOR then return val1.r == val2.r and val1.g == val2.g and val1.b == val2.b and val1.a == val2.a elseif chanType == MOHO.CHANNEL_BOOL then return (val1 == val2) elseif chanType == MOHO.CHANNEL_STRING then return (val1 == val2) end return false end ----------------------------------------------------------------------------------- -------------------------- Added in version 1.15 ---------------------------------- ----------------------------------------------------------------------------------- function AE_Utilities:Matrix2transform(theMatrix, printOutput, returnOutput) local translation = LM.Vector3:new_local() theMatrix:Transform(translation) local v3rz = LM.Vector3:new_local() v3rz:Set(1,0,0) theMatrix:Transform(v3rz) v3rz = v3rz - translation local rotationZ = math.atan2(v3rz.y, v3rz.x) local flip = false local v3rz2 = LM.Vector3:new_local() v3rz2:Set(0,1,0) theMatrix:Transform(v3rz2) v3rz2 = v3rz2 - translation local alterZrotation = math.atan2(-v3rz2.x, v3rz2.y) if math.abs(alterZrotation - rotationZ) > 0.01 then flip = true if math.abs(alterZrotation) < math.abs(rotationZ) then rotationZ = alterZrotation end end local v3sx = LM.Vector3:new_local() v3sx:Set(1,0,0) theMatrix:Transform(v3sx) local v3sy = LM.Vector3:new_local() v3sy:Set(0,1,0) theMatrix:Transform(v3sy) local v3sz = LM.Vector3:new_local() v3sz:Set(0,0,1) theMatrix:Transform(v3sz) local scaleX = (v3sx - translation):Mag() local scaleY = (v3sy - translation):Mag() local scaleZ = (v3sz - translation):Mag() local scale = LM.Vector3:new_local() scale:Set(scaleX, scaleY, scaleZ) local pString, rString, sString = nil, nil, nil if returnOutput or printOutput then pString = "("..translation.x..", "..translation.y..", "..translation.z..")\n" rString = "degr: "..rotationZ*180/math.pi.."\n" sString = "("..scale.x..", "..scale.y..", "..scale.z..")\n" fString = tostring(flip) end if printOutput then print(pString) print(rString) print(sString) print(fString) end return translation, rotationZ, scale, flip, pString, rString, sString, fString end function AE_Utilities:StringifyValue(value, chanType) if chanType == MOHO.CHANNEL_VAL then return tostring(value) elseif chanType == MOHO.CHANNEL_VEC2 then return tostring(value.x).." "..tostring(value.y) elseif chanType == MOHO.CHANNEL_VEC3 then return tostring(value.x).." "..tostring(value.y).." "..tostring(value.z) elseif chanType == MOHO.CHANNEL_COLOR then return tostring(value.r).." "..tostring(value.g).." "..tostring(value.b).." "..tostring(value.a) elseif chanType == MOHO.CHANNEL_BOOL then return tostring(value) elseif chanType == MOHO.CHANNEL_STRING then return value end return "unknown type" end ----------------------------------------------------------------------------------- -------------------------- Added in version 1.18 ---------------------------------- ----------------------------------------------------------------------------------- function AE_Utilities:GetChannelValue(moho, channel, frame, actionName, layer) local value = channel:GetValue(frame) if actionName and #actionName > 0 then if channel:ActionByName(actionName) then local derivedChannel = self:GetDerivedChannel(moho, channel:ActionByName(actionName)) value = derivedChannel:GetValue(frame) else value = channel:GetValue(0) end elseif layer then local derivedChannel = self:GetDerivedChannel(moho, channel) local value = derivedChannel:GetValue(frame) local add = self:SumActionInfluences(moho, frame, derivedChannel, layer) return (value + add) end return value end function AE_Utilities:Transform2Matrix(bone, pos, angle, scale, flipEnd, flipSide) if not Sy then Sy = Sx end local matrix = LM.Matrix:new_local() matrix:Identity() matrix:Translate(pos.x, pos.y, 0) matrix:Rotate(LM.Z_AXIS, angle) local x = scale if bone.fLength == 0 then y = x else y = 1 end if flipEnd then x = -1 * x end if flipSide then y = -1 * y end matrix:Scale(x,y,1) return matrix end function AE_Utilities:GetBoneMatrix(moho, bone, frame, actionName, skel) if not skel then skel = moho:Skeleton() end local matrix = LM.Matrix:new_local() matrix:Identity() local pos = self:GetChannelValue(moho, bone.fAnimPos, frame, actionName) --TODO: check bone.fPosControlParent local angle = self:GetChannelValue(moho, bone.fAnimAngle, frame, actionName) if bone.fAngleControlParent > -1 and skel:Bone(bone.fAngleControlParent) then local controlAngleDif = self:GetChannelValue(moho, skel:Bone(bone.fAngleControlParent).fAnimAngle, frame, actionName) controlAngleDif = controlAngleDif - self:GetChannelValue(moho, skel:Bone(bone.fAngleControlParent).fAnimAngle, 0) angle = angle + controlAngleDif * bone.fAngleControlScale end if bone.fFixedAngle then parBoneAngle = 0 local parBone = skel:Bone(bone.fParent) while parBone do parBoneAngle = parBoneAngle + self:GetChannelValue(moho, parBone.fAnimAngle, frame, actionName) if parBone.fFixedAngle then break end parBone = skel:Bone(parBone.fParent) end angle = angle - parBoneAngle end local scale = self:GetChannelValue(moho, bone.fAnimScale, frame, actionName) --TODO: check bone.fScaleControlParent local flipEnd = self:GetChannelValue(moho, bone.fFlipH, frame, actionName) local flipSide = self:GetChannelValue(moho, bone.fFlipV, frame, actionName) matrix:Translate(pos.x, pos.y, 0) matrix:Rotate(LM.Z_AXIS, angle) local x = scale if bone.fLength == 0 then y = x else y = 1 end if flipEnd then x = -1 * x end if flipSide then y = -1 * y end matrix:Scale(x,y,1) return matrix end function AE_Utilities:GetGlobalBonePos(moho, skel, bone, frame, actionName, layer) --[[ local vector = LM.Vector2:new_local() local boneMatrix = self:GetGlobalBoneMatrix(moho, skel, bone, frame, actionName) boneMatrix:Transform(vector) --]] vector, _, _, _, _ = self:GetGlobalBonePRS(moho, skel, bone, frame, actionName, layer) return vector end function AE_Utilities:GetGlobalBoneAngle(moho, skel, bone, frame, actionName, layer) _, angle, _, _, _ = self:GetGlobalBonePRS(moho, skel, bone, frame, actionName, layer) return angle end function AE_Utilities:GetGlobalBonePRS(moho, skel, bone, frame, actionName, layer) local pos = bone.fAnimPos.value local angle = bone.fAnimAngle.value local scale = bone.fAnimScale.value local flipEnd = bone.fFlipH.value local flipSide = bone.fFlipV.value if frame ~= moho.frame or (actionName and actionName ~= '') then pos = self:GetChannelValue(moho, bone.fAnimPos, frame, actionName, layer) angle = self:GetChannelValue(moho, bone.fAnimAngle, frame, actionName, layer) scale = self:GetChannelValue(moho, bone.fAnimScale, frame, actionName, layer) flipEnd = self:GetChannelValue(moho, bone.fFlipH, frame, actionName) flipSide = self:GetChannelValue(moho, bone.fFlipV, frame, actionName) end local parentBone = skel:Bone(bone.fParent) if not parentBone then return pos, angle, scale, flipEnd, flipSide end local parPos, parAngle, parScale, parFlipEnd, parFlipSide = self:GetGlobalBonePRS(moho, skel, parentBone, frame, actionName, layer) if bone.fFixedAngle then local restP, restR = self:Matrix2transform(parentBone.fRestMatrix) local parAngleDelta = parAngle - restR angle = angle - parAngleDelta end local resultAngle = parAngle + angle if parFlipSide and not parFlipEnd then resultAngle = parAngle - angle elseif not parFlipSide and parFlipEnd then resultAngle = parAngle + math.pi - angle elseif parFlipSide and parFlipEnd then resultAngle = parAngle + math.pi + angle end local x = parScale local y = 1 if parentBone.fLength == 0 then y = parScale end local resultPos = LM.Vector2:new_local() resultPos:Set(pos.x * x, pos.y * y) local rotateMatrix = LM.Matrix:new_local() rotateMatrix:Identity() rotateMatrix:Rotate(LM.Z_AXIS, parAngle) rotateMatrix:Transform(resultPos) resultPos = resultPos + parPos return resultPos, resultAngle, scale, flipEnd, flipSide end function AE_Utilities:GetGlobalBoneMatrix(moho, skel, bone, frame, actionName) local pos, angle, scale, filpEnd, flipSide = self:GetGlobalBonePRS(moho, skel, bone, frame, actionName) return self:Transform2Matrix(bone, pos, angle, scale, filpEnd, flipSide) end function AE_Utilities:GetLayerByUUID(moho, uuid) for i, layer in self:IterateAllLayers(moho) do if layer:UUID() == uuid then return layer end end return nil end -- added at 1.19 function AE_Utilities:GetGlobalLayerMatrix(moho, layer, frame) -- actions not processed yet local prevMatrix = LM.Matrix:new_local() prevMatrix:Identity() local nextLayer = layer repeat local prevLayer = nextLayer local matrix = LM.Matrix:new_local() nextLayer:GetLayerTransform(frame, matrix, moho.document) matrix:Multiply(prevMatrix) prevMatrix:Set(matrix) if nextLayer:Parent() then nextLayer = nextLayer:Parent() end until nextLayer == prevLayer local cameraMatrix = LM.Matrix:new_local() moho.document:GetCameraMatrix(frame, cameraMatrix) cameraMatrix:Invert() cameraMatrix:Multiply(prevMatrix) return cameraMatrix end function AE_Utilities:GetSecondLayer(moho) for i, layer in AE_Utilities:IterateAllLayers(moho) do if layer:SecondarySelection() and layer ~= moho.layer then return layer end end return nil end function AE_Utilities:GetSecondLayers(moho) local secondLayers = {} for i, layer in AE_Utilities:IterateAllLayers(moho) do if layer:SecondarySelection() and layer ~= moho.layer then table.insert(secondLayers, layer) end end return secondLayers end function AE_Utilities:GetShapeOrderChannel(moho, layer) local maxChannel = layer:CountChannels()-1 local chInfo = MOHO.MohoLayerChannel:new_local() local orderChannel = nil for i=0, maxChannel do layer:GetChannelInfo(i, chInfo) if chInfo.channelID == CHANNEL_SHAPE_ORDER then return moho:ChannelAsAnimString(layer:Channel(i, 0, moho.document)) end end end function AE_Utilities:GetLayerRelativePath(moho, fromLayer, toLayer) if fromLayer == toLayer then return fromLayer:Name() end local path = "" local commonParent = fromLayer while commonParent and not self:IsAncestor(commonParent, toLayer) do commonParent = commonParent:Parent() path = path .. "../" end local secondPath = toLayer:Name() local nextParent = toLayer:Parent() while nextParent and commonParent ~= nextParent do secondPath = nextParent:Name() .. "/" .. secondPath nextParent = nextParent:Parent() end return (path .. secondPath) end function AE_Utilities:GetLayerFromRelativePath(moho, fromLayer, path) local foundLayer = fromLayer local restPath = path while string.sub(restPath, 1, 3) == "../" do if not foundLayer then return nil end foundLayer = foundLayer:Parent() restPath = string.sub(restPath, 4) end local nextSlash = string.find(restPath, "/") local nextName = string.sub(restPath, 1, (nextSlash and nextSlash - 1 or -1)) if not foundLayer then foundLayer = moho.document:LayerByName(nextName) else foundLayer = moho:LayerAsGroup(foundLayer) if (foundLayer) then foundLayer = foundLayer:LayerByName(nextName) end end if not foundLayer then return nil end restPath = string.sub(restPath, #nextName + 2) while #restPath > 0 do nextSlash = string.find(restPath, "/") nextName = string.sub(restPath, 1, (nextSlash and nextSlash - 1 or -1)) foundLayer = moho:LayerAsGroup(foundLayer) if (foundLayer) then foundLayer = foundLayer:LayerByName(nextName) end if not foundLayer then return nil end restPath = string.sub(restPath, #nextName + 2) end return foundLayer end function AE_Utilities:GetOffsetChannel(moho, layer, curve, curvePoint, prePoint) local mesh = moho:LayerAsVector(layer) if not mesh then return nil end mesh = mesh:Mesh() local ptID = mesh:PointID(curve:Point(curvePoint)) local crvID = mesh:CurveID(curve) local channelOffset = 3 if not prePoint then channelOffset = 4 end local subNo = 0 for p = 0, (ptID - 1) do subNo = subNo + mesh:Point(p):CountCurves()*5 end for c = 0, mesh:Point(ptID):CountCurves() - 1 do local nextCurve = mesh:Point(ptID):Curve(c,-1) if nextCurve == curve then break else subNo = subNo + 5 end end subNo = subNo + channelOffset for subID, ID, channel, chInfo in self:IterateAllChannels(moho, layer) do if subID == subNo and chInfo.channelID == CHANNEL_CURVE then return moho:ChannelAsAnimVal(channel), subID, ID, chInfo end end end function AE_Utilities:GetWeightChannel(moho, layer, curve, curvePoint, prePoint) local mesh = moho:LayerAsVector(layer) if not mesh then return nil end mesh = mesh:Mesh() local ptID = mesh:PointID(curve:Point(curvePoint)) local crvID = mesh:CurveID(curve) local channelWeight = 1 if not prePoint then channelWeight = 2 end local subNo = 0 for p = 0, (ptID - 1) do subNo = subNo + mesh:Point(p):CountCurves()*5 end for c = 0, mesh:Point(ptID):CountCurves() - 1 do local nextCurve = mesh:Point(ptID):Curve(c,-1) if nextCurve == curve then break else subNo = subNo + 5 end end subNo = subNo + channelWeight for subID, ID, channel, chInfo in self:IterateAllChannels(moho, layer) do if subID == subNo and chInfo.channelID == CHANNEL_CURVE then return moho:ChannelAsAnimVal(channel), subID, ID, chInfo end end end function AE_Utilities:GetCurvatureChannel(moho, layer, curve, curvePoint) local mesh = moho:LayerAsVector(layer) if not mesh then return nil end mesh = mesh:Mesh() local ptID = mesh:PointID(curve:Point(curvePoint)) local crvID = mesh:CurveID(curve) local subNo = 0 for p = 0, (ptID - 1) do subNo = subNo + mesh:Point(p):CountCurves()*5 end for c = 0, mesh:Point(ptID):CountCurves() - 1 do local nextCurve = mesh:Point(ptID):Curve(c,-1) if nextCurve == curve then break else subNo = subNo + 5 end end for subID, ID, channel, chInfo in self:IterateAllChannels(moho, layer) do if subID == subNo and chInfo.channelID == CHANNEL_CURVE then return moho:ChannelAsAnimVal(channel), subID, ID, chInfo end end end function AE_Utilities:GetPointBoneTransformedPos(moho, layer, point, layerFrame) local layerTransform = LM.Matrix:new_local() local layerTransform2 = LM.Matrix:new_local() local layerInvertTransform = LM.Matrix:new_local() layer:GetLayerTransform(moho.frame, layerTransform, moho.document) local nextLayer = layer while nextLayer:Parent() and nextLayer:Parent() ~= layer:ControllingBoneLayer() do nextLayer = nextLayer:Parent() nextLayer:GetLayerTransform(layerFrame, layerTransform2, moho.document) layerTransform2:Multiply(layerTransform) layerTransform:Set(layerTransform2) end layerInvertTransform:Set(layerTransform) layerInvertTransform:Invert() local localChannelPos = LM.Vector2:new_local() localChannelPos:Set(point.fAnimPos:GetValue(layerFrame)) layerTransform:Transform(localChannelPos) local theBone = layer:ControllingSkeleton():Bone(point.fParent) local restMatrix = LM.Matrix:new_local() --restMatrix:Set(theBone.fRestMatrix) restMatrix = AE_Utilities:GetGlobalBoneMatrix(moho, layer:ControllingSkeleton(), theBone, 0, moho.document:CurrentDocAction()) movedMatrix = AE_Utilities:GetGlobalBoneMatrix(moho, layer:ControllingSkeleton(), theBone, layerFrame, moho.document:CurrentDocAction()) restMatrix:Invert() restMatrix:Transform(localChannelPos) movedMatrix:Transform(localChannelPos) layerInvertTransform:Transform(localChannelPos) return localChannelPos end function AE_Utilities:CropAngle(angle) if math.abs(angle) < math.pi then return angle end local new_angle = (math.abs(angle) % (2*math.pi)) * angle/math.abs(angle) if math.abs(new_angle) > math.pi then local pi = 2 * math.pi * new_angle/math.abs(new_angle) new_angle = new_angle - pi end return new_angle end function AE_Utilities:Log(...) local file = io.open(self.filepath, "a+") io.output(file) local arg = {...} local s = '' for i,val in pairs(arg) do s = s .. val end io.write(s) io.close() end function AE_Utilities:FileExists(name) local f = io.open(name, "r") return f ~= nil and io.close(f) end
AE_Utilities
Unlisted
Author: A.Evseeva
View Script
Script type: Utility
Uploaded: Jul 14 2020, 07:42
Last modified: Jul 17 2023, 04:45
Common methods necessary for some of my other scripts
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: 5950
AE_Utilities
Unlisted
Author: A.Evseeva
View Script
Script type: Utility
Uploaded: Jul 14 2020, 07:42
Last modified: Jul 17 2023, 04:45
Common methods necessary for some of my other scripts
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: 5950