UltimateZoneBuilder/Source/Plugins/UDBScript/API/SidedefWrapper.cs

530 lines
14 KiB
C#
Raw Normal View History

#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 CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.BuilderModes;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.VisualModes;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
class SidedefWrapper : MapElementWrapper, IEquatable<SidedefWrapper>
{
#region ================== Variables
private Sidedef sidedef;
#endregion
#region IEquatable<SidedefWrapper> members
public bool Equals(SidedefWrapper other)
{
return sidedef == other.sidedef;
}
public override bool Equals(object obj)
{
return Equals((SidedefWrapper)obj);
}
public override int GetHashCode()
{
return sidedef.GetHashCode();
}
#endregion
#region ================== Properties
/// <summary>
/// The `Sidedef`'s index. Read-only.
/// </summary>
public int index
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the isFront property can not be accessed.");
return sidedef.Index;
}
}
/// <summary>
/// `true` if this `Sidedef` is the front of its `Linedef`, otherwise `false`. Read-only.
/// </summary>
public bool isFront
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the isFront property can not be accessed.");
return sidedef.IsFront;
}
}
/// <summary>
/// The `Sector` the `Sidedef` belongs to. Read-only.
/// </summary>
public SectorWrapper sector
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the sector property can not be accessed.");
return new SectorWrapper(sidedef.Sector);
}
}
/// <summary>
/// The `Linedef` the `Sidedef` belongs to. Read-only.
/// </summary>
public LinedefWrapper line
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the line property can not be accessed.");
return new LinedefWrapper(sidedef.Line);
}
}
/// <summary>
/// The `Sidedef` on the other side of this `Sidedef`'s `Linedef`. Returns `null` if there is no other. Read-only.
/// </summary>
public SidedefWrapper other
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the other property can not be accessed.");
if (sidedef.Other == null)
return null;
return new SidedefWrapper(sidedef.Other);
}
}
/// <summary>
/// The `Sidedef`'s angle in degrees. Read-only.
/// </summary>
public double angle
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the angle property can not be accessed.");
return Angle2D.RadToDeg(sidedef.Angle);
}
}
/// <summary>
/// The `Sidedef`'s angle in radians. Read-only.
/// </summary>
public double angleRad
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the angleRad property can not be accessed.");
return sidedef.Angle;
}
}
/// <summary>
/// The x offset of the `Sidedef`'s textures.
/// </summary>
public int offsetX
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the offsetX property can not be accessed.");
return sidedef.OffsetX;
}
set
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the offsetX property can not be accessed.");
sidedef.OffsetX = value;
}
}
/// <summary>
/// The y offset of the `Sidedef`'s textures.
/// </summary>
public int offsetY
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the offsetY property can not be accessed.");
return sidedef.OffsetY;
}
set
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the offsetY property can not be accessed.");
sidedef.OffsetY = value;
}
}
/// <summary>
/// `Sidedef` flags. It's an object with the flags as properties. Only available in UDMF.
///
/// ```
/// s.flags['noattack'] = true; // Monsters in this sector don't attack
/// s.flags.noattack = true; // Also works
/// ```
/// </summary>
public ExpandoObject flags
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef 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 sidedef.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.SectorFlags.Keys.Contains(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.");
sidedef.SetFlag(pcea.PropertyName, (bool)so[pcea.PropertyName]);
});
return eo;
}
}
/// <summary>
/// The `Sidedef`'s upper texture.
/// </summary>
public string upperTexture
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the upperTexture property can not be accessed.");
return sidedef.HighTexture;
}
set
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the upperTexture property can not be accessed.");
sidedef.SetTextureHigh(value);
// Make sure to update the used textures, so that they are shown immediately
General.Map.Data.UpdateUsedTextures();
}
}
/// <summary>
/// The `Sidedef`'s middle texture.
/// </summary>
public string middleTexture
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the middleTexture property can not be accessed.");
return sidedef.MiddleTexture;
}
set
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the middleTexture property can not be accessed.");
sidedef.SetTextureMid(value);
// Make sure to update the used textures, so that they are shown immediately
General.Map.Data.UpdateUsedTextures();
}
}
/// <summary>
/// The `Sidedef`'s lower texture.
/// </summary>
public string lowerTexture
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the lowerTexture property can not be accessed.");
return sidedef.LowTexture;
}
set
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the lowerTexture property can not be accessed.");
sidedef.SetTextureLow(value);
// Make sure to update the used textures, so that they are shown immediately
General.Map.Data.UpdateUsedTextures();
}
}
/// <summary>
/// If the `Sidedef`'s upper part is selected or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool upperSelected
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the upperSelected property can not be accessed.");
if(General.Editing.Mode is BaseVisualMode)
{
bool u, m, l;
((BaseVisualMode)General.Editing.Mode).GetSelectedSurfaceTypesBySidedef(sidedef, out u, out m, out l);
return u;
}
else
{
return sidedef.Line.Selected;
}
}
}
/// <summary>
/// If the `Sidedef`'s upper part is highlighted or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool upperHighlighted
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the upperHighlighted property can not be accessed.");
if (General.Editing.Mode is BaseVisualMode)
{
VisualGeometry vs = (VisualGeometry)((BaseVisualMode)General.Editing.Mode).Highlighted;
if (vs == null)
return false;
return (vs.Sidedef == sidedef && vs.GeometryType == VisualGeometryType.WALL_UPPER);
}
else
{
Linedef ld = ((ClassicMode)General.Editing.Mode).HighlightedObject as Linedef;
if (ld == null)
return false;
return (ld.Front == sidedef || (ld.Back != null && ld.Back == sidedef));
}
}
}
/// <summary>
/// If the `Sidedef`'s middle part is selected or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool middleSelected
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the middleSelected property can not be accessed.");
if (General.Editing.Mode is BaseVisualMode)
{
bool u, m, l;
((BaseVisualMode)General.Editing.Mode).GetSelectedSurfaceTypesBySidedef(sidedef, out u, out m, out l);
return m;
}
else
{
return sidedef.Line.Selected;
}
}
}
/// <summary>
/// If the `Sidedef`'s middle part is highlighted or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool middleHighlighted
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the middleHighlighted property can not be accessed.");
if (General.Editing.Mode is BaseVisualMode)
{
VisualGeometry vs = (VisualGeometry)((BaseVisualMode)General.Editing.Mode).Highlighted;
if (vs == null)
return false;
return (vs.Sidedef == sidedef && (vs.GeometryType == VisualGeometryType.WALL_MIDDLE || vs.GeometryType == VisualGeometryType.WALL_MIDDLE_3D));
}
else
{
Linedef ld = ((ClassicMode)General.Editing.Mode).HighlightedObject as Linedef;
if (ld == null)
return false;
return (ld.Front == sidedef || (ld.Back != null && ld.Back == sidedef));
}
}
}
/// <summary>
/// If the `Sidedef`'s lower part is selected or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool lowerSelected
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the lowerSelected property can not be accessed.");
if (General.Editing.Mode is BaseVisualMode)
{
bool u, m, l;
((BaseVisualMode)General.Editing.Mode).GetSelectedSurfaceTypesBySidedef(sidedef, out u, out m, out l);
return l;
}
else
{
return sidedef.Line.Selected;
}
}
}
/// <summary>
/// If the `Sidedef`'s lower part is highlighted or not. Will always return `true` in classic modes if the parent `Linedef` is selected.
/// </summary>
/// <version>3</version>
public bool lowerHighlighted
{
get
{
if (sidedef.IsDisposed)
throw BuilderPlug.Me.ScriptRunner.CreateRuntimeException("Sidedef is disposed, the lowerHighlighted property can not be accessed.");
if (General.Editing.Mode is BaseVisualMode)
{
VisualGeometry vs = (VisualGeometry)((BaseVisualMode)General.Editing.Mode).Highlighted;
if (vs == null)
return false;
return (vs.Sidedef == sidedef && vs.GeometryType == VisualGeometryType.WALL_LOWER);
}
else
{
Linedef ld = ((ClassicMode)General.Editing.Mode).HighlightedObject as Linedef;
if (ld == null)
return false;
return (ld.Front == sidedef || (ld.Back != null && ld.Back == sidedef));
}
}
}
#endregion
#region ================== Constructors
internal SidedefWrapper(Sidedef sidedef) : base(sidedef)
{
this.sidedef = sidedef;
}
#endregion
#region ================== Update
internal override void AfterFieldsUpdate()
{
}
#endregion
#region ================== Methods
public override string ToString()
{
return sidedef.ToString();
}
#endregion
}
}