Ogre graphical console

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
User avatar
PixL
Halfling
Posts: 57
Joined: Mon Sep 26, 2005 9:33 am

Ogre graphical console

Post by PixL »

One thing that ogre lacks is a functioning console. A console should be one of the essentials of any game. So today I've desided to put together a simple console class that supports just the basics like scrolling, command prompt and command callbacks. It is allso animated like quake console ;) Here is a screenshot:

Image

Here is the code:

Console.h

Code: Select all

#pragma once

#include <OgreEventListeners.h>
#include <OgreKeyEvent.h>
#include <list>
#include <vector>

using namespace std;

class OgreConsole:public Singleton<OgreConsole>,FrameListener,LogListener,KeyListener{
public:
	OgreConsole();
	~OgreConsole();

	void	init(Ogre::Root *root);

	void	setVisible(bool visible);

	void	print(const String &text);

	virtual bool frameStarted(const Ogre::FrameEvent &evt);
	virtual bool frameEnded(const Ogre::FrameEvent &evt);

	void keyClicked(KeyEvent* e);
	void keyPressed(KeyEvent* e) {}
	void keyReleased(KeyEvent* e) {}

	void addCommand(const String &command, void (*)(vector<String>&));
	void removeCommand(const String &command);

	//log
	virtual void write( const String& name,
					const String& message, 
					LogMessageLevel lml = LML_NORMAL, 
					bool maskDebug = false ){print(name+": "+message);}
private:
	bool				visible;
	Ogre::EventProcessor *input;
	Ogre::Root			*root;
	Ogre::SceneManager	*scene;
	Ogre::Rectangle2D	*rect;
	Ogre::OverlayElement *textoverlay;
	float				height;
	int					scroll_lines;
	bool				update_overlay;
	int					start_line;
	list<String>		lines;
	String				prompt;
	map<String,void (*)(vector<String>&)>  commands;
};
Console.cpp

Code: Select all

#include "main.h"

OgreConsole *Singleton<OgreConsole>::ms_Singleton=0;

#define CONSOLE_LINE_LENGTH 85
#define CONSOLE_LINE_COUNT 16
OgreConsole::OgreConsole(){
	start_line=0;
}

OgreConsole::~OgreConsole(){
	if(input)
		delete input;
}

void OgreConsole::init(Ogre::Root *root){
	if(!root->getSceneManagerIterator().hasMoreElements())
		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "No scene manager found!", "init" );

	this->root=root;
	scene=root->getSceneManagerIterator().getNext();
	root->addFrameListener(this);

	input = new EventProcessor();
	input->initialise(root->getAutoCreatedWindow());
	input->startProcessingEvents();
	input->addKeyListener(this);

	height=1;

	// Create background rectangle covering the whole screen
	rect = new Rectangle2D(true);
	rect->setCorners(-1, 1, 1, 1-height);
	rect->setMaterial("console/background");
	rect->setRenderQueueGroup(RENDER_QUEUE_OVERLAY);
	rect->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));

	textoverlay=OverlayManager::getSingleton().createOverlayElement("TextArea","ConsoleText");
	textoverlay->setCaption("hello");
	textoverlay->setMetricsMode(GMM_RELATIVE);
	textoverlay->setPosition(0,0);
	textoverlay->setParameter("font_name","Console");
	textoverlay->setParameter("colour_top","1 1 1");
	textoverlay->setParameter("colour_bottom","1 1 1");
	textoverlay->setParameter("char_height","0.03");
	
	Overlay	*overlay=OverlayManager::getSingleton().create("Console");	
	overlay->add2D((OverlayContainer*)textoverlay);
	overlay->show();

	LogManager::getSingleton().addListener(this);

	// Attach background to the scene
	SceneNode* node = scene->getRootSceneNode()->createChildSceneNode("#Console");
	node->attachObject(rect);

	// Example of background scrolling
	//material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setScrollAnimation(-0.25, 0.0);
}

