Пример #1
0
        public void MultipleTextures_CorrectIndices()
        {
            var atlas = new TextureAtlas();

            var texture0 = atlas.AddTexture();
            var texture1 = atlas.AddTexture();
            var texture2 = atlas.AddTexture();

            Assert.AreEqual(0, texture0.Index);
            Assert.AreEqual(1, texture1.Index);
            Assert.AreEqual(2, texture2.Index);

            Assert.AreEqual(texture0, atlas.GetTexture(0));
            Assert.AreEqual(texture1, atlas.GetTexture(1));
            Assert.AreEqual(texture2, atlas.GetTexture(2));
        }
Пример #2
0
        public void AddTexture()
        {
            var atlas   = new TextureAtlas();
            var texture = atlas.AddTexture();

            Assert.IsNotNull(texture);
            Assert.AreEqual(atlas, texture.Atlas);
            Assert.AreEqual(0, texture.Index);
            Assert.AreEqual(texture, atlas.GetTexture(0));
        }
Пример #3
0
        public Texture(Resource TextureResource)
        {
            if (TextureResource == null)
            {
                Logger.Log(new LogMessage(LogSeverity.Error, $"Cannot load texture resource is null, please use Texture.Empty instead"));
                return;
            }

            // Store it so that we can refer to it later
            Resource = TextureResource;

            Logger.Log(new LogMessage(LogSeverity.Debug, $"Loading texture {TextureResource.Name}"));
            if (TextureResource.Path == null && TextureResource.Stream == null)
            {
                Logger.Log(new LogMessage(LogSeverity.Error, $"Cannot load texture resource {TextureResource.Name}, both the underlying stream and file path are null"));
                return;
            }

            if (!File.Exists(TextureResource.Path))
            {
                var _tmp = Path.GetTempFileName();

                using var _writer = File.Create(_tmp);
                TextureResource.Stream.BaseStream.CopyTo(_writer);

                TextureImage = Image.Load <Rgba32>(_tmp);

                File.Delete(_tmp);
            }
            else
            {
                TextureImage = Image.Load <Rgba32>(Resource.Path);
            }

            Logger.Log(new LogMessage(LogSeverity.Debug, $"Created new texture: {TextureImage.Width * TextureImage.Height} pixels, dimensions {TextureImage.Width}*{TextureImage.Height}"));

            id = counter++;
            TextureAtlas.AddTexture(this);
        }
