Example #1
0
        public ConnectionLineView(PortEditorView portViewA, PortEditorView portViewB, GraphEditorData graphEditorData)
        {
            if (portViewA.FlowType == portViewB.FlowType)
            {
                Debug.LogError("两个端口的FlowType相同,无法连接");
                return;
            }

            this.graphEditorData = graphEditorData;

            this.FlowOutPortView = portViewA.FlowType == FlowType.In ? portViewB : portViewA;
            this.FlowInPortView  = portViewB.FlowType == FlowType.In ? portViewB : portViewA;

            //流入节点都只允许一个连接
            graphEditorData.ClearPortAllConnections(FlowInPortView);

            if (!FlowOutPortView.connectedPortList.Contains(FlowInPortView))
            {
                FlowOutPortView.connectedPortList.Add(FlowInPortView);
            }

            if (!FlowInPortView.connectedPortList.Contains(FlowOutPortView))
            {
                FlowInPortView.connectedPortList.Add(FlowOutPortView);
            }
        }
Example #2
0
        /// <summary>
        /// 载入完成时,如果是<see cref="GetVariableNode"/>或者<see cref="SetVariableNode"/> 则需要初始化更新对应端口的类型
        /// </summary>
        public override void OnLoadFinish()
        {
            base.OnLoadFinish();

            //初始化读写节点的端口类型
            //如果input port端口的类型是VariableWrapper,则看是否设置的有值,有值的话更新整个端口的类型
            VariableWrapper variableWrapper = inputPortReflectionInfo.GetInputNodeVariableValue() as VariableWrapper;

            if (variableWrapper == null)
            {
                return;
            }

            int               variableId        = variableWrapper.variableId;
            GraphEditorData   data              = NodeView.graph.data;
            GraphVariableInfo graphVariableInfo = data.GetGraphVariableInfo(variableId);

            if (graphVariableInfo != null)
            {
                NodeView.UpdateGraphVariableNodeIOPortType(graphVariableInfo.valueType, true);
            }
            else
            {
                NodeView.UpdateGraphVariableNodeIOPortType(null, true);
            }
        }
Example #3
0
        private static void AddOrUpdateGraphsRecord(GraphEditorData data)
        {
            if (File.Exists(GraphRecordFilePath))
            {
                string      jsonString  = File.ReadAllText(GraphRecordFilePath);
                GraphRecord graphRecord = new GraphRecord();
                EditorJsonUtility.FromJsonOverwrite(jsonString, graphRecord);

                bool hasFoundGraph = false;
                for (int i = 0; i < graphRecord.graphBaseInfoList.Count; i++)
                {
                    if (graphRecord.graphBaseInfoList[i].graphId == data.graphId)
                    {
                        hasFoundGraph = true;
                        graphRecord.graphBaseInfoList[i].graphName        = data.graphName;
                        graphRecord.graphBaseInfoList[i].graphDescription = data.graphDescription;
                        break;
                    }
                }

                if (!hasFoundGraph)
                {
                    graphRecord.graphBaseInfoList.Add(new GraphBaseInfo
                    {
                        graphId = data.graphId, graphName = data.graphName, graphDescription = data.graphDescription
                    });
                    graphRecord.nextGraphId++;
                }

                jsonString = EditorJsonUtility.ToJson(graphRecord, true);
                File.WriteAllText(GraphRecordFilePath, jsonString);
            }
            else
            {
                GraphRecord graphRecord = new GraphRecord();

                graphRecord.graphBaseInfoList = new List <GraphBaseInfo>();
                graphRecord.graphBaseInfoList.Add(new GraphBaseInfo()
                {
                    graphId = data.graphId, graphName = data.graphName, graphDescription = data.graphDescription
                });
                graphRecord.nextGraphId++;

                string jsonString = EditorJsonUtility.ToJson(graphRecord, true);
                File.WriteAllText(GraphRecordFilePath, jsonString);
            }

            AssetDatabase.Refresh();
        }
Example #4
0
        void OpenGraphLoadWindow(object mousePositionObject)
        {
            Vector2 mousePosition = (Vector2)mousePositionObject;

            try
            {
                PopupWindow.Show(new Rect(mousePosition + position.position, new Vector2(500, 0)), new LoadGraphPopupWindow(
                                     loadGraphId =>
                {
                    Reset();
                    data = PersistenceTool.LoadGraph(this, loadGraphId);

                    //做一些载入完成的初始化工作
                    data.OnLoadFinish();

                    //检查连线的合法性
                    data.CheckAllNodeConnection();
                }));
            }
            catch
            {
            }
        }
