UltimateZoneBuilder/Source/Plugins/UDBScript/API/Vector2DWrapper.cs
biwa 5b2b149b40
UDBScript version 5 (#819)
Improved UDBScript to version 5:

- Added Plane class
- Added BlockMap, BlockEntry, and BlackMapQueryResult classes
- Sector class
  - Added getLabelPositions method to get the position of sector labels (where tags, effects etc. are displayed)
- Added support for JavaScript BigInt for UDMF fields. This means it's not necessary anymore to use UniValue to assign integers to new UDMF fields. Instead it can be done like this: sector.fields.my_int_field = 1n;
- Added type information file (udbscript.d.ts)
2022-11-13 01:15:17 +01:00

717 lines
18 KiB
C#

#region ================== Copyright (c) 2021 Boris Iwanski
/*
* This program is free software: you can redistribute it and/or modify
*
* it under the terms of the GNU General Public License as published by
*
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
*
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.If not, see<http://www.gnu.org/licenses/>.
*/
#endregion
#region ================== Namespaces
using System.Dynamic;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
internal struct Vector2DWrapper
{
#region ================== Variables
public double _x;
public double _y;
private readonly MapElement parent;
#endregion
#region ================== Properties
/// <summary>
/// The `x` value of the vector.
/// </summary>
public double x
{
get
{
return _x;
}
set
{
_x = value;
if (parent is Vertex)
((Vertex)parent).Move(new Vector2D(_x, _y));
else if (parent is Thing)
((Thing)parent).Move(new Vector2D(_x, _y));
}
}
/// <summary>
/// The `y` value of the vector.
/// </summary>
public double y
{
get
{
return _y;
}
set
{
_y = value;
if (parent is Vertex)
((Vertex)parent).Move(new Vector2D(_x, _y));
else if (parent is Thing)
((Thing)parent).Move(new Vector2D(_x, _y));
}
}
#endregion
#region ================== Constructors
internal Vector2DWrapper(Vector2D v, MapElement parent = null)
{
_x = v.x;
_y = v.y;
this.parent = parent;
}
internal Vector2DWrapper(double x, double y, MapElement parent)
{
_x = x;
_y = y;
this.parent = parent;
}
/// <summary>
/// Creates a new `Vector2D` from x and y coordinates
/// ```
/// let v = new UDB.Vector2D(32, 64);
/// ```
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
public Vector2DWrapper(double x, double y)
{
this._x = x;
this._y = y;
parent = null;
}
/// <summary>
/// Creates a new `Vector2D` from a point.
/// ```
/// let v = new UDB.Vector2D([ 32, 64 ]);
/// ```
/// </summary>
/// <param name="v">The vector to create the `Vector2D` from</param>
public Vector2DWrapper(object v)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(v);
_x = v1.x;
_y = v1.y;
parent = null;
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
#endregion
#region ================== Internal
internal Vector2D AsVector2D()
{
return new Vector2D(_x, _y);
}
#endregion
#region ================== Operators
public static implicit operator Vector3DWrapper(Vector2DWrapper a)
{
return new Vector3DWrapper(a._x, a._y, 0.0);
}
#region ================== Addition
public static object operator +(Vector2DWrapper lhs, object rhs)
{
if (rhs is double)
{
return new Vector2DWrapper(lhs._x + (double)rhs, lhs._y + (double)rhs);
}
else if (rhs.GetType().IsArray || rhs is ExpandoObject || rhs is Vector2DWrapper || rhs is Vector3DWrapper)
{
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(rhs);
return new Vector2DWrapper(lhs._x + v.x, lhs._y + v.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
else
{
return lhs.ToString() + rhs.ToString();
}
}
public static object operator +(object lhs, Vector2DWrapper rhs)
{
if (lhs is double)
{
return new Vector2DWrapper((double)lhs + rhs._x, (double)lhs + rhs._y);
}
else if (lhs.GetType().IsArray || lhs is ExpandoObject || lhs is Vector2DWrapper || lhs is Vector3DWrapper)
{
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(lhs);
return new Vector2DWrapper(v.x + rhs._x, v.y + rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
else
{
return lhs.ToString() + rhs.ToString();
}
}
#endregion
#region ================== Subtraction
public static object operator -(Vector2DWrapper lhs, object rhs)
{
if (rhs is double)
return new Vector2DWrapper(lhs._x - (double)rhs, lhs._y - (double)rhs);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(rhs);
return new Vector2DWrapper(lhs._x - v.x, lhs._y - v.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static object operator -(object lhs, Vector2DWrapper rhs)
{
if (lhs is double)
return new Vector2DWrapper((double)lhs - rhs._x, (double)lhs - rhs._y);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(lhs);
return new Vector2DWrapper(v.x - rhs._x, v.y - rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static Vector2DWrapper operator -(Vector2DWrapper a)
{
return new Vector2DWrapper(-a._x, -a._y);
}
#endregion
#region ================== Multiply
public static object operator *(Vector2DWrapper lhs, object rhs)
{
if (rhs is double)
return new Vector2DWrapper(lhs._x * (double)rhs, lhs._y * (double)rhs);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(rhs);
return new Vector2DWrapper(lhs._x * v.x, lhs._y * v.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static object operator *(object lhs, Vector2DWrapper rhs)
{
if (lhs is double)
return new Vector2DWrapper((double)lhs * rhs._x, (double)lhs * rhs._y);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(lhs);
return new Vector2DWrapper(v.x * rhs._x, v.y * rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
#endregion
#region ================== Divide
public static object operator /(Vector2DWrapper lhs, object rhs)
{
if (rhs is double)
return new Vector2DWrapper(lhs._x / (double)rhs, lhs._y / (double)rhs);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(rhs);
return new Vector2DWrapper(lhs._x / v.x, lhs._y / v.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static object operator /(object lhs, Vector2DWrapper rhs)
{
if (lhs is double)
return new Vector2DWrapper(rhs._x / (double)lhs, rhs._y / (double)lhs);
try
{
Vector2D v = BuilderPlug.Me.GetVector3DFromObject(lhs);
return new Vector2DWrapper(v.x / rhs._x, v.y / rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
#endregion
#region ================== Equality
public static bool operator ==(Vector2DWrapper lhs, object rhs)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(rhs);
return (lhs._x == v1.x) && (lhs._y == v1.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static bool operator ==(object lhs, Vector2DWrapper rhs)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(lhs);
return (v1.x == rhs._x) && (v1.y == rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static bool operator !=(Vector2DWrapper lhs, object rhs)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(rhs);
return (lhs._x != v1.x) || (lhs._y != v1.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
public static bool operator !=(object lhs, Vector2DWrapper rhs)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(lhs);
return (v1.x != rhs._x) || (v1.y != rhs._y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
#endregion
#endregion
#region ================== Statics
/// <summary>
/// Returns the dot product of two `Vector2D`s.
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>The dot product of the two vectors</returns>
public static double dotProduct(Vector2DWrapper a, Vector2DWrapper b)
{
// Calculate and return the dot product
return a._x * b._x + a._y * b._y;
}
/// <summary>
/// Returns the cross product of two `Vector2D`s.
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>Cross product of the two vectors as `Vector2D`</returns>
public static Vector2DWrapper crossProduct(object a, object b)
{
try
{
Vector2D a1 = BuilderPlug.Me.GetVector3DFromObject(a);
Vector2D b1 = BuilderPlug.Me.GetVector3DFromObject(b);
return new Vector2DWrapper(a1.y * b1.x, a1.x * b1.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Reflects a `Vector2D` over a mirror `Vector2D`.
/// </summary>
/// <param name="v">`Vector2D` to reflect</param>
/// <param name="m">Mirror `Vector2D`</param>
/// <returns>The reflected vector as `Vector2D`</returns>
public static Vector2DWrapper reflect(object v, object m)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(v);
Vector2D m1 = BuilderPlug.Me.GetVector3DFromObject(m);
Vector2D mv = Vector2D.Reflect(v1, m1);
return new Vector2DWrapper(mv.x, mv.y);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Returns a reversed `Vector2D`.
/// </summary>
/// <param name="v">`Vector2D` to reverse</param>
/// <returns>The reversed vector as `Vector2D`</returns>
public static Vector2DWrapper reversed(object v)
{
try
{
Vector2D v1 = BuilderPlug.Me.GetVector3DFromObject(v);
return new Vector2DWrapper(Vector2D.Reversed(v1));
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Creates a `Vector2D` from an angle in radians,
/// </summary>
/// <param name="angle">Angle in radians</param>
/// <returns>Vector as `Vector2D`</returns>
public static Vector2DWrapper fromAngleRad(double angle)
{
return new Vector2DWrapper(Vector2D.FromAngle(angle));
}
/// <summary>
/// Creates a `Vector2D` from an angle in degrees,
/// </summary>
/// <param name="angle">Angle in degrees</param>
/// <returns>Vector as `Vector2D`</returns>
public static Vector2DWrapper fromAngle(double angle)
{
return new Vector2DWrapper(Vector2D.FromAngle(Angle2D.DegToRad(angle)));
}
/// <summary>
/// Returns the angle between two `Vector2D`s in radians
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>Angle in radians</returns>
public static double getAngleRad(object a, object b)
{
try
{
Vector2D a1 = BuilderPlug.Me.GetVector3DFromObject(a);
Vector2D b1 = BuilderPlug.Me.GetVector3DFromObject(b);
return Vector2D.GetAngle(a1, b1);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Returns the angle between two `Vector2D`s in degrees.
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>Angle in degrees</returns>
public static double getAngle(object a, object b)
{
try
{
Vector2D a1 = BuilderPlug.Me.GetVector3DFromObject(a);
Vector2D b1 = BuilderPlug.Me.GetVector3DFromObject(b);
return Angle2D.RadToDeg(Vector2D.GetAngle(a1, b1));
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Returns the square distance between two `Vector2D`s.
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>The squared distance</returns>
public static double getDistanceSq(object a, object b)
{
try
{
Vector2D a1 = BuilderPlug.Me.GetVector3DFromObject(a);
Vector2D b1 = BuilderPlug.Me.GetVector3DFromObject(b);
return Vector2D.DistanceSq(a1, b1);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
/// <summary>
/// Returns the distance between two `Vector2D`s.
/// </summary>
/// <param name="a">First `Vector2D`</param>
/// <param name="b">Second `Vector2D`</param>
/// <returns>The distance</returns>
public static double getDistance(object a, object b)
{
try
{
Vector2D a1 = BuilderPlug.Me.GetVector3DFromObject(a);
Vector2D b1 = BuilderPlug.Me.GetVector3DFromObject(b);
return Vector2D.Distance(a1, b1);
}
catch (CantConvertToVectorException e)
{
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
}
}
#endregion
#region ================== Methods
/// <summary>
/// Returns the perpendicular to the `Vector2D`.
/// </summary>
/// <returns>The perpendicular as `Vector2D`</returns>
public Vector2DWrapper getPerpendicular()
{
return new Vector2DWrapper(-_y, _x);
}
/// <summary>
/// Returns a `Vector2D` with the sign of all components.
/// </summary>
/// <returns>A `Vector2D` with the sign of all components</returns>
public Vector2DWrapper getSign()
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetSign());
}
/// <summary>
/// Returns the angle of the `Vector2D` in radians.
/// </summary>
/// <returns>The angle of the `Vector2D` in radians</returns>
public double getAngleRad()
{
return new Vector2D(_x, _y).GetAngle();
}
/// <summary>
/// Returns the angle of the `Vector2D` in degree.
/// </summary>
/// <returns>The angle of the `Vector2D` in degree</returns>
public double getAngle()
{
return Angle2D.RadToDeg(new Vector2D(_x, _y).GetAngle());
}
/// <summary>
/// Returns the length of the `Vector2D`.
/// </summary>
/// <returns>The length of the `Vector2D`</returns>
public double getLength()
{
return new Vector2D(_x, _y).GetLength();
}
/// <summary>
/// Returns the square length of the `Vector2D`.
/// </summary>
/// <returns>The square length of the `Vector2D`</returns>
public double getLengthSq()
{
return new Vector2D(_x, _y).GetLengthSq();
}
/// <summary>
/// Returns the normal of the `Vector2D`.
/// </summary>
/// <returns>The normal as `Vector2D`</returns>
public Vector2DWrapper getNormal()
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetNormal());
}
/// <summary>
/// Returns the transformed vector as `Vector2D`.
/// </summary>
/// <param name="offsetx">X offset</param>
/// <param name="offsety">Y offset</param>
/// <param name="scalex">X scale</param>
/// <param name="scaley">Y scale</param>
/// <returns>The transformed vector as `Vector2D`</returns>
public Vector2DWrapper getTransformed(double offsetx, double offsety, double scalex, double scaley)
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetTransformed(offsetx, offsety, scalex, scaley));
}
/// <summary>
/// Returns the inverse transformed vector as `Vector2D`.
/// </summary>
/// <param name="invoffsetx">X offset</param>
/// <param name="invoffsety">Y offset</param>
/// <param name="invscalex">X scale</param>
/// <param name="invscaley">Y scale</param>
/// <returns>The inverse transformed vector as `Vector2D`</returns>
public Vector2DWrapper getInverseTransformed(double invoffsetx, double invoffsety, double invscalex, double invscaley)
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetInvTransformed(invoffsetx, invoffsety, invscalex, invscaley));
}
/// <summary>
/// Returns the rotated vector as `Vector2D`.
/// </summary>
/// <param name="theta">Angle in degree to rotate by</param>
/// <returns>The rotated `Vector2D`</returns>
public Vector2DWrapper getRotated(double theta)
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetRotated(Angle2D.DegToRad(theta)));
}
/// <summary>
/// Returns the rotated vector as `Vector2D`.
/// </summary>
/// <param name="theta">Angle in radians to rotate by</param>
/// <returns>The rotated `Vector2D`</returns>
public Vector2DWrapper getRotatedRad(double theta)
{
return new Vector2DWrapper(new Vector2D(_x, _y).GetRotated(theta));
}
/// <summary>
/// Checks if the `Vector2D` is finite or not.
/// </summary>
/// <returns>`true` if `Vector2D` is finite, otherwise `false`</returns>
public bool isFinite()
{
return new Vector2D(_x, _y).IsFinite();
}
public override string ToString()
{
return new Vector2D(_x, _y).ToString();
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is Vector2DWrapper)) return false;
Vector2DWrapper other = (Vector2DWrapper)obj;
if (_x != other._x) return false;
if (_y != other._y) return false;
return true;
}
#endregion
}
}