private void UpdateKeyboardMouse() { Camera camera = Boku.InGame.inGame.shared.camera; MouseEdit mouseEdit = Boku.InGame.inGame.MouseEdit; MouseEdit.MouseHitInfo hitInfo = MouseEdit.HitInfo; // Don't update mouseOver if the menus are active. This way the focus state will be preserved. if (!MenusActive && !SliderActive) { mouseOver.ActOnPath = KeyboardInput.ShiftIsPressed; mouseOver.Update(inGame, camera); // If the user presses the left button while not over anything // start adding a plain path. if (!mouseOver.Adding && !mouseOver.Adjusting && MouseInput.Left.WasPressed) { Road.GenIndex = 0; mouseOver.NewPath(hitInfo.TerrainPosition, focusColorIndex); } } // Check for Escape to cancel adding. // Also allow clicking the right button to cancel. if (mouseOver.Adding && (Actions.Cancel.WasPressed || MouseInput.Right.WasPressed)) { Actions.Cancel.ClearAllWasPressedState(); MouseInput.Right.ClearAllWasPressedState(); if (mouseOver.Adding) { mouseOver.StopAdding(); } } // Check to see if any of the menus need activating. if (MouseInput.Right.WasPressed) { // The menus may change depending on whether or not the full path is selected. SetUpMenus(); if (mouseOver.Over) { if (mouseOver.node != null) { nodeMenu.Activate(new Vector2(MouseInput.Position.X, MouseInput.Position.Y)); } if (mouseOver.edge != null) { edgeMenu.Activate(new Vector2(MouseInput.Position.X, MouseInput.Position.Y)); } } else { groundMenu.Activate(new Vector2(MouseInput.Position.X, MouseInput.Position.Y)); menuPosition = hitInfo.TerrainPosition; } } groundMenu.Update(); nodeMenu.Update(); edgeMenu.Update(); // See if we've tried to change path types. if (mouseOver.Over && mouseOver.Path != null && mouseOver.node != null && !MenusActive && !sliderActive) { if (Actions.Up.WasPressedOrRepeat) { mouseOver.Path.Road.AdvanceGen(1); } if (Actions.Down.WasPressedOrRepeat) { mouseOver.Path.Road.AdvanceGen(-1); } } // Change edge direction? if (mouseOver.Over && mouseOver.Path != null && mouseOver.edge != null) { if (Actions.Up.WasPressedOrRepeat) { if (mouseOver.ActOnPath) { mouseOver.Path.IncDir(); } else { mouseOver.edge.IncDir(); } } if (Actions.Down.WasPressedOrRepeat) { if (mouseOver.ActOnPath) { mouseOver.Path.DecDir(); } else { mouseOver.edge.DecDir(); } } } // Color palette support. if (mouseOver.Over && mouseOver.Path != null && !MenusActive && !sliderActive) { focusColorIndex = ColorPalette.GetIndexFromColor(mouseOver.Path.Color); Boku.InGame.ColorPalette.Active = true; int numColors = Boku.InGame.ColorPalette.NumEntries; if (Actions.Left.WasPressedOrRepeat) { focusColorIndex = (focusColorIndex + numColors - 1) % numColors; mouseOver.Path.Color = ColorPalette.GetColorFromIndex(focusColorIndex); Foley.PlayColorChange(); Boku.InGame.IsLevelDirty = true; } if (Actions.Right.WasPressedOrRepeat) { focusColorIndex = (focusColorIndex + 1) % numColors; mouseOver.Path.Color = ColorPalette.GetColorFromIndex(focusColorIndex); Foley.PlayColorChange(); Boku.InGame.IsLevelDirty = true; } } else { Boku.InGame.ColorPalette.Active = false; } // // Set up correct HelpOverlay // if (mouseOver.Over) { if (mouseOver.ActOnPath) { HelpOverlay.ReplaceTop("MouseEditPathsFocusPath"); } else if (mouseOver.node != null) { HelpOverlay.ReplaceTop("MouseEditPathsFocusNode"); } else if (mouseOver.edge != null) { HelpOverlay.ReplaceTop("MouseEditPathsFocusEdge"); } } }
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"); } } }
} // end of Update() private void UpdateTouch() { Camera camera = Boku.InGame.inGame.shared.camera; TouchEdit touchEdit = Boku.InGame.inGame.TouchEdit; TouchEdit.TouchHitInfo hitInfo = TouchEdit.HitInfo; // Don't update touchOver if the menus are active. This way the focus state will be preserved. if (!MenusActive && !SliderActive) { //handle color palette interactions if (touchOver.Over && touchOver.Path != null) { //set target color focusColorIndex = ColorPalette.GetIndexFromColor(touchOver.Path.Color); Boku.InGame.ColorPalette.Active = true; //check for touch on a new color Classification.Colors touchColor = Boku.InGame.ColorPalette.GetColorFromTouch(); if ((touchColor != Classification.Colors.None) && (touchOver.Path.Color != touchColor)) { touchOver.Path.Color = 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; } } else { //no path selected, hide the palette Boku.InGame.ColorPalette.Active = false; } //clear selections if menu options change if (TouchInput.WasTouched && !Boku.InGame.inGame.TouchEdit.HasNonUITouch()) { touchOver.Clear(); } //adding/adjusting flags may change with update - but we don't want to allow a new path if we entered the update in //one of these modes bool allowNewPath = !touchOver.Adding && !touchOver.Adjusting; touchOver.Update(inGame, camera); // If the user presses the left button while not over anything // start adding a plain path. if (allowNewPath && !touchOver.Adding && !touchOver.Adjusting && TouchGestureManager.Get().TapGesture.WasRecognized&& Boku.InGame.inGame.touchEditUpdateObj.ToolBar.IsButtonActionToggledOn(ToolBar.TouchControls.BrushActionIDs.baNode) && Boku.InGame.inGame.TouchEdit.HasNonUITouch()) { Road.GenIndex = 0; touchOver.NewPath(hitInfo.TerrainPosition, focusColorIndex); } } //We stop adding in touch mode when the add node button is toggled off if (touchOver.Adding && !Boku.InGame.inGame.touchEditUpdateObj.ToolBar.IsButtonActionToggledOn(ToolBar.TouchControls.BrushActionIDs.baNode)) { touchOver.StopAdding(); } // Check to see if any of the menus need activating. if (TouchGestureManager.Get().TouchHoldGesture.WasRecognized&& Boku.InGame.inGame.TouchEdit.HasNonUITouch()) { // The menus may change depending on whether or not the full path is selected. SetUpMenus(); if (touchOver.Over) { if (touchOver.node != null) { nodeMenu.Activate(TouchInput.GetOldestTouch().position); } if (touchOver.edge != null) { edgeMenu.Activate(TouchInput.GetOldestTouch().position); } } else { groundMenu.Activate(TouchInput.GetOldestTouch().position); menuPosition = hitInfo.TerrainPosition; } } 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) groundMenu.Deactivate(); nodeMenu.Deactivate(); edgeMenu.Deactivate(); } groundMenu.Update(); nodeMenu.Update(); edgeMenu.Update(); // Change edge direction? if (touchOver.Over && touchOver.Path != null && touchOver.edge != null) { //direction change via double tap if (TouchGestureManager.Get().DoubleTapGesture.WasRecognized) { if (touchOver.ActOnPath) { touchOver.Path.IncDir(); } else { touchOver.edge.IncDir(); } } } // // Set up correct HelpOverlay // if (touchOver.Over) { if (touchOver.ActOnPath) { HelpOverlay.ReplaceTop("MouseEditPathsFocusPath"); } else if (touchOver.node != null) { HelpOverlay.ReplaceTop("MouseEditPathsFocusNode"); } else if (touchOver.edge != null) { HelpOverlay.ReplaceTop("MouseEditPathsFocusEdge"); } } }
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"); } } }