void OgreConsole::keyClicked(Ogre::KeyEvent *e){
	if(e->getKey()==KC_F1){
		setVisible(!visible);
		return;
	}
	if(!visible)
		return;
	if(e->getKey()==KC_RETURN&&prompt.length()){
		//split the parameter list
		const char *str=prompt.c_str();
		vector<String> params;
		String param="";
		for(int c=0;c<prompt.length();c++){
			if(str[c]==' '){
				if(param.length())
					params.push_back(param);
				param="";
			}
			else
				param+=str[c];
		}
		if(param.length())
			params.push_back(param);

		//try to execute the command
		map<String,void(*)(vector<String>&)>::iterator i;
		for(i=commands.begin();i!=commands.end();i++){
			if((*i).first==params[0]){
				if((*i).second)
					(*i).second(params);
				break;
			}
		}

		print(prompt);
		prompt="";
	}
	else if(e->getKey()==KC_BACK){
		prompt=prompt.substr(0,prompt.length()-1);
	}
	else if(e->getKey()==KC_UP){
		if(start_line>0)
			start_line--;
	}
	else if(e->getKey()==KC_DOWN){
		if(start_line<lines.size())
			start_line++;
	}
	else if(e->getKey()==KC_SYSRQ){
		static int count=0;
		char tmp[20];
		sprintf(tmp, "screenshot_%d.png", ++count);
		root->getAutoCreatedWindow()->writeContentsToFile(tmp);
		print(String("Wrote: ")+tmp);
	}
	else{
		char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXUZabcdefghijklmnopqrstuvwxyz1234567890+!\"#%&/()=?[]\\*-_.:,; ";
		for(int c=0;c<sizeof(legalchars);c++){
			if(legalchars[c]==e->getKeyChar()){
				prompt+=e->getKeyChar();
				break;
			}
		}
	}
	update_overlay=true;
}
bool OgreConsole::frameStarted(const Ogre::FrameEvent &evt){
	if(visible&&height<1){
		height+=evt.timeSinceLastFrame*2;
		textoverlay->show();
		if(height>=1){
			height=1;
		}
	}
	else if(!visible&&height>0){
		height-=evt.timeSinceLastFrame*2;
		if(height<=0){
			height=0;
			textoverlay->hide();
		}
	}

	textoverlay->setPosition(0,(height-1)*0.5);
	rect->setCorners(-1,1+height,1,1-height);

	if(update_overlay){
		String text;
		list<String>::iterator i,start,end;
		
		//make sure is in range
		if(start_line>lines.size())
			start_line=lines.size();

		int lcount=0;
		start=lines.begin();
		for(int c=0;c<start_line;c++)
			start++;
		end=start;
		for(int c=0;c<CONSOLE_LINE_COUNT;c++){
			if(end==lines.end())
				break;
			end++;
		}
		for(i=start;i!=end;i++)
			text+=(*i)+"\n";
		
		//add the prompt
		text+="] "+prompt;

		textoverlay->setCaption(text);
		update_overlay=false;
	}
	return true;
}

void OgreConsole::print(const String &text){
	//subdivide it into lines
	const char *str=text.c_str();
	int start=0,count=0;
	int len=text.length();
	String line;
	for(int c=0;c<len;c++){
		if(str[c]=='\n'||line.length()>=CONSOLE_LINE_LENGTH){
			lines.push_back(line);
			line="";
		}
		if(str[c]!='\n')
			line+=str[c];
	}
	if(line.length())
		lines.push_back(line);
	if(lines.size()>CONSOLE_LINE_COUNT)
		start_line=lines.size()-CONSOLE_LINE_COUNT;
	else
		start_line=0;
	update_overlay=true;
}

bool OgreConsole::frameEnded(const Ogre::FrameEvent &evt){

	return true;
}

void OgreConsole::setVisible(bool visible){
	this->visible=visible;
}

void OgreConsole::addCommand(const String &command, void (*func)(vector<String>&)){
	commands[command]=func;
}

void OgreConsole::removeCommand(const String &command){
	commands.erase(commands.find(command));
}
material:

Code: Select all

material console/background
{
	technique
	{
		pass
		{
			scene_blend alpha_blend
			diffuse 0 0 1 0.5
		}

	}

}
And finaly the font:

Code: Select all

Console
{
	type 		truetype
	source 		console.ttf
	size 		32
	resolution 	55
}
You can find the font file here: http://fixedsys.moviecorner.de/?p=download&l=1

Hope this was useful to someone :)

btw, how do I put it on wiki? I'm totaly clueless on how to use the wiki :oops: I can't find any link for uploading/creating a new page.
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Post by Praetor »

Cool. This is definitely useful. I suggest you run over to the wiki and create an article for this so it doesn't get lost in the forums.
User avatar
Wretched_Wyx
Orc
Posts: 498
Joined: Thu Mar 16, 2006 5:27 pm
Contact:

Post by Wretched_Wyx »

I agree with Praetor, get that on the Wiki! Very useful, and very cool.
PixL wrote:btw, how do I put it on wiki? I'm totally clueless on how to use the wiki. I can't find any link for uploading/creating a new page.
Help/FAQ Page

The way I always start a new page, is by searching for the title of the page. So long as that exact page doesn't exist, at the top of the search page you would see "No page with this exact title exists, trying full text search". The "exact title exists" would be a red link. If you click on this, it will create a page with the title you searched for.

Another method would be to edit an existing page, making a link to your yet-to-exist page. For example, this console code would fit nicely in the Code Snippets section, under System (?). So if you went to that page, and scrolled to system, there would be an [edit] link. Click that link to edit that particular section. Then you can simply copy an existing link, replacing the name "[[YourPageName|" and description "YourDescription]]". Save the edit, click on your newly added link, and edit your page!

I hope that helped, if not then let us know and we'll go from there.
Last edited by Wretched_Wyx on Sat Dec 02, 2006 1:28 am, edited 1 time in total.
User avatar
Frenetic
Bugbear
Posts: 806
Joined: Fri Feb 03, 2006 7:08 am

Re: Ogre graphical console

Post by Frenetic »

PixL wrote:btw, how do I put it on wiki? I'm totaly clueless on how to use the wiki :oops: I can't find any link for uploading/creating a new page.
Login to the wiki using your forum credentials, go to an unused page you want to fill out (eg. http://www.ogre3d.org/wiki/index.php/Console ) and it will say "There is currently no text in this page". So just hit the Edit tab and add some.

The wiki doesn't have an "add a page" link. You just go to where you want content, and add it.

[Edit] Wretched_Wyx beat me.
Last edited by Frenetic on Sat Dec 02, 2006 1:27 am, edited 1 time in total.
User avatar
haffax
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4823
Joined: Fri Jun 18, 2004 1:40 pm
Location: Berlin, Germany
x 6
Contact:

Post by haffax »

Definitly useful and definitly wiki-material.
But actually "Ogre isn't lacking" a console, Ogre just doesn't have one, because it is outside its scope. This is very application specific.

To create a new wiki-page, simply enter the page name in the search box. It will tell you that the search failed and give you a link("this exact title"), where you can create the page. Be sure to link your page somewhere, for instance in the code snippet section.
Also, you might want to add the page to the Code Snippet category.
To do this, add

Code: Select all

[[Category:Code Snippet]]
to the bottom of the page.
team-pantheon programmer
creators of Rastullahs Lockenpracht
User avatar
Wretched_Wyx
Orc
Posts: 498
Joined: Thu Mar 16, 2006 5:27 pm
Contact:

Post by Wretched_Wyx »

Frenetic wrote:Wretched_Wyx beat me...
Tehe... I thought for sure by the time I hit submit, somebody else would have beaten me to the punch. Off topic, but I miss Firefly...
User avatar
PixL
Halfling
Posts: 57
Joined: Mon Sep 26, 2005 9:33 am

Post by PixL »

OK thanks. Got it up on wiki now :)

http://www.ogre3d.org/wiki/index.php/OgreConsole
onny
Gnoblar
Posts: 5
Joined: Tue Nov 21, 2006 1:28 pm

Post by onny »

'This is a great snippet, thx.

But I got a problem with the LogManager:

LogManager::getSingleton().addListener(this);

gives this error:

console.cpp(50) : error C2039: 'addListener' : is not a member of 'Ogre::LogManager'

