You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
6.7 KiB
210 lines
6.7 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
[RequireComponent(typeof (RawImage))]
|
|
[AddComponentMenu("UI/Pinch and Zoom Image")]
|
|
public class PinchZoomImage : MonoBehaviour
|
|
,IDragHandler, IPointerDownHandler, IPointerUpHandler
|
|
{
|
|
[Range(0, 0.1f)]
|
|
public float posDuration = 0.05f;
|
|
[Range(0, 0.1f)]
|
|
public float rotDuration = 0.05f;
|
|
[Range(0, 0.1f)]
|
|
public float scaleDuration = 0.05f;
|
|
public bool isRotation = true;
|
|
public bool isScale = true;
|
|
|
|
private bool simulatedByMouse = false;
|
|
|
|
public void SetPosition(Vector3 position)
|
|
{
|
|
target_pos = position;
|
|
}
|
|
|
|
public Vector3 GetPosition()
|
|
{
|
|
return target_pos;
|
|
}
|
|
|
|
//IDragHandler
|
|
public void OnDrag(PointerEventData eventData)
|
|
{
|
|
//Debug.Log("OnDrag"+Time.time);
|
|
pointers[eventData.pointerId] = eventData;
|
|
}
|
|
|
|
//IPointerDownHandler
|
|
public void OnPointerDown(PointerEventData eventData)
|
|
{
|
|
|
|
//Debug.Log("OnPointerDown" + Time.time);
|
|
if (simulatedByMouse && pointers.Count == 0)
|
|
{
|
|
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
|
|
PointerEventData p = new PointerEventData(EventSystem.current);
|
|
p.position = new Vector2(pos.x, pos.y);
|
|
p.pointerId = -2;
|
|
pointers.Add(p.pointerId, p);
|
|
}
|
|
pointers.Add(eventData.pointerId, eventData);
|
|
ResetAnchor();
|
|
transform.SetSiblingIndex(transform.childCount - 1);
|
|
}
|
|
|
|
//IPointerUpHandler
|
|
public void OnPointerUp(PointerEventData eventData)
|
|
{
|
|
//Debug.Log("OnPointerUp" + Time.time);
|
|
pointers.Remove(eventData.pointerId);
|
|
if (simulatedByMouse && pointers.Count == 1)
|
|
pointers.Remove(-2);
|
|
if (pointers.Count > 0)
|
|
ResetAnchor();
|
|
|
|
}
|
|
List<Vector2> GetPositionList()
|
|
{
|
|
List < Vector2 > result = new List<Vector2>();
|
|
foreach (int key in pointers.Keys)
|
|
result.Add(pointers[key].position);
|
|
return result;
|
|
}
|
|
private static Vector2 Average(List<Vector2> list)
|
|
{
|
|
Vector2 sum = Vector2.zero;
|
|
foreach (Vector2 v in list)
|
|
sum += v;
|
|
return sum / list.Count;
|
|
}
|
|
private static List<Vector2> Substract(List<Vector2> list, Vector2 pos)
|
|
{
|
|
List<Vector2> result = new List<Vector2>();
|
|
foreach (Vector2 v in list)
|
|
result.Add(v - pos);
|
|
return result;
|
|
}
|
|
private static float AverageMagnitude(List<Vector2> list)
|
|
{
|
|
float sum = 0.0f;
|
|
foreach (Vector2 v in list)
|
|
sum += v.magnitude;
|
|
return sum / list.Count;
|
|
}
|
|
Vector2 getAveragePosition()
|
|
{
|
|
Vector2 sum = Vector2.zero;
|
|
foreach (int key in pointers.Keys)
|
|
sum += pointers[key].position;
|
|
return sum / pointers.Count;
|
|
}
|
|
float getAverageDistance(Dictionary<int, Vector2> directions)
|
|
{
|
|
float sum = 0.0f;
|
|
foreach (int key in directions.Keys)
|
|
sum += directions[key].magnitude;
|
|
return sum / pointers.Count;
|
|
}
|
|
Dictionary<int, Vector2> getDirection(Vector2 pos)
|
|
{
|
|
Dictionary<int, Vector2> result = new Dictionary<int, Vector2>();
|
|
foreach (int key in pointers.Keys)
|
|
{
|
|
result.Add(key,pointers[key].position - pos);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Use this for initialization
|
|
void Start () {
|
|
target_pos = transform.localPosition;
|
|
target_q = transform.localRotation;
|
|
target_scale = transform.localScale.x;
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update () {
|
|
if (Input.GetKey(KeyCode.Escape))
|
|
Application.Quit();
|
|
if (Time.deltaTime == 0)
|
|
return;
|
|
|
|
if (pointers.Count > 0)
|
|
{
|
|
List<Vector2> pos_list = GetPositionList();
|
|
|
|
Vector2 pos = Average(pos_list);
|
|
List<Vector2> diff_list = Substract(pos_list, pos);
|
|
float magnitude = AverageMagnitude(diff_list);
|
|
|
|
{//translation
|
|
Vector3 diff_pos = pos - pre_pos;
|
|
target_pos += diff_pos;
|
|
vel += (diff_pos / Time.deltaTime - vel) * Mathf.Clamp01(Time.deltaTime / 0.2f);
|
|
pre_pos = pos;
|
|
}
|
|
if (pointers.Count > 1)
|
|
{
|
|
if (isScale)
|
|
{//Scale
|
|
target_scale = target_scale * magnitude / pre_magnitude;
|
|
pre_magnitude = magnitude;
|
|
}
|
|
if (isRotation)
|
|
{//rotation
|
|
Quaternion average = new Quaternion(0, 0, 0, 0);
|
|
for(int i=0;i<diff_list.Count; ++i)
|
|
{
|
|
Quaternion q = Quaternion.FromToRotation(pre_diff_list[i].normalized, diff_list[i].normalized);
|
|
average = Quaternion.Slerp(average, q, 1.0f / (i+1));
|
|
}
|
|
target_q = target_q * average;
|
|
pre_diff_list = diff_list;
|
|
}
|
|
}
|
|
}else
|
|
{
|
|
if (posDuration == 0.0f)
|
|
vel = Vector3.zero;
|
|
target_pos += vel * Time.deltaTime;
|
|
vel *= 0.9f;
|
|
}
|
|
|
|
float pos_step = Mathf.Clamp01(Time.deltaTime / posDuration);
|
|
float rot_step = Mathf.Clamp01(Time.deltaTime / rotDuration);
|
|
float scale_step = Mathf.Clamp01(Time.deltaTime / scaleDuration);
|
|
if (Application.isPlaying == false)
|
|
pos_step = rot_step = scale_step = 1.0f;
|
|
|
|
|
|
Vector3 new_pos = Vector3.Lerp(transform.localPosition, target_pos, pos_step); ;
|
|
transform.localPosition = new_pos;
|
|
transform.localRotation = Quaternion.Slerp(transform.localRotation, target_q, rot_step);
|
|
float s = Mathf.Lerp(transform.localScale.x, target_scale, scale_step);
|
|
transform.localScale = new Vector3(s, s, 1.0f);
|
|
}
|
|
private void ResetAnchor()
|
|
{
|
|
vel = Vector3.zero;
|
|
List<Vector2> pos_list = GetPositionList();
|
|
//target_pos = transform.localPosition;
|
|
pre_pos = Average(pos_list);
|
|
pre_diff_list = Substract(pos_list, pre_pos);
|
|
pre_magnitude = AverageMagnitude(pre_diff_list);
|
|
}
|
|
private Dictionary<int, PointerEventData> pointers = new Dictionary<int, PointerEventData>();
|
|
|
|
private Vector3 target_pos;
|
|
private Quaternion target_q;
|
|
private float target_scale;
|
|
|
|
private Vector2 pre_pos;
|
|
private List<Vector2> pre_diff_list;
|
|
private float pre_magnitude;
|
|
|
|
private Vector3 vel = Vector3.zero;
|
|
}
|
|
|