Skip to content
This repository has been archived by the owner on Sep 16, 2019. It is now read-only.

Commands

Daniel Walder edited this page Aug 15, 2017 · 2 revisions

Commands are units of work triggered by a user. They are usually triggered in one of the following ways:

  • Button clicked
  • Menu item clicked
  • Hotkey pressed
  • Command selected from the command box

In the BSP editor, commands will quite often commit a change or display a dialog. Examples of commands include menu items such as "Tools > Carve", "File > Save", and "Help > Check for updates".

Adding commands

Required reading: Exporting and importing classes

If you want to add a new command that edits a map, inherit a class from Sledge.BspEditor.Commands.BaseCommand. The class has one abstract method Invoke(MapDocument, CommandParameters) that must be implemented, as well as Name and Details properties.

All commands should have a uniquely identifiable id, specified by using the CommandID attribute.

Here's a simple example of a command:

[Export(typeof(ICommand))]       // Export the command so it's available to use
[CommandID("Examples:Example1")] // Must be a unique string to identify this command
public class ExampleCommand : BaseCommand
{
    public override string Name { get; set; } = "Do the thing";    // The name of the command
    public override string Details { get; set; } = "Does a thing"; // A short description of the command

    protected override async Task Invoke(MapDocument document, CommandParameters parameters)
    {
        // Code that runs when the command is invoked
        System.Windows.Forms.MessageBox.Show("This is an example.");
    }
}

Command context

Required reading: Context and context changes

By default, the base command will be runnable if the active document is a MapDocument, but you can change this by overriding the IsInContext(IContext, MapDocument) method.

In this example, the command will only be allowed if the current selection is non-empty:

// ... 
public class ExampleCommand : BaseCommand
{
    protected override bool IsInContext(IContext context, MapDocument document)
    {
        return !document.Selection.IsEmpty;
    }

    // ...
}

Translating command names and details

Required reading: Supporting translations

Simply tag the class with [AutoTranslate] to automatically translate the Name and Details properties in your command. The properties must have a public setter. The translation text will be taken from the corresponding keys in your assembly's translations file(s).

[AutoTranslate]
// ... 
public class ExampleCommand : BaseCommand
{
    // The set methods must be public to use auto translations
    public override string Name { get; set; }
    public override string Details { get; set; }

    // ...
}

Adding commands to the menu

Required reading: Menu sections and groupsOrder hints

Adding commands to the menu is as simple as appending a MenuItem attribute to your class. You can specify a menu icon using the MenuImage attribute as well.

[MenuItem("Examples", "", "Test", "M")] // Command will appear in the "Examples" menu section, the "Test" menu group, using "M" as the ordering hint
[MenuImage(typeof(Resources), nameof(Resources.Menu_Example))] // (Optional) This should identify an image resource in your assembly
// ...
public class ExampleCommand : BaseCommand
{
    // ...
}

More advanced custom commands

For slightly more control over your command, or if you're using a custom document type, you will need to implement the ICommand interface directly. All the previous rules remain the same, but the methods change slightly. To extract useful parameters for your command you will need to use the context, be sure to read the context tutorials.

Here's a very basic example to demonstrate an ICommand implementation:

[Export(typeof(ICommand))]
[CommandID("Examples:Example2")]
public class ExampleCommand : ICommand
{
    public string Name { get; set; } = "Example";
    public string Details { get; set; } = "Example";

    public bool IsInContext(IContext context)
    {
        return true;
    }

    public async Task Invoke(IContext context, CommandParameters parameters)
    {
        MessageBox.Show("Hello.");
    }
}
Clone this wiki locally