备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 388552ada77be9a4ea13526b21d3a28d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d2ec44108dda21438f164cae219f224
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d2927631b10c2f4b9ce492ed53fd69b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 200
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8da33d20535c346499a0c78cabe4d750
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0c2debde2a068741bac1cf9efca66ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: