--! @file lm_bind_points.lua
--! Select/deselect points (press <%s> to bind points, hold <shift> to modify current selection, <ctrl/cmd> to toggle lasso mode, <alt> to select a new bone)

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

ScriptName = "LM_BindPoints_AE"

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

LM_BindPoints_AE = {}

LM_BindPoints_AE.BASE_STR = 2050
LM_BindPoints_AE.STR_LABEL = LM_BindPoints_AE.BASE_STR
LM_BindPoints_AE.STR_DESC = LM_BindPoints_AE.BASE_STR + 1
LM_BindPoints_AE.STR_SELECTBONE = LM_BindPoints_AE.BASE_STR + 2
LM_BindPoints_AE.STR_SELECTGROUP = LM_BindPoints_AE.BASE_STR + 3
LM_BindPoints_AE.STR_BINDPOINTS = LM_BindPoints_AE.BASE_STR + 4
LM_BindPoints_AE.STR_LASSOMODE = LM_BindPoints_AE.BASE_STR + 5

--! Returns the name of the script. For this script, the name is "Bind Points".
--! @retval LM_String
function LM_BindPoints_AE:Name()
	return "Bind Points"
end

--! Returns the version of the script.
--! @retval LM_String
function LM_BindPoints_AE:Version()
	return "6.1"
end

--! Returns a localized description of the script's functionality.
--! @retval LM_String
function LM_BindPoints_AE:Description()
	return string.format(
		MOHO.Localize("/Scripts/Tool/BindPoints/Description=Select/deselect points (press <%s> to bind points, hold <shift> to modify current selection, <ctrl/cmd> to toggle lasso mode, <alt> to select a new bone)"),
		MOHO.BindingKeyName()
	)
end

--! Always returns "Smith Micro Software, Inc."
--! @retval LM_String
function LM_BindPoints_AE:Creator()
	return "Smith Micro Software, Inc."
end

--! Returns the localized label for the bind points function.
--! @retval LM_String
function LM_BindPoints_AE:UILabel()
	return MOHO.Localize("/Scripts/Tool/BindPoints/BindPoints=Bind Points")
end

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

LM_BindPoints_AE.startPt = LM.Point:new_local()

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

function LM_BindPoints_AE:IsEnabled(moho)
	if (moho:DisableDrawingTools()) then
		return false
	end
	if (moho:CountPoints() < 1) then
		return false
	end
	local skel = moho:ParentSkeleton()
	if (skel == nil) then
		return false
	end
	if (moho.layer:LayerParentBone() >= 0) then
		return false
	end
	return true
end

function LM_BindPoints_AE:IsRelevant(moho)
	if (moho:DisableDrawingTools()) then
		return false
	end
	local skel = moho:ParentSkeleton()
	if (skel == nil) then
		return false
	end
	return true
end

function LM_BindPoints_AE:OnMouseDown(moho, mouseEvent)
	self.startPt:Set(mouseEvent.pt)
	LM_SelectPoints:OnMouseDown(moho, mouseEvent)
end

function LM_BindPoints_AE:OnMouseMoved(moho, mouseEvent)
	LM_SelectPoints:OnMouseMoved(moho, mouseEvent)
end

function LM_BindPoints_AE:OnMouseUp(moho, mouseEvent)
	LM_SelectPoints:OnMouseUp(moho, mouseEvent)
	if (mouseEvent.altKey) then
		local dist = self.startPt - mouseEvent.pt
		if ((math.abs(dist.x) < 3) and (math.abs(dist.y) < 3)) then
			LM_SelectBone:Select(moho, mouseEvent.pt, mouseEvent.drawingVec, mouseEvent.view, false, false)
		end
	end
end

function LM_BindPoints_AE:OnKeyDown(moho, keyEvent)
	if (keyEvent.keyCode == LM.GUI.KEY_BIND) then
		self:HandleMessage(moho, keyEvent.view, self.BIND)
	elseif (keyEvent.keyCode == LM.GUI.KEY_UP) then
		LM_SelectBone:OnKeyDown(moho, keyEvent)
	elseif (keyEvent.keyCode == LM.GUI.KEY_DOWN) then
		LM_SelectBone:OnKeyDown(moho, keyEvent)
	end
end

function LM_BindPoints_AE:DrawMe(moho, view)
	LM_SelectPoints:DrawMe(moho, view)
end

-- **************************************************
-- Tool options - create and respond to tool's UI
-- **************************************************

LM_BindPoints_AE.BIND = MOHO.MSG_BASE
LM_BindPoints_AE.LASSO = MOHO.MSG_BASE + 1
LM_BindPoints_AE.DUMMY = MOHO.MSG_BASE + 2
LM_BindPoints_AE.ANIMSAFE = MOHO.MSG_BASE + 3
LM_BindPoints_AE.SELECTBONE = MOHO.MSG_BASE + 4
LM_BindPoints_AE.SELECTITEM = MOHO.MSG_BASE + 300