Example #5
0
        private void OnGUI()
        {
            instance = this;


            //初始化
            if (supportTypeNames == null)
            {
                supportTypeNames = new string[supportTypeList.Count];

                for (int i = 0; i < supportTypeList.Count; i++)
                {
                    supportTypeNames[i] = Utility.BeautifyTypeName(supportTypeList[i]);
                }
            }

            //draw title
            GUILayout.Label("行为图属性", Utility.GetGuiStyle("Title"));
            GUILayout.Space(10);

            GraphEditorWindow graphEditorWindow = GraphEditorWindow.instance;

            if (graphEditorWindow == null || graphEditorWindow.data == null)
            {
                GUILayout.Label("请先打开行为图编辑器窗口", Utility.GetGuiStyle("SkillGraphName"));
                return;
            }

            data = graphEditorWindow.data;

            DrawToolButtons();

            GUILayout.Space(30);

            DrawLocalVariableItemList();
        }
Example #6
0
 private void OnEnable()
 {
     instance = this;
     data     = new GraphEditorData();
     Reset();
 }
Example #7
0
        private static void UpdateNodeViewData(NodeConfigInfo nodeConfigInfo, NodeEditorView nodeView, GraphEditorData data)
        {
            //flow in port--处理流出节点的时候顺便就处理了

            //flow out port
            for (int i = 0; i < nodeConfigInfo.flowOutPortInfoList.Count; i++)
            {
                FlowOutPortConfigInfo flowOutPortConfigInfo = nodeConfigInfo.flowOutPortInfoList[i];
                FlowOutPortEditorView flowOutPortView       =
                    GetFlowOutPortViewByPortName(nodeView.flowOutPortViews, flowOutPortConfigInfo.flowOutPortName);
                if (flowOutPortView == null)
                {
                    Debug.LogFormat("节点{0}中找不到流出端口 <{1}> 了,该端口的连接被忽略", nodeView.ReflectionInfo.Type,
                                    flowOutPortConfigInfo.flowOutPortName);
                    continue;
                }

                for (int j = 0; j < flowOutPortConfigInfo.targetNodeList.Count; j++)
                {
                    int            targetNodeId   = flowOutPortConfigInfo.targetNodeList[j];
                    NodeEditorView targetNodeView = data.GetNode(targetNodeId);
                    if (targetNodeView == null)
                    {
                        Debug.LogErrorFormat("无法找到节点{0},可能是配置损坏/更改了类名...", targetNodeId);
                        continue;
                    }

                    if (targetNodeView.flowInPortView == null)
                    {
                        Debug.LogErrorFormat("节点类型{0}没有流入节点,是否节点性质发生了改变?", nodeView.ReflectionInfo.Type.FullName);
                        continue;
                    }

                    ConnectionLineView connectionLineView =
                        new ConnectionLineView(flowOutPortView, targetNodeView.flowInPortView, data);
                    data.connectionLineList.Add(connectionLineView);
                }
            }

            //output port -- 不用配置

            //input port
            for (int i = 0; i < nodeConfigInfo.inputPortInfoList.Count; i++)
            {
                InputPortConfigInfo inputPortConfigInfo = nodeConfigInfo.inputPortInfoList[i];
                InputPortEditorView inputPortView       =
                    GetInputPortViewByPortName(nodeView.inputPortViewList, inputPortConfigInfo.portName);

                if (inputPortView == null)
                {
                    Debug.LogFormat("节点{0}中无法找到接口名字为 <{1}> 的NodeInputVariable Field,该接口配置被跳过",
                                    nodeView.ReflectionInfo.Type.FullName, inputPortConfigInfo.portName);
                    continue;
                }

                //没有连接到其他节点的情况
                if (string.IsNullOrEmpty(inputPortConfigInfo.targetPortName))
                {
                    //设置默认值
                    Type valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName);
                    if (valueType == null)
                    {
                        valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName + ",UnityEngine");
                        if (valueType == null)
                        {
                            valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName + ",Assembly-CSharp");
                        }
                    }

                    if (valueType == null)
                    {
                        Debug.LogErrorFormat("工程中找不到类型: {0}", inputPortConfigInfo.nodeVariableGenericTypeName);
                        continue;
                    }

                    SetNodeInputVariableValue(inputPortView.inputPortReflectionInfo, valueType,
                                              inputPortConfigInfo.nodeVariableValue, nodeView);
                }
                //连接到其他节点的情况
                else
                {
                    NodeEditorView connectedToNodeView = data.GetNode(inputPortConfigInfo.targetNodeId);
                    if (connectedToNodeView == null)
                    {
                        Debug.LogErrorFormat("节点 {0} 的input接口 {1} 找不到连接的节点{2}", nodeView.NodeId, inputPortConfigInfo.portName,
                                             inputPortConfigInfo.targetNodeId);
                        continue;
                    }

                    OutputPortEditorView connectedToOutputPortView =
                        GetOutputPortViewByPortName(connectedToNodeView.outputPortViewList, inputPortConfigInfo.targetPortName);
                    if (connectedToOutputPortView == null)
                    {
                        Debug.LogFormat("找不到节点{0}中 接口名字为 <{1}> 的output接口,该接口的连接被跳过", connectedToNodeView.NodeId,
                                        inputPortConfigInfo.targetPortName);
                        continue;
                    }

                    ConnectionLineView connectionLineView =
                        new ConnectionLineView(inputPortView, connectedToOutputPortView, data);
                    data.connectionLineList.Add(connectionLineView);
                }
            }
        }
