Esempio n. 1
0
        internal void HandleCache(TinyToken cachedFontRoot)
        {
            if (!matches(cachedFontRoot))
            {
                return;
            }

            foreach (var cacheEntry in cachedFontRoot.Values <TinyObject>("Cache"))
            {
                var path = cacheEntry.Value <string>("Path");
                var hash = cacheEntry.Value <string>("Hash");

                var fullPath = Path.Combine(mapsetDirectory, path);
                if (!File.Exists(fullPath) || HashHelper.GetFileMd5(fullPath) != hash)
                {
                    continue;
                }

                textureCache.Add(cacheEntry.Value <string>("Text"), new FontTexture(
                                     path,
                                     cacheEntry.Value <float>("OffsetX"),
                                     cacheEntry.Value <float>("OffsetY"),
                                     cacheEntry.Value <int>("BaseWidth"),
                                     cacheEntry.Value <int>("BaseHeight"),
                                     cacheEntry.Value <int>("Width"),
                                     cacheEntry.Value <int>("Height")
                                     ));
            }
        }
Esempio n. 2
0
        private void writeArray(TextWriter writer, TinyArray array, TinyToken parent, int indentLevel)
        {
            var parentIsArray = parent != null && parent.Type == TinyTokenType.Array;

            var first = true;

            foreach (var token in array)
            {
                if (!first || !parentIsArray)
                {
                    writeIndent(writer, indentLevel);
                }

                if (token.IsEmpty)
                {
                    writer.WriteLine("- ");
                }
                else if (token.IsInline)
                {
                    writer.Write("- ");
                    write(writer, token, array, 0);
                }
                else
                {
                    writer.Write("- ");
                    write(writer, token, array, indentLevel + 1);
                }
                first = false;
            }
        }
        public FontGenerator LoadFont(string directory, FontDescription description, params FontEffect[] effects)
        {
            var fontDirectory = Path.GetFullPath(Path.Combine(context.MapsetPath, directory));

            if (fontDirectories.Contains(fontDirectory))
            {
                throw new InvalidOperationException($"This effect already generated a font inside \"{fontDirectory}\"");
            }
            fontDirectories.Add(fontDirectory);

            var fontGenerator = new FontGenerator(directory, description, effects, context.ProjectPath, context.MapsetPath);

            fontGenerators.Add(fontGenerator);

            var cachePath = fontCacheDirectory;

            if (Directory.Exists(cachePath))
            {
                var path = Path.Combine(cachePath, HashHelper.GetMd5(fontGenerator.Directory) + ".yaml");
                if (File.Exists(path))
                {
                    var cachedFontRoot = Util.Misc.WithRetries(() => TinyToken.Read(path), canThrow: false);
                    if (cachedFontRoot != null)
                    {
                        fontGenerator.HandleCache(cachedFontRoot);
                    }
                }
            }

            return(fontGenerator);
        }
Esempio n. 4
0
        public TinyToken Parse(IEnumerable <Token <YamlTokenType> > tokens)
        {
            TinyToken result = null;

            var context = new ParseContext <YamlTokenType>(tokens, new AnyParser(r => result = r));

            while (context.CurrentToken != null)
            {
                switch (context.CurrentToken.Type)
                {
                case YamlTokenType.Indent:
                    context.Indent(context.CurrentToken.Value.Length / 2);
                    context.ConsumeToken();
                    continue;

                case YamlTokenType.EndLine:
                    context.NewLine();
                    context.ConsumeToken();
                    continue;
                }
                //Debug.Print($"  - {context.Parser.GetType().Name} ({context.ParserCount})");
                context.Parser.Parse(context);
            }
            context.End();

            return(result);
        }
