ScriptName = "AE_ActionTools"
AE_ActionTools = {}
AE_ActionTools.BASE_STR = MOHO.MSG_BASE

function AE_ActionTools:Name()
	return "AE Action Tools"
end

function AE_ActionTools:Version()
	return "0.3"
end

function AE_ActionTools:Description()
	return "Some utilities to manipulate actions, bones and points"
end

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

function AE_ActionTools:UILabel()
	return "Action tools"
end

function AE_ActionTools:LoadPrefs(prefs)

end

function AE_ActionTools:SavePrefs(prefs)

end

function AE_ActionTools:ResetPrefs(prefs)

end



function AE_ActionTools:IsRelevant(moho)
	return true
end

function AE_ActionTools:IsEnabled(moho)
   return true
end

function AE_ActionTools:DrawMe(moho, view)
  LM_SelectBone:DrawMe(moho,view)
end

function AE_ActionTools:OnMouseDown(moho, mouseEvent)
  if moho.layer:LayerType() == MOHO.LT_BONE then LM_SelectBone:OnMouseDown(moho,mouseEvent) 
  elseif moho.layer:LayerType() == MOHO.LT_VECTOR then LM_SelectPoints:OnMouseDown(moho,mouseEvent)
  end 
end

function AE_ActionTools:OnMouseMoved(moho, mouseEvent) 
  if moho.layer:LayerType() == MOHO.LT_BONE then LM_SelectBone:OnMouseMoved(moho,mouseEvent)
  elseif moho.layer:LayerType() == MOHO.LT_VECTOR then LM_SelectPoints:OnMouseMoved(moho,mouseEvent)
  end 
end

function AE_ActionTools:OnMouseUp(moho, mouseEvent)
  if moho.layer:LayerType() == MOHO.LT_BONE then LM_SelectBone:OnMouseUp(moho,mouseEvent)
  elseif moho.layer:LayerType() == MOHO.LT_VECTOR then LM_SelectPoints:OnMouseUp(moho,mouseEvent)
  end 
end

AE_ActionTools.DELETEBUTTON = AE_ActionTools.BASE_STR + 1
--------------------------------------------------
AE_ActionTools.BONEPOSTRACKS = AE_ActionTools.BASE_STR + 10
AE_ActionTools.BONEANGLETRACKS = AE_ActionTools.BASE_STR + 11
AE_ActionTools.BONESCALETRACKS = AE_ActionTools.BASE_STR + 12

AE_ActionTools.VERTSHANDLESTRACKS = AE_ActionTools.BASE_STR + 13
AE_ActionTools.SHAPETRACKS = AE_ActionTools.BASE_STR + 14

--------------------------------------------------
AE_ActionTools.SELECTIONACTIONSMENU_START = AE_ActionTools.BASE_STR + 100

--------------------------------------------------
AE_ActionTools.ACTIONSMENU_START = AE_ActionTools.BASE_STR + 500

AE_ActionTools.debug = false

AE_ActionTools.bonePosTracks = true
AE_ActionTools.boneRotTracks = true
AE_ActionTools.boneScaleTracks = true
AE_ActionTools.vertsHandlesTracks = true
AE_ActionTools.shapeTracks = false

function AE_ActionTools:DoLayout(moho, layout)

	layout:AddChild(LM.GUI.StaticText("Select from: "))
	
	self.actionsMenu = LM.GUI.Menu("...")
	self.actionsPopup = LM.GUI.PopupMenu(240, true)
	self.actionsPopup:SetMenu(self.actionsMenu)
	layout:AddChild(self.actionsPopup)	
	self.actionsPopup:SetToolTip("All layer members actions, select one...")
	
	layout:AddChild(LM.GUI.StaticText("      Delete from: "))
	
	self.selActionsMenu = LM.GUI.Menu("Selection actions...")
	self.selActionsPopup = LM.GUI.PopupMenu(240, false)
	self.selActionsPopup:SetMenu(self.selActionsMenu)
	self.selActionsPopup:SetToolTip("Actions current selection used in")
	layout:AddChild(self.selActionsPopup) 
	
	self.delTracksMenu = LM.GUI.Menu("Delete bone tracks...")
	self.delTracksPopup = LM.GUI.PopupMenu(100, false)			
	self.delTracksPopup:SetMenu(self.delTracksMenu)
	self.delTracksPopup:SetToolTip("Filter tracks to delete from actions")
	layout:AddChild(self.delTracksPopup) 
	self.delTracksMenu:AddItem("Bone Rotation", 0, self.BONEANGLETRACKS)
	self.delTracksMenu:AddItem("Bone Translation", 0, self.BONEPOSTRACKS)	
	self.delTracksMenu:AddItem("Bone Scale", 0, self.BONESCALETRACKS)

	self.delVectorTracksMenu = LM.GUI.Menu("Delete vector tracks...")
	self.delVectorTracksPopup = LM.GUI.PopupMenu(100, false)			
	self.delVectorTracksPopup:SetMenu(self.delVectorTracksMenu)
	self.delVectorTracksPopup:SetToolTip("Filter tracks to delete from actions")
	layout:AddChild(self.delVectorTracksPopup) 
	self.delVectorTracksMenu:AddItem("Vertices and handles", 0, self.VERTSHANDLESTRACKS)
	self.delVectorTracksMenu:AddItem("Shapes", 0, self.SHAPETRACKS)		
	
	self.deleteButton = LM.GUI.Button("DELETE", self.DELETEBUTTON)
	self.deleteButton:SetToolTip("Delete selected bone or point from selected actions")
	layout:AddChild(self.deleteButton) 	

	

