}   // end of ToolMenuUpdateObj c'tor

            /// <summary>
            /// ToolMenuUpdateObj Update()
            /// </summary>
            /// <param name="camera"></param>
            public override void Update()
            {
                base.Update();

                // No need to check for input focus or anything.  If
                // we're active then the ToolMenu object has focus.

                shared.ToolMenu.Update();

                // If the ToolMenu is no longer active we're done.
                if (!shared.ToolMenu.Active)
                {
                    return;
                }

                // Do the common bits of the Update().  If our child is active we
                // can temporarily push/pop our commandMap to grab input focus.
                if (shared.ToolMenu.Active)
                {
                    CommandStack.Push(commandMap);
                }
                UpdateCamera(false);
                if (shared.ToolMenu.Active)
                {
                    CommandStack.Pop(commandMap);
                }
                UpdateWorld();
                // TODO (****) Should this only be called for tools that use the edit brush?
                // TODO (****) How do we turn off the edit brush rendering if we don't need it?
                UpdateEditBrush();

                GamePadInput pad = GamePadInput.GetGamePad0();

                // Run!
                if (pad.Back.WasPressed)
                {
                    // TODO (****) Transition to RunSim.
                    // Or is this already done in the base class???
                }

                // MiniHub!
                if (pad.Start.WasPressed)
                {
                    // TODO (****) Transition to MinHub.
                    // Or is this already done in the base class???
                }

                ToolTipManager.Update();
                ThoughtBalloonManager.Update(shared.camera);
            }   // end of ToolMenuUpdateObj Update()