I know in 1.4 something has changed with the Log system, but I couldnt really figure out how to make this work in 1.4
(LogListener are no longer added to the LogManager. Instead, addListener and removeListener have been added to Ogre::Log. So, you will need to get the log you wish to add a listener to, messages will no longer be broadcast for all created logs to listeners. Also, the interface is slightly different then previously, please check Ogre::LogListener (in OgreLog.h) class for details - eh?)

Any ideas? Thx
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

This would be pretty useful!

Do you mind if I use your code as a reference to build a console widget for QuickGUI? :twisted:

KungFooMasta
User avatar
SpaceDude
Bronze Sponsor
Bronze Sponsor
Posts: 822
Joined: Thu Feb 02, 2006 1:49 pm
Location: Nottingham, UK
x 3
Contact:

Post by SpaceDude »

onny wrote:Any ideas? Thx
How bout something like this:

Code: Select all

Ogre::LogManager::getSingleton().getDefaultLog().addListener(this)
Or you could create your own log and listen to it like this:

Code: Select all

Ogre::LogManager::getSingleton().getLog("Console").addListener(this)
That's strange, LogManager seems to be missing a function to get a list of all the logs... But in theory you could loop through all the logs and add yourself as a listen to each of them. The list of logs is found here:

Ogre::LogManager::mLogs
tdo1
Gnoblar
Posts: 12
Joined: Thu Jun 14, 2007 4:18 pm

Post by tdo1 »

ogreconsole is not compatible with ogre 1.4 ?

when i compile it i have a error : 'OgreEventListeners.h' : No such file or directory
User avatar
neocryptek
Gnome
Posts: 335
Joined: Sat Mar 01, 2003 11:21 pm
Location: Idaho, USA
Contact:

Post by neocryptek »

tdo1 wrote:ogreconsole is not compatible with ogre 1.4 ?

when i compile it i have a error : 'OgreEventListeners.h' : No such file or directory
Eihort removed all intput/event related stuff. You will need to port those pieces to whatever input system you use; the demos use OIS.
User avatar
nickgravelyn
Halfling
Posts: 96
Joined: Sat Jan 28, 2006 7:41 pm
Location: Michigan

Post by nickgravelyn »

This is real cool. I have a couple bugs/suggestions:

The first bug I've found is that when I pump OIS events into the system, it writes blank space for shift, control, the arrows, etc.

The second is that occassionally the background disappears from the console.

As far as suggestions, I'd suggest remaking the files using OIS for ease of integration for people. I'd also suggest allowing native use of the up/down arrow keys to scroll through previous commands. That'd be real cool.

Good work.
Nick Gravelyn
rluck
Kobold
Posts: 29
Joined: Fri Jun 08, 2007 7:20 am
x 1

Post by rluck »

Any chance someone could post this w/ OIS? I'm having a hell of a time compiling it and getting all forms of errors with such a simple change.

edit: nvm, done. Heres the code for anyone that comes here looking for the same thing.

Header

Code: Select all

#include <OgreFrameListener.h>
#include <Ogre.h>
#include <OIS/OIS.h>
#include <list>
#include <vector>

using namespace Ogre;
using namespace std;

class OgreConsole: public Singleton<OgreConsole>, FrameListener, LogListener
{
public:
	OgreConsole();
	~OgreConsole();

	void	init(Ogre::Root *root);
	void	shutdown();

	void	setVisible(bool visible);
	bool	isVisible(){return visible;}

	void	print(const String &text);

	virtual bool frameStarted(const Ogre::FrameEvent &evt);
	virtual bool frameEnded(const Ogre::FrameEvent &evt);

	void onKeyPressed(const OIS::KeyEvent &arg);

	void addCommand(const String &command, void (*)(vector<String>&));
	void removeCommand(const String &command);

	//log
	void messageLogged( const String& message, LogMessageLevel lml, bool maskDebug, const String &logName ) {print(logName+": "+message);}
private:
	bool				visible;
	bool				initialized;
	Root			*root;
	SceneManager	*scene;
	Rectangle2D	*rect;
	SceneNode		*node;
	OverlayElement *textbox;
	Overlay		*overlay;

