-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "AE_MergeSkeletons"

-- **************************************************
-- General information about this script
-- **************************************************

AE_MergeSkeletons = {}

function AE_MergeSkeletons:Name()
	return "Merge Skeletons"
end

function AE_MergeSkeletons:Version()
	return "1.0"
end

function AE_MergeSkeletons:UILabel()
	return "Merge Skeletons"
end

function AE_MergeSkeletons:Creator()
	return "Alexandra Evseeva"
end

function AE_MergeSkeletons:Description()
	return "Merge current skeleton with parent one"
end




-- **************************************************
-- Recurring values
-- **************************************************

-- AE_MergeSkeletons.value1 = false

-- **************************************************
-- Is Enabled
-- **************************************************

function AE_MergeSkeletons:IsEnabled(moho)
	return true
end


-- **************************************************
-- The guts of this script
-- **************************************************

function AE_MergeSkeletons:Run(moho)

	moho.document:PrepUndo(moho.layer)
	moho.document:SetDirty()
	
	   local sourceBoneLayer = moho.layer
   
   
   local sourceSkeleton = moho:Skeleton()
   
   local targetSkeleton = sourceBoneLayer:ControllingSkeleton()
   local targetBoneLayer = sourceBoneLayer:Parent()
   
   nextBoneLayer = moho:LayerAsBone(targetBoneLayer)
   while not nextBoneLayer or not nextBoneLayer:Skeleton() == targetSkeleton do 
		targetBoneLayer = targetBoneLayer:Parent()
		nextBoneLayer = moho:LayerAsBone(targetBoneLayer)
	end	
		
   moho:SetSelLayer(targetBoneLayer)

   local boneMap = {}
   for boneID=0, sourceSkeleton:CountBones()-1 do
      local sourceBone = sourceSkeleton:Bone(boneID)
      local targetBone = targetSkeleton:AddBone(0)
      boneMap[sourceBone] = targetBone
      self:CopyBoneProps(sourceBone, targetBone)
      targetBone:SetName(sourceBone:Name())
   end
   for k, v in pairs(boneMap) do
      if(k.fParent>-1) then
        v.fParent = targetSkeleton:BoneID(boneMap[sourceSkeleton:Bone(k.fParent)])
      end
      if(k.fAngleControlParent>-1) then
        v.fAngleControlParent = targetSkeleton:BoneID(boneMap[sourceSkeleton:Bone(k.fAngleControlParent)])
        v.fAngleControlScale = k.fAngleControlScale
      end
      if(k.fPosControlParent>-1) then
        v.fPosControlParent = targetSkeleton:BoneID(boneMap[sourceSkeleton:Bone(k.fPosControlParent)])
        v.fPosControlScale = k.fPosControlScale
      end
      if(k.fScaleControlParent>-1) then
        v.fScaleControlParent = targetSkeleton:BoneID(boneMap[sourceSkeleton:Bone(k.fScaleControlParent)])
        v.fScaleControlScale = k.fScaleControlScale
      end
      if(k.fTargetBone:GetValue(0)>-1) then
        v.fTargetBone:SetValue(0, targetSkeleton:BoneID(boneMap[sourceSkeleton:Bone(k.fTargetBone:GetValue(0))]))
      end	  
   end

   local layersMap = {}
   local oldGroup = moho:LayerAsGroup(sourceBoneLayer)
   local newGroup = moho:LayerAsGroup(targetBoneLayer)
   self:StoreBindings(moho, layersMap, oldGroup)
   while oldGroup:CountLayers()>0 do
      local childLayer = oldGroup:Layer(0)
      moho:PlaceLayerInGroup(childLayer, newGroup, false)
   end
   local boneIDMap = {}
   for k, v in pairs(boneMap) do
      boneIDMap[sourceSkeleton:BoneID(k)] = targetSkeleton:BoneID(v)
   end
   self:RestoreBindings(moho, layersMap, boneIDMap) 
   
   for k, v in pairs(boneMap) do
       local nextActionName = k:Name() 
       if sourceBoneLayer:HasAction(nextActionName) then 
          sourceBoneLayer:ActivateAction(nextActionName)
          local animAngle = k.fAnimAngle
          print(nextActionName, " keys: ", animAngle:CountKeys())
          targetBoneLayer:ActivateAction(nextActionName)
          for f=0, animAngle:Duration() do
             if animAngle:HasKey(f) then
                v.fAnimAngle:SetValue(f,animAngle:GetValue(f))
             end
            for otherBoneID = 0, sourceSkeleton:CountBones()-1 do 
                local otherBone = sourceSkeleton:Bone(otherBoneID)
                local otherTargetBone = boneMap[otherBone]
                if otherBone.fAnimAngle:HasKey(f) then
                   otherTargetBone.fAnimAngle:SetValue(f, otherBone.fAnimAngle:GetValue(f))
                end
                if otherBone.fAnimPos:HasKey(f) then
                   otherTargetBone.fAnimPos:SetValue(f, otherBone.fAnimPos:GetValue(f))
                end 
                if otherBone.fAnimScale:HasKey(f) then
                   otherTargetBone.fAnimScale:SetValue(f, otherBone.fAnimScale:GetValue(f))
                end
                if otherBone.fFlipH:HasKey(f) then
                   otherTargetBone.fFlipH:SetValue(f, otherBone.fFlipH:GetValue(f))
                end 
                if otherBone.fFlipV:HasKey(f) then
                   otherTargetBone.fFlipV:SetValue(f, otherBone.fFlipV:GetValue(f))
                end              
            end 
          end
       end
       nextActionName = k:Name() .. " 2"
       if sourceBoneLayer:HasAction(nextActionName) then 
          sourceBoneLayer:ActivateAction(nextActionName)
          local animAngle = k.fAnimAngle
          print(nextActionName, " keys: ", animAngle:CountKeys())
          targetBoneLayer:ActivateAction(nextActionName)
          for f=0, animAngle:Duration() do
             if animAngle:HasKey(f) then
                v.fAnimAngle:SetValue(f,animAngle:GetValue(f))
             end
            for otherBoneID = 0, sourceSkeleton:CountBones()-1 do 
                local otherBone = sourceSkeleton:Bone(otherBoneID)
                local otherTargetBone = boneMap[otherBone]
                if otherBone.fAnimAngle:HasKey(f) then
                   otherTargetBone.fAnimAngle:SetValue(f, otherBone.fAnimAngle:GetValue(f))
                end
                if otherBone.fAnimPos:HasKey(f) then
                   otherTargetBone.fAnimPos:SetValue(f, otherBone.fAnimPos:GetValue(f))
                end 
                if otherBone.fAnimScale:HasKey(f) then
                   otherTargetBone.fAnimScale:SetValue(f, otherBone.fAnimScale:GetValue(f))
                end
                if otherBone.fFlipH:HasKey(f) then
                   otherTargetBone.fFlipH:SetValue(f, otherBone.fFlipH:GetValue(f))
                end 
                if otherBone.fFlipV:HasKey(f) then
                   otherTargetBone.fFlipV:SetValue(f, otherBone.fFlipV:GetValue(f))
                end              
            end 
          end
       end       
   end
   
   sourceBoneLayer:ActivateAction("")
   
   while sourceSkeleton:CountBones()>0 do
      sourceSkeleton:DeleteBone(0,0)
   end
   moho.layer:ActivateAction("")
	
