/// <summary> /// Load function that unpacks <see cref="Rule"/> from corresponding <see cref="SerializedProperty"/>. /// </summary> private void LoadRule(bool inSet) { if (inSet) { string setName = SubjectRule.propertyPath.Remove(SubjectRule.propertyPath.IndexOf(".Array")).Replace("Profile.", ""); int ruleIndex = int.Parse(SubjectRule.propertyPath.Substring(SubjectRule.propertyPath.IndexOf("[") + 1).Replace("]", "")); deserializedRule = RuleSystemUtil.DeserializeRule(SubjectRule, setName, ruleIndex); } else { deserializedRule = RuleSystemUtil.DeserializeRule(SubjectRule); } rootNode = RuleCreator.CreateRoot(deserializedRule.RootGridPosition, OnNodePortContact, OnUpdateRootRequest, OnRemoveAThread, deserializedRule.MandatoryId, deserializedRule.QualityId, deserializedRule.MyAction, NodeSkin); if (deserializedRule.MyAction != null) { actionNode = RuleCreator.CreateActionNode(deserializedRule.ActionGridPosition, OnNodePortContact, OnUpdateActionRequest, OnRemoveNode, OnRemoveAThread, deserializedRule.MyAction, NodeSkin); } foreach (Decision decision in deserializedRule.MyDecisions) { ruleDecisions.Add(decision); NodeShell rawNode = RuleCreator.CreateNewDecisionNode(decision.identifier, decision.Operator, OnUpdateRuleRequest, OnNodePortContact, OnRemoveNode, OnRemoveAThread, NodeSkin); rawNode.Container = new NodeShell.Data { FloatValue = decision.FlatValue }; rawNode.Inputs = decision.inputID; rawNode.Rect.position = decision.GridPosition; rawNode.activated = true; ruleNodes.Add(rawNode); } }
/// <summary> /// Action-event handles <see cref="NodeShell"/> instantiation. Used specificly for <see cref="Decision"/> nodes. /// </summary> /// <param name="statement"><see cref="Statement"/> requesting node. </param> private void OnRequestDecisionNode(Statement statement) { createdDecision = new Decision(); createdDecision.identifier = GenerateDecisionId(); createdDecision.Operator = statement; createdNode = RuleCreator.CreateNewDecisionNode(createdDecision.identifier, statement, OnUpdateRuleRequest, OnNodePortContact, OnRemoveNode, OnRemoveAThread, NodeSkin); createdNode.Rect.position = mousePos; }
/// <summary> /// Event handle for nodes that are being created. /// </summary> /// <param name="e">Current Unity Event. </param> private void ProcessCreatedNode(Event e) { if (createdNode != null) { createdNode.Rect.position = e.mousePosition; createdNode.Draw(); switch (e.type) { case EventType.MouseUp: if (e.button == 0) { if (createdNode != null) { ruleDecisions.Add(createdDecision); ruleNodes.Add(createdNode); createdNode.activated = true; createdNode = null; createdDecision = null; } } else if (e.button == 1) { createdNode = null; } break; } } if (createdActionNode != null) { createdActionNode.Rect.position = e.mousePosition; createdActionNode.Draw(); switch (e.type) { case EventType.MouseUp: if (e.button == 0) { if (createdActionNode != null) { actionNode = createdActionNode; actionNode.activated = true; createdActionNode = null; } } else if (e.button == 1) { createdActionNode = null; } break; } } }
/// <summary> /// Action-event handles <see cref="NodeShell"/> remove from rule requests. /// </summary> /// <param name="node">Node that requests to be removed.</param> private void OnRemoveNode(NodeShell node) { if (ruleNodes.Remove(node)) { var decision = GetDecisionById(node.Id); ruleDecisions.Remove(decision); for (int i = Yarn.Count - 1; i > 0; i--) { if (Yarn[i].inputPort.MyNode == node || Yarn[i].outputPort.MyNode == node) { OnRemoveAThread(Yarn[i]); } } } else if (actionNode == node) { actionNode = null; } }
/// <summary> /// Swiches decision nodes existing style. /// </summary> /// <param name="statement"></param> /// <param name="node"></param> public static void ChangeStyle(Statement statement, ref NodeShell node) { switch (statement.Type) { case StatementType.unknown: break; case StatementType.Inequality: case StatementType.Gate: node.Style = new BoolNodeStyle(statement.Name, statement.Type); break; case StatementType.Generator: if (statement.GetType() == typeof(FlatValueStatement)) node.Style = new GenNodeStyle("Flat Value"); break; case StatementType.Mutator: break; case StatementType.Evaluation: break; } }
/// <summary> /// Creates established threads from deserialized Rule. /// </summary> private void LoadThreads() { if (rootNode.MandatoryID != -1) { NodeShell mandatory = GetNodeById(rootNode.MandatoryID); Thread rootThread = new Thread(rootNode.Port0, mandatory.Port1); rootNode.Port0.Connections.Add(rootThread); } if (rootNode.QualityID != -1) { NodeShell Quality = GetNodeById(rootNode.QualityID); Thread qualityThread = new Thread(rootNode.Port1, Quality.Port1); rootNode.Port1.Connections.Add(qualityThread); } rootNode.activated = true; if (actionNode != null) { Thread actionThread = new Thread(rootNode.Port2, actionNode.Port0); rootNode.Port2.Connections.Add(actionThread); actionNode.activated = true; } foreach (NodeShell node in ruleNodes) { if (node.Inputs.Length > 0) { foreach (int inputId in node.Inputs) { NodeShell output = GetNodeById(inputId); Thread thread = new Thread(node.Port0, output.Port1); node.Port0.Connections.Add(thread); Yarn.Add(thread); } } } }
/// <summary> /// Creates a node (specificly used for <see cref="Decision"/> nodes). /// </summary> /// <param name="id">Decision identifier. </param> /// <param name="statement">Decision asset represented by this node. </param> /// <param name="OnRuleUpdate">Event-handle for updating <see cref="Decision"/> data. </param> /// <param name="OnPortClick">Event-handle for <see cref="Port"/> clicks. </param> /// <param name="OnRemoveNode">Event-handle for removing this node. </param>> /// <param name="skin"><see cref="GUISkin"/> of nodes. </param> /// <returns></returns> public static NodeShell CreateNewDecisionNode(int id, Statement statement, Action<int, Statement, int[], NodeShell.Data, Vector2> OnRuleUpdate, Action<Port> OnPortClick, Action<NodeShell> OnRemoveNode, Action<Thread> OnRemoveThread, GUISkin skin) { NodeShell crNode = new NodeShell { Id = id, Asset = statement, Inputs = new int[0], Container = new NodeShell.Data(), Skin = skin, OnUpdateRule = OnRuleUpdate, OnRemoveNode = OnRemoveNode }; switch (statement.Type) { case StatementType.unknown: break; case StatementType.Inequality: case StatementType.Gate: BoolNodeStyle boolStyle = new BoolNodeStyle(statement.Name, statement.Type); crNode.Style = boolStyle; crNode.Rect = boolStyle.Rect; crNode.CurrentExpanedHeight = boolStyle.MinExpandedHeight; crNode.Port0 = new Port { type = PortType.Input, Name = statement.Name, MyNode = crNode, nodeSkin = skin, OnClickPort = OnPortClick, OnRemoveThread = OnRemoveThread, rect = new Rect(0, 0, skin.button.fixedWidth, skin.button.fixedHeight), isDecision = true }; break; case StatementType.Generator: GenNodeStyle genStyle = new GenNodeStyle("FlatValue"); crNode.Style = genStyle; crNode.Rect = genStyle.Rect; crNode.CurrentExpanedHeight = genStyle.MinExpandedHeight; break; case StatementType.Mutator: MutNodeStyle mutStyle = new MutNodeStyle(statement.Name); crNode.Style = mutStyle; crNode.Rect = mutStyle.Rect; crNode.CurrentExpanedHeight = mutStyle.MinExpandedHeight; crNode.Port0 = new Port { type = PortType.Input, Name = statement.Name, MyNode = crNode, nodeSkin = skin, OnClickPort = OnPortClick, OnRemoveThread = OnRemoveThread, rect = new Rect(0, 0, skin.button.fixedWidth, skin.button.fixedHeight), isDecision = true }; break; case StatementType.Evaluation: EvNodeStyle evStyle = new EvNodeStyle(statement.name); crNode.Style = evStyle; crNode.Rect = evStyle.Rect; crNode.CurrentExpanedHeight = evStyle.MinExpandedHeight; break; } crNode.Port1 = new Port { Name = statement.Name, type = PortType.Output, MyNode = crNode, nodeSkin = skin, Color = crNode.Style.Color, OnClickPort = OnPortClick, OnRemoveThread = OnRemoveThread, rect = new Rect(0, 0, skin.button.fixedWidth, skin.button.fixedHeight), isDecision = true }; return crNode; }