Example #8
0
        public static GraphEditorData LoadGraph(GraphEditorWindow graph, int graphId)
        {
            GraphEditorData resultData = new GraphEditorData();

            string graphEditorConfigFilePath = Path.Combine(Application.dataPath,
                                                            string.Format("FlatNode/Editor/GraphSavedConfig/{0}.json", graphId));

            if (!File.Exists(graphEditorConfigFilePath))
            {
                Debug.LogErrorFormat("无法载入行为图配置文件: {0}", graphEditorConfigFilePath);
            }

            string          jsonString      = File.ReadAllText(graphEditorConfigFilePath);
            GraphConfigInfo graphConfigInfo = new GraphConfigInfo();

            EditorJsonUtility.FromJsonOverwrite(jsonString, graphConfigInfo);

            //处理注释框
            for (int i = 0; i < graphConfigInfo.commentBoxInfoList.Count; i++)
            {
                CommentBoxInfo commentBoxInfo = graphConfigInfo.commentBoxInfoList[i];
                CommentBoxView commentBoxView = ParseCommentBoxInfo(commentBoxInfo, graph);

                resultData.commentBoxViewList.Add(commentBoxView);
            }

            //变量
            for (int i = 0; i < graphConfigInfo.graphVariableInfoList.Count; i++)
            {
                if (!graphConfigInfo.graphVariableInfoList[i].Validate())
                {
                    continue;
                }

                resultData.graphVariableInfoList.Add(graphConfigInfo.graphVariableInfoList[i].OnDeserialized());
            }

            //如果有节点无法解析出来(可能是改了类名称之类的),则需要跳过这些节点
            HashSet <int> errorNodeIndexSet = new HashSet <int>();

            //首先将所有的节点都生成
            for (int i = 0; i < graphConfigInfo.nodesList.Count; i++)
            {
                NodeEditorView nodeView = ParseNodeInfo(graphConfigInfo.nodesList[i], graph);
                if (nodeView == null)
                {
                    errorNodeIndexSet.Add(i);
                    continue;
                }

                resultData.nodeList.Add(nodeView);
            }

            //然后再将所有节点的内容写进去,将节点连起来
            int nodeIndex = 0;

            for (int i = 0; i < graphConfigInfo.nodesList.Count; i++)
            {
                if (errorNodeIndexSet.Contains(i))
                {
                    //skip
                    continue;
                }

                UpdateNodeViewData(graphConfigInfo.nodesList[i], resultData.nodeList[nodeIndex], resultData);
                nodeIndex++;
            }

            resultData.graphId          = graphConfigInfo.graphId;
            resultData.graphName        = graphConfigInfo.graphName;
            resultData.graphDescription = graphConfigInfo.graphDescription;

            return(resultData);
        }
