备份CatanBuilding瘦身独立工程
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 388552ada77be9a4ea13526b21d3a28d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CW.Common
|
||||
{
|
||||
/// <summary>This is the base class for all components that are created as children of another component, allowing them to be more easily managed.</summary>
|
||||
public abstract class CwChild : MonoBehaviour
|
||||
{
|
||||
public interface IHasChildren
|
||||
{
|
||||
bool HasChild(CwChild child);
|
||||
}
|
||||
|
||||
[ContextMenu("Destroy GameObject If Invalid All")]
|
||||
public void DestroyGameObjectIfInvalidAll()
|
||||
{
|
||||
if (transform.parent != null)
|
||||
{
|
||||
foreach (var siblings in transform.parent.GetComponentsInChildren<CwChild>())
|
||||
{
|
||||
siblings.DestroyGameObjectIfInvalid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Destroy GameObject If Invalid")]
|
||||
public void DestroyGameObjectIfInvalid()
|
||||
{
|
||||
var parent = GetParent();
|
||||
|
||||
if (parent == null || parent.HasChild(this) == false)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.Undo.DestroyObjectImmediate(gameObject);
|
||||
#else
|
||||
DestroyImmediate(gameObject);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IHasChildren GetParent();
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
//DestroyGameObjectIfInvalid();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d2ec44108dda21438f164cae219f224
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,139 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CW.Common
|
||||
{
|
||||
/// <summary>This makes the current <b>Transform</b> follow the <b>Target</b> Transform as if it were a child.</summary>
|
||||
[ExecuteInEditMode]
|
||||
[HelpURL(CwShared.HelpUrlPrefix + "CwFollow")]
|
||||
[AddComponentMenu(CwShared.ComponentMenuPrefix + "Follow")]
|
||||
public class CwFollow : MonoBehaviour
|
||||
{
|
||||
public enum FollowType
|
||||
{
|
||||
TargetTransform,
|
||||
MainCamera
|
||||
}
|
||||
|
||||
public enum UpdateType
|
||||
{
|
||||
Update,
|
||||
LateUpdate
|
||||
}
|
||||
|
||||
/// <summary>What should this component follow?</summary>
|
||||
public FollowType Follow { set { follow = value; } get { return follow; } } [SerializeField] private FollowType follow;
|
||||
|
||||
/// <summary>The transform that will be followed.</summary>
|
||||
public Transform Target { set { target = value; } get { return target; } } [SerializeField] private Transform target;
|
||||
|
||||
/// <summary>How quickly this Transform follows the target.
|
||||
/// -1 = instant.</summary>
|
||||
public float Damping { set { damping = value; } get { return damping; } } [SerializeField] private float damping = -1.0f;
|
||||
|
||||
/// <summary>Follow the target's rotation too?</summary>
|
||||
public bool Rotate { set { rotate = value; } get { return rotate; } } [SerializeField] private bool rotate = true;
|
||||
|
||||
/// <summary>Ignore Z axis for 2D?</summary>
|
||||
public bool IgnoreZ { set { ignoreZ = value; } get { return ignoreZ; } } [SerializeField] private bool ignoreZ;
|
||||
|
||||
/// <summary>Where in the game loop should this component update?</summary>
|
||||
public UpdateType FollowIn { set { followIn = value; } get { return followIn; } } [SerializeField] private UpdateType followIn = UpdateType.LateUpdate;
|
||||
|
||||
/// <summary>This allows you to specify a positional offset relative to the <b>Target</b>.</summary>
|
||||
public Vector3 LocalPosition { set { localPosition = value; } get { return localPosition; } } [SerializeField] private Vector3 localPosition;
|
||||
|
||||
/// <summary>This allows you to specify a rotational offset relative to the <b>Target</b>.</summary>
|
||||
public Vector3 LocalRotation { set { localRotation = value; } get { return localRotation; } } [SerializeField] private Vector3 localRotation;
|
||||
|
||||
/// <summary>This method will update the follow position now.</summary>
|
||||
[ContextMenu("UpdatePosition")]
|
||||
public void UpdatePosition()
|
||||
{
|
||||
var finalTarget = target;
|
||||
|
||||
if (follow == FollowType.MainCamera)
|
||||
{
|
||||
var mainCamera = Camera.main;
|
||||
|
||||
if (mainCamera != null)
|
||||
{
|
||||
finalTarget = mainCamera.transform;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalTarget != null)
|
||||
{
|
||||
var currentPosition = transform.position;
|
||||
var targetPosition = finalTarget.TransformPoint(localPosition);
|
||||
var factor = CwHelper.DampenFactor(damping, Time.deltaTime);
|
||||
|
||||
if (ignoreZ == true)
|
||||
{
|
||||
targetPosition.z = currentPosition.z;
|
||||
}
|
||||
|
||||
transform.position = Vector3.Lerp(currentPosition, targetPosition, factor);
|
||||
|
||||
if (rotate == true)
|
||||
{
|
||||
var targetRotation = finalTarget.rotation * Quaternion.Euler(localRotation);
|
||||
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (followIn == UpdateType.Update)
|
||||
{
|
||||
UpdatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (followIn == UpdateType.LateUpdate)
|
||||
{
|
||||
UpdatePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace CW.Common
|
||||
{
|
||||
using UnityEditor;
|
||||
using TARGET = CwFollow;
|
||||
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TARGET))]
|
||||
public class CwFollow_Editor : CwEditor
|
||||
{
|
||||
protected override void OnInspector()
|
||||
{
|
||||
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
|
||||
|
||||
Draw("follow", "What should this component follow?");
|
||||
if (Any(tgts, t => t.Follow == CwFollow.FollowType.TargetTransform))
|
||||
{
|
||||
BeginIndent();
|
||||
BeginError(Any(tgts, t => t.Target == null));
|
||||
Draw("target", "The transform that will be followed.");
|
||||
EndError();
|
||||
EndIndent();
|
||||
}
|
||||
Draw("damping", "How quickly this Transform follows the target.\n\n-1 = instant.");
|
||||
Draw("rotate", "Follow the target's rotation too?");
|
||||
Draw("ignoreZ", "Ignore Z axis for 2D?");
|
||||
Draw("followIn", "Where in the game loop should this component update?");
|
||||
|
||||
Separator();
|
||||
|
||||
Draw("localPosition", "This allows you to specify a positional offset relative to the Target transform.");
|
||||
Draw("localRotation", "This allows you to specify a rotational offset relative to the Target transform.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d2927631b10c2f4b9ce492ed53fd69b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 200
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,623 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CW.Common
|
||||
{
|
||||
/// <summary>This component combines finger and mouse and keyboard inputs into a single interface.</summary>
|
||||
[HelpURL(CwShared.HelpUrlPrefix + "CwInputManager")]
|
||||
[AddComponentMenu(CwShared.ComponentMenuPrefix + "Input Manager")]
|
||||
public class CwInputManager : MonoBehaviour
|
||||
{
|
||||
public enum AxisGesture
|
||||
{
|
||||
HorizontalDrag,
|
||||
VerticalDrag,
|
||||
Twist,
|
||||
HorizontalPull,
|
||||
VerticalPull
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct Axis
|
||||
{
|
||||
public int FingerCount;
|
||||
public bool FingerInvert;
|
||||
public AxisGesture FingerGesture;
|
||||
public float FingerSensitivity;
|
||||
|
||||
public KeyCode KeyNegative;
|
||||
public KeyCode KeyPositive;
|
||||
public KeyCode KeyNegativeAlt;
|
||||
public KeyCode KeyPositiveAlt;
|
||||
public float KeySensitivity;
|
||||
|
||||
public Axis(int fCount, bool fInvert, AxisGesture fGesture, float fSensitivty, KeyCode kNegative, KeyCode kPositive, KeyCode kNegativeAlt, KeyCode kPositiveAlt, float kSensitivity)
|
||||
{
|
||||
FingerCount = fCount;
|
||||
FingerInvert = fInvert;
|
||||
FingerGesture = fGesture;
|
||||
FingerSensitivity = fSensitivty;
|
||||
KeyNegative = kNegative;
|
||||
KeyPositive = kPositive;
|
||||
KeyNegativeAlt = kNegativeAlt;
|
||||
KeyPositiveAlt = kPositiveAlt;
|
||||
KeySensitivity = kSensitivity;
|
||||
}
|
||||
|
||||
public float GetValue(float delta)
|
||||
{
|
||||
var value = 0.0f;
|
||||
var fingers = GetFingers(true, true);
|
||||
var scale = 1.0f;
|
||||
|
||||
value -= CwInput.GetKeyIsHeld(KeyNegative) == true ? KeySensitivity * delta : 0.0f;
|
||||
value += CwInput.GetKeyIsHeld(KeyPositive) == true ? KeySensitivity * delta : 0.0f;
|
||||
|
||||
value -= CwInput.GetKeyIsHeld(KeyNegativeAlt) == true ? KeySensitivity * delta : 0.0f;
|
||||
value += CwInput.GetKeyIsHeld(KeyPositiveAlt) == true ? KeySensitivity * delta : 0.0f;
|
||||
|
||||
if (FingerCount > 0 && fingers.Count == FingerCount)
|
||||
{
|
||||
if (FingerInvert == true && fingers[0].Index >= 0)
|
||||
{
|
||||
scale = -1.0f;
|
||||
}
|
||||
|
||||
switch (FingerGesture)
|
||||
{
|
||||
case AxisGesture.HorizontalDrag: value += GetAverageDeltaScaled(fingers).x * FingerSensitivity * scale; break;
|
||||
case AxisGesture.VerticalDrag: value += GetAverageDeltaScaled(fingers).y * FingerSensitivity * scale; break;
|
||||
case AxisGesture.Twist: value += GetAverageTwistRadians(fingers) * FingerSensitivity; break;
|
||||
case AxisGesture.HorizontalPull: value += GetAveragePullScaled(fingers).x * FingerSensitivity * delta * scale; break;
|
||||
case AxisGesture.VerticalPull: value += GetAveragePullScaled(fingers).y * FingerSensitivity * delta * scale; break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct Trigger
|
||||
{
|
||||
public bool UseFinger;
|
||||
public bool UseMouse;
|
||||
public KeyCode UseKey;
|
||||
|
||||
public Trigger(bool uFinger, bool uMouse, KeyCode uKey)
|
||||
{
|
||||
UseFinger = uFinger;
|
||||
UseMouse = uMouse;
|
||||
UseKey = uKey;
|
||||
}
|
||||
|
||||
public bool WentDown(Finger finger)
|
||||
{
|
||||
if (UseFinger == true && finger.Index >= 0 && finger.Down == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseMouse == true && finger.Index == MOUSE_FINGER_INDEX && finger.Down == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseKey != KeyCode.None && finger.Index == HOVER_FINGER_INDEX && CwInput.GetKeyWentDown(UseKey) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsDown(Finger finger)
|
||||
{
|
||||
if (UseFinger == true && finger.Index >= 0 && finger.Up == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseMouse == true && finger.Index == MOUSE_FINGER_INDEX && finger.Up == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseKey != KeyCode.None && finger.Index == HOVER_FINGER_INDEX && CwInput.GetKeyIsHeld(UseKey) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool WentUp(Finger finger, bool useAnyFinger = false)
|
||||
{
|
||||
if (useAnyFinger == true && finger.Up == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseFinger == true && finger.Index >= 0 && finger.Up == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseMouse == true && finger.Index == MOUSE_FINGER_INDEX && finger.Up == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (UseKey != KeyCode.None && finger.Index == HOVER_FINGER_INDEX && CwInput.GetKeyWentUp(UseKey) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Link
|
||||
{
|
||||
public Finger Finger;
|
||||
|
||||
public static T Find<T>(List<T> links, Finger finger)
|
||||
where T : Link, new()
|
||||
{
|
||||
if (links != null)
|
||||
{
|
||||
foreach (var link in links)
|
||||
{
|
||||
if (link.Finger == finger)
|
||||
{
|
||||
return link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T Create<T>(ref List<T> links, Finger finger)
|
||||
where T : Link, new()
|
||||
{
|
||||
var link = Find(links, finger);
|
||||
|
||||
if (link == null)
|
||||
{
|
||||
if (links == null)
|
||||
{
|
||||
links = new List<T>();
|
||||
}
|
||||
|
||||
link = new T();
|
||||
|
||||
link.Finger = finger;
|
||||
|
||||
links.Add(link);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Link already exists!");
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public static void ClearAll<T>(List<T> links)
|
||||
where T : Link
|
||||
{
|
||||
if (links != null)
|
||||
{
|
||||
foreach (var link in links)
|
||||
{
|
||||
link.Clear();
|
||||
}
|
||||
|
||||
links.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAndRemove<T>(List<T> links, T link)
|
||||
where T : Link
|
||||
{
|
||||
if (link != null)
|
||||
{
|
||||
link.Clear();
|
||||
|
||||
if (links != null)
|
||||
{
|
||||
links.Remove(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Finger
|
||||
{
|
||||
public int Index;
|
||||
public float Pressure;
|
||||
public bool Down;
|
||||
public bool Up;
|
||||
public float Age;
|
||||
public bool StartedOverGui;
|
||||
public Vector2 StartScreenPosition;
|
||||
public Vector2 ScreenPosition;
|
||||
public Vector2 ScreenPositionOld;
|
||||
public Vector2 ScreenPositionOldOld;
|
||||
public Vector2 ScreenPositionOldOldOld;
|
||||
|
||||
public float SmoothScreenPositionDelta
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Up == false)
|
||||
{
|
||||
return Vector2.Distance(ScreenPositionOldOld, ScreenPositionOld);
|
||||
}
|
||||
|
||||
return Vector2.Distance(ScreenPositionOldOld, ScreenPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 GetSmoothScreenPosition(float t)
|
||||
{
|
||||
if (Up == false)
|
||||
{
|
||||
return Hermite(ScreenPositionOldOldOld, ScreenPositionOldOld, ScreenPositionOld, ScreenPosition, t);
|
||||
}
|
||||
|
||||
return Vector2.LerpUnclamped(ScreenPositionOldOld, ScreenPosition, t);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Fingers that began touching the screen on top of these UI layers will be ignored.</summary>
|
||||
public LayerMask GuiLayers { set { guiLayers = value; } get { return guiLayers; } } [SerializeField] private LayerMask guiLayers = 1 << 5;
|
||||
|
||||
/// <summary>This event will tell you when a finger begins touching the screen.</summary>
|
||||
public static event System.Action<Finger> OnFingerDown;
|
||||
|
||||
/// <summary>This event will tell you when a finger has begun, is, or has just stopped touching the screen.</summary>
|
||||
public static event System.Action<Finger> OnFingerUpdate;
|
||||
|
||||
/// <summary>This event will tell you when a finger stops touching the screen.</summary>
|
||||
public static event System.Action<Finger> OnFingerUp;
|
||||
|
||||
public const int MOUSE_FINGER_INDEX = -1;
|
||||
|
||||
public const int HOVER_FINGER_INDEX = -1337;
|
||||
|
||||
private static List<RaycastResult> tempRaycastResults = new List<RaycastResult>(10);
|
||||
|
||||
private static PointerEventData tempPointerEventData;
|
||||
|
||||
private static EventSystem tempEventSystem;
|
||||
|
||||
private static List<Finger> fingers = new List<Finger>();
|
||||
|
||||
private static List<Finger> filteredFingers = new List<Finger>();
|
||||
|
||||
private static Stack<Finger> pool = new Stack<Finger>();
|
||||
|
||||
public static List<Finger> Fingers
|
||||
{
|
||||
get
|
||||
{
|
||||
return fingers;
|
||||
}
|
||||
}
|
||||
|
||||
public static float ScaleFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
var dpi = Screen.dpi;
|
||||
|
||||
if (dpi <= 0)
|
||||
{
|
||||
dpi = 200.0f;
|
||||
}
|
||||
|
||||
return 200.0f / dpi;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Finger> GetFingers(bool ignoreStartedOverGui = false, bool ignoreHover = false)
|
||||
{
|
||||
filteredFingers.Clear();
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
if (ignoreStartedOverGui == true && finger.StartedOverGui == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ignoreHover == true && finger.Index == HOVER_FINGER_INDEX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredFingers.Add(finger);
|
||||
}
|
||||
|
||||
return filteredFingers;
|
||||
}
|
||||
|
||||
public static bool PointOverGui(Vector2 screenPosition, int guiLayers = 1 << 5)
|
||||
{
|
||||
return RaycastGui(screenPosition, guiLayers).Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>This method gives you all UI elements under the specified screen position, where element 0 is the first/top one.</summary>
|
||||
public static List<RaycastResult> RaycastGui(Vector2 screenPosition, int guiLayers = 1 << 5)
|
||||
{
|
||||
tempRaycastResults.Clear();
|
||||
|
||||
var currentEventSystem = EventSystem.current;
|
||||
|
||||
if (currentEventSystem != null)
|
||||
{
|
||||
// Create point event data for this event system?
|
||||
if (currentEventSystem != tempEventSystem)
|
||||
{
|
||||
tempEventSystem = currentEventSystem;
|
||||
|
||||
if (tempPointerEventData == null)
|
||||
{
|
||||
tempPointerEventData = new PointerEventData(tempEventSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempPointerEventData.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Raycast event system at the specified point
|
||||
tempPointerEventData.position = screenPosition;
|
||||
|
||||
currentEventSystem.RaycastAll(tempPointerEventData, tempRaycastResults);
|
||||
|
||||
// Loop through all results and remove any that don't match the layer mask
|
||||
if (tempRaycastResults.Count > 0)
|
||||
{
|
||||
for (var i = tempRaycastResults.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var raycastResult = tempRaycastResults[i];
|
||||
var raycastLayer = 1 << raycastResult.gameObject.layer;
|
||||
|
||||
if ((raycastLayer & guiLayers) == 0)
|
||||
{
|
||||
tempRaycastResults.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempRaycastResults;
|
||||
}
|
||||
|
||||
public static Vector2 GetAveragePosition(List<Finger> fingers)
|
||||
{
|
||||
var total = Vector2.zero;
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
total += finger.ScreenPosition;
|
||||
}
|
||||
|
||||
return fingers.Count == 0 ? total : total / fingers.Count;
|
||||
}
|
||||
|
||||
public static Vector2 GetAverageOldPosition(List<Finger> fingers)
|
||||
{
|
||||
var total = Vector2.zero;
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
total += finger.ScreenPositionOld;
|
||||
}
|
||||
|
||||
return fingers.Count == 0 ? total : total / fingers.Count;
|
||||
}
|
||||
|
||||
public static Vector2 GetAveragePullScaled(List<Finger> fingers)
|
||||
{
|
||||
var total = Vector2.zero;
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
total += finger.ScreenPosition - finger.StartScreenPosition;
|
||||
}
|
||||
|
||||
return fingers.Count == 0 ? total : total * ScaleFactor / fingers.Count;
|
||||
}
|
||||
|
||||
public static Vector2 GetAverageDeltaScaled(List<Finger> fingers)
|
||||
{
|
||||
var total = Vector2.zero;
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
total += finger.ScreenPosition - finger.ScreenPositionOld;
|
||||
}
|
||||
|
||||
return fingers.Count == 0 ? total : total * ScaleFactor / fingers.Count;
|
||||
}
|
||||
|
||||
public static float GetAverageTwistRadians(List<Finger> fingers)
|
||||
{
|
||||
var total = 0.0f;
|
||||
var center = GetAveragePosition(fingers);
|
||||
var oldCenter = GetAverageOldPosition(fingers);
|
||||
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
total += GetDeltaRadians(finger, center, oldCenter);
|
||||
}
|
||||
|
||||
return fingers.Count == 0 ? total : total / fingers.Count;
|
||||
}
|
||||
|
||||
/// <summary>If your component uses this component, then make sure you call this method at least once before you use it (e.g. from <b>Awake</b>).</summary>
|
||||
public static void EnsureThisComponentExists()
|
||||
{
|
||||
if (Application.isPlaying == true && CwHelper.FindAnyObjectByType<CwInputManager>() == null)
|
||||
{
|
||||
new GameObject(typeof(CwInputManager).Name).AddComponent<CwInputManager>();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
// Remove previously up fingers, or mark them as up in case the up event isn't read correctly
|
||||
for (var i = fingers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var finger = fingers[i];
|
||||
|
||||
if (finger.Up == true)
|
||||
{
|
||||
fingers.RemoveAt(i); pool.Push(finger);
|
||||
}
|
||||
else
|
||||
{
|
||||
finger.Up = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update real fingers
|
||||
if (CwInput.GetTouchCount() > 0)
|
||||
{
|
||||
for (var i = 0; i < CwInput.GetTouchCount(); i++)
|
||||
{
|
||||
int id; Vector2 position; float pressure; bool set;
|
||||
|
||||
CwInput.GetTouch(i, out id, out position, out pressure, out set);
|
||||
|
||||
AddFinger(id, position, pressure, set);
|
||||
}
|
||||
}
|
||||
// If there are no real touches, simulate some from the mouse?
|
||||
else if (CwInput.GetMouseExists() == true)
|
||||
{
|
||||
var mouseSet = false;
|
||||
var mouseUp = false;
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
mouseSet |= CwInput.GetMouseIsHeld(i);
|
||||
mouseUp |= CwInput.GetMouseWentUp(i);
|
||||
}
|
||||
|
||||
AddFinger(HOVER_FINGER_INDEX, CwInput.GetMousePosition(), 0.0f, true);
|
||||
|
||||
if (mouseSet == true || mouseUp == true)
|
||||
{
|
||||
AddFinger(MOUSE_FINGER_INDEX, CwInput.GetMousePosition(), 1.0f, mouseSet);
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
if (finger.Down == true && OnFingerDown != null) OnFingerDown .Invoke(finger);
|
||||
if ( OnFingerUpdate != null) OnFingerUpdate.Invoke(finger);
|
||||
if (finger.Up == true && OnFingerUp != null) OnFingerUp .Invoke(finger);
|
||||
}
|
||||
}
|
||||
|
||||
private Finger FindFinger(int index)
|
||||
{
|
||||
foreach (var finger in fingers)
|
||||
{
|
||||
if (finger.Index == index)
|
||||
{
|
||||
return finger;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void AddFinger(int index, Vector2 screenPosition, float pressure, bool set)
|
||||
{
|
||||
var finger = FindFinger(index);
|
||||
|
||||
if (finger == null)
|
||||
{
|
||||
finger = pool.Count > 0 ? pool.Pop() : new Finger();
|
||||
|
||||
finger.Index = index;
|
||||
finger.Down = true;
|
||||
finger.Age = 0.0f;
|
||||
|
||||
finger.StartedOverGui = PointOverGui(screenPosition, guiLayers);
|
||||
finger.StartScreenPosition = screenPosition;
|
||||
finger.ScreenPositionOld = screenPosition;
|
||||
finger.ScreenPositionOldOld = screenPosition;
|
||||
finger.ScreenPositionOldOldOld = screenPosition;
|
||||
|
||||
fingers.Add(finger);
|
||||
}
|
||||
else
|
||||
{
|
||||
finger.Down = false;
|
||||
finger.Age += Time.deltaTime;
|
||||
|
||||
finger.ScreenPositionOldOldOld = finger.ScreenPositionOldOld;
|
||||
finger.ScreenPositionOldOld = finger.ScreenPositionOld;
|
||||
finger.ScreenPositionOld = finger.ScreenPosition;
|
||||
}
|
||||
|
||||
finger.Pressure = pressure;
|
||||
finger.ScreenPosition = screenPosition;
|
||||
finger.Up = set == false;
|
||||
}
|
||||
|
||||
private static Vector2 Hermite(Vector2 a, Vector2 b, Vector2 c, Vector2 d, float t)
|
||||
{
|
||||
var mu2 = t * t;
|
||||
var mu3 = mu2 * t;
|
||||
var x = HermiteInterpolate(a.x, b.x, c.x, d.x, t, mu2, mu3);
|
||||
var y = HermiteInterpolate(a.y, b.y, c.y, d.y, t, mu2, mu3);
|
||||
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
private static float HermiteInterpolate(float y0,float y1, float y2,float y3, float mu, float mu2, float mu3)
|
||||
{
|
||||
var m0 = (y1 - y0) * 0.5f + (y2 - y1) * 0.5f;
|
||||
var m1 = (y2 - y1) * 0.5f + (y3 - y2) * 0.5f;
|
||||
var a0 = 2.0f * mu3 - 3.0f * mu2 + 1.0f;
|
||||
var a1 = mu3 - 2.0f * mu2 + mu;
|
||||
var a2 = mu3 - mu2;
|
||||
var a3 = -2.0f * mu3 + 3.0f * mu2;
|
||||
|
||||
return(a0*y1+a1*m0+a2*m1+a3*y2);
|
||||
}
|
||||
|
||||
private static float GetRadians(Vector2 screenPosition, Vector2 referencePoint)
|
||||
{
|
||||
return Mathf.Atan2(screenPosition.x - referencePoint.x, screenPosition.y - referencePoint.y);
|
||||
}
|
||||
|
||||
private static float GetDeltaRadians(Finger finger, Vector2 referencePoint, Vector2 lastReferencePoint)
|
||||
{
|
||||
var a = GetRadians(finger.ScreenPositionOld, lastReferencePoint);
|
||||
var b = GetRadians(finger.ScreenPosition, referencePoint);
|
||||
var d = Mathf.Repeat(a - b, Mathf.PI * 2.0f);
|
||||
|
||||
if (d > Mathf.PI)
|
||||
{
|
||||
d -= Mathf.PI * 2.0f;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8da33d20535c346499a0c78cabe4d750
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,238 @@
|
||||
//#define USE_CUSTOM_TEMPORARY
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CW.Common
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[DefaultExecutionOrder(1000)]
|
||||
[HelpURL(CwShared.HelpUrlPrefix + "CwRenderTextureManager")]
|
||||
[AddComponentMenu(CwShared.ComponentMenuPrefix + "Render Texture Manager")]
|
||||
public class CwRenderTextureManager : MonoBehaviour
|
||||
{
|
||||
/// <summary>This allows you to set how many frames an unused RenderTexture will remaining in memory before it's released.</summary>
|
||||
public int Lifetime { set { lifetime = value; } get { return lifetime; } } [SerializeField] private int lifetime = 3;
|
||||
|
||||
#if USE_CUSTOM_TEMPORARY
|
||||
private class Entry
|
||||
{
|
||||
public RenderTexture RT;
|
||||
|
||||
public RenderTextureDescriptor Desc;
|
||||
|
||||
public int Life;
|
||||
|
||||
public static Stack<Entry> Pool = new Stack<Entry>();
|
||||
}
|
||||
|
||||
private static List<Entry> entries = new List<Entry>();
|
||||
|
||||
private static LinkedList<CwRenderTextureManager> instances = new LinkedList<CwRenderTextureManager>();
|
||||
|
||||
private LinkedListNode<CwRenderTextureManager> node;
|
||||
|
||||
public static RenderTexture GetTemporary(RenderTextureDescriptor desc, string title)
|
||||
{
|
||||
if (instances.Count == 0)
|
||||
{
|
||||
new GameObject("CwRenderTextureManager").AddComponent<CwRenderTextureManager>();
|
||||
}
|
||||
|
||||
for (var i = entries.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var entry = entries[i];
|
||||
|
||||
if (entry.RT == null)
|
||||
{
|
||||
entry.RT = null;
|
||||
|
||||
Entry.Pool.Push(entry);
|
||||
|
||||
entries.RemoveAt(i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Match(ref entry.Desc, ref desc) == true)
|
||||
{
|
||||
Entry.Pool.Push(entry);
|
||||
|
||||
entries.RemoveAt(i);
|
||||
|
||||
entry.RT.name = title;
|
||||
|
||||
if (entry.RT.IsCreated() == false)
|
||||
{
|
||||
entry.RT.Create();
|
||||
}
|
||||
|
||||
return entry.RT;
|
||||
}
|
||||
}
|
||||
|
||||
var rt = new RenderTexture(desc);
|
||||
|
||||
rt.name = title;
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static RenderTexture ReleaseTemporary(RenderTexture rt)
|
||||
{
|
||||
if (rt != null)
|
||||
{
|
||||
if (instances.Count > 0)
|
||||
{
|
||||
var entry = Entry.Pool.Count > 0 ? Entry.Pool.Pop() : new Entry();
|
||||
|
||||
entry.RT = rt;
|
||||
entry.Desc = rt.descriptor;
|
||||
entry.Life = Mathf.Max(1, instances.First.Value.lifetime);
|
||||
|
||||
entries.Add(entry);
|
||||
|
||||
rt.DiscardContents();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt.Release();
|
||||
|
||||
DestroyImmediate(rt);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
node = instances.AddLast(this);
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
instances.Remove(node); node = null;
|
||||
|
||||
if (instances.Count == 0)
|
||||
{
|
||||
for (var i = entries.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var entry = entries[i];
|
||||
|
||||
if (entry.RT != null)
|
||||
{
|
||||
entry.RT.Release();
|
||||
|
||||
DestroyImmediate(entry.RT);
|
||||
}
|
||||
|
||||
Entry.Pool.Push(entry);
|
||||
}
|
||||
|
||||
entries.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (node == instances.First)
|
||||
{
|
||||
Tick();
|
||||
}
|
||||
}
|
||||
|
||||
private void Tick()
|
||||
{
|
||||
for (var i = entries.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var entry = entries[i];
|
||||
|
||||
if (entry.Life > 0)
|
||||
{
|
||||
entry.Life -= 1;
|
||||
|
||||
if (entry.Life == 0 && entry.RT != null && entry.RT.IsCreated() == true)
|
||||
{
|
||||
entry.RT.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Match(ref RenderTextureDescriptor a, ref RenderTextureDescriptor b)
|
||||
{
|
||||
if (a.enableRandomWrite != b.enableRandomWrite) return false;
|
||||
if (a.autoGenerateMips != b.autoGenerateMips) return false;
|
||||
if (a.useMipMap != b.useMipMap) return false;
|
||||
if (a.memoryless != b.memoryless) return false;
|
||||
if (a.flags != b.flags) return false;
|
||||
if (a.vrUsage != b.vrUsage) return false;
|
||||
if (a.shadowSamplingMode != b.shadowSamplingMode) return false;
|
||||
if (a.dimension != b.dimension) return false;
|
||||
if (a.depthBufferBits != b.depthBufferBits) return false;
|
||||
if (a.stencilFormat != b.stencilFormat) return false;
|
||||
if (a.colorFormat != b.colorFormat) return false;
|
||||
if (a.bindMS != b.bindMS) return false;
|
||||
if (a.graphicsFormat != b.graphicsFormat) return false;
|
||||
if (a.mipCount != b.mipCount) return false;
|
||||
if (a.volumeDepth != b.volumeDepth) return false;
|
||||
if (a.msaaSamples != b.msaaSamples) return false;
|
||||
if (a.height != b.height) return false;
|
||||
if (a.width != b.width) return false;
|
||||
if (a.sRGB != b.sRGB) return false;
|
||||
if (a.useDynamicScale != b.useDynamicScale) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
public static RenderTexture GetTemporary(RenderTextureDescriptor desc, string title)
|
||||
{
|
||||
var renderTexture = RenderTexture.GetTemporary(desc);
|
||||
|
||||
// TODO: For some reason RenderTexture.GetTemporary ignores the useMipMap flag?!
|
||||
if (renderTexture.useMipMap != desc.useMipMap)
|
||||
{
|
||||
renderTexture.Release();
|
||||
|
||||
renderTexture.descriptor = desc;
|
||||
|
||||
renderTexture.Create();
|
||||
}
|
||||
|
||||
return renderTexture;
|
||||
}
|
||||
|
||||
public static RenderTexture ReleaseTemporary(RenderTexture renderTexture)
|
||||
{
|
||||
if (renderTexture != null)
|
||||
{
|
||||
renderTexture.DiscardContents();
|
||||
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace CW.Common
|
||||
{
|
||||
using UnityEditor;
|
||||
using TARGET = CwRenderTextureManager;
|
||||
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TARGET))]
|
||||
public class CwRenderTextureManager_Editor : CwEditor
|
||||
{
|
||||
protected override void OnInspector()
|
||||
{
|
||||
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
|
||||
|
||||
Draw("lifetime", "This allows you to set how many frames an unused RenderTexture will remaining in memory before it's released.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 074581640de185e4f9953ebbc6d61a87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 26286
|
||||
packageName: Paint in 3D
|
||||
packageVersion: 3.0.2
|
||||
assetPath: Assets/Plugins/CW/Shared/Common/Extras/Scripts/CwRenderTextureManager.cs
|
||||
uploadId: 595998
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CW.Common
|
||||
{
|
||||
/// <summary>This attribute can be added to any int field to make it a random seed value that can easily be randomized.</summary>
|
||||
public class CwSeedAttribute : PropertyAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace CW.Common
|
||||
{
|
||||
using UnityEditor;
|
||||
|
||||
[CustomPropertyDrawer(typeof(CwSeedAttribute))]
|
||||
public class CwSeedDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var rect1 = position; rect1.xMax = position.xMax - 20;
|
||||
var rect2 = position; rect2.xMin = position.xMax - 18;
|
||||
|
||||
EditorGUI.PropertyField(rect1, property, label);
|
||||
|
||||
if (GUI.Button(rect2, "R") == true)
|
||||
{
|
||||
property.intValue = Random.Range(int.MinValue, int.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0c2debde2a068741bac1cf9efca66ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user