-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "AE_Magnet" -- ************************************************** -- General information about this script -- ************************************************** AE_Magnet = {} AE_Magnet.BASE_STR = 2145 function AE_Magnet:Name() return "Magnet" end function AE_Magnet:Version() return "6.48" end function AE_Magnet:Description() return MOHO.Localize("/Scripts/Tool/Magnet/Description=Move points within a radius of influence for selected layers(hold <alt> to adjust radius, <ctrl/cmd> to select points)") end function AE_Magnet:Creator() return "Smith Micro Software, improved by Alexandra Evseeva" end function AE_Magnet:UILabel() return(MOHO.Localize("/Scripts/Tool/Magnet/Magnet=Magnet")) end function AE_Magnet:LoadPrefs(prefs) self.magnetRadius = prefs:GetFloat("AE_Magnet.magnetRadius", 0.5) self.selectedOnly = prefs:GetBool("AE_Magnet.selectedOnly", false) self.multilayerMode = prefs:GetBool("AE_Magnet.multilayerMode", false) end function AE_Magnet:SavePrefs(prefs) prefs:SetFloat("AE_Magnet.magnetRadius", self.magnetRadius) prefs:SetBool("AE_Magnet.selectedOnly", self.selectedOnly) prefs:SetBool("AE_Magnet.multilayerMode", self.multilayerMode) end function AE_Magnet:NonDragMouseMove() return true -- Call MouseMoved() even if the mouse button is not down end function AE_Magnet:ResetPrefs() self.magnetRadius = 0.5 self.selectedOnly = false self.multilayerMode = false end -- ************************************************** -- Recurring values -- ************************************************** AE_Magnet.newMethod = false AE_Magnet.magnetRadius = 0.5 AE_Magnet.selectedOnly = true AE_Magnet.dragging = false AE_Magnet.dragVec = LM.Vector2:new_local() AE_Magnet.dragVec:Set(10000.0, 10000.0) AE_Magnet.dragResize = false AE_Magnet.selectionMode = false AE_Magnet.multilayerMode = false AE_Magnet.startRadius = 0 AE_Magnet.wasMoved = false AE_Magnet.minVec = LM.Vector2:new_local() AE_Magnet.maxVec = LM.Vector2:new_local() -- ************************************************** -- The guts of this script -- ************************************************** function AE_Magnet:IsEnabled(moho) --[[ if (moho:CountPoints() > 0) then return true end return false --]] return true end function AE_Magnet:IsRelevant(moho) --[[ local mesh = moho:DrawingMesh() if (mesh == nil) then return false end --]] return true end function AE_Magnet:OnInputDeviceEvent(moho, deviceEvent) return LM_TransformPoints:OnInputDeviceEvent(moho, deviceEvent) end function AE_Magnet:OnMouseDown(moho, mouseEvent) self.wasMoved = false local mesh = moho:DrawingMesh() if (mesh == nil) then return end if (mouseEvent.altKey) then self.dragResize = true self.startRadius = self.magnetRadius self.dragVec:Set(mouseEvent.drawingVec) mouseEvent.view:DrawMe() return elseif (mouseEvent.ctrlKey) then self.selectionMode = true mouseEvent.ctrlKey = false LM_SelectPoints:OnMouseDown(moho, mouseEvent) return end self.dragging = true self.dragVec:Set(mouseEvent.drawingVec) if not self.multilayerMode then moho.document:PrepUndo(moho.drawingLayer) else moho.document:PrepMultiUndo() end moho.document:SetDirty() --print("Mouse down") self.scaleList = {} self.endFPos = {} self.selList = {} self.layers = {} --deltas is from the previous version. It can be deleted now. self.deltas = {} --print("mouse: ", mouseEvent.drawingVec.x, ", ", mouseEvent.drawingVec.y) local vec = LM.Vector2:new_local() local m = LM.Matrix:new_local() local absMouse = LM.Vector2:new_local() vec:Set(mouseEvent.drawingVec) moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document) m:Transform(vec) absMouse:Set(vec) --print("abs: ", absMouse.x, ", ", absMouse.y) for la = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(la) layer:GetFullTransform(moho.frame, m, moho.document) m:Invert() m:Transform(vec) m:Invert() --print(layer:Name(), "\n", vec.x, ", ", vec.y) if (self.multilayerMode or layer == moho.drawingLayer) and layer:LayerType() == MOHO.LT_VECTOR then mesh = moho:LayerAsVector(layer):Mesh() for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if (not pt.fHidden and not (self.selectedOnly and not pt.fSelected)) then local v = pt.fPos - mouseEvent.drawingVec if(self.multilayerMode and layer~=moho.drawingLayer) then vec:Set(pt.fPos) m:Transform(vec) v = vec - absMouse end local magInfluence = v:Mag() --print(magInfluence) if (self.newMethod) then -- new method (more similar to how bones work) -- however, the "strength" is set to a constant 0.5 - the user would need to be able to change this magInfluence = magInfluence * magInfluence magInfluence = 0.5 / (1 + magInfluence * magInfluence * 1000) if (magInfluence > 0.001 or (self.selectedOnly and pt.fSelected)) then pt.fSelected = true if (magInfluence <= 0.001) then magInfluence = 0.0 end table.insert(self.scaleList, magInfluence) table.insert(self.endFPos, LM.Vector2:new_local()) table.insert(self.layers, layer) --------------------------- from the previous version. Can be deleted now table.insert(self.deltas, LM.Vector2:new_local()) self.deltas[#self.deltas]:Set(pt.fPos - pt.fAnimPos:GetValue(moho.frame)) ------------------------------------------------------------------------- else pt.fSelected = false end else -- old method if (magInfluence <= self.magnetRadius or (self.selectedOnly and pt.fSelected)) then -- mark the point as selected, and compute the magnet's influence over it pt.fSelected = true magInfluence = magInfluence / self.magnetRadius if (magInfluence > 1.0) then magInfluence = 1.0 end table.insert(self.scaleList, LM.Slerp(magInfluence, 1, 0)) table.insert(self.endFPos, LM.Vector2:new_local()) table.insert(self.layers, layer) --------------------------- from the previous version. Can be deleted now table.insert(self.deltas, LM.Vector2:new_local()) self.deltas[#self.deltas]:Set(pt.fPos - pt.fAnimPos:GetValue(moho.frame)) ------------------------------------------------------------------------- else pt.fSelected = false end end end end mesh:PrepMovePoints() for p=0, mesh:CountPoints()-1 do if mesh:Point(p).fSelected then table.insert(self.selList, mesh:Point(p)) end end end end --TODO:fix and uncomment next lines to work in onion skin mode --for now these lines do not work correctly --[[ for la = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(la) if (self.multilayerMode or layer == moho.drawingLayer) and layer:LayerType() == MOHO.LT_VECTOR then moho:AddPointKeyframe(moho.drawingFrame, layer, MOHO.MohoGlobals.EditMultipleKeys) end end self:CorrectPointPos(moho) for la = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(la) if (self.multilayerMode or layer == moho.drawingLayer) and layer:LayerType() == MOHO.LT_VECTOR then moho:AddPointKeyframe(moho.drawingFrame, layer, MOHO.MohoGlobals.EditMultipleKeys) end end --]] mouseEvent.view:DrawMe() end function AE_Magnet:OnMouseMoved(moho, mouseEvent) local mesh = moho:DrawingMesh() if (mesh == nil) then return end if (self.dragResize) then self.magnetRadius = self.startRadius + (mouseEvent.pt.x - mouseEvent.startPt.x) / 600 if (self.magnetRadius < 0.01) then self.magnetRadius = 0.01 end if (self.magnetRadius > 5.0) then self.magnetRadius = 5.0 end mouseEvent.view:DrawMe() return elseif (self.selectionMode) then mouseEvent.ctrlKey = false LM_SelectPoints:OnMouseMoved(moho, mouseEvent) return end self.dragVec:Set(mouseEvent.drawingVec) if (not self.dragging) then mouseEvent.view:DrawMe() return end local offset = mouseEvent.drawingVec - mouseEvent.drawingStartVec local vec = LM.Vector2:new_local() local vec2 = LM.Vector2:new_local() local m = LM.Matrix:new_local() local mloc = LM.Matrix:new_local() moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document) for i, pt in ipairs(self.selList) do local pointOffset = offset if(self.multilayerMode and self.layers[i]~=moho.drawingLayer)then vec:Set(mouseEvent.drawingVec) vec2:Set(mouseEvent.drawingStartVec) self.layers[i]:GetFullTransform(moho.frame, mloc, moho.document) mloc:Invert() mloc:Multiply(m) mloc:Transform(vec) mloc:Transform(vec2) pointOffset = vec - vec2 --print("moving for ", pointOffset.x, ", ", pointOffset.y) end pt.fPos = pt.fTempPos + pointOffset * self.scaleList[i] if(self.endFPos[i]~=nil)then self.endFPos[i]:Set(pt.fPos) end end self.wasMoved = true mouseEvent.view:DrawMe() end function AE_Magnet:OnMouseUp(moho, mouseEvent) local mesh = moho:DrawingMesh() if (mesh == nil) then return end self.dragging = false self.dragVec:Set(mouseEvent.drawingVec) if (self.dragResize) then self.dragResize = false mouseEvent.view:DrawMe() return elseif (self.selectionMode) then mouseEvent.ctrlKey = false LM_SelectPoints:OnMouseUp(moho, mouseEvent) self.selectionMode = false mouseEvent.view:DrawMe() return end if self.wasMoved then for la = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(la) --layerFrame = moho.frame + layer:TotalTimingOffset() moho:AddPointKeyframe(moho.drawingFrame, layer, MOHO.MohoGlobals.EditMultipleKeys) end self:CorrectPointPos(moho) for la = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(la) --layerFrame = moho.frame + layer:TotalTimingOffset() moho:AddPointKeyframe(moho.drawingFrame, layer, MOHO.MohoGlobals.EditMultipleKeys) end else for i, pt in ipairs(self.selList) do frame = moho.drawingFrame + self.layers[i]:TotalTimingOffset() pt.fAnimPos:SetValue(frame, pt.fAnimPos:GetValue(frame)) end end --moho:NewKeyframe(CHANNEL_POINT) moho:UpdateUI() self.selList = nil self.scaleList = nil end function AE_Magnet:OnKeyDown(moho, keyEvent) if (not self.dragging) then LM_SelectPoints:OnKeyDown(moho, keyEvent) end end function AE_Magnet:DrawMe(moho, view) local mesh = moho:DrawingMesh() if (mesh == nil) then return end if (self.selectionMode) then LM_SelectPoints:DrawMe(moho, view) return end MOHO.DrawToolSizeCircle(moho, view, self.dragVec, self.magnetRadius, self.dragResize) end -- ************************************************** -- Tool options - create and respond to tool's UI -- ************************************************** AE_Magnet.CHANGE = MOHO.MSG_BASE AE_Magnet.DUMMY = MOHO.MSG_BASE + 1 AE_Magnet.RESET = MOHO.MSG_BASE + 2 AE_Magnet.SELECTITEM = MOHO.MSG_BASE + 3 AE_Magnet.SELECTCHILDREN = MOHO.MSG_BASE + 4 function AE_Magnet:DoLayout(moho, layout) layout:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/Magnet/MagnetRadius=Magnet radius"))) self.radius = LM.GUI.TextControl(0, "00.0000", self.CHANGE, LM.GUI.FIELD_UFLOAT) self.radius:SetWheelInc(0.01) layout:AddChild(self.radius) self.selectedCheck = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/Magnet/SelectedPointsOnly=Selected points only"), self.CHANGE) layout:AddChild(self.selectedCheck) self.multilayerCheck = LM.GUI.CheckBox("Multi layer", self.CHANGE) layout:AddChild(self.multilayerCheck) self.selectChildrenButton = LM.GUI.Button("Select child layers", self.SELECTCHILDREN) layout:AddChild(self.selectChildrenButton) end function AE_Magnet:UpdateWidgets(moho) local mesh = moho:DrawingMesh() if (mesh == nil) then return end self.radius:SetValue(self.magnetRadius) self.selectedCheck:SetValue(self.selectedOnly) self.multilayerCheck:SetValue(self.multilayerMode) end function AE_Magnet:HandleMessage(moho, view, msg) if(msg == self.SELECTCHILDREN) then local layerCollection = self:SelectChildLayers(moho, moho.layer, MOHO.LT_VECTOR) if moho.layer:LayerType() ~= MOHO.LT_VECTOR and #layerCollection > 0 then moho:SetSelLayer(layerCollection[1]) for k,v in pairs(layerCollection) do moho:SetSelLayer(v, true) end end moho:UpdateUI() return end local mesh = moho:DrawingMesh() if (mesh == nil) then return end if (msg == self.RESET) then self.magnetRadius = 0.5 moho:UpdateUI() elseif (msg == self.CHANGE) then self.magnetRadius = self.radius:FloatValue() if (self.magnetRadius < 0.001) then self.magnetRadius = 0.001 end self.selectedOnly = self.selectedCheck:Value() self.multilayerMode = self.multilayerCheck:Value() 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 function AE_Magnet:CorrectPointPos(moho) for i, pt in ipairs(self.selList) do if(self.endFPos[i]~=nil) then --print(self.endFPos[i].x, self.endFPos[i].y) --print(pt.fPos.x, pt.fPos.y) local delta = self.endFPos[i] - pt.fPos pt.fPos = self.endFPos[i] + delta end end end function AE_Magnet:printPos(moho, pos) print("x = ", pos.x, " y = ", pos.y) local layerMatrix = LM.Matrix:new_local() moho.layer:GetFullTransform(moho.frame, layerMatrix, moho.document) local getAbsPos = LM.Vector2:new_local() getAbsPos:Set(pos) layerMatrix:Transform(getAbsPos) print("x = ", getAbsPos.x, " y = ", getAbsPos.y) end function AE_Magnet:SelectChildLayers(moho, layer, layer_type) local layerCollection = {} layer:SetSecondarySelection(true) if layer_type and layer:LayerType() ~= layer_type then layer:SetSecondarySelection(false) end if not layer_type or layer:LayerType() == layer_type then table.insert(layerCollection, layer) end if layer:IsGroupType() then local group = moho:LayerAsGroup(layer) for child = 0, group:CountLayers()-1 do local childCollection = self:SelectChildLayers(moho, group:Layer(child), layer_type) for k,v in pairs(childCollection) do table.insert(layerCollection, v) end end end return layerCollection end
Multilayer magnet
Listed
Author: A.Evseeva
View Script
Script type: Tool
Uploaded: Sep 15 2020, 08:55
Last modified: Jul 02 2021, 03:51
Magnet working with all the selected layers.
Also fixed errors on smartbone driven points.
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: 635

Multilayer magnet
Listed
Author: A.Evseeva
View Script
Script type: Tool
Uploaded: Sep 15 2020, 08:55
Last modified: Jul 02 2021, 03:51
Magnet working with all the selected layers.
Also fixed errors on smartbone driven points.
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: 635