Skip to content

Instantly share code, notes, and snippets.

@Moe-Baker
Created January 16, 2020 13:05
Show Gist options
  • Save Moe-Baker/4f127f78c36e62a4019e7fbf30c08ca6 to your computer and use it in GitHub Desktop.
Save Moe-Baker/4f127f78c36e62a4019e7fbf30c08ca6 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.AI;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
#endif
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace Game
{
public class SpriteSheetAnimator : MonoBehaviour
{
[SerializeField]
protected Texture2D source;
public Texture2D Source { get { return source; } }
[SerializeField]
protected List<Point> elements;
public List<Point> Elements { get { return elements; } }
[Serializable]
public class Point
{
[SerializeField]
protected Motion[] motions;
public Motion[] Motions { get { return motions; } }
[SerializeField]
protected FloatToggleValue frameTime;
public FloatToggleValue FrameTime { get { return frameTime; } }
public Point(Motion[] motions)
{
this.motions = motions;
}
public Point(Motion motion) : this(new Motion[] { motion })
{
}
public Point(Sprite sprite) : this(new Motion(sprite))
{
}
}
[Serializable]
public class Motion
{
[SerializeField]
protected Sprite sprite;
public Sprite Sprite { get { return sprite; } }
[SerializeField]
protected int channel = 0;
public int Channel { get { return channel; } }
[SerializeField]
protected bool clear = false;
public bool Clear { get { return clear; } }
public Motion(Sprite sprite)
{
this.sprite = sprite;
}
}
[Header("Playback")]
[SerializeField]
protected float frameTime = 0.1f;
public float FrameTime { get { return frameTime; } }
[SerializeField]
protected bool playOnAwake;
public bool PlayOnAwake { get { return playOnAwake; } }
[SerializeField]
protected bool loop;
public bool Loop { get { return loop; } }
[SerializeField]
protected ChannelsController channels;
public ChannelsController Channels { get { return channels; } }
[Serializable]
public class ChannelsController
{
public Dictionary<int, SpriteRenderer> Dictionary { get; protected set; }
public int Count => Dictionary.Count;
public SpriteRenderer this[int index] => Retrieve(index);
public Sandbox Reference { get; protected set; }
public virtual void Init(Sandbox reference)
{
this.Reference = reference;
Dictionary = new Dictionary<int, SpriteRenderer>();
}
public virtual SpriteRenderer Retrieve(int index)
{
if (Dictionary.ContainsKey(index))
return Dictionary[index];
else
{
var instance = Create(index);
Dictionary.Add(index, instance);
return instance;
}
}
public virtual SpriteRenderer Create(int index)
{
var gameObject = new GameObject("Channel " + index);
gameObject.transform.SetParent(Reference.transform);
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localRotation = Quaternion.identity;
gameObject.transform.localScale = Vector3.one;
var renderer = gameObject.AddComponent<SpriteRenderer>();
renderer.sortingOrder = index;
return renderer;
}
public virtual void ForAll(Action<SpriteRenderer> action)
{
foreach (var renderer in Dictionary.Values)
action(renderer);
}
public void Clear()
{
ForAll(Action);
void Action(SpriteRenderer renderer) => renderer.sprite = null;
}
}
private void Awake()
{
channels.Init(this);
if (playOnAwake) Play();
}
#if UNITY_EDITOR
private void Reset()
{
ConvertSource();
}
void ConvertSource()
{
if (source == null)
{
}
else
{
var path = AssetDatabase.GetAssetPath(source);
var sprites = AssetDatabase.LoadAllAssetsAtPath(path).OfType<Sprite>().ToList();
elements = new List<Point>();
for (int i = 0; i < sprites.Count; i++)
{
var instance = new Point(sprites[i]);
elements.Add(instance);
}
}
}
#endif
public void Play()
{
if(coroutine != null) StopCoroutine(coroutine);
if(elements.Count == 0)
{
Debug.LogWarning("No sprites defined, ignoring play request");
return;
}
channels.Clear();
coroutine = StartCoroutine(Procedure());
}
Coroutine coroutine;
IEnumerator Procedure()
{
var index = 0;
while (true)
{
var element = elements[index];
for (int i = 0; i < element.Motions.Length; i++)
Apply(element.Motions[i]);
yield return new WaitForSeconds(element.FrameTime.Evaluate(frameTime));
if (++index == elements.Count)
{
channels.Clear();
if (loop)
index = 0;
else
break;
}
}
coroutine = null;
}
protected virtual void Apply(Motion motion)
{
var channel = channels[motion.Channel];
if (motion.Clear) channels.Clear();
channels[motion.Channel].sprite = motion.Sprite;
}
[CustomEditor(typeof(Sandbox))]
public class Inspector : Editor
{
new IList<Sandbox> targets;
private void OnEnable()
{
targets = base.targets.Cast<Sandbox>().ToArray();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DrawProcessButton();
}
void DrawProcessButton()
{
if(GUILayout.Button("Convert Source"))
{
for (int i = 0; i < targets.Count; i++)
{
targets[i].ConvertSource();
}
}
}
}
}
[Serializable]
public class ComplexToggleValue : ToggleValue<ComplexToggleValue.Data>
{
[Serializable]
public class Data
{
public IntToggleValue _int;
public FloatToggleValue _float;
public StringToggleValue _string;
public ColorToggleValue _color;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment