/// <summary> /// Load circuit templates stored in an external file</summary> /// <param name="uri">Document URI, or null to present file open dialog to user</param> /// <returns>Returns the file path used to load the external templates. /// An empty string indicates no templates were loaded</returns> protected override ImportedContent LoadExternalTemplateLibrary(Uri uri) { string filePath = string.Empty; if (uri == null) { var dlg = new OpenFileDialog(); dlg.Filter = "Script Template File (*.vscript)|*.vscript".Localize(); dlg.CheckFileExists = true; if (dlg.ShowDialog() == DialogResult.OK) { uri = new Uri(dlg.FileName, UriKind.RelativeOrAbsolute); filePath = dlg.FileName; } } else { filePath = uri.LocalPath; } if (File.Exists(filePath)) { if (TemplatingContext.ValidateNewFolderUri(uri)) { // read existing document using standard XML reader using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var reader = new ScriptReader(m_nodeDefinitionManager.NodeTypeManager); var root = reader.Read(stream, uri); var toFolder = CreateTemplateFolder(); reader.ImportTemplates(toFolder.DomNode, root, uri); return(new ImportedContent(toFolder.DomNode, uri)); } } } return(new ImportedContent(null, null)); }
/// <summary> /// Rescan all referenced template documents </summary> protected override void ReloadExternalTemplates() { // 1st, scan the template hierarchy tree and remember all the existing template's guid -> DomNode map var oldNodeGuidDictionary = new Dictionary <string, DomNode>(); foreach (var node in TemplatingContext.RootFolder.DomNode.Subtree) { if (node.Is <ScriptTemplate>()) { var template = node.Cast <ScriptTemplate>(); if (template.Guid != Guid.Empty) { oldNodeGuidDictionary[template.Guid.ToString()] = node; } } } // 2nd, scan the template hierarchy tree again and reload all the external templates var newNodeGuidDictionary = new Dictionary <string, DomNode>(); foreach (var node in TemplatingContext.RootFolder.DomNode.Subtree) { var templateFolder = node.As <Sce.Atf.Dom.TemplateFolder>(); if (templateFolder == null || templateFolder.Url == null) { continue; } if (File.Exists(templateFolder.Url.LocalPath)) { using (FileStream stream = new FileStream(templateFolder.Url.LocalPath, FileMode.Open, FileAccess.Read)) { var reader = new ScriptReader(m_nodeDefinitionManager.NodeTypeManager); var rootNode = reader.Read(stream, templateFolder.Url); foreach (var newnode in rootNode.Subtree) { var guidAttr = newnode.Type.GetAttributeInfo("guid"); if (guidAttr == null) { continue; } var guidStr = newnode.GetAttribute(guidAttr) as string; if (!string.IsNullOrEmpty(guidStr)) { newNodeGuidDictionary[guidStr] = newnode; } } reader.ImportTemplates(templateFolder.DomNode, rootNode, templateFolder.Url); } } } // 3rd, replace original nodes with newly loaded, matched by GUIDs foreach (var node in TemplatingContext.RootFolder.DomNode.GetRoot().Subtree) { // currently two types that reference templates: GroupInstance or ModuleInstance DomNode refNode; var groupInstance = node.As <VisualScript.ScriptGroupReference>(); if (groupInstance != null) { if (newNodeGuidDictionary.TryGetValue(groupInstance.Template.Guid.ToString(), out refNode)) { groupInstance.Template = refNode.As <ScriptTemplate>(); // need to reset pin targets due to DomNode replacements var graphContainer = groupInstance.DomNode.Parent.Cast <ICircuitContainer>(); foreach (var edge in graphContainer.Wires) { if (edge.OutputElement.DomNode == groupInstance.DomNode) { edge.OutputPinTarget = null; } if (edge.InputElement.DomNode == groupInstance.DomNode) { edge.InputPinTarget = null; } } continue; } } var moduleReference = node.As <ScriptNodeReference>(); if (moduleReference != null) { if (newNodeGuidDictionary.TryGetValue(moduleReference.Template.Guid.ToString(), out refNode)) { moduleReference.Template = refNode.As <ScriptTemplate>(); // need to reset pin targets due to DomNode replacements var graphContainer = moduleReference.DomNode.Parent.Cast <ICircuitContainer>(); foreach (var edge in graphContainer.Wires) { if (edge.OutputElement.DomNode == moduleReference.DomNode) { edge.OutputPinTarget = null; } if (edge.InputElement.DomNode == moduleReference.DomNode) { edge.InputPinTarget = null; } } } } } // finally, prune the old nodes foreach (var keyValue in newNodeGuidDictionary) { DomNode oldNode; if (oldNodeGuidDictionary.TryGetValue(keyValue.Key, out oldNode)) { oldNode.RemoveFromParent(); } } }