end

function AE_MergeSkeletons:CopyBoneProps(src, trg)
   trg.fLength = src.fLength  
   trg.fAnimPos:SetValue(0, src.fPos)        
   trg.fAnimAngle:SetValue(0, src.fAngle)    
   trg.fAnimScale:SetValue(0, src.fScale) 
   trg:ShowLabel(src:IsLabelShowing())
   trg.fShy = src.fShy
   trg.fStrength = src.fStrength
   trg.fFixedAngle = src.fFixedAngle
   trg.fMinConstraint = src.fMinConstraint
   trg.fMaxConstraint = src.fMaxConstraint
   trg.fConstraints = src.fConstraints
   trg.fIgnoredByIK = src.fIgnoredByIK

end

function AE_MergeSkeletons:StoreBindings(moho, storeArray, rootGroup)
  for childID = 0, rootGroup:CountLayers()-1 do
    local childLayer = rootGroup:Layer(childID)
    local storeObject = {}
    storeObject["layer"] = childLayer:LayerParentBone()
    if childLayer:LayerType() == MOHO.LT_VECTOR then 
      local vertices = {}
      moho:SetSelLayer(childLayer)
      local mesh = moho:Mesh()
      for pointID = 0, mesh:CountPoints()-1 do
        vertices[pointID] = mesh:Point(pointID).fParent
      end
      storeObject["vertices"] = vertices
    end  
    storeArray[childLayer] = storeObject
    if childLayer:IsGroupType() then
      local childGroup = moho:LayerAsGroup(childLayer)
      self:StoreBindings(moho, storeArray, childGroup)
    end
  end
end 

function AE_MergeSkeletons:RestoreBindings(moho, storeArray, boneIDMap)
  for k, v in pairs(storeArray) do
    if v.layer > -1 then
      k:SetLayerParentBone(boneIDMap[v.layer]) 
    end
    if k:LayerType() == MOHO.LT_VECTOR then
      moho:SetSelLayer(k)
      local mesh = moho:Mesh()
      for pointID = 0, mesh:CountPoints()-1 do
        if v.vertices[pointID] > -1 then
          local newBone = boneIDMap[v.vertices[pointID]]
          mesh:Point(pointID).fParent = newBone
        end
      end
    end 
  end
end



Merge skeletons
Listed

Script type: Button/Menu

Uploaded: Jan 21 2021, 11:37

Merge bones from a nested skeleton layer into parent layer skeleton

Installation Options:

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: 66