bool OnTrigger() { if (waitingToStopMove) { return(false); } if (GizmoCheck()) { StartMove(); return(true); } else if (hoverActor != null && !hoverActor.IsLockedByAnother()) { bool addedOrPresent = editMain.AddSetOrRemoveTargetActor(hoverActor); if (addedOrPresent) { gizmoAxis = GizmoAxis.Center; gizmoSelectionFeedback.SetActor(GetFocusActor()); StartMove(); } return(true); } else { if (!Util.HoldingModiferKeys()) { editMain.ClearTargetActors(); gizmoSelectionFeedback.SetActor(GetFocusActor()); } return(false); } }
/// <summary> /// Sets the color for the specified gizmo axis. If 'GizmoAxis.None' is /// specified, the method will have no effect. /// </summary> public void SetAxisColor(GizmoAxis axis, Color color) { if (axis == GizmoAxis.None) { return; } _axesColors[(int)axis] = color; }
/// <summary> /// Returns the color for the specified gizmo axis. If 'GizmoAxis.None' is /// specified, black will be returned. /// </summary> public Color GetAxisColor(GizmoAxis axis) { if (axis == GizmoAxis.None) { return(Color.black); } return(_axesColors[(int)axis]); }
private void StartDrag(GizmoAxis axis, Vector2 currentPosition) { this._previousButtonState = ButtonState.Pressed; this._unmovedWorldPosition = currentPosition; this.CurrentAxis = axis; System.Windows.Input.Mouse.OverrideCursor = Cursors.SizeAll; this.XAxisColor = new Color(this.XAxisColor, 0.5f); this.YAxisColor = new Color(this.YAxisColor, 0.5f); }
private void clearSelection(TabPanelData data) { //clear out the previous selection data.mWorld.selectAxis(GizmoAxis.GizmoAxis_None); mHighlightedAxis = GizmoAxis.GizmoAxis_None; if (data.mSelectedEntity != null) { data.mWorld.deselectEntity(data.mSelectedEntity); data.mSelectedEntity = null; } propertyGrid1.SelectedObject = null; }
/// <summary> /// Event handler for angle input fields. /// </summary> /// <param name="axis">Axis.</param> void InputValueChanged(GizmoAxis axis) { Vector3 angles; float.TryParse(xInput.text, out angles.x); float.TryParse(yInput.text, out angles.y); float.TryParse(zInput.text, out angles.z); var rotationCenter = Multitool.instance.GetBounds().center; var euler = selected[0].transform.rotation.eulerAngles; selected[0].transform.RotateAround(rotationCenter, Vector3.right, angles.x - euler.x); selected[0].transform.RotateAround(rotationCenter, Vector3.up, angles.y - euler.y); selected[0].transform.RotateAround(rotationCenter, Vector3.forward, angles.z - euler.z); }
/// <summary> /// Helper method for applying color to the gizmo lines. /// </summary> private void ApplyColor(GizmoAxis axis, Color color) { switch (ActiveMode) { case GizmoMode.NonUniformScale: case GizmoMode.Translate: switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; } break; case GizmoMode.Rotate: switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; } break; case GizmoMode.UniformScale: ApplyLineColor(0, _translationLineVertices.Length, ActiveAxis == GizmoAxis.None ? _axisColors[0] : _highlightColor); break; } }
/// <summary> /// Per-frame check to see if mouse is hovering over any axis. /// </summary> private void SelectAxis(Vector2 mousePosition) { if (!Enabled) { return; } float closestintersection = float.MaxValue; Ray ray = _camera.CreateCameraRay(mousePosition); var intersection = XSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = YSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = ZSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } if (closestintersection >= float.MaxValue || closestintersection <= float.MinValue) { ActiveAxis = GizmoAxis.None; } }
public void ActivateAxis(GizmoAxis axis) { switch (axis) { case GizmoAxis.Center: AxisCenter.SetActive(true); break; case GizmoAxis.X: AxisX.SetActive(true); break; case GizmoAxis.Y: AxisY.SetActive(true); break; case GizmoAxis.Z: AxisZ.SetActive(true); break; } SetType(Type); }
/// <summary> /// Given a specified axis, the method will return its corresponding plane normal which is most /// aligned with the camera look vector. This is necessary when performing a translation or scale /// along a certain gizmo axis. Normally, we could just use a single plane for each axis (e.g. for /// the X axis we could always use the XY plane), but depending on the camera rotation, this can /// produce some unwanted effects. The method allows us to eliminate them by choosing the plane /// normal most aligned with the camera look vector. /// </summary> protected Vector3 GetAxisPlaneNormalMostAlignedWithCameraLook(GizmoAxis gizmoAxis) { float bestAbsDotProduct = 0.0f; Vector3 bestPlaneNormal = _gizmoTransform.forward; // Each axis has a set of 2 possible plane normals that can be used. These are: // a) X axis (XY and XZ plane normals); // b) Y axis (XY and YZ plane normals); // c) Z axis (YZ and XZ plane normals). Vector3[] planeNormals; if (gizmoAxis == GizmoAxis.X) { planeNormals = new Vector3[] { _gizmoTransform.forward, _gizmoTransform.up } } ; else if (gizmoAxis == GizmoAxis.Y) { planeNormals = new Vector3[] { _gizmoTransform.forward, _gizmoTransform.right } } ; else { planeNormals = new Vector3[] { _gizmoTransform.right, _gizmoTransform.up } }; // Now loop through all possible plane normals for the specified input axis and choose the // one which is most aligned with the camera look vector. for (int normalIndex = 0; normalIndex < 2; ++normalIndex) { // The most aligned axis is the one whose dot product with the camera look vector is // the closest to 1. We will use the absolute value of the dot product since the direction // doesn't matter. float absDotProduct = Mathf.Abs(Vector3.Dot(_cameraTransform.forward, planeNormals[normalIndex])); if (absDotProduct > bestAbsDotProduct) { bestAbsDotProduct = absDotProduct; bestPlaneNormal = planeNormals[normalIndex]; } } return(bestPlaneNormal); }
protected void SelectAxis(GizmoAxis axis) { if (axis != _selectedAxis) { _selectedAxis = axis; if (axis != GizmoAxis.None) { if (OnHighlight != null) { OnHighlight(); } } else { if (OnUnHighlight != null) { OnUnHighlight(); } } } }
public void DeactivateAxis(GizmoAxis axis) { switch (axis) { case GizmoAxis.Center: AxisCenter.SetActive(false); break; case GizmoAxis.X: AxisX.SetActive(false); break; case GizmoAxis.Y: AxisY.SetActive(false); break; case GizmoAxis.Z: AxisZ.SetActive(false); break; } SetType(Type); }
private bool GizmoCheck() { if (editMain.GetTargetActorsCount() == 0) { return(false); } RaycastHit[] hits; hits = Physics.RaycastAll(editMain.GetCursorRay()); for (int i = 0; i < hits.Length; i++) { if (hits[i].collider == xCollider) { gizmoAxis = GizmoAxis.X; return(true); } if (hits[i].collider == yCollider) { gizmoAxis = GizmoAxis.Y; return(true); } if (hits[i].collider == zCollider) { gizmoAxis = GizmoAxis.Z; return(true); } if (hits[i].collider == centerCollider) { gizmoAxis = GizmoAxis.Center; return(true); } } gizmoAxis = GizmoAxis.None; return(false); }
void MoveFocusedActorOnAxis(GizmoAxis axis) { Ray ray = editMain.GetCursorRay(); Ray axisRay = zAxisRay; Vector3 offset = zAxisRayOffset; SnapAxis snapAxis = SnapAxis.Horizontal; if (axis == GizmoAxis.Y) { snapAxis = SnapAxis.Vertical; axisRay = yAxisRay; offset = yAxisRayOffset; } else if (axis == GizmoAxis.X) { axisRay = xAxisRay; offset = xAxisRayOffset; } Vector3 point = Util.GetClosestPointOnRayFromRay(axisRay, ray) - offset; SetFocusedActorPositionWithChecks(point, snapAxis); }
void Update() { if (Input.GetMouseButtonDown(1)) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 1000f, layer)) { if (hit.transform.parent == transform) { ChangeMode(); } } } if (Input.GetMouseButtonDown(0)) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); dragplane = new Plane(); if (Physics.Raycast(ray, out hit, 1000f, layer)) { hitvector = hit.point - transform.position; if (hit.collider == xAxis) { selectedAxis = GizmoAxis.X; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == yAxis) { selectedAxis = GizmoAxis.Y; dragplane.SetNormalAndPosition(transform.forward, transform.position); } else if (hit.collider == zAxis) { selectedAxis = GizmoAxis.Z; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == xyPlane) { selectedAxis = GizmoAxis.XY; dragplane.SetNormalAndPosition(transform.forward, transform.position); } else if (hit.collider == xzPlane) { selectedAxis = GizmoAxis.XZ; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == yzPlane) { selectedAxis = GizmoAxis.YZ; dragplane.SetNormalAndPosition(transform.right, transform.position); } else if (hit.collider == xyRotate) { selectedAxis = GizmoAxis.XYRotate; rotationAxis = -transform.forward; lookHitPoint = hit.point - transform.position - Vector3.Project(hit.point - transform.position, transform.forward); //Debug.DrawLine(transform.position, transform.position + lookHitPoint, Color.cyan, 10.0f); dragplane.SetNormalAndPosition(lookHitPoint, hit.point); //DrawPlane(lookHitPoint, transform.position + lookHitPoint, 10.0f); rotating = true; } else if (hit.collider == xzRotate) { selectedAxis = GizmoAxis.XZRotate; rotationAxis = -transform.up; lookHitPoint = hit.point - transform.position - Vector3.Project(hit.point - transform.position, transform.up); //Debug.DrawLine(transform.position, transform.position + lookHitPoint, Color.cyan, 10.0f); dragplane.SetNormalAndPosition(lookHitPoint, hit.point); //DrawPlane(lookHitPoint, transform.position + lookHitPoint, 10.0f); rotating = true; } else if (hit.collider == yzRotate) { selectedAxis = GizmoAxis.YZRotate; rotationAxis = -transform.right; lookHitPoint = hit.point - transform.position - Vector3.Project(hit.point - transform.position, transform.right); //Debug.DrawLine(transform.position, transform.position + lookHitPoint, Color.cyan, 10.0f); dragplane.SetNormalAndPosition(lookHitPoint, hit.point); //DrawPlane(lookHitPoint, transform.position + lookHitPoint, 10.0f); rotating = true; } else if (hit.collider == sphereRotate) { selectedAxis = GizmoAxis.none; lookCamera = Camera.main.transform.position - transform.position; startDragRot = transform.position + lookCamera.normalized * sphereRadius; dragplane.SetNormalAndPosition(lookCamera.normalized, startDragRot); //DrawPlane(lookCamera.normalized, startDragRot, 10.0f); rotating = true; } else { Debug.Log(hit.collider.name); return; } if (rotating) { if (dragplane.Raycast(ray, out rayDistance)) { startDragRot = ray.GetPoint(rayDistance); } rotationParent = new GameObject(); rotationParent.transform.position = transform.position; transform.SetParent(rotationParent.transform); } distance = hit.distance; startDrag = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance)); startPos = transform.position; dragging = true; } } if (dragging || rotating) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (dragplane.Raycast(ray, out rayDistance)) { mousePos = ray.GetPoint(rayDistance); } Vector3 onDrag = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance)); Vector3 translation = onDrag - startDrag; Vector3 projectedTranslation = Vector3.zero; if (dragging) { switch (selectedAxis) { case GizmoAxis.X: { projectedTranslation = Vector3.Project(translation, transform.right); transform.position = startPos + projectedTranslation.normalized * translation.magnitude; break; } case GizmoAxis.Y: { projectedTranslation = Vector3.Project(translation, transform.up); transform.position = startPos + projectedTranslation.normalized * translation.magnitude; break; } case GizmoAxis.Z: { projectedTranslation = Vector3.Project(translation, transform.forward); transform.position = startPos + projectedTranslation.normalized * translation.magnitude; break; } case GizmoAxis.XY: case GizmoAxis.XZ: case GizmoAxis.YZ: { transform.position = mousePos - hitvector; break; } } } if (rotating) { translation = mousePos - startDragRot; //Debug.DrawLine(startDragRot, mousePos, Color.white, 6.0f); Vector3 rotationAxis2 = Vector3.zero; switch (selectedAxis) { case GizmoAxis.XYRotate: { projectedTranslation = translation - Vector3.Project(translation, rotationAxis); //Debug.DrawLine(startDragRot, startDragRot + projectedTranslation, Color.yellow, 1.0f); rotationAxis2 = Vector3.Cross(projectedTranslation, lookHitPoint); //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis2.normalized, Color.magenta, 1.0f); //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis.normalized, Color.cyan, 1.0f); break; } case GizmoAxis.XZRotate: { projectedTranslation = translation - Vector3.Project(translation, rotationAxis); //Debug.DrawLine(startDragRot, startDragRot + projectedTranslation, Color.yellow, 1.0f); rotationAxis2 = Vector3.Cross(projectedTranslation, lookHitPoint); //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis2.normalized, Color.magenta, 1.0f); //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis.normalized, Color.magenta, 1.0f); break; } case GizmoAxis.YZRotate: { projectedTranslation = translation - Vector3.Project(translation, rotationAxis); //Debug.DrawLine(startDragRot, startDragRot + projectedTranslation, Color.yellow, 1.0f); rotationAxis2 = Vector3.Cross(projectedTranslation, lookHitPoint); //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis.normalized, Color.gray, 1.0f); break; } case GizmoAxis.none: { rotationAxis2 = rotationAxis; projectedTranslation = translation; rotationAxis = Vector3.Cross(translation, lookCamera); break; } } float angle; Quaternion delta; //Debug.DrawLine(transform.position, transform.position + 5 * rotationAxis.normalized, Color.red, 1.0f); angle = -Mathf.Rad2Deg * projectedTranslation.magnitude / sphereRadius; delta = Quaternion.AngleAxis(angle, rotationAxis2); if (selectedAxis == GizmoAxis.none) { rotationParent.transform.rotation = delta; } else { rotationParent.transform.rotation = delta; } } if (Input.GetMouseButtonUp(0)) { SetFalse(); } } }
/// <summary> /// Helper method for applying color to the gizmo lines. /// </summary> private void ApplyColor(GizmoAxis axis, Color color) { switch (ActiveMode) { case GizmoMode.NonUniformScale: case GizmoMode.Translate: switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; case GizmoAxis.XY: ApplyLineColor(0, 4, color); ApplyLineColor(6, 4, color); break; case GizmoAxis.YZ: ApplyLineColor(6, 2, color); ApplyLineColor(12, 2, color); ApplyLineColor(10, 2, color); ApplyLineColor(16, 2, color); break; case GizmoAxis.ZX: ApplyLineColor(0, 2, color); ApplyLineColor(4, 2, color); ApplyLineColor(12, 4, color); break; } break; case GizmoMode.Rotate: switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; } break; case GizmoMode.UniformScale: ApplyLineColor(0, _translationLineVertices.Length, ActiveAxis == GizmoAxis.None ? _axisColors[0] : _highlightColor); break; } }
public void Update(GameTime gameTime, float mouseX, float mouseY) { _currentMouseState = Mouse.GetState(); _currentKeys = Keyboard.GetState(); //Vector2 mousePosition = new Vector2(_currentMouseState.X, _currentMouseState.Y); Vector2 mousePosition = new Vector2(mouseX, mouseY); // show or hide the orientation-lines helper. //_showLines = _currentKeys.IsKeyDown(Keys.Space); if (_isActive) { _lastIntersectionPosition = _intersectPosition; if (WasButtonHeld(MouseButtons.Left) && ActiveAxis != GizmoAxis.None) { switch (ActiveMode) { case GizmoMode.UniformScale: case GizmoMode.NonUniformScale: case GizmoMode.Translate: { #region Translate & Scale Vector3 delta = Vector3.Zero; Ray ray = ConvertMouseToRay(mousePosition); Matrix transform = Matrix.Invert(_rotationMatrix); ray.Position = Vector3.Transform(ray.Position, transform); ray.Direction = Vector3.TransformNormal(ray.Direction, transform); switch (ActiveAxis) { case GizmoAxis.XY: case GizmoAxis.X: { Plane plane = new Plane(Vector3.Forward, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).Z); float? intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction*intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } delta = ActiveAxis == GizmoAxis.X ? new Vector3(_tDelta.X, 0, 0) : new Vector3(_tDelta.X, _tDelta.Y, 0); } } break; case GizmoAxis.Z: case GizmoAxis.YZ: case GizmoAxis.Y: { Plane plane = new Plane(Vector3.Left, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).X); float? intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction*intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } switch (ActiveAxis) { case GizmoAxis.Y: delta = new Vector3(0, _tDelta.Y, 0); break; case GizmoAxis.Z: delta = new Vector3(0, 0, _tDelta.Z); break; default: delta = new Vector3(0, _tDelta.Y, _tDelta.Z); break; } } } break; case GizmoAxis.ZX: { Plane plane = new Plane(Vector3.Down, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).Y); float? intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction*intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } } delta = new Vector3(_tDelta.X, 0, _tDelta.Z); } break; } if (SnapEnabled) { float snapValue = TranslationSnapValue; if (ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale) snapValue = ScaleSnapValue; if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; snapValue *= PRECISION_MODE_SCALE; } _translationScaleSnapDelta += delta; delta = new Vector3( (int) (_translationScaleSnapDelta.X/snapValue)*snapValue, (int) (_translationScaleSnapDelta.Y/snapValue)*snapValue, (int) (_translationScaleSnapDelta.Z/snapValue)*snapValue); _translationScaleSnapDelta -= delta; } else if (PrecisionModeEnabled) delta *= PRECISION_MODE_SCALE; if (ActiveMode == GizmoMode.Translate) { // transform (local or world) delta = Vector3.Transform(delta, _rotationMatrix); _translationDelta = delta; } else if (ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { // -- Apply Scale -- // _scaleDelta += delta; } #endregion } break; case GizmoMode.Rotate: { #region Rotate float delta = mousePosition.X - _lastMouseState.X; delta *= (float)gameTime.ElapsedGameTime.TotalSeconds * 0.01f; if (SnapEnabled) { float snapValue = MathHelper.ToRadians(RotationSnapValue); if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; snapValue *= PRECISION_MODE_SCALE; } _rotationSnapDelta += delta; float snapped = (int) (_rotationSnapDelta/snapValue)*snapValue; _rotationSnapDelta -= snapped; delta = snapped; } else if (PrecisionModeEnabled) delta *= PRECISION_MODE_SCALE; // rotation matrix to transform - if more than one objects selected, always use world-space. Matrix rot = Matrix.Identity; rot.Forward = SceneWorld.Forward; rot.Up = SceneWorld.Up; rot.Right = SceneWorld.Right; switch (ActiveAxis) { case GizmoAxis.X: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Right, delta); break; case GizmoAxis.Y: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Up, delta); break; case GizmoAxis.Z: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Forward, delta); break; } _rotationDelta = rot; #endregion } break; } } else { if (_currentMouseState.LeftButton == ButtonState.Released && _currentMouseState.RightButton == ButtonState.Released) SelectAxis(mousePosition); } SetGizmoPosition(); // -- Trigger Translation, Rotation & Scale events -- // if (WasButtonHeld(MouseButtons.Left) /*&& !IsAnyModifierPressed()*/) { if (_translationDelta != Vector3.Zero) { foreach (var entity in Selection) OnTranslateEvent(entity, _translationDelta); _translationDelta = Vector3.Zero; } if (_rotationDelta != Matrix.Identity) { foreach (var entity in Selection) OnRotateEvent(entity, _rotationDelta); _rotationDelta = Matrix.Identity; } if (_scaleDelta != Vector3.Zero) { foreach (var entity in Selection) OnScaleEvent(entity, _scaleDelta); _scaleDelta = Vector3.Zero; } } } _lastMouseState = _currentMouseState; if (Selection.Count < 1) { _isActive = false; ActiveAxis = GizmoAxis.None; return; } // helps solve visual lag (1-frame-lag) after selecting a new entity if (!_isActive) SetGizmoPosition(); _isActive = true; // -- Scale Gizmo to fit on-screen -- // Vector3 vLength = _cameraPosition - _position; const float scaleFactor = 25; _screenScale = vLength.Length()/scaleFactor; _screenScaleMatrix = Matrix.CreateScale(new Vector3(_screenScale)); _localForward = Selection[0].Forward; _localUp = Selection[0].Up; // -- Vector Rotation (Local/World) -- // _localForward.Normalize(); _localRight = Vector3.Cross(_localForward, _localUp); _localUp = Vector3.Cross(_localRight, _localForward); _localRight.Normalize(); _localUp.Normalize(); // -- Create Both World Matrices -- // _objectOrientedWorld = _screenScaleMatrix*Matrix.CreateWorld(_position, _localForward, _localUp); _axisAlignedWorld = _screenScaleMatrix*Matrix.CreateWorld(_position, SceneWorld.Forward, SceneWorld.Up); // Assign World if (ActiveSpace == TransformSpace.World || ActiveMode == GizmoMode.Rotate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { _gizmoWorld = _axisAlignedWorld; // align lines, boxes etc. with the grid-lines _rotationMatrix.Forward = SceneWorld.Forward; _rotationMatrix.Up = SceneWorld.Up; _rotationMatrix.Right = SceneWorld.Right; } else { _gizmoWorld = _objectOrientedWorld; // align lines, boxes etc. with the selected object _rotationMatrix.Forward = _localForward; _rotationMatrix.Up = _localUp; _rotationMatrix.Right = _localRight; } // -- Reset Colors to default -- // ApplyColor(GizmoAxis.X, _axisColors[0]); ApplyColor(GizmoAxis.Y, _axisColors[1]); ApplyColor(GizmoAxis.Z, _axisColors[2]); // -- Apply Highlight -- // ApplyColor(ActiveAxis, _highlightColor); }
/// <summary> /// Per-frame check to see if mouse is hovering over any axis. /// </summary> private void SelectAxis(Vector2 mousePosition) { if (!Enabled) return; float closestintersection = float.MaxValue; Ray ray = ConvertMouseToRay(mousePosition); if (ActiveMode == GizmoMode.Translate && ActiveSpace == TransformSpace.Local) { // transform ray into local-space of the boundingboxes. ray.Direction = Vector3.TransformNormal(ray.Direction, Matrix.Invert(_gizmoWorld)); ray.Position = Vector3.Transform(ray.Position, Matrix.Invert(_gizmoWorld)); } #region X,Y,Z Boxes float? intersection = XAxisBox.Intersects(ray); if (intersection.HasValue) if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } intersection = YAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = ZAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion if (ActiveMode == GizmoMode.Rotate || ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale) { #region BoundingSpheres intersection = XSphere.Intersects(ray); if (intersection.HasValue) if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } intersection = YSphere.Intersects(ray); if (intersection.HasValue) if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } intersection = ZSphere.Intersects(ray); if (intersection.HasValue) if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } #endregion } if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { // if no axis was hit (x,y,z) set value to lowest possible to select the 'farthest' intersection for the XY,XZ,YZ boxes. // This is done so you may still select multi-axis if you're looking at the gizmo from behind! if (closestintersection >= float.MaxValue) closestintersection = float.MinValue; #region BoundingBoxes intersection = XYBox.Intersects(ray); if (intersection.HasValue) if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.XY; closestintersection = intersection.Value; } intersection = XZAxisBox.Intersects(ray); if (intersection.HasValue) if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.ZX; closestintersection = intersection.Value; } intersection = YZBox.Intersects(ray); if (intersection.HasValue) if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.YZ; closestintersection = intersection.Value; } #endregion } if (closestintersection >= float.MaxValue || closestintersection <= float.MinValue) ActiveAxis = GizmoAxis.None; }
public static void HandleInput(MyGuiInput input) { // -- Select Gizmo Mode -- // if (input.IsEditorControlNewPressed(MyEditorControlEnums.SWITCH_GIZMO_MODE) && !input.IsAnyCtrlKeyPressed()) { SwitchGizmoMode(); } // -- Select Gizmo Mode -- // if (input.IsEditorControlNewPressed(MyEditorControlEnums.SWITCH_GIZMO_MODE) && input.IsAnyCtrlKeyPressed() ) { SwitchRotateSnapping(); } // -- Cycle TransformationSpaces -- // if (input.IsEditorControlNewPressed(MyEditorControlEnums.SWITCH_GIZMO_SPACE)) { if (ActiveSpace == TransformSpace.LOCAL) ActiveSpace = TransformSpace.WORLD; else { ActiveSpace = TransformSpace.LOCAL; } } // Below are options, that we can add later, but gizmo is prepared for them // however, key mappings will be probably changed // -- Cycle PivotTypes -- // //if (input.IsNewKeyPress(Keys.P)) //{ // ActivePivot++; //} // -- Toggle PrecisionMode -- // //if (input.IsKeyPress(Keys.K)) //{ // m_precisionMode = true; //} //else //{ // m_precisionMode = false; //} // -- Toggle Snapping -- // //if (MyEditor.Static.IsEditingPrefabContainer() == false) //{ if (input.IsNewKeyPress(Keys.G)) { SnapEnabled = !SnapEnabled; } //} if (Enabled) { if (input.IsEditorControlNewPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY)) { // reset for intersection (plane vs. ray) m_translationDelta = Vector3.Zero; m_intersectPosition = Vector3.Zero; // reset for snapping m_translationScaleSnapDelta = Vector3.Zero; m_rotationSnapDelta = 0; m_lastCursorPosition = MyGuiManager.MouseCursorPosition; m_oldCursorPosition = MyGuiManager.MouseCursorPosition; m_gizmoDelta = null; m_gizmoStartPosition = null; m_mouseStartPosition = m_lastCursorPosition; m_startCameraForward = MyCamera.ForwardVector; m_startCameraUp = MyCamera.UpVector; m_startObjectPosition = Position; } m_lastIntersectionPosition = m_intersectPosition; TransformationActive = false; if (input.IsEditorControlPressed(MyEditorControlEnums.PRIMARY_ACTION_KEY)) { if (MyEditor.TransformLocked) { ActiveAxis = LastActiveAxis; } if (ActiveAxis != GizmoAxis.NONE) { //this will help to disable rectangular selection of multiple objects during object transformation with mouse TransformationActive = true; if (ActiveMode == GizmoMode.TRANSLATE) { #region Translate if (HasTransformationStarted()) { StartTransformationData(); } //if (input.IsAnyShiftKeyPressed() && input.IsNewLeftMousePressed()) //{ // MyEditor.Static.CopySelected(false); //} //else if (HasTransformationStarted()) //{ // StartTransformationData(); //} Vector3 delta = Vector3.Zero; Vector3 worldPosition = Position; if (ActiveAxis == GizmoAxis.XY) { GizmoTranslation(Vector3.Left, Vector3.Up, ref worldPosition); } else if (ActiveAxis == GizmoAxis.YZ) { GizmoTranslation(Vector3.Up, Vector3.Forward, ref worldPosition); } else if (ActiveAxis == GizmoAxis.ZX) { GizmoTranslation(Vector3.Left, Vector3.Forward, ref worldPosition); } else if (ActiveAxis == GizmoAxis.X) { GizmoTranslation(Vector3.Left, null, ref worldPosition); } else if (ActiveAxis == GizmoAxis.Y) { GizmoTranslation(Vector3.Up, null, ref worldPosition); } else if (ActiveAxis == GizmoAxis.Z) { GizmoTranslation(Vector3.Forward, null, ref worldPosition); } // When object is half distance to far, stop it's movement Plane maxMovePlane = MyCamera.GetBoundingFrustum().Far; maxMovePlane.D *= TRANSLATION_MAX_DISTANCE_FROM_CAMERA / MyCamera.FAR_PLANE_DISTANCE; Vector3 moveVector = worldPosition - Position; Ray moveRay = new Ray(Position, -moveVector); float? intersection = moveRay.Intersects(maxMovePlane); Vector3 cam = MyCamera.Position; // Intersection found and moving object towards far clip plane if (intersection.HasValue && Vector3.Dot(MyCamera.ForwardVector, moveVector) > 0 && (worldPosition - cam).Length() > Math.Abs(maxMovePlane.D)) { Vector3 intersectionPoint = (moveRay.Position + (moveRay.Direction * intersection.Value)); worldPosition = intersectionPoint; } moveVector = worldPosition - Position; // copy selected object only when moved from his original position + LMB + Shift bool copySelected = (moveVector.LengthSquared() >= 0f && input.IsAnyShiftKeyPressed() && input.IsNewLeftMousePressed()); if (copySelected) { MyEditor.Static.CopySelected(false); } bool applyTranslation = true; PrepareSafeSelectedEntitiesIterationHelper(); foreach (var entity in m_safeIterationHelper) { Vector3 newPosition = entity.GetPosition() + moveVector; BoundingSphere sphere = new BoundingSphere(newPosition + entity.LocalVolumeOffset, entity.WorldVolume.Radius); if (!entity.CanMoveAndRotate(newPosition, entity.GetWorldRotation()) || MyMwcSectorConstants.SECTOR_SIZE_FOR_PHYS_OBJECTS_BOUNDING_BOX.Contains(sphere) != MinerWarsMath.ContainmentType.Contains) { applyTranslation = false; break; } } if (applyTranslation) { PrepareSafeSelectedEntitiesIterationHelper(); List<MyEntity> transformedEntities = new List<MyEntity>(); // apply foreach (MyEntity entity in m_safeIterationHelper) { // skip already transformed linked entities if (transformedEntities.Contains(entity)) { continue; } Vector3 newPosition = entity.GetPosition() + moveVector; //snaping after mouse over /* // Snap to grid if (SnapEnabled && ActiveSpace == TransformSpace.WORLD && !MyEditor.Static.IsLinked(entity)) { SnapToGrid(ref newPosition, TranslationSnapValue); } */ MoveAndRotateObject(newPosition, entity.GetWorldRotation(), entity); MyEditor.Static.FixLinkedEntities(entity, transformedEntities, null); transformedEntities.Add(entity); } // test if some entities are intersection //CheckCollisions(m_safeIterationHelper); //MyEditor.Static.CheckAllCollidingObjects(); MyEditor.Static.HighlightCollisions(m_safeIterationHelper); } #endregion } else if (ActiveMode == GizmoMode.ROTATE) { #region Rotate if (HasTransformationStarted()) StartTransformationData(); Vector2 deltaCursorPosition; float delta; if (!MyVideoModeManager.IsHardwareCursorUsed()) { Vector2 minMouseCoord = MyGuiManager.GetMinMouseCoord(); Vector2 maxMouseCoord = MyGuiManager.GetMaxMouseCoord(); Vector2 newCursorPosition = MyGuiManager.MouseCursorPosition; if (MyGuiManager.MouseCursorPosition.X <= minMouseCoord.X) newCursorPosition = new Vector2(maxMouseCoord.X, MyGuiManager.MouseCursorPosition.Y); if (MyGuiManager.MouseCursorPosition.X >= maxMouseCoord.X) newCursorPosition = new Vector2(minMouseCoord.X, MyGuiManager.MouseCursorPosition.Y); if (MyGuiManager.MouseCursorPosition.Y <= minMouseCoord.Y) newCursorPosition = new Vector2(MyGuiManager.MouseCursorPosition.X, maxMouseCoord.Y); if (MyGuiManager.MouseCursorPosition.Y >= maxMouseCoord.Y) newCursorPosition = new Vector2(MyGuiManager.MouseCursorPosition.X, minMouseCoord.Y); MyGuiManager.MouseCursorPosition = newCursorPosition; //KeenSoftwareHouse.Library.Trace.Trace.SendMsgLastCall(MyGuiManager.MouseCursorPosition.ToString() + " " + MyGuiManager.MouseCursorPosition.ToString()); float deltaX = MathHelper.ToRadians(input.GetMouseXForGamePlay() - MyMinerGame.ScreenSizeHalf.X); float deltaY = MathHelper.ToRadians(input.GetMouseYForGamePlay() - MyMinerGame.ScreenSizeHalf.Y); deltaX = MathHelper.Clamp(deltaX, -1, 1); deltaY = MathHelper.Clamp(deltaY, -1, 1); delta = deltaY + deltaX; Vector2 cursorDelta = Vector2.Zero; if (MyGuiManager.MouseCursorPosition.Y != 0.0 && MyGuiManager.MouseCursorPosition.Y != 1.0) { cursorDelta = MyGuiManager.MouseCursorPosition - m_lastCursorPosition; } m_inputScale = MathHelper.Clamp(Math.Abs(cursorDelta.Y) * 100, 0, 1); delta *= m_inputScale; m_oldCursorPosition = MyGuiManager.MouseCursorPosition; } else { Vector2 minMouseCoord = MyGuiManager.GetMinMouseCoord(); Vector2 maxMouseCoord = MyGuiManager.GetMaxMouseCoord(); Vector2 newCursorPosition = MyGuiManager.MouseCursorPosition; deltaCursorPosition = MyGuiManager.MouseCursorPosition - m_oldCursorPosition; if (MyGuiManager.MouseCursorPosition.X - 0.03f <= minMouseCoord.X) { deltaCursorPosition = new Vector2(0, 0); newCursorPosition = new Vector2(maxMouseCoord.X - 0.05f, MyGuiManager.MouseCursorPosition.Y); } if (MyGuiManager.MouseCursorPosition.X + 0.03f >= maxMouseCoord.X * 0.98f) { deltaCursorPosition = new Vector2(0, 0); newCursorPosition = new Vector2(minMouseCoord.X + 0.05f, MyGuiManager.MouseCursorPosition.Y); } if (MyGuiManager.MouseCursorPosition.Y - 0.03f <= minMouseCoord.Y) { deltaCursorPosition = new Vector2(0, 0); newCursorPosition = new Vector2(MyGuiManager.MouseCursorPosition.X, maxMouseCoord.Y - 0.05f); } if (MyGuiManager.MouseCursorPosition.Y + 0.03f >= maxMouseCoord.Y) { deltaCursorPosition = new Vector2(0, 0); newCursorPosition = new Vector2(MyGuiManager.MouseCursorPosition.X, minMouseCoord.Y + 0.05f); } MyGuiManager.MouseCursorPosition = newCursorPosition; delta = (deltaCursorPosition.X + deltaCursorPosition.Y) * 4.0f; delta = MathHelper.Clamp(delta, -2.0f, 2.0f); m_oldCursorPosition = MyGuiManager.MouseCursorPosition; } // Allow snapping of gizmo to make it move depending on the selected grid scale if (ActiveRotateSnapping!=RotateSnapping.NONE) { float snapValue = MathHelper.ToRadians(GetRotateSnapValue()); if (m_precisionMode) { delta *= m_precisionModeScale; snapValue *= m_precisionModeScale; } m_rotationSnapDelta += delta; float snapped = (int)(m_rotationSnapDelta / snapValue) * snapValue; m_rotationSnapDelta -= snapped; delta = snapped; } else if (m_precisionMode) { delta *= m_precisionModeScale; } // rotation matrix to transform - if more than one objects selected, always use world-space. Matrix rot = Matrix.Identity; rot.Forward = m_sceneWorld.Forward; rot.Up = m_sceneWorld.Up; rot.Right = m_sceneWorld.Right; // Create rotation delta matrix if (ActiveAxis == GizmoAxis.X) { rot *= Matrix.CreateFromAxisAngle(Rotation.Right, delta); } else if (ActiveAxis == GizmoAxis.Y) { rot *= Matrix.CreateFromAxisAngle(Rotation.Up, delta); } else if (ActiveAxis == GizmoAxis.Z) { rot *= Matrix.CreateFromAxisAngle(Rotation.Forward, delta); } // store rotation parameters so that we can calculate the difference in rotation of "before" rotation and "after" CalculateYawPitchRollFromRotationDelta(rot); PrepareSafeSelectedEntitiesIterationHelper(); List<MyEntity> transformedEntities = new List<MyEntity>(); // -- Apply rotation -- // foreach (MyEntity entity in m_safeIterationHelper) { // skip already transformed linked entities if (transformedEntities.Contains(entity)) { continue; } // VoxelMaps cannot be rotated if (entity is MyVoxelMap == false) { // use gizmo position for all PivotTypes except for object-center, it should use the entity.position instead. Vector3 newPosition; Matrix newRotation; GetRotationAndPosition(entity, rot, out newPosition, out newRotation); Matrix normalizedMat = new Matrix(); normalizedMat.Right = Vector3.Normalize(newRotation.Right); normalizedMat.Forward = Vector3.Normalize(Vector3.Cross(Vector3.Normalize(newRotation.Up), normalizedMat.Right)); normalizedMat.Up = Vector3.Normalize(Vector3.Cross(normalizedMat.Right, normalizedMat.Forward)); normalizedMat.Translation = newRotation.Translation; normalizedMat.M44 = newRotation.M44; //KeenSoftwareHouse.Library.Trace.Trace.SendMsgLastCall("{"); //KeenSoftwareHouse.Library.Trace.Trace.SendMsgLastCall(normalizedMat.ToString()); //KeenSoftwareHouse.Library.Trace.Trace.SendMsgLastCall(newRotation.ToString()); //KeenSoftwareHouse.Library.Trace.Trace.SendMsgLastCall("}"); MoveAndRotateObject(newPosition, normalizedMat, entity); MyEditor.Static.FixLinkedEntities(entity, transformedEntities, null); transformedEntities.Add(entity); } } SetPosition(); Vector3 moveVector = m_startObjectPosition - Position; PrepareSafeSelectedEntitiesIterationHelper(); transformedEntities = new List<MyEntity>(); // apply foreach (MyEntity entity in m_safeIterationHelper) { // skip already transformed linked entities if (transformedEntities.Contains(entity)) { continue; } Vector3 newPosition = entity.GetPosition() + moveVector; MoveAndRotateObject(newPosition, entity.GetWorldRotation(), entity); MyEditor.Static.FixLinkedEntities(entity, transformedEntities, null); transformedEntities.Add(entity); } #endregion } } } else { PrepareSafeSelectedEntitiesIterationHelper(); foreach (MyEntity entity in m_safeIterationHelper) { float moveObjectDistanceInMeters = MyEditorGrid.GetGridStepInMeters(); float rotationAngleInRadians = MathHelper.ToRadians(GetRotationDelta()); Matrix entityOrientation = entity.GetWorldRotation(); bool isVoxelMap = entity is MyVoxelMap; Vector3 entityPosition = entity.GetPosition(); #region Translate and Rotate with keyboard Vector3 newPosition = entityPosition; Matrix newRotation = entityOrientation; // Keyboard translation if (IsTransformationKeyPressed(input, Keys.NumPad1)) { newPosition = GetTransformInAxis(GizmoAxis.X, entityPosition, Rotation, -moveObjectDistanceInMeters); } if (IsTransformationKeyPressed(input, Keys.NumPad3)) { newPosition = GetTransformInAxis(GizmoAxis.X, entityPosition, Rotation, +moveObjectDistanceInMeters); } if (IsTransformationKeyPressed(input, Keys.NumPad2)) { newPosition = GetTransformInAxis(GizmoAxis.Z, entityPosition, Rotation, +moveObjectDistanceInMeters); } if (IsTransformationKeyPressed(input, Keys.NumPad5)) { newPosition = GetTransformInAxis(GizmoAxis.Z, entityPosition, Rotation, -moveObjectDistanceInMeters); } if (IsTransformationKeyPressed(input, Keys.NumPad9)) { newPosition = GetTransformInAxis(GizmoAxis.Y, entityPosition, Rotation, +moveObjectDistanceInMeters); } if (IsTransformationKeyPressed(input, Keys.NumPad6)) { newPosition = GetTransformInAxis(GizmoAxis.Y, entityPosition, Rotation, -moveObjectDistanceInMeters); } // Keyboard rotation Matrix oneStepRotationDelta = Matrix.Identity; if (IsTransformationKeyPressed(input, Keys.NumPad7) && !isVoxelMap) { oneStepRotationDelta = Matrix.CreateFromAxisAngle(Rotation.Right, rotationAngleInRadians); GetRotationAndPosition(entity, oneStepRotationDelta, out newPosition, out newRotation); } if (IsTransformationKeyPressed(input, Keys.NumPad4) && !isVoxelMap) { oneStepRotationDelta = Matrix.CreateFromAxisAngle(Rotation.Up, rotationAngleInRadians); GetRotationAndPosition(entity, oneStepRotationDelta, out newPosition, out newRotation); } if (IsTransformationKeyPressed(input, Keys.NumPad8) && !isVoxelMap) { oneStepRotationDelta = Matrix.CreateFromAxisAngle(Rotation.Forward, rotationAngleInRadians); GetRotationAndPosition(entity, oneStepRotationDelta, out newPosition, out newRotation); } if (HasTransformationStarted()) StartTransformationData(); // Transform bool translated = newPosition != entityPosition; bool rotated = newRotation != entityOrientation; if (translated || rotated) { if (translated) ActiveMode = GizmoMode.TRANSLATE; if (rotated) { ActiveMode = GizmoMode.ROTATE; if (IsDelayForSmoothMovementReached()) { RotationAmountInDegrees += (int)GetRotationDelta(); } else { RotationAmountInDegrees = (int)GetRotationDelta(); } } MoveAndRotateObject(newPosition, newRotation, entity); } #endregion } UpdateAxisSelection(MyGuiManager.GetScreenCoordinateFromNormalizedCoordinate(MyGuiManager.MouseCursorPosition)); /* if (GetSnapPoint(true) == null) { } else { ActiveAxis = GizmoAxis.NONE; } */ } if (HasTransformationEnded()) EndTransformationData(); // previous is used to detect, when is right time to create undo/redo editor action(start of transform, and end of transform) TransformationActivePrevious = TransformationActive; } else { ActiveAxis = GizmoAxis.NONE; } }
public void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (isCharacterMovementActive && e.Button != MouseButtons.Right) { TabPanelData data = mMainForm.getTabPanel(); DatabaseObjectInfo inf = DatabaseObjectRegistry.get(data.mSelectedEntity); if (data.mSelectedEntity != null && inf.locked) { if (e.Button == MouseButtons.Left) { //move the selected character along the preferred axis if (mHighlightedAxis != GizmoAxis.GizmoAxis_None) { if (mOldPoint.X == -1) { mOldPoint.X = e.X; mOldPoint.Y = e.Y; } float dx = e.X - mOldPoint.X; float dy = e.Y - mOldPoint.Y; //move character along the gizmo float scale = 1; Vector3 axis = new Vector3(0, 0, 0); switch (mHighlightedAxis) { default: { } break; case GizmoAxis.GizmoAxis_X: { axis = new Vector3(1, 0, 0); axis = axis * dx; } break; case GizmoAxis.GizmoAxis_Y: { axis = new Vector3(0, -1, 0); axis = axis * dy; } break; case GizmoAxis.GizmoAxis_Z: { axis = new Vector3(0, 0, 1); axis = axis * dx; } break; } //switch axis = axis * scale; Vector3 pos = data.mSelectedEntity.getLocation(); pos = pos + axis; data.mSelectedEntity.setLocation(ref pos); //add this actor to the modified list if (!modifiedActorList.Contains(data.mSelectedEntity)) { modifiedActorList.Add(data.mSelectedEntity); } GodzUtil.RunMainPass(); //cache mouse pos mOldPoint.X = e.X; mOldPoint.Y = e.Y; } } else { //reset cached mousepoint mOldPoint.X = -1; mOldPoint.Y = -1; //highlight the active axis the character will be moved along.... Point p = new Point(); p.X = e.X; p.Y = e.Y; mHighlightedAxis = data.mWorld.pickAxis(ref p); //tick the actors so they send events over to renderer GodzUtil.RunMainPass(); } //else } } else { //reset mOldPoint.X = -1; mOldPoint.Y = -1; } }
/// <summary> /// Helper method for applying color to the gizmo lines. /// </summary> /// <param name="axis"></param> /// <param name="color"></param> static void ApplyColor(GizmoAxis axis, Color color) { if (ActiveMode == GizmoMode.TRANSLATE) { switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; case GizmoAxis.XY: ApplyLineColor(0, 4, color); ApplyLineColor(6, 4, color); break; case GizmoAxis.YZ: ApplyLineColor(6, 2, color); ApplyLineColor(12, 2, color); ApplyLineColor(10, 2, color); ApplyLineColor(16, 2, color); break; case GizmoAxis.ZX: ApplyLineColor(0, 2, color); ApplyLineColor(4, 2, color); ApplyLineColor(12, 4, color); break; } } else if (ActiveMode == GizmoMode.ROTATE) { switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; } } }
/// <summary> /// Get delta vector transformation around provided rotation matrix /// </summary> /// <param name="axis"></param> /// <param name="position"></param> /// <param name="rotation"></param> /// <param name="delta"></param> /// <returns></returns> static Vector3 GetTransformInAxis(GizmoAxis axis, Vector3 position, Matrix rotation, float delta) { Vector3 deltaVec = Vector3.Zero; if (axis == GizmoAxis.X) { deltaVec = new Vector3(delta, 0, 0); deltaVec = Vector3.Transform(deltaVec, rotation); } else if (axis == GizmoAxis.Y) { deltaVec = new Vector3(0, delta, 0); deltaVec = Vector3.Transform(deltaVec, rotation); } else if (axis == GizmoAxis.Z) { deltaVec = new Vector3(0, 0, delta); deltaVec = Vector3.Transform(deltaVec, rotation); } position += deltaVec; return position; }
public void Draw3D() { return; if (m_IsEnabled == false) { return; } m_ActiveMode = GizmoMode.TRANSLATE; m_ActiveAxis = GizmoAxis.XY; m_ActivePivot = PivotType.OBJECT_CENTER; GameFiles.GraphicsDevice.DepthStencilState = DepthStencilState.None; m_LineEffect.World = m_GizmoWorld; m_LineEffect.View = GameFiles.ViewMatrix; m_LineEffect.Projection = GameFiles.ProjectionMatrix; m_LineEffect.CurrentTechnique.Passes[0].Apply(); GameFiles.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, m_TranslationLineVertices, 0, m_TranslationLineVertices.Length / 2); if (m_ActiveMode == GizmoMode.TRANSLATE || m_ActiveMode == GizmoMode.NON_LINEAR_SCALE) { if (m_ActiveAxis == GizmoAxis.XY || m_ActiveAxis == GizmoAxis.YZ || m_ActiveAxis == GizmoAxis.ZX) { GameFiles.GraphicsDevice.BlendState = BlendState.AlphaBlend; GameFiles.GraphicsDevice.RasterizerState = RasterizerState.CullNone; m_QuadEffect.World = m_GizmoWorld; m_QuadEffect.View = GameFiles.ViewMatrix; m_QuadEffect.Projection = GameFiles.ProjectionMatrix; m_QuadEffect.CurrentTechnique.Passes[0].Apply(); Quad activeQuad = new Quad(); switch (m_ActiveAxis) { case GizmoAxis.XY: activeQuad = m_Quads[0]; break; case GizmoAxis.ZX: activeQuad = m_Quads[1]; break; case GizmoAxis.YZ: activeQuad = m_Quads[2]; break; } GameFiles.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, activeQuad.Vertices, 0, 4, activeQuad.Indexes, 0, 2); GameFiles.GraphicsDevice.BlendState = BlendState.Opaque; GameFiles.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; } if (m_ActiveMode == GizmoMode.TRANSLATE) { for (int loop = 0; loop < 3; loop++) { for (int meshLoop = 0; meshLoop < m_TranslationModel.Meshes.Count; meshLoop++) { ModelMesh tempModelMesh = m_TranslationModel.Meshes[meshLoop]; for (int meshPartLoop = 0; meshPartLoop < m_TranslationModel.Meshes.Count; meshPartLoop++) { ModelMeshPart tempModelMeshPart = tempModelMesh.MeshParts[meshPartLoop]; BasicEffect effect = (BasicEffect)tempModelMeshPart.Effect; Vector3 color = m_AxisColors[loop].ToVector3(); effect.World = m_ModelLocalSpace[loop] * m_GizmoWorld; effect.DiffuseColor = color; effect.EmissiveColor = color; effect.EnableDefaultLighting(); effect.View = GameFiles.ViewMatrix; effect.Projection = GameFiles.ProjectionMatrix; } tempModelMesh.Draw(); } } } else { for (int loop = 0; loop < 3; loop++) { for (int meshLoop = 0; meshLoop < m_ScaleModel.Meshes.Count; meshLoop++) { ModelMesh tempModelMesh = m_ScaleModel.Meshes[meshLoop]; for (int meshPartLoop = 0; meshPartLoop < m_ScaleModel.Meshes.Count; meshPartLoop++) { ModelMeshPart tempModelMeshPart = tempModelMesh.MeshParts[meshPartLoop]; BasicEffect effect = (BasicEffect)tempModelMeshPart.Effect; Vector3 color = m_AxisColors[meshPartLoop].ToVector3(); effect.World = m_ModelLocalSpace[meshPartLoop] * m_GizmoWorld; effect.DiffuseColor = color; effect.EmissiveColor = color; effect.EnableDefaultLighting(); effect.View = GameFiles.ViewMatrix; effect.Projection = GameFiles.ProjectionMatrix; } tempModelMesh.Draw(); } } } } else if (m_ActiveMode == GizmoMode.ROTATE) { for (int loop = 0; loop < 3; loop++) { for (int meshLoop = 0; meshLoop < m_RotationModel.Meshes.Count; meshLoop++) { ModelMesh tempModelMesh = m_RotationModel.Meshes[meshLoop]; for (int meshPartLoop = 0; meshPartLoop < m_RotationModel.Meshes.Count; meshPartLoop++) { ModelMeshPart tempModelMeshPart = tempModelMesh.MeshParts[meshPartLoop]; BasicEffect effect = (BasicEffect)tempModelMeshPart.Effect; Vector3 color = m_AxisColors[meshPartLoop].ToVector3(); effect.World = m_ModelLocalSpace[meshPartLoop] * m_GizmoWorld; effect.DiffuseColor = color; effect.EmissiveColor = color; effect.EnableDefaultLighting(); effect.View = GameFiles.ViewMatrix; effect.Projection = GameFiles.ProjectionMatrix; } tempModelMesh.Draw(); } } } else if (m_ActiveMode == GizmoMode.SCALE) { for (int loop = 0; loop < 3; loop++) { for (int meshLoop = 0; meshLoop < m_RotationModel.Meshes.Count; meshLoop++) { ModelMesh tempModelMesh = m_RotationModel.Meshes[meshLoop]; for (int meshPartLoop = 0; meshPartLoop < m_RotationModel.Meshes.Count; meshPartLoop++) { ModelMeshPart tempModelMeshPart = tempModelMesh.MeshParts[meshPartLoop]; BasicEffect effect = (BasicEffect)tempModelMeshPart.Effect; Vector3 color = m_AxisColors[meshPartLoop].ToVector3(); effect.World = m_ModelLocalSpace[meshPartLoop] * m_GizmoWorld; effect.DiffuseColor = color; effect.EmissiveColor = color; effect.EnableDefaultLighting(); effect.View = GameFiles.ViewMatrix; effect.Projection = GameFiles.ProjectionMatrix; } tempModelMesh.Draw(); } } if (m_ActiveAxis != GizmoAxis.NONE) { GameFiles.GraphicsDevice.BlendState = BlendState.AlphaBlend; GameFiles.GraphicsDevice.RasterizerState = RasterizerState.CullNone; m_QuadEffect.World = m_GizmoWorld; m_QuadEffect.View = GameFiles.ViewMatrix; m_QuadEffect.Projection = GameFiles.ProjectionMatrix; m_QuadEffect.CurrentTechnique.Passes[0].Apply(); for (int loop = 0; loop < m_Quads.Length; loop++) { GameFiles.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, m_Quads[loop].Vertices, 0, 4, m_Quads[loop].Indexes, 0, 2); } GameFiles.GraphicsDevice.BlendState = BlendState.Opaque; GameFiles.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; } } GameFiles.GraphicsDevice.DepthStencilState = DepthStencilState.Default; }
/// <summary> /// Helper method for applying color to the gizmo lines. /// </summary> private void ApplyColor(GizmoAxis axis, Color color) { if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale) { switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; case GizmoAxis.XY: ApplyLineColor(0, 4, color); ApplyLineColor(6, 4, color); break; case GizmoAxis.YZ: ApplyLineColor(6, 2, color); ApplyLineColor(12, 2, color); ApplyLineColor(10, 2, color); ApplyLineColor(16, 2, color); break; case GizmoAxis.ZX: ApplyLineColor(0, 2, color); ApplyLineColor(4, 2, color); ApplyLineColor(12, 4, color); break; } } else if (ActiveMode == GizmoMode.Rotate) { switch (axis) { case GizmoAxis.X: ApplyLineColor(0, 6, color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, color); break; } } else if (ActiveMode == GizmoMode.UniformScale) { // all three axis red. if (ActiveAxis == GizmoAxis.None) ApplyLineColor(0, translationLineVertices.Length, axisColors[0]); else ApplyLineColor(0, translationLineVertices.Length, highlightColor); } }
/// <summary> /// Per-frame check to see if mouse is hovering over any axis. /// </summary> private void UpdateAxisSelection(Vector2 mousePosition) { float closestintersection = float.MaxValue; Ray ray = Engine.ray; closestintersection = float.MaxValue; float? intersection; if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { #region BoundingBoxes intersection = XY_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.XY; closestintersection = intersection.Value; } } intersection = XZ_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.ZX; closestintersection = intersection.Value; } } intersection = YZ_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.YZ; closestintersection = intersection.Value; } } intersection = X_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (ActiveMode == GizmoMode.Rotate || ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale) { #region BoundingSpheres intersection = X_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (ActiveMode == GizmoMode.Rotate) { #region X,Y,Z Boxes intersection = X_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (closestintersection == float.MaxValue) { ActiveAxis = GizmoAxis.None; } }
public void Update() { _view = EDRegistry.Camera.ViewMatrix; _projection = EDRegistry.Camera.ProjectionMatrix; _cameraPosition = EDRegistry.Camera.Transform.Position; var mousePosition = EDRegistry.Mouse.Position; if (_isActive) { _lastIntersectionPosition = _intersectPosition; if (EDRegistry.Mouse.JustClicked()) { ResetDeltas(); } if (WasButtonHeld(MouseButton.Left) && ActiveAxis != GizmoAxis.None) { switch (ActiveMode) { case GizmoMode.UniformScale: case GizmoMode.NonUniformScale: case GizmoMode.Translate: { #region Translate & Scale Vector3 delta = Vector3.Zero; Ray ray = ConvertMouseToRay(mousePosition); Matrix transform = Matrix.Invert(_rotationMatrix); ray.Position = Vector3.Transform(ray.Position, transform); ray.Direction = Vector3.TransformNormal(ray.Direction, transform); switch (ActiveAxis) { case GizmoAxis.XY: case GizmoAxis.X: { Plane plane = new Plane(Vector3.Forward, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).Z); float?intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction * intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } delta = ActiveAxis == GizmoAxis.X ? new Vector3(_tDelta.X, 0, 0) : new Vector3(_tDelta.X, _tDelta.Y, 0); } } break; case GizmoAxis.Z: case GizmoAxis.YZ: case GizmoAxis.Y: { Plane plane = new Plane(Vector3.Left, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).X); float?intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction * intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } switch (ActiveAxis) { case GizmoAxis.Y: delta = new Vector3(0, _tDelta.Y, 0); break; case GizmoAxis.Z: delta = new Vector3(0, 0, _tDelta.Z); break; default: delta = new Vector3(0, _tDelta.Y, _tDelta.Z); break; } } } break; case GizmoAxis.ZX: { Plane plane = new Plane(Vector3.Down, Vector3.Transform(_position, Matrix.Invert(_rotationMatrix)).Y); float?intersection = ray.Intersects(plane); if (intersection.HasValue) { _intersectPosition = (ray.Position + (ray.Direction * intersection.Value)); if (_lastIntersectionPosition != Vector3.Zero) { _tDelta = _intersectPosition - _lastIntersectionPosition; } } delta = new Vector3(_tDelta.X, 0, _tDelta.Z); } break; } if (SnapEnabled) { float snapValue = TranslationSnapValue; if (ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale) { snapValue = ScaleSnapValue; } if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; snapValue *= PRECISION_MODE_SCALE; } _translationScaleSnapDelta += delta; delta = new Vector3( (int)(_translationScaleSnapDelta.X / snapValue) * snapValue, (int)(_translationScaleSnapDelta.Y / snapValue) * snapValue, (int)(_translationScaleSnapDelta.Z / snapValue) * snapValue); _translationScaleSnapDelta -= delta; } else if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; } if (ActiveMode == GizmoMode.Translate) { // transform (local or world) delta = Vector3.Transform(delta, _rotationMatrix); _translationDelta = delta; } else if (ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { // -- Apply Scale -- // _scaleDelta += delta; } #endregion } break; case GizmoMode.Rotate: { #region Rotate float delta = EDRegistry.Mouse.Delta.X * Time.TotalTime; if (SnapEnabled) { float snapValue = MathHelper.ToRadians(RotationSnapValue); if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; snapValue *= PRECISION_MODE_SCALE; } _rotationSnapDelta += delta; float snapped = (int)(_rotationSnapDelta / snapValue) * snapValue; _rotationSnapDelta -= snapped; delta = snapped; } else if (PrecisionModeEnabled) { delta *= PRECISION_MODE_SCALE; } // rotation matrix to transform - if more than one objects selected, always use world-space. Matrix rot = Matrix.Identity; rot.Forward = SceneWorld.Forward; rot.Up = SceneWorld.Up; rot.Right = SceneWorld.Right; switch (ActiveAxis) { case GizmoAxis.X: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Right, delta); break; case GizmoAxis.Y: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Up, delta); break; case GizmoAxis.Z: rot *= Matrix.CreateFromAxisAngle(_rotationMatrix.Forward, delta); break; } _rotationDelta = rot; #endregion } break; } } else { if (EDRegistry.Mouse.Up(C3DE.Inputs.MouseButton.Left) || EDRegistry.Mouse.Up(C3DE.Inputs.MouseButton.Right)) { SelectAxis(mousePosition); } } SetGizmoPosition(); // -- Trigger Translation, Rotation & Scale events -- // if (WasButtonHeld(MouseButton.Left)) { if (_translationDelta != Vector3.Zero) { foreach (var entity in Selection) { OnTranslateEvent(entity, _translationDelta); } _translationDelta = Vector3.Zero; } if (_rotationDelta != Matrix.Identity) { foreach (var entity in Selection) { OnRotateEvent(entity, _rotationDelta); } _rotationDelta = Matrix.Identity; } if (_scaleDelta != Vector3.Zero) { foreach (var entity in Selection) { OnScaleEvent(entity, _scaleDelta); } _scaleDelta = Vector3.Zero; } } } //_lastMouseState = _currentMouseState; if (Selection.Count < 1) { _isActive = false; ActiveAxis = GizmoAxis.None; return; } // helps solve visual lag (1-frame-lag) after selecting a new entity if (!_isActive) { SetGizmoPosition(); } _isActive = true; // -- Scale Gizmo to fit on-screen -- // Vector3 vLength = _cameraPosition - _position; const float scaleFactor = 25; _screenScale = vLength.Length() / scaleFactor; _screenScaleMatrix = Matrix.CreateScale(new Vector3(_screenScale)); _localForward = Selection[0].Transform.Forward; _localUp = Selection[0].Transform.Up; // -- Vector Rotation (Local/World) -- // _localForward.Normalize(); _localRight = Vector3.Cross(_localForward, _localUp); _localUp = Vector3.Cross(_localRight, _localForward); _localRight.Normalize(); _localUp.Normalize(); // -- Create Both World Matrices -- // _objectOrientedWorld = _screenScaleMatrix * Matrix.CreateWorld(_position, _localForward, _localUp); _axisAlignedWorld = _screenScaleMatrix * Matrix.CreateWorld(_position, SceneWorld.Forward, SceneWorld.Up); // Assign World if (ActiveSpace == TransformSpace.World || ActiveMode == GizmoMode.Rotate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { _gizmoWorld = _axisAlignedWorld; // align lines, boxes etc. with the grid-lines _rotationMatrix.Forward = SceneWorld.Forward; _rotationMatrix.Up = SceneWorld.Up; _rotationMatrix.Right = SceneWorld.Right; } else { _gizmoWorld = _objectOrientedWorld; // align lines, boxes etc. with the selected object _rotationMatrix.Forward = _localForward; _rotationMatrix.Up = _localUp; _rotationMatrix.Right = _localRight; } // -- Reset Colors to default -- // ApplyColor(GizmoAxis.X, _axisColors[0]); ApplyColor(GizmoAxis.Y, _axisColors[1]); ApplyColor(GizmoAxis.Z, _axisColors[2]); // -- Apply Highlight -- // ApplyColor(ActiveAxis, _highlightColor); }
/// <summary> /// Per-frame check to see if mouse is hovering over any axis. /// </summary> private void SelectAxis(Vector2 mousePosition) { if (!Enabled) { return; } float closestintersection = float.MaxValue; Ray ray = ConvertMouseToRay(mousePosition); if (ActiveMode == GizmoMode.Translate) { // transform ray into local-space of the boundingboxes. ray.Direction = Vector3.TransformNormal(ray.Direction, Matrix.Invert(_gizmoWorld)); ray.Position = Vector3.Transform(ray.Position, Matrix.Invert(_gizmoWorld)); } #region X,Y,Z Boxes float?intersection = XAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = YAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = ZAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion if (ActiveMode == GizmoMode.Rotate || ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale) { #region BoundingSpheres intersection = XSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = YSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = ZSphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { // if no axis was hit (x,y,z) set value to lowest possible to select the 'farthest' intersection for the XY,XZ,YZ boxes. // This is done so you may still select multi-axis if you're looking at the gizmo from behind! if (closestintersection >= float.MaxValue) { closestintersection = float.MinValue; } #region BoundingBoxes intersection = XYBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.XY; closestintersection = intersection.Value; } } intersection = XZAxisBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.ZX; closestintersection = intersection.Value; } } intersection = YZBox.Intersects(ray); if (intersection.HasValue) { if (intersection.Value > closestintersection) { ActiveAxis = GizmoAxis.YZ; closestintersection = intersection.Value; } } #endregion } if (closestintersection >= float.MaxValue || closestintersection <= float.MinValue) { ActiveAxis = GizmoAxis.None; } }
/// <summary> /// Per-frame check to see if mouse is hovering over any axis. /// </summary> /// <param name="mousePosition"></param> static void UpdateAxisSelection(Vector2 mousePosition) { float closestintersection = float.MaxValue; MinerWarsMath.Ray ray = MyUtils.ConvertMouseToRay(); closestintersection = float.MaxValue; float? intersection; if (ActiveMode == GizmoMode.TRANSLATE) { #region BoundingBoxes intersection = XY_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.XY; closestintersection = intersection.Value; } } intersection = XZ_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.ZX; closestintersection = intersection.Value; } } intersection = YZ_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.YZ; closestintersection = intersection.Value; } } intersection = X_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (ActiveMode == GizmoMode.ROTATE || ActiveMode == GizmoMode.TRANSLATE) { #region BoundingSpheres intersection = X_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Sphere.Intersects(ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (ActiveMode == GizmoMode.ROTATE) { #region X,Y,Z Boxes intersection = X_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.X; closestintersection = intersection.Value; } } intersection = Y_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Y; closestintersection = intersection.Value; } } intersection = Z_Box.Intersects(ref ray); if (intersection.HasValue) { if (intersection.Value < closestintersection) { ActiveAxis = GizmoAxis.Z; closestintersection = intersection.Value; } } #endregion } if (closestintersection == float.MaxValue) { ActiveAxis = GizmoAxis.NONE; } }
// Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); dragplane = new Plane(); if (Physics.Raycast(ray, out hit, 1000f, layer)) { if (hit.collider == xAxis) { selectedAxis = GizmoAxis.X; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == xAxisNeg) { selectedAxis = GizmoAxis.Xneg; dragplane.SetNormalAndPosition(-transform.up, transform.position); } else if (hit.collider == yAxis) { selectedAxis = GizmoAxis.Y; dragplane.SetNormalAndPosition(transform.forward, transform.position); } else if (hit.collider == yAxisNeg) { selectedAxis = GizmoAxis.Yneg; dragplane.SetNormalAndPosition(-transform.forward, transform.position); } else if (hit.collider == zAxis) { selectedAxis = GizmoAxis.Z; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == zAxisNeg) { selectedAxis = GizmoAxis.Zneg; dragplane.SetNormalAndPosition(-transform.up, transform.position); } else { Debug.Log(hit.collider.name); return; } distance = hit.distance; startDrag = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance)); startPos = transform.position; startScale = transform.localScale; dragging = true; } } if (dragging) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); Vector3 onDrag = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance)); Vector3 translation = onDrag - startDrag; Vector3 projectedTranslation = Vector3.zero; if (dragging) { float lsx = startScale.x; float lsy = startScale.y; float lsz = startScale.z; switch (selectedAxis) { case GizmoAxis.X: { projectedTranslation = Vector3.Project(translation, transform.right); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsx += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, transform.right)); break; } case GizmoAxis.Xneg: { projectedTranslation = Vector3.Project(translation, -transform.right); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsx += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, -transform.right)); break; } case GizmoAxis.Y: { projectedTranslation = Vector3.Project(translation, transform.up); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsy += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, transform.up)); break; } case GizmoAxis.Yneg: { projectedTranslation = Vector3.Project(translation, -transform.up); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsy += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, -transform.up)); break; } case GizmoAxis.Z: { projectedTranslation = Vector3.Project(translation, transform.forward); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsz += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, transform.forward)); break; } case GizmoAxis.Zneg: { projectedTranslation = Vector3.Project(translation, -transform.forward); CreateObject.transform.position = startPos + 0.5f * (projectedTranslation.normalized * translation.magnitude); lsz += translation.magnitude * Mathf.Sign(Vector3.Dot(projectedTranslation, -transform.forward)); break; } } transform.localScale = new Vector3(Mathf.Clamp(lsx, 0.01f, Mathf.Infinity), Mathf.Clamp(lsy, 0.01f, Mathf.Infinity), Mathf.Clamp(lsz, 0.01f, Mathf.Infinity)); foreach (UVScaler uvs in gameObject.GetComponentsInChildren <UVScaler>()) { uvs.SetUV(); } } if (Input.GetMouseButtonUp(0)) { dragging = false; } } }
void Update() { if (Input.GetMouseButtonDown(0)) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); dragplane = new Plane(); if (Physics.Raycast(ray, out hit, 1000f, layer)) { hitvector = hit.point - transform.position; if (hit.collider == xAxis) { selectedAxis = GizmoAxis.X; direction = Vector3.right; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == yAxis) { selectedAxis = GizmoAxis.Y; direction = Vector3.up; dragplane.SetNormalAndPosition(transform.forward, transform.position); } else if (hit.collider == zAxis) { selectedAxis = GizmoAxis.Z; direction = Vector3.forward; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == xyPlane) { selectedAxis = GizmoAxis.XY; dragplane.SetNormalAndPosition(transform.forward, transform.position); } else if (hit.collider == xzPlane) { selectedAxis = GizmoAxis.XZ; dragplane.SetNormalAndPosition(transform.up, transform.position); } else if (hit.collider == yzPlane) { selectedAxis = GizmoAxis.YZ; dragplane.SetNormalAndPosition(transform.right, transform.position); } else if (hit.collider == xyRotate) { selectedAxis = GizmoAxis.XYRotate; rotating = true; } if (dragplane.Raycast(ray, out rayDistance)) { distToCenter = Vector3.Distance(hit.point, transform.position); } dragging = true; } } if (dragging && !rotating) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (dragplane.Raycast(ray, out rayDistance)) { mousePos = ray.GetPoint(rayDistance); } mousePlane = new Plane(); switch (selectedAxis) { case GizmoAxis.X: { mousePlane.SetNormalAndPosition(transform.right, mousePos); ray = new Ray(transform.position, transform.right); break; } case GizmoAxis.Y: { mousePlane.SetNormalAndPosition(transform.up, mousePos); ray = new Ray(transform.position, transform.up); break; } case GizmoAxis.Z: { mousePlane.SetNormalAndPosition(transform.forward, mousePos); ray = new Ray(transform.position, transform.forward); break; } case GizmoAxis.XY: case GizmoAxis.XZ: case GizmoAxis.YZ: { transform.position = mousePos - hitvector; break; } break; } if (mousePlane.Raycast(ray, out rayDistance)) { Vector3 trans = direction * (rayDistance - distToCenter); transform.Translate(trans); } if (Input.GetMouseButtonUp(0)) { SetFalse(); } } if (rotating) { newRotY -= Input.GetAxis("Mouse X") * rotationSpeed; transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, newRotY, transform.localEulerAngles.z); if (Input.GetMouseButtonUp(0)) { SetFalse(); } } }
private void ApplyColor(GizmoAxis a_GizmoAxis, Color a_Color) { if (m_ActiveMode == GizmoMode.TRANSLATE || m_ActiveMode == GizmoMode.NON_LINEAR_SCALE) { switch (a_GizmoAxis) { case GizmoAxis.X: ApplyLineColor(0, 6, a_Color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, a_Color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, a_Color); break; case GizmoAxis.XY: ApplyLineColor(0, 4, a_Color); ApplyLineColor(6, 4, a_Color); break; case GizmoAxis.YZ: ApplyLineColor(6, 2, a_Color); ApplyLineColor(12, 2, a_Color); ApplyLineColor(10, 2, a_Color); ApplyLineColor(16, 2, a_Color); break; case GizmoAxis.ZX: ApplyLineColor(0, 2, a_Color); ApplyLineColor(4, 2, a_Color); ApplyLineColor(12, 4, a_Color); break; } } else if (m_ActiveMode == GizmoMode.ROTATE) { switch (a_GizmoAxis) { case GizmoAxis.X: ApplyLineColor(0, 6, a_Color); break; case GizmoAxis.Y: ApplyLineColor(6, 6, a_Color); break; case GizmoAxis.Z: ApplyLineColor(12, 6, a_Color); break; } } else if (m_ActiveMode == GizmoMode.SCALE) { if (m_ActiveAxis == GizmoAxis.NONE) { ApplyLineColor(0, m_TranslationLineVertices.Length, m_AxisColors[0]); } else { ApplyLineColor(0, m_TranslationLineVertices.Length, m_HighlightColor); } } }
public void Update(GameTime gameTime, bool enableMove) { if (_isActive && enableMove) { Vector3 translateScaleLocal = Vector3.Zero; Vector3 translateScaleWorld = Vector3.Zero; Matrix rotationLocal = Matrix.Identity; Matrix rotationWorld = Matrix.Identity; if (_mouse.IsMouseButtonDown(Input.MouseButton.Left) && ActiveAxis != GizmoAxis.None) { if (_mouse.LastState().LeftButton == ButtonState.Released) { StartEvent?.Invoke(); } switch (ActiveMode) { case GizmoMode.UniformScale: case GizmoMode.NonUniformScale: case GizmoMode.Translate: HandleTranslateAndScale(_mouse.Position(), out translateScaleLocal, out translateScaleWorld); break; case GizmoMode.Rotate: HandleRotation(gameTime, out rotationLocal, out rotationWorld); break; } } else { if (_mouse.LastState().LeftButton == ButtonState.Pressed && _mouse.State().LeftButton == ButtonState.Released) { StopEvent?.Invoke(); } ResetDeltas(); if (_mouse.State().LeftButton == ButtonState.Released && _mouse.State().RightButton == ButtonState.Released) { SelectAxis(_mouse.Position()); } } UpdateGizmoPosition(); // -- Trigger Translation, Rotation & Scale events -- // if (_mouse.IsMouseButtonDown(Input.MouseButton.Left)) { if (translateScaleWorld != Vector3.Zero) { if (ActiveMode == GizmoMode.Translate) { foreach (var entity in Selection) { OnTranslateEvent(entity, translateScaleWorld, translateScaleLocal); } } else { foreach (var entity in Selection) { OnScaleEvent(entity, translateScaleWorld); } } } if (rotationWorld != Matrix.Identity) { foreach (var entity in Selection) { OnRotateEvent(entity, rotationWorld, rotationLocal); } } } } if (Selection.Count == 0) { _isActive = false; ActiveAxis = GizmoAxis.None; return; } // helps solve visual lag (1-frame-lag) after selecting a new entity if (!_isActive) { UpdateGizmoPosition(); } _isActive = true; // -- Scale Gizmo to fit on-screen -- // Vector3 vLength = _camera.Position - _position; const float scaleFactor = 25; _screenScale = vLength.Length() / scaleFactor; var screenScaleMatrix = Matrix.CreateScale(new Vector3(_screenScale * ScaleModifier)); _localForward = Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(Selection[0].Orientation)); //Selection[0].Forward; _localUp = Vector3.Transform(Vector3.Up, Matrix.CreateFromQuaternion(Selection[0].Orientation)); //Selection[0].Up; // -- Vector Rotation (Local/World) -- // _localForward.Normalize(); _localRight = Vector3.Cross(_localForward, _localUp); _localUp = Vector3.Cross(_localRight, _localForward); _localRight.Normalize(); _localUp.Normalize(); // -- Create Both World Matrices -- // _objectOrientedWorld = screenScaleMatrix * Matrix.CreateWorld(_position, _localForward, _localUp); _axisAlignedWorld = screenScaleMatrix * Matrix.CreateWorld(_position, SceneWorld.Forward, SceneWorld.Up); // Assign World if (GizmoDisplaySpace == TransformSpace.World || //ActiveMode == GizmoMode.Rotate || //ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale) { _gizmoWorld = _axisAlignedWorld; // align lines, boxes etc. with the grid-lines _rotationMatrix.Forward = SceneWorld.Forward; _rotationMatrix.Up = SceneWorld.Up; _rotationMatrix.Right = SceneWorld.Right; } else { _gizmoWorld = _objectOrientedWorld; // align lines, boxes etc. with the selected object _rotationMatrix.Forward = _localForward; _rotationMatrix.Up = _localUp; _rotationMatrix.Right = _localRight; } // -- Reset Colors to default -- // ApplyColor(GizmoAxis.X, _axisColors[0]); ApplyColor(GizmoAxis.Y, _axisColors[1]); ApplyColor(GizmoAxis.Z, _axisColors[2]); // -- Apply Highlight -- // ApplyColor(ActiveAxis, _highlightColor); }