pull/7/head
Nicolay Korslund 15 years ago
commit ff64c1fbf0

@ -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})
@ -87,9 +88,9 @@ set(GAMEWORLD_HEADER
source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER})
set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD} ${GAMEGUI})
set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD})
set(OPENMW_HEADER ${GAME_HEADER} ${GAMEREND_HEADER} ${GAMEINPUT_HEADER} ${GAMESCRIPT_HEADER}
${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMEGUI_HEADER})
${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER})
# Main executable
add_executable(openmw

@ -51,8 +51,10 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt)
// global scripts
mEnvironment.mGlobalScripts->run (mEnvironment);
// passing of time (30 times as fast as RL time)
mEnvironment.mWorld->advanceTime ((mEnvironment.mFrameDuration*30)/3600);
// passing of time
if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game)
mEnvironment.mWorld->advanceTime (
mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600);
return true;
}
@ -206,11 +208,12 @@ void OMW::Engine::go()
mOgre.getScene());
// Create window manager - this manages all the MW-specific GUI windows
mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui());
MWScript::registerExtensions (mExtensions);
mEnvironment.mSoundManager = new MWSound::SoundManager;
mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui(), mEnvironment,
mExtensions, mNewGame);
MWScript::registerExtensions (mExtensions);
mEnvironment.mSoundManager = new MWSound::SoundManager;
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
mEnvironment);

@ -0,0 +1,219 @@
#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
{
ErrorHandler::reset();
std::istringstream input (cmd + '\n');
Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions());
Compiler::LineParser parser (*this, mCompilerContext, output.getLocals(),
output.getLiterals(), output.getCode(), true);
scanner.scan (parser);
return isGood();
}
catch (const Compiler::SourceException& error)
{
// 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("");
}
}

@ -4,11 +4,35 @@
#include <openengine/gui/layout.hpp>
#include <list>
#include <string>
#include <vector>
#include <components/compiler/errorhandler.hpp>
#include <components/compiler/lineparser.hpp>
#include <components/compiler/scanner.hpp>
#include <components/compiler/locals.hpp>
#include <components/compiler/output.hpp>
#include <components/interpreter/interpreter.hpp>
#include "../mwscript/compilercontext.hpp"
#include "../mwscript/interpretercontext.hpp"
namespace MWGui
{
class Console : private OEngine::GUI::Layout
class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler
{
private:
MWScript::CompilerContext mCompilerContext;
MWWorld::Environment& mEnvironment;
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);
/// Report a file related error
virtual void report (const std::string& message, Type type);
public:
MyGUI::EditPtr command;
MyGUI::EditPtr history;
@ -20,127 +44,35 @@ namespace MWGui
StringList::iterator current;
std::string editString;
Console(int w, int h)
: Layout("openmw_console_layout.xml")
{
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);
}
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");
/* NOTE: This is where the console command should be
handled.
The console command is in the string 'cm'. Output from the
command should be put back into the console with the
printOK() or printError() functions.
*/
printOK("OK - echoing line " + cm);
command->setCaption("");
}
MyGUI::Char _char);
void acceptCommand(MyGUI::EditPtr _sender);
};
}
#endif

@ -7,8 +7,9 @@
using namespace MWGui;
WindowManager::WindowManager(MyGUI::Gui *_gui)
: gui(_gui), mode(GM_Game), shown(GW_ALL), allowed(GW_ALL)
WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment,
const Compiler::Extensions& extensions, bool newGame)
: gui(_gui), mode(GM_Game), shown(GW_ALL), allowed(newGame ? GW_None : GW_ALL)
{
// Get size info from the Gui object
assert(gui);
@ -19,7 +20,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui)
menu = new MainMenu(w,h);
map = new MapWindow();
stats = new StatsWindow();
console = new Console(w,h);
console = new Console(w,h, environment, extensions);
// The HUD is always on
hud->setVisible(true);

