Exemplo n.º 1
0
    /// <summary>
    /// Setup a custom font from the sprite sheet.
    /// </summary>
    /// <remarks>The glyphs in your sprite sheet should be organized into a grid, with each cell size being the same. If <paramref name="monospaced"/> is false then RetroBlit will automatically trim any
    /// horizontal empty space on either side of the glyph. If <paramref name="monospaced"/> is true then the empty space is retained.</remarks>
    /// <param name="characterList">List of all characters in this font. Must be in same order as glyphSprites</param>
    /// <param name="glyphSprites">List of packed sprites to use for the glyphs. Must be in same order as characterList</param>
    /// <param name="spriteSheet">The sprite sheet containing the font</param>
    /// <param name="characterSpacing">Spacing between characters</param>
    /// <param name="lineSpacing">Line spacing between lines of text</param>
    /// <param name="monospaced">True if font is monospaced</param>
    /// <returns>Setup status</returns>
    public RB.AssetStatus Setup(List <char> characterList, List <string> glyphSprites, SpriteSheetAsset spriteSheet, int characterSpacing, int lineSpacing, bool monospaced)
    {
        InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);

        progress = 0;

        if (spriteSheet == null)
        {
            Debug.LogError("Invalid sprite sheet");
            return(status);
        }

        if (spriteSheet.status != RB.AssetStatus.Ready)
        {
            Debug.LogError("Sprite sheet is not ready or not loaded");
            return(status);
        }

        if (glyphSprites == null)
        {
            Debug.LogError("Glyph sprites list is null!");
            return(status);
        }

        if (characterList.Count != glyphSprites.Count)
        {
            Debug.LogError("Expected " + characterList.Count + " glyph sprites to cover the given unicode range, was given " + glyphSprites.Count + " glyph sprites");
            return(status);
        }

        var glyphSprites2 = new List <PackedSprite>(glyphSprites.Count);

        for (int i = 0; i < glyphSprites.Count; i++)
        {
            glyphSprites2.Add(RB.PackedSpriteGet(glyphSprites[i], spriteSheet));
        }

        RetroBlitInternal.RBAPI.instance.Font.FontSetup(this, 0, 0, characterList, glyphSprites2, spriteSheet, characterSpacing, lineSpacing, monospaced, true);

        InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);

        progress = 1;

        return(status);
    }
Exemplo n.º 2
0
        /// <summary>
        /// Load a sprite sheet or sprite pack from the given file, or create a blank one of given size, or load from an existing texture
        /// </summary>
        /// <param name="asset">Asset object to load into</param>
        /// <param name="size">Size of new empty spritesheet if no filename is specified</param>
        /// <param name="fileName">Filename</param>
        /// <param name="texture">Existing texture to use</param>
        /// <param name="source">Source type</param>
        /// <param name="sheetType">Sheet type</param>
        /// <returns>True if successful</returns>
        public bool SpriteSheetLoad(SpriteSheetAsset asset, Vector2i size, string fileName, RenderTexture texture, RB.AssetSource source, SpriteSheetAsset.SheetType sheetType)
        {
            if (asset == null)
            {
                return(false);
            }

            asset.progress = 0;

            // Release any existing asset
            SpriteSheetUnload(asset);

            asset.InternalSetErrorStatus(RB.AssetStatus.Invalid, RB.Result.Undefined);

            if (fileName != null)
            {
                fileName.Replace('\\', '/');

                if (fileName.EndsWith(".sp.rb"))
                {
                    Debug.LogError("Do not specify the .sp.rb file extension when loading a sprite pack");
                    asset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                    return(false);
                }
                else if ((sheetType == SpriteSheetAsset.SheetType.SpriteSheet && source != RB.AssetSource.WWW) && (fileName.EndsWith(".png") || fileName.EndsWith(".jpg") || fileName.EndsWith(".jpeg") || fileName.EndsWith(".gif") || fileName.EndsWith(".tif") || fileName.EndsWith(".tga") || fileName.EndsWith(".psd")))
                {
                    // Does not apply to WWW, must specify extension there to form valid http request
                    Debug.LogError("Do not specify the image file extension when loading a sprite. For example, use \"hero\", instead of \"hero.png\"");
                    asset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                    return(false);
                }
            }

            // Async loading implies we are not creating an empty texture, nor initializing from an existing texture
            if (source != RB.AssetSource.Resources && fileName == null)
            {
                asset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
            }
            else
            {
                if (sheetType == SpriteSheetAsset.SheetType.SpritePack)
                {
                    // Abort any existing async load for this asset
                    AbortAsyncSpritePackLoad(asset);

                    var asyncSpritePackResource = new RBSpritePackLoader();
                    asyncSpritePackResource.Load(fileName, asset, source);

                    if (asset.status == RB.AssetStatus.Ready)
                    {
                        return(true);
                    }

                    // Always add to async queue, even if immediately failed. This gives out consistent async method of error checking
                    mASyncSpritePacks.Add(asyncSpritePackResource);

                    return(true);
                }
                else if (sheetType == SpriteSheetAsset.SheetType.SpriteSheet)
                {
                    // Abort any existing async load for this asset
                    AbortAsyncSpriteSheetLoad(asset);

                    var asyncResource = new RBSpriteSheetLoader();
                    asyncResource.Load(fileName, texture, size, asset, source);

                    if (asset.status == RB.AssetStatus.Ready)
                    {
                        return(true);
                    }

                    // Always add to async queue, even if immediately failed. This gives out consistent async method of error checking
                    mASyncSpriteSheets.Add(asyncResource);

                    return(true);
                }
                else
                {
                    asset.InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);
                    return(false);
                }
            }

            return(false);
        }