Esempio n. 5
0
        private bool matches(TinyToken cachedFontRoot)
        {
            if (cachedFontRoot.Value <string>("FontPath") == description.FontPath &&
                cachedFontRoot.Value <int>("FontSize") == description.FontSize &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("ColorR"), description.Color.R, 0.00001f) &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("ColorG"), description.Color.G, 0.00001f) &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("ColorB"), description.Color.B, 0.00001f) &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("ColorA"), description.Color.A, 0.00001f) &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("PaddingX"), description.Padding.X, 0.00001f) &&
                MathUtil.FloatEquals(cachedFontRoot.Value <float>("PaddingY"), description.Padding.Y, 0.00001f) &&
                cachedFontRoot.Value <FontStyle>("FontStyle") == description.FontStyle &&
                cachedFontRoot.Value <bool>("TrimTransparency") == description.TrimTransparency &&
                cachedFontRoot.Value <bool>("EffectsOnly") == description.EffectsOnly &&
                cachedFontRoot.Value <bool>("Debug") == description.Debug)
            {
                var effectsRoot = cachedFontRoot.Value <TinyArray>("Effects");
                if (effectsRoot.Count != effects.Length)
                {
                    return(false);
                }

                for (var i = 0; i < effects.Length; i++)
                {
                    if (!effects[i].Matches(effectsRoot[i].Value <TinyToken>()))
                    {
                        return(false);
                    }
                }

                return(true);
            }
            return(false);
        }
Esempio n. 6
0
 public bool Matches(TinyToken cachedEffectRoot)
 => cachedEffectRoot.Value <string>("Type") == GetType().FullName&&
 cachedEffectRoot.Value <int>("Thickness") == Thickness &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorR"), Color.R, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorG"), Color.G, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorB"), Color.B, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorA"), Color.A, 0.00001f);
Esempio n. 7
0
 public bool Matches(TinyToken cachedEffectRoot)
 => cachedEffectRoot.Value <string>("Type") == GetType().FullName&&
 cachedEffectRoot.Value <int>("Radius") == Radius &&
 MathUtil.DoubleEquals(cachedEffectRoot.Value <double>("Power"), Power, 0.00001) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorR"), Color.R, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorG"), Color.G, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorB"), Color.B, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorA"), Color.A, 0.00001f);
Esempio n. 8
0
 public bool Matches(TinyToken cachedEffectRoot)
 => cachedEffectRoot.Value <string>("Type") == GetType().FullName&&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("OffsetX"), Offset.X, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("OffsetY"), Offset.Y, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("SizeX"), Size.X, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("SizeY"), Size.Y, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorR"), Color.R, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorG"), Color.G, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorB"), Color.B, 0.00001f) &&
 MathUtil.FloatEquals(cachedEffectRoot.Value <float>("ColorA"), Color.A, 0.00001f) &&
 cachedEffectRoot.Value <WrapMode>("WrapMode") == WrapMode;
Esempio n. 9
0
        public TinyToken Parse(IEnumerable <Token <JsonTokenType> > tokens)
        {
            TinyToken result = null;

            var context = new ParseContext <JsonTokenType>(tokens, new AnyParser(r => result = r));

            while (context.CurrentToken != null)
            {
                //Debug.Print($"  - {context.Parser.GetType().Name} ({context.ParserCount}) {context.CurrentToken}");
                context.Parser.Parse(context);
            }
            context.End();

            return(result);
        }
Esempio n. 10
0
        private void write(TextWriter writer, TinyToken token, TinyToken parent, int indentLevel)
        {
            switch (token.Type)
            {
            case TinyTokenType.Object:
                writeObject(writer, (TinyObject)token, parent, indentLevel);
                break;

            case TinyTokenType.Array:
                writeArray(writer, (TinyArray)token, parent, indentLevel);
                break;

            default:
                writeValue(writer, (TinyValue)token, parent, indentLevel);
                break;
            }
        }
