/// <summary>
        /// Load handlers for each level
        /// </summary>
        public static void LoadLevelHandlers(Level newLevel)
        {
            Launch.Log("[Loading] Initialising per-level handlers...");

            IEnumerable<Type> e = LevelHandlerTypes.Where(
                t => ((HandlerAttribute[]) t.GetCustomAttributes(typeof(HandlerAttribute), false))
                     .Where(a => ((a.LevelType & newLevel.Type) == newLevel.Type) && (a.LevelNames == null || a.LevelNames.Contains(newLevel.Name)))
                     .Count() > 0);

            foreach (Type t in e) {
                Launch.Log("[Loading] \tCreating " + t);
                AddLevelObject(Activator.CreateInstance(t), t);
            }
        }
        public static void SetupShadows(this SceneManager sceneMgr, Level level)
        {
            if (Options.ShadowDetail != ShadowDetailOption.None) {
                sceneMgr.ShadowTechnique = ShadowTechnique.SHADOWTYPE_STENCIL_MODULATIVE;
                sceneMgr.ShadowFarDistance = float.Parse(Options.Get("ShadowDistance"));
                sceneMgr.ShadowColour = level.Definition.GetVectorProperty("ShadowColour", new Vector3(0.8f, 0.8f, 0.8f)).ToColourValue();
            }
            else {
                sceneMgr.ShadowTechnique = ShadowTechnique.SHADOWTYPE_NONE;
            }

            /*
            sceneMgr.ShadowTechnique = ShadowTechnique.SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED;

            sceneMgr.SetShadowTextureCountPerLightType(Light.LightTypes.LT_DIRECTIONAL, 3);
            sceneMgr.ShadowTextureCount = 3;
            sceneMgr.SetShadowTextureConfig(0, 1024, 1024, PixelFormat.PF_FLOAT32_R);
            sceneMgr.SetShadowTextureConfig(1, 512, 512, PixelFormat.PF_FLOAT32_R);
            sceneMgr.SetShadowTextureConfig(2, 512, 512, PixelFormat.PF_FLOAT32_R);
            sceneMgr.ShadowTextureSelfShadow = true;
            sceneMgr.ShadowCasterRenderBackFaces = false;
            sceneMgr.ShadowFarDistance = 150;
            sceneMgr.SetShadowTextureCasterMaterial("PSSM/shadow_caster");
            sceneMgr.SetShadowTextureFadeStart(0.7f);

            PSSMShadowCameraSetup pssm = new PSSMShadowCameraSetup();
            pssm.SplitPadding = 1f;
            pssm.CalculateSplitPoints(3, 0.01f, sceneMgr.ShadowFarDistance - 10);
            pssm.SetOptimalAdjustFactor(0, 2);
            pssm.SetOptimalAdjustFactor(1, 1f);
            pssm.SetOptimalAdjustFactor(2, 0.5f);
            pssm.UseSimpleOptimalAdjust = false;

            sceneMgr.SetShadowCameraSetup(new ShadowCameraSetupPtr(pssm));*/
        }
        /// <summary>
        /// runs level manager stuff that needs to run immediately after kernel setup
        /// </summary>
        public void RunPostInitEvents()
        {
            // don't let this run twice
            if (hasRunPostInitEvents)
                throw new ApplicationException("The LevelManager has already run its post-initialisation events!");

            CurrentLevel = new Level(Settings.Default.MainMenuName);
            CurrentLevel.ReadMuffin();

            // run level loading events
            var args = new LevelChangedEventArgs(CurrentLevel, new Level(null), new LevelChangeRequest() { NewLevelName = Settings.Default.MainMenuName });
            Invoke(OnLevelLoad, args);
            LKernel.LoadLevelHandlers(args.NewLevel);

            IsValidLevel = true;

            // make sure this won't run again
            hasRunPostInitEvents = true;
            // pause it for the main menu
            Pauser.IsPaused = true;
            // we don't want any input to go while we're in the middle of changing levels
            LKernel.GetG<InputSwallowerManager>().AddSwallower(() => !IsValidLevel, this);
        }