Editor loses reference after any value is changed

Hello folks,

I come once more asking for guidance, I am currently working on extending the editor with a basic mesh processing tool to create procedural walls, but in the attempt of moving some vertices, I found out that the way I was using an Editor script was probably wrong, and all the code I wrote until then worked “by accident”.

The situation is the following: I have a GameObject with a WallsHandler component attached. The WallsHandler is used to handle (what a surprise) a particular mesh I have generated with another component. All the work done by WallsHandler is actually done by its Editor script called WallsHandlerEditor, as the script is only meant to be used in editor mode. This Editor script has several features, including the possibility of cutting a window inside the associated mesh, users can click any triangle on the mesh, and if some parameters are validated, it creates the actual window “hole” and attach a collider to its position. This collider is stored inside an array of BoxCollider. When the user hits one of those colliders, a button is displayed on top of the window, and if the button is clicked, an EditorWindow called fixtureWindow is displayed. Here’s a screen of the result:

So far so good, what is really bothering me is the actual process of editing the window. Every modification I do inside this fixtureWindowis is successfully applied to my WallsHandlerEditor and its associated mesh, but the boolean value I was using to check whether the window is open or not is reset. When this boolean is equal to true, I also draw a Handler to freely move the window along its normals (as you can see from the picture above). What I really cannot understand is why, just after any change is made (both if i move the handler or inside the fixtureWindow) the boolean control value is turned to false and the handler disappears. My code has NO WAY to reset that value, and I literally have no idea why this is happening. What makes it even more strange is that even if the value is turned to false, the EditorWindow can still edit the mesh…

This is part of WallsHandlerEditor code:

[InitializeOnLoad]
[CustomEditor(typeof(WallsHandler))]
public class WallsHandlerEditor : Editor {
   public bool hasSomethingToDisplay = false;
   public bool fixtureEditMode = false;
   public Vector3 showCenter = new Vector3();
   public int index = -1;
   WallsHandler _target;
  