Пример #4
0
        IEnumerator ConnectAsynchronously()
        {
            string serverUrl = FixURL(ServerField.text);

            GameSession.Login     = LoginField.text;
            GameSession.ServerUrl = serverUrl;
            TextureAtlas.Init();

            LoadingScreen.SetActive(true);

            // Download and parse main json
            ResourcesInfo resourcesInfo;

            using (var request = UnityWebRequest.Get("http://" + serverUrl + "/main.json")) {
                request.SendWebRequest();
                while (!request.isDone)
                {
                    Slider.value = request.downloadProgress;
                    yield return(null);
                }
                if (request.isHttpError || request.isNetworkError)
                {
                    LoadingScreen.SetActive(false);
                    yield break;
                }
                resourcesInfo = JsonUtility.FromJson <ResourcesInfo>('{' + request.downloadHandler.text + '}');
                resourcesInfo.resourcesUrl = FixURL(resourcesInfo.resourcesUrl);
            }

            // Download and parse remapper json
            RemapperInfo remapperInfo;

            using (var request = resourcesInfo.DownloadText(resourcesInfo.remapper)) {
                request.SendWebRequest();
                while (!request.isDone)
                {
                    Slider.value = request.downloadProgress;
                    yield return(null);
                }
                if (request.isHttpError || request.isNetworkError)
                {
                    LoadingScreen.SetActive(false);
                    yield break;
                }
                remapperInfo = JsonUtility.FromJson <RemapperInfo>('{' + request.downloadHandler.text + '}');
                GameSession.SetRemapper(remapperInfo.GetFlattenBlocks());
            }

            // Download and apply foliage colormap
            using (var request = resourcesInfo.DownloadTexture(resourcesInfo.foliageColormap)) {
                request.SendWebRequest();
                while (!request.isDone)
                {
                    Slider.value = request.downloadProgress;
                    yield return(null);
                }
                if (request.isHttpError || request.isNetworkError)
                {
                    LoadingScreen.SetActive(false);
                    yield break;
                }
                GameSession.FoliageColormap.Load(DownloadHandlerTexture.GetContent(request));
            }

            // Download and apply grass colormap
            using (var request = resourcesInfo.DownloadTexture(resourcesInfo.grassColormap)) {
                request.SendWebRequest();
                while (!request.isDone)
                {
                    Slider.value = request.downloadProgress;
                    yield return(null);
                }
                if (request.isHttpError || request.isNetworkError)
                {
                    LoadingScreen.SetActive(false);
                    yield break;
                }
                GameSession.GrassColormap.Load(DownloadHandlerTexture.GetContent(request));
            }

            // Download and parse blocks json
            BlocksInfo blocksInfo;

            using (var request = resourcesInfo.DownloadText(resourcesInfo.blocks)) {
                request.SendWebRequest();
                while (!request.isDone)
                {
                    Slider.value = request.downloadProgress;
                    yield return(null);
                }
                if (request.isHttpError || request.isNetworkError)
                {
                    LoadingScreen.SetActive(false);
                    yield break;
                }
                blocksInfo = JsonUtility.FromJson <BlocksInfo>('{' + request.downloadHandler.text + '}');
            }

            // Load all blocks
            GameSession.Palette = new Block[blocksInfo.list.Length + 1];
            for (int i = 1; i < blocksInfo.list.Length + 1; i++)
            {
                TempBlock block = blocksInfo.list[i - 1];
                Vector3[] faces = new Vector3[block.textures.Length];
                for (int j = 0; j < faces.Length; j++)
                {
                    string textureName = block.textures[j];
                    using (var request = resourcesInfo.DownloadTexture(textureName)) {
                        request.SendWebRequest();
                        while (!request.isDone)
                        {
                            Slider.value = request.downloadProgress;
                            yield return(null);
                        }
                        if (request.isHttpError || request.isNetworkError)
                        {
                            LoadingScreen.SetActive(false);
                            yield break;
                        }
                        faces[j] = TextureAtlas.AddTexture(textureName, DownloadHandlerTexture.GetContent(request), null);
                    }
                }

                RenderType renderType = block.renderType == null
                                        ? RenderType.Block
                                        : (RenderType)Enum.Parse(typeof(RenderType), block.renderType);

                ShaderType shaderType = block.shaderType == null
                                        ? ShaderType.Block
                                        : (ShaderType)Enum.Parse(typeof(ShaderType), block.shaderType);

                BiomedType biomed = block.biomed == null
                                        ? BiomedType.None
                                        : (BiomedType)Enum.Parse(typeof(BiomedType), block.biomed);

                ColliderType colliderType = block.colliderType == null
                                        ? ColliderType.Block
                                        : (ColliderType)Enum.Parse(typeof(ColliderType), block.colliderType);

                Vector3 colliderMin = new Vector3(block.colliderMinX,
                                                  block.colliderMinY, block.colliderMinZ);

                Vector3 colliderMax = new Vector3(block.colliderMaxX,
                                                  block.colliderMaxY, block.colliderMaxZ);

                Block grassOverlay = null;
                if (block.grassOverlay != null)
                {
                    using (var request = resourcesInfo.DownloadTexture(block.grassOverlay)) {
                        request.SendWebRequest();
                        while (!request.isDone)
                        {
                            Slider.value = request.downloadProgress;
                            yield return(null);
                        }
                        if (request.isHttpError || request.isNetworkError)
                        {
                            LoadingScreen.SetActive(false);
                            yield break;
                        }
                        grassOverlay = new Block("", new Vector3[] { TextureAtlas.AddTexture(
                                                                         block.grassOverlay, DownloadHandlerTexture.GetContent(request), null) }, ColliderType.None,
                                                 colliderMin, colliderMax);
                    }
                }

                GameSession.Palette[i] = new Block(block.name, faces, colliderType,
                                                   colliderMin, colliderMax, renderType, shaderType, biomed, grassOverlay,
                                                   block.renderParam);
            }

            AsyncOperation operation = SceneManager.LoadSceneAsync("GameScene");

            while (!operation.isDone)
            {
                float progress = Mathf.Clamp01(operation.progress / 0.9f);

                Slider.value = progress;

                yield return(null);
            }
        }
