Example #1
0
        /// <summary>
        /// Set parameters for effect
        /// </summary>
        /// <param name="type">Effect</param>
        /// <param name="intensity">Intensity</param>
        /// <param name="vec">Vector data</param>
        /// <param name="color">RGB color</param>
        public void EffectSet(RB.Effect type, float intensity, Vector2i vec, Color32 color)
        {
            switch (type)
            {
                case RB.Effect.Noise:
                case RB.Effect.Desaturation:
                case RB.Effect.Curvature:
                case RB.Effect.Shake:
                case RB.Effect.Negative:
                case RB.Effect.Pixelate:
                    ParamsGet(type).Intensity = Mathf.Clamp01(intensity);
                    break;

                case RB.Effect.Scanlines:
                    ParamsGet(type).Intensity = Mathf.Clamp01(intensity);
                    break;

                case RB.Effect.Zoom:
                    ParamsGet(type).Intensity = Mathf.Clamp(intensity, 0, 10000.0f);
                    break;

                case RB.Effect.Slide:
                case RB.Effect.Wipe:
                    ParamsGet(type).Vector = new Vector2i(
                        Mathf.Clamp(vec.x, -RB.DisplaySize.width, RB.DisplaySize.width),
                        Mathf.Clamp(vec.y, -RB.DisplaySize.height, RB.DisplaySize.height));
                    break;

                case RB.Effect.Rotation:
                    ParamsGet(type).Intensity = RBUtil.WrapAngle(intensity);
                    break;

                case RB.Effect.ColorFade:
                case RB.Effect.ColorTint:
                    ParamsGet(type).Intensity = Mathf.Clamp01(intensity);
                    ParamsGet(type).Color = color;
                    break;

                case RB.Effect.Fizzle:
                    // Increase intensity by 1% to ensure full pixel coverage
                    ParamsGet(type).Intensity = Mathf.Clamp01(intensity) * 1.01f;
                    ParamsGet(type).Color = color;
                    break;

                case RB.Effect.Pinhole:
                case RB.Effect.InvertedPinhole:
                    ParamsGet(type).Intensity = Mathf.Clamp01(intensity);
                    ParamsGet(type).Vector = new Vector2i((int)Mathf.Clamp(vec.x, 0, RB.DisplaySize.width - 1), (int)Mathf.Clamp(vec.y, 0, RB.DisplaySize.height - 1));
                    ParamsGet(type).Color = color;
                    break;
            }
        }
        /// <summary>
        /// Load audio asset
        /// </summary>
        /// <param name="path">Path to load from</param>
        /// <param name="asset">AudioAsset to load into</param>
        /// <param name="source">Source type</param>
        /// <returns>True if successful</returns>
        public bool Load(string path, AudioAsset asset, RB.AssetSource source)
        {
            audioAsset = asset;
            this.path  = path;

            if (path == null)
            {
                audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
            }

            if (asset == null)
            {
                Debug.LogError("AudioAsset is null!");
                return(false);
            }

            if (source == RB.AssetSource.Resources)
            {
                // Synchronous load
                if (path == null)
                {
                    Debug.LogError("Audio filename is null!");
                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                    return(false);
                }

#if !RETROBLIT_STANDALONE
                var clip = Resources.Load <AudioClip>(path);
#else
                var clip = Resources.LoadAudioSample(path);
#endif

                if (clip == null)
                {
                    Debug.LogError("Can't find sound file " + path + ", it must be under the Assets/Resources folder. " +
                                   "If you're trying to load from an WWW address, or Addressable Assets then please specify so with the \"source\" parameter.");

                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }

                // If current music clip is affected then update the clip
                if (asset == RetroBlitInternal.RBAPI.instance.Audio.currentMusicClip)
                {
                    var channel = RetroBlitInternal.RBAPI.instance.Audio.musicChannel;
                    if (channel.Source != null)
                    {
                        channel.Source.clip = clip;
                        channel.Source.loop = true;
                        channel.Source.Play();
                    }
                }

                asset.audioClip = clip;
                asset.progress  = 1;
                audioAsset.InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);

                return(true);
            }
            else if (source == RB.AssetSource.WWW)
            {
                var audioType = AudioTypeFromPath(path);
                if (audioType == AudioType.UNKNOWN)
                {
                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotSupported);
                    return(false);
                }

                mWebRequest = UnityWebRequestMultimedia.GetAudioClip(path, audioType);
                if (mWebRequest == null)
                {
                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                audioAsset.progress = 0;
                audioAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (source == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <AudioClip>(path);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    audioAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    audioAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    audioAsset.addressableHandle = mAddressableRequest;
                    audioAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                audioAsset.progress = 0;
                audioAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#endif
            else if (source == RB.AssetSource.ResourcesAsync)
            {
                // Finally attempt async resource load
                mResourceRequest = Resources.LoadAsync <AudioClip>(this.path);

                if (mResourceRequest == null)
                {
                    audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                audioAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
            }
            else
            {
                audioAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotSupported);
                return(false);
            }

            return(true);
        }
Example #3
0
        private bool LoadMapInfo()
        {
            string infoPath;

            path = path + ".tmx.rb/";

            mapAsset.internalState.mapDef.realPathName = path;

            mapAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            if (mSource == RB.AssetSource.WWW || mSource == RB.AssetSource.AddressableAssets)
            {
                infoPath = path + "info.bytes";
            }
            else
            {
                infoPath = path + "info";
            }

            // Check if this is a web request
            if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequest.Get(infoPath);
                if (mWebRequest == null)
                {
                    mapAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    mapAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                mapAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <TextAsset>(infoPath);

                if (mResourceRequest == null)
                {
                    mapAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <TextAsset>(infoPath);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    mapAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    mapAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    mapAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                mapAsset.progress = 0;
                mapAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#endif
            mapAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            return(true);
        }
Example #4
0
        private bool LoadLayerInfo()
        {
            RBTilemapTMX.TMXMapDef map = null;

            map = layerState.map.internalState.mapDef;

            if (map == null || map.realPathName == null || map.realPathName.Length == 0 || map.layers == null)
            {
                Debug.LogError("Can't load TMX layer, invalid map, or map not loaded yet!");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (!map.infinite)
            {
                Debug.LogError("TMX map is not infinite, use LoadTMXLayer() instead");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (!map.layers.ContainsKey(mTmxSourceLayer))
            {
                Debug.LogError("Layer " + mTmxSourceLayer + " not found");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                return(false);
            }

            var tmxLayer      = (RBTilemapTMX.TMXLayerDef)map.layers[mTmxSourceLayer];
            int layerNameHash = mWorkStr.Set(mTmxSourceLayer).ToLowerInvariant().GetHashCode();

            int chunkWidth  = map.chunkSize.x;
            int chunkHeight = map.chunkSize.y;

            ulong part1  = (ulong)mChunkOffset.x;
            ulong part2  = (ulong)mChunkOffset.y;
            ulong offset = ((part1 << 32) & 0xFFFFFFFF00000000) | (part2 & 0xFFFFFFFF);

            mTupleKey = new RBTilemapTMX.RetroBlitTuple <int, ulong>(layerNameHash, offset);

            var decompressed = map.chunkLRU.Get(mTupleKey);

            if (decompressed != null)
            {
                RetroBlitInternal.RBAPI.instance.Tilemap.FinalizeLayerChunkLoad(map, mTmxSourceLayer, mDestinationLayer, mChunkOffset, mDestPos, mPackedSpriteLookup, layerState, decompressed);
                return(true);
            }

            // If the chunk can't be found then fail silently and wipe the chunk area. This will also
            // release the chunk geometry on next draw because it will not have any vertices
            if (!mChunkIndex.ContainsKey(offset))
            {
                for (int y = mDestPos.y; y < mDestPos.y + chunkHeight; y++)
                {
                    for (int x = mDestPos.x; x < mDestPos.x + chunkWidth; x++)
                    {
                        RetroBlitInternal.RBAPI.instance.Tilemap.SpriteSet(mDestinationLayer, x, y, RB.SPRITE_EMPTY, Color.white, 0);

                        RBTilemapTMX.Tile[] tilesArr;
                        int tileIndex;
                        if (RetroBlitInternal.RBAPI.instance.Tilemap.GetTileRef(mDestinationLayer, x, y, out tilesArr, out tileIndex, true))
                        {
                            tilesArr[tileIndex].data = null;
                        }
                    }
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);
                return(true);
            }

            mChunkDef = mChunkIndex[offset];

            var mPath = map.realPathName + "layer_" + layerNameHash.ToString("x") + "_seg_" + mChunkDef.segmentIndex;

            if (mSource == RB.AssetSource.WWW || mSource == RB.AssetSource.AddressableAssets)
            {
                mPath += ".bytes";
            }

            // Check if this is a web request
            if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequest.Get(mPath);
                if (mWebRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <TextAsset>(mPath);

                if (mResourceRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);

                    return(false);
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <TextAsset>(mPath);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                layerState.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
                layerState.progress = 0;

                return(true);
            }
#endif
            return(true);
        }
Example #5
0
        private bool LoadLayerChunkIndex()
        {
            RBTilemapTMX.TMXMapDef map = null;

            map = layerState.map.internalState.mapDef;

            if (map == null || map.realPathName == null || map.realPathName.Length == 0 || map.layers == null)
            {
                Debug.LogError("Can't load TMX layer, invalid map, or map not loaded yet!");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (!map.infinite)
            {
                Debug.LogError("TMX map is not infinite, use LoadTMXLayer() instead");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (!map.layers.ContainsKey(mTmxSourceLayer))
            {
                Debug.LogError("Layer " + mTmxSourceLayer + " not found");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                return(false);
            }

            var tmxLayer      = (RBTilemapTMX.TMXLayerDef)map.layers[mTmxSourceLayer];
            int layerNameHash = mWorkStr.Set(mTmxSourceLayer).ToLowerInvariant().GetHashCode();

            mIndexPath = map.realPathName + "layer_" + layerNameHash.ToString("x") + "_index";
            if (mSource == RB.AssetSource.WWW)
            {
                mIndexPath += ".bytes";
            }

            var cached = map.layerIndexLRU.Get(mIndexPath);

            if (cached != null)
            {
                // Already have the chunk index in cache, no need to do anything else
                mChunkIndex = cached;
                return(true);
            }

            // Not in cache, will have to load async

            // Check if this is a web request
            if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequest.Get(mIndexPath);
                if (mWebRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <TextAsset>(mIndexPath);

                if (mResourceRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);

                    return(false);
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <TextAsset>(mIndexPath);
                }
#pragma warning disable 0414 // Unused warning
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }
#pragma warning restore 0414

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                layerState.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
                layerState.progress = 0;

                return(true);
            }
#endif
            // This should never happen
            layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);

            return(false);
        }
        private bool LoadLayerInfo()
        {
            RBTilemapTMX.TMXMapDef map = null;

            map = layerState.map.internalState.mapDef;

            if (map == null || map.realPathName == null || map.realPathName.Length == 0 || map.layers == null)
            {
                Debug.LogError("Can't load TMX layer, invalid map, or map not loaded yet!");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (map.infinite)
            {
                Debug.LogError("TMX map is infinite, use MapLoadTMXLayerChunk() instead");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                return(false);
            }

            if (!map.layers.ContainsKey(mTmxSourceLayer))
            {
                Debug.LogError("Layer " + mTmxSourceLayer + " not found");
                layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                return(false);
            }

            var tmxLayer      = (RBTilemapTMX.TMXLayerDef)map.layers[mTmxSourceLayer];
            var layerNameHash = mWorkStr.Set(mTmxSourceLayer).ToLowerInvariant().GetHashCode().ToString("x");

            mPath = map.realPathName + "layer_" + layerNameHash;

            if (mSource == RB.AssetSource.WWW || mSource == RB.AssetSource.AddressableAssets)
            {
                mPath += ".bytes";
            }

            // Check if this is a web request
            if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequest.Get(mPath);
                if (mWebRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <TextAsset>(mPath);

                if (mResourceRequest == null)
                {
                    layerState.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);

                    return(false);
                }
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <TextAsset>(mPath);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    layerState.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                layerState.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
                layerState.progress = 0;

                return(true);
            }
#endif

            layerState.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            return(true);
        }
        /// <summary>
        /// Load sprite sheet asset
        /// </summary>
        /// <param name="path">Path to asset</param>
        /// <param name="existingTexture">Existing texture to load from</param>
        /// <param name="size">Size of the texture</param>
        /// <param name="asset">SpriteSheetAsset to load into</param>
        /// <param name="source">Asset source type</param>
        /// <returns>True if successful</returns>
        public bool Load(string path, RenderTexture existingTexture, Vector2i size, SpriteSheetAsset asset, RB.AssetSource source)
        {
            this.spriteSheetAsset = asset;
            this.path             = path;

            if (asset == null)
            {
                Debug.LogError("SpriteSheetAsset is null!");
                return(false);
            }

            if (source == RB.AssetSource.Resources)
            {
                // Empty texture
                if (path == null && existingTexture == null)
                {
                    if (size.x <= 0 || size.y <= 0)
                    {
                        spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                        return(false);
                    }

                    RenderTexture tex = new RenderTexture(size.x, size.y, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
                    if (tex == null)
                    {
                        spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                        return(false);
                    }

                    tex.filterMode   = FilterMode.Point;
                    tex.wrapMode     = TextureWrapMode.Clamp;
                    tex.anisoLevel   = 0;
                    tex.antiAliasing = 1;

                    tex.autoGenerateMips = false;
                    tex.depth            = 0;
                    tex.useMipMap        = false;

                    tex.Create();

                    asset.internalState.texture       = tex;
                    asset.internalState.textureWidth  = (ushort)tex.width;
                    asset.internalState.textureHeight = (ushort)tex.height;
#if MESH_UPLOAD_2019_3
                    asset.internalState.texelWidth  = 0xFFFF / (float)tex.width;
                    asset.internalState.texelHeight = 0xFFFF / (float)tex.height;
#endif
                    asset.internalState.spriteGrid.cellSize.width  = (ushort)tex.width;
                    asset.internalState.spriteGrid.cellSize.height = (ushort)tex.height;
                    asset.internalState.columns    = (ushort)(asset.internalState.textureWidth / asset.internalState.spriteGrid.cellSize.width);
                    asset.internalState.rows       = (ushort)(asset.internalState.textureHeight / asset.internalState.spriteGrid.cellSize.height);
                    asset.internalState.needsClear = true;

                    if (asset.internalState.columns < 1)
                    {
                        asset.internalState.columns = 1;
                    }

                    if (asset.internalState.rows < 1)
                    {
                        asset.internalState.rows = 1;
                    }

                    // If there is no spritesheet set then set this one as the current one
                    if (RetroBlitInternal.RBAPI.instance.Renderer.CurrentSpriteSheet == null)
                    {
                        RetroBlitInternal.RBAPI.instance.Renderer.SpriteSheetSet(asset);
                    }

                    asset.progress = 1;
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);

                    return(true);
                }
                else if (existingTexture != null)
                {
                    asset.internalState.texture       = existingTexture;
                    asset.internalState.textureWidth  = (ushort)existingTexture.width;
                    asset.internalState.textureHeight = (ushort)existingTexture.height;
#if MESH_UPLOAD_2019_3
                    asset.internalState.texelWidth  = 0xFFFF / (float)existingTexture.width;
                    asset.internalState.texelHeight = 0xFFFF / (float)existingTexture.height;
#endif
                    asset.internalState.spriteGrid.cellSize.width  = (ushort)existingTexture.width;
                    asset.internalState.spriteGrid.cellSize.height = (ushort)existingTexture.height;
                    asset.internalState.columns = (ushort)(asset.internalState.textureWidth / asset.internalState.spriteGrid.cellSize.width);
                    asset.internalState.rows    = (ushort)(asset.internalState.textureHeight / asset.internalState.spriteGrid.cellSize.height);

                    if (asset.internalState.columns < 1)
                    {
                        asset.internalState.columns = 1;
                    }

                    if (asset.internalState.rows < 1)
                    {
                        asset.internalState.rows = 1;
                    }

                    // If there is no spritesheet set then set this one as the current one
                    if (RetroBlitInternal.RBAPI.instance.Renderer.CurrentSpriteSheet == null)
                    {
                        RetroBlitInternal.RBAPI.instance.Renderer.SpriteSheetSet(asset);
                    }

                    asset.progress = 1;
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);

                    return(true);
                }
                else
                {
                    // Synchronous load
                    var spritesTextureOriginal = Resources.Load <Texture2D>(path);
                    if (spritesTextureOriginal == null)
                    {
                        Debug.LogError("Could not load sprite sheet from " + path + ", make sure the resource is placed somehwere in Assets/Resources folder. " +
                                       "If you're trying to load a Sprite Pack then please specify \"SpriteSheetAsset.SheetType.SpritePack\" as \"sheetType\". " +
                                       "If you're trying to load from an WWW address, or Addressable Assets then please specify so with the \"source\" parameter.");
                        asset.internalState.texture = null;
                        spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);

                        return(false);
                    }

                    FinalizeTexture(spritesTextureOriginal);

                    return(asset.status == RB.AssetStatus.Ready ? true : false);
                }
            }
            else if (source == RB.AssetSource.WWW)
            {
                if (!ImageTypeSupported(path))
                {
                    Debug.LogError("WWW source supports only PNG and JPG images");
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotSupported);
                    return(false);
                }

                mWebRequest = UnityWebRequestTexture.GetTexture(path, true);
                if (mWebRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (source == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <Texture2D>(this.path);

                if (mResourceRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);

                    return(false);
                }
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (source == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <Texture2D>(path);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                spriteSheetAsset.progress = 0;
                spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#endif

            spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            return(true);
        }
        private bool LoadSpriteSheet()
        {
            string spriteSheetPath;

            if (mSource == RB.AssetSource.WWW)
            {
                spriteSheetPath = path + ".sp.rb/spritepack.png";
            }
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                spriteSheetPath = path + ".sp.rb/spritepack.png";
            }
            else
            {
                spriteSheetPath = path + ".sp.rb/spritepack";
            }

            if (mSource == RB.AssetSource.Resources)
            {
                // Synchronous load
                var spritesTextureOriginal = Resources.Load <Texture2D>(spriteSheetPath);
                if (spritesTextureOriginal == null)
                {
                    Debug.LogError("Could not load sprite pack from " + path + ", make sure the resource is placed somehwere in Assets/Resources folder. " +
                                   "If you're trying to load a Sprite Pack then please specify \"SpriteSheetAsset.SheetType.SpritePack\" as \"sheetType\". " +
                                   "If you're trying to load from an WWW address, or Addressable Assets then please specify so with the \"source\" parameter.");
                    spriteSheetAsset.internalState.texture = null;

                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);

                    return(false);
                }

                FinalizeTexture(spritesTextureOriginal);

                return(spriteSheetAsset.status == RB.AssetStatus.Ready ? true : false);
            }
            else if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequestTexture.GetTexture(spriteSheetPath, true);
                if (mWebRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <Texture2D>(spriteSheetPath);

                if (mResourceRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequestTexture = Addressables.LoadAssetAsync <Texture2D>(spriteSheetPath);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    RBUtil.Unused(e);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequestTexture.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequestTexture);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#endif

            spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            return(true);
        }
        private bool LoadSpritePackInfo()
        {
            string infoPath;

            if (mSource == RB.AssetSource.WWW)
            {
                infoPath = path + ".sp.rb/info.bytes";
            }
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                infoPath = path + ".sp.rb/info.bytes";
            }
            else
            {
                infoPath = path + ".sp.rb/info";
            }

            if (mSource == RB.AssetSource.Resources)
            {
                // Synchronous load
                var infoFile = Resources.Load <TextAsset>(infoPath);
                if (infoFile == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }

                if (FinalizeSpritePackInfo(infoFile.bytes))
                {
                    LoadSpriteSheet();
                    return(spriteSheetAsset.status == RB.AssetStatus.Ready ? true : false);
                }
            }

            if (mSource == RB.AssetSource.WWW)
            {
                mWebRequest = UnityWebRequest.Get(infoPath);
                if (mWebRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                if (mWebRequest.SendWebRequest() == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
            else if (mSource == RB.AssetSource.ResourcesAsync)
            {
                mResourceRequest = Resources.LoadAsync <TextAsset>(infoPath);

                if (mResourceRequest == null)
                {
                    spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (mSource == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequestInfo = Addressables.LoadAssetAsync <TextAsset>(infoPath);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    Addressables.Release(mAddressableRequestInfo);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    Addressables.Release(mAddressableRequestInfo);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequestInfo.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequestInfo);
                    spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                spriteSheetAsset.progress = 0;
                spriteSheetAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

                return(true);
            }
#endif

            spriteSheetAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);

            return(true);
        }
        /// <summary>
        /// Load shader asset
        /// </summary>
        /// <param name="path">Path to load from</param>
        /// <param name="asset">ShaderAsset to load into</param>
        /// <param name="source">Source type</param>
        /// <returns>True if successful</returns>
        public bool Load(string path, ShaderAsset asset, RB.AssetSource source)
        {
            shaderAsset = asset;
            this.path   = path;

            if (path == null)
            {
                shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
            }

            if (asset == null)
            {
                Debug.LogError("ShaderAsset is null!");
                return(false);
            }

            if (source == RB.AssetSource.Resources)
            {
                // Synchronous load
                if (path == null)
                {
                    Debug.LogError("Shader filename is null!");
                    shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                    return(false);
                }

                var shader = Resources.Load <Shader>(path);

                if (shader == null)
                {
                    Debug.LogError("Could not load shader from " + path + ", make sure the resource is placed somehwere in Assets/Resources folder");
                    shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }

                return(FinalizeShader(shader));
            }
            else if (source == RB.AssetSource.WWW)
            {
                // Not a supported source, should never get here
                shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotSupported);
                return(false);
            }
            else if (source == RB.AssetSource.ResourcesAsync)
            {
                // Finally attempt async resource load
                mResourceRequest = Resources.LoadAsync <Shader>(this.path);

                if (mResourceRequest == null)
                {
                    shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NoResources);
                    return(false);
                }

                shaderAsset.progress = 0;
                shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
            }
#if ADDRESSABLES_PACKAGE_AVAILABLE
            else if (source == RB.AssetSource.AddressableAssets)
            {
                // Exceptions on LoadAssetAsync can't actually be caught... this might work in the future so leaving it here
                try
                {
                    mAddressableRequest = Addressables.LoadAssetAsync <Shader>(this.path);
                }
                catch (UnityEngine.AddressableAssets.InvalidKeyException e)
                {
                    RBUtil.Unused(e);
                    shaderAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotFound);
                    return(false);
                }
                catch (Exception e)
                {
                    RBUtil.Unused(e);
                    shaderAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                // Check for an immediate failure
                if (mAddressableRequest.Status == AsyncOperationStatus.Failed)
                {
                    Addressables.Release(mAddressableRequest);
                    shaderAsset.SetErrorStatus(RB.AssetStatus.Failed, RB.Result.Undefined);
                    return(false);
                }

                shaderAsset.SetErrorStatus(RB.AssetStatus.Loading, RB.Result.Pending);
                shaderAsset.progress = 0;

                return(true);
            }
#endif
            else
            {
                shaderAsset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.NotSupported);
                return(false);
            }

            return(true);
        }