  void OnEnable(){
     // Debug.Log("INSERT HELP TOOLBOX FOR FIXING THE PLANE TRANSFORM");
     _target = (WallsHandler)target;
   }
void OnSceneGUI(){
     if(fixtureEditMode){
       Debug.Log("works");
       Handles.color = Color.yellow;
       // ONCE I GET THE RIGHT NORMALS, I CAN JUST GRAB THE WINDOW ONE IN THIS DIRECTION
       Vector3 a = _target.fixtures[index].face1Window[0];
       Vector3 b = _target.fixtures[index].face1Window[3];
       Vector3 c = _target.fixtures[index].face2Window[2];
       Vector3 side1 = b - a;
       Vector3 side2 = c - a;
       Vector3 perp = Vector3.Cross(side1, side2);  
       EditorGUI.BeginChangeCheck();
  
       Vector3 lookTarget = Handles.Slider(showCenter, perp);
       if (EditorGUI.EndChangeCheck())
     {
       float distn = Vector3.Distance(showCenter, lookTarget);
         float movDistance = System.Convert.ToSingle(System.Math.Round(distn,4));

         //NEED TO FIND THE LEFT AND RIGHT EMPTY SPACES AT FIRST
         //index IS THE CURRENT fixtures INDEX
         fixture curFixture = _target.fixtures[index];
         int leftCompanion1 = findAdjacentFace(curFixture.face1[1], curFixture.face1[3]);
        
         Mesh m = _target.gameObject.GetComponent<MeshFilter>().sharedMesh;

         int leftCompanion2 = findCompanionIndex( leftCompanion1, m);
        
         int rightCompanion1 = findAdjacentFace(curFixture.face1[0], curFixture.face1[2]);
         int rightCompanion2 = findCompanionIndex( rightCompanion1, m);
         Vector3[] side1Verts = getOrderedVertices(leftCompanion1, leftCompanion2, _target.gameObject.GetComponent<MeshFilter>().sharedMesh);
         Vector3[] side2Verts = getOrderedVertices(rightCompanion1, rightCompanion2, _target.gameObject.GetComponent<MeshFilter>().sharedMesh);

         //calculate difference between current and new width, check if there's enough space, and in case, apply
         // CURRENT WINDOW WIDTH + OFFSET, MANAGE IN A DIFFERENT WAY THE OFFSET
         Vector3 midPoint = Vector3.Lerp(curFixture.face1[0], curFixture.face1[1], 0.5f); // GETTING THE CENTRAL POINT OF THE WINDOWS. USING THE TOP ONES, IT IS IRRELEVANT
         float availableLeftSpace;
         float availableRightSpace;
      
         //AVAILABLE SPACE IS CALCULATED ON ONLY ONE SIDE, AS IT IS ALWAYS GRANTED TO BE EVEN
         if(side1Verts[0] == curFixture.face1[1]){
           float distance = Vector3.Distance(curFixture.face1[1], side1Verts[1]);
           availableLeftSpace = System.Convert.ToSingle(System.Math.Round(distance,4));
         } else {
           float distance = Vector3.Distance(curFixture.face1[1], side1Verts[0]);
           availableLeftSpace = System.Convert.ToSingle(System.Math.Round(distance,4));
         }
         if(side2Verts[1] == curFixture.face1[0]){
           float distance = Vector3.Distance(curFixture.face1[0], side2Verts[0]);
           availableRightSpace = System.Convert.ToSingle(System.Math.Round(distance,4));
         } else {
           float distance = Vector3.Distance(curFixture.face1[0], side2Verts[1]);
           availableRightSpace = System.Convert.ToSingle(System.Math.Round(distance,4));
         }
         //TRUE IS MOVING LEFT, FALSE IS MOVING RIGHT
         bool moveDirection = true;
         if(moveDirection){
           if(availableLeftSpace-movDistance >= 0.2f){
             DestroyImmediate(_target.gameObject.GetComponent<MeshCollider>());
             Mesh locMesh = _target.transform.GetComponent<MeshFilter>().sharedMesh;
             Vector3[] oldVerts = locMesh.vertices;
             Vector3[] newVerts = new Vector3[oldVerts.Length];
            
             //I COULD RETRIEVE THE INDEXES AT THE BEGINNING AND NOT SEARCH FOR THEM EVERY TIME
             // ALSO, THERE IS NO POINT IN MOVING TOWARDS SIDEVERTS,
             // I COULD SIMPLY MOVE AWAY OR CLSOER TO THE OPPOSITE WINDOW VERTEX
             for(int i = 0; i < oldVerts.Length;i++){
               // EXTERNAL VERTS LEFT SIDE
               if(oldVerts[i] == curFixture.face1[1]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1[0], -movDistance);
               } else if(oldVerts[i] == curFixture.face1[3]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1[2], -movDistance);
               } else if(oldVerts[i] == curFixture.face2[0]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2[1], -movDistance);
               } else if(oldVerts[i] == curFixture.face2[2]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2[3], -movDistance);
               }
               // INTERNAL VERTS LEFT SIDE
               else if(oldVerts[i] == curFixture.face1Window[1]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1Window[3], -movDistance);
               } else if(oldVerts[i] == curFixture.face1Window[2]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1Window[0], -movDistance);
               } else if(oldVerts[i] == curFixture.face2Window[0]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2Window[2], -movDistance);
               } else if(oldVerts[i] == curFixture.face2Window[3]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2Window[1], -movDistance);
               }
               // EXTERNAL VERTS RIGHT SIDE
               else if(oldVerts[i] == curFixture.face1[0]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1[1], -movDistance);
               } else if(oldVerts[i] == curFixture.face1[2]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1[3], -movDistance);
               } else if(oldVerts[i] == curFixture.face2[1]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2[0], -movDistance);
               } else if(oldVerts[i] == curFixture.face2[3]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2[2], -movDistance);
               }
               // INTERNAL VERTS RIGHT SIDE

               else if(oldVerts[i] == curFixture.face1Window[0]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1Window[2], -movDistance);
               } else if(oldVerts[i] == curFixture.face1Window[3]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face1Window[1], -movDistance);
               } else if(oldVerts[i] == curFixture.face2Window[1]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2Window[3], -movDistance);
               } else if(oldVerts[i] == curFixture.face2Window[2]){
                 newVerts[i] = Vector3.MoveTowards(oldVerts[i], curFixture.face2Window[0], -movDistance);
               }
               //IT'S A COMMON VERTEX
               else {
                 newVerts[i] = oldVerts[i];
               }
             }

             _target.transform.GetComponent<MeshFilter>().sharedMesh.vertices = newVerts;
             _target.gameObject.AddComponent<MeshCollider>();
             Debug.Log("here");
           }
         }
       }
     }
}

