zoukankan      html  css  js  c++  java
  • Unity 编辑器开发SceneView GUI控制

    前几天项目需要就做了个类似于Collider EditCollider的功能

    下面是我做的效果

    基础代码如下:

    public class ExportCFGInputWindow : EditorWindow
    {
        public static ExportCFGInputWindow instance;
        Vector3 dot1, dot2, dot3, dot4;
      
        void OnEnable() {
            instance = this;
            SceneView.duringSceneGui -= this.OnSceneGUI;
            SceneView.duringSceneGui += this.OnSceneGUI;
            dot1 = new Vector3(0, 0, 0);
            dot2 = new Vector3(0, 0, 1);
            dot3 = new Vector3(1, 0, 1);
            dot4 = new Vector3(1, 0, 0);
            mid1Cor = Color.green;
            mid2Cor = Color.green;
            mid3Cor = Color.green;
            mid4Cor = Color.green;
        }
        void OnDisable() {
            instance = null;
            SceneView.duringSceneGui -= this.OnSceneGUI;
        }
    
      
        void OnSceneGUI(SceneView sceneView)
        {
            Handles.color = Color.green;
            Handles.DrawAAPolyLine(2, dot1, dot2, dot3, dot4, dot1);
     
        }
    
    }
    

    效果如图

    下面是我踩的坑

        先不管先把小绿点画于是我在OnSceneGui方法里面插入了如下代码

    void OnSceneGUI(SceneView sceneView)
        {
            Handles.color = Color.green;
            Handles.DrawAAPolyLine(2, dot1, dot2, dot3, dot4, dot1);
    
             Handles.DotHandleCap(0, new Vector3((dot1.x + dot2.x) * 0.5f, 0, (dot1.z + dot2.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);

          //0.005f * sceneView.size 的作用是让小绿点无论你把场景放大或者缩小都是一样大。

    Handles.DotHandleCap(0, new Vector3((dot2.x + dot3.x) * 0.5f, 0, (dot2.z + dot3.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint); Handles.DotHandleCap(0, new Vector3((dot3.x + dot4.x) * 0.5f, 0, (dot3.z + dot4.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint); Handles.DotHandleCap(0, new Vector3((dot4.x + dot1.x) * 0.5f, 0, (dot4.z + dot1.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint); }

        这是画完绿点的样子

        虽然有了绿点但是没法控制于是我写了个方法来监听鼠标,这个方法在OnSceneGUI函数中调用。具体思路是:绿点的位置知道,只要监听鼠标在绿点下按下然后移动鼠标,我控制绿点两端的点跟着鼠标移动就可以完成了。

        但是!万事都怕但是。出现了一个令我头大的问题:鼠标左键的EventType.MouseUp事件我监听不到(这个问题求好心人帮忙解释一下。)导致我无法停止对相应点的控制,当然鼠标中键和鼠标右键没有问题,但是鼠标中键和鼠标右键会在编辑器下有其他操作。于是我放弃了这个思路。(这里代码就不上了)

        既然鼠标不行被逼无奈我就使用了键盘控制的方式 ,思路如下:

          4键控制上图最左边的小绿点,8键控制最上面的小绿点,6键控制最右面的小绿点,2键控制最下面的小绿点。+键表示该点向外伸,-键表示该点向外内缩。

        下面是代码

    int ExportDir = 0;//移动方向
    void CheckKey()//这个方法在OnSeneGui函数中调用 { Event e = Event.current; if (e.type == EventType.KeyDown) { if (e.keyCode == KeyCode.Keypad4) { ExportDir = 4; mid1Cor = Color.red; mid2Cor = Color.green; mid3Cor = Color.green; mid4Cor = Color.green; } if (e.keyCode == KeyCode.Keypad6) { ExportDir = 6; mid1Cor = Color.green; mid2Cor = Color.green; mid3Cor = Color.red; mid4Cor = Color.green; } if (e.keyCode == KeyCode.Keypad2) { ExportDir = 2; mid1Cor = Color.green; mid2Cor = Color.green; mid3Cor = Color.green; mid4Cor = Color.red; } if (e.keyCode == KeyCode.Keypad8) { ExportDir = 8; mid1Cor = Color.green; mid2Cor = Color.red; mid3Cor = Color.green; mid4Cor = Color.green; } if (e.keyCode == KeyCode.KeypadPlus) { //ExportDir = 4; Plus(ExportDir); } if (e.keyCode == KeyCode.KeypadMinus) { //ExportDir = 4; Minus(ExportDir); } } }
      float EditorSpeed = 0.05f; void Plus(int dir) { if (dir == 4) { dot1.x -= EditorSpeed; dot2.x -= EditorSpeed; } else if (dir == 6) { dot3.x += EditorSpeed; dot4.x += EditorSpeed; } else if (dir == 2) { dot1.z -= EditorSpeed; dot4.z -= EditorSpeed; } else if (dir == 8) { dot2.z += EditorSpeed; dot3.z += EditorSpeed; } else { return; } } void Minus(int dir) { if (dir == 4) { dot1.x += EditorSpeed; dot2.x += EditorSpeed; } else if (dir == 6) { dot3.x -= EditorSpeed; dot4.x -= EditorSpeed; } else if (dir == 2) { dot1.z += EditorSpeed; dot4.z += EditorSpeed; } else if (dir == 8) { dot2.z -= EditorSpeed; dot3.z -= EditorSpeed; } else { return; } }

          这样一来我先按下数字键4在按下+键最左边的点就会向左移动了

          为了显示清楚我还对小绿点显示颜色左了相应的处理,当选择哪个点做动作时它就会变红,代码如下

    Color    mid1Cor = Color.green;
    Color    mid2Cor = Color.green;
    Color    mid3Cor = Color.green;
    Color    mid4Cor = Color.green;
    void OnSceneGUI(SceneView sceneView)
        {
            Handles.color = Color.green;
            Handles.DrawAAPolyLine(2, dot1, dot2, dot3, dot4, dot1);
    
            
             Handles.color = mid1Cor;
             Handles.DotHandleCap(0, new Vector3((dot1.x + dot2.x) * 0.5f, 0, (dot1.z + dot2.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid2Cor;
             Handles.DotHandleCap(0, new Vector3((dot2.x + dot3.x) * 0.5f, 0, (dot2.z + dot3.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid3Cor;
             Handles.DotHandleCap(0, new Vector3((dot3.x + dot4.x) * 0.5f, 0, (dot3.z + dot4.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid4Cor;
             Handles.DotHandleCap(0, new Vector3((dot4.x + dot1.x) * 0.5f, 0, (dot4.z + dot1.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             CheckKey();
           
        }
    

        效果如下:

      这个功能也能勉强满足需求,暂时就这样了。

      后来有一天,我发现有人这样用

     Handles.FreeMoveHandle(target.pos,Quaternion.identity,2.0,Vector3.zero,Handles.DrawRectangle);
    

      Handles类的FreeMoveHandle函数我马上查了一下API发现

    public static Vector3 FreeMoveHandle(Vector3 position, Quaternion rotation, float size, Vector3 snap, DrawCapFunction capFunc);
    

      最后一个参数是个委托。我一下子就明白改怎么弄了。代码如下

     void OnSceneGUI(SceneView sceneView)
        {
            Handles.color = Color.green;
            Handles.DrawAAPolyLine(2, dot1, dot2, dot3, dot4, dot1);
    
             float m1px = Handles.FreeMoveHandle(new Vector3((dot1.x + dot2.x) * 0.5f, 0, (dot1.z + dot2.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).x;
             dot1 = new Vector3(m1px, 0, dot1.z);
             dot2 = new Vector3(m1px, 0, dot2.z);
    
             float m2px = Handles.FreeMoveHandle(new Vector3((dot2.x + dot3.x) * 0.5f, 0, (dot2.z + dot3.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).z;
             dot2 = new Vector3(dot2.x, 0, m2px);
             dot3 = new Vector3(dot3.x, 0, m2px);
    
             float m3px = Handles.FreeMoveHandle(new Vector3((dot3.x + dot4.x) * 0.5f, 0, (dot3.z + dot4.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).x;
             dot3 = new Vector3(m3px, 0, dot3.z);
             dot4 = new Vector3(m3px, 0, dot4.z);
    
             float m4px = Handles.FreeMoveHandle(new Vector3((dot4.x + dot1.x) * 0.5f, 0, (dot4.z + dot1.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).z;
             dot4 = new Vector3(dot4.x, 0, m4px);
             dot1 = new Vector3(dot1.x, 0, m4px);
    
        }
    

      这样就达到了我想要的鼠标控制小绿点的效果。但是键盘控制的代码我也保留了,因为我觉得这是个教训,而且在有时候键盘控制也蛮方便的。

    完整代码如下:

    public class ExportCFGInputWindow : EditorWindow
    {
        public static ExportCFGInputWindow instance;
        Vector3 dot1, dot2, dot3, dot4;
        Color mid1Cor, mid2Cor, mid3Cor, mid4Cor;
        int ExportDir = 0;
        float EditorSpeed = 0.05f;
        void OnEnable() {
            instance = this;
            SceneView.duringSceneGui -= this.OnSceneGUI;
            SceneView.duringSceneGui += this.OnSceneGUI;
            dot1 = new Vector3(0, 0, 0);
            dot2 = new Vector3(0, 0, 1);
            dot3 = new Vector3(1, 0, 1);
            dot4 = new Vector3(1, 0, 0);
            mid1Cor = Color.green;
            mid2Cor = Color.green;
            mid3Cor = Color.green;
            mid4Cor = Color.green;
        }
        void OnDisable() {
            instance = null;
            SceneView.duringSceneGui -= this.OnSceneGUI;
        }
    
        Vector3 m1, m2, m3, m4;
        void OnSceneGUI(SceneView sceneView)
        {
            Handles.color = Color.green;
            Handles.DrawAAPolyLine(2, dot1, dot2, dot3, dot4, dot1);
    
             #region 鼠标控制
             float m1px = Handles.FreeMoveHandle(new Vector3((dot1.x + dot2.x) * 0.5f, 0, (dot1.z + dot2.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).x;
             dot1 = new Vector3(m1px, 0, dot1.z);
             dot2 = new Vector3(m1px, 0, dot2.z);
    
             float m2px = Handles.FreeMoveHandle(new Vector3((dot2.x + dot3.x) * 0.5f, 0, (dot2.z + dot3.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).z;
             dot2 = new Vector3(dot2.x, 0, m2px);
             dot3 = new Vector3(dot3.x, 0, m2px);
    
             float m3px = Handles.FreeMoveHandle(new Vector3((dot3.x + dot4.x) * 0.5f, 0, (dot3.z + dot4.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).x;
             dot3 = new Vector3(m3px, 0, dot3.z);
             dot4 = new Vector3(m3px, 0, dot4.z);
    
             float m4px = Handles.FreeMoveHandle(new Vector3((dot4.x + dot1.x) * 0.5f, 0, (dot4.z + dot1.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap).z;
             dot4 = new Vector3(dot4.x, 0, m4px);
             dot1 = new Vector3(dot1.x, 0, m4px);
             #endregion
    
             #region 键盘控制
             Handles.color = mid1Cor;
             Handles.DotHandleCap(0, new Vector3((dot1.x + dot2.x) * 0.5f, 0, (dot1.z + dot2.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid2Cor;
             Handles.DotHandleCap(0, new Vector3((dot2.x + dot3.x) * 0.5f, 0, (dot2.z + dot3.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid3Cor;
             Handles.DotHandleCap(0, new Vector3((dot3.x + dot4.x) * 0.5f, 0, (dot3.z + dot4.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             Handles.color = mid4Cor;
             Handles.DotHandleCap(0, new Vector3((dot4.x + dot1.x) * 0.5f, 0, (dot4.z + dot1.z) * 0.5f), Quaternion.identity, 0.005f * sceneView.size, EventType.Repaint);
             CheckKey();
             #endregion
             
        }
       
        void CheckKey()
        {
            Event e = Event.current;
            if (e.type == EventType.KeyDown)
            {
                
                if (e.keyCode == KeyCode.Keypad4)
                {
                    ExportDir = 4;
                    mid1Cor = Color.red;
                    mid2Cor = Color.green;
                    mid3Cor = Color.green;
                    mid4Cor = Color.green;
                }
                if (e.keyCode == KeyCode.Keypad6)
                {
                    ExportDir = 6;
                    mid1Cor = Color.green;
                    mid2Cor = Color.green;
                    mid3Cor = Color.red;
                    mid4Cor = Color.green;
                }
                if (e.keyCode == KeyCode.Keypad2)
                {
                    ExportDir = 2;
                    mid1Cor = Color.green;
                    mid2Cor = Color.green;
                    mid3Cor = Color.green;
                    mid4Cor = Color.red;
                }
                if (e.keyCode == KeyCode.Keypad8)
                {
                    ExportDir = 8;
                    mid1Cor = Color.green;
                    mid2Cor = Color.red;
                    mid3Cor = Color.green;
                    mid4Cor = Color.green;
                }
                if (e.keyCode == KeyCode.KeypadPlus)
                {
                    //ExportDir = 4;
                    Plus(ExportDir);
                }
                if (e.keyCode == KeyCode.KeypadMinus)
                {
                    //ExportDir = 4;
                    Minus(ExportDir);
                }
            }
           
        }
        void Plus(int dir)
        {
    
            if (dir == 4)
            {
                dot1.x -= EditorSpeed;
                dot2.x -= EditorSpeed;
            }
            else if (dir == 6)
            {
                dot3.x += EditorSpeed;
                dot4.x += EditorSpeed;
            }
            else if (dir == 2)
            {
                dot1.z -= EditorSpeed;
                dot4.z -= EditorSpeed;
            }
            else if (dir == 8)
            {
                dot2.z += EditorSpeed;
                dot3.z += EditorSpeed;
            }
            else
            {
                return;
            }
        }
        void Minus(int dir)
        {
    
            if (dir == 4)
            {
                dot1.x += EditorSpeed;
                dot2.x += EditorSpeed;
            }
            else if (dir == 6)
            {
                dot3.x -= EditorSpeed;
                dot4.x -= EditorSpeed;
            }
            else if (dir == 2)
            {
                dot1.z += EditorSpeed;
                dot4.z += EditorSpeed;
            }
            else if (dir == 8)
            {
                dot2.z -= EditorSpeed;
                dot3.z -= EditorSpeed;
            }
            else
            {
                return;
            }
        }
        private void OnGUI()
        {
            GUILayout.BeginVertical();
            //标签
            GUILayout.BeginHorizontal();
            GUILayout.Box("输入相应的参数", TitleBoxStyle(), GUILayout.Height(60),GUILayout.ExpandWidth(true));
            GUILayout.EndHorizontal();
            GUILayout.Space(10);
            
            GUILayout.BeginHorizontal();
            GUIStyle boxStyle = new GUIStyle();
            boxStyle.alignment = TextAnchor.MiddleCenter;
            GUILayout.Box("当前移动速度"+ EditorSpeed, boxStyle, GUILayout.Height(30), GUILayout.Width(80));
            GUILayout.Space(10);
            EditorSpeed = GUILayout.HorizontalSlider(EditorSpeed, 0.01f, 1);
            GUILayout.EndHorizontal();
           
            GUILayout.EndVertical();
        }
       
      
    }
    

      希望这次的分享对大家有点收获,不好的地方希望大家能帮我指出。

  • 相关阅读:
    HOWTO re
    数据类型
    字符串
    最大公约数
    this
    tip 2:找最小公倍数之Boost
    tip 1:一个简单的将int型转换成char的方法
    Item47
    成员函数模板
    item44:将与参数无关的代码抽离template
  • 原文地址:https://www.cnblogs.com/littlebao/p/12359258.html
Copyright © 2011-2022 走看看