In Game Console window using DirectX 11

Started by
20 comments, last by darcmagik 8 years ago

The map / callback is much more flexible / extendable than a switch. It also lets many different systems add new console commands while remaining independent from each other (decoupled). Instead of function pointers, std::function lets the 'users' of the system bind lambdas as well, which is nice :)

void SystemA::RegisterConsoleCommands( Console& c )
{
  c.Add( "Foo", [&]( const char* param ) { m_foo += atoi(param); }
}
Advertisement

The map / callback is much more flexible / extendable than a switch. It also lets many different systems add new console commands while remaining independent from each other (decoupled). Instead of function pointers, std::function lets the 'users' of the system bind lambdas as well, which is nice :)


void SystemA::RegisterConsoleCommands( Console& c )
{
  c.Add( "Foo", [&]( const char* param ) { m_foo += atoi(param); }
}

This is what I do, seconded.

Thank you everybody again for the advice, I am working diligently on this project and getting this console window to display on the screen correctly and then to get the text entry to work. Now the challenge I'm running into right now is that the game being in 2D is setup with a coordinate system where 0, 0 is the upper left corner and the lower corner is the window width, window height. But the system I'm using (DirectXTK) for drawing the quad on the screen draws the quad in a 3D coordinate space where 0,0 is the exact center of the screen. So I'm working on converting the points for the quad over from one coordinate space to the other.

Darcmagik

Of all the things I've lost I miss my mind the most.

You can use an orthographic projection matrix to map from a standard 2D coordinate system (where (0,0) is the top left, and (DisplayWidth, DisplayHeight) is the bottom right) to D3D normalized device coordinates (where (-1, -1) is the bottom left and (1, 1) is the top right). DirectXMath has the XMMatrixOrthographicOffCenterLH function which you can use to generate such a matrix. Just fill out the parameters such that Top = 0, Left = 0, Bottom = DisplayHeight, and Right = DisplayWidth. If you look at the documentation from the old D3DX function for doing the same thing, you can see how it generates a matrix such that it has an appropriate scale and translation.

Thank you for mentioning the ability to set the projection I had forgotten all about that. I had come up with a solution for converting the points over from the 2 systems and it worked quite nicely and honestly I gather that the way that the XMMatrixOrthographicOffCenterLH function converts things over is probably in a similar way but using the Orthographic projection is a much cleaner way so I will use this instead of my original answer.

Darcmagik

Of all the things I've lost I miss my mind the most.

Ok guys I have been working on this now for a few days and I'm now running into another road block and I thought I would come to you guys and see if I can find a solution. So the problem I am having is working with function pointers, and std::function's in my code. So right now I'm using a map in the console system:

This is how it is defined.


std::map<std::string, std::function<void()>> m_commandMap;

The problem I'm having is with adding the commands to the map, I currently am using a function called AddCommand:


void Console::AddCommand(std::string commandName, void* funcPoint)
{
	m_commandMap.insert(std::pair<std::string, std::function<void()>>(commandName, funcPoint));
}

I apologize if my syntax is incorrect but I'm not finding very much good information online about correct syntax of using std::function.

On top of this I have a function for processing the commands:


void Console::ProcessCommand(std::string commandName)
{
	if (!commandName.empty())
	{
		auto functionIndex = m_commandMap.find(commandName);
		if (functionIndex != m_commandMap.end())
		{
			functionIndex->second();
		}
	}
}

The part that I seem to be failing at is I can't figure out how to pass the function to the method AddCommand, what I have so far is:


editorConsole->AddCommand("FPS", TurnFPSOnOff);

But of course it doesn't like this line for how I'm passing the address of the function to Add Command It says the error is incompatible types of parameters. I am running out of ideas for how to handle it please help...

Darcmagik

Of all the things I've lost I miss my mind the most.

This is how I handle it in my script thingie:

Here's the struct I use to store function name and pointer:


struct Script_Function
{
	BOOL ProduceCode;
	CHAR Name[64];
	INT ParamsCount;
	SCR_PARAM Params[16];
	VOID(*Func_Ptr)(LPVOID, LPVOID, INT);
};

Here's how I set the struct:


Script_Function InternalFunctionList[SCR_INTERNALFUNCTIONSCOUNT] = {
	{ TRUE, "Declare", 2, { SCR_PARAM_NEWVAR, SCR_PARAM_INTFLOATSTRING }, Script_Internal_Declare },
// ...

And how I call it:


InternalFunctionList[index].Func_Ptr(this, bcparamlist, pcount);

Hope it helps, even though it doesn't use the std:: things!

.:vinterberg:.

Is TurnFPSOnOff a global function or member function of some class?

Member functions should be something like ClassType::TurnFPSOnOFF or &ClassType::TurnFPSOnOFF

while global functions would just be TurnFPSOnOff or &TurnFPSOnOff

That is for function pointers anyway. Of course if a member function, you would need a pointer to an object of the class in order to call it.

Is TurnFPSOnOff a global function or member function of some class?

It is a member function of the Class Game.

So I'm not set on using the std::function features somebody mentioned it before and I decided to do some research into it and thought I would attempt to see if I can make it work. However if I don't use the std::function then I have to still use function pointers and the challenge I have is trying to figure out using either function pointers or std::function inside of a map container. If I use function pointers I have tried using a void* pointer for the type in the map (I think that is how I would have to handle the situation.) that didn't work because it complains about trying to convert from Game* type to void*. If I use the std::function I get Visual Studio errors C2672: std::invoke: no matching overloaded function found, and error C2893: Failed to specialize function template'unknown-type std::invoke(...

So to recap I'm trying to figure out a way to handle this situation. I will do more research tomorrow after I get sleep because I am now seeing double on the screen. But if anybody reading this has any suggestions for how to handle this please speak up as I would appreciate the knowledge for how to handle this. Even if you don't want to give me the solution but have a really good resource related to this topic I would greatly appreciate even that.

Darcmagik

Of all the things I've lost I miss my mind the most.

to use std::function with member functions according to cplusplus.com goes something like this.


class Game
{
public:
Game() {}
void Go() { std::cout << "Game::Go called" << std::endl; }
};


// Creates a function from a member function pointer
std::function<void(Game&)> fn = &Game::Go;
Game game;


// you have to pass an object to the function to call
fn(game);

Or, you could use a lambda


Game game;
std::function<void()> fn(
[&]() 
{
     std::cout << "Lambda function called" << std::endl;
     game.Go();
});


fn();

This topic is closed to new replies.

Advertisement