@ -15,6 +15,16 @@ namespace MyGUI
class Gui;
}
namespace Compiler
{
class Extensions;
}
namespace MWWorld
{
class Environment;
}
namespace MWGui
{
class HUD;
@ -91,11 +101,15 @@ namespace MWGui
public:
/// The constructor needs the main Gui object
WindowManager(MyGUI::Gui *_gui);
WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment,
const Compiler::Extensions& extensions, bool newGame);
virtual ~WindowManager();
void setMode(GuiMode newMode)
{
if (newMode==GM_Inventory && allowed==GW_None)
return;
mode = newMode;
updateVisible();
}

@ -17,19 +17,7 @@ namespace MWScript
char CompilerContext::getGlobalType (const std::string& name) const
{
if (const ESM::Global *global = mEnvironment.mWorld->getStore().globals.find (name))
{
switch (global->type)
{
case ESM::VT_Short: return 's';
case ESM::VT_Int: return 'l';
case ESM::VT_Float: return 'f';
default: return ' ';
}
}
return ' ';
return mEnvironment.mWorld->getGlobalVariableType (name);
}
bool CompilerContext::isId (const std::string& name) const

@ -40,7 +40,7 @@ namespace MWWorld
case ESM::VT_Short:
type = 's';
value.mShort = *reinterpret_cast<const Interpreter::Type_Integer *> (
value.mShort = *reinterpret_cast<const Interpreter::Type_Float *> (
&iter->second.value);
break;
@ -145,5 +145,15 @@ namespace MWWorld
default: throw std::runtime_error ("unsupported global variable type");
}
}
char Globals::getType (const std::string& name) const
{
Collection::const_iterator iter = mVariables.find (name);
if (iter==mVariables.end())
return ' ';
return iter->second.first;
}
}

@ -21,7 +21,7 @@ namespace MWWorld
{
Interpreter::Type_Float mFloat;
Interpreter::Type_Float mLong; // Why Morrowind, why? :(
Interpreter::Type_Integer mShort;
Interpreter::Type_Float mShort;
};
typedef std::map<std::string, std::pair<char, Data> > Collection;
@ -53,6 +53,9 @@ namespace MWWorld
float getFloat (const std::string& name) const;
///< Get value independently from real type.
char getType (const std::string& name) const;
///< If there is no global variable with this name, ' ' is returned.
};
}

@ -228,6 +228,11 @@ namespace MWWorld
return (*mGlobalVariables)[name];
}
char World::getGlobalVariableType (const std::string& name) const
{
return mGlobalVariables->getType (name);
}
Ptr World::getPtr (const std::string& name, bool activeOnly)
{
// the player is always in an active cell.
@ -358,4 +363,9 @@ namespace MWWorld
{
mSkyManager->setMoonColour (red);
}
float World::getTimeScaleFactor() const
{
return mGlobalVariables->getInt ("timescale");
}
}

@ -82,6 +82,9 @@ namespace MWWorld
Globals::Data& getGlobalVariable (const std::string& name);
char getGlobalVariableType (const std::string& name) const;
///< Return ' ', if there is no global variable with this name.
Ptr getPtr (const std::string& name, bool activeOnly);
///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells.
@ -103,6 +106,8 @@ namespace MWWorld
int getSecundaPhase() const;
void setMoonColour (bool red);
float getTimeScaleFactor() const;
};
}

@ -9,6 +9,8 @@ namespace Compiler
class SourceException : public std::exception
{
public:
virtual const char *what() const throw() { return "compile error";}
///< Return error message
};
@ -17,6 +19,8 @@ namespace Compiler
class FileException : public SourceException
{
public:
virtual const char *what() const throw() { return "can't read file"; }
///< Return error message
};
@ -24,7 +28,10 @@ namespace Compiler
/// \brief Exception: EOF condition encountered
class EOFException : public SourceException
{ virtual const char *what() const throw() { return "end of file"; }
{
public:
virtual const char *what() const throw() { return "end of file"; }
///< Return error message
};
}

