public bool MoveObject(Vector2 relativeFrom, Vector2 relativeDelta, CameraBase camera, bool tryToClone, [CanBeNull] out IMoveable cloned) { if (_keepHighlight) { tryToClone = false; } else { _keepHighlight = true; } if (_justCloned) { tryToClone = false; } cloned = null; if (_arrowHighlighted != default(Vector3)) { var plane = new Plane(ParentMatrix.GetTranslationVector(), -camera.Look); var rayFrom = camera.GetPickingRay(relativeFrom, new Vector2(1f, 1f)); var rayTo = camera.GetPickingRay(relativeFrom + relativeDelta, new Vector2(1f, 1f)); if (!Ray.Intersects(rayFrom, plane, out var distanceFrom) || !Ray.Intersects(rayTo, plane, out var distanceTo)) { return(false); } var pointDelta = rayTo.Direction * distanceTo - rayFrom.Direction * distanceFrom; if (tryToClone) { cloned = _parent.Clone(); _justCloned = true; } var totalDistance = pointDelta.Length(); var resultMovement = new Vector3( pointDelta.X * _arrowHighlighted.X, pointDelta.Y * _arrowHighlighted.Y, pointDelta.Z * _arrowHighlighted.Z); resultMovement.Normalize(); resultMovement *= totalDistance; _parent.Move(resultMovement); UpdateBoundingBox(); return(true); } if (_circleHighlighted != default(Vector3)) { var rotationAxis = _circleHighlighted.X * _circleHighlighted.Y * _circleHighlighted.Z != 0f ? camera.Look : _circleHighlighted; if (tryToClone) { cloned = _parent.Clone(); _justCloned = true; } _parent.Rotate(Quaternion.RotationAxis(rotationAxis, relativeDelta.X * 10f)); UpdateBoundingBox(); return(true); } if (_scaleHighlighted) { var v = relativeDelta.X + relativeDelta.Y; _parent.Scale(new Vector3(v > 0f ? 1.01f : 1f / 1.01f)); UpdateBoundingBox(); return(true); } return(false); }