示例#2
0
 public virtual bool RouteAndAnimate(InteractionInstance interaction, Sim Actor)
 {
     if (!base.Actor.RouteToPointRadialRange(base.Target.Position, 0.5f, 2f))
     {
         return(false);
     }
     interaction.StandardEntry();
     if (Actor.SimDescription.ChildOrAbove)
     {
         //Think about styling
         ThoughtBalloonManager.BalloonData balloonData = ThoughtBalloonManager.GetBalloonData("Makeover", base.Actor);
         balloonData.BalloonType = ThoughtBalloonTypes.kSpeechBalloon;
         base.Actor.ThoughtBalloonManager.ShowBalloon(balloonData);
     }
     return(true);
 }
            }   // end of RunSimUpdateObj c'tor

            /// <summary>
            /// RunSimUpdateObj Update()
            /// </summary>
            /// <param name="camera"></param>
            public override void Update()
            {
                base.Update();

                parent.Camera.Update();

                float secs = Time.WallClockFrameSeconds;

                ThoughtBalloonManager.Update(shared.camera);
                SaidStringManager.Update();
#if !NETFX_CORE
                MicrobitManager.Update();
#endif

                // Start with visible cursor.
                parent.cursor3D.Activate();
                parent.cursor3D.Rep    = Cursor3D.Visual.RunSim;
                parent.cursor3D.Hidden = false;

                //
                // Determine the correct camera mode.
                //

                //
                //  The priorities used to determine the camera mode when the game is running are:
                //
                //  1)  First person.  This can be either via programming or because the user zoomed
                //      into a bot the camera was following.
                //  2)  Follow mode caused by bot(s) programmed with "follow" camera view.
                //  3)  World tweak screen fixed camera or fixed offset camera.
                //  4)  Follow mode caused by user controlled bot(s).
                //  5)  Free camera.
                //

                // Start with a fake loop to break out of.
                while (true)
                {
                    Terrain terrain = InGame.inGame.Terrain;    // Just a shortcut.

                    //
                    // Always use edit mode when the game is paused except during victory on level with one of the fixed cameras
                    // or when game is paused for a bot to speak (modal text display).
                    //
                    bool victoryActive = VictoryOverlay.ActiveGameOver || VictoryOverlay.ActiveWinner;
                    bool speaking      = InGame.inGame.shared.smallTextDisplay.Active || InGame.inGame.shared.scrollableTextDisplay.Active;
                    if (Time.Paused && !((terrain.FixedCamera || terrain.FixedOffsetCamera) && victoryActive) && !speaking)
                    {
                        CameraInfo.Mode = CameraInfo.Modes.Edit;
                        CameraInfo.CameraFocusGameActor = null;
                        break;
                    }

                    //
                    // 1) First person
                    //
                    if (CameraInfo.FirstPersonActive)
                    {
                        CameraInfo.Mode = CameraInfo.Modes.Actor;

                        // We're following a single actor so update the FollowActor camera values.
                        shared.camera.FollowCameraValid = false;

                        // Turn off 3d cursor since we don't need it.
                        parent.cursor3D.Deactivate();
                        if (parent.cursorClone != null)
                        {
                            parent.cursorClone.Deactivate();
                            parent.cursorClone = null;
                        }
                        break;
                    }

                    //
                    // 2)  Follow mode caused by bot(s) programmed with "follow" camera view.
                    //
                    if (CameraInfo.ProgrammedFollowList.Count > 0)
                    {
                        // Note that even though we looked at the count of bot programmed to
                        // have the camera follow them, for this mode we want to keep all
                        // deserving bots in camera.  So, the rest of this section will use
                        // the merged follow list instead of just the programmed follow list.

                        SetUpCameraFollowMode();

                        break;
                    }

                    //
                    // 3) World tweak fixed cameras.  Note for fixed offset we have to let
                    //    the later modes do their stuff and then override the camera.
                    //

                    if (terrain.FixedCamera)
                    {
                        CameraInfo.Mode = CameraInfo.Modes.FixedTarget;
                        CameraInfo.CameraFocusGameActor = null;

                        // Turn off 3d cursor since we don't need it.
                        parent.cursor3D.Deactivate();
                        if (parent.cursorClone != null)
                        {
                            parent.cursorClone.Deactivate();
                            parent.cursorClone = null;
                        }

                        break;
                    }

                    //
                    // 4) Follow mode caused by user controlled bot(s).
                    //
                    if (CameraInfo.MergedFollowList.Count > 0)
                    {
                        SetUpCameraFollowMode();

                        break;
                    }

                    //
                    // 5) Free!
                    //
                    // Not following an actor.
                    CameraInfo.Mode = CameraInfo.Modes.Edit;
                    CameraInfo.CameraFocusGameActor = null;

                    // Turn on 3d cursor in case we previously disabled it.
                    parent.cursor3D.Activate();
                    parent.CreateCursorClone();
                    parent.cursor3D.Hidden = false;

                    // We have no camera restrictions, so keep track of what the user is doing.
                    shared.camera.PlayValid      = true;
                    shared.camera.PlayCameraFrom = shared.camera.From;
                    shared.camera.PlayCameraAt   = shared.camera.At;

                    shared.camera.FollowCameraValid = false;


                    // Final break just to be sure the loop exits.
                    break;
                }

                //
                // Now that we're done, we need to check again to see if
                // we should be in FixedOffsetMode.
                //
                if (!Time.Paused && InGame.inGame.Terrain.FixedOffsetCamera && !CameraInfo.FirstPersonActive)
                {
                    CameraInfo.Mode = CameraInfo.Modes.FixedOffset;
                }

                // Zero out any offset while running.
                float t = Math.Min(Time.GameTimeFrameSeconds, 1.0f);
                shared.camera.HeightOffset = MyMath.Lerp(shared.camera.HeightOffset, 0.0f, t);

                //
                bool inputFocus = CommandStack.Peek() == commandMap;

                // Move the camera.
                switch (CameraInfo.Mode)
                {
                case CameraInfo.Modes.Edit:
                    MoveCameraEditMode(inputFocus, false);
                    break;

                case CameraInfo.Modes.Actor:
                    MoveCameraActorMode(true, false);
                    break;

                case CameraInfo.Modes.FixedTarget:
                    MoveCameraFixedTargetMode(inputFocus);
                    break;

                case CameraInfo.Modes.FixedOffset:
                    MoveCameraFixedOffsetMode(inputFocus);
                    break;

                case CameraInfo.Modes.MultiTarget:
                    MoveCameraMultiTargetMode(inputFocus, false);
                    break;
                }

                shared.camera.Update();

                // Update terrain.
                parent.terrain.Update(shared.camera);

                // Update the list of objects using our local camera.
                for (int i = 0; i < updateList.Count; i++)
                {
                    UpdateObject obj = (UpdateObject)updateList[i];
                    obj.Update();
                }
                parent.UpdateObjects();

                /// Pregame must update after parent.UpdateObjects, in case it
                /// decides to switchToMiniHub
                if (InGame.inGame.preGame != null)
                {
                    InGame.inGame.preGame.Update();
                }

                // Update the particle system.
                shared.particleSystemManager.Update();
                DistortionManager.Update();
                FirstPersonEffectMgr.Update();

                // This must be done after all brains are updated.
                Scoreboard.Update(shared.camera);

                // Update the TextDisplays.  Ignored if not active.
                shared.scrollableTextDisplay.Update(shared.camera);
                shared.smallTextDisplay.Update(shared.camera);

                VictoryOverlay.Update();

                // Do the input processing after object update because there will be order of operation issue if we don't
                //
                // Check if we have input focus.  Don't do any input
                // related update if we don't.
                if (inputFocus)
                {
                    // Grab the current state of the gamepad.
                    GamePadInput pad = GamePadInput.GetGamePad0();

                    // Switch to Mini-Hub?
                    if (Actions.MiniHub.WasPressed)
                    {
                        Actions.MiniHub.ClearAllWasPressedState();

                        //parent.ResetSim(CurrentLevelFilename());

                        // Needed to make sure that deactivated objects are actually removed from
                        // the list otherwise they may get saved along with the newly activated ones.
                        //parent.Refresh(BokuGame.gameListManager.updateList, BokuGame.gameListManager.renderList);

                        parent.SwitchToMiniHub();
                        return;
                    }

                    //handle swipe to return to edit for touch input
                    if (GamePadInput.ActiveMode == GamePadInput.InputMode.Touch)
                    {
                        SwipeGestureRecognizer swipeGesture = TouchGestureManager.Get().SwipeGesture;
                        if (swipeGesture.WasRecognized &&
                            swipeGesture.SwipeDirection == Directions.North)
                        {
#if NETFX_CORE
                            float halfWidth = (float)BokuGame.bokuGame.Window.ClientBounds.Width * 0.5f;
                            float height    = (float)BokuGame.bokuGame.Window.ClientBounds.Height;
#else
                            float halfWidth = (float)XNAControl.Instance.ClientSize.Width * 0.5f;
                            float height    = (float)XNAControl.Instance.ClientSize.Height;
#endif

                            //center half of the screen width-wise
                            float minX = halfWidth - (halfWidth * k_TouchExitAreaWidthPercent);
                            float maxX = halfWidth + (halfWidth * k_TouchExitAreaWidthPercent);

                            //bottom 20% height-wise
                            float minY = height - (height * k_TouchExitAreaHeightPercent);


                            Vector2 pos = swipeGesture.InitialPosition;
                            if (pos.X >= minX && pos.X <= maxX && pos.Y >= minY)
                            {
                                // User did a swipe from the bottom of the screen, enter edit mode
                                InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject;
                                InGame.inGame.CurrentUpdateMode = UpdateMode.TouchEdit;

                                Foley.PlayPressStart();
                                return;
                            }
                        }

                        // HACKHACK (****) Put in a tap recognizer since swipe seems to fail.
                        {
                            TapGestureRecognizer hackTapGesture = TouchGestureManager.Get().TapGesture;
                            if (hackTapGesture.WasTapped())
                            {
#if NETFX_CORE
                                float halfWidth = (float)BokuGame.bokuGame.Window.ClientBounds.Width * 0.5f;
                                float height    = (float)BokuGame.bokuGame.Window.ClientBounds.Height;
#else
                                float halfWidth = (float)XNAControl.Instance.ClientSize.Width * 0.5f;
                                float height    = (float)XNAControl.Instance.ClientSize.Height;
#endif

                                //center area of the screen width-wise
                                float minX = halfWidth - (halfWidth * 0.1f);
                                float maxX = halfWidth + (halfWidth * 0.1f);

                                //bottom 10% height-wise
                                float minY = height - (height * 0.1f);

                                Vector2 pos = hackTapGesture.Position;
                                if (pos.X >= minX && pos.X <= maxX && pos.Y >= minY)
                                {
                                    // User did a tap on the bottom of the screen, enter edit mode
                                    InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject;
                                    InGame.inGame.CurrentUpdateMode = UpdateMode.TouchEdit;

                                    Foley.PlayPressStart();
                                    return;
                                }
                            }
                        }
                    }

                    bool gameOver = VictoryOverlay.GameOver;

                    if (Time.Paused && !gameOver)
                    {
                        // We must be in user induced pause mode.
                        if (Actions.Unpause.WasPressed)
                        {
                            Actions.Unpause.ClearAllWasPressedState();

                            Time.Paused = false;
                            HelpOverlay.Pop();
                        }
                    }
                    else
                    {
                        if (gameOver)
                        {
                            // Game over man!  Let the user restart if they want.
                            if (Actions.Restart.WasPressed)
                            {
                                Actions.Restart.ClearAllWasPressedState();

                                InGame.inGame.ResetSim(preserveScores: false, removeCreatablesFromScene: true, keepPersistentScores: false);
                                // Since we're going right back into RunSim mode we need to first inline.
                                ApplyInlining();
                            }
                        }

                        // Open ToolMenu.
                        if (Actions.ToolMenu.WasPressed)
                        {
                            Actions.ToolMenu.ClearAllWasPressedState();

                            parent.CurrentUpdateMode = UpdateMode.ToolMenu;
                            Foley.PlayPressStart();
                            return;
                        }

                        // Pause?
                        // We want to make pause hard to get into so it requires both triggers and both stickButtons to be pressed.
                        if ((pad.LeftStickButton.IsPressed && pad.RightStickButton.IsPressed && pad.LeftTriggerButton.IsPressed && pad.RightTriggerButton.IsPressed) || Actions.Pause.WasPressed)
                        {
                            Actions.Pause.ClearAllWasPressedState();

                            if (!Time.Paused)
                            {
                                Time.Paused = true;
                                HelpOverlay.Push("PauseGame");
                                GamePadInput.GetGamePad0().IgnoreLeftStickUntilZero();
                                GamePadInput.GetGamePad0().IgnoreRightStickUntilZero();
                            }
                        }
                    }
                }

                // Force the the HelpOverlay to be correct.
                if (!Time.Paused || VictoryOverlay.Active)
                {
                    if (InGame.inGame.PreGame != null && InGame.inGame.PreGame.Active)
                    {
                        if (HelpOverlay.Depth() != 1 || HelpOverlay.Peek() != "RunSimulationPreGame")
                        {
                            HelpOverlay.Clear();
                            HelpOverlay.Push("RunSimulationPreGame");
                        }
                    }
                    else
                    {
                        if (HelpOverlay.Depth() != 1 || HelpOverlay.Peek() != "RunSimulation")
                        {
                            HelpOverlay.Clear();
                            HelpOverlay.Push("RunSimulation");
                        }
                    }
                }
                else
                {
                    // We're paused.
                    if (HelpOverlay.Depth() != 2 || HelpOverlay.Peek(1) != "RunSimulation")
                    {
                        HelpOverlay.Clear();
                        HelpOverlay.Push("RunSimulation");
                        HelpOverlay.Push("PauseGame");
                    }
                }

                // When in run mode, allow the user to click on the "Press [esc] to edit" text as if it was a button.
                if (MouseInput.Left.WasPressed)
                {
                    Point mousePos = MouseInput.Position;
                    if (HelpOverlay.MouseHitBottomText(mousePos))
                    {
                        // Switch to edit mode.
                        InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject;
                    }
                }
                TapGestureRecognizer tapGesture = TouchGestureManager.Get().TapGesture;
                if (tapGesture.WasTapped())
                {
                    // JW - Until we have proper Touch help overlays, we are still using the mouse/keyboard
                    // overlays. The mouse handling code for these depends on being able to 'absorb' pressed
                    // info to hide it from later callers. Our touch stuff doesn't (and really shouldn't)
                    // do this. So, we handle cases here based on what type of overlay is being displayed.
                    if (HelpOverlay.Peek() == "RunSimulationPreGame")
                    {
                        // Tap during instructions: just begin game.
                        InGame.inGame.PreGame.Active = false;
                    }

                    // Also test if running sim for tapping on "tap to edit" at bottom.
                    if (HelpOverlay.Peek() == "RunSimulation")
                    {
                        Point pos = new Point((int)tapGesture.Position.X, (int)tapGesture.Position.Y);
                        if (HelpOverlay.MouseHitBottomText(pos))
                        {
                            // Switch to edit mode.
                            InGame.inGame.CurrentUpdateMode = UpdateMode.EditObject;
                        }
                    }
                }
            }   // end of RunSimUpdateObj Update()
