上海虹口龙之梦项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

442 lines
17 KiB

using System;
using System.Collections;
using UnityEngine;
#if !UniRxLibrary
using ObservableUnity = UniRx.Observable;
#endif
#if UNITY_2018_3_OR_NEWER
#pragma warning disable CS0618
#endif
namespace UniRx
{
using System.Threading;
#if !(UNITY_METRO || UNITY_WP8) && (UNITY_4_4 || UNITY_4_3 || UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5 || UNITY_3_4 || UNITY_3_3 || UNITY_3_2 || UNITY_3_1 || UNITY_3_0_0 || UNITY_3_0 || UNITY_2_6_1 || UNITY_2_6)
// Fallback for Unity versions below 4.5
using Hash = System.Collections.Hashtable;
using HashEntry = System.Collections.DictionaryEntry;
#else
// Unity 4.5 release notes:
// WWW: deprecated 'WWW(string url, byte[] postData, Hashtable headers)',
// use 'public WWW(string url, byte[] postData, Dictionary<string, string> headers)' instead.
using Hash = System.Collections.Generic.Dictionary<string, string>;
using HashEntry = System.Collections.Generic.KeyValuePair<string, string>;
#endif
#if UNITY_2018_3_OR_NEWER
[Obsolete("Use UnityWebRequest, a fully featured replacement which is more efficient and has additional features")]
#endif
public static partial class ObservableWWW
{
public static IObservable<string> Get(string url, Hash headers = null, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<string>((observer, cancellation) => FetchText(new WWW(url, null, (headers ?? new Hash())), observer, progress, cancellation));
}
public static IObservable<byte[]> GetAndGetBytes(string url, Hash headers = null, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<byte[]>((observer, cancellation) => FetchBytes(new WWW(url, null, (headers ?? new Hash())), observer, progress, cancellation));
}
public static IObservable<WWW> GetWWW(string url, Hash headers = null, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<WWW>((observer, cancellation) => Fetch(new WWW(url, null, (headers ?? new Hash())), observer, progress, cancellation));
}
public static IObservable<string> Post(string url, byte[] postData, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<string>((observer, cancellation) => FetchText(new WWW(url, postData), observer, progress, cancellation));
}
public static IObservable<string> Post(string url, byte[] postData, Hash headers, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<string>((observer, cancellation) => FetchText(new WWW(url, postData, headers), observer, progress, cancellation));
}
public static IObservable<string> Post(string url, WWWForm content, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<string>((observer, cancellation) => FetchText(new WWW(url, content), observer, progress, cancellation));
}
public static IObservable<string> Post(string url, WWWForm content, Hash headers, IProgress<float> progress = null)
{
var contentHeaders = content.headers;
return ObservableUnity.FromCoroutine<string>((observer, cancellation) => FetchText(new WWW(url, content.data, MergeHash(contentHeaders, headers)), observer, progress, cancellation));
}
public static IObservable<byte[]> PostAndGetBytes(string url, byte[] postData, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<byte[]>((observer, cancellation) => FetchBytes(new WWW(url, postData), observer, progress, cancellation));
}
public static IObservable<byte[]> PostAndGetBytes(string url, byte[] postData, Hash headers, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<byte[]>((observer, cancellation) => FetchBytes(new WWW(url, postData, headers), observer, progress, cancellation));
}
public static IObservable<byte[]> PostAndGetBytes(string url, WWWForm content, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<byte[]>((observer, cancellation) => FetchBytes(new WWW(url, content), observer, progress, cancellation));
}
public static IObservable<byte[]> PostAndGetBytes(string url, WWWForm content, Hash headers, IProgress<float> progress = null)
{
var contentHeaders = content.headers;
return ObservableUnity.FromCoroutine<byte[]>((observer, cancellation) => FetchBytes(new WWW(url, content.data, MergeHash(contentHeaders, headers)), observer, progress, cancellation));
}
public static IObservable<WWW> PostWWW(string url, byte[] postData, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<WWW>((observer, cancellation) => Fetch(new WWW(url, postData), observer, progress, cancellation));
}
public static IObservable<WWW> PostWWW(string url, byte[] postData, Hash headers, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<WWW>((observer, cancellation) => Fetch(new WWW(url, postData, headers), observer, progress, cancellation));
}
public static IObservable<WWW> PostWWW(string url, WWWForm content, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<WWW>((observer, cancellation) => Fetch(new WWW(url, content), observer, progress, cancellation));
}
public static IObservable<WWW> PostWWW(string url, WWWForm content, Hash headers, IProgress<float> progress = null)
{
var contentHeaders = content.headers;
return ObservableUnity.FromCoroutine<WWW>((observer, cancellation) => Fetch(new WWW(url, content.data, MergeHash(contentHeaders, headers)), observer, progress, cancellation));
}
public static IObservable<AssetBundle> LoadFromCacheOrDownload(string url, int version, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<AssetBundle>((observer, cancellation) => FetchAssetBundle(WWW.LoadFromCacheOrDownload(url, version), observer, progress, cancellation));
}
public static IObservable<AssetBundle> LoadFromCacheOrDownload(string url, int version, uint crc, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<AssetBundle>((observer, cancellation) => FetchAssetBundle(WWW.LoadFromCacheOrDownload(url, version, crc), observer, progress, cancellation));
}
// over Unity5 supports Hash128
#if !(UNITY_4_7 || UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3 || UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5 || UNITY_3_4 || UNITY_3_3 || UNITY_3_2 || UNITY_3_1 || UNITY_3_0_0 || UNITY_3_0 || UNITY_2_6_1 || UNITY_2_6)
public static IObservable<AssetBundle> LoadFromCacheOrDownload(string url, Hash128 hash128, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<AssetBundle>((observer, cancellation) => FetchAssetBundle(WWW.LoadFromCacheOrDownload(url, hash128), observer, progress, cancellation));
}
public static IObservable<AssetBundle> LoadFromCacheOrDownload(string url, Hash128 hash128, uint crc, IProgress<float> progress = null)
{
return ObservableUnity.FromCoroutine<AssetBundle>((observer, cancellation) => FetchAssetBundle(WWW.LoadFromCacheOrDownload(url, hash128, crc), observer, progress, cancellation));
}
#endif
// over 4.5, Hash define is Dictionary.
// below Unity 4.5, WWW only supports Hashtable.
// Unity 4.5, 4.6 WWW supports Dictionary and [Obsolete]Hashtable but WWWForm.content is Hashtable.
// Unity 5.0 WWW only supports Dictionary and WWWForm.content is also Dictionary.
#if !(UNITY_METRO || UNITY_WP8) && (UNITY_4_5 || UNITY_4_6 || UNITY_4_7)
static Hash MergeHash(Hashtable wwwFormHeaders, Hash externalHeaders)
{
var newHeaders = new Hash();
foreach (DictionaryEntry item in wwwFormHeaders)
{
newHeaders[item.Key.ToString()] = item.Value.ToString();
}
foreach (HashEntry item in externalHeaders)
{
newHeaders[item.Key] = item.Value;
}
return newHeaders;
}
#else
static Hash MergeHash(Hash wwwFormHeaders, Hash externalHeaders)
{
foreach (HashEntry item in externalHeaders)
{
wwwFormHeaders[item.Key] = item.Value;
}
return wwwFormHeaders;
}
#endif
static IEnumerator Fetch(WWW www, IObserver<WWW> observer, IProgress<float> reportProgress, CancellationToken cancel)
{
using (www)
{
if (reportProgress != null)
{
while (!www.isDone && !cancel.IsCancellationRequested)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
yield return null;
}
}
else
{
if (!www.isDone)
{
yield return www;
}
}
if (cancel.IsCancellationRequested)
{
yield break;
}
if (reportProgress != null)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
}
if (!string.IsNullOrEmpty(www.error))
{
observer.OnError(new WWWErrorException(www, www.text));
}
else
{
observer.OnNext(www);
observer.OnCompleted();
}
}
}
static IEnumerator FetchText(WWW www, IObserver<string> observer, IProgress<float> reportProgress, CancellationToken cancel)
{
using (www)
{
if (reportProgress != null)
{
while (!www.isDone && !cancel.IsCancellationRequested)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
yield return null;
}
}
else
{
if (!www.isDone)
{
yield return www;
}
}
if (cancel.IsCancellationRequested)
{
yield break;
}
if (reportProgress != null)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
}
if (!string.IsNullOrEmpty(www.error))
{
observer.OnError(new WWWErrorException(www, www.text));
}
else
{
observer.OnNext(www.text);
observer.OnCompleted();
}
}
}
static IEnumerator FetchBytes(WWW www, IObserver<byte[]> observer, IProgress<float> reportProgress, CancellationToken cancel)
{
using (www)
{
if (reportProgress != null)
{
while (!www.isDone && !cancel.IsCancellationRequested)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
yield return null;
}
}
else
{
if (!www.isDone)
{
yield return www;
}
}
if (cancel.IsCancellationRequested)
{
yield break;
}
if (reportProgress != null)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
}
if (!string.IsNullOrEmpty(www.error))
{
observer.OnError(new WWWErrorException(www, www.text));
}
else
{
observer.OnNext(www.bytes);
observer.OnCompleted();
}
}
}
static IEnumerator FetchAssetBundle(WWW www, IObserver<AssetBundle> observer, IProgress<float> reportProgress, CancellationToken cancel)
{
using (www)
{
if (reportProgress != null)
{
while (!www.isDone && !cancel.IsCancellationRequested)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
yield return null;
}
}
else
{
if (!www.isDone)
{
yield return www;
}
}
if (cancel.IsCancellationRequested)
{
yield break;
}
if (reportProgress != null)
{
try
{
reportProgress.Report(www.progress);
}
catch (Exception ex)
{
observer.OnError(ex);
yield break;
}
}
if (!string.IsNullOrEmpty(www.error))
{
observer.OnError(new WWWErrorException(www, ""));
}
else
{
observer.OnNext(www.assetBundle);
observer.OnCompleted();
}
}
}
}
public class WWWErrorException : Exception
{
public string RawErrorMessage { get; private set; }
public bool HasResponse { get; private set; }
public string Text { get; private set; }
public System.Net.HttpStatusCode StatusCode { get; private set; }
public System.Collections.Generic.Dictionary<string, string> ResponseHeaders { get; private set; }
public WWW WWW { get; private set; }
// cache the text because if www was disposed, can't access it.
public WWWErrorException(WWW www, string text)
{
this.WWW = www;
this.RawErrorMessage = www.error;
this.ResponseHeaders = www.responseHeaders;
this.HasResponse = false;
this.Text = text;
var splitted = RawErrorMessage.Split(' ', ':');
if (splitted.Length != 0)
{
int statusCode;
if (int.TryParse(splitted[0], out statusCode))
{
this.HasResponse = true;
this.StatusCode = (System.Net.HttpStatusCode)statusCode;
}
}
}
public override string ToString()
{
var text = this.Text;
if (string.IsNullOrEmpty(text))
{
return RawErrorMessage;
}
else
{
return RawErrorMessage + " " + text;
}
}
}
}
#if UNITY_2018_3_OR_NEWER
#pragma warning restore CS0618
#endif