Beispiel #1
0
        /// <summary>
        /// Creates a texture from bytes laid out in BGRA format, row major.
        /// </summary>
        /// <param name="data">The raw bytes containing the texture in BGRA format, row major.</param>
        /// <param name="width">Width of the texture in pixels.</param>
        /// <param name="height">Height of the texture in pixels.</param>
        /// <returns>The created texture.</returns>
        public static pTexture FromRawBytes(byte[] data, int width, int height)
        {
            pTexture pt = new pTexture(width, height);

            pt.SetData(data);
            return(pt);
        }
Beispiel #2
0
        internal static pTexture LoadFirst(string s, SkinSource source = SkinSource.All, bool dashSeparator = true)
        {
            pTexture sourceTex = Load(s, source);

            pTexture[] texArray     = LoadAll(s, source, dashSeparator);
            pTexture   alternateTex = texArray != null ? texArray[0] : null;

            return(textureFromMostSpecificSkin(sourceTex, alternateTex));
        }
Beispiel #3
0
        internal static pTexture LoadFirstAvailable(string[] names, SkinSource source = SkinSource.All)
        {
            pTexture t = null;

            foreach (string s in names)
            {
                if ((t = Load(s, source)) != null)
                {
                    break;
                }
            }
            return(t);
        }
Beispiel #4
0
 private static pTexture textureFromMostSpecificSkin(pTexture first, pTexture second)
 {
     if (first != null && (
             second == null ||
             first.Source == SkinSource.Beatmap ||
             first.Source == SkinSource.Skin && second.Source != SkinSource.Beatmap ||
             first.Source == SkinSource.Osu && second.Source != SkinSource.Beatmap && second.Source != SkinSource.Skin)
         )
     {
         return(first);
     }
     return(second);
 }
Beispiel #5
0
        /// <summary>
        /// Creates a texture from a bitmap.
        /// </summary>
        /// <param name="bitmap">The bitmap to create the texture from.</param>
        /// <returns>The created texture.</returns>
        public static pTexture FromBitmap(Bitmap bitmap, TextureAtlas atlas = null)
        {
            if (bitmap == null)
            {
                return(null);
            }

            int usableWidth  = Math.Min(OsuGlControl.MaxTextureSize, bitmap.Width);
            int usableHeight = Math.Min(OsuGlControl.MaxTextureSize, bitmap.Height);

            pTexture tex = atlas == null ? new pTexture(usableWidth, usableHeight) : atlas.Add(usableWidth, usableHeight);

            tex.SetData(bitmap);

            return(tex);
        }
Beispiel #6
0
        internal static void ClearBeatmapCache(bool force = false)
        {
            BeatmapCacheHoldReferences = force;

            if (BeatmapSpriteCache.Count == 0)
            {
                return;
            }

            //Avoid inter-thread access problems.
            pTexture[] cache = new pTexture[BeatmapSpriteCache.Count];
            BeatmapSpriteCache.Values.CopyTo(cache, 0);

            foreach (pTexture t in cache)
            {
                if (t == null)
                {
                    continue;
                }

                if (t.Disposable)
                {
                    //textures marked as disposable will be cleaned up themselves, so we don't need to forcefully dispose.
                    //this case is used in TransitionManager to allow extended lifetime on background sprites.
                    continue;
                }

                t.Dispose();
            }

            BeatmapSpriteCache.Clear();

            AnimationCache.Clear();

            BeatmapCacheReferences.Clear();

            BeatmapCacheHoldReferences = false;

            LookupCache.Clear();

            if (force)
            {
                ResetAtlases(BeatmapTextureAtlases);
            }
        }
