Unity功能开发之_(单选、多选、框选)

 

 

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.EventSystems;
using UnityEngine.UI;


/// 
/// 功能:单选、多选(按住左边的Ctrl+点击)、框选
/// 
public enum State
{
    OnLeft,
    OnCtrlLeft
}


public class MultipleSelection : MonoBehaviour
{
 
    //定义一根射线
    private Ray ray;
    //枚举默认的点击状态是左键点击的状态
    private State clickState = State.OnLeft;
    private Vector3 v1, v2;
  


    //************弹窗信息

    //info面板
   // public GameObject infoPanel;
    //碰撞信息
    private RaycastHit hitInfo;


    //画线的材质
    // public Material mat;
    //鼠标一开始点击的位置
    private Vector2 FirstMouseposition;
    //鼠标松开的位置
    private Vector2 SecondMousePosition;
    //是否画线标志位
    private bool StartRender = false;
    //renderer数组用来保存各个对象身上的组件
    private Renderer[] gameObjects;
    //单选和框选的标志位
    private bool isKuangxuan=false;
    //用来存储每次点击的对象以及对象的颜色
    private Dictionary dict;
    //鼠标点击的对象
    private GameObject clickGameObject;

   // public RectTransform rectTrans;
    //public RectTransform objRectTrans;
    //选择到的对象,用来做显示隐藏
    public static List objlist = new List();

   // BoxCollider[] objCollider;

    //获取renderer中心点所需要的变量
    float xmax = 0;
    float ymax = 0;
    float zmax = 0;
    float xmin = 0;
    float ymin = 0;
    float zmin = 0;

    void Start()
    {
        dict = new Dictionary();
        //找到对象中含有的renderer组件
        gameObjects = FindObjectsOfType();
      //  objCollider = FindObjectsOfType();
    }
   

