/*
* Copyright (c) 2023 Codefoco (codefoco@codefoco.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
using System.ComponentModel;
namespace Tizen.NUI.Physics2D.Chipmunk
{
///
/// Segment queries return where a shape was hit and its surface normal at the point of contact.
/// Use == null to test if a shape was hit. Segment queries
/// are like ray casting, but because not all spatial indexes allow processing infinitely long
/// ray queries, it's limited to segments. In practice, this is still very fast and you don’t
/// need to worry too much about the performance as long as you aren’t using extremely long
/// segments for your queries.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public sealed class SegmentQueryInfo : IEquatable
{
#pragma warning disable IDE0032
private readonly Shape shape;
private readonly Vect point;
private readonly Vect normal;
private readonly double alpha;
#pragma warning restore IDE0032
///
/// Shape that was hit, or None if no collision occured.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Shape Shape => shape;
///
/// The point of impact.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Vect Point => point;
///
/// The normal of the surface that was hit.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Vect Normal => normal;
///
/// The normalized distance along the query segment in the range [0, 1]
///
[EditorBrowsable(EditorBrowsableState.Never)]
public double Alpha => alpha;
///
/// Construct a Segment query info.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public SegmentQueryInfo(Shape s, Vect p, Vect n, double a)
{
shape = s;
point = p;
normal = n;
alpha = a;
}
///
/// Return true if the given object is reference-equal to this one.
///
///
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
var other = obj as SegmentQueryInfo;
if (other == null)
{
return false;
}
return this == other;
}
///
/// Return true if both objects are reference-equal to each other.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool operator ==(SegmentQueryInfo left, SegmentQueryInfo right)
{
if (ReferenceEquals(left, null))
{
return ReferenceEquals(right, null);
}
return left.Equals(right);
}
///
/// Return true if both objects are not reference-equal to each other.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool operator !=(SegmentQueryInfo a, SegmentQueryInfo b)
{
return !(a == b);
}
///
/// Create a SegmentQuery from a native struct cpSegmentQueryInfo.
///
internal static SegmentQueryInfo FromQueryInfo(cpSegmentQueryInfo queryInfo)
{
Shape shape;
if (queryInfo.shape == IntPtr.Zero)
{
shape = null;
}
else
{
shape = Shape.FromHandle(queryInfo.shape);
}
return new SegmentQueryInfo(
shape,
queryInfo.point,
queryInfo.normal,
queryInfo.alpha);
}
///
/// Return true if the fields in both objects are equivalent and the
/// field is within of the other's.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool Equals(SegmentQueryInfo other)
{
if (ReferenceEquals(other, null) ||
shape?.Handle != other.shape?.Handle ||
point != other.point ||
normal != other.normal)
{
return false;
}
return Math.Abs(alpha - other.alpha) < float.Epsilon;
}
///
/// Get the hash code.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
var hashCode = -1275187100;
hashCode = hashCode * -1521134295 + shape.GetHashCode();
hashCode = hashCode * -1521134295 + point.GetHashCode();
hashCode = hashCode * -1521134295 + normal.GetHashCode();
hashCode = hashCode * -1521134295 + alpha.GetHashCode();
return hashCode;
}
}
}