BeGear.cs

来源:互联网 发布:软妹小九九淘宝店名字 编辑:程序博客网 时间:2024/06/16 22:50
using System.Collections.Generic;using System.Linq;using UnityEngine;[ExecuteInEditMode]public class BeGear : MonoBehaviour{    #region 委托声明    public delegate void VoidDelegate();    public event VoidDelegate onDoSelect;    public void DoSelect() { if (onDoSelect != null) onDoSelect(); }    #endregion    #region 公共变量    public int Depth = 1;    public UIAtlas GearWidgetAtlas;    public string GearSpriteName;    public string NormalItemSpriteName;    public string ActiveItemSpriteName;    public string HintSpriteName;    public Vector2 GearSize = new Vector2(800, 800);    public Vector2 ItemSize = new Vector2(750, 120);    public Vector2 EllipseSize = new Vector2(800, 1600);    public bool IsUnifyItemScale = false;    public float NestleAccuracy = 0.01f;    [Range(50, 200)]    public int SpacingDistance;    #endregion    #region 公共属性    public UIAtlas CurrentAtlas { get; internal set; }    public int CurrentSelectIndex { get; internal set; }    public string CurrentSelectSpriteName { get; internal set; }    public bool IsAccordingToAtlasToIndex { get; set; }    #endregion    #region 私有变量    Camera m_camera;    GameObject m_gear;    GameObject m_itemScroll;    GameObject m_selectedItem;    GameObject m_lastHint;    bool m_isDragging;    Dictionary<string, UISpriteData> m_currentDictionary = new Dictionary<string, UISpriteData>();    UIFont m_optionFont;    Color m_optionFontColor;    UIFont m_hintFont;    Color m_hintColor;    string m_hint;    Vector2 m_photoSize;    int m_intervalWithLeft;    int m_intervalWithIcon;    bool m_isNeedUpdate;    bool m_isNeedHint = true;//默认显示提示信息    #endregion    #region 私有属性    Vector3 Location { get { return transform.localPosition; } }    float Scale { get { return IsUnifyItemScale ? Mathf.Min(m_gear.transform.localScale.x, m_gear.transform.localScale.y) : 1; } }    float OvalValueA { get { return (EllipseSize.x + ItemSize.x) / 2 * Scale; } }    float OvalValueB { get { return (EllipseSize.y + ItemSize.y) / 2 * Scale; } }    float PieceAngle { get { return 90.0f / Mathf.FloorToInt(90 * OvalValueB / (90 * (ItemSize.y + SpacingDistance))); } }    float QuarterAngle { get { return Mathf.FloorToInt(90 / PieceAngle) * PieceAngle; } }    float MinAngle { get { return QuarterAngle + PieceAngle; } }    float MaxAngle { get { return QuarterAngle + PieceAngle * m_currentDictionary.Count; } }    float AngleAddUp { get; set; }    #endregion    #region 系统函数    void Start()    {        //初始化参数        m_camera = FindObjectOfType<UIRoot>().transform.Find("Camera").GetComponent<Camera>();        UICamera.currentCamera = m_camera;        CurrentSelectSpriteName = null;        CurrentSelectIndex = 0;//默认选中第一个        //清空子物体        gameObject.transform.DestroyChildren();        //重建滚轮        m_gear = newObject("gear", transform);        var gearSprite = m_gear.AddComponent<UISprite>();        gearSprite.atlas = GearWidgetAtlas;        gearSprite.spriteName = GearSpriteName;        gearSprite.depth = Depth;        gearSprite.width = Mathf.FloorToInt(GearSize.x);        gearSprite.height = Mathf.FloorToInt(GearSize.y);        gearSprite.autoResizeBoxCollider = true;        var gearCollider = m_gear.AddComponent<BoxCollider>();        gearCollider.isTrigger = true;        gearCollider.size = new Vector3(GearSize.x, GearSize.y, 0);        //注册滚轮监听        UIEventListener.Get(m_gear.gameObject).onDragStart = gearOnDragStart;        UIEventListener.Get(m_gear.gameObject).onDrag = gearOnDrag;        UIEventListener.Get(m_gear.gameObject).onDragEnd = gearOnDragEnd;        //重建列表        m_itemScroll = newObject("itemScroll", transform);        //重建选项        optionReset();    }    void Update()    {        //图集更换处理        if (m_isNeedUpdate)        {            optionReset();            m_isNeedUpdate = false;        }        //拖拽停止后贴靠最近的选项位        if (m_isDragging) return;        var residualAngle = AngleAddUp % PieceAngle;        //小于修正精度则退出        if (residualAngle < NestleAccuracy || PieceAngle - residualAngle < NestleAccuracy)        {            showHint();//修正完毕后显示提示信息            return;        }        if (residualAngle > PieceAngle / 2)        {//逆时针正数            chainRotate(residualAngle * 0.1f);        }        else        {//顺时针负数            chainRotate(-residualAngle * 0.1f);        }    }    #endregion    #region 调用函数    public void Init(Vector2 photoSize, int intervalWithLeft, int intervalWithIcon, UIFont optionFont, Color optionFontColor, UIAtlas atlas, Dictionary<string, UISpriteData> dic, int lastSelect, bool isAccordingToAtlasToIndex)    {        m_photoSize = photoSize;        m_intervalWithLeft = intervalWithLeft;        m_intervalWithIcon = intervalWithIcon;        m_optionFont = optionFont;        m_optionFontColor = optionFontColor;        CurrentAtlas = atlas;        m_currentDictionary.Clear();        m_currentDictionary = dic;        CurrentSelectIndex = lastSelect;        IsAccordingToAtlasToIndex = isAccordingToAtlasToIndex;        m_isNeedUpdate = true;    }    public void SetHint(UIFont hintFont, Color hintColor, string hint)    {        m_hintFont = hintFont;        m_hintColor = hintColor;        m_hint = hint;    }    #endregion    #region 计算函数    Vector3 getScreen(Vector2 location)    {        var pos = UICamera.currentCamera.ScreenToWorldPoint(new Vector3(location.x, location.y, 0f));        return UICamera.currentCamera.transform.InverseTransformPoint(pos);    }    Vector3 getTouchAxis(GameObject reference)    {        var center = reference.transform.localPosition + Location;        var touchPos = UICamera.currentTouch.pos;        var axis = getScreen(touchPos) - center;        return axis;    }    Vector3 getAngleToAxis(float angle)    {        var x = Mathf.Sin(angle * Mathf.Deg2Rad);        var y = Mathf.Cos(angle * Mathf.Deg2Rad);        return new Vector3(x, y);    }    float getAngleBetweenAxis(Vector3 axis1, Vector3 axis2, bool isClockwise = false, bool isJustOneside = false)    {        var cross = Vector3.Cross(axis1, axis2);        var angle = Vector3.Angle(axis1, axis2);        var round = isJustOneside ? 0 : 360;        var v = 0.0f;        if (isClockwise)        {            v = cross.z > 0 ? angle : round - angle;        }        else        {            v = cross.z < 0 ? angle : round - angle;        }        return v;    }    Vector2 getOvalAxis(Vector2 axis, float a, float b, bool isClockwise = false)    {        var cross = Vector3.Cross(axis, Vector2.right);        var angle = Vector2.Angle(axis, Vector2.right);        var deg360 = 0.0f;        if (isClockwise)        {            deg360 = cross.z > 0 ? angle : 360 - angle;        }        else        {            deg360 = cross.z < 0 ? angle : 360 - angle;        }        var t = deg360 * Mathf.Deg2Rad;        var bcost = b * Mathf.Cos(t);        var asint = a * Mathf.Sin(t);        var bcostp2 = Mathf.Pow(bcost, 2);        var asintp2 = Mathf.Pow(asint, 2);        var sqrt = Mathf.Sqrt(bcostp2 + asintp2);        var r = a * b / sqrt;        var x = r * Mathf.Cos(t);        var y = r * Mathf.Sin(t);        var v = new Vector2(x, y);        return v;    }    #endregion    #region 处理函数    static GameObject newObject(string objectName, Component parent)    {        var obj = new GameObject        {            name = objectName,            tag = parent.tag,            layer = parent.gameObject.layer        };        obj.transform.SetParent(parent.transform);        obj.transform.localScale = Vector3.one;        obj.transform.localPosition = Vector3.zero;        obj.transform.rotation = Quaternion.identity;        obj.transform.localEulerAngles = Vector3.zero;        return obj;    }    GameObject newItem(string itemName)    {        var item = newObject(itemName, m_itemScroll.transform);        var itemSprite = item.AddComponent<UISprite>();        itemSprite.atlas = GearWidgetAtlas;        itemSprite.depth = Depth;        itemSprite.width = Mathf.FloorToInt(ItemSize.x);        itemSprite.height = Mathf.FloorToInt(ItemSize.y);        itemSprite.autoResizeBoxCollider = true;        var itemCollider = item.AddComponent<BoxCollider>();        itemCollider.isTrigger = true;        itemCollider.size = new Vector3(itemSprite.width, itemSprite.height, 0);        return item;    }    void newOption(Component parent, int spriteIndex)    {        //设置标签        var label = newObject("label", parent).AddComponent<UILabel>();        label.depth = Depth + 1;        label.bitmapFont = m_optionFont;        var fontSize = m_optionFont.defaultSize;        label.fontSize = fontSize;        label.color = m_optionFontColor;        var currentName = getDictionaryKeyByIndex(m_currentDictionary, spriteIndex);        label.text = currentName;        label.width = currentName.Length * fontSize;        label.height = fontSize;        //设置图片        var photo = newObject("photo", parent);        var photoSprite = photo.AddComponent<UISprite>();        photoSprite.depth = Depth + 1;        photoSprite.atlas = CurrentAtlas;        photoSprite.spriteName = getDictionaryValueByIndex(m_currentDictionary, spriteIndex).name;        photoSprite.width = Mathf.FloorToInt(m_photoSize.x);        photoSprite.height = Mathf.FloorToInt(m_photoSize.y);        photoSprite.autoResizeBoxCollider = true;        //设置碰撞器        var photoCollider = photo.AddComponent<BoxCollider>();        photoCollider.isTrigger = true;        photoCollider.size = new Vector3(photoSprite.width, photoSprite.height, 0);        //注册监听        UIEventListener.Get(photo).onDragStart = optionOnDragStart;        UIEventListener.Get(photo).onDrag = optionOnDrag;        UIEventListener.Get(photo).onDragEnd = optionOnDragEnd;        //微调图标和标签位置        photo.transform.localPosition = new Vector3(m_intervalWithLeft - (ItemSize.x - photoSprite.width) / 2, 0, 0);        label.alignment = NGUIText.Alignment.Left;        var leftPos = photo.transform.localPosition.x + (float)(photoSprite.width + label.width) / 2 + m_intervalWithIcon;        label.transform.localPosition = new Vector3(leftPos, 0, 0);    }    GameObject newHint(Component parent, string hint)    {        var obj = newObject("hint", parent);        obj.transform.localPosition = new Vector3(100, 200);        var sprite = newObject("backdrop", obj.transform).AddComponent<UISprite>();        sprite.depth = Depth + 1;        sprite.atlas = GearWidgetAtlas;        sprite.spriteName = HintSpriteName;        sprite.MakePixelPerfect();        var label = obj.AddComponent<UILabel>();        label.depth = Depth + 2;        label.bitmapFont = m_hintFont;        label.alignment = NGUIText.Alignment.Left;        label.fontSize = 35;        label.color = m_hintColor;        label.text = hint;        label.width = sprite.width - 55;        label.height = sprite.height - 55;        return obj;    }    static TKey getDictionaryKeyByIndex<TKey, TValue>(Dictionary<TKey, TValue> dic, int index)    {        return dic.Keys.ToArray()[index];    }    static TValue getDictionaryValueByIndex<TKey, TValue>(Dictionary<TKey, TValue> dic, int index)    {        return dic.Values.ToArray()[index];    }    #endregion    #region 执行函数    void saveCurrentSelectSpriteName()    {        if (IsAccordingToAtlasToIndex)        {//图集索引模式            try            {                CurrentSelectSpriteName = CurrentAtlas.spriteList[CurrentSelectIndex].name;//尝试读取当前图像名            }            catch            {                CurrentSelectSpriteName = null;//索引失败            }        }        else        {//非图集索引模式            CurrentSelectSpriteName = null;//默认置空        }    }    void selectItem(Transform item)    {        var itemSprite = item.GetComponent<UISprite>();        //判断是否选中        var isCurrentSelect = false;        var offset = Mathf.Abs(item.localPosition.y);        var decisionDistance = SpacingDistance / 2;        if (offset < decisionDistance) isCurrentSelect = true;        if (isCurrentSelect)        {            itemSprite.spriteName = ActiveItemSpriteName;            //获取当前选中            var photo = item.Find("photo");            if (photo == null) return;            var optionSprite = photo.GetComponent<UISprite>();            if (optionSprite == null) return;            m_selectedItem = item.gameObject;            CurrentSelectIndex = int.Parse(item.gameObject.name.Split('_')[1]);            saveCurrentSelectSpriteName();            DoSelect();//执行委托        }        else        {            itemSprite.spriteName = NormalItemSpriteName;        }    }    void optionReset()    {        AngleAddUp = 0; //重置旋转角        m_itemScroll.transform.DestroyChildren(); //清空列表        for (var i = 0; i < m_currentDictionary.Count; i++)        {            //创建物件            var item = newItem("item_" + i);            item.transform.localPosition = new Vector3(0, 0); //重置物件位置            //新建选项            newOption(item.transform, i);            //注册物件监听            UIEventListener.Get(item.gameObject).onDragStart = itemOnDragStart;            UIEventListener.Get(item.gameObject).onDrag = itemOnDrag;            UIEventListener.Get(item.gameObject).onDragEnd = itemOnDragEnd;            //隐藏选项            item.gameObject.SetActive(false);        }        //转动物件到合适位置        chainRotate(CurrentSelectIndex * PieceAngle + MinAngle);    }    void chainRotate(float angleOfRotation)    {        var addUp = AngleAddUp + angleOfRotation;        var itemScroll = m_itemScroll.transform;        var count = itemScroll.childCount;        var link = Mathf.RoundToInt(addUp) / Mathf.RoundToInt(PieceAngle);        link = link < 0 ? 0 : link;        link = link >= count ? count : link;        AngleAddUp = addUp;        if (AngleAddUp < MinAngle)        {            AngleAddUp = MinAngle;            return;        }        if (AngleAddUp > MaxAngle)        {            AngleAddUp = MaxAngle;            return;        }        //物件处理        var a = OvalValueA;        var b = OvalValueB;        for (var i = 0; i < link; i++)        {            var item = itemScroll.GetChild(i);            var angle = AngleAddUp - (i + 1) * PieceAngle;            if (angle > 180)            {                item.transform.localPosition = new Vector3(0, b, 0);                item.gameObject.SetActive(false);            }            else if (angle < PieceAngle)            {                item.transform.localPosition = new Vector3(0, -b, 0);                item.gameObject.SetActive(false);            }            else            {                item.gameObject.SetActive(true);                item.transform.localScale = Vector3.one * Scale;                var srcAxis = getAngleToAxis(angle);                var trgAxis = getOvalAxis(srcAxis, a, b, true);                var v = new Vector3(trgAxis.x, trgAxis.y);                item.transform.localPosition = v;            }            selectItem(item.transform); //设置物件选中        }        //滚轮处理        m_gear.transform.localEulerAngles += new Vector3(0, 0, angleOfRotation);        //提示信息处理        hideHint();    }    void hideHint()    {        m_isNeedHint = true;//激活提示信息显示标志        DestroyObject(m_lastHint);    }    void showHint()    {        if (!m_isNeedHint || m_selectedItem == null) return;        m_lastHint = newHint(m_selectedItem.transform, m_hint);        m_isNeedHint = false;//禁止提示信息显示标志    }    #endregion    #region 滚轮监听事件    Vector3 m_gearDragOverTouchPos;    void gearOnDragStart(GameObject go)    {        m_isDragging = true;        m_gearDragOverTouchPos = getTouchAxis(m_gear);    }    void gearOnDragEnd(GameObject go)    {        m_isDragging = false;    }    void gearOnDrag(GameObject go, Vector2 delta)    {        var axis = getTouchAxis(m_gear);        var stepAngle = getAngleBetweenAxis(axis, m_gearDragOverTouchPos, false, true);        chainRotate(stepAngle);        m_gearDragOverTouchPos = getTouchAxis(m_gear);    }    #endregion    #region 物件监听事件    Vector3 m_itemDragOverTouchPos;    void itemOnDragStart(GameObject go)    {        m_isDragging = true;        m_itemDragOverTouchPos = getTouchAxis(m_gear);    }    void itemOnDragEnd(GameObject go)    {        m_isDragging = false;    }    void itemOnDrag(GameObject go, Vector2 delta)    {        var axis = getTouchAxis(m_gear);        var stepAngle = getAngleBetweenAxis(axis, m_itemDragOverTouchPos, false, true);        chainRotate(stepAngle);        m_itemDragOverTouchPos = getTouchAxis(m_gear);    }    #endregion    #region 选项监听事件    Vector3 m_optionDragOverTouchPos;    void optionOnDragStart(GameObject go)    {        m_isDragging = true;        m_optionDragOverTouchPos = getTouchAxis(m_gear);    }    void optionOnDragEnd(GameObject go)    {        m_isDragging = false;    }    void optionOnDrag(GameObject go, Vector2 delta)    {        var axis = getTouchAxis(m_gear);        var stepAngle = getAngleBetweenAxis(axis, m_optionDragOverTouchPos, false, true);        chainRotate(stepAngle);        m_optionDragOverTouchPos = getTouchAxis(m_gear);    }    #endregion}

0 0
原创粉丝点击