Beispiel #7
0
        internal static pTexture[] LoadAll(string s, SkinSource source = SkinSource.All, bool dashSeparator = true)
        {
            pTexture[] texArray;
            if (AnimationCache.TryGetValue(s, out texArray) && texArray[0].Source == source)
            {
                return(texArray);
            }

            int    frameSuffixPosition = s.LastIndexOf('.');
            string dash = dashSeparator ? @"-" : string.Empty;

            string   frame0Name = frameSuffixPosition == -1 ? s + dash + 0 : s.Insert(frameSuffixPosition, dash + 0);
            pTexture animated   = Load(frame0Name, source);
            pTexture sprite     = Load(s, source);

            if (animated != null && animated == textureFromMostSpecificSkin(animated, sprite))
            {
                List <pTexture> textures = new List <pTexture>();

                for (int i = 1; animated != null; i++)
                {
                    textures.Add(animated);

                    string frameIName = frameSuffixPosition == -1 ? s + dash + i : s.Insert(frameSuffixPosition, dash + i);
                    animated = Load(frameIName, animated.Source);
                }

                texArray          = textures.ToArray();
                AnimationCache[s] = texArray;
                return(texArray);
            }

            if (sprite != null)
            {
                texArray          = new[] { sprite };
                AnimationCache[s] = texArray;
                return(texArray);
            }

            return(null);
        }
Beispiel #8
0
        internal static void Dereference(string filename)
        {
            if (BeatmapCacheHoldReferences)
            {
                return;
            }

            int referenceCount = 0;

            if (BeatmapCacheReferences.TryGetValue(filename, out referenceCount))
            {
                if (referenceCount > 1)
                { //Still other references being held.
                    BeatmapCacheReferences[filename]--;
                    return;
                }
            }
            else
            {
                return;
            }
            //Doesn't exist in beatmapCache (is this right?)

            BeatmapCacheReferences.Remove(filename);

            if (!BeatmapSpriteCache.ContainsKey(filename))
            {
                return;
            }

            pTexture tex = BeatmapSpriteCache[filename];

            if (tex != null)
            {
                tex.Dispose();
                BeatmapSpriteCache.Remove(filename);
                LookupCache.Clear();
            }
        }
