mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-26 05:41:45 +00:00
5eb438e3ba
Added map scripting capabilities to UDB (#656). Documentation at https://biwa.github.io/udbscript-docs/
751 lines
22 KiB
C#
751 lines
22 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;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Dynamic;
|
|
using System.Linq;
|
|
using CodeImp.DoomBuilder.Geometry;
|
|
using CodeImp.DoomBuilder.Map;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
|
|
{
|
|
class LinedefWrapper : MapElementWrapper, IMoreTags, IEquatable<LinedefWrapper>
|
|
{
|
|
#region ================== Variables
|
|
|
|
private Linedef linedef;
|
|
private MapElementArgumentsWrapper elementargs;
|
|
|
|
#endregion
|
|
|
|
#region IEquatable<LinedefWrapper> members
|
|
|
|
public bool Equals(LinedefWrapper other)
|
|
{
|
|
return linedef == other.linedef;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return Equals((LinedefWrapper)obj);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return linedef.GetHashCode();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
/// <summary>
|
|
/// The linedef's index. Read-only.
|
|
/// </summary>
|
|
public int index
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the index property can not be accessed.");
|
|
|
|
return linedef.Index;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The linedef's start `Vertex`.
|
|
/// </summary>
|
|
public VertexWrapper start
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the start property can not be accessed.");
|
|
|
|
return new VertexWrapper(linedef.Start);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The linedef's end `Vertex`.
|
|
/// </summary>
|
|
public VertexWrapper end
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the end property can not be accessed.");
|
|
|
|
return new VertexWrapper(linedef.End);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s front `Sidedef`. Is `null` when there is no front (should not happen).
|
|
/// </summary>
|
|
public SidedefWrapper front
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the front property can not be accessed.");
|
|
|
|
if (linedef.Front == null)
|
|
return null;
|
|
|
|
return new SidedefWrapper(linedef.Front);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s back `Sidedef`. Is `null` when there is no back.
|
|
/// </summary>
|
|
public SidedefWrapper back
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the back property can not be accessed.");
|
|
|
|
if (linedef.Back == null)
|
|
return null;
|
|
|
|
return new SidedefWrapper(linedef.Back);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Line2D` from the `start` to the `end` `Vertex`.
|
|
/// </summary>
|
|
public Line2DWrapper line
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the line property can not be accessed.");
|
|
|
|
return new Line2DWrapper(linedef.Line);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If the `Linedef` is selected or not.
|
|
/// </summary>
|
|
public bool selected
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the selected property can not be accessed.");
|
|
|
|
return linedef.Selected;
|
|
}
|
|
set
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the selected property can not be accessed.");
|
|
|
|
linedef.Selected = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If the `Linedef` is marked or not. It is used to mark map elements that were created or changed (for example after drawing new geometry).
|
|
/// </summary>
|
|
public bool marked
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the marked property can not be accessed.");
|
|
|
|
return linedef.Marked;
|
|
}
|
|
set
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the marked property can not be accessed.");
|
|
|
|
linedef.Marked = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The activation flag. Hexen format only.
|
|
/// </summary>
|
|
public int activate
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the activate property can not be accessed.");
|
|
|
|
return linedef.Activate;
|
|
}
|
|
set
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the activate property can not be accessed.");
|
|
|
|
linedef.Activate = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// `Linedef` flags. It's an object with the flags as properties. In Doom format and Hexen format they are identified by numbers, in UDMF by their name.
|
|
/// Doom and Hexen:
|
|
/// ```
|
|
/// ld.flags['64'] = true; // Set the block sound flag
|
|
/// ```
|
|
/// UDMF:
|
|
/// ```
|
|
/// ld.flags['blocksound'] = true; // Set the block sound flag
|
|
/// ld.flags.blocksound = true; // Also works
|
|
/// ```
|
|
/// </summary>
|
|
public ExpandoObject flags
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the flags property can not be accessed.");
|
|
|
|
dynamic eo = new ExpandoObject();
|
|
IDictionary<string, object> o = eo as IDictionary<string, object>;
|
|
|
|
foreach (KeyValuePair<string, bool> kvp in linedef.GetFlags())
|
|
{
|
|
o.Add(kvp.Key, kvp.Value);
|
|
}
|
|
|
|
// Create event that gets called when a property is changed. This sets the flag
|
|
((INotifyPropertyChanged)eo).PropertyChanged += new PropertyChangedEventHandler((sender, ea) => {
|
|
PropertyChangedEventArgs pcea = ea as PropertyChangedEventArgs;
|
|
IDictionary<string, object> so = sender as IDictionary<string, object>;
|
|
|
|
// Only allow known flags to be set
|
|
if (!General.Map.Config.LinedefFlags.Keys.Contains(pcea.PropertyName) && !General.Map.Config.LinedefActivates.Any(lai => lai.Key == pcea.PropertyName))
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Flag name '" + pcea.PropertyName + "' is not valid.");
|
|
|
|
// New value must be bool
|
|
if (!(so[pcea.PropertyName] is bool))
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Flag values must be bool.");
|
|
|
|
linedef.SetFlag(pcea.PropertyName, (bool)so[pcea.PropertyName]);
|
|
});
|
|
|
|
return eo;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// `Array` of arguments of the `Linedef`. Number of arguments depends on game config (usually 5). Hexen format and UDMF only.
|
|
/// </summary>
|
|
public MapElementArgumentsWrapper args
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the args property can not be accessed.");
|
|
|
|
return elementargs;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// `Linedef` action.
|
|
/// </summary>
|
|
public int action
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the action property can not be accessed.");
|
|
|
|
return linedef.Action;
|
|
}
|
|
set
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the action property can not be accessed.");
|
|
|
|
linedef.Action = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// `Linedef` tag. UDMF only.
|
|
/// </summary>
|
|
public int tag
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the tag property can not be accessed.");
|
|
|
|
return linedef.Tag;
|
|
}
|
|
set
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the tag property can not be accessed.");
|
|
|
|
linedef.Tag = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s squared length. Read-only.
|
|
/// </summary>
|
|
public double lengthSq
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the lengthSq property can not be accessed.");
|
|
|
|
return linedef.LengthSq;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s length. Read-only.
|
|
/// </summary>
|
|
public double length
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the length property can not be accessed.");
|
|
|
|
return linedef.Length;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 1.0 / length. Read-only.
|
|
/// </summary>
|
|
public double lengthInv
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the lengthInv property can not be accessed.");
|
|
|
|
return linedef.LengthInv;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s angle in degree. Read-only.
|
|
/// </summary>
|
|
public int angle
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the angle property can not be accessed.");
|
|
|
|
return linedef.AngleDeg;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The `Linedef`'s angle in radians. Read-only.
|
|
/// </summary>
|
|
public double angleRad
|
|
{
|
|
get
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the angleRad property can not be accessed.");
|
|
|
|
return linedef.Angle;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructors
|
|
|
|
internal LinedefWrapper(Linedef linedef) : base(linedef)
|
|
{
|
|
this.linedef = linedef;
|
|
elementargs = new MapElementArgumentsWrapper(linedef);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Update
|
|
|
|
internal override void AfterFieldsUpdate()
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
public override string ToString()
|
|
{
|
|
return linedef.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies the properties of this `Linedef` to another `Linedef`.
|
|
/// </summary>
|
|
/// <param name="other">The `Linedef` to copy the properties to</param>
|
|
public void copyPropertiesTo(LinedefWrapper other)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the copyPropertiesTo method can not be accessed.");
|
|
|
|
linedef.CopyPropertiesTo(other.linedef);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears all flags.
|
|
/// </summary>
|
|
public void clearFlags()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the clearFlags medhot can not be accessed.");
|
|
|
|
linedef.ClearFlags();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flips the `Linedef`'s vertex attachments.
|
|
/// </summary>
|
|
public void flipVertices()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the flipVertices method can not be accessed.");
|
|
|
|
linedef.FlipVertices();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flips the `Linedef`'s `Sidedef`s.
|
|
/// </summary>
|
|
public void flipSidedefs()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the flipSidedefs method can not be accessed.");
|
|
|
|
linedef.FlipSidedefs();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flips the `Linedef`'s vertex attachments and `Sidedef`s. This is a shortcut to using both `flipVertices()` and `flipSidedefs()`.
|
|
/// </summary>
|
|
public void flip()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the flip method can not be accessed.");
|
|
|
|
linedef.FlipVertices();
|
|
linedef.FlipSidedefs();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a `Vector2D` for testing on one side. The `Vector2D` is on the front when `true` is passed, otherwise on the back.
|
|
/// </summary>
|
|
/// <param name="front">`true` for front, `false` for back</param>
|
|
/// <returns>`Vector2D` that's either on the front of back of the Linedef</returns>
|
|
public Vector2DWrapper getSidePoint(bool front)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the getSidePoint method can not be accessed.");
|
|
|
|
return new Vector2DWrapper(linedef.GetSidePoint(front));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a `Vector2D` that's in the center of the `Linedef`.
|
|
/// </summary>
|
|
/// <returns>`Vector2D` in the center of the `Linedef`</returns>
|
|
public Vector2DWrapper getCenterPoint()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the getCenterPoint method can not be accessed.");
|
|
|
|
return new Vector2DWrapper(linedef.GetCenterPoint());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Automatically sets the blocking and two-sided flags based on the existing `Sidedef`s.
|
|
/// </summary>
|
|
public void applySidedFlags()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the applySidedFlags method can not be accessed.");
|
|
|
|
linedef.ApplySidedFlags();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a `Vector2D` that's *on* the line, closest to `pos`. `pos` can either be a `Vector2D`, or an array of numbers.
|
|
/// ```
|
|
/// var v1 = ld.nearestOnLine(new Vector2D(32, 64));
|
|
/// var v2 = ld.nearestOnLine([ 32, 64 ]);
|
|
/// ```
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <returns>`Vector2D` that's on the linedef</returns>
|
|
public Vector2DWrapper nearestOnLine(object pos)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the nearestOnLine method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return new Vector2DWrapper(linedef.NearestOnLine(v));
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the shortest "safe" squared distance from `pos` to the line. If `bounded` is `true` that means that the not the whole line's length will be used, but `lengthInv` less at the start and end.
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <param name="bounded">`true` if only the finite length of the line should be used, `false` if the infinite length of the line should be used</param>
|
|
/// <returns>Squared distance to the line</returns>
|
|
public double safeDistanceToSq(object pos, bool bounded)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the safeDistanceToSq method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return linedef.SafeDistanceToSq(v, bounded);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the shortest "safe" distance from `pos` to the line. If `bounded` is `true` that means that the not the whole line's length will be used, but `lengthInv` less at the start and end.
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <param name="bounded">`true` if only the finite length of the line should be used, `false` if the infinite length of the line should be used</param>
|
|
/// <returns>Distance to the line</returns>
|
|
public double safeDistanceTo(object pos, bool bounded)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the safeDistanceTo method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return linedef.SafeDistanceTo(v, bounded);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the shortest squared distance from `pos` to the line.
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <param name="bounded">`true` if only the finite length of the line should be used, `false` if the infinite length of the line should be used</param>
|
|
/// <returns>Squared distance to the line</returns>
|
|
public double distanceToSq(object pos, bool bounded)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the distanceToSq method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return linedef.DistanceToSq(v, bounded);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the shortest distance from `pos` to the line.
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <param name="bounded">`true` if only the finite length of the line should be used, `false` if the infinite length of the line should be used</param>
|
|
/// <returns>Distance to the line</returns>
|
|
public double distanceTo(object pos, bool bounded)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the distanceTo method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return linedef.DistanceTo(v, bounded);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests which side of the `Linedef` `pos` is on. Returns < 0 for front (right) side, > for back (left) side, and 0 if `pos` is on the line.
|
|
/// </summary>
|
|
/// <param name="pos">Point to check against</param>
|
|
/// <returns>< 0 for front (right) side, > for back (left) side, and 0 if `pos` is on the line</returns>
|
|
public double sideOfLine(object pos)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the sideOfLine method can not be accessed.");
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
return linedef.SideOfLine(v);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Splits the `Linedef` at the given position. This can either be a `Vector2D`, an array of numbers, or an existing `Vertex`. The result will be two lines, from the start `Vertex` of the `Linedef` to `pos`, and from `pos` to the end `Vertex` of the `Linedef`.
|
|
/// </summary>
|
|
/// <param name="pos">`Vertex` to split by</param>
|
|
/// <returns>The newly created `Linedef`</returns>
|
|
public LinedefWrapper split(object pos)
|
|
{
|
|
if (linedef.IsDisposed)
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Linedef is disposed, the split method can not be accessed.");
|
|
|
|
if(pos is VertexWrapper)
|
|
return new LinedefWrapper(linedef.Split(((VertexWrapper)pos).Vertex));
|
|
|
|
try
|
|
{
|
|
Vector2D v = (Vector2D)BuilderPlug.Me.GetVectorFromObject(pos, false);
|
|
Vertex nv = General.Map.Map.CreateVertex(v);
|
|
nv.SnapToAccuracy();
|
|
Linedef nld = linedef.Split(nv);
|
|
linedef.UpdateCache();
|
|
nld.UpdateCache();
|
|
return new LinedefWrapper(nld);
|
|
}
|
|
catch (CantConvertToVectorException e)
|
|
{
|
|
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes the `Linedef`. Note that this will result in unclosed `Sector`s unless it has the same `Sector`s on both sides.
|
|
/// </summary>
|
|
public void delete()
|
|
{
|
|
if (linedef.IsDisposed)
|
|
return;
|
|
|
|
linedef.Dispose();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Interface implementations
|
|
|
|
/// <summary>
|
|
/// Returns an `Array` of the `Linedef`'s tags. UDMF only. Supported game configurations only.
|
|
/// </summary>
|
|
/// <returns>`Array` of tags</returns>
|
|
public int[] getTags()
|
|
{
|
|
return linedef.Tags.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a tag to the `Linedef`. UDMF only. Supported game configurations only.
|
|
/// </summary>
|
|
/// <param name="tag">Tag to add</param>
|
|
/// <returns>`true` when the tag was added, `false` when the tag already exists</returns>
|
|
public bool addTag(int tag)
|
|
{
|
|
if (linedef.Tags.Contains(tag))
|
|
return false;
|
|
|
|
// We have to take the detour by creating a new list and assigning that because otherwise the
|
|
// BeforePropsChange will not be triggered
|
|
List<int> tags = new List<int>(linedef.Tags);
|
|
tags.Add(tag);
|
|
tags.Remove(0);
|
|
|
|
linedef.Tags = tags;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a tag from the `Linedef`. UDMF only. Supported game configurations only.
|
|
/// </summary>
|
|
/// <param name="tag">Tag to remove</param>
|
|
/// <returns>`true` when the tag was removed successfully, `false` when the tag did not exist</returns>
|
|
public bool removeTag(int tag)
|
|
{
|
|
if (linedef.Tags.Contains(tag))
|
|
{
|
|
// If it's the only tag just set it to 0, otherwise remove the tag completely
|
|
if (linedef.Tags.Count == 1)
|
|
linedef.Tag = 0;
|
|
else
|
|
{
|
|
// We have to take the detour by creating a new list and assigning that because otherwise the
|
|
// BeforePropsChange will not be triggered
|
|
List<int> tags = new List<int>(linedef.Tags);
|
|
tags.Remove(tag);
|
|
linedef.Tags = tags;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|