added script interpreter for console

pull/7/head
Marc Zinnschlag 15 years ago
parent d72ed19460
commit 281f2d1136

@ -37,6 +37,7 @@ set(GAMEGUI_HEADER
)
set(GAMEGUI
mwgui/window_manager.cpp
mwgui/console.cpp
)
source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI})

@ -0,0 +1,217 @@
#include "console.hpp"
#include <components/compiler/exception.hpp>
#include "../mwscript/extensions.hpp"
namespace MWGui
{
class ConsoleInterpreterContext : public MWScript::InterpreterContext
{
Console& mConsole;
public:
ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment,
MWWorld::Ptr reference);
virtual void messageBox (const std::string& message,
const std::vector<std::string>& buttons);
};
ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console,
MWWorld::Environment& environment, MWWorld::Ptr reference)
: MWScript::InterpreterContext (environment,
reference.isEmpty() ? 0 : &reference.getRefData().getLocals(), reference),
mConsole (console)
{}
void ConsoleInterpreterContext::messageBox (const std::string& message,
const std::vector<std::string>& buttons)
{
if (!buttons.empty())
mConsole.printError ("MessageBox doesn't support buttons while in console mode");
else
mConsole.printOK (message);
}
bool Console::compile (const std::string& cmd, Compiler::Output& output)
{
try
{
std::istringstream input (cmd + '\n');
Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions());
Compiler::LineParser parser (*this, mCompilerContext, output.getLocals(),
output.getLiterals(), output.getCode());
scanner.scan (parser);
return isGood();
}
catch (const Compiler::SourceException&)
{
// error has already been reported via error handler
}
catch (const std::exception& error)
{
printError (std::string ("An exception has been thrown: ") + error.what());
}
return false;
}
void Console::report (const std::string& message, const Compiler::TokenLoc& loc, Type type)
{
std::ostringstream error;
error << "column " << loc.mColumn << " (" << loc.mLiteral << "):";
printError (error.str());
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
}
void Console::report (const std::string& message, Type type)
{
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
}
Console::Console(int w, int h, MWWorld::Environment& environment,
const Compiler::Extensions& extensions)
: Layout("openmw_console_layout.xml"),
mCompilerContext (MWScript::CompilerContext::Type_Console, environment),
mEnvironment (environment)
{
setCoord(10,10, w-10, h/2);
getWidget(command, "edit_Command");
getWidget(history, "list_History");
// Set up the command line box
command->eventEditSelectAccept =
newDelegate(this, &Console::acceptCommand);
command->eventKeyButtonPressed =
newDelegate(this, &Console::keyPress);
// Set up the log window
history->setOverflowToTheLeft(true);
history->setEditStatic(true);
history->setVisibleVScroll(true);
// compiler
mCompilerContext.setExtensions (&extensions);
}
void Console::enable()
{
setVisible(true);
// Give keyboard focus to the combo box whenever the console is
// turned on
MyGUI::InputManager::getInstance().setKeyFocusWidget(command);
}
void Console::disable()
{
setVisible(false);
}
void Console::setFont(const std::string &fntName)
{
history->setFontName(fntName);
command->setFontName(fntName);
}
void Console::clearHistory()
{
history->setCaption("");
}
void Console::print(const std::string &msg)
{
history->addText(msg);
}
void Console::printOK(const std::string &msg)
{
print("#FF00FF" + msg + "\n");
}
void Console::printError(const std::string &msg)
{
print("#FF2222" + msg + "\n");
}
void Console::keyPress(MyGUI::WidgetPtr _sender,
MyGUI::KeyCode key,
MyGUI::Char _char)
{
if(command_history.empty()) return;
// Traverse history with up and down arrows
if(key == MyGUI::KeyCode::ArrowUp)
{
// If the user was editing a string, store it for later
if(current == command_history.end())
editString = command->getCaption();
if(current != command_history.begin())
{
current--;
command->setCaption(*current);
}
}
else if(key == MyGUI::KeyCode::ArrowDown)
{
if(current != command_history.end())
{
current++;
if(current != command_history.end())
command->setCaption(*current);
else
// Restore the edit string
command->setCaption(editString);
}
}
}
void Console::acceptCommand(MyGUI::EditPtr _sender)
{
const std::string &cm = command->getCaption();
if(cm.empty()) return;
// Add the command to the history, and set the current pointer to
// the end of the list
command_history.push_back(cm);
current = command_history.end();
editString.clear();
// Log the command
print("#FFFFFF> " + cm + "\n");
Compiler::Locals locals;
Compiler::Output output (locals);
if (compile (cm, output))
{
try
{
ConsoleInterpreterContext interpreterContext (*this, mEnvironment, MWWorld::Ptr());
Interpreter::Interpreter interpreter (interpreterContext);
MWScript::installOpcodes (interpreter);
std::vector<Interpreter::Type_Code> code;
output.getCode (code);
interpreter.run (&code[0], code.size());
}
catch (const std::exception& error)
{
printError (std::string ("An exception has been thrown: ") + error.what());
}
}
command->setCaption("");
}
}

