Loki Dev Log #2

Loki Dev Log #2

I’d say that this week was pretty productive. I finished two large tasks that needed to be done on Loki’s editor. The editor tools, entity brush, transform tool, and the entity inspector. Here are a couple of challenges I encountered and implementation notes.

Editor Tools

So, the editor tools include the following items. For the most part, they all do what you’d think they’d do.

Transform Tool - Translates an entity.

Brush Tool - spawns an entity.

Select Tool - selects an entity.

What made this sort of challenging is that I wanted to implement an undo and redo system and knowing some design patterns I knew that I would have to use some form of the Command Pattern. If you do not know what that is Robert Nystrom has an excellent write up on the topic. But the best way I can explain it without this post becoming too long is that the command pattern encapsulates an action. Honestly, its’ easier to just show it.

public class Command
{
    public virtual void Execute() { }
}
public class MoveCommand() : Command
{
    public override void Execute(Entity entity ,Point position)
    {
        entity.GetComponent<TransformComponent>().Position = position;
    }
}

Using this pattern, it allows us to have a common interface to execute interactions. With it, it becomes possible to create additional actions like an AttackCommand or a JumpCommand. The sample I gave was super basic but if we were to modify Command just a tad we can add an undo functionality.

public class Command
{
    public virtual void Execute() { }
    public virtual void Undo() { }
}
public class MoveCommand() : Command
{
    // moving some stuff around to make it more cleaner

    private TransformComponent _transformComponent;
    private Point _originalPosition; 

    public override void Execute(Entity entity, Point position)
    {
        _transformComponent = entity.GetComponent<TransformComponent>();
        
        // saving the original position for later 
        _originalPosition = _transformComponent.Position; 

        _transformComponent.Position = position;
    }

    public override void Undo()
    {
        _transformComponent.Position = _originalPosition
    }
}

As you can see, if we were to save the original Execute parameters then we could use it later. So now all we need to do is save these Command objects. This can be done by just storing them in a data structure like a list or stack. Anything that lets you traverse backwards. (note: with a stack you could only undo.)

Anyways back to the plot

Using the command pattern allows for me to have undo and redo functionality but, I need something a little bit more refined for my purposes. Basically, I want to give the commands more functionality. For example, when using the brush tool, I would usually want to transform the entity immediately after spawning it. The workflow for that looks a little like this.

Brush 
-> On Mouse Down 
    Spawn selected entity.

-> While Mouse Down 
    Transform selected entity.

-> On Mouse Up
    Exit. 

But what this describes is a FSM(finite state machine), something that I’ve never used in conjunction with the command pattern. So, what I ended up doing looked something like this.

public class Command
{
    public virtual void Enter() { }

    public virtual bool Update(){return false;}

    public virtual void Exit() { }
    
    public virtual void Undo() { }
}

Couple of notes here. Usually, an FSM returns the next state to be executed but this only returns a boolean to tell whether or not a command is finished executing. But I can’t do that because I can’t add something like an IdleCommand to the list of commands being stored for undo and redo, I would literally be “undoing” idle actions. Which is why this section of the project has been a little weird. But if it works, it works!

Loki

Inspector

In my ignorant opinion, an editor can’t be an editor if it doesn’t have a proper inspector. What the inspector does is show you the properties of an entity that are able to be edited. Here’s the end result.

Inspector_Image

This was actually a lot of fun to work on. I’m not going to get into the nitty gritty details but, what this does is when an entity is selected, it go through each of its accessible properties and components and adds a TextBlock and data bound TextBox for each one that it comes across to the InspectorControl. But, the fun part is how im determining whether or not a property is accessible. Given that there are circumstances where a property may be public but not needed to be exposed to the inspector, I created a custom attribute called EditorInspectable. This can take a parameter called DisplayName that overwrites the field name in the inspector to whatever that value is set to. Here’s what that looks like.

[AttributeUsage(AttributeTargets.All)]
public class EditorInspectable: Attribute
{
    public string DisplayName { get; set; }
    public EditorInspectable()
    {
    }
    public EditorInspectable(string displayName)
    {
        DisplayName = displayName;
    }
}

Here’s the attribute and all of its glory. Here is it in use.

[EditorInspectable("Transform Component")]
public class TransformComponent:Component
{
    [EditorInspectable]
    public Vector2 Position { get; set; }
    public TransformComponent()
    {
    }
    public TransformComponent(Entity entity, Vector2 position)
    {
        Position = position;
        Initialize();
    }
}

I’ve never had a reason to use attributes before so I just thought this was pretty cool.

Side note, in a previous post I said that I would have Lua scripting, which I still plan to have, and I think that inspector loading for fields in Lua scripts would just be any global variable. Not sure just yet if its possible to do something akin to attributes in Lua. We’ll see.

But anyway that’s it for this post.