	float				height;
	bool				update_overlay;
	int					start_line;
	list<String>		lines;
	String				prompt;
	map<String,void (*)(vector<String>&)>  commands;
};
CPP

Code: Select all

#include "Console.h"

OgreConsole *Singleton<OgreConsole>::ms_Singleton=0;

#define CONSOLE_LINE_LENGTH 85
#define CONSOLE_LINE_COUNT 15
OgreConsole::OgreConsole(){
	start_line=0;
}

OgreConsole::~OgreConsole(){
	
}

void OgreConsole::init(Ogre::Root *root){
	if(!root->getSceneManagerIterator().hasMoreElements())
		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "No scene manager found!", "init" );

	this->root=root;
	scene=root->getSceneManagerIterator().getNext();
	root->addFrameListener(this);

	height=1;

	// Create background rectangle covering the whole screen
	rect = new Rectangle2D(true);
	rect->setCorners(-1, 1, 1, 1-height);
	rect->setMaterial("console/background");
	rect->setRenderQueueGroup(RENDER_QUEUE_OVERLAY);
	rect->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));
	node = scene->getRootSceneNode()->createChildSceneNode("#Console");
	node->attachObject(rect);

	textbox=OverlayManager::getSingleton().createOverlayElement("TextArea","ConsoleText");
	textbox->setCaption("hello");
	textbox->setMetricsMode(GMM_RELATIVE);
	textbox->setPosition(0,0);
	textbox->setParameter("font_name","Console");
	textbox->setParameter("colour_top","1 1 1");
	textbox->setParameter("colour_bottom","1 1 1");
	textbox->setParameter("char_height","0.03");
	
	overlay=OverlayManager::getSingleton().create("Console");	
	overlay->add2D((OverlayContainer*)textbox);
	overlay->show();
	LogManager::getSingleton().getDefaultLog()->addListener(this);
}

void OgreConsole::shutdown(){
	if(!initialized)
		return;
	delete rect;
	delete node;
	delete textbox;
	delete overlay;
}
void OgreConsole::onKeyPressed(const OIS::KeyEvent &arg){
	if(!visible)
		return;
	if (arg.key == OIS::KC_RETURN)
	{
		//split the parameter list
		const char *str=prompt.c_str();
		vector<String> params;
		String param="";
		for(int c=0;c<prompt.length();c++){
			if(str[c]==' '){
				if(param.length())
					params.push_back(param);
				param="";
			}
			else
				param+=str[c];
		}
		if(param.length())
			params.push_back(param);

		//try to execute the command
		map<String,void(*)(vector<String>&)>::iterator i;
		for(i=commands.begin();i!=commands.end();i++){
			if((*i).first==params[0]){
				if((*i).second)
					(*i).second(params);
				break;
			}
		}

		print(prompt);
		prompt="";
	}
	if (arg.key == OIS::KC_BACK)
		prompt=prompt.substr(0,prompt.length()-1);
	if (arg.key == OIS::KC_PGUP)
	{
		if(start_line>0)
			start_line--;
	}
	if (arg.key == OIS::KC_PGDOWN)
	{
		if(start_line<lines.size())
			start_line++;
	}
	else
	{
		char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+!\"#%&/()=?[]\\*-_.:,; ";
		for(int c=0;c<sizeof(legalchars);c++){
			if(legalchars[c]==arg.text){
				prompt+=arg.text;
				break;
			}
		}
	}
	update_overlay=true;
}
bool OgreConsole::frameStarted(const Ogre::FrameEvent &evt){
	if(visible&&height<1){
		height+=evt.timeSinceLastFrame*2;
		textbox->show();
		if(height>=1){
			height=1;
		}
	}
	else if(!visible&&height>0){
		height-=evt.timeSinceLastFrame*2;
		if(height<=0){
			height=0;
			textbox->hide();
		}
	}

	textbox->setPosition(0,(height-1)*0.5);
	rect->setCorners(-1,1+height,1,1-height);

	if(update_overlay){
		String text;
		list<String>::iterator i,start,end;
		
		//make sure is in range
		if(start_line>lines.size())
			start_line=lines.size();

		int lcount=0;
		start=lines.begin();
		for(int c=0;c<start_line;c++)
			start++;
		end=start;
		for(int c=0;c<CONSOLE_LINE_COUNT;c++){
			if(end==lines.end())
				break;
			end++;
		}
		for(i=start;i!=end;i++)
			text+=(*i)+"\n";
		
		//add the prompt
		text+="] "+prompt;

		textbox->setCaption(text);
		update_overlay=false;
	}
	return true;
}

