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