public static BlackholeBG CreateBlackholeWithCustomColors(BinaryPacker.Element effectData)
        {
            if (!effectData.Attr("colorsMild").Contains("|") &&
                !effectData.Attr("colorsWild").Contains("|") &&
                !effectData.Attr("bgColorInner").Contains("|") &&
                !effectData.Attr("bgColorOuterMild").Contains("|") &&
                !effectData.Attr("bgColorOuterWild").Contains("|"))
            {
                // there is no gradient on any color: we can just instanciate a vanilla blackhole and mess with its properties.

                // set up colorsMild for the hook above. we can't use DynData to pass this over, since the object does not exist yet!
                colorsMild = parseColors(effectData.Attr("colorsMild", "6e3199,851f91,3026b0"));
                for (int i = 0; i < colorsMild.Length; i++)
                {
                    colorsMild[i] *= 0.8f;
                }

                // build the blackhole: the hook will take care of setting colorsMild.
                BlackholeBG blackhole = new BlackholeBG();

                // ... now we've got to set everything else.
                DynData <BlackholeBG> blackholeData = new DynData <BlackholeBG>(blackhole);
                blackholeData["colorsWild"]       = parseColors(effectData.Attr("colorsWild", "ca4ca7,b14cca,ca4ca7"));
                blackholeData["bgColorInner"]     = Calc.HexToColor(effectData.Attr("bgColorInner", "000000"));
                blackholeData["bgColorOuterMild"] = Calc.HexToColor(effectData.Attr("bgColorOuterMild", "512a8b"));
                blackholeData["bgColorOuterWild"] = Calc.HexToColor(effectData.Attr("bgColorOuterWild", "bd2192"));
                blackhole.Alpha = effectData.AttrFloat("alpha", 1f);

                return(blackhole);
            }
            else
            {
                // there are gradients: we need a custom blackhole!

                // set up colorsMild for the hook above. we can't use DynData to pass this over, since the object does not exist yet!
                colorsMild = new ColorCycle(effectData.Attr("colorsMild", "6e3199,851f91,3026b0"), 0.8f).GetColors();

                // build the blackhole: the hook will take care of setting colorsMild.
                BlackholeCustomColors blackhole = new BlackholeCustomColors(
                    effectData.Attr("colorsMild", "6e3199,851f91,3026b0"),
                    effectData.Attr("colorsWild", "ca4ca7,b14cca,ca4ca7"),
                    effectData.Attr("bgColorInner", "000000"),
                    effectData.Attr("bgColorOuterMild", "512a8b"),
                    effectData.Attr("bgColorOuterWild", "bd2192"));

                // ... now we've got to set the initial values of everything else.
                blackhole.blackholeData["colorsWild"]       = blackhole.cycleColorsWild.GetColors();
                blackhole.blackholeData["bgColorInner"]     = blackhole.cycleBgColorInner.GetColors()[0];
                blackhole.blackholeData["bgColorOuterMild"] = blackhole.cycleBgColorOuterMild.GetColors()[0];
                blackhole.blackholeData["bgColorOuterWild"] = blackhole.cycleBgColorOuterWild.GetColors()[0];
                blackhole.Alpha = effectData.AttrFloat("alpha", 1f);

                return(blackhole);
            }
        }
        public static BlackholeBG CreateBlackholeWithCustomColors(BinaryPacker.Element effectData)
        {
            // set up colorsMild for the hook above. we can't use DynData to pass this over, since the object does not exist yet!
            colorsMild = parseColors(effectData.Attr("colorsMild", "6e3199,851f91,3026b0"));
            for (int i = 0; i < colorsMild.Length; i++)
            {
                colorsMild[i] *= 0.8f;
            }

            // build the blackhole: the hook will take care of setting colorsMild.
            BlackholeBG blackhole = new BlackholeBG();

            // ... now we've got to set everything else.
            DynData <BlackholeBG> blackholeData = new DynData <BlackholeBG>(blackhole);

            blackholeData["colorsWild"]       = parseColors(effectData.Attr("colorsWild", "ca4ca7,b14cca,ca4ca7"));
            blackholeData["bgColorInner"]     = Calc.HexToColor(effectData.Attr("bgColorInner", "000000"));
            blackholeData["bgColorOuterMild"] = Calc.HexToColor(effectData.Attr("bgColorOuterMild", "512a8b"));
            blackholeData["bgColorOuterWild"] = Calc.HexToColor(effectData.Attr("bgColorOuterWild", "bd2192"));
            blackhole.Alpha = effectData.AttrFloat("alpha", 1f);

            return(blackhole);
        }
        private IEnumerator Cutscene()
        {
            Engine.TimeRate = 1f;
            boost.Active    = false;
            yield return(null);

            yield return(0.152f);

            cameraOffset = new Vector2(0.0f, -20f);
            boost.Active = true;
            player.EnforceLevelBounds = false;
            yield return(null);

            BlackholeBG blackhole = Level.Background.Get <BlackholeBG>();

            if (blackhole != null)
            {
                blackhole.Direction = -2.5f;
                blackhole.SnapStrength(Level, BlackholeBG.Strengths.High);
                blackhole.CenterOffset.Y = 100f;
                blackhole.OffsetOffset.Y = -50f;
                blackhole = null;
            }

            Add(new Coroutine(WaveCamera()));
            Add(new Coroutine(BirdRoutine(0.8f)));
            Level.Add(streaks = new AscendManager.Streaks(null));
            for (var p = 0.0f; p < 1.0; p += Engine.DeltaTime / 12f)
            {
                fadeToWhite   = p;
                streaks.Alpha = p;
                foreach (Parallax parallax in Level.Foreground.GetEach <Parallax>("blackhole"))
                {
                    Parallax fg = parallax;
                    fg.FadeAlphaMultiplier = 1f - p;
                }

                yield return(null);
            }

            while (bird != null)
            {
                yield return(null);
            }

            FadeWipe wipe = new FadeWipe(Level, false)
            {
                Duration = 4f
            };

            var from = cameraOffset.Y;
            var to   = 180;

            for (var p = 0.0f; p < 1.0; p += Engine.DeltaTime / 2f)
            {
                cameraOffset.Y = from + (to - from) * Ease.BigBackIn(p);
                yield return(null);
            }

            while (wipe.Percent < 1.0)
            {
                yield return(null);
            }

            EndCutscene(Level);
        }