-- -- Object Link manager -- @Author Gunnar Droege -- @Description An interface to the dotnet library to manage externally defined global linking -- global gRsLinkMgr global useMetaLinks = false struct sLinkState ( name, guid, asset, target, linkState, linkChannel = -1, sceneState = #unresolved, -- #resolved #resolvedByName #notSerialised fn ResolveInScene linkObj = ( name = linkObj.name guid = linkObj.guid.toString() asset = linkObj.ContentNode linkState = linkObj.StatusFlags target = ::RsGuidTools.GetObjByGuid guid if undefined!=target then ( sceneState = #resolved ) else ( -- optional name fallback local nameMatches = getNodeByName name all:true if nameMatches.count>0 then ( sceneState = #resolvedByName target = nameMatches[1] ) ) ) ) struct sObjChannelLinkStates ( linkChannel = -1, parent, children = #() ) struct RsObjLinkMgr ( dotnetMgr, --------------------------------- fn ResolveContainer obj = ( local map = RsMapObjectGetMapContainerFor obj if undefined==map then map = RsMapContainer name:"none" filename:(maxfilePath+maxFileName) return map ), public --------------------------------- fn SetContentTreeHelper CTreeHelper = ( print "setting contenttreehelper" dotnetMgr.CTreeHelper = CTreeHelper ), fn SetLog ulog = ( print "setting ulog" dotnetMgr.Log = ulog ), fn SetBranch branch = ( print ("setting branch to "+branch.Project.name as string+"|"+branch.name as string) dotnetMgr.Branch = branch ), fn printBranch = ( local branch = dotnetMgr.Branch print ("branch "+branch.Project.name as string+"|"+branch.name as string) ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Reset .Net cache ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn FlushCache deleteSceneLinks:true = ( if not useMetaLinks then return true print "Resetting link cache" local serialisedGuids = dotnetMgr.FlushEditedNodes() if deleteSceneLinks then ( progressstart "Deleting links' scene representation" local i=1 for guid in serialisedGuids while (RsMapProgress i serialisedGuids.count) do ( local sceneObj = ::RsGuidTools.GetObjByGuid (guid.toString()) if undefined!=sceneObj then ( RsSceneLink.RemoveContainer ::LinkType_ANY sceneObj ) i+=1 ) progressend() ) ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- forget viewport links ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn RemoveRsSceneLinks = ( local openContainers = RsMapGetMapContainers() for map in openContainers do ( editingNamespace = map.name print ("Deleting RsScene links on map \""+editingNamespace+"\"") progressStart ("Map \""+editingNamespace+"\" link deletion.") local objIndex = 1 for obj in map.objects while (RsMapProgress objIndex map.objects.count) do ( RsSceneLink.RemoveContainer ::LinkType_ANY obj objIndex += 1 ) progressEnd() ) ), fn GetLinkFile obj = ( local objGuid = RsGuidMgr.GetGuid obj if undefined!=objGuid then ( return (dotnetClass "RSG.ObjectLinks.MetaAssetResolver").GetMetaFilePath gRsBranch (::RsObjLinkFuncs.MakeGuid objGuid) ((dotnetclass "RSG.ObjectLinks.MetaTypes").MetaTypeLinks) ) return "" ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Save link from scene into meta files ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn SaveObjLinks obj map: = ( if not isValidnode obj then return false if map==unsupplied then map = ResolveContainer obj -- save out legacy scene stored linking for parentLinkType in RsSceneLink.GetNodeParentLinkTypes obj do ( local target = RsSceneLink.GetParent parentLinkType obj if undefined!=target then this.SetParent parentLinkType obj target sourcemap:map else RsSceneLink.RemoveContainer parentLinkType obj ) for childLinkType in RsSceneLink.GetNodeChildLinkTypes obj do ( local children = #() RsSceneLink.GetChildren childLinkType obj &children for child in children do ( if undefined!=child then this.SetParent childLinkType child obj targetmap:map ) ) ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Save all scene links from scene into meta files and delete .Net cache ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn SaveSceneLinks = ( -- Touching nodes print "Saving out links" local openContainers = RsMapGetMapContainers() local sceneObjs = objects as array for map in openContainers do ( editingNamespace = map.name progressStart ("Saving out links for map \""+editingNamespace as string+"\"") local objIndex = 0 for obj in map.objects while (RsMapProgress objIndex map.objects.count) do ( local kids = #() ::RsCollectChildren obj kids for k in kids do ( SaveObjLinks k map:map local sceneObjIndex = findItem sceneObjs k deleteItem sceneObjs sceneObjIndex ) objIndex += 1 ) progressEnd() ) -- we need to save out SOME sort of asset information. we can't resolve any objects in DCC if no assetpath is given and it's unlikely to be exported, too. if maxFilename!="" then ( progressStart ("Saving out mapless links") objIndex = 0 local maplessContainer = RsMapContainer \ name:(getFilenameFile maxFilename) \ filename:(maxFilePath + maxFilename) \ objects:sceneObjs for obj in sceneObjs where isValidNode obj while (RsMapProgress objIndex sceneObjs.count) do ( SaveObjLinks obj map:maplessContainer objIndex += 1 ) progressEnd() ) -- triggerng serialiation and cache reset FlushCache() gRsUlog.Validate() ), fn ResolveChannelObjStates obj channelObj = ( local channelStates = sObjChannelLinkStates linkChannel:channelObj.Channel.value__ local linkParent = channelObj.Parent if undefined!=linkParent then ( channelStates.parent = sLinkState linkChannel:channelObj.Channel.value__ channelStates.parent.ResolveInScene linkParent if channelStates.parent.sceneState != #unresolved then ( local res = RsSceneLink.Setparent channelStates.parent.linkChannel obj channelStates.parent.target ) ) local linkChildren = channelObj.Children local childEnum = linkChildren.GetEnumerator() while childEnum.MoveNext() do ( linkChild = childEnum.Current local linkState = sLinkState linkChannel:channelObj.Channel.value__ linkState.ResolveInScene linkChild if linkState.sceneState != #unresolved then ( local res = RsSceneLink.Setparent linkState.linkChannel linkState.target obj ) append channelStates.children linkState ) return channelStates ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Save scenes from scene into meta files and delete .Net cache ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn LoadObjLinks obj = ( local objectChannelStates = #() -- local now = (dotnetclass "DateTime").now local objGuid = RsGuidMgr.GetGuid obj if undefined==objGuid then return objectChannelStates -- now = (dotnetclass "DateTime").now local linkObj = dotnetMgr.Resolve (::RsObjLinkFuncs.MakeGuid objGuid) -- print ("Time for "+obj.name+" Container resolve: "+ ((dotnetclass "DateTime").now.subtract now).tostring()) -- now = (dotnetclass "DateTime").now if undefined!=linkObj then ( local chEnum = linkObj.Channels.GetEnumerator() while chEnum.MoveNext() do ( append objectChannelStates (ResolveChannelObjStates obj chEnum.Current) ) ) -- print ("loading time: "+ ((dotnetclass "DateTime").now.subtract now).tostring()) objectChannelStates ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- load all links from meta files into scene cache ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn LoadSceneLinks conts:(RsMapGetMapContainers()) = ( progressStart ("Loading links for map...") local objIndex = 0 for obj in objects while (RsMapProgress objIndex objects.count) do ( LoadObjLinks obj objIndex += 1 ) progressEnd() FlushCache deleteSceneLinks:false gRsUlog.Validate() ), fn SaveCallback = ( if not useMetaLinks then return true if (RsQueryBoxTimeOut "Save out ALL SceneLinks to metadata? This will delete all local links in max to avoid ambiguity on next load." timeout:10 defaultBtn:2) then ( SaveSceneLinks() ) else ( FlushCache() ) ), ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- accessors ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn SetParent linkChannel source target sourcemap: targetmap: = ( if not isValidNode source or not isValidNode target then ( print ("Either of the nodes is not a valid node to link: "+source as string+", "+target as string) return false ) if not RsSceneLink.SetParent linkChannel source target then ( print ("Linking failed for nodes "+source as string+" and "+target as string+" for channel "+linkChannel as string) return false ) if sourcemap==unsupplied then sourcemap = ResolveContainer source if targetmap==unsupplied then targetmap = ResolveContainer target -- we need all f these to link: if undefined == sourcemap or #none == sourcemap or undefined == sourcemap.filename or "" == sourcemap.filename or undefined == targetmap or #none == targetmap or undefined == targetmap.filename or "" == targetmap.filename then ( gRsUlog.LogWarning ("Didn't (re)link "+source as string+" and "+target as string+" due to missing map information.") context:#(source, target) return false ) local sourceGuid = (RsGuidMgr.GetGuid source) local targetGuid = (RsGuidMgr.GetGuid target) local sourceContentNode = (RsContentTree.getContentNode sourcemap.filename) local targetContentNode = (RsContentTree.getContentNode targetmap.filename) dotnetMgr.CTreeHelper = RsContentTree.ContentTreeHelper -- print ("Linking "+target as string+" to "+source as string+" on channel "+linkChannel as string+" with map "+map as string) dotnetMgr.Link \ linkChannel \ sourceContentNode sourceGuid (source.name) \ targetContentNode targetGuid (target.name) ), fn Unlink linkChannel source target:unsupplied map: = ( if map==unsupplied then map = ResolveContainer source local filename = map.filename local srcGuidStr = (RsGuidMgr.GetGuid source) RsSceneLink.RemoveContainer linkChannel source local trgGuidStr = "" if unsupplied!=target then ( trgGuidStr = (RsGuidMgr.GetGuid target) ) dotnetMgr.Unlink linkChannel srcGuidStr trgGuidStr return false ), fn GetChildren ch obj kids update:true = ( if useMetaLinks and update then LoadObjLinks obj RsSceneLink.GetChildren ch obj kids ), fn GetParents ch obj kids update:true = ( if useMetaLinks and update then LoadObjLinks obj RsSceneLink.GetParents ch obj kids ), fn GetParent ch obj update:true = ( if useMetaLinks and update then LoadObjLinks obj RsSceneLink.GetParent ch obj ), fn GetNodeChildLinkTypes obj update:true = ( if useMetaLinks and update then LoadObjLinks obj RsSceneLink.GetNodeChildLinkTypes obj ), fn GetNodeParentLinkTypes obj update:true = ( if useMetaLinks and update then LoadObjLinks obj RsSceneLink.GetNodeParentLinkTypes obj ), getChannelName = RsSceneLink.getChannelName ) filein "ObjectLink_funcs.ms"