Re-organize all projects (#4166)
This commit is contained in:
55
Content.Shared/Verbs/GlobalVerb.cs
Normal file
55
Content.Shared/Verbs/GlobalVerb.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// A verb is an action in the right click menu of an entity.
|
||||
/// Global verbs are visible on all entities, regardless of their components.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To add a global verb to all entities,
|
||||
/// define it and mark it with <see cref="GlobalVerbAttribute"/>
|
||||
/// </remarks>
|
||||
public abstract class GlobalVerb : VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations should write into <paramref name="data"/> to return their data.
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="target">The entity this verb is being evaluated for.</param>
|
||||
/// <param name="data">The data that must be filled in.</param>
|
||||
/// <returns>The text string that is shown in the right click menu for this verb.</returns>
|
||||
public abstract void GetData(IEntity user, IEntity target, VerbData data);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this verb is activated from the right click menu.
|
||||
/// </summary>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="target">The entity that is being acted upon.</param>
|
||||
public abstract void Activate(IEntity user, IEntity target);
|
||||
|
||||
public VerbData GetData(IEntity user, IEntity target)
|
||||
{
|
||||
var data = new VerbData();
|
||||
GetData(user, target, data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This attribute should be used on <see cref="GlobalVerb"/>. These are verbs which are on visible for all entities,
|
||||
/// regardless of the components they contain.
|
||||
/// </summary>
|
||||
[MeansImplicitUse]
|
||||
[BaseTypeRequired(typeof(GlobalVerb))]
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public sealed class GlobalVerbAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
16
Content.Shared/Verbs/HideContextMenuComponent.cs
Normal file
16
Content.Shared/Verbs/HideContextMenuComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class HideContextMenuComponent : Component, IShowContextMenu
|
||||
{
|
||||
public override string Name => "HideContextMenu";
|
||||
|
||||
public bool ShowContextMenu(IEntity examiner)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Content.Shared/Verbs/IShowContextMenu.cs
Normal file
10
Content.Shared/Verbs/IShowContextMenu.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
public interface IShowContextMenu : IComponent
|
||||
{
|
||||
bool ShowContextMenu(IEntity examiner);
|
||||
}
|
||||
}
|
||||
18
Content.Shared/Verbs/PlayerContainerVisibilityMessage.cs
Normal file
18
Content.Shared/Verbs/PlayerContainerVisibilityMessage.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public class PlayerContainerVisibilityMessage : EntityEventArgs
|
||||
{
|
||||
public readonly bool CanSeeThrough;
|
||||
|
||||
public PlayerContainerVisibilityMessage(bool canSeeThrough)
|
||||
{
|
||||
CanSeeThrough = canSeeThrough;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Content.Shared/Verbs/SharedVerbSystem.cs
Normal file
63
Content.Shared/Verbs/SharedVerbSystem.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Interaction.Helpers;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
public class SharedVerbSystem : EntitySystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all of the entities relevant for the contextmenu
|
||||
/// </summary>
|
||||
/// <param name="player"></param>
|
||||
/// <param name="targetPos"></param>
|
||||
/// <param name="contextEntities"></param>
|
||||
/// <param name="buffer">Whether we should slightly extend out the ignored range for the ray predicated</param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetContextEntities(IEntity player, MapCoordinates targetPos, [NotNullWhen(true)] out List<IEntity>? contextEntities, bool buffer = false)
|
||||
{
|
||||
contextEntities = null;
|
||||
var length = buffer ? 1.0f: 0.5f;
|
||||
|
||||
var entities = IoCManager.Resolve<IEntityLookup>().
|
||||
GetEntitiesIntersecting(targetPos.MapId, Box2.CenteredAround(targetPos.Position, (length, length))).ToList();
|
||||
|
||||
if (entities.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have LOS to the clicked-location, otherwise no popup.
|
||||
var vectorDiff = player.Transform.MapPosition.Position - targetPos.Position;
|
||||
var distance = vectorDiff.Length + 0.01f;
|
||||
bool Ignored(IEntity entity)
|
||||
{
|
||||
return entities.Contains(entity) ||
|
||||
entity == player ||
|
||||
!entity.TryGetComponent(out OccluderComponent? occluder) ||
|
||||
!occluder.Enabled;
|
||||
}
|
||||
|
||||
var mask = player.TryGetComponent(out SharedEyeComponent? eye) && eye.DrawFov
|
||||
? CollisionGroup.Opaque
|
||||
: CollisionGroup.None;
|
||||
|
||||
var result = player.InRangeUnobstructed(targetPos, distance, mask, Ignored);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
contextEntities = entities;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Content.Shared/Verbs/Verb.cs
Normal file
91
Content.Shared/Verbs/Verb.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// A verb is an action in the right click menu of an entity.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To add a verb to an entity, define it as a nested class inside the owning component,
|
||||
/// and mark it with <see cref="VerbAttribute"/>
|
||||
/// </remarks>
|
||||
[UsedImplicitly]
|
||||
public abstract class Verb : VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations should write into <paramref name="data"/> to return their data.
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
/// <param name="data">The data that must be filled into.</param>
|
||||
protected abstract void GetData(IEntity user, IComponent component, VerbData data);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this verb is activated from the right click menu.
|
||||
/// </summary>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
public abstract void Activate(IEntity user, IComponent component);
|
||||
|
||||
public VerbData GetData(IEntity user, IComponent component)
|
||||
{
|
||||
var data = new VerbData();
|
||||
GetData(user, component, data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Sub class of <see cref="T:Content.Shared.Verbs.Verb" /> that works on a specific type of component,
|
||||
/// to reduce casting boiler plate for implementations.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of component that this verb will run on.</typeparam>
|
||||
public abstract class Verb<T> : Verb where T : IComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations should write into <paramref name="data"/> to return their data.
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
/// <param name="data">The data that must be filled into.</param>
|
||||
protected abstract void GetData(IEntity user, T component, VerbData data);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this verb is activated from the right click menu.
|
||||
/// </summary>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
protected abstract void Activate(IEntity user, T component);
|
||||
|
||||
protected sealed override void GetData(IEntity user, IComponent component, VerbData data)
|
||||
{
|
||||
GetData(user, (T) component, data);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override void Activate(IEntity user, IComponent component)
|
||||
{
|
||||
Activate(user, (T) component);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This attribute should be used on <see cref="Verb"/> implementations nested inside component classes,
|
||||
/// so that they're automatically detected.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
[MeansImplicitUse]
|
||||
public sealed class VerbAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
20
Content.Shared/Verbs/VerbBase.cs
Normal file
20
Content.Shared/Verbs/VerbBase.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
public abstract class VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, this verb requires the user to be inside within
|
||||
/// <see cref="VerbUtility.InteractionRange"/> meters from the entity on which this verb resides.
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// OR the user can be the entity's container
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
}
|
||||
}
|
||||
16
Content.Shared/Verbs/VerbCategories.cs
Normal file
16
Content.Shared/Verbs/VerbCategories.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard verb categories.
|
||||
/// </summary>
|
||||
public static class VerbCategories
|
||||
{
|
||||
public static readonly VerbCategoryData Debug =
|
||||
("Debug", "/Textures/Interface/VerbIcons/debug.svg.192dpi.png");
|
||||
|
||||
public static readonly VerbCategoryData Rotate = ("Rotate", null);
|
||||
public static readonly VerbCategoryData Construction = ("Construction", null);
|
||||
}
|
||||
}
|
||||
32
Content.Shared/Verbs/VerbCategoryData.cs
Normal file
32
Content.Shared/Verbs/VerbCategoryData.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains combined name and icon information for a verb category.
|
||||
/// </summary>
|
||||
public readonly struct VerbCategoryData
|
||||
{
|
||||
public VerbCategoryData(string name, SpriteSpecifier? icon)
|
||||
{
|
||||
Name = name;
|
||||
Icon = icon;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public SpriteSpecifier? Icon { get; }
|
||||
|
||||
public static implicit operator VerbCategoryData((string name, string? icon) tuple)
|
||||
{
|
||||
var (name, icon) = tuple;
|
||||
|
||||
if (icon == null)
|
||||
{
|
||||
return new VerbCategoryData(name, null);
|
||||
}
|
||||
|
||||
return new VerbCategoryData(name, new SpriteSpecifier.Texture(new ResourcePath(icon)));
|
||||
}
|
||||
}
|
||||
}
|
||||
66
Content.Shared/Verbs/VerbData.cs
Normal file
66
Content.Shared/Verbs/VerbData.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
#nullable enable
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores visual data for a verb.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An instance of this class gets instantiated by the verb system and should be filled in by implementations of
|
||||
/// <see cref="Verb.GetData(IEntity, IComponent, VerbData)"/>.
|
||||
/// </remarks>
|
||||
public sealed class VerbData
|
||||
{
|
||||
/// <summary>
|
||||
/// The text that the user sees on the verb button.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Sprite of the icon that the user sees on the verb button.
|
||||
/// </summary>
|
||||
public SpriteSpecifier? Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the category this button is under.
|
||||
/// </summary>
|
||||
public string Category { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Sprite of the icon that the user sees on the verb button.
|
||||
/// </summary>
|
||||
public SpriteSpecifier? CategoryIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this verb is visible, disabled (greyed out) or hidden.
|
||||
/// </summary>
|
||||
public VerbVisibility Visibility { get; set; } = VerbVisibility.Visible;
|
||||
|
||||
public bool IsInvisible => Visibility == VerbVisibility.Invisible;
|
||||
public bool IsDisabled => Visibility == VerbVisibility.Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// Convenience property to set verb category and icon at once.
|
||||
/// </summary>
|
||||
[ValueProvider("Content.Shared.GameObjects.VerbCategories")]
|
||||
public VerbCategoryData CategoryData
|
||||
{
|
||||
set
|
||||
{
|
||||
Category = value.Name;
|
||||
CategoryIcon = value.Icon;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience property to set <see cref="Icon"/> to a raw texture path.
|
||||
/// </summary>
|
||||
public string IconTexture
|
||||
{
|
||||
set => Icon = new SpriteSpecifier.Texture(new ResourcePath(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Content.Shared/Verbs/VerbSystemMessages.cs
Normal file
70
Content.Shared/Verbs/VerbSystemMessages.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
public static class VerbSystemMessages
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public class RequestVerbsMessage : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid EntityUid;
|
||||
|
||||
public RequestVerbsMessage(EntityUid entityUid)
|
||||
{
|
||||
EntityUid = entityUid;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class VerbsResponseMessage : EntityEventArgs
|
||||
{
|
||||
public readonly NetVerbData[] Verbs;
|
||||
public readonly EntityUid Entity;
|
||||
|
||||
public VerbsResponseMessage(NetVerbData[] verbs, EntityUid entity)
|
||||
{
|
||||
Verbs = verbs;
|
||||
Entity = entity;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly struct NetVerbData
|
||||
{
|
||||
public readonly string Text;
|
||||
public readonly string Key;
|
||||
public readonly string Category;
|
||||
public readonly SpriteSpecifier? Icon;
|
||||
public readonly SpriteSpecifier? CategoryIcon;
|
||||
public readonly bool Available;
|
||||
|
||||
public NetVerbData(VerbData data, string key)
|
||||
{
|
||||
Text = data.Text;
|
||||
Key = key;
|
||||
Category = data.Category;
|
||||
CategoryIcon = data.CategoryIcon;
|
||||
Icon = data.Icon;
|
||||
Available = data.Visibility == VerbVisibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class UseVerbMessage : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid EntityUid;
|
||||
public readonly string VerbKey;
|
||||
|
||||
public UseVerbMessage(EntityUid entityUid, string verbKey)
|
||||
{
|
||||
EntityUid = entityUid;
|
||||
VerbKey = verbKey;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
100
Content.Shared/Verbs/VerbUtility.cs
Normal file
100
Content.Shared/Verbs/VerbUtility.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
public static class VerbUtility
|
||||
{
|
||||
public const float InteractionRange = 2;
|
||||
public const float InteractionRangeSquared = InteractionRange * InteractionRange;
|
||||
|
||||
// TODO: This is a quick hack. Verb objects should absolutely be cached properly.
|
||||
// This works for now though.
|
||||
public static IEnumerable<(IComponent, Verb)> GetVerbs(IEntity entity)
|
||||
{
|
||||
var typeFactory = IoCManager.Resolve<IDynamicTypeFactory>();
|
||||
|
||||
foreach (var component in entity.GetAllComponents())
|
||||
{
|
||||
var type = component.GetType();
|
||||
foreach (var nestedType in type.GetAllNestedTypes())
|
||||
{
|
||||
if (!typeof(Verb).IsAssignableFrom(nestedType) || nestedType.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var verb = typeFactory.CreateInstance<Verb>(nestedType);
|
||||
yield return (component, verb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an IEnumerable of all classes inheriting <see cref="GlobalVerb"/> with the <see cref="GlobalVerbAttribute"/> attribute.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The assembly to search for global verbs in.</param>
|
||||
public static IEnumerable<GlobalVerb> GetGlobalVerbs(Assembly assembly)
|
||||
{
|
||||
var typeFactory = IoCManager.Resolve<IDynamicTypeFactory>();
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
if (Attribute.IsDefined(type, typeof(GlobalVerbAttribute)))
|
||||
{
|
||||
if (!typeof(GlobalVerb).IsAssignableFrom(type) || type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
yield return typeFactory.CreateInstance<GlobalVerb>(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool VerbAccessChecks(IEntity user, IEntity target, VerbBase verb)
|
||||
{
|
||||
if (verb.RequireInteractionRange && !InVerbUseRange(user, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (verb.BlockedByContainers && !VerbContainerCheck(user, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool InVerbUseRange(IEntity user, IEntity target)
|
||||
{
|
||||
var distanceSquared = (user.Transform.WorldPosition - target.Transform.WorldPosition)
|
||||
.LengthSquared;
|
||||
if (distanceSquared > InteractionRangeSquared)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool VerbContainerCheck(IEntity user, IEntity target)
|
||||
{
|
||||
if (!user.IsInSameOrNoContainer(target))
|
||||
{
|
||||
if (!target.TryGetContainer(out var container) ||
|
||||
container.Owner != user)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Content.Shared/Verbs/VerbVisibility.cs
Normal file
25
Content.Shared/Verbs/VerbVisibility.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// Possible states of visibility for the verb in the right click menu.
|
||||
/// </summary>
|
||||
public enum VerbVisibility
|
||||
{
|
||||
/// <summary>
|
||||
/// The verb will be listed in the right click menu.
|
||||
/// </summary>
|
||||
Visible,
|
||||
|
||||
/// <summary>
|
||||
/// The verb will be listed, but it will be grayed out and unable to be clicked on.
|
||||
/// </summary>
|
||||
Disabled,
|
||||
|
||||
/// <summary>
|
||||
/// The verb will not be listed in the right click menu.
|
||||
/// </summary>
|
||||
Invisible
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user