Exemplo n.º 3
0
    /// <summary>
    /// Setup a custom font from the sprite sheet.
    /// </summary>
    /// <remarks>The glyphs in your sprite sheet should be organized into a grid, with each cell size being the same. If <paramref name="monospaced"/> is false then RetroBlit will automatically trim any
    /// horizontal empty space on either side of the glyph. If <paramref name="monospaced"/> is true then the empty space is retained.</remarks>
    /// <param name="unicodeStart">First unicode character in the font</param>
    /// <param name="unicodeEnd">Last unicode character in the font</param>
    /// <param name="glyphSprites">List of packed sprites to use for the glyphs</param>
    /// <param name="spriteSheet">The sprite sheet containing the font</param>
    /// <param name="characterSpacing">Spacing between characters</param>
    /// <param name="lineSpacing">Line spacing between lines of text</param>
    /// <param name="monospaced">True if font is monospaced</param>
    /// <returns>Setup status</returns>
    public RB.AssetStatus Setup(char unicodeStart, char unicodeEnd, List <PackedSprite> glyphSprites, SpriteSheetAsset spriteSheet, int characterSpacing, int lineSpacing, bool monospaced)
    {
        InternalSetErrorStatus(RB.AssetStatus.Failed, RB.Result.BadParam);

        progress = 0;

        if (unicodeStart < 0 || unicodeEnd < unicodeStart)
        {
            Debug.LogError("Invalid unicode range");
            return(status);
        }

        if (spriteSheet == null)
        {
            Debug.LogError("Invalid sprite sheet");
            return(status);
        }

        if (spriteSheet.status != RB.AssetStatus.Ready)
        {
            Debug.LogError("Sprite sheet is not ready or not loaded");
            return(status);
        }

        if (glyphSprites == null)
        {
            Debug.LogError("Glyph sprites list is null!");
            return(status);
        }

        if ((unicodeEnd - unicodeStart + 1) != glyphSprites.Count)
        {
            Debug.LogError("Expected " + (unicodeEnd - unicodeStart + 1) + " glyph sprites to cover the given unicode range, was given " + glyphSprites.Count + " glyph sprites");
            return(status);
        }

        RetroBlitInternal.RBAPI.instance.Font.FontSetup(this, unicodeStart, unicodeEnd, null, glyphSprites, spriteSheet, characterSpacing, lineSpacing, monospaced, true);

        InternalSetErrorStatus(RB.AssetStatus.Ready, RB.Result.Success);

        progress = 1;

        return(status);
    }
        /// <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);
        }