Example #9
0
        public static void SaveGraph(GraphEditorData data)
        {
            string jsonString = String.Empty;

            byte[] runtimeConfigBytes = null;

            bool isSuccess = true;

            try
            {
                //存储技能配置json文件,配置文件使用json是因为可读性好
                GraphConfigInfo graphConfigInfo = new GraphConfigInfo
                {
                    graphId               = data.graphId,
                    graphName             = data.graphName,
                    graphDescription      = data.graphDescription,
                    nodesList             = new List <NodeConfigInfo>(),
                    commentBoxInfoList    = new List <CommentBoxInfo>(),
                    graphVariableInfoList = new List <GraphVariableInfo>(),
                };

                for (int i = 0; i < data.nodeList.Count; i++)
                {
                    NodeEditorView nodeView = data.nodeList[i];

                    graphConfigInfo.nodesList.Add(ConvertToNodeInfo(nodeView));
                }

                for (int i = 0; i < data.commentBoxViewList.Count; i++)
                {
                    CommentBoxView commentBoxView = data.commentBoxViewList[i];
                    graphConfigInfo.commentBoxInfoList.Add(ConvertToCommentInfo(commentBoxView));
                }

                for (int i = 0; i < data.graphVariableInfoList.Count; i++)
                {
                    graphConfigInfo.graphVariableInfoList.Add(data.graphVariableInfoList[i].OnSerialized());
                }

                jsonString         = JsonUtility.ToJson(graphConfigInfo, true);
                runtimeConfigBytes =
                    ConvertToRuntimeInfo(data.nodeList, data.graphVariableInfoList, data.graphId);
            }
            catch (Exception e)
            {
                isSuccess = false;
                Debug.LogError(e.Message);
                throw;
            }
            finally
            {
                if (isSuccess)
                {
                    string graphEditorConfigFilePath = Path.Combine(Application.dataPath,
                                                                    string.Format("FlatNode/Editor/GraphSavedConfig/{0}.json", data.graphId));
                    File.WriteAllText(graphEditorConfigFilePath, jsonString);

                    string graphRuntimeConfigFilePath = Path.Combine(Application.dataPath,
                                                                     string.Format("Resources/GraphRuntime/{0}.bytes", data.graphId));
                    string parentDirctoryPath = Directory.GetParent(graphRuntimeConfigFilePath).FullName;
                    if (!Directory.Exists(parentDirctoryPath))
                    {
                        Directory.CreateDirectory(parentDirctoryPath);
                    }
                    if (runtimeConfigBytes != null)
                    {
                        File.WriteAllBytes(graphRuntimeConfigFilePath, runtimeConfigBytes);
                    }

                    //更新所有图的记录文件
                    AddOrUpdateGraphsRecord(data);

                    AssetDatabase.Refresh();
                }
            }
        }