Esempio n. 11
0
        internal void HandleCache(TinyToken cachedFontRoot)
        {
            if (!matches(cachedFontRoot))
            {
                return;
            }

            foreach (var cacheEntry in cachedFontRoot.Values <TinyObject>("Cache"))
            {
                var path = cacheEntry.Value <string>("Path");
                var hash = cacheEntry.Value <string>("Hash");

                var fullPath = Path.Combine(mapsetDirectory, path);
                if (!File.Exists(fullPath) || HashHelper.GetFileMd5(fullPath) != hash)
                {
                    continue;
                }

                var text = cacheEntry.Value <string>("Text");
                if (text.Contains('\ufffd'))
                {
                    Trace.WriteLine($"Ignoring invalid font texture \"{text}\" ({path})");
                    continue;
                }
                if (textureCache.ContainsKey(text))
                {
                    throw new InvalidDataException($"The font texture for \"{text}\" ({path}) has been cached multiple times");
                }

                textureCache.Add(text, new FontTexture(
                                     path,
                                     cacheEntry.Value <float>("OffsetX"),
                                     cacheEntry.Value <float>("OffsetY"),
                                     cacheEntry.Value <int>("BaseWidth"),
                                     cacheEntry.Value <int>("BaseHeight"),
                                     cacheEntry.Value <int>("Width"),
                                     cacheEntry.Value <int>("Height")
                                     ));
            }
        }
Esempio n. 12
0
        private void writeObject(TextWriter writer, TinyObject obj, TinyToken parent, int indentLevel)
        {
            var parentIsArray = parent != null && parent.Type == TinyTokenType.Array;

            var first = true;

            foreach (var property in obj)
            {
                if (!first || !parentIsArray)
                {
                    writeIndent(writer, indentLevel);
                }

                var key = property.Key;
                if (key.Contains(" ") || key.Contains(":") || key.StartsWith("-"))
                {
                    key = "\"" + YamlUtil.EscapeString(key) + "\"";
                }

                var value = property.Value;
                if (value.IsEmpty)
                {
                    writer.WriteLine(key + ":");
                }
                else if (value.IsInline)
                {
                    writer.Write(key + ": ");
                    write(writer, value, obj, 0);
                }
                else
                {
                    writer.WriteLine(key + ":");
                    write(writer, value, obj, indentLevel + 1);
                }
                first = false;
            }
        }
