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

public class GraphicUnLockManager : MonoBehaviour
{
[Tooltip("含有Selectable及Image组件的UI对象,作为连接点。")]
public List<RectTransform> _lstPoints = new List<RectTransform>();
[Tooltip("用于设置所画线的颜色。(可使用“unlit/Color”Shader)")]
public Material _matLineColor;
[Tooltip("用于设置所画线的高度。")]
public int _nHalfHeight = 15;
[Tooltip("用于设置选择时Image的颜色。")]
public Color _clrSelect = Color.red;
[Tooltip("用于设置未选择时Image的颜色。")]
public Color _clrUnSelect = Color.white;

[HideInInspector]
public List<RectTransform> _lstSelectPoints = new List<RectTransform>();//已选择连接点
[HideInInspector]
public List<int> _lstPassword = new List<int>();//以输入密码
[HideInInspector]
public Action<bool> onInputState;//true为开始输入,false为结束输入

private bool _isPressing = false;//是否按下
private Vector2 _vtPressPos;//按下点坐标

private float _fDistance;//距离
private float _fDegree;//夹角
private Matrix4x4 _matrixTrans;//变换矩阵
private Vector2[] _vertexPos = new Vector2[4];//顶点数组

private Vector2 _tempPos;

void Awake()
{
InitEnterEvent();//初始化所有连接点的消息
ClearLines();//清空相关数据
}

void Update()
{
if (!IsPressed())
{//当未按下时清空是数据
ClearLines();
}
}

bool IsPressed()
{
//触摸
if (Input.touchCount > 0)
{
switch (Input.touches[0].phase)
{
case TouchPhase.Began:
_isPressing = true;
if (onInputState != null)
{
onInputState(true);//状态改变
}
break;
case TouchPhase.Ended:
case TouchPhase.Canceled:
_isPressing = false;
if (onInputState != null)
{
onInputState(false);//状态改变
}
break;
}

_vtPressPos = Input.touches[0].position;
}
else
{
//鼠标
if (Input.GetMouseButtonDown(0))
{
_isPressing = true;
if (onInputState != null)
{
onInputState(true);//状态改变
}
}
if (Input.GetMouseButtonUp(0))
{
_isPressing = false;
if (onInputState != null)
{
onInputState(false);//状态改变
}
}

_vtPressPos = Input.mousePosition;
}

return _isPressing;
}

void OnPostRender()
{
DrawLines();//画所有线
}

void OnGUI()
{
string msg = "";

msg += "是否正在输入:" + IsPressed() + "\n";
msg += "密码:";
for (int i = 0; i < _lstPassword.Count; i++)
{
msg += _lstPassword[i] + ",";
}

GUIStyle guiStyle = new GUIStyle();
guiStyle.normal.textColor = new Color(1, 1, 1); //设置字体颜色
guiStyle.fontSize = 75; //设置字体大小
GUILayout.Label(msg, guiStyle);
}

void InitEnterEvent()
{
//为每个点添加Enter事件
_lstPoints.ForEach((rtTrans) =>
{
EventTrigger trigger = rtTrans.GetComponent<EventTrigger>();
if (trigger == null)
{
trigger = rtTrans.gameObject.AddComponent<EventTrigger>();
}

//添加事件
EventTrigger.Entry entryEnter = new EventTrigger.Entry();
entryEnter.eventID = EventTriggerType.PointerEnter;//进入事件
EventTrigger.TriggerEvent evtEnter = new EventTrigger.TriggerEvent();
evtEnter.AddListener(OnSelectPoint);
entryEnter.callback = evtEnter;
trigger.triggers.Add(entryEnter);

EventTrigger.Entry entryDown = new EventTrigger.Entry();
entryDown.eventID = EventTriggerType.PointerDown;//按下事件
EventTrigger.TriggerEvent evtDown = new EventTrigger.TriggerEvent();
evtDown.AddListener(OnSelectPoint);
entryDown.callback = evtDown;
trigger.triggers.Add(entryDown);
});
}

public void OnSelectPoint(BaseEventData obj)
{
//转换数据类型
PointerEventData data = obj as PointerEventData;

GameObject target = null;
if (null != data.pointerEnter)
{
target = data.pointerEnter;
}
else if (null != data.pointerPress)
{
target = data.pointerPress;
}

AddSelectPoint(target);//添加选择连接点
}

void AddSelectPoint(GameObject obj)
{
if (IsPressed() && null != obj)
{
//将未连接的点添加到需要连接的点的列表中去
RectTransform rtTrans = obj.GetComponent<RectTransform>();
if (null != rtTrans && !_lstSelectPoints.Contains(rtTrans))
{
//添加到绘制列表
_lstSelectPoints.Add(rtTrans);
//添加密码序列
_lstPassword.Add(_lstPoints.IndexOf(rtTrans));
//改变颜色
rtTrans.GetComponent<Image>().color = _clrSelect;
}
}
}

void ClearLines()
{
//清空选择及密码列表
_lstSelectPoints.Clear();
_lstPassword.Clear();

//还原颜色
_lstPoints.ForEach((rtTrans) =>
{
rtTrans.GetComponent<Image>().color = _clrUnSelect;
});
}

void DrawLine(Vector2 vtStart, Vector2 vtEnd)
{
_tempPos = vtEnd - vtStart;
_fDistance = Vector3.Distance(Vector3.zero, _tempPos);//距离
_fDegree = Vector3.Angle(_tempPos, Vector3.right);//与x轴正方向的夹角

//判断旋转方向,逆时针为正,顺时针为付
if (_tempPos.y < 0)
{
_fDegree *= -1;
}

//设置变换矩阵
_matrixTrans.SetTRS(vtStart, Quaternion.Euler(0, 0, _fDegree), Vector3.one);//设置变换矩阵

//设置绘制顶点坐标
_vertexPos[0].x = 0;
_vertexPos[0].y = -_nHalfHeight;
_vertexPos[1].x = 0;
_vertexPos[1].y = _nHalfHeight;
_vertexPos[2].x = _fDistance;
_vertexPos[2].y = _nHalfHeight;
_vertexPos[3].x = _fDistance;
_vertexPos[3].y = -_nHalfHeight;

//绘制
GL.PushMatrix();
GL.LoadPixelMatrix();//使(0,0,0)为左下角,(Screen.width,Screen.height,0)为右上角
GL.MultMatrix(_matrixTrans);
GL.Begin(GL.QUADS);//绘制四边形
for (int n = 0; n < 4; n++)
{
GL.Vertex(_vertexPos[n]);
}
GL.End();
GL.PopMatrix();
}

void DrawLines()
{
//设置线的材质
_matLineColor.SetPass(0);

//连接已选择的点
for (int nIndex = 0; nIndex < _lstSelectPoints.Count - 1; nIndex++)
{
DrawLine(_lstSelectPoints[nIndex].position, _lstSelectPoints[nIndex + 1].position);
}

//连接到Press点
if (IsPressed() && _lstSelectPoints.Count > 0)
{
DrawLine(_vtPressPos, _lstSelectPoints[_lstSelectPoints.Count - 1].position);
}
}
}