Example #10
0
        /// <summary>
        /// 绘制各种类型的输入框
        /// </summary>
        /// <param name="type"></param>
        void DrawInputFieldLabel(Type type)
        {
            if (type == typeof(float))
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 100f);

                EditorGUI.BeginChangeCheck();
                float value = (float)inputPortReflectionInfo.GetInputNodeVariableValue();
                value = EditorGUI.FloatField(labelInputAreaRect, value);
                if (EditorGUI.EndChangeCheck())
                {
                    inputPortReflectionInfo.SetInputNodeVariableValue(value);
                }
            }
            else if (type == typeof(int))
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 100f);

                EditorGUI.BeginChangeCheck();
                int value = (int)inputPortReflectionInfo.GetInputNodeVariableValue();
                value = EditorGUI.IntField(labelInputAreaRect, value);
                if (EditorGUI.EndChangeCheck())
                {
                    inputPortReflectionInfo.SetInputNodeVariableValue(value);
                }
            }
            else if (type == typeof(string))
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 100f);

                EditorGUI.BeginChangeCheck();
                string value = (string)inputPortReflectionInfo.GetInputNodeVariableValue();
                if (GUI.Button(labelInputAreaRect, value))
                {
                    PopupWindow.Show(labelInputAreaRect,
                                     new StringEditPopupWindow(value,
                                                               stringContent => { inputPortReflectionInfo.SetInputNodeVariableValue(stringContent); }));
                }
            }
            else if (type == typeof(bool))
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 20f);

                EditorGUI.BeginChangeCheck();
                bool value = (bool)inputPortReflectionInfo.GetInputNodeVariableValue();
                value = EditorGUI.Toggle(labelInputAreaRect, value);
                if (EditorGUI.EndChangeCheck())
                {
                    inputPortReflectionInfo.SetInputNodeVariableValue(value);
                }
            }
            else if (type.IsEnum)
            {
                if (maxEnumNeedWidth < 0)
                {
                    maxEnumNeedWidth = Utility.GetEnumMaxGuiWidth(type, 16);
                }

                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, maxEnumNeedWidth + 25); //25是enum选择框箭头的位置

                EditorGUI.BeginChangeCheck();
                Enum enumValue = (Enum)inputPortReflectionInfo.GetInputNodeVariableValue();
                enumValue = EditorGUI.EnumPopup(labelInputAreaRect, enumValue);
                if (EditorGUI.EndChangeCheck())
                {
                    inputPortReflectionInfo.SetInputNodeVariableValue(enumValue);
                }
            }
            //支持list<int>
            else if (type == typeof(List <int>))
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 100f);

                List <int> list = inputPortReflectionInfo.GetInputNodeVariableValue() as List <int>;
                if (list == null)
                {
                    list = new List <int>();
                }

                string listHint = string.Join(",", list.Select(x => x.ToString()).ToArray());
                if (GUI.Button(labelInputAreaRect, listHint))
                {
                    ListIntEditorWindow.ShowWindow(list,
                                                   editedList => { inputPortReflectionInfo.SetInputNodeVariableValue(editedList); });
                }
            }
            else if (type == typeof(LayerMaskWrapper))
            {
                if (maxLayerMaskNeedWidth < 0)
                {
                    maxLayerMaskNeedWidth = Utility.GetLayerMaxGuiLength(8);
                }

                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, maxLayerMaskNeedWidth + 25);

                EditorGUI.BeginChangeCheck();
                LayerMaskWrapper layerMaskWrapperValue = (LayerMaskWrapper)inputPortReflectionInfo.GetInputNodeVariableValue();
                if (layerMaskWrapperValue == null)
                {
                    layerMaskWrapperValue = new LayerMaskWrapper();
                }

                string[] gameLayerNames = Utility.GetUnityLayerNames();

                int selectLayer = EditorGUI.MaskField(labelInputAreaRect, layerMaskWrapperValue.layer, gameLayerNames);
                if (EditorGUI.EndChangeCheck())
                {
                    layerMaskWrapperValue.layer = selectLayer;
//                    Debug.Log("select layer mask: " + layerMaskValue);
                    inputPortReflectionInfo.SetInputNodeVariableValue(layerMaskWrapperValue);
                }
            }
            //选择技能变量
            else if (type == typeof(VariableWrapper))
            {
                VariableWrapper variableWrapper = inputPortReflectionInfo.GetInputNodeVariableValue() as VariableWrapper;
                if (variableWrapper == null)
                {
                    variableWrapper = new VariableWrapper();
                }

                int               varibleId         = variableWrapper.variableId;
                GraphEditorData   data              = GraphEditorWindow.instance.data;
                GraphVariableInfo graphVariableInfo = data.GetGraphVariableInfo(varibleId);

                string buttonName;
                //当前没有选择任何一个变量
                if (graphVariableInfo == null)
                {
                    buttonName = "选择一个变量!";
                }
                else
                {
                    buttonName = graphVariableInfo.name;
                }

                CalculateAndDrawLabelCommonElement("变量: ", EditorStyles.label.CalcSize(new GUIContent(buttonName)).x + 20);
                if (GUI.Button(labelInputAreaRect, buttonName))
                {
                    PopupWindow.Show(labelInputAreaRect, new SelectGraphVariablePopupWindow(data.CurrentGraphVariableInfoList,
                                                                                            selectVariableId =>
                    {
                        variableWrapper.variableId = selectVariableId;
                        inputPortReflectionInfo.SetInputNodeVariableValue(variableWrapper);

                        Type variableType = GraphEditorWindow.instance.data
                                            .GetGraphVariableInfo(selectVariableId).valueType;
                        NodeView.UpdateGraphVariableNodeIOPortType(variableType, true);
                    }));
                }
            }
            //所有需要自定义Input标签的类型写在这个分支前面
            else if (type.IsClass)
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                CalculateAndDrawLabelCommonElement(typeName, 30f);

                GUI.Label(labelInputAreaRect, "(Null)", labelTextStyle);
            }
            else
            {
                string typeName = Utility.BeautifyTypeName(type) + ": ";
                string content  = string.Format("Default({0})", type.Name);
                CalculateAndDrawLabelCommonElement(typeName, Utility.GetStringGuiWidth(content, labelTextStyle.fontSize));

                GUI.Label(labelInputAreaRect, content, labelTextStyle);
            }
        }