@ -11,19 +11,67 @@
namespace Compiler
{
void LineParser::parseExpression (Scanner& scanner, const TokenLoc& loc)
{
mExprParser.reset();
if (!mExplicit.empty())
{
mExprParser.parseName (mExplicit, loc, scanner);
mExprParser.parseSpecial (Scanner::S_ref, loc, scanner);
}
scanner.scan (mExprParser);
char type = mExprParser.append (mCode);
mState = EndState;
switch (type)
{
case 'l':
Generator::message (mCode, mLiterals, "%g", 0);
break;
case 'f':
Generator::message (mCode, mLiterals, "%f", 0);
break;
default:
throw std::runtime_error ("unknown expression result type");
}
}
LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals, std::vector<Interpreter::Type_Code>& code)
Literals& literals, std::vector<Interpreter::Type_Code>& code, bool allowExpression)
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code),
mState (BeginState), mExprParser (errorHandler, context, locals, literals)
mState (BeginState), mExprParser (errorHandler, context, locals, literals),
mAllowExpression (allowExpression)
{}
bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
{
if (mAllowExpression && mState==BeginState)
{
scanner.putbackInt (value, loc);
parseExpression (scanner, loc);
return true;
}
return Parser::parseInt (value, loc, scanner);
}
bool LineParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
{
if (mAllowExpression && mState==BeginState)
{
scanner.putbackFloat (value, loc);
parseExpression (scanner, loc);
return true;
}
return Parser::parseFloat (value, loc, scanner);
}
@ -129,6 +177,29 @@ namespace Compiler
return false;
}
if (mState==BeginState && mAllowExpression)
{
std::string name2 = toLower (name);
char type = mLocals.getType (name2);
if (type!=' ')
{
scanner.putbackName (name, loc);
parseExpression (scanner, loc);
return true;
}
type = getContext().getGlobalType (name2);
if (type!=' ')
{
scanner.putbackName (name, loc);
parseExpression (scanner, loc);
return true;
}
}
if (mState==BeginState && getContext().isId (name))
{
mState = PotentialExplicitState;
@ -172,6 +243,30 @@ namespace Compiler
return true;
}
}
if (mAllowExpression)
{
if (keyword==Scanner::K_getdisabled || keyword==Scanner::K_getdistance)
{
scanner.putbackKeyword (keyword, loc);
parseExpression (scanner, loc);
return true;
}
if (const Extensions *extensions = getContext().getExtensions())
{
char returnType;
std::string argumentType;
if (extensions->isFunction (keyword, returnType, argumentType,
!mExplicit.empty()))
{
scanner.putbackKeyword (keyword, loc);
parseExpression (scanner, loc);
return true;
}
}
}
}
if (mState==BeginState)
@ -232,13 +327,25 @@ namespace Compiler
mState = EndState;
return true;
}
if (mAllowExpression)
{
if (keyword==Scanner::K_getsquareroot || keyword==Scanner::K_menumode ||
keyword==Scanner::K_random || keyword==Scanner::K_scriptrunning ||
keyword==Scanner::K_getsecondspassed)
{
scanner.putbackKeyword (keyword, loc);
parseExpression (scanner, loc);
return true;
}
}
return Parser::parseKeyword (keyword, loc, scanner);
}
bool LineParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
{
if (code==Scanner::S_newline && mState==EndState)
if (code==Scanner::S_newline && (mState==EndState || mState==BeginState))
return false;
if (code==Scanner::S_comma && mState==MessageState)
@ -252,6 +359,14 @@ namespace Compiler
mState = ExplicitState;
return true;
}
if (mAllowExpression && mState==BeginState &&
(code==Scanner::S_open || code==Scanner::S_minus))
{
scanner.putbackSpecial (code, loc);
parseExpression (scanner, loc);
return true;
}
return Parser::parseSpecial (code, loc, scanner);
}

@ -35,11 +35,17 @@ namespace Compiler
std::string mExplicit;
char mType;
ExprParser mExprParser;
bool mAllowExpression;
void parseExpression (Scanner& scanner, const TokenLoc& loc);
public:
LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals, std::vector<Interpreter::Type_Code>& code);
Literals& literals, std::vector<Interpreter::Type_Code>& code,
bool allowExpression = false);
///< \param allowExpression Allow lines consisting of a naked expression
/// (result is send to the messagebox interface)
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
///< Handle an int token.

@ -1 +1 @@
Subproject commit c04d72cbe380217c2d1d60f8a2c6e4810fe4c050
Subproject commit 82a3c071e56f2df451618e1371424c39aa299690
Loading…
Cancel
Save