Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Embedded Console  (Read 4707 times)

0 Members and 1 Guest are viewing this topic.

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Embedded Console
« on: March 30, 2014, 01:57:42 am »
https://github.com/dabbertorres/EmbeddedConsole

This is a relatively simple embedded console in a RenderWindow. It takes advantage of C++11, especially in the use of std::function.

Current Features:
  • Arguments
  • returns
  • If you can write a function to do it, it can run it

It only supports showing one prompt, input, and output right now, but plans are in place to remedy this limitation.
Here's a screenshot:


And an example of usage:
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include "Console.hpp"

int main(int argc, char **argv)
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Console");

    sf::Font font;
    if(!font.loadFromFile("./data/DejaVuSansMono.ttf"))
        return 1;

    swift::Console console(500, 200, font);

    console.addCommand("mouse", [&window](std::vector<std::string> args)
    {
        if(args.size() == 2)
        {
            if(args[1] == "x")
                return "x: " + std::to_string(sf::Mouse::getPosition(window).x) + '\n';
            else if(args[1] == "y")
                return "y: " + std::to_string(sf::Mouse::getPosition(window).y) + '\n';
        }
        return "x: " + std::to_string(sf::Mouse::getPosition(window).x) + '\n'
        + "y: " + std::to_string(sf::Mouse::getPosition(window).y) + '\n';
    });

    console.addCommand("hello", [](std::vector<std::string> args)
    {
        return "Hello to you too!";
    });

    console.addCommand("exit", [&console](std::vector<std::string> args)
    {
        console.activate(false);
        return "";
    });

    while(window.isOpen())
    {
        sf::Event event;

        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::TextEntered:
                    console.update(static_cast<char>(event.text.unicode));
                    break;
                case sf::Event::KeyPressed:
                    switch(event.key.code)
                    {
                        case sf::Keyboard::Up:
                            console.activate(false);
                            break;
                        case sf::Keyboard::Down:
                            console.activate(true);
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }
        }

        window.clear(sf::Color::White);

        window.draw(console);

        window.display();
    }

    return 0;
}
« Last Edit: March 30, 2014, 03:07:25 am by dabbertorres »

Kojay

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Re: Embedded Console
« Reply #1 on: March 30, 2014, 09:25:55 am »
Remarks and ideas:

  • No need to write Console's destructor.
  • It seems more natural to keep previous lines and pop as necessary (presumably your commented out deque was to that end?
  • line 65 of Console.cpp - instead of insert(make_pair()) can simply do commandList.emplace(c, f);
  • The states parameter isn't used in the draw function - either pass it to the draw calls or unname it.
  • line 41 of Console.cpp - gcc points out that t < 128 is always true
  • I would rather the commands the user registers return an ostream instead of a string - streaming makes for nicer syntax than string concatenation and you 're already using a stringstream in handleCommand.
  • Could Up and Down be used to cycle through command history instead?
  • (If you want to be really fancy) Provide autocomplete.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Embedded Console
« Reply #2 on: March 30, 2014, 11:08:35 am »
I like the fact that one can simply bind lambda expressions to a command :)

std::function<const std::string(std::vector<std::string> args)>
Omit the const (returning a const object is a bad idea). Pass by value is fine, as long as you use move semantics (call std::move() to pass the vector), otherwise you copy unnecessarily. And I would use a typedef for the vector of strings, and maybe also for the function.

One thing to add would be functionality that helps with parsing and interpreting the command arguments.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Embedded Console
« Reply #3 on: March 30, 2014, 06:18:28 pm »
Remarks and ideas:

  • No need to write Console's destructor.
  • It seems more natural to keep previous lines and pop as necessary (presumably your commented out deque was to that end?
  • line 65 of Console.cpp - instead of insert(make_pair()) can simply do commandList.emplace(c, f);
  • The states parameter isn't used in the draw function - either pass it to the draw calls or unname it.
  • line 41 of Console.cpp - gcc points out that t < 128 is always true
  • I would rather the commands the user registers return an ostream instead of a string - streaming makes for nicer syntax than string concatenation and you 're already using a stringstream in handleCommand.
  • Could Up and Down be used to cycle through command history instead?
  • (If you want to be really fancy) Provide autocomplete.
  • I know there isn't, but I tend to keep it just in case I ever want to use it.
  • Yes, that is correct. The deque is there for that purpose, I just wanted something working first. It's on the todo list!
  • Of course... Not sure how I missed that, thanks.
  • That's kind of in the same boat as the deque, should be used soon.
  • SFML's text tutorial has a check for that, so I was more following that. In any case, it was more of a sanity check. Thanks for the info.
  • That's a good idea... I agree, I'll look into doing that.
  • That's the plan for the future!
  • That is definitely a future addition!

I like the fact that one can simply bind lambda expressions to a command :)

std::function<const std::string(std::vector<std::string> args)>
Omit the const (returning a const object is a bad idea). Pass by value is fine, as long as you use move semantics (call std::move() to pass the vector), otherwise you copy unnecessarily. And I would use a typedef for the vector of strings, and maybe also for the function.

One thing to add would be functionality that helps with parsing and interpreting the command arguments.
Thanks! I love lambdas. They make things so much easier/add so much more functionality (captures are awesome).
Alright, I was trying to show that the string wasn't going to be changed, and for dealing with temporaries.
Same deal with passing the vector and strings by value, avoiding the temporaries issue. And I thought move semantics was the default in C++11 (or is it for C++14?)?
I played with a typedef previously, since you think it's a good idea, I'll go through with it!

You don't think a vector is enough for that? I was trying to C++icize the int argc, char** argv argument handling. With a vector, one can use:
for(auto &a : args) {}
 
syntax, which is nice and to the point. Or am I misunderstanding you?

In any case, thanks for the remarks!
« Last Edit: March 30, 2014, 06:38:14 pm by dabbertorres »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Embedded Console
« Reply #4 on: March 30, 2014, 07:14:30 pm »
std::vector is good, but you may copy unnecessarily. Move semantics are not "default", they are only applied automatically for return values and temporaries, but not when passing arguments (since the values might still be used afterwards). In other situations, you  have to use std::move().
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Embedded Console
« Reply #5 on: March 30, 2014, 10:12:27 pm »
Ah I see, thanks for info.

Dantez

  • Guest
Re: Embedded Console
« Reply #6 on: March 31, 2014, 01:21:47 am »
Function handleCommand doesn't handle blank command correctly (when just hitting enter).

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Embedded Console
« Reply #7 on: March 31, 2014, 04:10:18 am »
Oops, thanks for that, fixed and committed fix.
« Last Edit: March 31, 2014, 04:13:47 am by dabbertorres »

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Embedded Console
« Reply #8 on: April 01, 2014, 08:07:12 pm »
Multi-line support is now added (previous lines stay), horizontal wrap around is in place, and the text scrolls vertically as more commands and output happen.

The beginnings of using the Up and Down arrows for scrolling through history are in place as well.

Operator << has been added as well... Though it needs some refinement.

 

anything