public override string GenerateCode() { if (condition != null && condition.isAssigned) { string data = CodeGenerator.ParseValue((object)condition); if (!string.IsNullOrEmpty(data)) { if (CodeGenerator.debugScript || CodeGenerator.CanReturnState(this)) { return(CodeGenerator.GenerateIfStatement(data, CodeGenerator.GetFinishCode(this, true, true, false, onTrue, onFinished), CodeGenerator.GetFinishCode(this, false, true, false, onFalse, onFinished))); } if (onTrue.isAssigned) { if (onFalse.isAssigned) { data = CodeGenerator.GenerateIfStatement(data, CodeGenerator.GenerateFlowCode(onTrue, this)); string failure = CodeGenerator.GenerateFlowCode(onFalse, this); if (!string.IsNullOrEmpty(failure)) { var flag = onFalse.targetType == MemberData.TargetType.FlowNode && onFalse.GetTargetNode() is NodeIf && !(onFalse.GetTargetNode() as NodeIf).onFinished.isAssigned; if (flag && CodeGenerator.IsGroupedNode(this)) { data += " else " + failure.RemoveLineAndTabOnFirst(); } else { data += " else {" + failure.AddLineInFirst().AddTabAfterNewLine(1) + "\n}"; } } } else { data = CodeGenerator.GenerateIfStatement(data, CodeGenerator.GenerateFlowCode(onTrue, this)); } data += CodeGenerator.GetFinishCode(this, true, false, false, onFinished).AddLineInFirst(); return(data); } else if (onFalse.isAssigned) { return (CodeGenerator.GenerateIfStatement( data.AddFirst("!(").Add(")"), CodeGenerator.GenerateFlowCode(onFalse, this)) + CodeGenerator.GetFinishCode(this, false, true, false, onFinished).AddLineInFirst()); } return (CodeGenerator.GenerateIfStatement(data, "") + CodeGenerator.GetFinishCode(this, true, false, false, onFinished).AddLineInFirst()); } else { throw new Exception("Condition generates empty code"); } } throw new System.Exception("Unassigned condition"); }
public bool AddNodeTree(MemberData member, TreeViewItem parentTree, IList <TreeViewItem> rows, bool isChildren = true) { if (member.isAssigned && member.IsTargetingPinOrNode) { if (member.targetType == MemberData.TargetType.FlowNode) { Node n = member.GetTargetNode(); if (n != null) { AddNodes(n, parentTree, rows, isChildren); return(true); } } else if (member.targetType == MemberData.TargetType.FlowInput) { Node n = member.GetTargetNode(); var flow = member.Invoke(null) as FlowInput; if (n != null && flow != null) { bool flag = false; if (!flowPortsMap.TryGetValue(flow, out var flowTree)) { flag = true; flowTree = new HierarchyPortTree( n, flow, uNodeEditorUtility.GetUIDFromString($"{n.GetHashCode()}:FI={member.startName}"), -1, $"{n.GetNodeName()} ( {ObjectNames.NicifyVariableName(flow.name)} )") { icon = uNodeEditorUtility.GetTypeIcon(n.GetNodeIcon()) as Texture2D }; flowPortsMap[flow] = flowTree; } if (isChildren) { parentTree.AddChild(flowTree); } else { parentTree.parent.AddChild(flowTree); } rows.Add(flowTree); if (flag) { var drawer = HierarchyDrawer.FindDrawer(n.GetType()); drawer.manager = this; drawer.AddChildNodes(n, flowTree, rows); } return(true); } } } return(false); }
public bool CanAddTree(MemberData member) { if (member.isAssigned && member.IsTargetingPinOrNode) { if (member.targetType == MemberData.TargetType.FlowNode) { return(member.GetTargetNode() != null); } else if (member.targetType == MemberData.TargetType.FlowInput) { return(member.GetTargetNode() != null && member.Invoke(null) as FlowInput != null); } } return(false); }
public override void RegisterPort() { base.RegisterPort(); if (CodeGenerator.isGenerating) { //Register this node as state node, because this is coroutine node with state. CodeGenerator.RegisterAsStateNode(this); var node = targetNode.GetTargetNode(); if (node != null) { //Register each target node as state node, because this node need to compare the target state. CodeGenerator.RegisterAsStateNode(node); } } }
/// <summary> /// True if instance variable from node has used in flow nodes. /// </summary> /// <param name="from"></param> /// <param name="field"></param> /// <param name="index"></param> /// <param name="flows"></param> /// <returns></returns> public static bool NeedInstanceVariable(Node from, FieldInfo field, int index, IList <Node> flows) { if (from && flows != null && flows.Count > 0) { var allConnection = GetAllNode(from.transform.parent); var allFlows = new HashSet <NodeComponent>(); foreach (var flow in flows) { if (flow == null) { continue; } FindAllNodeConnection(flow, ref allFlows); } bool check = false; Func <object, bool> validation = null; validation = delegate(object obj) { if (obj is MemberData) { MemberData member = obj as MemberData; if (member.isAssigned) { Node n = member.GetTargetNode(); if (n) { int tes; if (member.targetType == MemberData.TargetType.NodeFieldElement && n == from && int.TryParse(member.startName.Split('#')[1], out tes) && tes == index && member.startName.Split('#')[0] == field.Name) { check = true; } else if (member.targetType == MemberData.TargetType.ValueNode) { AnalizerUtility.AnalizeObject(n, validation); } } } } return(check); }; foreach (Node node in allConnection) { if (node == null || !isInUngrouped && IsGroupedNode(from) /*&& allFlows.Contains(node)*/) { continue; } AnalizerUtility.AnalizeObject(node, validation); if (check) { var nodes = GetFlowConnectedTo(node); if (nodes.Count > 0) { return(nodes.Any(n => !allFlows.Contains(n))); } } } } return(false); }
public IEnumerator OnUpdate() { while (state == StateType.Running) { if (!targetNode.isAssigned) { Debug.LogError("Unassigned target node", this); Finish(); yield break; } Node n; if (canExecuteEvent && (RepeatForever || RepeatCount > repeatNumber)) { WaitUntil w; if (!targetNode.ActivateFlowNode(out n, out w)) { yield return(w); } repeatNumber++; canExecuteEvent = false; } else { n = targetNode.GetTargetNode(); } if (n.IsFinished()) { JumpStatement js = n.GetJumpState(); if (js != null) { if (js.jumpType == JumpStatementType.Continue) { continue; } else if (js.jumpType == JumpStatementType.Break) { Finish(); yield break; } jumpState = js; Finish(); yield break; } if (StopEventOnFailure && n.currentState == StateType.Failure) { Finish(); yield break; } if (!RepeatForever && RepeatCount <= repeatNumber) { Finish(); } canExecuteEvent = true; } yield return(null); } }
/// <summary> /// Return true of flow member is coroutine. /// </summary> /// <param name="member"></param> /// <returns></returns> protected bool HasCoroutineInFlow(MemberData member) { if (member != null && member.isAssigned) { var node = member.GetTargetNode(); if (node != null) { return(node.IsCoroutine()); } } return(false); }
public override bool IsCoroutine() { if (kind == PortKind.FlowInput && target.isAssigned) { var node = target.GetTargetNode(); if (node != null) { return(node.IsCoroutine()); } } return(base.IsCoroutine()); }
/// <summary> /// Get flow nodes from node. /// </summary> /// <param name="node"></param> /// <returns></returns> public static HashSet <NodeComponent> GetFlowConnection(NodeComponent node) { HashSet <NodeComponent> allNodes; if (generatorData.flowNodeConnectionsMap.TryGetValue(node, out allNodes)) { return(allNodes); } allNodes = new HashSet <NodeComponent>(); if (node is StateNode) { StateNode eventNode = node as StateNode; TransitionEvent[] TE = eventNode.GetTransitions(); foreach (TransitionEvent transition in TE) { if (transition.GetTargetNode() != null && !allNodes.Contains(transition.GetTargetNode())) { allNodes.Add(transition.GetTargetNode()); } } } Func <object, bool> validation = delegate(object obj) { if (obj is MemberData) { MemberData member = obj as MemberData; if (member != null && member.isAssigned && (member.targetType == MemberData.TargetType.FlowNode || member.targetType == MemberData.TargetType.FlowInput) && !allNodes.Contains(member.GetTargetNode())) { allNodes.Add(member.GetTargetNode()); } } return(false); }; AnalizerUtility.AnalizeObject(node, validation); generatorData.flowNodeConnectionsMap[node] = allNodes; return(allNodes); }
public static HashSet <NodeComponent> GetConnections(NodeComponent node) { HashSet <NodeComponent> allNodes; if (generatorData.nodeConnectionsMap.TryGetValue(node, out allNodes)) { return(allNodes); } allNodes = new HashSet <NodeComponent>(); if (node is StateNode) { StateNode eventNode = node as StateNode; TransitionEvent[] TE = eventNode.GetTransitions(); foreach (TransitionEvent transition in TE) { var tNode = transition.GetTargetNode(); if (tNode != null) { allNodes.Add(tNode); } } } else if (node is BaseEventNode) { BaseEventNode stateEvent = node as BaseEventNode; foreach (var member in stateEvent.GetFlows()) { var tNode = member.GetTargetNode(); if (tNode != null) { allNodes.Add(tNode); } } } Func <object, bool> validation = delegate(object obj) { if (obj is MemberData) { MemberData member = obj as MemberData; if (member != null && member.IsTargetingPinOrNode) { allNodes.Add(member.GetTargetNode()); } } return(false); }; AnalizerUtility.AnalizeObject(node, validation); generatorData.nodeConnectionsMap[node] = allNodes; return(allNodes); }
public static void RetargetValueNode(Node source, Node destination) { List <uNodeComponent> nodes = new List <uNodeComponent>(); foreach (Transform t in source.transform.parent) { var comp = t.GetComponent <uNodeComponent>(); if (comp != null) { if (comp is StateNode) { var state = comp as StateNode; var transitions = state.GetTransitions(); foreach (var tr in transitions) { nodes.Add(tr); } } nodes.Add(comp); } } Func <object, bool> validation = delegate(object o) { if (o is MemberData) { MemberData member = o as MemberData; if (member.targetType == MemberData.TargetType.ValueNode) { Node n = member.GetTargetNode(); if (n != null && n == source) { member.RefactorUnityObject(new Object[] { source }, new Object[] { destination }); //return true; } } } return(false); }; foreach (var n in nodes) { AnalizerUtility.AnalizeObject(n, validation); } }
private static void ConnectNode(NodeComponent node) { if (node != null && !generatorData.connectedNode.Contains(node)) { generatorData.connectedNode.Add(node); var nodes = GetConnections(node); if (nodes != null) { foreach (NodeComponent n in nodes) { if (n) { ConnectNode(n); } } } if (node is ISuperNode) { ISuperNode superNode = node as ISuperNode; foreach (var n in superNode.nestedFlowNodes) { if (n != null) { ConnectNode(n); } } } Func <object, bool> validation = delegate(object obj) { if (obj is MemberData) { MemberData member = obj as MemberData; if (member.IsTargetingPinOrNode) { ConnectNode(member.GetTargetNode()); } } return(false); }; AnalizerUtility.AnalizeObject(node, validation); } }
public static PortView GetOutputPort(MemberData inputValue, UGraphView graphView) { var outputNode = inputValue.GetTargetNode(); if (outputNode != null) { if (inputValue.IsTargetingNode) { switch (inputValue.targetType) { case MemberData.TargetType.FlowNode: return(GetSelfPort(outputNode, Orientation.Vertical, graphView)); case MemberData.TargetType.ValueNode: PortView port; if (graphView.portValueNodeAliases.TryGetValue(outputNode, out port) && port != null) { return(port); } return(GetSelfPort(outputNode, Orientation.Horizontal, graphView)); } } UNodeView nodeView; if (graphView.nodeViewsPerNode.TryGetValue(outputNode, out nodeView)) { foreach (var p in nodeView.outputPorts) { if (p.portData.portID == inputValue.startName) { return(p); } } } } return(null); }
public static HashSet <NodeComponent> GetFlowConnectedTo(Node target) { if (target != null) { if (generatorData.FlowConnectedTo.TryGetValue(target, out var comp)) { return(comp); } comp = new HashSet <NodeComponent>(); Node currNode = null; Func <object, bool> validation = delegate(object obj) { if (obj is MemberData) { MemberData member = obj as MemberData; Node targetNode = member.GetTargetNode(); if (targetNode == target) { if (member.targetType == MemberData.TargetType.FlowNode || member.targetType == MemberData.TargetType.FlowInput) { comp.Add(currNode); return(true); } else if (member.targetType == MemberData.TargetType.ValueNode || member.targetType == MemberData.TargetType.NodeField || member.targetType == MemberData.TargetType.NodeFieldElement) { var connectedNodes = GetFlowConnectedTo(currNode); if (connectedNodes != null) { foreach (var n in connectedNodes) { comp.Add(n); } } } } } return(false); }; foreach (Node node in generatorData.allNode) { if (target == node) { continue; } if (node is StateNode) { StateNode eventNode = node as StateNode; TransitionEvent[] TE = eventNode.GetTransitions(); foreach (TransitionEvent transition in TE) { if (transition != null && transition.GetTargetNode() == target) { comp.Add(node); break; } } } else if (node is IMacro) { IMacro macro = node as IMacro; var outputFlows = macro.OutputFlows; foreach (var flow in outputFlows) { if (flow != null && flow.target.GetTargetNode() == target) { comp.Add(node); break; } } } currNode = node; AnalizerUtility.AnalizeObject(node, validation); } foreach (EventNode method in generatorData.eventNodes) { if (method == null) { continue; } foreach (var flow in method.GetFlows()) { if (flow.GetTargetNode() == target) { comp.Add(method); break; } } } generatorData.FlowConnectedTo[target] = comp; return(comp); } return(null); }
/// <summary> /// Function for generating code for flow member. /// </summary> /// <param name="flowMember">The flow member</param> /// <param name="from">The node which flow member comes from</param> /// <param name="waitTarget">If true, will generate wait code on coroutine member.</param> /// <returns></returns> public static string GenerateFlowCode(MemberData flowMember, NodeComponent from, bool waitTarget = true) { if (flowMember == null) { return(null); } if (!flowMember.isAssigned) { return(null); } Node target = flowMember.GetTargetNode(); if (target == null) { return(null); } if (flowMember.targetType != MemberData.TargetType.FlowNode && flowMember.targetType != MemberData.TargetType.FlowInput) { throw new System.Exception("Incorrect target type : " + flowMember.targetType.ToString() + ", TargetType must FlowNode or FlowInput"); } if (flowMember.targetType != MemberData.TargetType.FlowInput && !target.IsFlowNode()) { throw new System.Exception("node is not flow node."); } string debug = null; if (setting.debugScript) { debug = GenerateDebugCode(flowMember).AddLineInEnd(); } if (flowMember.targetType == MemberData.TargetType.FlowNode) { if (!isInUngrouped && !uNodeUtility.IsInStateGraph(target) && !IsUngroupedNode(target)) { return(debug + GenerateNode(target)); } if (waitTarget && (isInUngrouped || from && from.IsSelfCoroutine() || allowYieldStatement && IsUngroupedNode(target))) { if (!generatorData.ungroupedNode.Contains(target)) { return(debug + GenerateNode(target)); } if (!allowYieldStatement) { throw new Exception("The current block doesn't allow coroutines / yield statements"); } return(debug + "yield return " + RunEvent(target)); } if (!isInUngrouped && generatorData.groupedNode.Contains(target)) { return(debug + GenerateNode(target)); } if (!generatorData.ungroupedNode.Contains(target)) { if (!allowYieldStatement && target.IsSelfCoroutine()) { throw new Exception("The current block doesn't allow coroutines / yield statements"); } throw new uNodeException($"Forbidden to generate state code because the node: {target.GetNodeName()} is not registered as State Node.\nEnsure to register it using {nameof(CodeGenerator)}.{nameof(CodeGenerator.RegisterAsStateNode)}", target); } return(debug + RunEvent(target)); } else { return(debug + GenerateFlowCode(flowMember.Invoke(null) as IFlowGenerate, target)); } // return debug + GetInvokeCode(_eventCode, false, generatorData.GetEventName(target)); }
/// <summary> /// Return true on flow body can be simplify to lambda expression code. /// </summary> /// <param name="target"></param> /// <param name="returnType"></param> /// <param name="parameterTypes"></param> /// <returns></returns> public static bool CanSimplifyToLambda(MemberData target, Type returnType, IList <Type> parameterTypes) { if (target.IsTargetingNode) { var bodyNode = target.GetTargetNode(); if (bodyNode is MultipurposeNode) { var node = bodyNode as MultipurposeNode; if (node.target.target.isAssigned && !node.onFinished.isAssigned) { System.Type[] memberTypes = null; if (node.target.target.targetType == MemberData.TargetType.Method) { var members = node.target.target.GetMembers(false); if (members != null && members.Length > 0) { var lastMember = members.LastOrDefault() as System.Reflection.MethodInfo; if (lastMember != null && lastMember.ReturnType == returnType) { memberTypes = lastMember.GetParameters().Select(i => i.ParameterType).ToArray(); } } } else if (node.target.target.targetType == MemberData.TargetType.uNodeFunction) { uNodeFunction func = node.target.target.GetUnityObject() as uNodeFunction; if (func != null && func.ReturnType() == returnType) { memberTypes = func.parameters.Select(i => i.Type).ToArray(); } } if (memberTypes != null) { if (parameterTypes.Count == memberTypes.Length && node.target.parameters.Length == memberTypes.Length) { bool flag = true; for (int x = 0; x < parameterTypes.Count; x++) { if (parameterTypes[x] != memberTypes[x]) { flag = false; break; } } if (flag) { for (int x = 0; x < parameterTypes.Count; x++) { var p = node.target.parameters[x]; if (p.targetType != MemberData.TargetType.NodeFieldElement || p.GetAccessIndex() != x) { flag = false; break; } } if (flag) { return(true); } } } } } } } return(false); }
/// <summary> /// Are the flow connection identifiead as coroutine? /// </summary> /// <param name="member"></param> /// <returns></returns> public static bool IsCoroutineFlow(MemberData member) { var node = member.GetTargetNode(); return(IsCoroutineFlow(node)); }
private string GenerateEventCodes() { if (!body.isAssigned) { return(null); } Type targetType = target.type; if (targetType == null) { return(null); } System.Type[] parameterTypes = null; if (targetType.IsCastableTo(typeof(Delegate))) { parameterTypes = targetType.GetMethod("Invoke").GetParameters().Select(i => i.ParameterType).ToArray(); if (CodeGenerator.IsGroupedNode(this) && CodeGenerator.CanSimplifyToLambda(body, targetType, parameterTypes)) { var bodyNode = body.GetTargetNode(); if (bodyNode as MultipurposeNode) { string result = bodyNode.GenerateValueCode(); if (result.EndsWith(")")) { int deep = 0; for (int i = result.Length - 1; i > 0; i--) { var c = result[i]; if (c == '(') { if (deep == 0) { result = result.Remove(i); break; } else { deep--; } } else if (c == ')' && i != result.Length - 1) { deep++; } } } return(result); } } } else if (targetType.IsCastableTo(typeof(UnityEventBase))) { var method = targetType.GetMethod("AddListener"); var param = method.GetParameters()[0].ParameterType; parameterTypes = param.GetGenericArguments(); if (CodeGenerator.IsGroupedNode(this) && CodeGenerator.CanSimplifyToLambda(body, typeof(void), parameterTypes)) { var bodyNode = body.GetTargetNode(); if (bodyNode as MultipurposeNode) { string result = bodyNode.GenerateValueCode(); if (result.EndsWith(")")) { int deep = 0; for (int i = result.Length - 1; i > 0; i--) { var c = result[i]; if (c == '(') { if (deep == 0) { result = result.Remove(i); break; } else { deep--; } } else if (c == ')' && i != result.Length - 1) { deep++; } } } return(result); } } } else { throw new Exception("Unsupported event to hook:" + target.DisplayName(true)); } //Generate lambda code string contents = null; List <Type> types = new List <Type>(); List <string> parameterNames = new List <string>(); for (int i = 0; i < parameterTypes.Length; i++) { var pType = parameterTypes[i]; var field = this.GetType().GetField("parameters"); if (pType != null) { string varName = null; if (CodeGenerator.NeedInstanceVariable(this, field, i, new Node[] { this })) { varName = CodeGenerator.GenerateVariableName("tempVar", this); contents = CodeGenerator.AddVariable(this, field, i, pType, true) + " = " + varName + ";" + contents.AddLineInFirst(); } else { varName = CodeGenerator.GetVariableName(this, field, i); } types.Add(pType); parameterNames.Add(varName); } } contents += CodeGenerator.GenerateFlowCode(body, this).AddLineInFirst(); return(CodeGenerator.GenerateAnonymousMethod(types, parameterNames, contents)); }
public override string GenerateValueCode() { System.Type rType = null; if (returnType.isAssigned) { rType = returnType.Get <System.Type>(); } if (rType != null && parameterTypes.All(item => item.isAssigned && item.Get <System.Type>() != null)) { string contents = null; System.Type[] types = parameterTypes.Select(m => m.isAssigned ? m.startType : null).ToArray(); if (!CodeGenerator.IsInStateGraph(this) && CodeGenerator.CanSimplifyToLambda(body, rType, types)) { var bodyNode = body.GetTargetNode(); if (bodyNode as MultipurposeNode) { string result = bodyNode.GenerateValueCode(); if (result.EndsWith(")")) { int deep = 0; for (int i = result.Length - 1; i > 0; i--) { var c = result[i]; if (c == '(') { if (deep == 0) { result = result.Remove(i); break; } else { deep--; } } else if (c == ')' && i != result.Length - 1) { deep++; } } } return(result); } } List <string> parameterNames = new List <string>(); var field = this.GetType().GetField("parameterValues"); for (int i = 0; i < types.Length; i++) { string varName = null; System.Type type = types[i]; if (type != null) { if (CodeGenerator.NeedInstanceVariable(this, field, i, body)) //Auto generate instance variable for parameter. { varName = CodeGenerator.GenerateVariableName("tempVar", this.GetInstanceID().ToString() + i); contents = CodeGenerator.AddVariable(this, field, i, type, true) + " = " + varName + ";" + contents.AddLineInFirst(); } else { varName = CodeGenerator.GetVariableName(this, field, i); } parameterNames.Add(varName); } } CodeGenerator.BeginBlock(allowYield: false); //Ensure there's no yield statements contents += CodeGenerator.GenerateFlowCode(body, this, false).AddLineInFirst(); CodeGenerator.EndBlock(); //Ensure to restore to previous block return(CodeGenerator.GenerateAnonymousMethod(types, parameterNames, contents)); } return(null); }