@ -10,10 +10,11 @@
#include <components/compiler/lineparser.hpp>
#include <components/compiler/scanner.hpp>
#include <components/compiler/locals.hpp>
#include <components/compiler/literals.hpp>
#include <components/compiler/exception.hpp>
#include <components/compiler/output.hpp>
#include <components/interpreter/interpreter.hpp>
#include "../mwscript/compilercontext.hpp"
#include "../mwscript/interpretercontext.hpp"
namespace MWGui
{
@ -22,51 +23,15 @@ namespace MWGui
private:
MWScript::CompilerContext mCompilerContext;
MWWorld::Environment& mEnvironment;
bool compile (const std::string& cmd)
{
try
{
std::istringstream input (cmd + '\n');
Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions());
Compiler::Locals locals;
Compiler::Literals literals;
std::vector<Interpreter::Type_Code> code;
Compiler::LineParser parser (*this, mCompilerContext, locals, literals, code);
scanner.scan (parser);
return isGood();
}
catch (const Compiler::SourceException&)
{
// error has already been reported via error handler
}
catch (const std::exception& error)
{
printError (std::string ("An exception has been thrown: ") + error.what());
}
return false;
}
bool compile (const std::string& cmd, Compiler::Output& output);
/// Report error to the user.
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type)
{
std::ostringstream error;
error << "column " << loc.mColumn << " (" << loc.mLiteral << "):";
printError (error.str());
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
}
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
/// Report a file related error
virtual void report (const std::string& message, Type type)
{
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
}
virtual void report (const std::string& message, Type type);
public:
MyGUI::EditPtr command;
@ -79,127 +44,35 @@ namespace MWGui
StringList::iterator current;
std::string editString;
Console(int w, int h, MWWorld::Environment& environment, const Compiler::Extensions& extensions)
: Layout("openmw_console_layout.xml"),
mCompilerContext (MWScript::CompilerContext::Type_Console, environment)
{
setCoord(10,10, w-10, h/2);
getWidget(command, "edit_Command");
getWidget(history, "list_History");
// Set up the command line box
command->eventEditSelectAccept =
newDelegate(this, &Console::acceptCommand);
command->eventKeyButtonPressed =
newDelegate(this, &Console::keyPress);
// Set up the log window
history->setOverflowToTheLeft(true);
history->setEditStatic(true);
history->setVisibleVScroll(true);
// compiler
mCompilerContext.setExtensions (&extensions);
}
void enable()
{
setVisible(true);
// Give keyboard focus to the combo box whenever the console is
// turned on
MyGUI::InputManager::getInstance().setKeyFocusWidget(command);
}
void disable()
{
setVisible(false);
}
void setFont(const std::string &fntName)
{
history->setFontName(fntName);
command->setFontName(fntName);
}
void clearHistory()
{
history->setCaption("");
}
Console(int w, int h, MWWorld::Environment& environment, const Compiler::Extensions& extensions);
void enable();
void disable();
void setFont(const std::string &fntName);
void clearHistory();
// Print a message to the console. Messages may contain color
// code, eg. "#FFFFFF this is white".
void print(const std::string &msg)
{ history->addText(msg); }
void print(const std::string &msg);
// These are pre-colored versions that you should use.
/// Output from successful console command
void printOK(const std::string &msg)
{ print("#FF00FF" + msg + "\n"); }
void printOK(const std::string &msg);
/// Error message
void printError(const std::string &msg)
{ print("#FF2222" + msg + "\n"); }
void printError(const std::string &msg);
private:
void keyPress(MyGUI::WidgetPtr _sender,
MyGUI::KeyCode key,
MyGUI::Char _char)
{
if(command_history.empty()) return;
// Traverse history with up and down arrows
if(key == MyGUI::KeyCode::ArrowUp)
{
// If the user was editing a string, store it for later
if(current == command_history.end())
editString = command->getCaption();
if(current != command_history.begin())
{
current--;
command->setCaption(*current);
}
}
else if(key == MyGUI::KeyCode::ArrowDown)
{
if(current != command_history.end())
{
current++;
if(current != command_history.end())
command->setCaption(*current);
else
// Restore the edit string
command->setCaption(editString);
}
}
}
void acceptCommand(MyGUI::EditPtr _sender)
{
const std::string &cm = command->getCaption();
if(cm.empty()) return;
// Add the command to the history, and set the current pointer to
// the end of the list
command_history.push_back(cm);
current = command_history.end();
editString.clear();
// Log the command
print("#FFFFFF> " + cm + "\n");
if (compile (cm))
{
// TODO execute command
}
command->setCaption("");
}
MyGUI::Char _char);
void acceptCommand(MyGUI::EditPtr _sender);
};
}
#endif

Loading…
Cancel
Save