void OgreConsole::print(const String &text){
	//subdivide it into lines
	const char *str=text.c_str();
	int start=0,count=0;
	int len=text.length();
	String line;
	for(int c=0;c<len;c++){
		if(str[c]=='\n'||line.length()>=CONSOLE_LINE_LENGTH){
			lines.push_back(line);
			line="";
		}
		if(str[c]!='\n')
			line+=str[c];
	}
	if(line.length())
		lines.push_back(line);
	if(lines.size()>CONSOLE_LINE_COUNT)
		start_line=lines.size()-CONSOLE_LINE_COUNT;
	else
		start_line=0;
	update_overlay=true;
}

bool OgreConsole::frameEnded(const Ogre::FrameEvent &evt){

	return true;
}

void OgreConsole::setVisible(bool visible){
	this->visible=visible;
}

void OgreConsole::addCommand(const String &command, void (*func)(vector<String>&)){
	commands[command]=func;
}

void OgreConsole::removeCommand(const String &command){
	commands.erase(commands.find(command));
}
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

****WIKIed**** :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
flonou
Gnoblar
Posts: 22
Joined: Sun Dec 09, 2007 12:06 am

Post by flonou »

Used this code and modified it to add buffered commands. Very usefull for a game (thanks to its author)

but I had some problems :
Shouldn't the lines

Code: Select all

else
   {
      char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+!\"#%&/()=?[]\\*-_.:,; ";
      for(int c=0;c<sizeof(legalchars);c++){
         if(legalchars[c]==arg.text){
            prompt+=arg.text;
            break;
         }
      }
   } 
be

Code: Select all

else
   {
      char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+!\"#%&/()=?[]\\*-_.:,; ";
      for(int c=0;c<sizeof(legalchars)-1;c++){
         if(legalchars[c]==arg.text){
            prompt+=arg.text;
            break;
         }
      }
   } 
to prevent '\0' to match with arg.text ???
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 3
Contact:

Post by _tommo_ »

Wow really useful... i was looking for a thing like this from much time :P

Straight inserted in our engine :D thanks so much!
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
birmacher
Gnoblar
Posts: 14
Joined: Tue Sep 25, 2007 9:06 pm

Post by birmacher »

Hy,

How would I able to build up the function I want to register to the console?
It's ok that I should use the addCommand func:), but how should the function look like.

I have this:

Code: Select all

namespace game {
class Class1 {
public:
(...)
void exit ( );
};
};
after that when I say that OgreConsole::getSingleton().addCommand("quit",&game::Class1::exit);
i get this error:
'engine::OgreConsole::addCommand' : cannot convert parameter 2 from 'void (__thiscall game::Class1::* )(void)' to 'void (__cdecl *)(std::vector<_Ty> &)'
User avatar
SpaceDude
Bronze Sponsor
Bronze Sponsor
Posts: 822
Joined: Thu Feb 02, 2006 1:49 pm
Location: Nottingham, UK
x 3
Contact:

Post by SpaceDude »

Try this:

Code: Select all

namespace game {
class Class1 {
public:
(...)
void exit (vector<String>& Params);
};
};
birmacher
Gnoblar
Posts: 14
Joined: Tue Sep 25, 2007 9:06 pm

Post by birmacher »

Thx, it works correctly if the function is not included in a class.
So addCommand ( "quit", &exit_cmd )

