Files
UPhotoFrame/Assets/Scripts/PhotoFrame.cs
T

187 lines
4.6 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class PhotoFrame : MonoBehaviour
{
const float PHOTO_INTERVAL = 5f;
const float ANIMATION_LENGTH = 2f;
[SerializeField]
GameObject mainUI;
[SerializeField]
RectTransform imageContainer;
[SerializeField]
Image[] images;
[SerializeField]
InputField url;
private int currentImage;
private Cache cache;
private Image CurrentImage
{
get { return images[currentImage]; }
}
private Image NextImage
{
get { return images[(currentImage + 1) % images.Length]; }
}
public void Start()
{
cache = new Cache(Application.persistentDataPath);
Screen.sleepTimeout = SleepTimeout.NeverSleep;
currentImage = 0;
ActivateUI(true);
}
private void ActivateUI(bool v)
{
mainUI.gameObject.SetActive(v);
for (int i = 0; i < images.Length; i++)
{
images[i].gameObject.SetActive(!v);
}
}
Coroutine mainCoroutine;
public void OnRunButtonClicked()
{
ActivateUI(false);
mainCoroutine = StartCoroutine(SwitchImages());
}
public void OnStopButtonClicked()
{
if (mainCoroutine != null)
{
StopCoroutine(mainCoroutine);
mainCoroutine = null;
}
for (int i = 0; i < images.Length; i++)
{
if (images[i].sprite != null)
{
Destroy(images[i].sprite.texture);
Destroy(images[i].sprite);
images[i].sprite = null;
}
}
ActivateUI(true);
}
private IEnumerator SwitchImages()
{
yield return null;
var loader = new ImageLoader(url.text);
while (loader.Status == LoaderStatus.Initializing) yield return null;
Color opaque = new Color(1, 1, 1, 1);
Color transparent = new Color(1, 1, 1, 0);
CurrentImage.color = transparent;
NextImage.color = transparent;
while (true)
{
var startTime = Time.realtimeSinceStartup;
int imageIndex = Random.Range(0, loader.images.Count);
string imageUrl = loader.images[imageIndex];
var bytes = cache.Get(imageUrl);
if (bytes != null)
{
var tex = new Texture2D(2, 2);
tex.LoadImage(bytes);
SetImageTexture(NextImage, tex);
}
else
{
var request = UnityWebRequest.Get(imageUrl);
request.downloadHandler = new DownloadHandlerTexture(true);
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
yield return new WaitForSeconds(1f);
continue;
}
var downloadTime = Time.realtimeSinceStartup - startTime;
if (PHOTO_INTERVAL > downloadTime)
{
yield return new WaitForSeconds(PHOTO_INTERVAL - downloadTime);
}
var dh = request.downloadHandler as DownloadHandlerTexture;
var tex = dh.texture;
SetImageTexture(NextImage, tex);
dh.Dispose();
request.Dispose();
cache.Add(imageUrl, tex.EncodeToJPG());
}
float currentStart = CurrentImage.color.a;
float currentFinish = transparent.a;
float nextStart = NextImage.color.a;
float nextFinish = opaque.a;
startTime = Time.time;
while (Time.time < startTime + ANIMATION_LENGTH)
{
float ct = Time.time;
float x = (ct - startTime) / ANIMATION_LENGTH;
float currentA = currentStart + x * (currentFinish - currentStart);
Color cC = new Color(CurrentImage.color.r, CurrentImage.color.g, CurrentImage.color.b, currentA);
CurrentImage.color = cC;
float nextA = nextStart + x * (nextFinish - nextStart);
Color nC = new Color(NextImage.color.r, NextImage.color.g, NextImage.color.b, nextA);
NextImage.color = nC;
yield return null;
}
currentImage = (currentImage + 1) % images.Length;
Resources.UnloadUnusedAssets();
System.GC.Collect();
}
}
private void SetImageTexture(Image nextImage, Texture2D tex)
{
if (nextImage.sprite != null)
{
Destroy(nextImage.sprite.texture);
Destroy(nextImage.sprite);
nextImage.sprite = null;
}
float imageWidth = imageContainer.rect.width;
float imageHeight = imageContainer.rect.height;
//
int maxHeight, maxWidth;
if (imageWidth < imageHeight)
{
// scale to height
maxHeight = 2048;
maxWidth = (int)(2048 / imageHeight * imageWidth);
}
else
{
// scale to width
maxWidth = 2048;
maxHeight = (int)(2048 / imageWidth * imageHeight);
}
float factor = Mathf.Min((float) maxWidth / tex.width, (float)maxHeight / tex.height);
int newWidth = (int)(tex.width * factor);
int newHeight = (int)(tex.height * factor);
TextureScale.Bilinear(tex, newWidth, newHeight);
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
nextImage.sprite = sprite;
nextImage.rectTransform.anchorMin = new Vector2((maxWidth - (float)newWidth) / maxWidth / 2, (maxHeight - (float)newHeight) / maxHeight / 2);
}
}