end

function AE_ActionTools:HandleMessage(moho, view, msg)
	if (msg == self.DELETEBUTTON) then 
		self:DeleteSelectedActions(moho)
	--------------------------------------------------------------
	elseif msg > self.SELECTIONACTIONSMENU_START and msg < self.ACTIONSMENU_START then 
		self.selActionsMenu:SetChecked(msg, not self.selActionsMenu:IsChecked(msg))
	elseif msg > self.ACTIONSMENU_START	then
		local actionName = self.actionsMenu:FirstCheckedLabel()
		self:SelectActionMembers(moho, actionName)
	elseif msg == self.BONEPOSTRACKS then 
		self.delTracksMenu:SetChecked(msg, not self.delTracksMenu:IsChecked(msg))
		self.bonePosTracks = self.delTracksMenu:IsChecked(self.BONEPOSTRACKS)
	elseif msg == self.BONEANGLETRACKS then 
		self.delTracksMenu:SetChecked(msg, not self.delTracksMenu:IsChecked(msg))
		self.boneRotTracks = self.delTracksMenu:IsChecked(self.BONEANGLETRACKS)	
	elseif msg == self.BONESCALETRACKS then 
		self.delTracksMenu:SetChecked(msg, not self.delTracksMenu:IsChecked(msg))
		self.boneScaleTracks = self.delTracksMenu:IsChecked(self.BONESCALETRACKS)
	elseif msg == self.VERTSHANDLESTRACKS then 
		self.delVectorTracksMenu:SetChecked(msg, not self.delVectorTracksMenu:IsChecked(msg))
		self.vertsHandlesTracks = self.delVectorTracksMenu:IsChecked(self.VERTSHANDLESTRACKS)
	elseif msg == self.SHAPETRACKS then 
		self.delVectorTracksMenu:SetChecked(msg, not self.delVectorTracksMenu:IsChecked(msg))
		self.shapeTracks = self.delVectorTracksMenu:IsChecked(self.SHAPETRACKS)		
	end
end

function AE_ActionTools:UpdateWidgets(moho)
	self:UpdateActionList(moho)
	if moho:Skeleton() then
		self.delTracksPopup:Enable(true)
	else
		self.delTracksPopup:Enable(false)
	end
	self.delTracksMenu:SetChecked(self.BONEPOSTRACKS, self.bonePosTracks)
	self.delTracksMenu:SetChecked(self.BONEANGLETRACKS, self.boneRotTracks)	
	self.delTracksMenu:SetChecked(self.BONESCALETRACKS, self.boneScaleTracks)
	self.delVectorTracksMenu:SetChecked(self.VERTSHANDLESTRACKS, self.vertsHandlesTracks)	
	self.delVectorTracksMenu:SetChecked(self.SHAPETRACKS, self.shapeTracks)	
end

function AE_ActionTools:GetChannelByCode(moho, layer, code)
	for subID, ID, channel, chInfo in AE_Utilities:IterateAllChannels(moho, layer) do
		if chInfo.channelID == code then 
			if self.debug then print ("subChannels: ", chInfo.subChannelCount) end
			return ID 
		end
	end
end

