public bool CollidesWith(float x, float y, IViewport viewport) { var boundingBoxesComponent = _boundingBox; if (boundingBoxesComponent == null) { return(false); } if (_crop?.IsGuaranteedToFullyCrop() ?? false) { //This should not be needed as the bounding box should be cropped anyway. //However, for a performance optimization if an entity is guaranteed to be fully cropped (like items in the bottom of a long listbox) the bounding box is not calculated, so we need to take it into account here. return(false); } AGSBoundingBox boundingBox = boundingBoxesComponent.WorldBoundingBox; var pixelPerfectComponent = _pixelPerfect; IArea pixelPerfect = pixelPerfectComponent == null || !pixelPerfectComponent.IsPixelPerfect ? null : pixelPerfectComponent.PixelPerfectHitTestArea; var drawable = _drawableInfo; if (drawable != null && !drawable.IgnoreViewport) { var matrix = viewport.GetMatrix(drawable.RenderLayer); matrix.Invert(); Vector3 xyz = new Vector3(x, y, 0f); Vector3.Transform(ref xyz, ref matrix, out xyz); //todo: (support ignore scaling areas = false?) x = xyz.X; y = xyz.Y; } if (pixelPerfect == null || !pixelPerfect.Enabled) { if (!boundingBox.IsValid) { return(false); } if (boundingBox.Contains(new Vector2(x, y))) { return(true); } } else { var obj = _obj; float objScaleX = obj == null ? 1f : obj.CurrentSprite.ScaleX; float objScaleY = obj == null ? 1f : obj.CurrentSprite.ScaleY; var scale = _scale; float scaleX = scale == null ? 1f : scale.ScaleX; float scaleY = scale == null ? 1f : scale.ScaleY; if (pixelPerfect.IsInArea(new PointF(x, y), boundingBox, scaleX * objScaleX, scaleY * objScaleY)) { return(true); } } return(false); }
public bool CollidesWith(float x, float y, IViewport viewport) { var boundingBoxesComponent = _boundingBox; if (boundingBoxesComponent == null) { return(false); } AGSBoundingBox boundingBox = boundingBoxesComponent.WorldBoundingBox; var pixelPerfectComponent = _pixelPerfect; IArea pixelPerfect = pixelPerfectComponent == null || !pixelPerfectComponent.IsPixelPerfect ? null : pixelPerfectComponent.PixelPerfectHitTestArea; if (!(_drawableInfo?.IgnoreViewport ?? false)) { var matrix = viewport.GetMatrix(_drawableInfo.RenderLayer); matrix.Invert(); Vector3 xyz = new Vector3(x, y, 0f); Vector3.Transform(ref xyz, ref matrix, out xyz); //todo: (support ignore scaling areas = false?) x = xyz.X; y = xyz.Y; } if (pixelPerfect == null || !pixelPerfect.Enabled) { if (!boundingBox.IsValid) { return(false); } if (boundingBox.Contains(new Vector2(x, y))) { return(true); } } else { var obj = _obj; float objScaleX = obj == null ? 1f : obj.CurrentSprite.ScaleX; float objScaleY = obj == null ? 1f : obj.CurrentSprite.ScaleY; var scale = _scale; float scaleX = scale == null ? 1f : scale.ScaleX; float scaleY = scale == null ? 1f : scale.ScaleY; if (pixelPerfect.IsInArea(new PointF(x, y), boundingBox, scaleX * objScaleX, scaleY * objScaleY)) { return(true); } } return(false); }
/// <summary> /// Get the mouse position in a specific viewport coordinates, projected onto /// a specific object's world. /// </summary> /// <returns>The projected point.</returns> /// <param name="viewport">Viewport.</param> /// <param name="projectedInto">Projected into.</param> public Vector2 GetProjectedPoint(IViewport viewport, IObject projectedInto) { float windowWidth = GetWindowWidth(); float windowHeight = GetWindowHeight(); var projectBottom = windowHeight - viewport.ProjectionBox.Y * windowHeight; var projectTop = projectBottom - viewport.ProjectionBox.Height * windowHeight; var projectLeft = viewport.ProjectionBox.X * windowWidth; var projectRight = projectLeft + viewport.ProjectionBox.Width * windowWidth; var parentBoundingBoxes = viewport.Parent?.GetBoundingBoxes(_mainViewport); if (parentBoundingBoxes != null) { projectLeft += parentBoundingBoxes.ViewportBox.MinX; projectRight += parentBoundingBoxes.ViewportBox.MinX; projectBottom -= parentBoundingBoxes.ViewportBox.MinY; projectTop -= parentBoundingBoxes.ViewportBox.MinY; } float y = MathUtils.Lerp(projectTop, VirtualResolution.Height, projectBottom, 0f, YWindow); float x = MathUtils.Lerp(projectLeft, 0f, projectRight, VirtualResolution.Width, XWindow); var matrix = viewport.GetMatrix(projectedInto.RenderLayer); matrix.Invert(); Vector3 xyz = new Vector3(x, y, 0f); Vector3.Transform(ref xyz, ref matrix, out xyz); x = xyz.X; y = xyz.Y; var hitTestBox = projectedInto.TreeNode.Parent?.WorldBoundingBox; if (hitTestBox?.IsValid ?? false) { x -= hitTestBox.Value.MinX; y -= hitTestBox.Value.MinY; } var renderLayer = projectedInto.RenderLayer; if (renderLayer?.IndependentResolution != null) { float maxX = renderLayer.IndependentResolution.Value.Width; float maxY = renderLayer.IndependentResolution.Value.Height; x = MathUtils.Lerp(0f, 0f, VirtualResolution.Width, maxX, x); y = MathUtils.Lerp(0f, 0f, VirtualResolution.Height, maxY, y); } return(new Vector2(x, y)); }
public PointF WindowToObject(IViewport viewport, IObject obj, PointF position) { var projectBottom = Window.AppWindowHeight - viewport.ScreenArea.Y - viewport.ProjectionBox.Y * viewport.ScreenArea.Height; var projectTop = projectBottom - viewport.ProjectionBox.Height * viewport.ScreenArea.Height; var parentBoundingBoxes = viewport.Parent?.GetBoundingBoxes(_mainViewport); if (parentBoundingBoxes != null) { projectBottom -= parentBoundingBoxes.ViewportBox.MinY; projectTop -= parentBoundingBoxes.ViewportBox.MinY; } var projectLeft = viewport.ScreenArea.X; var projectRight = projectLeft + viewport.ScreenArea.Width; float y = MathUtils.Lerp(projectTop, _virtualResolution.Height, projectBottom, 0f, position.Y); float x = MathUtils.Lerp(projectLeft, 0f, projectRight, _virtualResolution.Width, position.X); var matrix = viewport.GetMatrix(obj.RenderLayer); matrix.Invert(); Vector3 xyz = new Vector3(x, y, 0f); Vector3.Transform(ref xyz, ref matrix, out xyz); x = xyz.X; y = xyz.Y; var hitTestBox = obj.TreeNode.Parent?.WorldBoundingBox; if (hitTestBox?.IsValid ?? false) { x -= hitTestBox.Value.MinX; y -= hitTestBox.Value.MinY; } var renderLayer = obj.RenderLayer; if (renderLayer?.IndependentResolution != null) { float maxX = renderLayer.IndependentResolution.Value.Width; float maxY = renderLayer.IndependentResolution.Value.Height; x = MathUtils.Lerp(0f, 0f, _virtualResolution.Width, maxX, x); y = MathUtils.Lerp(0f, 0f, _virtualResolution.Height, maxY, y); } return(new PointF(x, y)); }
private AGSBoundingBoxes recalculate(IViewport viewport, ViewportBoundingBoxes viewportBoxes) { var boundingBoxes = viewportBoxes.BoundingBoxes; var drawable = _drawable; var matrix = _matrix; var scale = _scale; var sprite = _image?.CurrentSprite; bool isHitTestBoxDirty = _isHitTestBoxDirty; if (scale == null || drawable == null || matrix == null) { return(boundingBoxes); } var baseSize = sprite?.BaseSize ?? scale.BaseSize; if (isHitTestBoxDirty) { _isCropDirty = true; _isHitTestBoxDirty = false; updateHitTestBox(baseSize, drawable, matrix); } var crop = _crop; _areViewportsDirty = false; viewportBoxes.IsDirty = false; bool resolutionMatches = AGSModelMatrixComponent.GetVirtualResolution(false, _settings.VirtualResolution, drawable, null, out PointF _, out Size _); var viewportMatrix = drawable.IgnoreViewport ? Matrix4.Identity : viewport.GetMatrix(drawable.RenderLayer); AGSBoundingBox intermediateBox, hitTestBox; hitTestBox = _hitTestBox; float width = baseSize.Width; float height = baseSize.Height; if (resolutionMatches) { intermediateBox = _intermediateBox; } else { var modelMatrices = matrix.GetModelMatrices(); var modelMatrix = modelMatrices.InObjResolutionMatrix; intermediateBox = _boundingBoxBuilder.BuildIntermediateBox(width, height, ref modelMatrix); } var renderBox = _boundingBoxBuilder.BuildRenderBox(ref intermediateBox, ref viewportMatrix, out PointF renderCropScale); PointF hitTestCropScale = renderCropScale; if (MathUtils.FloatEquals(hitTestCropScale.X, 1f) && MathUtils.FloatEquals(hitTestCropScale.Y, 1f)) { hitTestCropScale = new PointF(_hitTestBox.Width / renderBox.Width, _hitTestBox.Height / renderBox.Height); } var cropInfo = renderBox.Crop(BoundingBoxType.Render, crop, renderCropScale); boundingBoxes.PreCropViewportBox = renderBox; renderBox = cropInfo.BoundingBox; boundingBoxes.ViewportBox = renderBox; if (cropInfo.TextureBox != null) { boundingBoxes.TextureBox = cropInfo.TextureBox; } else { var textureOffset = _textureOffset; var image = sprite?.Image; // ReSharper disable CompareOfFloatsByEqualityOperator if (image != null && (width != image.Width || height != image.Height || // ReSharper restore CompareOfFloatsByEqualityOperator (!textureOffset?.TextureOffset.Equals(PointF.Empty) ?? false))) { var offset = textureOffset?.TextureOffset ?? PointF.Empty; setProportionalTextureSize(boundingBoxes, image, width, height, offset); } else { boundingBoxes.TextureBox = null; } } if (cropInfo.Equals(_defaultCropInfo)) { boundingBoxes.WorldBox = default; } else { hitTestBox = hitTestBox.Crop(BoundingBoxType.HitTest, crop, hitTestCropScale).BoundingBox; boundingBoxes.WorldBox = hitTestBox; } _isCropDirty = false; return(boundingBoxes); }