-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "AE_MeshinstanceTool" -- ************************************************** -- General information about this script -- ************************************************** AE_MeshinstanceTool = {} function AE_MeshinstanceTool:Name() return "Meshinstance Tool" end function AE_MeshinstanceTool:Version() return "1.31" end function AE_MeshinstanceTool:UILabel() return "Meshinstance tool" end function AE_MeshinstanceTool:Creator() return "Alexandra Evseeva" end function AE_MeshinstanceTool:Description() return "Interface for binding mesh layers (alternative to built-in internal reference system). Child layers repeat vertex and curvature animation of their parents" end function AE_MeshinstanceTool:LoadPrefs(prefs) self.allLayers = prefs:GetBool("AE_MeshinstanceTool.allLayers", false) self.preventSelection = prefs:GetBool("AE_MeshinstanceTool.preventSelection", true) end function AE_MeshinstanceTool:SavePrefs(prefs) prefs:SetBool("AE_MeshinstanceTool.allLayers", self.allLayers) prefs:SetBool("AE_MeshinstanceTool.preventSelection", self.preventSelection) end function AE_MeshinstanceTool:ResetPrefs() self.allLayers = false self.preventSelection = true end -- ************************************************** -- Is Relevant / Is Enabled -- ************************************************** function AE_MeshinstanceTool:IsRelevant(moho) return true end function AE_MeshinstanceTool:IsEnabled(moho) if self.preventSelection and not self.GPUmode and moho.frame > 0 and self:GetLayerParent(moho, moho.layer) then --self:SelectParentLayer(moho) local curParent = self:GetLayerParent(moho) if curParent and moho.layer ~= curParent then moho:SetSelLayer(curParent) moho:UpdateUI() end end return true end -- ************************************************** -- Tool options - create and respond to tool's UI -- ************************************************** AE_MeshinstanceTool.srcKeyName = "AE_MeshinstSrc" AE_MeshinstanceTool.srcPathKeyName = "AE_MeshinstSrcPath" AE_MeshinstanceTool.scriptName = "ae_meshinstance.lua" AE_MeshinstanceTool.allLayers = false AE_MeshinstanceTool.realtimeOn = 0 AE_MeshinstanceTool.preventSelection = true AE_MeshinstanceTool.GPUmode = false AE_MeshinstanceTool.MSG = MOHO.MSG_BASE AE_MeshinstanceTool.REALTIME_BUTTON = AE_MeshinstanceTool.MSG + 1 AE_MeshinstanceTool.PARENT_BUTTON = AE_MeshinstanceTool.MSG + 2 AE_MeshinstanceTool.NEWPARENT_BUTTON = AE_MeshinstanceTool.MSG + 3 AE_MeshinstanceTool.NEWPARENT_BUTTON = AE_MeshinstanceTool.MSG + 4 AE_MeshinstanceTool.UPDATE_LINK = AE_MeshinstanceTool.MSG + 5 AE_MeshinstanceTool.ALLLAYERS_BUTTON = AE_MeshinstanceTool.MSG + 7 AE_MeshinstanceTool.DUPLAYER_BUTTON = AE_MeshinstanceTool.MSG + 8 --[[ AE_MeshinstanceTool.LOCKLAYER_BUTTON = AE_MeshinstanceTool.MSG + 9 --]] AE_MeshinstanceTool.PREVENTSELECTION = AE_MeshinstanceTool.MSG + 10 AE_MeshinstanceTool.DUPGROUP_BUTTON = AE_MeshinstanceTool.MSG + 11 AE_MeshinstanceTool.PARENT_BUTTON_ALT = AE_MeshinstanceTool.MSG + 12 function AE_MeshinstanceTool:DoLayout(moho, layout) layout:AddChild(LM.GUI.StaticText("REALTIME: ")) self.realtime_button = LM.GUI.Button("???", self.REALTIME_BUTTON) layout:AddChild(self.realtime_button) self.realtime_button:SetToolTip("Press to switch realtime on and off for all parented layers") layout:AddChild(LM.GUI.StaticText("Current layer's parent is ")) self.parent_button = LM.GUI.Button(" NONE ", self.PARENT_BUTTON, LM.GUI.ALIGN_CENTER) layout:AddChild(self.parent_button) self.parent_button:SetAlternateMessage(self.PARENT_BUTTON_ALT) self.parent_button:SetToolTip("Press to select parent layer") layout:AddChild(LM.GUI.StaticText("Set parent to ")) self.newParent_button = LM.GUI.Button(" NONE ", self.NEWPARENT_BUTTON) layout:AddChild(self.newParent_button) self.newParent_button:SetToolTip("Select two layers: parent first, child second (and active selected), then press this button") self.updateLink_button = LM.GUI.Button("UPDATE LINK", self.UPDATE_LINK) layout:AddChild(self.updateLink_button) self.updateLink_button:SetToolTip("Press to refresh linking for a single selected child layer") self.updateAll_button = LM.GUI.Button("UPDATE ALL", self.ALLLAYERS_BUTTON) layout:AddChild(self.updateAll_button) self.updateAll_button:SetToolTip("Press to refresh linking for all layers") layout:AddChild(LM.GUI.StaticText("Create")) self.dupLayer_button = LM.GUI.Button("reference", self.DUPLAYER_BUTTON) layout:AddChild(self.dupLayer_button) self.dupLayer_button:SetToolTip("Duplicate group or layer creating linked layer(s)") self.dupGroup_button = LM.GUI.Button("copy", self.DUPGROUP_BUTTON) layout:AddChild(self.dupGroup_button) self.dupGroup_button:SetToolTip("Duplicate group creating a group with same link structure") --[[ self.lockLayer_button = LM.GUI.Button("unlock", self.LOCKLAYER_BUTTON) layout:AddChild(self.lockLayer_button) self.lockLayer_button:SetToolTip("Lock/unlock current layer") --]] self.preventSelection_check = LM.GUI.CheckBox("Prevent child selection", self.PREVENTSELECTION) layout:AddChild(self.preventSelection_check) end function AE_MeshinstanceTool:UpdateWidgets(moho) if self.realtimeOn == 0 then self.realtime_button:SetLabel("???", false) elseif self.realtimeOn == 1 then self.realtime_button:SetLabel("ON", false) elseif self.realtimeOn == -1 then self.realtime_button:SetLabel("OFF", false) end local curParent = self:GetLayerParent(moho) if curParent then self.parent_button:SetLabel(curParent:Name(),false) self.parent_button:Enable(true) else self.parent_button:SetLabel("NONE", false) self.parent_button:Enable(true) --[[ -- folowing code slows down layer selecting, so it's commented out -- and needs to be replaced with asking current layer for its children or their quantity at least -- writing these properties to parent layer during parenting self.parent_button:Enable(false) for i, layer in AE_Utilities:IterateAllLayers(moho) do if self:GetLayerParent(moho, layer) == moho.layer then self.parent_button:Enable(true) break end end --]] end local newParent = self:GetNewParent(moho) if newParent then self.newParent_button:SetLabel(newParent:Name(), false) self.newParent_button:Enable(true) else self.newParent_button:SetLabel("NONE", false) if curParent then self.newParent_button:Enable(true) else self.newParent_button:Enable(false) end end self.preventSelection_check:SetValue(self.preventSelection) --[[ local label = moho.layer:IsLocked() and 'unlock' or 'lock' self.lockLayer_button:SetLabel(label, false) --]] end function AE_MeshinstanceTool:HandleMessage(moho, view, msg) if(msg == self.REALTIME_BUTTON) then self.realtimeOn = self:SwitchRealtime(moho) self:UpdateWidgets(moho) elseif(msg == self.PARENT_BUTTON) then self:SelectParentLayer(moho, false) elseif(msg == self.PARENT_BUTTON_ALT) then --self:SelectParentLayer(moho, true) self:SelectAllGroup(moho) elseif(msg == self.NEWPARENT_BUTTON) then self:SetNewParentLayer(moho) elseif(msg == self.UPDATE_LINK) then self:UpdateLink(moho) elseif(msg == self.ALLLAYERS_BUTTON) then self:UpdateAllLayers(moho) elseif(msg == self.DUPLAYER_BUTTON) then moho.document:SetDirty() moho.document:PrepUndo() local oldLayer = moho.layer local newLayer = moho:DuplicateLayer(oldLayer) self:DuplicateLayer(moho, oldLayer, newLayer) elseif(msg == self.DUPGROUP_BUTTON) then moho.document:SetDirty() moho.document:PrepUndo() local oldLayer = moho.layer local newLayer = moho:DuplicateLayer(oldLayer) self:CopyGroupStructure(moho, oldLayer, newLayer) --[[ elseif (msg == self.LOCKLAYER_BUTTON) then moho.layer:SetLocked(not moho.layer:IsLocked()) moho.layer:SetLabelColor(moho.layer:IsLocked() and -1 or 0) self:UpdateWidgets(moho) --]] elseif msg == self.PREVENTSELECTION then self.preventSelection = self.preventSelection_check:Value() end end function AE_MeshinstanceTool:OnMouseDown(moho, mouseEvent) end function AE_MeshinstanceTool:DrawMe(moho, view) end -- ************************************************** -- The guts of this script -- ************************************************** function AE_MeshinstanceTool:DoesFileExist(name) return os.rename(name, name) and true or false end function AE_MeshinstanceTool:ScriptSourcePath() local str = debug.getinfo(2, "S").source:sub(2) local _, slashPos = string.find(string.lower(str), "scripts") local slash = string.sub(str, slashPos+1, slashPos+1) local pattern = "(.*\\)[tT]ool\\" if slash == "/" then pattern = "(.*/)[tT]ool/" end return (str:match(pattern) .. "ScriptResources".. slash .. "ae_meshinstance" .. slash), slash end function AE_MeshinstanceTool:GetScriptPath(moho) local docPath = string.sub(moho.document:Path(), 1, #moho.document:Path()-#moho.document:Name()) local scriptPath = docPath .. self.scriptName if not self:DoesFileExist(scriptPath) then local sourcePath, slash = self:ScriptSourcePath() sourcePath = sourcePath..self.scriptName local cmdline = 'copy "' .. sourcePath .. '" "' .. scriptPath .. '"' if slash == "/" then cmdline = string.gsub(cmdline, "copy", "cp") end --print(cmdline) os.execute(cmdline) end return scriptPath end function AE_MeshinstanceTool:SwitchRealtime(moho) local scriptPath = self:GetScriptPath(moho) if self.realtimeOn > -1 then for i, layer in AE_Utilities:IterateAllLayers(moho) do self:TurnScriptOff(moho,layer) end return -1 end for i, layer in AE_Utilities:IterateAllLayers(moho) do self:TurnScriptOn(moho,layer,scriptPath) end return 1 end function AE_MeshinstanceTool:SelectAllGroup(moho) local curParent = self:GetLayerParent(moho) local layersToSelect = {} for i, layer in AE_Utilities:IterateAllLayers(moho) do local inGroup = false if curParent and curParent == layer then inGroup = true else layerParent = self:GetLayerParent(moho, layer) if curParent and curParent == layerParent then inGroup = true elseif layerParent == moho.layer then inGroup = true end end if inGroup then table.insert(layersToSelect, layer) end end for i, layer in pairs(layersToSelect) do moho:SetSelLayer(layer, true) moho:ShowLayerInLayersPalette(layer) end moho:UpdateUI() self:UpdateWidgets(moho) end function AE_MeshinstanceTool:SelectParentLayer(moho, addToSelection) local curParent = self:GetLayerParent(moho) if curParent then moho:SetSelLayer(curParent, addToSelection) moho:UpdateUI() moho:ShowLayerInLayersPalette(curParent) self:UpdateWidgets(moho) end end function AE_MeshinstanceTool:LinkLayers(moho, childLayer, parentLayer) local scriptInfo = childLayer:ScriptData() if not parentLayer then scriptInfo:Remove(self.srcKeyName) scriptInfo:Remove(self.srcPathKeyName) --childLayer:SetLocked(false) if childLayer:LabelColor() == -1 then childLayer:SetLabelColor(0) end return end scriptInfo:Set(self.srcKeyName, parentLayer:UUID()) scriptInfo:Set(self.srcPathKeyName, AE_Utilities:GetLayerRelativePath(moho, childLayer, parentLayer)) end function AE_MeshinstanceTool:SetNewParentLayer(moho) local newParentLayer = self:GetNewParent(moho) local scriptInfo = moho.layer:ScriptData() if newParentLayer then local path = AE_Utilities:GetLayerRelativePath(moho, moho.layer, newParentLayer) local foundParent = AE_Utilities:GetLayerFromRelativePath(moho, moho.layer, path) if foundParent ~= newParentLayer then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, string.format("Can not link %s to %s", moho.layer:Name(), newParentLayer:Name())) end end self:LinkLayers(moho, moho.layer, newParentLayer) if not newParentLayer then --scriptInfo:Remove(self.srcKeyName) --scriptInfo:Remove(self.srcPathKeyName) self.parent_button:SetLabel("NONE",false) self.parent_button:Enable(false) return end --scriptInfo:Set(self.srcKeyName, newParentLayer:UUID()) --scriptInfo:Set(self.srcPathKeyName, AE_Utilities:GetLayerRelativePath(moho, moho.layer, newParentLayer)) self.parent_button:SetLabel(newParentLayer:Name(),false) self.parent_button:Enable(true) end function AE_MeshinstanceTool:UpdateBinding(moho, layer, parentLayer) local mesh = moho:LayerAsVector(layer) local parentMesh = moho:LayerAsVector(parentLayer) if not mesh or not parentMesh then return end mesh = mesh:Mesh() parentMesh = parentMesh:Mesh() for p = 0, math.min(parentMesh:CountPoints(), mesh:CountPoints())-1 do mesh:Point(p).fParent = parentMesh:Point(p).fParent end end function AE_MeshinstanceTool:UpdateLink(moho) if not self:IsScriptOn(moho, moho.layer) then local theLayer = moho.layer self.GPUmode = true local scriptPath = self:GetScriptPath(moho) for i, layer in AE_Utilities:IterateAllLayers(moho) do local parentLayer = self:GetLayerParent(moho,layer) if parentLayer == layer then LM.GUI.Alert(LM.GUI.ALERT_WARINING, "Removed self-reference from " .. AE_Utilities:GetLayerRelativePath(moho, nil, layer)) self:LinkLayers(moho, layer, nil) elseif parentLayer then if layer == theLayer or parentLayer == theLayer then moho:SetSelLayer(layer) self:LinkLayers(moho, layer, parentLayer) self:UpdateBinding(moho, layer, parentLayer) self:TurnScriptOn(moho, layer, scriptPath) self:TurnScriptOff(moho, layer) layer:UpdateCurFrame() end end end moho:SetSelLayer(theLayer) self.GPUmode = false end moho:UpdateUI() end function AE_MeshinstanceTool:UpdateAllLayers(moho) if not self:IsScriptOn(moho, moho.layer) then local scriptPath = self:GetScriptPath(moho) for i, layer in AE_Utilities:IterateAllLayers(moho) do if not layer:IsReferencedLayer() then local parentLayer = self:GetLayerParent(moho,layer) if parentLayer == layer then LM.GUI.Alert(LM.GUI.ALERT_WARINING, "Removed self-reference from " .. AE_Utilities:GetLayerRelativePath(moho, nil, layer)) self:LinkLayers(moho, layer, nil) elseif parentLayer then --print("updating ", layer:Name(), " from ", parentLayer:Name()) self:LinkLayers(moho, layer, parentLayer) self:UpdateBinding(moho, layer, parentLayer) self:TurnScriptOn(moho, layer, scriptPath) self:TurnScriptOff(moho, layer) layer:UpdateCurFrame() end end end end moho:UpdateUI() end function AE_MeshinstanceTool:GetLayerParent(moho, layer) if not layer then layer = moho.layer end local scriptInfo = layer:ScriptData() local currentSrcUUID = scriptInfo:GetString(self.srcKeyName) if not currentSrcUUID or currentSrcUUID == '' then return nil end for i, nextLayer in AE_Utilities:IterateAllLayers(moho) do if nextLayer:UUID() == currentSrcUUID then local path = AE_Utilities:GetLayerRelativePath(moho, layer, nextLayer) scriptInfo:Set(self.srcPathKeyName, path) return nextLayer end end local path = scriptInfo:GetString(self.srcPathKeyName) local pathLayer = AE_Utilities:GetLayerFromRelativePath(moho, layer, path) if pathLayer then scriptInfo:Set(self.srcKeyName, pathLayer:UUID()) return pathLayer end return nil end function AE_MeshinstanceTool:GetNewParent(moho) if not moho.document:CountSelectedLayers()==2 then return nil end for i, nextLayer in AE_Utilities:IterateAllLayers(moho) do if nextLayer:SecondarySelection() and nextLayer ~= moho.layer then return nextLayer end end return nil end function AE_MeshinstanceTool:ReplaceChannel(moho, channel, srcChannel) local derChannel = AE_Utilities:GetDerivedChannel(moho, channel) local derSrcChannel = AE_Utilities:GetDerivedChannel(moho, srcChannel) derChannel:Clear() for k=0, derSrcChannel:CountKeys()-1 do local value = derSrcChannel:GetValueByID(k) local when = derSrcChannel:GetKeyWhen(k) local interp = MOHO.InterpSetting:new_local() derSrcChannel:GetKeyInterpByID(k, interp) derChannel:SetValue(when, value) derChannel:SetKeyInterp(when, interp) end end function AE_MeshinstanceTool:TurnScriptOn(moho, layer, scriptPath) local scriptInfo = layer:ScriptData() if scriptInfo:HasKey(self.srcKeyName) then layer:SetLayerScript(scriptPath) --print("script turned on for ", layer:Name()) end end function AE_MeshinstanceTool:TurnScriptOff(moho, layer) if self:IsScriptOn(moho,layer) then layer:SetLayerScript(nil) --print("script turned off for ", layer:Name()) local scriptInfo = layer:ScriptData() if scriptInfo:HasKey(self.srcKeyName) then local srcUUID = scriptInfo:GetString(self.srcKeyName) local srcLayer = AE_Utilities:GetLayerByUUID(moho, srcUUID) if srcLayer then for subID, chID, channel, chInfo in AE_Utilities:IterateAllChannels(moho, layer) do if not chInfo.selectionBased then if chInfo.channelID == CHANNEL_CURVE or chInfo.channelID == CHANNEL_POINT then local srcChInfo = MOHO.MohoLayerChannel:new_local() srcLayer:GetChannelInfo(chID, srcChInfo) local srcChannel = srcLayer:Channel(chID, subID, moho.document) if not srcChannel then return end self:ReplaceChannel(moho, channel, srcChannel) for a=0, srcChannel:CountActions()-1 do if srcChannel:Action(a):Duration() > 0 then local actionName = srcChannel:ActionName(a) local actChannel = channel:ActionByName(actionName) if not actChannel then channel:ActivateAction(actionName) actChannel = channel:ActionByName(actionName) end self:ReplaceChannel(moho, actChannel, srcChannel:Action(a)) end end end end end end end end end function AE_MeshinstanceTool:IsScriptOn(moho, layer) local scriptPath = layer:LayerScript() if scriptPath and string.sub(scriptPath, -#self.scriptName) == self.scriptName then return true end return false end function AE_MeshinstanceTool:DuplicateLayer(moho, oldLayer, newLayer) if oldLayer:IsGroupType() then if not newLayer:IsGroupType() then return end oldLayer = moho:LayerAsGroup(oldLayer) newLayer = moho:LayerAsGroup(newLayer) if oldLayer:CountLayers() ~= newLayer:CountLayers() then return end for i=0, oldLayer:CountLayers()-1 do self:DuplicateLayer(moho, oldLayer:Layer(i), newLayer:Layer(i)) end else if not moho:LayerAsVector(oldLayer) or not moho:LayerAsVector(newLayer) then return end self:LinkLayers(moho, newLayer, oldLayer) --[[ newLayer:SetLocked(true) newLayer:SetLabelColor(-1) --]] end end function AE_MeshinstanceTool:CopyGroupStructure(moho, oldLayer, newLayer, oldRoot) if not oldRoot then oldRoot = oldLayer end if oldLayer:IsGroupType() then if not newLayer:IsGroupType() then return end oldLayer = moho:LayerAsGroup(oldLayer) newLayer = moho:LayerAsGroup(newLayer) if oldLayer:CountLayers() ~= newLayer:CountLayers() then return end for i=0, oldLayer:CountLayers()-1 do self:CopyGroupStructure(moho, oldLayer:Layer(i), newLayer:Layer(i), oldRoot) end else if not moho:LayerAsVector(oldLayer) or not moho:LayerAsVector(newLayer) then return end local oldParent = self:GetLayerParent(moho, oldLayer) if not oldParent then return end if not AE_Utilities:IsAncestor(oldRoot, oldParent) then return end local path = AE_Utilities:GetLayerRelativePath(moho, oldLayer, oldParent) local checkPath = AE_Utilities:GetLayerFromRelativePath(moho, oldLayer, path) if checkPath ~= oldParent then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, string.format("Have a problem with parenting %s to %s. Link will not be copied", oldLayer:Name(), oldParent:Name())) end local newParent = AE_Utilities:GetLayerFromRelativePath(moho, newLayer, path) if not newParent then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, string.format("Have a problem with parenting %s to %s. Link will not be copied", oldLayer:Name(), oldParent:Name())) end self:LinkLayers(moho, newLayer, newParent) end end
AE Meshinstance
Listed
Author: A.Evseeva
View Script
Script type: Tool
Uploaded: Feb 13 2021, 07:09
Last modified: Jul 29 2022, 12:03
Link mesh layers with ability to turn the link on and off
Movement of points and bezier handles are linked, actions and bone bindings are sinchronized, all the other channels are not linked. Meshes must have equal numbers of points and curve segments.Â
In "realtime" mode child layers carry layer script, put into project save folder. In "off" mode layers are not linked but can be sinchronized with button press.
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: 1290
AE Meshinstance
Listed
Author: A.Evseeva
View Script
Script type: Tool
Uploaded: Feb 13 2021, 07:09
Last modified: Jul 29 2022, 12:03
Link mesh layers with ability to turn the link on and off
Movement of points and bezier handles are linked, actions and bone bindings are sinchronized, all the other channels are not linked. Meshes must have equal numbers of points and curve segments.Â
In "realtime" mode child layers carry layer script, put into project save folder. In "off" mode layers are not linked but can be sinchronized with button press.
In "realtime" mode child layers carry layer script, put into project save folder. In "off" mode layers are not linked but can be sinchronized with button press.
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: 1290