// CONSTRUCTOR ----------------------------------------------------------------------------------
        public GameScene( GameSceneData pData )
        {
            gameTimeLimit = pData.timeLimit;

            this.AddChild( BackgroundLayer = new Layer() );
            this.AddChild( GameplayLayer = new Layer() );
            this.AddChild( ForegroundLayer = new Layer() );
            this.AddChild( DialogLayer = new Layer() );
            Layers = new Layer[] {BackgroundLayer, GameplayLayer, ForegroundLayer, DialogLayer};

            Touch.GetData(0).Clear();
            InputManager.Instance.Reset();

            currentLevel = pData.level;
            this.Camera.SetViewFromViewport();
            _physics = GamePhysics.Instance;

            Hud = new Crystallography.UI.GameSceneHud(this);
            if (gameTimeLimit > 0.0f) {
                Hud.SetGameTimeLimit(gameTimeLimit);
            }
            ForegroundLayer.AddChild(Hud);

            SG = SelectionGroup.Instance;
            SG.Reset( this );
            ForegroundLayer.AddChild(SG.getNode());

            #if DEBUG
            // This is debug routine that will draw the physics bounding box around all physics bodies
            if(DEBUG_BOUNDINGBOXS)
            {
                this.AdHocDraw += () => {
                    foreach (ICrystallonEntity e in _allEntites) {
                        if (e is SpriteTileCrystallonEntity) {
            //							Node n = e.getNode();
            //							Vector2 halfDimensions = new Vector2((e as SpriteTileCrystallonEntity).Width, (e as SpriteTileCrystallonEntity).Height) /4.0f;
            //							var bl = n.Position - halfDimensions;
            //							var tr = n.Position + halfDimensions;
                            Director.Instance.DrawHelpers.DrawBounds2(
                                e.getBounds()
                            );
                        }
                    }
            //					foreach (PhysicsBody pb in _physics.SceneBodies) {
            //						if ( pb != null ) {
            //							var bottomLeft = pb.AabbMin;
            //							var topRight = pb.AabbMax;
            //							Director.Instance.DrawHelpers.DrawBounds2Fill (
            //								new Bounds2(bottomLeft*GamePhysics.PtoM, topRight*GamePhysics.PtoM));
            //						}
            //					}
                };

                this.AdHocDraw += () => {
                    var s = SelectionGroup.Instance.getNode().Position;
                    var bl = s - (20*Vector2.One);
                    var tr = s + (20*Vector2.One);
                    Director.Instance.DrawHelpers.DrawBounds2Fill(
                        new Bounds2(bl,tr)
                    );
                };

                this.AdHocDraw += () => {
            //					var s = SelectionGroup.Instance.getPosition() - SelectionGroup.Instance.heading.Normalize() * FMath.Max( 80.0f, FMath.Min(120.0f, (120.0f * SelectionGroup.Instance.velocity/100.0f)));
                    var s = SelectionGroup.Instance.getNode().LocalToWorld( SelectionGroup.UP_LEFT_SELECTION_POINT );
                    var bl = s - (2*Vector2.One);
                    var tr = bl + (4*Vector2.One);
                    Director.Instance.DrawHelpers.DrawBounds2Fill(
                        new Bounds2(bl,tr)
                    );
                };
                this.AdHocDraw += () => {
                    var s = SelectionGroup.Instance.getNode().LocalToWorld( SelectionGroup.UP_RIGHT_SELECTION_POINT );
                    var bl = s - (2*Vector2.One);
                    var tr = bl + (4*Vector2.One);
                    Director.Instance.DrawHelpers.DrawBounds2Fill(
                        new Bounds2(bl,tr)
                    );
                };
                this.AdHocDraw += () => {
                    var s = SelectionGroup.Instance.getNode().LocalToWorld( SelectionGroup.LEFT_UP_SELECTION_POINT );
                    var bl = s - (2*Vector2.One);
                    var tr = bl + (4*Vector2.One);
                    Director.Instance.DrawHelpers.DrawBounds2Fill(
                        new Bounds2(bl,tr)
                    );
                };
                this.AdHocDraw += () => {
                    var s = SelectionGroup.Instance.getNode().LocalToWorld( SelectionGroup.RIGHT_UP_SELECTION_POINT );
                    var bl = s - (2*Vector2.One);
                    var tr = bl + (4*Vector2.One);
                    Director.Instance.DrawHelpers.DrawBounds2Fill(
                        new Bounds2(bl,tr)
                    );
                };
            }
            #endif

            Scheduler.Instance.ScheduleUpdateForTarget(this,0,false);
            Pause (false);
            Sequence sequence = new Sequence();
            sequence.Add( new DelayTime(0.1f) );
            sequence.Add( new CallFunc( () => ResetToLevel() ) );
            this.RunAction(sequence);

            ForegroundLayer.AddChild( Support.ParticleEffectsManager.Instance );

            #if METRICS
            DataStorage.AddMetric("Level", () => currentLevel, 1);
            #endif
        }
        public void Destroy()
        {
            InputManager.Instance.DoubleTapDetected -= HandleInputManagerInstanceDoubleTapDetected;
            InputManager.Instance.TouchJustDownDetected -= HandleInputManagerInstanceTouchJustDownDetected;
            InputManager.Instance.TouchJustUpDetected -= HandleInputManagerInstanceTouchJustUpDetected;
            InputManager.Instance.TouchDownDetected -= HandleInputManagerInstanceTouchDownDetected;
            InputManager.Instance.DragDetected -= HandleInputManagerInstanceDragDetected;
            InputManager.Instance.TapDetected -= HandleInputManagerInstanceTapDetected;

            RemoveAll();
            this.removeFromScene(true);
            _instance = null;
            lastPosition.Clear();
            lastPosition = null;
            _scene = null;
            lastEntityReleased = null;
            lastEntityTouched = null;
            justDownPositionEntity = null;
        }
        public override void OnExit()
        {
            foreach ( Layer l in Layers ) {
                l.RemoveAllChildren(true);
            }
            Layers = null;
            Hud = null;
            SG.Destroy();
            SG = null;
            Support.ParticleEffectsManager.Instance.Destroy();
            base.OnExit();
            Support.MusicSystem.Instance.StopAll();
            Crystallography.UI.PausePanel.PauseDetected -= HandleCrystallographyUIPausePanelPauseDetected;

            InputManager.Instance.UpJustUpDetected -= HandleInputManagerInstanceUpJustUpDetected;

            AppMain.UI_INPUT_ENABLED = true;
            #if DEBUG
            Console.WriteLine("########### EXIT GameScene ###############");
            #endif
        }
            public void AddSelectionMarkerParticle( SelectionGroup pParent, Vector4 pColor)
            {
                if (ActiveScoreParticles >= ScoreParticles.Count) {
                #if DEBUG
                    System.Console.WriteLine("Hit Max Particle Count(" + ScoreParticles.Count.ToString() + "! Particle not created.");
                #endif
                    return;
                }

                Particle p = SelectionMarkerParticles[ActiveSelectionMarkerParticles];
                p.variant = 0;
                //				p.parent = pParent;
                p.size = new Vector2( 32.0f, 32.0f);
                p.size_delta = new Vector2(3.0f, 3.0f);
                p.offset = -0.5f*p.size;
                p.position = InputManager.Instance.TouchPosition + p.offset;
                //				p.position = pParent.getNode().LocalToWorld(pParent.getNode().Pivot) + p.offset;
                p.color = pColor;
                p.time = 0.0f;
                p.lifetime = 1.0f;

                //				p.offset = new Vector2( 0.5f * p.size.X, 0.5f * p.size.Y);
                //				p.size_delta = Vector2.Zero;
                //				p.velocity = -0.3f * p.lifetime * gravity + Vector2.UnitX * GameScene.Random.NextSign()*(50.0f + 50.0f * GameScene.Random.NextFloat());
                p.velocity = Vector2.Zero;
                p.type = (int)ParticleType.SELECTION_MARKER;
                ActiveSelectionMarkerParticles++;
            }