Пример #5
0
        /// <summary>
        /// Generates the texture atlasses
        /// </summary>
        public void GenerateTextureAtlasses()
        {
            uint   id       = 1000;
            int    cnt      = 1;
            string baseName = "Textures/TA_" + ID + "_";

            mTextureAtlasses.Clear();
            TextureAtlas atlas = null;

            // Get a sorted list of views based on # of used textures
            List <GUIView> sortedViews = new List <GUIView>(Views);

            sortedViews.Sort((a, b) => (b.TextureIDs.Count - a.TextureIDs.Count));

            List <int> allTextureIDs = new List <int>();

            foreach (GUIView view in sortedViews)
            {
                allTextureIDs.AddRange(view.TextureIDs);
            }

            foreach (TextureInfo info in Textures)
            {
                allTextureIDs.Add(info.ID);
            }

            allTextureIDs = new List <int>(allTextureIDs.Distinct());

            foreach (int texId in allTextureIDs)
            {
                TextureInfo info = this.GetTextureInfo(texId);
                if (info == null)
                {
                    continue;
                }

                bool bExists = false;

                // This texture has already been added before.
                foreach (TextureAtlas tmpAtlas in mTextureAtlasses)
                {
                    if (tmpAtlas.FindNode(info) != null)
                    {
                        bExists = false;
                    }
                }

                if (bExists)
                {
                    continue;
                }

                if (info.NoAtlas)
                {
                    continue;
                }

                bool clear   = (info.AtlasBorderType == TextureInfo.AtlasBorder.Clear);
                int  padding = (info.AtlasPadding < 0) ? mAtlasPadding : info.AtlasPadding;

                Bitmap bitmap = Utils.ExpandImageBorder(Image.FromFile(GUIProject.CurrentProject.ProjectDirectory + "/" + info.Filename), padding, clear);
                if (bitmap == null)
                {
                    continue;
                }

                if (atlas == null || !atlas.AddTexture(bitmap, info))
                {
                    uint finalID = (((uint)this.ID) << 24) | ((uint)2 << 16) | (((uint)id++) & 0x0000FFFF);

                    atlas = new TextureAtlas(finalID, 2048, 2048, baseName + cnt + ".png");
                    if (atlas.AddTexture(bitmap, info))
                    {
                        mTextureAtlasses.Add(atlas);
                        cnt++;
                    }
                    else
                    {
                        atlas = null;
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Reloads the font
        /// </summary>
        public void ReloadFont()
        {
            if (mProject == null)
            {
                return;
            }

            int borderWidth = 2;

            string fullPath = mProject.ProjectDirectory + "/" + mFontFile;

            if (System.IO.File.Exists(fullPath))
            {
                // Ensure that the character list ALWAYS contains at least the ? character.
                if (!Characters.Contains('?'))
                {
                    Characters.Add('?');
                }

                // Load the image glyph textures
                foreach (FontBuilder.ImageGlyph imageGlyph in Images)
                {
                    imageGlyph.Load(mProject.ProjectDirectory);
                }

                if (mFontData != null)
                {
                    mFontData.Dispose();
                }

                mFontData = new FontBuilder.FontData(Characters, Images);
                FontBuilder.Glyph[] glyphs = mFontData.GetGlyphs(fullPath, mFontSize);

                // Clear out our existing textures and texture atlasses
                foreach (TextureAtlas atlas in mTextureAtlasses)
                {
                    DisposeAtlasNode(atlas.mRoot);
                }
                mTextureAtlasses.Clear();

                mTextures.Clear();
                mCharInfoList.Clear();
                mMaxTop = -99999;

                Image  texture       = null;
                Bitmap textureBitmap = null;
                if (File.Exists(mProject.ProjectDirectory + "/" + mTextureFile))
                {
                    texture       = Image.FromFile(mProject.ProjectDirectory + "/" + mTextureFile);
                    textureBitmap = new Bitmap(texture);
                }

                TextureAtlas curAtlas = null;
                foreach (FontBuilder.Glyph glyph in glyphs)
                {
                    if (glyph == null)
                    {
                        continue;
                    }

                    if (mMaxTop < glyph.mTop)
                    {
                        mMaxTop = glyph.mTop;
                    }

                    Bitmap finalBitmap = null;
                    if (glyph.mBitmap != null)
                    {
                        finalBitmap = (borderWidth == 0) ? new Bitmap(glyph.mBitmap) : Utils.ExpandImageBorder(glyph.mBitmap, borderWidth, true);
                        if (finalBitmap == null)
                        {
                            continue;
                        }

                        Bitmap outlinedBitmap = null;
                        Bitmap texturedBitmap = null;

                        if (OutlineAmount > 0.0f && OutlineColor.A != 0)
                        {
                            float s = Math.Min(1.0f, Math.Max(OutlineSharpness, 0.0f));
                            outlinedBitmap = BlurBitmap(finalBitmap, OutlineAmount, OutlineSharpness, OutlineColor);
                            finalBitmap.Dispose();
                            finalBitmap = outlinedBitmap;
                        }

                        BitmapData texturedBitmapData = null;
                        if (textureBitmap != null && glyph.mImageGlyph == 0)
                        {
                            texturedBitmap     = ApplyTexture(textureBitmap, glyph.mBitmap, mTextureBaseline, glyph.mTop);
                            texturedBitmapData = texturedBitmap.LockBits(new Rectangle(0, 0,
                                                                                       texturedBitmap.Width,
                                                                                       texturedBitmap.Height),
                                                                         ImageLockMode.ReadOnly,
                                                                         texturedBitmap.PixelFormat);
                        }

                        // Now we need to use the original bitmap (from the glyph) and reapply it to the new
                        // bitmap (that may or may not have been blurred) with the fill color
                        BitmapData sourceBitmapData = glyph.mBitmap.LockBits(new Rectangle(0, 0, glyph.mBitmap.Width, glyph.mBitmap.Height),
                                                                             ImageLockMode.ReadOnly,
                                                                             glyph.mBitmap.PixelFormat);

                        BitmapData targetBitmapData = finalBitmap.LockBits(new Rectangle((finalBitmap.Width - glyph.mBitmap.Width) / 2,
                                                                                         (finalBitmap.Height - glyph.mBitmap.Height) / 2,
                                                                                         glyph.mBitmap.Width,
                                                                                         glyph.mBitmap.Height),
                                                                           ImageLockMode.WriteOnly,
                                                                           finalBitmap.PixelFormat);

                        try
                        {
                            for (int x = 0; x < sourceBitmapData.Width; x++)
                            {
                                for (int y = 0; y < sourceBitmapData.Height; y++)
                                {
                                    IntPtr sourcePixel  = (IntPtr)((int)sourceBitmapData.Scan0 + sourceBitmapData.Stride * y + x * 4);
                                    IntPtr targetPixel  = (IntPtr)((int)targetBitmapData.Scan0 + targetBitmapData.Stride * y + x * 4);
                                    IntPtr texturePixel = IntPtr.Zero;

                                    if (texturedBitmapData != null)
                                    {
                                        texturePixel = (IntPtr)((int)texturedBitmapData.Scan0 + texturedBitmapData.Stride * y + x * 4);
                                    }

                                    Color srcColor = Color.FromArgb(Marshal.ReadInt32(sourcePixel));
                                    Color tgtColor = Color.FromArgb(Marshal.ReadInt32(targetPixel));
                                    Color texColor = (texturePixel != IntPtr.Zero) ? Color.FromArgb(Marshal.ReadInt32(texturePixel)) : Color.White;

                                    float alpha = srcColor.A / 255.0f;
                                    if (alpha == 0.0f)
                                    {
                                        continue;
                                    }

                                    byte r = (byte)(tgtColor.R * (1.0f - alpha) + FillColor.R * (srcColor.R / 255.0f) * (texColor.R / 255.0f) * alpha);
                                    byte g = (byte)(tgtColor.G * (1.0f - alpha) + FillColor.G * (srcColor.G / 255.0f) * (texColor.G / 255.0f) * alpha);
                                    byte b = (byte)(tgtColor.B * (1.0f - alpha) + FillColor.B * (srcColor.B / 255.0f) * (texColor.B / 255.0f) * alpha);
                                    byte a = (byte)(tgtColor.A * (1.0f - alpha) + FillColor.A * (srcColor.A / 255.0f) * (texColor.A / 255.0f) * alpha);

                                    Color finalColor = Color.FromArgb(a, r, g, b);

                                    Marshal.WriteInt32(targetPixel, finalColor.ToArgb());
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            System.Console.WriteLine("Exception : " + ex);
                        }

                        glyph.mBitmap.UnlockBits(sourceBitmapData);
                        finalBitmap.UnlockBits(targetBitmapData);

                        if (texturedBitmapData != null)
                        {
                            texturedBitmap.UnlockBits(texturedBitmapData);
                        }
                    }
                    else
                    {
                        finalBitmap = new Bitmap(4, 4);
                    }

                    if (curAtlas == null || !curAtlas.AddTexture(finalBitmap, glyph))
                    {
                        curAtlas = new TextureAtlas(0, AtlasSize.Width, AtlasSize.Height, "tmp");
                        mTextureAtlasses.Add(curAtlas);

                        curAtlas.AddTexture(finalBitmap, glyph);
                    }
                }

                if (textureBitmap != null)
                {
                    textureBitmap.Dispose();
                }

                if (texture != null)
                {
                    texture.Dispose();
                }

                // Unload the image glyph textures
                foreach (FontBuilder.ImageGlyph imageGlyph in Images)
                {
                    imageGlyph.Unload();
                }

                // Then iterate and add to the texture atlas(ses).
                if (Otter.Interface.Graphics.Instance != null)
                {
                    foreach (int textureID in mTextures)
                    {
                        Otter.Interface.Graphics.Instance.UnloadTexture(textureID);
                    }

                    foreach (TextureAtlas atlas in mTextureAtlasses)
                    {
                        Bitmap bitmap = atlas.GetBitmap();

                        // BitmapData
                        BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);

                        // Get the address of the first line.
                        IntPtr ptr = bitmapData.Scan0;

                        // Declare an array to hold the bytes of the bitmap.
                        int    size  = Math.Abs(bitmapData.Stride) * bitmap.Height;
                        byte[] bytes = new byte[size];

                        System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, size);

                        int textureID = Otter.Interface.Graphics.Instance.LoadTexture(bytes, bitmap.Width, bitmap.Height, 32);

                        bitmap.UnlockBits(bitmapData);

                        mTextures.Add(textureID);

                        bitmap.Dispose();

                        // SLOW
                        foreach (FontBuilder.Glyph glyph in glyphs)
                        {
                            if (glyph == null)
                            {
                                continue;
                            }

                            AtlasNode node = atlas.FindNode(glyph);

                            if (node != null)
                            {
                                NewCharInfo info = new NewCharInfo();

                                int diffW = node.mRectangle.Width - borderWidth * 2 - glyph.mW;
                                int diffH = node.mRectangle.Height - borderWidth * 2 - glyph.mH;

                                info.mCharCode   = glyph.mCharCode;
                                info.mImageGlyph = glyph.mImageGlyph;
                                info.mX          = node.mRectangle.X + borderWidth;
                                info.mY          = node.mRectangle.Y + borderWidth;
                                info.mW          = glyph.mW + diffW;
                                info.mH          = glyph.mH + diffH;

                                info.mTop         = glyph.mTop + diffH / 2;
                                info.mAdvance     = glyph.mAdvance;
                                info.mLeftBearing = glyph.mLeftBearing - diffW / 2;

                                info.mAtlasIndex = mTextureAtlasses.IndexOf(atlas);

                                mCharInfoList.Add(info);
                            }
                        }
                    }

                    MemoryStream stream = new MemoryStream();

                    Platform platform = new Platform();
                    platform.Endianness  = Endian.Little;
                    platform.ColorFormat = ColorFormat.ARGB;

                    PlatformBinaryWriter bw = new PlatformBinaryWriter(stream, platform);
                    this.Export(bw);

                    mFontID = Otter.Interface.Graphics.Instance.LoadFont(this.Name, stream.GetBuffer(), mTextures);

                    bw.Close();
                    stream.Close();
                }
            }
        }
Пример #7
0
 static Texture()
 {
     blank    = new(ResourceManager.GetFile("white texture"));
     blank.id = counter++;
     TextureAtlas.AddTexture(blank);
 }