function AE_ActionTools:UpdateActionList(moho)
	if self.debug then print("something happens") end
	local actionNames = {}
	local selActionNames = {}  
	local found = false
	local selFound = false
	for act=0, moho.layer:CountActions()-1 do
		local nextName = moho.layer:ActionName(act)
		if moho.layer:LayerType() == MOHO.LT_VECTOR then
			local mesh = moho:Mesh()
			local curveOffset = 0
			local curvatureChannelID = self:GetChannelByCode(moho, moho.layer, CHANNEL_CURVE)
			if self.debug then print("curvature channel: ", curvatureChannelID) end
			for p=0, mesh:CountPoints()-1 do
				local nextPoint = mesh:Point(p)
				local numCurves = nextPoint:CountCurves()
				if nextPoint.fSelected or not found then 
					local actionChannel = nextPoint.fAnimPos:ActionByName(nextName)
					if actionChannel and actionChannel:Duration()>0 then 
						found = true
						if nextPoint.fSelected then
							selFound = true
							break 
						end
					end	
					if self.debug then print("iterating from ", (curveOffset*5), " to ", (curveOffset*5) + (numCurves * 5)) end
					for subID = (curveOffset*5), (curveOffset*5) + (numCurves * 5) - 1 do
						local curveChannel = moho.layer:Channel(curvatureChannelID, subID, moho.document)
						if self.debug then print(subID) end
						actionChannel = curveChannel:ActionByName(nextName)
						if self.debug and actionChannel then print("duration: ", actionChannel:Duration()) end
						if actionChannel and actionChannel:Duration()>0 then 
							found = true
							if nextPoint.fSelected then
								selFound = true
								break 
							end
						end
					end
				end
				if selFound then break end
				curveOffset = curveOffset + numCurves
			end
			for s=0, mesh:CountShapes()-1 do
				local nextShape = mesh:Shape(s)
				if nextShape.fSelected or not found then 
					local fillChannel = nextShape.fMyStyle.fFillCol
					local actionChannel = fillChannel:ActionByName(nextName)
					if actionChannel  and actionChannel:Duration()>0 then
						found = true
						if nextShape.fSelected then
							selFound = true
							break
						end
					end
					if not found then
						local lineChannel = nextShape.fMyStyle.fLineCol
						local actionChannel = lineChannel:ActionByName(nextName)
						if actionChannel  and actionChannel:Duration()>0 then 
							found = true
							if nextShape.fSelected then
								selFound = true
								break
							end					
						end
					end
				end
			end
		elseif moho.layer:LayerType() == MOHO.LT_BONE then 
			local skel = moho:Skeleton()
			for b=0, skel:CountBones()-1 do
				local nextBone = skel:Bone(b)
				if nextBone.fSelected or not found then 	
					local actionChannel = nextBone.fAnimAngle:ActionByName(nextName)
					if actionChannel and actionChannel:Duration()>0 then 
						found = true
						if nextBone.fSelected then 
							selFound = true
							break 
						end
					end
					actionChannel = nextBone.fAnimScale:ActionByName(nextName)
					if actionChannel and actionChannel:Duration()>0 then 
						found = true
						if nextBone.fSelected then 
							selFound = true
							break 
						end
					end
					actionChannel = nextBone.fAnimPos:ActionByName(nextName)
					if actionChannel and actionChannel:Duration()>0 then 
						found = true
						if nextBone.fSelected then 
							selFound = true
							break 
						end
					end
				end
			end 
		end
		if found then table.insert(actionNames, nextName) end
		if selFound then table.insert(selActionNames, nextName) end
		found = false
		selFound = false
	end
	self.selActionsMenu:RemoveAllItems()
	for j=1, #selActionNames do
		self.selActionsMenu:AddItem(selActionNames[j], 0, self.SELECTIONACTIONSMENU_START+j)
	end
	self.actionsMenu:RemoveAllItems()
	for j=1, #actionNames do
		self.actionsMenu:AddItem(actionNames[j], 0, self.ACTIONSMENU_START+j)
	end	
end