Beispiel #9
0
        internal static void ReloadCache(Dictionary <string, pTexture> cache, bool force = false)
        {
            Dictionary <string, pTexture> oldCache = new Dictionary <string, pTexture>(cache);

            cache.Clear();

            foreach (KeyValuePair <string, pTexture> s in oldCache)
            {
                if (s.Value == null)
                {
                    cache[s.Key] = null;
                }
                else
                {
                    if (s.Value.TextureGl != null)
                    {
                        s.Value.TextureGl.Dispose();
                    }

                    pTexture newlyLoaded = Load(s.Key, s.Value.Source, s.Value.ContainingAtlas);

                    if (newlyLoaded != null)
                    {
                        GC.SuppressFinalize(newlyLoaded);
                        s.Value.TextureGl  = newlyLoaded.TextureGl;
                        s.Value.DpiScale   = newlyLoaded.DpiScale;
                        s.Value.IsDisposed = false;
                    }
                    else
                    {
                        s.Value.TextureGl = null;
                    }

                    cache[s.Key] = s.Value;
                    LookupCache[s.Value.Source][s.Key] = s.Value;
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Creates a texture from a file containing a bitmap.
        /// </summary>
        /// <param name="filename">The file containing the texture data.</param>
        /// <returns>The created texture.</returns>
        public static pTexture FromFile(string filename, TextureAtlas atlas = null)
        {
            if (!File.Exists(filename))
            {
                return(null);
            }

            try
            {
                using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    pTexture t = FromStream(stream, atlas);
                    if (t != null)
                    {
                        t.Filename = filename;
                    }
                    return(t);
                }
            }
            catch
            {
                return(null);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Read a pTexture from the ResourceStore (ouenresources project).
        /// </summary>
        public static pTexture FromResourceStore(string filename, TextureAtlas atlas = null)
        {
            pTexture tex = null;

#if DEBUG
            tex = fromDebugLocations(filename);
            if (tex != null)
            {
                return(tex);
            }
#endif

            //load using newer resources where available.
            if (GameBase.NewGraphicsAvailable)
            {
                tex = FromNewResourceStore(filename, atlas);
                if (tex != null)
                {
                    tex.Filename = filename;
                    return(tex);
                }
            }

            byte[] bytes = ResourcesStore.ResourceManager.GetObject(filename) as byte[];

            if (bytes == null)
            {
                return(null);
            }

            using (Stream stream = new MemoryStream(bytes))
            {
                using (HaxBinaryReader br = new HaxBinaryReader(stream))
                {
                    //XNA pipeline header crap.  F**k it all.
                    br.ReadBytes(10);
                    int typeCount = br.Read7BitEncodedInt();
                    for (int i = 0; i < typeCount; i++)
                    {
                        br.ReadString();
                        br.ReadInt32();
                    }
                    br.Read7BitEncodedInt();
                    br.Read7BitEncodedInt();
                    //And that's the header dealt with.

                    br.ReadInt32();

                    int width  = br.ReadInt32();
                    int height = br.ReadInt32();

                    tex          = atlas == null ? new pTexture(width, height) : atlas.Add(width, height);
                    tex.Filename = filename;

                    int numberLevels = br.ReadInt32();

                    for (int i = 0; i < numberLevels; i++)
                    {
                        int    count = br.ReadInt32();
                        byte[] data  = br.ReadBytes(count);

                        bgraToRgba(data, data.Length);
                        tex.SetData(data, i, 0);
                    }
                }
            }

            return(tex);
        }
Beispiel #12
0
        static pTexture fromDebugLocations(string filename)
        {
            if (fswUi == null)
            {
                if (fswFailed)
                {
                    return(null);
                }

                try
                {
                    fswUi = new FileSystemWatcher(Path.Combine("..", "..", "..", "..", "osu!ui", "Resources"))
                    {
                        EnableRaisingEvents = true
                    };
                    fswGameplay = new FileSystemWatcher(Path.Combine("..", "..", "..", "..", "osu!gameplay", "Resources"))
                    {
                        EnableRaisingEvents = true
                    };
                }
                catch
                {
                    fswFailed = true;
                }
            }

            pTexture tex = null;

            bool   x2     = GameBase.UseHighResolutionSprites;
            string suffix = GameBase.UseHighResolutionSprites ? @"@2x.png" : @".png";

            string directFile = Path.Combine("..", "..", "..", "..", "osu!ui", "Resources", filename + suffix);

            tex = pTexture.FromFile(directFile);
            if (tex != null)
            {
                fswUi.Renamed += delegate(object sender, RenamedEventArgs e)
                {
                    if (Path.GetFileName(directFile) != e.Name)
                    {
                        return;
                    }
                    while (true)
                    {
                        try
                        {
                            using (Stream stream = new FileStream(directFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                                using (Bitmap b = (Bitmap)Image.FromStream(stream, false, false))
                                {
                                    tex.SetData(b);
                                    tex.UploadNextFrame();
                                }

                            break;
                        }
                        catch { }
                    }
                };

                tex.Filename = directFile;
                tex.DpiScale = x2 ? 2 : 1;
                return(tex);
            }

            directFile = Path.Combine("..", "..", "..", "..", "osu!gameplay", "Resources", filename + suffix);
            tex        = pTexture.FromFile(directFile);
            if (tex != null)
            {
                fswGameplay.Renamed += delegate(object sender, RenamedEventArgs e)
                {
                    if (Path.GetFileName(directFile) != e.Name)
                    {
                        return;
                    }
                    while (true)
                    {
                        try
                        {
                            using (Stream stream = new FileStream(directFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                                using (Bitmap b = (Bitmap)Image.FromStream(stream, false, false))
                                {
                                    tex.SetData(b);
                                    tex.UploadNextFrame();
                                }

                            break;
                        }
                        catch { }
                    }
                };

                tex.Filename = directFile;
                tex.DpiScale = x2 ? 2 : 1;
                return(tex);
            }

            return(tex);
        }
Beispiel #13
0
        public static pTexture FromNewResourceStore(string filename, TextureAtlas atlas = null)
        {
            bool highResolution = GameBase.UseHighResolutionSprites;

            if (highResolution)
            {
                filename += @"@2x";
            }

            using (Bitmap b = osu_gameplay.ResourcesStore.ResourceManager.GetObject(filename) as Bitmap)
                if (b != null)
                {
                    pTexture tex = FromBitmap(b, atlas);
                    if (highResolution)
                    {
                        tex.DpiScale = 2;
                    }
                    return(tex);
                }

            //dll modification checks
            using (Bitmap b = osu_ui.ResourcesStore.ResourceManager.GetObject(filename) as Bitmap)
                if (b != null)
                {
                    bool valid = true;

                    switch (filename)
                    {
                        //case @"menu-osu":
                        //    valid &= b.GetPixel(320 / 2, 320 / 2) == System.Drawing.Color.FromArgb(255, 255, 190, 219);
                        //    valid &= b.GetPixel(220 / 2, 220 / 2) == System.Drawing.Color.FromArgb(255, 255, 199, 227);
                        //    valid &= b.GetPixel(420 / 2, 420 / 2) == System.Drawing.Color.FromArgb(255, 255, 245, 249);
                        //    break;
                        //case @"menu-osu@2x":
                        //    valid &= b.GetPixel(320, 320) == System.Drawing.Color.FromArgb(255, 255, 190, 220);
                        //    valid &= b.GetPixel(220, 220) == System.Drawing.Color.FromArgb(255, 255, 199, 227);
                        //    valid &= b.GetPixel(420, 420) == System.Drawing.Color.FromArgb(255, 255, 245, 249);
                        //    break;
                        //case @"menu-background":
                        //    valid &= b.GetPixel(0, 0) == System.Drawing.Color.FromArgb(243, 0, 206, 255);
                        //    valid &= b.GetPixel(400 / 2, 400 / 2) == System.Drawing.Color.FromArgb(255, 0, 165, 255);
                        //    valid &= b.GetPixel(1552 / 2, 1024 / 2) == System.Drawing.Color.FromArgb(255, 0, 144, 255);
                        //    break;
                        //case @"menu-background@2x":
                        //    valid &= b.GetPixel(0, 0) == System.Drawing.Color.FromArgb(228, 1, 206, 255);
                        //    valid &= b.GetPixel(400, 400) == System.Drawing.Color.FromArgb(255, 0, 165, 255);
                        //    valid &= b.GetPixel(1552, 1024) == System.Drawing.Color.FromArgb(255, 0, 144, 255);
                        //    break;
                    }

                    if (!valid)
                    {
#if DEBUG
                        throw new Exception(@"DLL modification checks need updating");
#else
                        OsuMain.ExitImmediately();
#endif
                    }

                    pTexture tex = FromBitmap(b, atlas);
                    if (highResolution)
                    {
                        tex.DpiScale = 2;
                    }
                    return(tex);
                }
            return(null);
        }
Beispiel #14
0
        internal static pTexture Load(string name, SkinSource source = SkinSource.All, TextureAtlas atlas = null)
        {
            if (name == null)
            {
                return(null);
            }

            if (SkinManager.IgnoreBeatmapSkin && source != SkinSource.Beatmap)
            {
                source &= ~SkinSource.Beatmap;
            }

            if (source == SkinSource.All)
            {
                switch (GameBase.Mode)
                {
                case OsuModes.Play:
                case OsuModes.Edit:
                    break;

                default:
                    //As a default, don't load from the beatmap unless we are in play or edit mode.
                    source &= ~SkinSource.Beatmap;
                    break;
                }
            }

            pTexture tex = null;

            Dictionary <string, pTexture> dic = null;

            if (!LookupCache.TryGetValue(source, out dic))
            {
                dic = LookupCache[source] = new Dictionary <string, pTexture>();
            }

            if (dic.TryGetValue(name, out tex))
            {
                return(tex);
            }

            try
            {
                //Check for beatmap-specific sprite availability
                Beatmap current = null;
                if ((source & SkinSource.Beatmap) > 0 && (current = BeatmapManager.Current) != null)
                {
                    if (BeatmapSpriteCache.TryGetValue(name, out tex))
                    {
                        //Cached sprite is available.
                        //Note that we must check null *inside* this if block because a cached null means this source has no available file.
                        //If we find a null, we don't want to enter the else block and check for a file every time, so we quietly ignore this source here.
                        if (tex != null)
                        {
                            return(tex);
                        }
                    }
                    else
                    {
                        string filename = name.IndexOf('.') < 0 ? name + @".png" : name;
                        using (Stream stream = current.GetFileStream(filename))
                        {
                            if (stream != null)
                            {
                                tex = pTexture.FromStream(stream, atlas);
                                if (tex != null)
                                {
                                    tex.Filename  = filename;
                                    tex.AssetName = name;
                                    tex.Source    = SkinSource.Beatmap;
                                    tex.UploadNextFrame();
                                }

                                BeatmapSpriteCache[name] = tex;

                                if (atlas != null)
                                {
                                    BeatmapTextureAtlases.Add(atlas);
                                }

                                return(tex);
                            }
                        }

                        BeatmapSpriteCache[name] = null;
                    }
                }

                if ((source & SkinSource.Skin) > 0 && !SkinManager.IsDefault)
                {
                    if (SkinSpriteCache.TryGetValue(name, out tex))
                    {
                        //Cached sprite is available.
                        //Note that we must check null *inside* this if block because a cached null means this source has no available file.
                        //If we find a null, we don't want to enter the else block and check for a file every time, so we quietly ignore this source here.
                        if (tex != null)
                        {
                            return(tex);
                        }
                    }
                    else
                    {
                        string filename = Path.Combine(SkinManager.Current.FullPath, name.IndexOf('.') < 0 ? name + @".png" : name);

                        string filename2x = filename.Insert(filename.LastIndexOf('.'), @"@2x");
                        if (GameBase.UseHighResolutionSprites && File.Exists(filename2x))
                        {
                            tex = pTexture.FromFile(filename2x, atlas);
                            SkinSpriteCache[name] = tex;

                            if (atlas != null)
                            {
                                SkinTextureAtlases.Add(atlas);
                            }

                            if (tex != null)
                            {
                                tex.DpiScale  = 2;
                                tex.Source    = SkinSource.Skin;
                                tex.AssetName = name;
                                tex.UploadNextFrame();
                            }
                            return(tex);
                        }

                        if (File.Exists(filename))
                        {
                            tex = pTexture.FromFile(filename, atlas);
                            SkinSpriteCache[name] = tex;

                            if (atlas != null)
                            {
                                SkinTextureAtlases.Add(atlas);
                            }

                            if (tex != null)
                            {
                                tex.Source    = SkinSource.Skin;
                                tex.AssetName = name;
                                tex.UploadNextFrame();
                            }
                            return(tex);
                        }

                        SkinSpriteCache[name] = null;
                    }
                }

                if ((source & SkinSource.Osu) == 0)
                {
                    return(null);
                }

                try
                {
                    if (DefaultSpriteCache.TryGetValue(name, out tex))
                    {
                        return(tex);
                    }

#if LOAD_LOCAL
                    if ((tex = Load(name, SkinSource.Skin)) != null)
                    {
                        return(tex);
                    }
#endif

                    name = GeneralHelper.PathSanitise(name);
                    tex  = name.IndexOf(Path.DirectorySeparatorChar) > 0 ? pTexture.FromFile(name, atlas) : pTexture.FromResourceStore(GeneralHelper.StripExtension(name), atlas);

                    DefaultSpriteCache[name] = tex;

                    if (atlas != null)
                    {
                        DefaultTextureAtlases.Add(atlas);
                    }

                    if (tex != null)
                    {
                        tex.Source    = SkinSource.Osu;
                        tex.AssetName = name;
                        tex.UploadNextFrame();
                    }
                    return(tex);
                }
                catch
                {
                    return(null);
                }
            }
            finally
            {
                dic[name] = tex;
            }
        }