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
- BeGear.cs
- CS..........................
- cs
- cs
- cs
- Cs
- cs
- cs
- cs
- CS
- cs
- cs,
- cs
- cs
- cs
- cs
- cs
- cs
- 关于python 元类
- 关于数据序列化(4)自定义序列化的实现,支持常用集合框架
- redis3.2.8 sentinel模式一主两从高可用环境搭建测试
- ANSI X9.9 MAC算法介绍
- ReactNative打包-Android(简单实用)
- BeGear.cs
- 零成本“即用即走”的小程序,为什么没能留住用户
- 数位dp入门
- QT 语法知识
- Cloneable
- 【linux】centos 安装 python-pip
- 关于微信小程序的一点个人总结
- I/O架构
- POJ 1018 Communication System 笔记