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

ScriptName = "AE_SmartGrandchildren"

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

AE_SmartGrandchildren = {}

function AE_SmartGrandchildren:Name()
	return 'Apply smart to grandchildren'
end

function AE_SmartGrandchildren:Version()
	return '1.1'
end

function AE_SmartGrandchildren:UILabel()
	return 'Apply smart to grandchildren'
end

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

function AE_SmartGrandchildren:Description()
	return 'Make a smartbone appliable for it\'s layer\' grandchildren'
end


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

function AE_SmartGrandchildren:IsRelevant(moho)
	return true
end

function AE_SmartGrandchildren:IsEnabled(moho)
	return true
end

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

function AE_SmartGrandchildren:Run(moho)
	moho.document:SetDirty()
	moho.document:PrepUndo(nil)
	
	local theSkel = moho:Skeleton()
	if not theSkel then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Skeleton not found") end
	local theLayer = moho:LayerAsBone(moho.layer)
	if not theLayer or theLayer:Skeleton() ~= theSkel then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Please select the top bone layer") end
	local theSmart = theSkel:Bone(theSkel:SelectedBoneID())
	if not theSmart then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Please select the smartbone you want to use on grandchildren") end
	if not theLayer:HasAction(theSmart:Name()) and not theLayer:HasAction(theSmart:Name() .. " 2") then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Selected bone is not a smart one") end
	
	for i, childLayer in AE_Utilities:IterateAllLayers(moho) do
		if childLayer:ControllingSkeleton() == theSkel then
			childLayer = moho:LayerAsBone(childLayer)
			if childLayer then
				local hasAction = false
				for i, grandLayer in AE_Utilities:IterateAllLayers(moho) do
					if grandLayer:ControllingSkeleton() == childLayer:Skeleton() then
						if grandLayer:HasAction(theSmart:Name()) or grandLayer:HasAction(theSmart:Name() .. " 2") then
							hasAction = true 
							break
						end
					end
				end
				if hasAction then 
					-- create copy smart
					local childSkel = childLayer:Skeleton()
					local childSmart = childSkel:AddBone(0)
					childSmart:SetName("_" .. theSmart:Name())
					childSmart.fAnimPos:SetValue(0, theSmart.fAnimPos:GetValue(0))
					childSmart.fAnimAngle:SetValue(0, theSmart.fAnimAngle:GetValue(0))
					childSmart.fLength = theSmart.fLength
					childSmart.fStrength = 0
					-- for each of two actions
					for i, actName in pairs({theSmart:Name(), theSmart:Name().." 2"}) do
						local theSmartRotation = theSmart.fAnimAngle:ActionByName(actName)
						if theSmartRotation and theSmartRotation:Duration() > 0 then
							-- copy rotation of theSmart to copySmart actions of theSmart and copySmart
							theSmartRotation = moho:ChannelAsAnimVal(theSmartRotation)
							childLayer:ActivateAction(actName)
							for k = 1, theSmartRotation:CountKeys() - 1 do
								local when = theSmartRotation:GetKeyWhen(k)
								childSmart.fAnimAngle:SetValue(when, theSmartRotation:GetValue(when))
								local interp = MOHO.InterpSetting:new_local()
								theSmartRotation:GetKeyInterp(when, interp)
								childSmart.fAnimAngle:SetKeyInterp(when, interp)
							end
							childLayer:ActivateAction("_" .. actName)
							for k = 1, theSmartRotation:CountKeys() - 1 do
								local when = theSmartRotation:GetKeyWhen(k)
								childSmart.fAnimAngle:SetValue(when, theSmartRotation:GetValue(when))
								local interp = MOHO.InterpSetting:new_local()
								theSmartRotation:GetKeyInterp(when, interp)
								childSmart.fAnimAngle:SetKeyInterp(when, interp)								
							end	
							--TODO: maybe temporaly return to mainline?
							-- move grandChildren animation from theSmart actions to copySmart actions
							for i, grandLayer in AE_Utilities:IterateAllLayers(moho) do
								if grandLayer:ControllingSkeleton() == childLayer:Skeleton() then
									for j, i, channel, chInfo in AE_Utilities:IterateAllChannels(moho, grandLayer) do
										local grandOldAction = channel:ActionByName(actName)
										if grandOldAction and grandOldAction:Duration() > 0 then
											grandOldAction = AE_Utilities:GetDerivedChannel(moho, grandOldAction)
											--TODO: maybe get "_"..actName action from channel?
											channel = AE_Utilities:GetDerivedChannel(moho, channel)
											if grandOldAction and channel then
												for k = 1, grandOldAction:CountKeys() - 1 do
													local when = grandOldAction:GetKeyWhen(k)
													channel:SetValue(when, grandOldAction:GetValue(when))
													local interp = MOHO.InterpSetting:new_local()
													grandOldAction:GetKeyInterp(when, interp)
													channel:SetKeyInterp(when, interp)
												end
												grandOldAction:Clear()
											end
										end
									end
								end
							end
						end					
					end
					childLayer:ActivateAction(nil)
				end
			end
		end
	end
	
end

Apply smart to grandchildren
Listed

Script type: Button/Menu

Uploaded: Apr 09 2022, 15:28

Last modified: Apr 09 2022, 15:37

Script Version: 1.1

Fix smartactions made for smartbone in top bone layer using layers driven with its child bone layers
When your smartbone is located in a top bone layer and its action includes both child bone layers and "grandchild" bone layers -- children of child skeleton. In that case all the animation plays while you are inside the action timeline, but breaks when you drive smartbone on the Mainline.
So go to Mainline, select the top bone layer and the smartbone and use the script.

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