Esempio n. 13
0
        private void checkLatestVersion()
        {
            NetHelper.Request($"https://api.github.com/repos/{Program.Repository}/releases?per_page=10&page=1", "cache/net/releases", 15 * 60,
                              (response, exception) =>
            {
                if (IsDisposed)
                {
                    return;
                }
                if (exception != null)
                {
                    handleLastestVersionException(exception);
                    return;
                }
                try
                {
                    var hasLatest     = false;
                    var latestVersion = Program.Version;
                    var description   = "";
                    var downloadUrl   = (string)null;

                    var releases = TinyToken.ReadString <JsonFormat>(response);
                    foreach (var release in releases.Values <TinyObject>())
                    {
                        var isDraft      = release.Value <bool>("draft");
                        var isPrerelease = release.Value <bool>("prerelease");
                        if (isDraft || isPrerelease)
                        {
                            continue;
                        }

                        var name    = release.Value <string>("name");
                        var version = new Version(name);

                        if (!hasLatest)
                        {
                            hasLatest     = true;
                            latestVersion = version;

                            foreach (var asset in release.Values <TinyObject>("assets"))
                            {
                                var downloadName = asset.Value <string>("name");
                                if (downloadName.EndsWith(".zip"))
                                {
                                    downloadUrl = asset.Value <string>("browser_download_url");
                                    break;
                                }
                            }
                        }

                        if (Program.Version < version || Program.Version >= latestVersion)
                        {
                            var publishedAt = release.Value <string>("published_at");
                            var publishDate = DateTime.ParseExact(publishedAt, @"yyyy-MM-dd\THH:mm:ss\Z", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
                            var authorName  = release.Value <string>("author", "login");

                            var body = release.Value <string>("body");
                            if (body.Contains("---"))
                            {
                                body = body.Substring(0, body.IndexOf("---"));
                            }
                            body = body.Replace("\r\n", "\n").Trim(' ', '\n');
                            body = $"v{version} - {authorName}, {publishDate.ToTimeAgo()}\n{body}\n\n";

                            var newDescription = description + body;
                            if (description.Length > 0 && newDescription.Count(c => c == '\n') > 35)
                            {
                                break;
                            }

                            description = newDescription;
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (Program.Version < latestVersion)
                    {
                        updateButton.Text     = $"Version {latestVersion} available!";
                        updateButton.Tooltip  = $"What's new:\n\n{description.TrimEnd('\n')}";
                        updateButton.OnClick += (sender, e) =>
                        {
                            if (downloadUrl != null && latestVersion >= new Version(1, 4))
                            {
                                Manager.Add(new UpdateMenu(downloadUrl));
                            }
                            else
                            {
                                Updater.OpenLastestReleasePage();
                            }
                        };
                        updateButton.StyleName = "";
                        updateButton.Disabled  = false;
                    }
                    else
                    {
                        versionLabel.Tooltip   = $"Recent changes:\n\n{description.TrimEnd('\n')}";
                        updateButton.Displayed = false;
                    }
                    bottomLayout.Pack(600);
                }
                catch (Exception e)
                {
                    handleLastestVersionException(e);
                }
            });
        }
Esempio n. 14
0
 public override void Write(TextWriter writer, TinyToken value)
 => write(writer, value, null, 0);
Esempio n. 15
0
        private void writeValue(TextWriter writer, TinyValue valueToken, TinyToken parent, int indentLevel)
        {
            if (indentLevel != 0)
            {
                throw new InvalidOperationException();
            }

            var type  = valueToken.Type;
            var value = valueToken.Value <object>();

            switch (type)
            {
            case TinyTokenType.Null:
                writer.WriteLine();
                break;

            case TinyTokenType.String:
                writer.WriteLine("\"" + YamlUtil.EscapeString((string)value) + "\"");
                break;

            case TinyTokenType.Integer:
                writer.WriteLine(value?.ToString());
                break;

            case TinyTokenType.Float:
                if (value is float floatFloat)
                {
                    writer.WriteLine(floatFloat.ToString(CultureInfo.InvariantCulture));
                }
                else if (value is double floatDouble)
                {
                    writer.WriteLine(floatDouble.ToString(CultureInfo.InvariantCulture));
                }
                else if (value is decimal floatDecimal)
                {
                    writer.WriteLine(floatDecimal.ToString(CultureInfo.InvariantCulture));
                }
                else if (value is string floatString)
                {
                    writer.WriteLine(floatString);
                }
                else
                {
                    throw new InvalidDataException(value?.ToString());
                }
                break;

            case TinyTokenType.Boolean:
                writer.WriteLine(((bool)value) ? BooleanTrue : BooleanFalse);
                break;

            case TinyTokenType.Array:
            case TinyTokenType.Object:
            case TinyTokenType.Invalid:
                // Should never happen :)
                throw new InvalidDataException(type.ToString());

            default:
                throw new NotImplementedException(type.ToString());
            }
        }
Esempio n. 16
0
        private void loadText(string path)
        {
            var targetDirectory = Path.Combine(Path.GetDirectoryName(path), DataFolder);

            using (var directoryReader = new SafeDirectoryReader(targetDirectory))
            {
                var indexPath = directoryReader.GetPath("index.yaml");
                var indexRoot = TinyToken.Read(indexPath);

                var indexVersion = indexRoot.Value <int>("FormatVersion");
                if (indexVersion > Version)
                {
                    throw new InvalidOperationException("This project was saved with a more recent version, you need to update to open it");
                }

                var userPath = directoryReader.GetPath("user.yaml");
                if (File.Exists(userPath))
                {
                    var userRoot = TinyToken.Read(userPath);

                    var userVersion = userRoot.Value <int>("FormatVersion");
                    if (userVersion > Version)
                    {
                        throw new InvalidOperationException("This project's user settings were saved with a more recent version, you need to update to open it");
                    }

                    var savedBy = userRoot.Value <string>("Editor");
                    Debug.Print($"Project saved by {savedBy}");

                    OwnsOsb = userRoot.Value <bool>("OwnsOsb");
                }

                MapsetPath = indexRoot.Value <string>("MapsetPath");
                SelectBeatmap(indexRoot.Value <long>("BeatmapId"), indexRoot.Value <string>("BeatmapName"));
                ImportedAssemblies = indexRoot.Values <string>("Assemblies");

                // Load effects
                var layerInserters = new Dictionary <string, Action>();
                foreach (var effectPath in Directory.EnumerateFiles(directoryReader.Path, "effect.*.yaml", SearchOption.TopDirectoryOnly))
                {
                    var guidMatch = effectGuidRegex.Match(effectPath);
                    if (!guidMatch.Success || guidMatch.Groups.Count < 2)
                    {
                        throw new InvalidDataException($"Could not parse effect Guid from '{effectPath}'");
                    }

                    var effectRoot = TinyToken.Read(effectPath);

                    var effectVersion = effectRoot.Value <int>("FormatVersion");
                    if (effectVersion > Version)
                    {
                        throw new InvalidOperationException("This project contains an effect that was saved with a more recent version, you need to update to open it");
                    }

                    var effect = AddEffect(effectRoot.Value <string>("Script"));
                    effect.Guid = Guid.Parse(guidMatch.Groups[1].Value);
                    effect.Name = effectRoot.Value <string>("Name");

                    var configRoot = effectRoot.Value <TinyObject>("Config");
                    var fieldIndex = 0;
                    foreach (var fieldProperty in configRoot)
                    {
                        var fieldRoot = fieldProperty.Value;

                        var fieldTypeName = fieldRoot.Value <string>("Type");
                        var fieldContent  = fieldRoot.Value <string>("Value");
                        var fieldValue    = ObjectSerializer.FromString(fieldTypeName, fieldContent);

                        var allowedValues = fieldRoot
                                            .Value <TinyObject>("AllowedValues")?
                                            .Select(p => new NamedValue {
                            Name = p.Key, Value = ObjectSerializer.FromString(fieldTypeName, p.Value.Value <string>()),
                        })
                                            .ToArray();

                        effect.Config.UpdateField(fieldProperty.Key, fieldRoot.Value <string>("DisplayName") ?? fieldProperty.Key, fieldIndex++, fieldValue?.GetType(), fieldValue, allowedValues);
                    }

                    var layersRoot = effectRoot.Value <TinyObject>("Layers");
                    foreach (var layerProperty in layersRoot)
                    {
                        var layerEffect = effect;
                        var layerGuid   = layerProperty.Key;
                        var layerRoot   = layerProperty.Value;
                        layerInserters.Add(layerGuid, () => layerEffect.AddPlaceholder(new EditorStoryboardLayer(layerRoot.Value <string>("Name"), layerEffect)
                        {
                            Guid         = Guid.Parse(layerGuid),
                            OsbLayer     = layerRoot.Value <OsbLayer>("OsbLayer"),
                            DiffSpecific = layerRoot.Value <bool>("DiffSpecific"),
                            Visible      = layerRoot.Value <bool>("Visible"),
                        }));
                    }
                }

                // Insert layers defined in the index
                var layersOrder = indexRoot.Values <string>("Layers");
                if (layersOrder != null)
                {
                    foreach (var layerGuid in layersOrder.Distinct())
                    {
                        if (layerInserters.TryGetValue(layerGuid, out var insertLayer))
                        {
                            insertLayer();
                        }
                    }
                }

                // Insert all remaining layers
                foreach (var key in layersOrder == null ? layerInserters.Keys : layerInserters.Keys.Except(layersOrder))
                {
                    var insertLayer = layerInserters[key];
                    insertLayer();
                }
            }
        }
Esempio n. 17
0
 public override void Write(TextWriter writer, TinyToken value)
 => throw new NotImplementedException();