    void Update()
    {
        

        //**********************多选
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetMouseButtonDown(0))
        {
            objlist.Clear();
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hitInfo))
            {
                //得到当前点击物体的颜色,并放入字典中
                OnChangeColor();
                objlist.Add(hitInfo.transform.gameObject);
            }

        }
        else
        if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
        {
            //点击空白处,清空
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hitInfo))
            {
                if (hitInfo.collider)
                {
                   // infoPanel.gameObject.SetActive(false);
                    RecoverColor();
                    clickState = State.OnCtrlLeft;
                    objlist.Clear();
                }
            }
            else
            {
               // infoPanel.gameObject.SetActive(false);
                RecoverColor();
                clickState = State.OnCtrlLeft;
                objlist.Clear();
            }

        }
        //点击ESC键,清空选中
        if (Input.GetKey(KeyCode.Escape))
        {
           // infoPanel.gameObject.SetActive(false);
            RecoverColor();
            clickState = State.OnCtrlLeft;
            objlist.Clear();
        }
                
        if (clickState != State.OnLeft)
        {
            //鼠标左键单击的时候
            if (Input.GetMouseButtonDown(0))
            {
                v1 = Input.mousePosition;
                StartRender = true;
                FirstMouseposition = Input.mousePosition;
                //选取对象
                //PickGameObject();
                isKuangxuan = true;

            }
        }
        if (Input.GetMouseButtonUp(0) && isKuangxuan == true)
        {
            objlist.Clear();
            v2 = Input.mousePosition;
            if (Vector3.Distance(v1, v2) < 1)
            {
                StartRender = false;

                ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                //******************单选
                if (Physics.Raycast(ray, out hitInfo))
                {
                    OnChangeColor();
                    objlist.Add(hitInfo.transform.gameObject);
                }
            }
            
            else
            {
                //******************框选
                StartRender = false;
                ChangeTwoPoint();
                //将线框里的对象都进行变色处理
                PickGameObject();
                //选择完毕后,将两个点归0
                FirstMouseposition = SecondMousePosition = Vector2.zero; 
            }
            
            isKuangxuan = false;

        }
        SecondMousePosition = Input.mousePosition;


        clickState = State.OnLeft;

      
    }

    /// 
    /// 存储原色,以及变色
    /// 
    void OnChangeColor()
    {
        clickGameObject = hitInfo.transform.gameObject;
        if (dict.ContainsKey(clickGameObject)) return;
        dict.Add(clickGameObject, clickGameObject.GetComponent().material.color);
        if (clickGameObject.GetComponent().material.color == Color.blue)
            clickGameObject.GetComponent().material.color = new Color(0,0.5f,1);
        else
            clickGameObject.GetComponent().material.color = Color.blue;
    }
    /// 
    /// 恢复颜色
    /// 
    void RecoverColor()
    {
        //遍历字典让颜色恢复到原来的状态
        if (dict.Count != 0)
        {
            foreach (var kvp in dict)
            {
                kvp.Key.GetComponent().material.color = kvp.Value;
            }
            dict.Clear();
        }
    }

    //OnPostRender在相机渲染完所有物体之后被调用。只有该脚本
    //附于相机并启用时才会调用这个函数。OnPostRender可以是一个协同程序,在函数中调用yield语句即
    void OnPostRender()
    {
        if (StartRender)
        {
            //激活第一个pass,设置材质通道
            // mat.SetPass(0);
            GL.Color(Color.green);
            //辅助函数用来做一个正交投影变换,用来绘制2D图形
            GL.LoadOrtho();
            //开始绘制四边形
            GL.Begin(GL.LINES);
            DrawLine(FirstMouseposition.x, FirstMouseposition.y, SecondMousePosition.x, SecondMousePosition.y);
            GL.End();
        }
    }


    void DrawLine(float x1, float y1, float x2, float y2)
    {
        GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
        GL.Vertex(new Vector3(x2 / Screen.width, y1 / Screen.height, 0));
        GL.Vertex(new Vector3(x2 / Screen.width, y1 / Screen.height, 0));
        GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
        GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
        GL.Vertex(new Vector3(x1 / Screen.width, y2 / Screen.height, 0));
        GL.Vertex(new Vector3(x1 / Screen.width, y2 / Screen.height, 0));
        GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
    }

    void ChangeTwoPoint()
    {
        //右下角往左上方向进行框选
        if (FirstMouseposition.x > SecondMousePosition.x)
        {
            float position1 = FirstMouseposition.x;
            FirstMouseposition.x = SecondMousePosition.x;
            SecondMousePosition.x = position1;
        }

        //左上角往右下方向进行框选
        if (FirstMouseposition.y > SecondMousePosition.y)
        {
            float position2 = FirstMouseposition.y;
            FirstMouseposition.y = SecondMousePosition.y;
            SecondMousePosition.y = position2;
        }
    }

    //框选对象
    void PickGameObject()
    {
        objlist.Clear();
        foreach (Renderer item in gameObjects)
        {
            Vector3 position = Camera.main.WorldToScreenPoint(GetCenterPoint(item));
            if (position.x >= FirstMouseposition.x & position.x <= SecondMousePosition.x & position.y >= FirstMouseposition.y & position.y <= SecondMousePosition.y)
            {
                //if (dict.ContainsKey(clickGameObject)) return;
                dict.Add(item.gameObject, item.material.color);
                item.material.color = Color.blue;
                objlist.Add(item.transform.gameObject);
            }
        }
        
    }
    //获取renderer组件的中心点
    Vector3 GetCenterPoint(Renderer render)
    {
        Vector3 vmax = render.bounds.max;
        Vector3 vmin = render.bounds.min;
        xmax = vmax.x;
        ymax = vmax.y;
        zmax = vmax.z;
        xmin = vmin.x;
        ymin = vmin.y;
        zmin = vmin.z;
        return (new Vector3((xmax + xmin) * 0.5f, (ymax + ymin) * 0.5f, (zmax + zmin) * 0.5f));
    }


}

 

你可能感兴趣的:(Unity,功能实现)