public Node(GraphGrammarNode node, int index) : this() { this.AlphabetID = node.AlphabetID; this.Name = node.Name; this.Index = index; this.Terminal = node.Terminal; }
// Update symbol appearance. public void UpdateSymbol(GraphGrammarSymbol before, GraphGrammarSymbol after) { int symbolIndex = -1; GraphGrammarNode node = null; GraphGrammarConnection connection = null; if (before is GraphGrammarNode) { node = (GraphGrammarNode)after; symbolIndex = _nodes.FindIndex(x => x.Equals(before)); _nodes[symbolIndex].AlphabetID = node.AlphabetID; _nodes[symbolIndex].Terminal = node.Terminal; _nodes[symbolIndex].Name = node.Name; _nodes[symbolIndex].Abbreviation = node.Abbreviation; _nodes[symbolIndex].Description = node.Description; _nodes[symbolIndex].OutlineColor = node.OutlineColor; _nodes[symbolIndex].FilledColor = node.FilledColor; _nodes[symbolIndex].TextColor = node.TextColor; } else if (before is GraphGrammarConnection) { connection = (GraphGrammarConnection)after; symbolIndex = _connections.FindIndex(x => x.Equals(before)); _connections[symbolIndex].AlphabetID = connection.AlphabetID; _connections[symbolIndex].Name = connection.Name; _connections[symbolIndex].Description = connection.Description; _connections[symbolIndex].OutlineColor = connection.OutlineColor; _connections[symbolIndex].Requirement = connection.Requirement; _connections[symbolIndex].Arrow = connection.Arrow; } return; }
// Unserialize nodes private static List <Mission.GraphGrammarNode> UnserializeNodes(XElement element) { List <Mission.GraphGrammarNode> nodes = new List <Mission.GraphGrammarNode>(); XElement elementNodes = element.Element("Nodes"); foreach (var elementNode in elementNodes.Elements("Node")) { Mission.GraphGrammarNode node = new Mission.GraphGrammarNode(); node.ID = new Guid(elementNode.Attribute("id").Value); node.AlphabetID = new Guid(elementNode.Element("AlphabetID").Value); node.Ordering = System.Int32.Parse(elementNode.Element("Ordering").Value); node.Name = elementNode.Element("Name").Value; node.Abbreviation = elementNode.Element("Abbreviation").Value; node.Description = elementNode.Element("Description").Value; node.Terminal = (Mission.NodeTerminalType)Enum.Parse(typeof(Mission.NodeTerminalType), elementNode.Element("Terminal").Value); XElement elementScope = elementNode.Element("Scope"); node.OutlineScope = UnserializeRect(elementScope.Element("Outline")); node.FilledScope = UnserializeRect(elementScope.Element("Filled")); node.TextScope = UnserializeRect(elementScope.Element("Text")); XElement elementSymbolColor = elementNode.Element("SymbolColor"); node.OutlineColor = UnserializeColor(elementSymbolColor.Element("Outline")); node.FilledColor = UnserializeColor(elementSymbolColor.Element("Filled")); node.TextColor = UnserializeColor(elementSymbolColor.Element("Text")); nodes.Add(node); } return(nodes); }
public static void Initialize() { // Initial whole fields in window. _symbolName = string.Empty; _symbolAbbreviation = string.Empty; _symbolDescription = string.Empty; _symbolOutlineColor = Color.black; _symbolFilledColor = Color.white; _symbolTextColor = Color.black; _symbolTerminal = NodeTerminalType.Terminal; // Set the first values. _currentTab = AlphabetWindowTab.Nodes; _isInitTabButton = true; _editingMode = EditingMode.None; _scrollPosition = Vector2.zero; _messageHint = string.Empty; _messageType = MessageType.Info; _node = new GraphGrammarNode(NodeTerminalType.Terminal); _connection = new GraphGrammarConnection(); _symbolListCanvas = new Rect(0, 0, Screen.width, Screen.height); _symbolListCanvasInWindow = _symbolListCanvas; _symbolListArea = new Rect(0, 0, Screen.width, Screen.height); _centerPosition = new Vector2(Screen.width / 2, 75); _connectionType = ConnectionType.WeakRequirement; _connectionArrowType = ConnectionArrowType.Normal; // Revoke all. Alphabet.RevokeAllSelected(); }
// Update the information form another node, mostly reference is in Alphabet. public void UpdateSymbolInfo(GraphGrammarNode referenceNode) { _terminal = referenceNode.Terminal; _name = referenceNode.Name; _abbreviation = referenceNode.Abbreviation; _description = referenceNode.Description; _outlineColor = referenceNode.OutlineColor; _filledColor = referenceNode.FilledColor; _textColor = referenceNode.TextColor; }
// Same symbols in mission grammar will be updated in the same time when the alphabet updated. public static void OnAlphabetUpdated(GraphGrammarSymbol symbol) { GraphGrammarNode referenceNode = null; GraphGrammarConnection referenceConnection = null; if (symbol is GraphGrammarNode) { referenceNode = (GraphGrammarNode)symbol; foreach (var group in _groups) { foreach (var rule in group.Rules) { foreach (var node in rule.SourceRule.Nodes) { if (node.AlphabetID == referenceNode.AlphabetID) { node.UpdateSymbolInfo(referenceNode); } } foreach (var node in rule.ReplacementRule.Nodes) { if (node.AlphabetID == referenceNode.AlphabetID) { node.UpdateSymbolInfo(referenceNode); } } } } } else if (symbol is GraphGrammarConnection) { referenceConnection = (GraphGrammarConnection)symbol; foreach (var group in _groups) { foreach (var rule in group.Rules) { foreach (var connection in rule.SourceRule.Connections) { if (connection.AlphabetID == referenceConnection.AlphabetID) { connection.UpdateSymbolInfo(referenceConnection); } } foreach (var connection in rule.ReplacementRule.Connections) { if (connection.AlphabetID == referenceConnection.AlphabetID) { connection.UpdateSymbolInfo(referenceConnection); } } } } } }
// Return a boolean about it's abbreviation never be used in alphabet. public static bool IsNodeAbbreviationUsed(GraphGrammarNode currentNode) { if (currentNode == null) { return(false); } return((from node in Alphabet.Nodes where node.Abbreviation == currentNode.Abbreviation && node != Alphabet.SelectedNode select node) .Any()); }
// Draw the node in the node list. public static void DrawNodeInList(GraphGrammarNode node) { node.PositionX = 30; node.PositionY = 25 + 50 * _nodes.FindIndex(n => n == node); // Background color of selectable area. Color rectColor = SampleStyle.ColorBlue; rectColor.a = 0.75f; EditorCanvas.DrawQuad(new Rect(5, node.PositionY - 23, Screen.width - 8, 46), node.Selected ? rectColor : Color.clear); // Draw this node. node.Draw(); }
// Refresh the fields when select any symbol. void UpdateFields(GraphGrammarNode node) { _symbolTerminal = node.Terminal; _symbolName = node.Name; _symbolAbbreviation = node.Abbreviation; _symbolDescription = node.Description; _symbolOutlineColor = node.OutlineColor; _symbolFilledColor = node.FilledColor; _symbolTextColor = node.TextColor; // Repaint the window. Repaint(); }
// Add a new node from another exist node. public GraphGrammarNode AddNode(GraphGrammarNode nodeClone) { RevokeAllSelected(); // Deep copy. GraphGrammarNode node = new GraphGrammarNode(nodeClone); node.Ordering = _nodes.Count + 1; node.Selected = true; _nodes.Add(node); // Update the current node. _selectedSymbol = node; return(node); }
// Add a new node. public void AddNode() { // Revoke all symbols first. RevokeAllSelected(); // Create a new node and update its ordering and selected status. GraphGrammarNode node = new GraphGrammarNode(NodeTerminalType.NonTerminal); node.Ordering = _nodes.Count + 1; node.Selected = true; _nodes.Add(node); // Update the current node. _selectedSymbol = node; return; }
// Buttons about adding new symbol, modifying and deleting. void LayoutEditingModeButtonGroup() { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(Languages.GetText("MissionAlphabet-AddNew"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Left, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight)) { // Switch the mode. _editingMode = EditingMode.Create; // Initial the preview node and connection. _node = new GraphGrammarNode(); _connection = new GraphGrammarConnection(); // Initial all fields and repaint. Alphabet.RevokeAllSelected(); InitFields(); Repaint(); } switch (_currentTab) { case AlphabetWindowTab.Nodes: EditorGUI.BeginDisabledGroup(Alphabet.SelectedNode == null || Alphabet.IsAnyNode(Alphabet.SelectedNode.AlphabetID)); break; case AlphabetWindowTab.Connections: EditorGUI.BeginDisabledGroup(Alphabet.SelectedConnection == null); break; } if (GUILayout.Button(Languages.GetText("MissionAlphabet-Modify"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Mid, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight)) { // Switch the mode. _editingMode = EditingMode.Modify; } if (GUILayout.Button(Languages.GetText("MissionAlphabet-Delete"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Right, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight)) { // Switch the mode. _editingMode = EditingMode.Delete; // Remove the node or connection from alphabet and repaint. switch (_currentTab) { case AlphabetWindowTab.Nodes: Alphabet.RemoveNode(Alphabet.SelectedNode); break; case AlphabetWindowTab.Connections: Alphabet.RemoveConnection(Alphabet.SelectedConnection); break; } Repaint(); } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndHorizontal(); }
// Basic construction. public GraphGrammarConnection() : base() { this._alphabetID = Guid.NewGuid(); this._type = SymbolType.Connection; this._name = string.Empty; this._description = string.Empty; this._requirement = ConnectionType.WeakRequirement; this._arrow = ConnectionArrowType.Normal; this._startpointScope = new Rect(0, 0, this._pointScopeSize, this._pointScopeSize); this._endpointScope = new Rect(100, 100, this._pointScopeSize, this._pointScopeSize); this._outlineColor = Color.black; this._startpointStickyOn = null; this._endpointStickyOn = null; }
// Update the node information from the current field values. void UpdateNode(GraphGrammarNode node) { if (node == null) { return; } node.Terminal = _symbolTerminal; node.Name = _symbolName; node.Abbreviation = _symbolAbbreviation; node.Description = _symbolDescription; node.OutlineColor = _symbolOutlineColor; node.FilledColor = _symbolFilledColor; node.TextColor = _symbolTextColor; // Repaint the window. Repaint(); }
// Clone construction for basic informations. public GraphGrammarConnection(GraphGrammarConnection connection) { // Generate new symbol ID, but use same alphabet ID. this._symbolID = Guid.NewGuid(); this._alphabetID = connection.AlphabetID; // Basic information to copy. this._type = SymbolType.Connection; this._name = connection.Name; this._description = connection.Description; this._requirement = connection.Requirement; this._arrow = connection.Arrow; this._startpointScope = connection.StartpointScope; this._endpointScope = connection.EndpointScope; this._outlineColor = connection.OutlineColor; this._startpointStickyOn = null; this._endpointStickyOn = null; }
// Add node and connection to graph grammar by dfs. // "layer" is used to calculate x position private static void RecursionGraphGrammar(Node node, ref GraphGrammar graphGrammar, int layer) { if (CountInLayer.Count <= layer) { CountInLayer.Add(0); } // Mark this node. node.Explored = true; // "index" is used to calculate y position. int index = 0; foreach (Node edgeNode in node.Children) { // Add connection (Now only use Connections[0], will modify). Node childNode = edgeNode.Children[0]; var connection = new GraphGrammarConnection(Alphabet.Connections.Find(c => c.AlphabetID == edgeNode.AlphabetID)); graphGrammar.Connections.Add(connection); // Set starting sticked attribute. _nodeMappingTable[node].AddStickiedConnection(connection, "start"); connection.StartpointStickyOn = _nodeMappingTable[node]; connection.StartPosition = _nodeMappingTable[node].Position; // If mapping table have not contained this Node then add it. if (!_nodeMappingTable.ContainsKey(childNode)) { // Set position. _nodeMappingTable[childNode] = new GraphGrammarNode(_referenceNodeTable[childNode.AlphabetID]) { Position = new Vector2(LEFT_TOP_POSITION.x + layer * PADDING, LEFT_TOP_POSITION.y + (CountInLayer[layer] + index) * PADDING) }; graphGrammar.Nodes.Add(_nodeMappingTable[childNode]); } // Set ending sticked attribute. _nodeMappingTable[childNode].AddStickiedConnection(connection, "end"); connection.EndpointStickyOn = _nodeMappingTable[childNode]; connection.EndPosition = _nodeMappingTable[childNode].Position; // Check the mark exist. if (!childNode.Explored) { // Search deeper, so "layer" must increase. RecursionGraphGrammar(childNode, ref graphGrammar, layer + 1); } index++; } CountInLayer[layer] += index; }
// Initialization. public static void Initial() { _nodes = new List <GraphGrammarNode>() { new GraphGrammarNode("any", "?", "System default.", NodeTerminalType.Terminal), new GraphGrammarNode("none", "none", "System default.", NodeTerminalType.Terminal), new GraphGrammarNode("entrance", "en", "System default.", NodeTerminalType.Terminal), new GraphGrammarNode("goal", "go", "System default.", NodeTerminalType.Terminal), }; _connections = new List <GraphGrammarConnection>() { new GraphGrammarConnection("Weak requirement", "System default.", ConnectionType.WeakRequirement, ConnectionArrowType.Normal), new GraphGrammarConnection("Strong requirement", "System default.", ConnectionType.StrongRequirement, ConnectionArrowType.Double), new GraphGrammarConnection("Inhibition", "System default.", ConnectionType.Inhibition, ConnectionArrowType.WithCircle), }; _anyNode = _nodes[0]; _startingNode = _nodes[1]; _defaultNode = _nodes[1]; }
// Clone construction for basic informations. public GraphGrammarNode(GraphGrammarNode node) { // Generate new symbol ID, but use same alphabet ID. this._symbolID = Guid.NewGuid(); this._alphabetID = node.AlphabetID; // Basic information to copy. this._type = SymbolType.Node; this._name = node.Name; this._abbreviation = node.Abbreviation; this._description = node.Description; this._terminal = node.Terminal; this._outlineScope = node.OutlineScope; this._filledScope = node.FilledScope; this._textScope = node.TextScope; this._outlineColor = node.OutlineColor; this._filledColor = node.FilledColor; this._textColor = node.TextColor; // Keep it empty. this._stickiedConnections = new List <StickiedConnection>(); }
// Export the original structure from tree structure to canvas. public static GraphGrammar TransformFromGraph() { var graphGrammar = new GraphGrammar(); // Get reference table (For getting the symbol of Alphabet.) _referenceNodeTable = Alphabet.ReferenceNodeTable; // _referenceConnectionTable = Alphabet.ReferenceConnectionTable; // Initialize mapping table. _nodeMappingTable = new Dictionary <Node, GraphGrammarNode>(); // Add root node. _nodeMappingTable[_root] = new GraphGrammarNode(_referenceNodeTable[_root.AlphabetID]) { Position = LEFT_TOP_POSITION }; graphGrammar.Nodes.Add(_nodeMappingTable[_root]); CountInLayer.Clear(); CountInLayer.Add(0); RecursionGraphGrammar(_root, ref graphGrammar, 1); ClearExplored(_root); ResultGraph = graphGrammar; return(graphGrammar); }
// No 7. CyclicLink. private static bool ValidateCyclicLink(MissionRule rule, GraphGrammar graphGrammar) { // Store the parents and children to avoid the repeat call method. Dictionary <GraphGrammarNode, List <GraphGrammarNode> > parentsTable = new Dictionary <GraphGrammarNode, List <GraphGrammarNode> >(); Dictionary <GraphGrammarNode, List <GraphGrammarNode> > childrenTable = new Dictionary <GraphGrammarNode, List <GraphGrammarNode> >(); foreach (var node in graphGrammar.Nodes) { parentsTable[node] = node.Parents; childrenTable[node] = node.Children; } // Kahn's Algorithm // Array that record the removed edges. bool[,] _usedEdge = new bool[graphGrammar.Nodes.Count, graphGrammar.Nodes.Count]; // Non-indegree queue. Queue <GraphGrammarNode> nonIndegree = new Queue <GraphGrammarNode>(); // Push non-indegree node to queue. foreach (var node in graphGrammar.Nodes.FindAll(x => parentsTable[x].Count == 0 && // children can not be node itself. (!childrenTable[x].Exists(p => p.Ordering == x.Ordering)))) { nonIndegree.Enqueue(node); } // Bfs. while (nonIndegree.Count > 0) { // Pop. GraphGrammarNode popNode = nonIndegree.Dequeue(); // Remove the edge between this node and children node. foreach (var childNode in childrenTable[popNode]) { // Remove edge. _usedEdge[popNode.Ordering - 1, childNode.Ordering - 1] = true; // Check this child if it is non-indegree or not. bool hasInput = false; foreach (var parentNode in parentsTable[childNode]) { if (!_usedEdge[parentNode.Ordering - 1, childNode.Ordering - 1]) { hasInput = true; break; } } // If it is non-indegree then push it. if (!hasInput) { nonIndegree.Enqueue(childNode); } } } // Return false when any edge exist. It represents that this is a cyclic link. foreach (var node in graphGrammar.Nodes) { foreach (var childNode in childrenTable[node]) { if (!_usedEdge[node.Ordering - 1, childNode.Ordering - 1]) { return(false); } } } // Otherwise, this is not cyclic link. return(true); }
// Remove one node. public static void RemoveNode(GraphGrammarNode node) { _nodes.Remove(node); }
public Node(GraphGrammarNode node) : this() { this.AlphabetID = node.AlphabetID; this.Name = node.Name; this.Terminal = node.Terminal; }
public GraphGrammarConnection GetConnectionByNode(GraphGrammarNode node1, GraphGrammarNode node2) { return(_connections.Find(c => ((c.StartpointStickyOn.ID == node1.ID && c.EndpointStickyOn.ID == node2.ID) || c.EndpointStickyOn.ID == node1.ID && c.StartpointStickyOn.ID == node2.ID))); }
// Add a new node. public static void AddNode(GraphGrammarNode node) { _nodes.Add(node); }