另一个参考:https://blog.csdn.net/nanggong/article/details/52513729

unity3d 九宫密码锁的更多相关文章

  1. Android实现九宫拼图过程记录

    算法老师给了一份关于九宫拼图的算法过程用C++写的,让我们自己封装,成为一个有图形界面的工程,我接触过android,c++的mfc,Java的图形界面JUI,网页的css.html.javascri ...

  2. Unity3d学习 预设体(prefab)的一些理解

    之前一直在想如果要在Unity3d上创建很多个具有相同结构的对象,是如何做的,后来查了相关资料发现预设体可以解决这个问题! 预设体的概念: 组件的集合体 , 预制物体可以实例化成游戏对象. 创建预设体 ...

  3. Unity3d入门 - 关于unity工具的熟悉

    上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...

  4. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  5. warensoft unity3d 更新说明

    warensoft unity3d 组件的Alpha版本已经发布了将近一年,很多网友发送了改进的Email,感谢大家的支持. Warensoft Unity3D组件将继续更新,将改进的功能如下: 1. ...

  6. Unity3D框架插件uFrame实践记录(一)

    1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...

  7. Unity3D 5.3 新版AssetBundle使用方案及策略

    1.概览 Unity3D 5.0版本之后的AssetBundle机制和之前的4.x版本已经发生了很大的变化,一些曾经常用的流程已经不再使用,甚至一些老的API已经被新的API所取代. 因此,本文的主要 ...

  8. 山寨Unity3D?搜狐畅游的免费开源游戏引擎Genesis-3D

    在CSDN上看到了<搜狐畅游发布3D游戏引擎Genesis-3D 基于MIT协议开源>(http://www.csdn.net/article/2013-11-21/2817585-cha ...

  9. 从Unity3D编译器升级聊起Mono

    接前篇Unity 5.3.5p8 C#编译器升级,本文侧重了解一些Mono的知识. Unity3D的编译器升级 新升级的Mono C#编译器(对应Mono 4.4) Unity编辑器及播放器所使用的M ...

随机推荐

  1. 数组方法map(映射),reduce(规约),foreach(遍历),filter(过滤)

    数组方法map(映射),reduce(规约),foreach(遍历),filter(过滤) map()方法返回一个由原数组中每一个元素调用一个指定方法后返回的新数组 reduce()方法接受一个函数作 ...

  2. Vmware安装Kali

    下载软件 破解版的Vmware14 kali(我的是kali-linux-2018.2-amd64) 配置虚拟机 新建虚拟机,选择自定义 虚拟机硬件兼容性 选择虚拟机硬件兼容性为Workstation ...

  3. laravel中连表查询

    $skuList = ProductSkuModel::selectRaw('product_skus.id as sku_id, product_skus.code as code, product ...

  4. 【PowerDesigner】【7】Table视图显示Comment

    原理:把显示name的列的值,替换成注释的值. 步骤:打开菜单Tools>Execute Commands>Edit/Run Script.. 或者用快捷键 Ctrl+Shift+X.将下 ...

  5. git中.gitignore文件不起作用的解决

    git rm -r --cached . git add . git commit -m 'update .gitignore'

  6. java设计模式之生产者/消费者模式

    什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者 ...

  7. cf-914D-线段树

    http://codeforces.com/contest/914/problem/D 题目大意是给出一个数列,进行两种操作,一个是将位置i的数置为x,另一个操作是询问[l,r]内的数的gcd是不是x ...

  8. python中list、tuple、dict、set的使用

    1.list列表 list是一种可变的,有序的列表,可以随时添加和删除其中的元素. 其格式如下:list-name=[element1,element2,....] >>> nums ...

  9. MySql习题和答案

    MySQL测试题 一.表关系请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号.ps:针对的是自己的生物成绩比物理成绩高,再把符合 ...

  10. Boost.PropertyTree读取ini文件(Linux环境)

    昨天因为需要读取配置文件略略伤神.网上很多例子但是我用都会报错,很多人把Boost.PropertyTree的函数写很麻烦的包所以报错我也不知道什么问题,所以今天整理下. 头上附上官网链接:Boost ...