示例#4
0
        private void HandleMouseInput(Camera uicamera)
        {
            if (GamePadInput.ActiveMode != GamePadInput.InputMode.KeyboardMouse)
            {
                return;
            }

            // If the mouse took over from the touch, it should clear any
            // highlights the touch had going.
            Boku.InGame.inGame.TouchEdit.Clear();

            Camera    camera    = Boku.InGame.inGame.shared.camera;
            MouseEdit mouseEdit = Boku.InGame.inGame.MouseEdit;

            MouseEdit.MouseHitInfo hitInfo = null;

            hitInfo = MouseEdit.HitInfo;
            mouseEdit.DoObject(camera);

            if (hitInfo.HaveActor)
            {
                FocusActor      = hitInfo.ActorHit;
                focusColorIndex = ColorPalette.GetIndexFromColor(FocusActor.Classification.Color);
                Boku.InGame.ColorPalette.Active = true;
            }
            else
            {
                FocusActor = null;
                Boku.InGame.ColorPalette.Active = false;
            }

            if (MouseInput.Left.WasReleased)
            {
                selectedActor = null;
            }

            //don't add if we detected a paste
            if (MouseInput.Left.WasPressed && !MenusActive && (mouseEdit.MiddleAction != true))
            {
                MouseInput.Left.ClearAllWasPressedState();

                if (FocusActor != null)
                {
                    // Start draggin if over actor.
                    selectedActor = FocusActor;
                    actorOffset   = selectedActor.Movement.Position - hitInfo.TerrainPosition;
                }
                else if (!MenusActive && !SliderActive && inGame.editObjectUpdateObj.newItemSelectorShim.State != UIShim.States.Active)
                {
                    // No actor in focus so activate AddItem menu.
                    Vector2 position = new Vector2(hitInfo.TerrainPosition.X, hitInfo.TerrainPosition.Y);
                    inGame.editObjectUpdateObj.ActivateNewItemSelector(position, true);
                }
            }

            if (MouseInput.Left.IsPressed &&
                (selectedActor != null) &&
                (hitInfo != null))
            {
                Vector3 position = hitInfo.TerrainPosition + actorOffset;
                selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);

                // Try and keep the bot directly under the mouse cursor while still being at the correct height.
                // A possible alternative would be to use the cursor's 2d position for the bot and just have the
                // bot float at the appropriate height over the cursor.  This would allow more exact placement of
                // bots over terrain but it would mean a visual disconnect between where the cursor is and where
                // the bot is.  There would also be a jump when the bot is first clicked on since the terrain
                // position of the cursor is most likely further back than the bot's current position.
                if (hitInfo.VerticalOffset == 0.0f)
                {
                    Vector3 terrainToCameraDir = hitInfo.TerrainPosition - camera.From;
                    terrainToCameraDir.Normalize();
                    position = hitInfo.TerrainPosition + terrainToCameraDir * (selectedActor.EditHeight / terrainToCameraDir.Z);
                    selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);
                }

                // If the actor is supposed to stay above water, try to enforce that.
                // This can have some strange visual effects since it forces the actor to
                // float above where the mouse cursor is but the alternative is to have
                // actor get dragged under water.
                if (selectedActor.StayAboveWater)
                {
                    float waterAlt = Terrain.GetWaterBase(position);
                    if (waterAlt != 0)
                    {
                        position.Z = waterAlt + selectedActor.EditHeight;
                        selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);
                    }
                }

                Boku.InGame.IsLevelDirty = true;
            }

            if (MouseInput.Right.WasReleased)
            {
                menuActor          = FocusActor;
                menuCursorPosition = hitInfo.TerrainPosition;

                // We need to do this repeatedly since the Paste option will
                // change depending on what's in the cut/paste buffer.
                SetUpMenus();

                if (FocusActor == null)
                {
                    actorMenu.Deactivate();
                    noActorMenu.Activate(new Vector2(MouseInput.Position.X, MouseInput.Position.Y));
                }
                else
                {
                    noActorMenu.Deactivate();
                    actorMenu.Activate(new Vector2(MouseInput.Position.X, MouseInput.Position.Y));
                    // Turn off any thought balloons so they don't clutter the menu.
                    ThoughtBalloonManager.RemoveThoughts(FocusActor);
                }
            }

            noActorMenu.Update();
            actorMenu.Update();

            // Support for changing tree types via up/down arrow keys.
            if (FocusActor != null && FocusActor.Classification.name == "tree")
            {
                inGame.editObjectUpdateObj.MakeTreeChange(FocusActor);
            }

            // Color palette support.
            if (FocusActor != null && !MenusActive && !sliderActive)
            {
                int numColors = Boku.InGame.ColorPalette.NumEntries;
                if (Actions.Left.WasPressedOrRepeat)
                {
                    focusColorIndex       = (focusColorIndex + numColors - 1) % numColors;
                    shared.curObjectColor = focusColorIndex;
                    FocusActor.ClassColor = ColorPalette.GetColorFromIndex(focusColorIndex);
                    Foley.PlayColorChange();
                    Boku.InGame.IsLevelDirty = true;
                }
                if (Actions.Right.WasPressedOrRepeat)
                {
                    focusColorIndex       = (focusColorIndex + 1) % numColors;
                    shared.curObjectColor = focusColorIndex;
                    FocusActor.ClassColor = ColorPalette.GetColorFromIndex(focusColorIndex);
                    Foley.PlayColorChange();
                    Boku.InGame.IsLevelDirty = true;
                }
            }

            // Align NSEW
            if (FocusActor != null && !MenusActive && !sliderActive)
            {
                if (Actions.Up.WasPressedOrRepeat)
                {
                    // Rotate clockwise.
                    float targetRotation = MathHelper.PiOver2 * (int)((FocusActor.Movement.RotationZ + MathHelper.TwoPi - 0.0001f) / MathHelper.PiOver2);
                    FocusActor.Movement.RotationZ = targetRotation;
                    Foley.PlayClickUp();
                    Boku.InGame.IsLevelDirty = true;
                }
                if (Actions.Down.WasPressedOrRepeat)
                {
                    // Rotate counter-clockwise.
                    float targetRotation = MathHelper.PiOver2 * (int)((FocusActor.Movement.RotationZ + MathHelper.PiOver2 + 0.0001f) / MathHelper.PiOver2);
                    FocusActor.Movement.RotationZ = targetRotation;
                    Foley.PlayClickDown();
                    Boku.InGame.IsLevelDirty = true;
                }
            }

            // Cut/Copy/Paste via keyboard.
            if (Actions.Cut.WasPressed && FocusActor != null)
            {
                inGame.editObjectUpdateObj.CutAction(FocusActor);
            }
            if (Actions.Copy.WasPressed && FocusActor != null)
            {
                inGame.editObjectUpdateObj.CopyAction(FocusActor);
            }
            if (Actions.Paste.WasPressed)
            {
                inGame.editObjectUpdateObj.PasteAction(null, hitInfo.TerrainPosition);
            }

            //
            // Figure out help overlay mode.
            //
            if (inGame.editObjectUpdateObj.newItemSelectorShim.State == UIShim.States.Active)
            {
                // The pie menu is active.
                HelpOverlay.ReplaceTop("MouseObjectEditAddItemMenu");
            }
            else if (hitInfo != null && hitInfo.HaveActor)
            {
                // We have an actor in focus.
                if (FocusActor != null && FocusActor.Classification.name == "tree")
                {
                    HelpOverlay.ReplaceTop("MouseEditEditObjectFocusTree");
                }
                else
                {
                    HelpOverlay.ReplaceTop("MouseEditEditObjectFocus");
                }
            }
        }
