Example #1
0
    public static int GeometryControlsOnGUI(int cur_y, AXNodeGraphEditorWindow editor, AXParametricObject po)
    {
        int gap     = ArchimatixUtils.gap;
        int lineHgt = ArchimatixUtils.lineHgt;

        float x1         = 10;
        float x2         = 20;
        float winMargin  = ArchimatixUtils.indent;
        float innerWidth = po.rect.width - 2 * winMargin;



        AXParameter p = null;

        // Geometry (and other) controllers
        if (po.geometryControls != null && po.geometryControls.children != null)
        {
            for (int i = 0; i < po.geometryControls.children.Count; i++)
            {
                p = po.geometryControls.children[i] as AXParameter;

                if (p.PType != AXParameter.ParameterType.None && p.PType != AXParameter.ParameterType.GeometryControl)
                {
                    continue;
                }

                // these points are world, not relative to the this GUIWindow
                p.inputPoint  = new Vector2(po.rect.x, po.rect.y + cur_y + lineHgt / 2);
                p.outputPoint = new Vector2(po.rect.x + po.rect.width, po.rect.y + cur_y + lineHgt / 2);

                Rect pRect = new Rect(x1, cur_y, innerWidth, lineHgt);

                try {
                    int hgt = ParameterGUI.OnGUI(pRect, editor, p);
                    cur_y += hgt + gap;
                } catch {
                }
            }
        }

        if (po.is2D() || po.generator is Grouper)
        {
            if (GUI.Button(new Rect(x2, cur_y, lineHgt * 1.25f, lineHgt), new GUIContent("+", "Create a new Control Parameter")))
            {
                Undo.RegisterCompleteObjectUndo(po.model, "New AXParameter");
                AXParameter tmpP = po.addParameter(new AXParameter());

                foreach (AXParameter pop in po.parameters)
                {
                    if (pop != p)
                    {
                        pop.isOpen = false;
                    }
                }

                po.model.indexedParameters.Add(tmpP.Guid, tmpP);

                po.doneEditing();

                tmpP.isOpen      = true;
                tmpP.isEditing   = false;
                tmpP.shouldFocus = true;
                //po.isEditing  = true;

                po.model.cleanGraph();


                AXNodeGraphEditorWindow.repaintIfOpen();
            }

            /*
             * if (GUI.Button (new Rect(x1+editButtonWid+6, cur_y, editButtonWid,lineHgt), "Done" ))
             *              po.doneEditing();
             * else
             *      if (GUI.Button (new Rect(x1+editButtonWid+6, cur_y, editButtonWid,lineHgt), "Edit Controls" ))
             *              po.isEditing = true;
             */
            cur_y += lineHgt + gap + 5;
        }


        if (po.generator is MaterialTool)
        {
            MaterialTool materialTool = (po.generator as MaterialTool);

            GUIStyle labelstyle = GUI.skin.GetStyle("Label");
            labelstyle.alignment = TextAnchor.MiddleLeft;
            GUI.Label(new Rect(10, cur_y, 250, 32), "   Texels/Unit: " + materialTool.texelsPerUnit.ToString("F0"));
            cur_y += 32;
        }
        else if (po.generator is ShapeOffsetter)
        {
            ShapeOffsetter offsetter = (po.generator as ShapeOffsetter);

            AXParameter output_p = offsetter.P_Output;

            if (output_p == null)
            {
                output_p = po.getParameter("Output Shape");
            }

            if (output_p == null)
            {
                return(cur_y);
            }


            Rect tRect = new Rect(25, cur_y, 150, 16);

            GUIStyle labelstyle = GUI.skin.GetStyle("Label");
            labelstyle.alignment = TextAnchor.MiddleLeft;

            /*
             * if (p.PType == AXParameter.ParameterType.Output)
             * {
             * labelstyle.alignment = TextAnchor.MiddleRight;
             * labelstyle.fixedWidth = lRect.width+5;
             * }
             */

            // JOIN_TYPE: Square, Round, Miter
            if (offsetter.offset != 0)
            {
                string[] options = ArchimatixUtils.getMenuOptions("JoinType");
                EditorGUIUtility.labelWidth = 75;                //-50;

                EditorGUI.BeginChangeCheck();
                output_p.joinType = (JoinType)EditorGUI.Popup(tRect, "JoinType", (int)output_p.joinType, options);
                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RegisterCompleteObjectUndo(po.model, "value change for JoinType");
                    po.model.autobuild();
                }
                cur_y += ArchimatixUtils.lineHgt + ArchimatixUtils.gap;
            }

            // ARC_TOLERANCE (for JoinType.Round)
            if (output_p.joinType == AXClipperLib.JoinType.jtRound || output_p.endType == AXClipperLib.EndType.etOpenRound)
            {
                tRect.y = cur_y;


                if (float.IsNaN(output_p.arcTolerance))
                {
                    output_p.arcTolerance = 50;
                }
                if (output_p.arcTolerance < .25f)
                {
                    output_p.arcTolerance = .25f;
                }

                float smooth = (float)(120 / (output_p.arcTolerance * output_p.arcTolerance));

                AXEditorUtilities.assertFloatFieldKeyCodeValidity("shapehandler_Text_smoothness_" + output_p.Guid + "_" + output_p.Name);

                EditorGUI.BeginChangeCheck();
                GUI.SetNextControlName("shapehandler" + output_p.Name);
                smooth = EditorGUI.FloatField(tRect, "smoothness", smooth);
                if (EditorGUI.EndChangeCheck())
                {
                    output_p.arcTolerance = (float)(Mathf.Sqrt(120 / smooth));
                    Undo.RegisterCompleteObjectUndo(po.model, "value change for " + output_p.Name);
                    if (output_p.arcTolerance < .25f)
                    {
                        output_p.arcTolerance = .25f;
                    }
                    if (output_p.arcTolerance > 50)
                    {
                        output_p.arcTolerance = 50;
                    }
                    if (float.IsNaN(output_p.arcTolerance))
                    {
                        output_p.arcTolerance = 50;
                    }
                    po.model.isAltered(20);
                }
                cur_y += ArchimatixUtils.lineHgt + ArchimatixUtils.gap;
            }
        }

        return(cur_y);
    }
