/* INFINITY CODE */ /* https://infinity-code.com */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine; using UnityEngine.Networking; /// /// The wrapper class for WWW.
/// It allows you to control requests.
/// To create is recommended to use OnlineMapsUtils.GetWWW. ///
public class OnlineMapsWWW: CustomYieldInstruction, IDisposable { #region Actions /// /// Called when a request has been created but not yet sent. /// public static Action OnCreateRequest; /// /// This event is occurs when URL is initialized, and allows you to modify it. /// public static Func OnInit; /// /// Events to validate the request. Return false if you want to cancel the request. /// public static Predicate OnValidate; /// /// Event that occurs when a request is completed. /// public Action OnComplete; #endregion #region Variables private static MonoBehaviour temponaryBehavour; private byte[] _bytes; private Dictionary _customFields; private string _error; private string _id; private bool _isDone; private string _url; private MonoBehaviour currentCoroutineBehaviour; private bool isYield = false; private string responseHeadersString; private RequestType type; private IEnumerator waitResponse; private UnityWebRequest www; #endregion #region Properties /// /// Gets / sets custom fields value by key /// /// Custom field key /// Custom field value public object this[string key] { get { object val; return customFields.TryGetValue(key, out val) ? val : null; } set { customFields[key] = value; } } /// /// Returns the contents of the fetched web page as a byte array. /// public byte[] bytes { get { if (type == RequestType.www) return www.downloadHandler.data; return _bytes; } } /// /// The number of bytes downloaded by this query. /// public int bytesDownloaded { get { if (type == RequestType.www) return (int) www.downloadedBytes; return _bytes != null ? _bytes.Length : 0; } } private static MonoBehaviour coroutineBehaviour { get { if (OnlineMaps.instance != null) return OnlineMaps.instance; if (temponaryBehavour == null) { GameObject go = new GameObject("__OnlineMapsWWW__"); go.hideFlags = HideFlags.HideInHierarchy; temponaryBehavour = go.AddComponent(); } return temponaryBehavour; } } /// /// Gets customFields dictionary /// public Dictionary customFields { get { if (_customFields == null) _customFields = new Dictionary(); return _customFields; } } /// /// Returns an error message if there was an error during the download. /// public string error { get { if (type == RequestType.www) return www.error; return _error; } } /// /// This property is true if the request has encountered an error. /// public bool hasError { get { return !string.IsNullOrEmpty(error); } } /// /// ID of query. /// public string id { get { return _id; } } /// /// Is the download already finished? /// public bool isDone { get { if (type == RequestType.www) return www != null && www.isDone; return _isDone; } } public override bool keepWaiting { get { isYield = true; return !isDone; } } public UnityWebRequest request { get { return www; } } /// /// Dictionary of headers returned by the request. /// public Dictionary responseHeaders { get { if (!isDone) throw new UnityException("WWW is not finished downloading yet"); if (type == RequestType.www) return www.GetResponseHeaders(); return ParseHTTPHeaderString(responseHeadersString); } } /// /// Returns the contents of the fetched web page as a string. /// public string text { get { if (type == RequestType.www) return www.downloadHandler.text; return _bytes != null ? GetTextEncoder().GetString(_bytes, 0, _bytes.Length) : null; } } /// /// The URL of this request. /// public string url { get { return _url; } } #endregion #region Methods /// /// Constructor /// /// URL of request public OnlineMapsWWW(string url) { SetURL(url); type = RequestType.www; if (OnValidate != null && !OnValidate(this.url)) { currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitCancel()); return; } www = UnityWebRequest.Get(this.url); if (OnCreateRequest != null) OnCreateRequest(this); www.SendWebRequest(); currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitResponse()); } /// /// Constructor /// /// URL of request public OnlineMapsWWW(StringBuilder url) : this(url.ToString()) { } /// /// Constructor /// /// URL of request /// Type of request /// Request ID public OnlineMapsWWW(string url, RequestType type, string reqID) { this.type = type; SetURL(url); if (OnValidate != null && !OnValidate(this.url)) { currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitCancel()); return; } _id = reqID; if (type == RequestType.www) { www = UnityWebRequest.Get(this.url); if (OnCreateRequest != null) OnCreateRequest(this); www.SendWebRequest(); currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitResponse()); } } /// /// Constructor. /// /// WWW instance. private OnlineMapsWWW(UnityWebRequest www) { SetURL(www.url); type = RequestType.www; if (OnValidate != null && !OnValidate(url)) { currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitCancel()); return; } this.www = www; waitResponse = WaitResponse(); currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(waitResponse); } public OnlineMapsWWW(string url, string postData, Dictionary headers = null) { SetURL(url); type = RequestType.www; if (OnValidate != null && !OnValidate(this.url)) { currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitCancel()); return; } byte[] bodyRaw = Encoding.UTF8.GetBytes(postData); www = new UnityWebRequest(this.url, "POST"); if (OnCreateRequest != null) OnCreateRequest(this); www.uploadHandler = new UploadHandlerRaw(bodyRaw); www.downloadHandler = new DownloadHandlerBuffer(); if (headers != null) { foreach (var pair in headers) { www.SetRequestHeader(pair.Key, pair.Value); } } www.SendWebRequest(); currentCoroutineBehaviour = coroutineBehaviour; currentCoroutineBehaviour.StartCoroutine(WaitResponse()); } /// /// Disposes of an existing object. /// public void Dispose() { if (www != null && !www.isDone) www.Dispose(); www = null; _customFields = null; if (waitResponse != null) currentCoroutineBehaviour.StopCoroutine(waitResponse); } /// /// Escapes characters in a string to ensure they are URL-friendly. /// /// A string with characters to be escaped. /// Escaped string. public static string EscapeURL(string s) { return UnityWebRequest.EscapeURL(s); } private void Finish() { if (OnComplete != null) OnComplete(this); if (!hasError) { OnlineMapsLog.Info("Response: " + www.responseCode + " from " + url, OnlineMapsLog.Type.request); } else { OnlineMapsLog.Warning("Error: " + error + "\nfrom " + url, OnlineMapsLog.Type.request); } if (!isYield) Dispose(); } private Encoding GetTextEncoder() { string str; if (responseHeaders.TryGetValue("CONTENT-TYPE", out str)) { int index = str.IndexOf("charset", StringComparison.OrdinalIgnoreCase); if (index > -1) { int num2 = str.IndexOf('=', index); if (num2 > -1) { char[] trimChars = { '\'', '"' }; string name = str.Substring(num2 + 1).Trim().Trim(trimChars).Trim(); int length = name.IndexOf(';'); if (length > -1) { name = name.Substring(0, length); } try { return Encoding.GetEncoding(name); } catch (Exception) { Debug.Log("Unsupported encoding: '" + name + "'"); } } } } return Encoding.UTF8; } /// /// Replaces the contents of an existing Texture2D with an image from the downloaded data. /// /// An existing texture object to be overwritten with the image data. public void LoadImageIntoTexture(Texture2D tex) { if (tex == null) throw new Exception("Texture is null"); if (type == RequestType.www) tex.LoadImage(bytes); else tex.LoadImage(_bytes); } internal static Dictionary ParseHTTPHeaderString(string input) { Dictionary dictionary = new Dictionary(); if (string.IsNullOrEmpty(input)) return dictionary; StringReader reader = new StringReader(input); int num = 0; while (true) { string str = reader.ReadLine(); if (str == null) { return dictionary; } if ((num++ == 0) && str.StartsWith("HTTP")) { dictionary["STATUS"] = str; } else { int index = str.IndexOf(": "); if (index != -1) { string str2 = str.Substring(0, index).ToUpper(); string str3 = str.Substring(index + 2); dictionary[str2] = str3; } } } } /// /// Sets the contents and headers of the response for type = direct. /// /// Headers of response. /// Content of response. public void SetBytes(string responseHeadersString, byte[] _bytes) { if (type == RequestType.www) throw new Exception("OnlineMapsWWW.SetBytes available only for type = direct."); this.responseHeadersString = responseHeadersString; this._bytes = _bytes; _isDone = true; Finish(); } /// /// Sets the error for type = direct. /// /// Error message. public void SetError(string errorStr) { if (type == RequestType.www) throw new Exception("OnlineMapsWWW.SetError available only for type = direct."); _error = errorStr; _isDone = true; Finish(); } private void SetURL(string url) { #if UNITY_IOS url = url.Replace("|", "%7C"); #endif #if UNITY_WEBGL// && !UNITY_EDITOR if (OnlineMaps.instance.useProxy) { if (url.Contains(".virtualearth.net")) url = OnlineMaps.instance.proxyURL + url; else if (url.Contains("sampleserver4.arcgisonline.com/ArcGIS/rest/services/Elevation")) url = OnlineMaps.instance.proxyURL + url; } #endif if (OnInit != null) url = OnInit(url); OnlineMapsLog.Info(url, OnlineMapsLog.Type.request); _url = url; } private IEnumerator WaitCancel() { type = RequestType.direct; yield return null; _error = "Request canceled."; Finish(); } private IEnumerator WaitResponse() { while (!www.isDone) { yield return null; } waitResponse = null; Finish(); } #endregion /// /// Type of request. /// public enum RequestType { /// /// The request will be processed independently.
/// Use OnlineMapsUtils.OnGetWWW to process of request. ///
direct, /// /// The request will be processed using WWW or UnityWebClient class. /// www } }