function LM_BindPoints_AE:DoLayout(moho, layout)
	self.boneMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/BindPoints/SelectBone=Select Bone"))

	self.bonePopup = LM.GUI.PopupMenu(128, false)
	self.bonePopup:SetMenu(self.boneMenu)
	layout:AddChild(self.bonePopup)

	self.pointMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/BindPoints/SelectGroup=Select Group"))

	self.pointPopup = LM.GUI.PopupMenu(128, false)
	self.pointPopup:SetMenu(self.pointMenu)
	layout:AddChild(self.pointPopup)

	self.bindBut = LM.GUI.Button(MOHO.Localize("/Scripts/Tool/BindPoints/BindPoints=Bind Points"), self.BIND)
	layout:AddChild(self.bindBut)

	self.lassoCheck = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/BindPoints/LassoMode=Lasso mode"), self.LASSO)
	layout:AddChild(self.lassoCheck)
	
	self.animsafeCheck  = LM.GUI.CheckBox("Anim safe", self.ANIMSAFE)
	layout:AddChild(self.animsafeCheck)
end

function LM_BindPoints_AE:UpdateWidgets(moho)
	if (moho:CurrentTool() ~= "LM_BindPoints_AE") then
		return -- this could get called when doing a double-tap on a multitouch Wacom device with a different active tool
	end

	local skel = moho:ParentSkeleton()
	if (skel == nil) then
		return
	end
	local mesh = moho:Mesh()
	if (mesh == nil) then
		return
	end

	MOHO.BuildBoneMenu(self.boneMenu, skel, self.SELECTBONE, self.DUMMY)
	MOHO.BuildGroupMenu(self.pointMenu, mesh, self.SELECTITEM, self.DUMMY)
	self.lassoCheck:SetValue(LM_SelectPoints.lassoMode)
end

function LM_BindPoints_AE:HandleMessage(moho, view, msg)
	local skel = moho:ParentSkeleton()
	if (skel == nil) then
		return
	end

	local mesh = moho:Mesh()
	if (mesh == nil) then
		return
	end

	if (msg == self.BIND) then
		moho.document:PrepUndo(moho.layer)
		moho.document:SetDirty()

		local boneID = -1
		for i = 0, skel:CountBones() - 1 do
			if (skel:Bone(i).fSelected) then
				boneID = i
				break
			end
		end
		local boneTransform = LM.Matrix:new_local()
		local restTransform = LM.Matrix:new_local()
		if boneID >= 0 then
			boneTransform:Set(skel:Bone(boneID).fMovedMatrix)
			boneTransform:Invert()
			restTransform:Set(skel:Bone(boneID).fRestMatrix)
		end
		local tempV2 = LM.Vector2:new_local()
		local layerTransform = LM.Matrix:new_local()
		local layerTransform2 = LM.Matrix:new_local()
		local layerInvertTransform = LM.Matrix:new_local()
		moho.layer:GetLayerTransform(moho.frame, layerTransform, moho.document)
		local layer = moho.layer
		while layer:Parent() ~= moho.layer:ControllingBoneLayer() do
			layer = layer:Parent()
			layer:GetLayerTransform(moho.frame, layerTransform2, moho.document)
			layerTransform2:Multiply(layerTransform)
			layerTransform:Set(layerTransform2)
		end
		layerInvertTransform:Set(layerTransform)
		layerInvertTransform:Invert()
		for i = 0, mesh:CountPoints() - 1 do
			local pt = mesh:Point(i)
			if (pt.fSelected) then -- attach selected points
				if self.animsafeCheck:Value() and boneID >= 0 then
					tempV2:Set(pt.fPos)
					layerTransform:Transform(tempV2)
					boneTransform:Transform(tempV2)
					restTransform:Transform(tempV2)
					layerInvertTransform:Transform(tempV2)
					pt.fAnimPos:Clear()
					pt.fAnimPos:SetValue(0, tempV2)
				end
				pt.fParent = boneID
			elseif (pt.fParent == boneID) then -- detach unselected points that used to be attached
				if not self.animsafeCheck:Value() then pt.fParent = -1 end
			end
		end
		moho.layer:UpdateCurFrame(true)
		view:DrawMe()
	elseif (msg == self.LASSO) then
		LM_SelectPoints.lassoMode = self.lassoCheck:Value()
	elseif (msg >= self.SELECTBONE and msg < self.SELECTITEM) then
		for i = 0, skel:CountBones() - 1 do
			skel:Bone(i).fSelected = (i == msg - self.SELECTBONE)
		end
		moho:UpdateBonePointSelection()
		moho:UpdateUI()
	elseif (msg >= self.SELECTITEM) then
		mesh:SelectNone()
		local i = msg - self.SELECTITEM
		local name = mesh:Group(i):Name()
		mesh:SelectGroup(name)
		moho:UpdateUI()
	end
end

Bind points modification
Listed

Script type: Tool

Uploaded: Apr 30 2021, 07:44

Bind points to bone at non-zero frame, saving their current position
Use "Anim Safe" checkbox to turn the feature on.
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: 191