and this is the fixtureWindow code:

using UnityEngine;
using UnityEditor;


public class fixtureWindow : EditorWindow {
   WallsHandlerEditor editor;
   fixture currentFixture;
   public float width;
   public float height;
   public float heightfromGround;
   public float borderDistance = 0.2f; //MINIMUM DISTANCE OF NODES FROM THE CANVAS

   public void Init(WallsHandlerEditor e, fixture fixt){
     editor = e;
     currentFixture = fixt;
     height = fixt.face1Window[2].y - fixt.face1Window[1].y;
     heightfromGround = currentFixture.face1Window[1].y;
     width = Vector3.Distance(fixt.face1Window[1], fixt.face1Window[3]);
   }

   void OnDestroy(){
     Debug.Log("Destroy");
     editor.exitEditMode();
   }

   void OnGUI(){
     EditorGUI.BeginChangeCheck();
       width = EditorGUILayout.FloatField("Width", width);
       if(EditorGUI.EndChangeCheck()){
         editor.checkNewWidth(width);
       }

     EditorGUI.BeginChangeCheck();
       height = EditorGUILayout.FloatField("Height", height);
       if(EditorGUI.EndChangeCheck()){
         editor.checkNewWindowHeight(height, borderDistance);
         heightfromGround = currentFixture.face1Window[1].y;
         this.Repaint();
       }

     //CHECKING WHETHER THE HEIGHT FROM GROUND WAS CHANGED OR NOT
     EditorGUI.BeginChangeCheck();
       heightfromGround = EditorGUILayout.FloatField("Height from Ground", heightfromGround);
       if (EditorGUI.EndChangeCheck()){
         if(heightfromGround < borderDistance){
           heightfromGround = borderDistance;
         }
  float maxHeight = currentFixture.face1[0].y - borderDistance - (currentFixture.face1Window[0].y - currentFixture.face1Window[1].y);
  if(heightfromGround > (maxHeight)){
  heightfromGround = (maxHeight);
  }
         editor.checkNewHeightFromGround(heightfromGround);
       }
    
  if (GUILayout.Button("Delete window")){
     Debug.Log("TODO");
  }
   }
  
}

Ignoring the heavily not optimized code, what could be possibly causing the problem? I tried to debug OnEnable and it is not called, what is changing that value? Why fixtureWindow keeps track of the editor but the editor bool control is reset?

Up, I could really use some help here…

Editor windows can be a little tricky to get to play nicely with others.

Without testing, one quick thing you can try is to serilalize your bools in the editor script. Since it defaults to false, changing focus may be causing it to “forget” its values and return to false. See if that works.

Thanks for replying me. Serialization could be a solution, but I’ve been working with the Editor for six months now and I love the way I can play with it and create new functionalities from scratch. I was more worried about doing something wrong rather than making it work :stuck_out_tongue: I’ll probably stick to your suggestion and find a workaround for the problem, but I’ll also try to make a simple test case and submit it to Unity if it doesn’t work :slight_smile: Thanks again!