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

ScriptName = "AE_FixedAngleOnOf"

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

AE_FixedAngleOnOf = {}

function AE_FixedAngleOnOf:Name()
	return 'Independent angle on/off'
end

function AE_FixedAngleOnOf:Version()
	return '1.0'
end

function AE_FixedAngleOnOf:UILabel()
	return 'Independent angle on/off'
end

function AE_FixedAngleOnOf:Creator()
	return 'Alexandra Evseeva'
end

function AE_FixedAngleOnOf:Description()
	return 'Select one bone and use script'
end


-- **************************************************
-- Is Relevant / Is Enabled
-- **************************************************

function AE_FixedAngleOnOf:IsRelevant(moho)
	return true
end

function AE_FixedAngleOnOf:IsEnabled(moho)
	return true
end

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

function AE_FixedAngleOnOf:Run(moho)
	moho.document:SetDirty()
	moho.document:PrepUndo(nil)
	
	local skel = moho:Skeleton()
	if not skel then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Skeleton not found") end
	if moho:CountSelectedBones(true) ~= 1 then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Please select one and only one bone") end

	local theBone = skel:Bone(skel:SelectedBoneID())
	if theBone.fAnimParent:Duration() > 0 then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Can't process bones with animated parenting") end
	local parentBone = skel:Bone(theBone.fAnimParent.value)
	if not parentBone then 
		theBone.fFixedAngle = not theBone.fFixedAngle
		return
	end
	
	local AE_Utilities_GetGlobalBonePRS_cancalcIK = false
	if AE_Utilities_GetGlobalBonePRS_cancalcIK then
	
		local gpP, gpR = AE_Utilities:Matrix2transform(parentBone.fRestMatrix)
		for k = 1, theBone.fAnimAngle:CountKeys() - 1 do
			local actChannel = theBone.fAnimAngle
			local when = actChannel:GetKeyWhen(k)
			local gP, gR = AE_Utilities:GetGlobalBonePRS(moho, skel, theBone, when)
			local pP, pR = AE_Utilities:GetGlobalBonePRS(moho, skel, parentBone, when)
			local theValue = actChannel:GetValue(when)
			print('frame ', when, ' global parent: ', 180*pR/math.pi, ' global child was: ', 180*gR/math.pi)
			if theBone.fFixedAngle then
				theValue = gR - pR
			else
				theValue = gR - gpR
			end
			actChannel:SetValue(when, theValue)
		end
		for a = 0, theBone.fAnimAngle:CountActions() - 1 do
			local actChannel = theBone.fAnimAngle:Action(a)
			if actChannel:Duration() > 0 then
				local actName = theBone.fAnimAngle:ActionName(a)
				actChannel = moho:ChannelAsAnimVal(actChannel)
				for k = 1, actChannel:CountKeys() - 1 do
					local when = actChannel:GetKeyWhen(k)
					local gP, gR = AE_Utilities:GetGlobalBonePRS(moho, skel, theBone, when, actName)
					local pP, pR = AE_Utilities:GetGlobalBonePRS(moho, skel, parentBone, when, actName)
					local theValue = actChannel:GetValue(when)
					if theBone.fFixedAngle then
						theValue = gR - pR
					else
						theValue = gR - gpR
					end	
					actChannel:SetValue(when, theValue)
				end
			end
			
		end
		theBone.fFixedAngle = not theBone.fFixedAngle
	else 
		local frameToReturn = moho.frame
	
		local storedVals = {}
		storedVals[""] = {}
		for k = 1, theBone.fAnimAngle:CountKeys() - 1 do
			local when = theBone.fAnimAngle:GetKeyWhen(k)
			moho:SetCurFrame(when)
			storedVals[""][when] = theBone.fAngle
		end
		
		for a = 0, theBone.fAnimAngle:CountActions() - 1 do
			local actChannel = theBone.fAnimAngle:Action(a)
			if actChannel:Duration() > 0 then
				local actName = theBone.fAnimAngle:ActionName(a)
				moho.layer:ActivateAction(actName)
				for k = 1, actChannel:CountKeys() - 1 do
					local when = actChannel:GetKeyWhen(k)
					moho:SetCurFrame(when)
					storedVals[actName][when] = theBone.fAngle					
				end
			end
		end
		moho.layer:ActivateAction(nil)
		theBone.fFixedAngle = not theBone.fFixedAngle
		
		for k = 1, theBone.fAnimAngle:CountKeys() - 1 do
			local when = theBone.fAnimAngle:GetKeyWhen(k)
			moho:SetCurFrame(when)
			local oldVal = storedVals[""][when]
			local addVal = oldVal - theBone.fAngle
			theBone.fAnimAngle:SetValue(when, theBone.fAnimAngle:GetValue(when) + addVal)
		end
		
		for a = 0, theBone.fAnimAngle:CountActions() - 1 do
			local actChannel = theBone.fAnimAngle:Action(a)
			if actChannel:Duration() > 0 then
				local actName = theBone.fAnimAngle:ActionName(a)
				moho.layer:ActivateAction(actName)
				for k = 1, actChannel:CountKeys() - 1 do
					local when = actChannel:GetKeyWhen(k)
					moho:SetCurFrame(when)
					local oldVal = storedVals[actName][when]
					local addVal = oldVal - theBone.fAngle
					theBone.fAnimAngle:SetValue(when, theBone.fAnimAngle:GetValue(when) + addVal)									
				end
			end
		end
		moho.layer:ActivateAction(nil)
		moho:SetCurFrame(frameToReturn)
	end	
	
end

Safe turn Independent Angle on and off
Listed

Script type: Button/Menu

Uploaded: Apr 10 2022, 01:21

Fixes all the angle animation both in Mainline and actions to not to change after Independent angle value flipped
Select only one bone to flip it's Independent Angle value. 
Only this bone's keys will be fixed. Values produced with parent bones' keys having no keys of processed bone in same frames may look wrong.

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