Example #2
0
    public static void display(float imagesize = 64, AXNodeGraphEditorWindow editor = null)
    {
        //Debug.Log("imagesise="+imagesize);
        // called from an OnGUI
        //imagesize = 64;
        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUIStyle.none, GUIStyle.none);

        EditorGUILayout.BeginVertical();

        string[] itemStrings = null;

        // Select menu item list
        if (editor.OutputParameterBeingDragged == null)
        {
            if (editor.model != null && editor.model.selectedPOs.Count > 1)
            {
                //if (editor.model.selectedPOs[0].is2D())
                //	itemStrings = ArchimatixEngine.nodeStringsFrom2DMultiSelect;

                //else
                itemStrings = ArchimatixEngine.nodeStringsFromMultiSelect;
            }
            else
            {
                itemStrings = ArchimatixEngine.nodeStrings;
            }
        }
        else if (editor.OutputParameterBeingDragged.parametricObject.is2D())
        {
            itemStrings = ArchimatixEngine.nodeStringsFrom2DOutput;
        }

        else if (editor.OutputParameterBeingDragged.parametricObject.is3D())
        {
            if (editor.OutputParameterBeingDragged.Type == AXParameter.DataType.Spline)
            {
                itemStrings = ArchimatixEngine.nodeStringsFrom2DOutput;
            }
            else
            {
                itemStrings = ArchimatixEngine.nodeStringsFrom3DOutput;
            }
        }
        else if (editor.OutputParameterBeingDragged.parametricObject.generator is RepeaterTool)
        {
            itemStrings = ArchimatixEngine.nodeStringsFromRepeaterTool;
        }


        /*
         * if (Library.last2DItem != null)
         * {
         *      if (GUILayout.Button(new GUIContent(Library.last2DItem.icon, Library.last2DItem.po.Name), new GUILayoutOption[] {GUILayout.Width(imagesize), GUILayout.Height(imagesize)}))
         *      {
         *
         *      }
         * }
         */


        List <string> stringList = null;

        if (itemStrings != null)
        {
            stringList = itemStrings.ToList();
        }

        if (stringList != null)
        {
            stringList.AddRange(Archimatix.customNodeNames);
        }

        // Build Menu
        string poName;

        if (stringList != null)
        {
            for (int i = 0; i < stringList.Count; i++)
            {
                string nodeName = stringList[i];

                Texture2D nodeIcon = null;


                if (ArchimatixEngine.nodeIcons.ContainsKey(nodeName))
                {
                    nodeIcon = ArchimatixEngine.nodeIcons[nodeName];
                }
                else
                {
                    if (ArchimatixEngine.nodeIcons.ContainsKey("CustomNode"))
                    {
                        nodeIcon = ArchimatixEngine.nodeIcons["CustomNode"];
                    }
                    else
                    {
                        continue;
                    }
                }



                if (nodeIcon != null)
                {
                    if (GUILayout.Button(new GUIContent(nodeIcon, nodeName), new GUILayoutOption[] { GUILayout.Width(imagesize), GUILayout.Height(imagesize) }))
                    {
                        //if (editor.DraggingOutputParameter != null)
                        //{
                        AXModel model = AXEditorUtilities.getOrMakeSelectedModel();

                        Undo.RegisterCompleteObjectUndo(model, "Node Menu Selection");

                        AXParametricObject mostRecentPO = model.recentlySelectedPO;


                        int index = nodeName.IndexOf("_");

                        poName = (index > 0) ? nodeName.Substring(0, index) : nodeName;

                        // Support multi-select operation
                        List <AXParametricObject> selectedPOs = new List <AXParametricObject>();
                        if (model.selectedPOs.Count > 0)
                        {
                            selectedPOs.AddRange(model.selectedPOs);
                        }



                        // ADD NEW PO TO MODEL (only this new po is selected after this)
                        AXParametricObject po = AXEditorUtilities.addNodeToCurrentModel(poName, false);

                        if (po == null || po.generator == null)
                        {
                            return;
                        }


                        float max_x = -AXGeometryTools.Utilities.IntPointPrecision;


                        if (poName == "FreeCurve")
                        {
                            ArchimatixEngine.sceneViewState = ArchimatixEngine.SceneViewState.AddPoint;
                        }



                        // DRAGGING A PARAMETER? THEN RIG'R UP!
                        if (editor.OutputParameterBeingDragged != null)
                        {
                            AXParametricObject draggingPO  = editor.OutputParameterBeingDragged.parametricObject;
                            AXParameter        new_input_p = null;

                            switch (nodeName)
                            {
                            case "Instance2D":
                            case "ShapeOffsetter":
                                po.getParameter("Input Shape").makeDependentOn(editor.OutputParameterBeingDragged);
                                po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));

                                if (po.geometryControls != null)
                                {
                                    po.geometryControls.isOpen = true;
                                }
                                break;

                            case "ShapeDistributor":
                                List <AXParameter> deps = new List <AXParameter>();

                                for (int dd = 0; dd < editor.OutputParameterBeingDragged.Dependents.Count; dd++)
                                {
                                    deps.Add(editor.OutputParameterBeingDragged.Dependents[dd]);
                                }

                                for (int dd = 0; dd < deps.Count; dd++)
                                {
                                    deps[dd].makeDependentOn(po.getParameter("Output Shape"));
                                }

                                po.getParameter("Input Shape").makeDependentOn(editor.OutputParameterBeingDragged);
                                po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));

                                if (po.geometryControls != null)
                                {
                                    po.geometryControls.isOpen = true;
                                }
                                break;

                            case "ShapeMerger":
                                po.generator.getInputShape().addInput().makeDependentOn(editor.OutputParameterBeingDragged);
                                if (editor.OutputParameterBeingDragged.axis != Axis.NONE)
                                {
                                    po.intValue("Axis", (int)editor.OutputParameterBeingDragged.axis);
                                }
                                else
                                {
                                    po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));
                                }

                                break;

                            case "PlanRepeater2D":
                            case "PlanRepeater2D_Corner":
                                po.getParameter("Corner Shape").makeDependentOn(editor.OutputParameterBeingDragged);
                                po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));
                                break;

                            case "PlanRepeater_Corner":
                                po.getParameter("Corner Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;


                            case "PairRepeater2D":
                            case "RadialRepeater2D":
                            case "RadialRepeater2D_Node":
                            case "LinearRepeater2D":
                            case "LinearRepeater2D_Node":
                            case "GridRepeater2D":
                            case "GridRepeater2D_Node":
                                po.getParameter("Node Shape").makeDependentOn(editor.OutputParameterBeingDragged);
                                po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));
                                break;

                            case "RadialRepeater2D_Cell":
                            case "LinearRepeater2D_Cell":
                            case "GridRepeater2D_Cell":
                                po.getParameter("Cell Shape").makeDependentOn(editor.OutputParameterBeingDragged);
                                po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));
                                break;

                            case "Grouper":
                                //po.addInputMesh().makeDependentOn(editor.OutputParameterBeingDragged);


                                po.addGroupee(editor.OutputParameterBeingDragged.parametricObject);

                                break;

                            case "PlanRepeater2D_Plan":
                            case "Polygon_Plan":
                            case "Extrude_Plan":
                            case "PlanSweep_Plan":
                            case "PlanRepeater_Plan":
                            case "PlanDeformer_Plan":

                                // SYNC AXES
                                if (editor.OutputParameterBeingDragged.axis != Axis.NONE)
                                {
                                    po.intValue("Axis", (int)editor.OutputParameterBeingDragged.axis);
                                }
                                else
                                {
                                    po.intValue("Axis", editor.OutputParameterBeingDragged.parametricObject.intValue("Axis"));
                                }


                                if (nodeName == "Extrude_Plan" && po.intValue("Axis") != (int)Axis.Y)
                                {
                                    po.floatValue("Bevel", 0);
                                }



                                // INSERT SHAPE_DISTRIBUTOR?
                                new_input_p = po.getParameter("Plan", "Input Shape");
                                //if (draggingPO.is2D() && !(draggingPO.generator is ShapeDistributor) && editor.OutputParameterBeingDragged.Dependents != null && editor.OutputParameterBeingDragged.Dependents.Count > 0)
                                //	model.insertShapeDistributor(editor.OutputParameterBeingDragged, new_input_p);
                                //else
                                new_input_p.makeDependentOn(editor.OutputParameterBeingDragged);

                                // the output of the new node should match the shapestate of the input
                                if (po.generator.P_Output != null)
                                {
                                    po.generator.P_Output.shapeState = new_input_p.shapeState;
                                }

                                AXNodeGraphEditorWindow.repaintIfOpen();

                                break;

                            case "Lathe_Section":
                            case "PlanSweep_Section":
                            case "PlanRepeater_Section":

                                //po.getParameter("Section").makeDependentOn(editor.OutputParameterBeingDragged);

                                // INSERT SHAPE_DISTRIBUTOR?
                                new_input_p = po.getParameter("Section");
                                if (draggingPO.is2D() && !(draggingPO.generator is ShapeDistributor) && draggingPO.hasDependents())
                                {
                                    model.insertShapeDistributor(editor.OutputParameterBeingDragged, new_input_p);
                                }
                                else
                                {
                                    new_input_p.makeDependentOn(editor.OutputParameterBeingDragged);
                                }

                                // the output of the new node should match the shapestate of the input
                                //if (po.generator.P_Output != null)
                                //Debug.Log(new_input_p.Name+" "+new_input_p.shapeState + " :=: " +editor.OutputParameterBeingDragged.Name + " " + editor.OutputParameterBeingDragged.shapeState);



                                AXNodeGraphEditorWindow.repaintIfOpen();


                                break;


                            case "NoiseDeformer":
                            case "ShearDeformer":
                            case "TwistDeformer":
                            case "DomicalDeformer":
                            case "TaperDeformer":
                            case "InflateDeformer":
                            case "PlanDeformer":

                                po.getParameter("Input Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            //case "PlanDeformer_Plan":



                            case "PairRepeater":
                            case "StepRepeater":
                            case "RadialStepRepeater":

                                po.getParameter("Node Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;


                            case "LinearRepeater_Node":
                                AXParameter nodeMesh_p = po.getParameter("Node Mesh");
                                nodeMesh_p.makeDependentOn(editor.OutputParameterBeingDragged);

                                // if the src is very long in x, assume you want to repeat in Z
                                if (editor.OutputParameterBeingDragged.parametricObject.bounds.size.x > (6 * editor.OutputParameterBeingDragged.parametricObject.bounds.size.z))
                                {
                                    po.initiateRipple_setBoolParameterValueByName("zAxis", true);
                                }

                                break;

                            case "LinearRepeater_Cell":
                            case "PlanRepeater_Cell":
                                po.getParameter("Cell Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            case "LinearRepeater_Span":
                                po.getParameter("Bay SpanU").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;


                            case "LinearRepeater":
                                po.getParameter("RepeaterU").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            case "FloorRepeater":
                                po.getParameter("Floor Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            case "RadialRepeater":
                            case "RadialRepeater_Node":
                            case "GridRepeater_Node":
                            case "PlanRepeater_Node":
                                po.getParameter("Node Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            case "RadialRepeater_Span":
                            case "GridRepeater_Span":
                                po.getParameter("Bay SpanU", "SpanU Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;

                            case "GridRepeater_Cell":
                                po.getParameter("Cell Mesh").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;


                            case "ShapeRepeater_Plan":
                                AXEditorUtilities.addNodeToCurrentModel("ShapeRepeater").getParameter("Plan").makeDependentOn(editor.OutputParameterBeingDragged);
                                break;


                            default:
                                AXEditorUtilities.addNodeToCurrentModel(nodeName);
                                break;
                            }


                            if (editor.OutputParameterBeingDragged.parametricObject != null)
                            {
                                mostRecentPO = editor.OutputParameterBeingDragged.parametricObject;
                                //po.rect = editor.OutputParameterBeingDragged.parametricObject.rect;
                                //po.rect.x += 325;
                            }

                            /*
                             * else
                             * {
                             *      po.rect.x = (model.focusPointInGraphEditor.x)+100;// + UnityEngine.Random.Range(-100, 300);
                             *      po.rect.y = (model.focusPointInGraphEditor.y - 250) + UnityEngine.Random.Range(-10, 0);
                             * }
                             */
                        }



                        // NO DRAGGING - CONNECT ALL MULTI_SELECTED
                        else if (selectedPOs != null && selectedPOs.Count > 0)
                        {
                            switch (nodeName)
                            {
                            case "ShapeMerger":
                                AXShape shp = po.generator.getInputShape();
                                for (int j = 0; j < selectedPOs.Count; j++)
                                {
                                    AXParametricObject poo = selectedPOs [j];
                                    if (j == 0)
                                    {
                                        po.intValue("Axis", selectedPOs [j].intValue("Axis"));
                                    }
                                    max_x = Mathf.Max(max_x, poo.rect.x);
                                    if (poo.is2D())
                                    {
                                        AXParameter out_p = poo.generator.getPreferredOutputParameter();
                                        if (out_p != null)
                                        {
                                            shp.addInput().makeDependentOn(out_p);
                                        }
                                    }
                                }

                                po.rect.x = max_x + 250;
                                break;

                            case "Grouper":
                                //Debug.Log("selectedPOs="+selectedPOs.Count);

                                //if (model.currentWorkingGroupPO != null && ! selectedPOs.Contains(model.currentWorkingGroupPO))
                                //{
                                po.addGroupees(selectedPOs);

                                Rect r = AXUtilities.getBoundaryRectFromPOs(selectedPOs);
                                po.rect.x = r.center.x - po.rect.width / 2;
                                po.rect.y = r.center.y - po.rect.height / 2;
                                //}
                                //po.rect.x = max_x+250;
                                break;

                            case "Channeler":
                                //Debug.Log("selectedPOs="+selectedPOs.Count);

                                //if (model.currentWorkingGroupPO != null && ! selectedPOs.Contains(model.currentWorkingGroupPO))
                                //{
                                foreach (AXParametricObject selpo in selectedPOs)
                                {
                                    AXParameter inputer = po.addInputMesh();

                                    inputer.makeDependentOn(selpo.generator.P_Output);
                                }


                                Rect cr = AXUtilities.getBoundaryRectFromPOs(selectedPOs);
                                po.rect.x = cr.center.x - po.rect.width / 2;
                                po.rect.y = cr.center.y - po.rect.height / 2;
                                //}
                                //po.rect.x = max_x+250;
                                break;
                            }
                        }

                        else
                        {
                            switch (nodeName)
                            {
                            case "ShapeMerger":
                                po.assertInputControls();
                                //po.generator.getInputShape().addInput();
                                break;
                            }
                        }



                        editor.OutputParameterBeingDragged = null;
                        model.autobuild();

                        po.generator.adjustWorldMatrices();

                        if (mostRecentPO != null)
                        {
                            po.rect    = mostRecentPO.rect;
                            po.rect.x += (mostRecentPO.rect.width + 50);
                        }
                        else
                        {
                            po.rect.x = (model.focusPointInGraphEditor.x) + 100;                          // + UnityEngine.Random.Range(-100, 300);
                            po.rect.y = (model.focusPointInGraphEditor.y - 250) + UnityEngine.Random.Range(-10, 0);
                        }

                        po.rect.height = 700;

                        //AXNodeGraphEditorWindow.zoomToRectIfOpen(po.rect);


                        //model.beginPanningToRect(po.rect);
                    }
                }
            }
        }
        //GUILayout.Label (GUI.tooltip);


        EditorGUILayout.Space();
        EditorGUILayout.EndVertical();

        EditorGUILayout.EndScrollView();

        /* Not sure why I was doing this - it took up a huge amount of CPU!
         *
         *
         * editor.Repaint();
         * SceneView sv = SceneView.lastActiveSceneView;
         * if (sv != null)
         *      sv.Repaint();
         *
         */
    }
    // Use this for initialization
    public static void OnGUI(AXRelation r)
    {
        GUIStyle richLabelStyle = new GUIStyle(GUI.skin.label);

        richLabelStyle.richText = true;



        string labelA = r.pA.Parent.Name + "." + r.pA.Name;
        string labelB = r.pB.Parent.Name + "." + r.pB.Name;



        GUILayout.Label("<color=" + ((EditorGUIUtility.isProSkin) ? "#bbbbff" : "#660022") + "> <size=13>Relation Expressions</size></color>", richLabelStyle);


        GUILayout.Space(5);


        // SLIDING A SETS B
        EditorGUILayout.BeginHorizontal();

        // B = f(A)
        GUILayout.Label(labelB + "=", GUILayout.Width(150));

        // swap the internal variable name to let the user always use current name,
        // even if that name has changed since the last time the expresion was edited.
        if (r.expression_AB != null)
        {
//			if (
//				Debug.Log();
            GUI.SetNextControlName("expression_Text_AB_" + r.pA_guid + "_" + r.pB_guid);

            r.expression_AB = GUILayout.TextField(r.expression_AB.Replace(r.pA.guidAsEpressionKey, labelA));
            r.expression_AB = r.expression_AB.Replace(labelA, r.pA.guidAsEpressionKey);
        }
        EditorGUILayout.EndHorizontal();



        // SLIDING B SETS A
        EditorGUILayout.BeginHorizontal();

        // A = f(B)
        GUILayout.Label(labelA + "=", GUILayout.Width(150));

        // swap the internal variable name to let the user always use current name,
        // even if that name has changed since the last time the expresion was edited.
        string tmp_expression_BA = "";

        if (r.expression_BA != null)
        {
            GUI.SetNextControlName("expressionBA_Text_BA_" + r.pA_guid + "_" + r.pB_guid);
            tmp_expression_BA = GUILayout.TextField(r.expression_BA.Replace(r.pB.guidAsEpressionKey, labelB));
            r.expression_BA   = tmp_expression_BA.Replace(labelB, r.pB.guidAsEpressionKey);
        }
        EditorGUILayout.EndHorizontal();


        GUILayout.Space(10);


        // FOOTER MENU

        AXModel model = r.pA.parametricObject.model;



        // HORIZONTALMENU
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Revert"))
        {
            r.revert();
            AXNodeGraphEditorWindow.repaintIfOpen();
        }
        if (GUILayout.Button("Save"))
        {
            model.selectedRelationInGraph = null;

            //relationEditWindowIsDisplayed = false;
        }
        if (GUILayout.Button("Delete"))
        {
            //Debug.Log("model "+ model);
            model.unrelate(r);
            model.selectedRelation        = null;
            model.selectedRelationInGraph = null;
        }
        if (GUILayout.Button("Cancel"))
        {
            r.revert();
            model.selectedRelationInGraph = null;
            model.selectedRelation        = null;
        }
        EditorGUILayout.EndHorizontal();

//		labelStyle.alignment = textAlignment;
//		labelStyle.fixedWidth = fixedWidth;
    }