function AE_ActionTools:DeleteSelectedActions(moho)
	local actionsList = {}
	local firstID = self.selActionsMenu:FirstChecked()
	local curMsg = self.selActionsMenu:FirstCheckedMsg()
	for i=firstID, self.selActionsMenu:CountItems()-1 do
		local nextLabel = self.selActionsMenu:ItemLabel(curMsg)
		if self.selActionsMenu:IsChecked(curMsg) and moho.layer:HasAction(nextLabel) then table.insert(actionsList, nextLabel) end
		curMsg = curMsg + 1
	end
	--for k, v in pairs(actionsList) do print("removing animation from ", v) end
	for k,actionName in pairs(actionsList) do
		if moho.layer:LayerType() == MOHO.LT_VECTOR then
			local mesh = moho:Mesh()
			if self.vertsHandlesTracks then 
				local curveOffset = 0
				local curvatureChannelID = self:GetChannelByCode(moho, moho.layer, CHANNEL_CURVE)
				for p=0, mesh:CountPoints()-1 do 
					local numCurves = mesh:Point(p):CountCurves()
					if mesh:Point(p).fSelected then
						local actionChannel = mesh:Point(p).fAnimPos:ActionByName(actionName)
						if actionChannel then actionChannel:ClearAfter(0) end 
						for subID = (curveOffset * 5), (curveOffset*5) + (numCurves * 5) - 1 do
							local curveChannel = moho.layer:Channel(curvatureChannelID, subID, moho.document)
							if curveChannel then
								actionChannel = curveChannel:ActionByName(actionName)
								if actionChannel then actionChannel:ClearAfter(0) end
							end
						end					
					end
					curveOffset = curveOffset + numCurves
				end
			end
			if self.shapeTracks then
				for s = 0, mesh:CountShapes() - 1 do
					local nextShape = mesh:Shape(s)
					if nextShape.fSelected then
						local fillChannel = nextShape.fMyStyle.fFillCol
						local actionChannel = fillChannel:ActionByName(actionName)
						if actionChannel then actionChannel:ClearAfter(0) end 
						local lineChannel = nextShape.fMyStyle.fLineCol
						actionChannel = lineChannel:ActionByName(actionName)
						if actionChannel then actionChannel:ClearAfter(0) end
					end
				end
			end
		elseif moho.layer:LayerType() == MOHO.LT_BONE then
			local skel = moho:Skeleton() 
			for b=0, skel:CountBones()-1 do 
				if skel:Bone(b).fSelected then
					local actionChannel = skel:Bone(b).fAnimPos:ActionByName(actionName)
					if self.bonePosTracks then 
						if actionChannel then actionChannel:ClearAfter(0) end 
					end
					if self.boneRotTracks then 
						actionChannel = skel:Bone(b).fAnimAngle:ActionByName(actionName)
						if actionChannel then actionChannel:ClearAfter(0) end
					end
					if self.boneScaleTracks then
						actionChannel = skel:Bone(b).fAnimScale:ActionByName(actionName)  
						if actionChannel then actionChannel:ClearAfter(0) end 
					end
				end
			end    
		end
	end

	moho:UpdateUI()
	self:UpdateActionList(moho)  
end

function AE_ActionTools:SelectActionMembers(moho, actionName)
	if moho.layer:LayerType() == MOHO.LT_VECTOR then
		local mesh = moho:Mesh()
		local curveOffset = 0
		local curvatureChannelID = self:GetChannelByCode(moho, moho.layer, CHANNEL_CURVE)
		if self.debug then print("curvature channel: ", curvatureChannelID) end
		for p=0, mesh:CountPoints()-1 do
			local nextPoint = mesh:Point(p)
			local numCurves = nextPoint:CountCurves()
			if not nextPoint.fSelected then 
				local actionChannel = nextPoint.fAnimPos:ActionByName(actionName)
				if actionChannel and actionChannel:Duration()>0 then 
					nextPoint.fSelected = true 
				end
				if self.debug then print("iterating from ", (curveOffset*5), " to ", (curveOffset*5) + (numCurves * 5)) end
				if not nextPoint.fSelected then
					for subID = (curveOffset*5), (curveOffset*5) + (numCurves * 5) - 1 do
						local curveChannel = moho.layer:Channel(curvatureChannelID, subID, moho.document)
						if self.debug then print(subID) end
						actionChannel = curveChannel:ActionByName(actionName)
						if self.debug and actionChannel then print("duration: ", actionChannel:Duration()) end
						if actionChannel and actionChannel:Duration()>0 then 
							nextPoint.fSelected = true
							break
						end
					end
				end
			end
			curveOffset = curveOffset + numCurves
		end
		for s = 0, mesh:CountShapes() - 1 do
			local nextShape = mesh:Shape(s)
			nextShape.fSelected = false
			local fillChannel = nextShape.fMyStyle.fFillCol
			local actionChannel = fillChannel:ActionByName(actionName)
			if actionChannel and actionChannel:Duration() > 0 then nextShape.fSelected = true end 
			local lineChannel = nextShape.fMyStyle.fLineCol
			actionChannel = lineChannel:ActionByName(actionName)
			if actionChannel and actionChannel:Duration() > 0 then nextShape.fSelected = true end 
		end
	elseif moho.layer:LayerType() == MOHO.LT_BONE then 
		local skel = moho:Skeleton()
		local boneProps = {"fAnimAngle", "fAnimScale", "fAnimPos"}
		for b=0, skel:CountBones()-1 do
			local nextBone = skel:Bone(b)
			if not nextBone.fSelected then 
				for i,v in pairs(boneProps) do
					local actionChannel = nextBone[v]:ActionByName(actionName)
					if actionChannel and actionChannel:Duration()>0 then 
						nextBone.fSelected = true
						break
					end					
				end
			end
		end 
	end	
end





Icon
AE Action tools
Listed

Script type: Tool

Uploaded: Apr 12 2021, 06:11

Control which actions use selected bones or points and remove unwanted uses
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: 199