Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In the code for the toolkit for my game, I have a concept I've been calling "contexts."

Each context refers to, essentially, different tools (SelectionContext, DrawTerrainContext, et cetera) and contains contain "actions" which are added/removed from the undo history.

Some pseudo-code:

public abstract class Context
{
    public abstract void Initialize();
    public abstract void Destroy();
    public virtual void Update();
}

public interface IAction
{
    void Execute();
    void Undo();
}

public class SelectionContext : Context
{
    public override void Initialiize() { ... }
    public override void Destroy() { /... }
    public override void Update() {
        if(mouseDown && noSelection)
            startSelection();
        else if(mouseDown && !noSelection)
            expandSelection();
        else if(!mouseDown && !noSelection)
            finishSelection();
    }

    private class SelectionAction : IAction
    {
        private List<object> _oldSelection;
        private List<object> _newSelection;

        public SelectionAction() { ... }
        public void Execute() { ... }
        public void Undo() { ... }
    }
}

The above context may define things like a RectangleSelectionAction, EllipticalSelectionAction, et cetera.

Stacking them like this allows me to do things like select a section of terrain then go to a different context to change textures (or what have you), then return to the selection.

While this is an improvement over putting almost everything in one file it still seems a little strange to me having to define small private classes in each context for each of their major actions.

Is there a standard (or better) way of abstracting out different tools from the main toolkit program to allow for easier development of future tools?

share|improve this question
1  
I like what you describe, but since you are asking for other ways to deal with your situation, I recommend taking a look at Plug-in (Computing). See also: Plug-in Architecture Framework for Beginners, Plugin Architecture, Plug-in Architectures –  Joshua Drake May 7 '12 at 12:32

1 Answer 1

up vote 2 down vote accepted

Yes, the standard approach is to have some kind of plugin API.

The details of this approach will vary based mainly on the implementation of your overall toolset and the needs of your game and its tools. What you've described here is a reasonable first start at a plugin system for your own tools.

It sounds like it works for you, so you should keep exploring it. Don't resist the design simply because it involves "small classes," because that's not always a bad thing (if a class encapsulates all the data and behavior it needs to perform its designated function, it's probably acceptable).

It also sounds like all your "context" plugins are still resident in the main assembly of your tools. That's fine, as it is straightforward and easy to work with.

In the long run, if you find yourself in a scenario where other developers or users would want to extend your tools with new contexts (but don't/shouldn't have access to the main toolchain code) you can take your plugin API to the next step, which is loading the code from external assemblies.

To do this, you'd extract the bits of your tools that define the context API (IAction, the Context base class, and whatever else you may have) into a class library that's compiled in a DLL that others can reference. They'd create a class library themselves, with a reference to your plugin API DLL, and implement their new contexts.

They would then place their compiled plug-in DLL in a location you specify, such as a Plugins directory next to your application.

Your application then loads, at startup or some other appropriate time, every DLL found in that directory, attempts to find any subclasses of Context, creates them (Activator.CreateInstance is a simple, though not entirely crazy-efficient, way to do so), and then uses them as normal.

You may find in this scenario that you need to provide addition extensibility hooks to the context API, such as an "initialize" and "shutdown" entry point you can all to allow the context to do some setup work.

But basically you've stumbled on the general principle, just chosen slightly non-standard names for some of your interfaces, but that's fine. It works for you and isn't a horrible broken mess, so you're on the right track.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.