but inside a class it gave the next error after
So addCommand ( "quit", &game::Game::exit_cmd )
cannot convert parameter 2 from 'void (__thiscall game::Class1::* )(std::vector<_Ty> &)' to 'void (__cdecl *)(std::vector<_Ty> &)
User avatar
SpaceDude
Bronze Sponsor
Bronze Sponsor
Posts: 822
Joined: Thu Feb 02, 2006 1:49 pm
Location: Nottingham, UK
x 3
Contact:

Post by SpaceDude »

Function pointers is actually one of the most difficult concepts to grasp in C++ programming, they aren't used very frequently. But if you are interested you can read about them here:

http://www.newty.de/fpt/index.html

The problem with your code is that when you just specify "game::Class1::exit_cmd" as the function to call, it doesn't know which instance of the class "Class1" to use. In this case your "Class1" class is probably a singleton but the compiler doesn't know that. The easiest way to solve it is by making your function static like so:

Code: Select all

namespace game {
class Class1 {
public:
(...)
static void exit (vector<String>& Params);
};
};
But then you won't be able to access non-static variables and functions from within exit (essentially making it act as if it was a global function in the namespace game::Class1).
oeginc
Gnoblar
Posts: 2
Joined: Fri Feb 01, 2008 7:53 pm

Post by oeginc »

Surprisingly I was able to get this code into my project and get it somewhat working....

The problem I am having now is... How do I feed the input to the onKeyPressed method? :)

Right now I have in my FrameListener something like this...

Code: Select all

mKeyboard->capture();
// Exit if we press Esc
if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))
{
	return false;
}
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Post by Jabberwocky »

You'll want to implement an OIS::KeyListener class in your code, so you can catch the key events, then have some code like this:

Code: Select all

bool MyInputClass::keyPressed( const OIS::KeyEvent& i_event )
{
   OgreConsole::getSingleton().keyPressed( i_event );
}
(I'm just kinda winging that code, but it'll look something like that).

If you need help with the OIS specifics, you can post on the OIS forums
Image
DEvil HUnter
Halfling
Posts: 81
Joined: Fri Aug 25, 2006 10:54 am

Post by DEvil HUnter »

bug:
unhandeled exeption thrown if you press return and input string is empty or only spaces...

this solve it:
change this (in onKeyPress(...)):

Code: Select all

...
//try to execute the command
for(map<String,void(*)(vector<String>&)>::iterator i=commands.begin();i!=commands.end();i++){
...
to this:

Code: Select all

...
//try to execute the command
if(params.size())
   for(map<String,void(*)(vector<String>&)>::iterator i=commands.begin();i!=commands.end();i++){
...
things making the code better:
flonou wrote:Used this code and modified it to add buffered commands. Very usefull for a game (thanks to its author)

but I had some problems :
Shouldn't the lines

Code: Select all

else
   {
      char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+!"#%&/()=?[]\\*-_.:,; ";
      for(int c=0;c<sizeof(legalchars);c++){
         if(legalchars[c]==arg.text){
            prompt+=arg.text;
            break;
         }
      }
   } 
be

Code: Select all

else
   {
      char legalchars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890+!"#%&/()=?[]\\*-_.:,; ";
      for(int c=0;c<sizeof(legalchars)-1;c++){
         if(legalchars[c]==arg.text){
            prompt+=arg.text;
            break;
         }
      }
   } 
to prevent '\0' to match with arg.text ???
yes is better! '\0' should never be in the entered string...


this code change make the insert of blank lines possible (pressing return)
in print(...):

Code: Select all

...
if(line.length())
      lines.push_back(line);
...
changed to:

Code: Select all

...
lines.push_back(line);
...
falghar
Gnoblar
Posts: 5
Joined: Mon Mar 17, 2008 8:26 pm

sending keyboard input to the console

Post by falghar »

Hey i just hoped someone could tell me the correct code to pass input into the console and what function to put it in. I cant seem to find this anywhere i think this should be included in the wiki just as an example

i was trying something like this but i think this is passing in a blank key every time
OIS::KeyEvent e(mKeyboard, OIS::KC_UNASSIGNED,0);
OgreConsole::getSingleton().onKeyPressed(e);

i was calling the code in
virtual bool processUnbufferedKeyInput(const FrameEvent& evt)
in exampleframelistener.h

thankyou for any help
Post Reply