示例#5
0
        private void HandleTouchInput(Camera uicamera)
        {
            //TODO: this method is now extremely unwieldly - now that we have the basics down, refactor and consolidate the various checks
            if (GamePadInput.ActiveMode != GamePadInput.InputMode.Touch)
            {
                return;
            }

            // If the mouse took over from the touch, it should clear any
            // highlights the touch had going.
            Boku.InGame.inGame.MouseEdit.Clear();

            Camera    camera    = Boku.InGame.inGame.shared.camera;
            TouchEdit touchEdit = Boku.InGame.inGame.TouchEdit;

            TouchEdit.TouchHitInfo hitInfo = null;

            //keep track of previous focus actor for comparisons this frame
            GameActor previousFocusActor = FocusActor;

            hitInfo = TouchEdit.HitInfo;

            //Check for color pallet hits
            if (Boku.InGame.ColorPalette.Active && (FocusActor != null) && !actorMenu.Active && !noActorMenu.Active)
            {
                Classification.Colors touchColor = Boku.InGame.ColorPalette.GetColorFromTouch();
                if ((touchColor != Classification.Colors.None) && (FocusActor.ClassColor != touchColor))
                {
                    FocusActor.ClassColor = touchColor;
                    focusColorIndex       = ColorPalette.GetIndexFromColor(touchColor);
                    Foley.PlayColorChange();
                    Boku.InGame.IsLevelDirty = true;
                }
                // For the duration of the color palette handling touch, all touch inputs are deferred.
                if (Boku.InGame.ColorPalette.HandlingTouch)
                {
                    return;
                }
            }

            bool hasNonUITouch = touchEdit.HasNonUITouch();
            bool hasValidTap   = TouchGestureManager.Get().TapGesture.WasValidEditObjectTap;

            touchEdit.DoObject(camera);

            //check for tap to adjust hit actor
            if (hasValidTap ||
                TouchGestureManager.Get().DoubleTapGesture.WasRecognized ||
                TouchGestureManager.Get().TouchHoldGesture.WasRecognized ||
                TouchGestureManager.Get().TouchHoldGesture.SlightHoldMade ||
                (TouchGestureManager.Get().DragGesture.IsDragging&& TouchInput.InitialActorHit != null))
            {
                if (hasNonUITouch && TouchGestureManager.Get().DragGesture.IsDragging&& TouchInput.InitialActorHit != null)
                {
                    FocusActor      = TouchInput.InitialActorHit;
                    focusColorIndex = ColorPalette.GetIndexFromColor(FocusActor.Classification.Color);
                    Boku.InGame.ColorPalette.Active = true;
                }
                else if (hasNonUITouch && hitInfo.HaveActor)
                {
                    FocusActor      = hitInfo.ActorHit;
                    focusColorIndex = ColorPalette.GetIndexFromColor(FocusActor.Classification.Color);
                    Boku.InGame.ColorPalette.Active = true;
                }
                else
                {
                    FocusActor = null;
                    Boku.InGame.ColorPalette.Active = false;
                }
            }

            //check for double tap on terrain to bring up add actor
            if (hasNonUITouch &&
                TouchGestureManager.Get().DoubleTapGesture.WasRecognized&&
                FocusActor == null &&
                !MenusActive && !SliderActive && inGame.editObjectUpdateObj.newItemSelectorShim.State != UIShim.States.Active)
            {
                // No actor in focus so activate AddItem menu.
                Vector2 position = new Vector2(hitInfo.TerrainPosition.X, hitInfo.TerrainPosition.Y);
                inGame.editObjectUpdateObj.ActivateNewItemSelector(position, true);
            }

            //handle dragging an actor
            if (TouchGestureManager.Get().DragGesture.IsDragging&& TouchInput.InitialActorHit != null && FocusActor != null)
            {
                //clear out menu if up
                actorMenu.Deactivate();
                noActorMenu.Deactivate();

                //select the focus actor when we start dragging
                if (selectedActor == null)
                {
                    // Start draggin if over actor.
                    selectedActor = FocusActor;
                    actorOffset   = selectedActor.Movement.Position - hitInfo.TerrainPosition;
                }

                Vector3 position = hitInfo.TerrainPosition + actorOffset;
                selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);

                // Try and keep the bot directly under the mouse cursor while still being at the correct height.
                // A possible alternative would be to use the cursor's 2d position for the bot and just have the
                // bot float at the appropriate height over the cursor.  This would allow more exact placement of
                // bots over terrain but it would mean a visual disconnect between where the cursor is and where
                // the bot is.  There would also be a jump when the bot is first clicked on since the terrain
                // position of the cursor is most likely further back than the bot's current position.
                if (hitInfo.VerticalOffset == 0.0f)
                {
                    Vector3 terrainToCameraDir = hitInfo.TerrainPosition - camera.From;
                    terrainToCameraDir.Normalize();
                    position = hitInfo.TerrainPosition + terrainToCameraDir * (selectedActor.EditHeight / terrainToCameraDir.Z);
                    selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);
                }

                // If the actor is supposed to stay above water, try to enforce that.
                // This can have some strange visual effects since it forces the actor to
                // float above where the mouse cursor is but the alternative is to have
                // actor get dragged under water.
                if (selectedActor.StayAboveWater)
                {
                    float waterAlt = Terrain.GetWaterBase(position);
                    if (waterAlt != 0)
                    {
                        position.Z = waterAlt + selectedActor.EditHeight;
                        selectedActor.Movement.Position = Boku.InGame.SnapPosition(position);
                    }
                }

                Boku.InGame.IsLevelDirty = true;
            }
            else
            {
                selectedActor = null;


                //rules for context menus:
                // tap + hold -> always bring up menu (terrain or actor accordingly)
                // double tap -> bring up menu if over an actor (actor only)
                // single tap -> bring up menu if over an actor that was already selected (actor only)
                if (hasNonUITouch &&
                    (TouchGestureManager.Get().TouchHoldGesture.WasRecognized ||
                     (FocusActor != null && TouchGestureManager.Get().DoubleTapGesture.WasRecognized) ||
                     (FocusActor != null && hasValidTap && FocusActor == previousFocusActor)))
                {
                    menuActor          = FocusActor;
                    menuCursorPosition = hitInfo.TerrainPosition;

                    // We need to do this repeatedly since the Paste option will
                    // change depending on what's in the cut/paste buffer.
                    SetUpMenus();

                    if (FocusActor == null)
                    {
                        actorMenu.Deactivate();
                        noActorMenu.Activate(TouchInput.GetOldestTouch().position);
                    }
                    else
                    {
                        noActorMenu.Deactivate();
                        actorMenu.Activate(TouchInput.GetOldestTouch().position);
                        // Turn off any thought balloons so they don't clutter the menu.
                        ThoughtBalloonManager.RemoveThoughts(FocusActor);
                    }
                }

                // Handle two finger actions. Only enabled when not dragging.
                if (hasNonUITouch && TouchInput.TouchCount == 2 && selectedActor == null)
                {
                    PinchGestureRecognizer pinchGesture = TouchGestureManager.Get().GetActiveGesture(TouchGestureType.Pinch, TouchGestureType.Rotate) as PinchGestureRecognizer;
                    if (pinchGesture != null && pinchGesture.IsPinching)
                    {
                        //Debug.WriteLine("Pinching... Scale: "+ pinchGesture.Scale );
                        DoScaleActor(pinchGesture.DeltaScale, FocusActor);
                    }

                    RotationGestureRecognizer rotationGesture = TouchGestureManager.Get().GetActiveGesture(TouchGestureType.Rotate, TouchGestureType.Pinch) as RotationGestureRecognizer;
                    if (null != rotationGesture && rotationGesture.IsRotating)
                    {
                        DoRotateActor(rotationGesture.RotationDelta, FocusActor);
                    }
                }
            }

            if (TouchGestureManager.Get().RotateGesture.IsValidated ||
                TouchGestureManager.Get().PinchGesture.IsValidated ||
                TouchGestureManager.Get().DoubleDragGesture.IsValidated)
            {
                //turn off menu if rotating, pinching or double dragging (i.e. terrain manipulation)
                actorMenu.Deactivate();
                noActorMenu.Deactivate();
            }

            noActorMenu.Update();
            actorMenu.Update();

            // Support for changing tree types via up/down arrow keys.
            if (FocusActor != null && FocusActor.Classification.name == "tree")
            {
                inGame.editObjectUpdateObj.MakeTreeChange(FocusActor);
            }

            //
            // Figure out help overlay mode.
            //
            if (inGame.editObjectUpdateObj.newItemSelectorShim.State == UIShim.States.Active)
            {
                // The pie menu is active.
                HelpOverlay.ReplaceTop("MouseEditAddItemMenu");
            }
            else if (hitInfo != null && hitInfo.HaveActor)
            {
                // We have an actor in focus.
                if (FocusActor != null && FocusActor.Classification.name == "tree")
                {
                    HelpOverlay.ReplaceTop("MouseEditEditObjectFocusTree");
                }
                else
                {
                    HelpOverlay.ReplaceTop("MouseEditEditObjectFocus");
                }
            }
        }