diff --git a/Makefile b/Makefile index ff334be1e6..74a1297c44 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,11 @@ BGCC=$(CXX) $(CXXFLAGS) $(CF_BULLET) # Ogre C++ files, on the form ogre/cpp_X.cpp. Only the first file is # passed to the compiler, the rest are dependencies. -ogre_cpp=ogre framelistener interface bsaarchive mygui +ogre_cpp=ogre framelistener interface bsaarchive + +# MyGUI C++ files, gui/cpp_X.cpp. These are currently included into +# with cpp_ogre.cpp. +mygui_cpp=mygui console # FFmpeg files, in the form sound/cpp_X.cpp. avcodec_cpp=avcodec @@ -31,7 +35,7 @@ bullet_cpp=bullet player scale #### No modifications should be required below this line. #### -ogre_cpp_files=$(ogre_cpp:%=ogre/cpp_%.cpp) +ogre_cpp_files=$(ogre_cpp:%=ogre/cpp_%.cpp) $(mygui_cpp:%=gui/cpp_%.cpp) avcodec_cpp_files=$(avcodec_cpp:%=sound/cpp_%.cpp) bullet_cpp_files=$(bullet_cpp:%=bullet/cpp_%.cpp) diff --git a/core/config.d b/core/config.d index 7dd27b5fd4..458badf04a 100644 --- a/core/config.d +++ b/core/config.d @@ -56,14 +56,6 @@ struct ConfigManager IniWriter iniWriter; - // Sound setting - /* - float musicVolume; - float sfxVolume; - float mainVolume; - bool useMusic; - //*/ - // Mouse sensitivity float *mouseSensX; float *mouseSensY; @@ -157,11 +149,6 @@ struct ConfigManager */ readIni(reset); - - // I think DMD is on the brink of collapsing here. This has been - // moved elsewhere, because DMD couldn't handle one more import in - // this file. - //updateMouseSensitivity(); } // Read config from morro.ini, if it exists. The reset parameter is @@ -172,10 +159,6 @@ struct ConfigManager // Read configuration file, if it exists. IniReader ini; - // TODO: Right now we have to specify each option twice, once for - // reading and once for writing. Fix it? Nah. Don't do anything, - // this entire configuration scheme is likely to change anyway. - ini.readFile(confFile); screenShotNum = ini.getInt("General", "Screenshots", 0); @@ -209,13 +192,9 @@ struct ConfigManager finalOgreConfig = showOgreConfig || firstRun || !exists("ogre.cfg"); - // Set default key bindings if the user specified the -rk setting, - // or if no config file was found. - if(reset || !ini.wasRead) with(keyBindings) + // Set default key bindings first. + with(keyBindings) { - // Remove all existing key bindings - //clear(); - // Bind some default keys bind(Keys.MoveLeft, KC.A, KC.LEFT); bind(Keys.MoveRight, KC.D, KC.RIGHT); @@ -238,20 +217,32 @@ struct ConfigManager bind(Keys.PhysMode, KC.T); bind(Keys.Nighteye, KC.N); bind(Keys.ToggleGui, KC.Mouse1); + bind(Keys.Console, KC.F1); bind(Keys.Debug, KC.G); bind(Keys.Pause, KC.PAUSE, KC.P); bind(Keys.ScreenShot, KC.SYSRQ); bind(Keys.Exit, KC.Q, KC.ESCAPE); } - else + + // Unless the ini file was missing or we were asked to reset all + // keybindings to default, replace all present bindings with the + // values from the ini. + if(!reset && ini.wasRead) { // Read key bindings for(int i; i + WWW: http://openmw.snaptoad.com/ + + This file (cpp_console.cpp) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + +class Console : public Layout +{ + MyGUI::EditPtr command; + MyGUI::EditPtr history; + +public: + Console() + : Layout("openmw_console_layout.xml") + { + setCoord(0,0, + mWindow->getWidth()*2/3, mWindow->getHeight()/2); + + getWidget(command, "edit_Command"); + getWidget(history, "list_History"); + + // Set up the command line combobox + command->eventEditSelectAccept = + newDelegate(this, &Console::acceptCommand); + + // Set up the log window + history->setOverflowToTheLeft(true); + history->setEditStatic(true); + history->setVisibleVScroll(true); + } + + void takeFocus() + { + // Give keyboard focus to the combo box whenever the console is + // turned on + MyGUI::InputManager::getInstance().setKeyFocusWidget(command); + } + + void acceptCommand(MyGUI::EditPtr _sender) + { + const Ogre::UTFString &cm = command->getCaption(); + if(cm.empty()) return; + + if(cm == "big") + history->setFontName("youtube"); + + history->addText(cm + "\n"); + history->addText("this is a fake output result\n"); + command->setCaption(""); + } +}; + +Console *cons; + +extern "C" void gui_toggleConsole() +{ + if(consoleMode) + { + leaveGui(); + if(cons) + cons->setVisible(false); + } + else + { + enterGui(); + if(cons) + { + cons->setVisible(true); + cons->takeFocus(); + } + } + + consoleMode = !consoleMode; +} diff --git a/ogre/cpp_mygui.cpp b/gui/cpp_mygui.cpp similarity index 83% rename from ogre/cpp_mygui.cpp rename to gui/cpp_mygui.cpp index 7c7b72ae1d..5b54707d14 100644 --- a/ogre/cpp_mygui.cpp +++ b/gui/cpp_mygui.cpp @@ -1,3 +1,26 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.snaptoad.com/ + + This file (cpp_mygui.cpp) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + // TODO: KILLME std::string cellName; @@ -134,16 +157,17 @@ public: mPrefix = MyGUI::utility::toString(this, "_"); mListWindowRoot = MyGUI::LayoutManager::getInstance().loadLayout(mLayoutName, mPrefix, _parent); - const std::string main_name = mPrefix + MAIN_WINDOW; - for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); iter!=mListWindowRoot.end(); ++iter) { - if ((*iter)->getName() == main_name) + const std::string main_name = mPrefix + MAIN_WINDOW; + for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); iter!=mListWindowRoot.end(); ++iter) { - mMainWidget = (*iter); - break; + if ((*iter)->getName() == main_name) + { + mMainWidget = (*iter); + break; + } } + MYGUI_ASSERT(mMainWidget, "root widget name '" << MAIN_WINDOW << "' in layout '" << mLayoutName << "' not found."); } - MYGUI_ASSERT(mMainWidget, "root widget name '" << MAIN_WINDOW << "' in layout '" << mLayoutName << "' not found."); - } } void shutdown() @@ -361,48 +385,70 @@ HUD *hud; StatsWindow *stats; MapWindow *map; MyGUI::WidgetPtr FPSText; -MyGUI::WindowPtr mwindow; OIS::MouseState state; +bool consoleMode = false; +bool inventoryMode = false; -// KILLME -extern "C" void gui_toggleGui() +void enterGui() { + guiMode++; + if(guiMode == 1) { - guiMode = 0; - mGUI->hidePointer(); - if(mwindow) - mwindow->setVisible(false); - if(stats) - stats->setVisible(false); - if(map) - map->setVisible(false); - state = mMouse->getMouseState(); - } - else - { + // If we just entered GUI mode, enable the pointer + mGUI->showPointer(); + // Restore the GUI mouse position. This is a hack because silly // OIS doesn't allow us to set the mouse position ourselves. *((OIS::MouseState*)&(mMouse->getMouseState())) = state; mGUI->injectMouseMove(state.X.abs, state.Y.abs, 0); + } +} - guiMode = 1; - mGUI->showPointer(); - if(mwindow) - mwindow->setVisible(true); +void leaveGui() +{ + guiMode--; + + if(guiMode < 0) + { + std::cout << "WARNING: guiMode is " << guiMode << "\n"; + guiMode = 0; + } + + // Are we done with all GUI windows? + if(guiMode == 0) + { + // If so, hide the pointer and store the mouse state for later. + mGUI->hidePointer(); + state = mMouse->getMouseState(); + } +} + +#include "cpp_console.cpp" + +extern "C" void gui_toggleGui() +{ + if(inventoryMode) + { + leaveGui(); + if(stats) + stats->setVisible(false); + if(map) + map->setVisible(false); + } + else + { + enterGui(); if(stats) stats->setVisible(true); if(map) map->setVisible(true); } + + inventoryMode = !inventoryMode; } -// KILLME -void turnGuiOff(MyGUI::WidgetPtr sender) -{ - guiMode = 1; - gui_toggleGui(); -} +extern "C" int32_t* gui_getGuiModePtr() { return &guiMode; } extern "C" void gui_setupGUI(int32_t debugOut) { @@ -421,46 +467,15 @@ extern "C" void gui_setupGUI(int32_t debugOut) stats = new StatsWindow(); map = new MapWindow(); + cons = new Console(); - /* - // Window with Morrowind skin - mwindow = mGUI->createWidget - ("MW_Window", - (mWidth-width)/2, (mHeight-height)/2, // Position - 400, 190, // Size - MyGUI::ALIGN_DEFAULT, "Windows"); - mwindow->setCaption("Skin test"); - mwindow->setMinSize(120, 140); + // Hide all the windows at startup + stats->setVisible(false); + map->setVisible(false); + cons->setVisible(false); + guiMode = 1; + leaveGui(); - MyGUI::WidgetPtr tmp; - tmp = mwindow->createWidget - ("MW_Button", - 10, 32, // Position - 45, 24, // Size - MyGUI::ALIGN_LEFT | MyGUI::ALIGN_TOP, - "MWButton1"); - tmp->setCaption("Close"); - tmp->eventMouseButtonClick = MyGUI::newDelegate(&turnGuiOff); - - tmp = mwindow->createWidget - ("DaedricText_orig", - 20,80, - 500, 30, - MyGUI::ALIGN_LEFT | MyGUI::ALIGN_TOP, - "Daed1"); - tmp->setCaption("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - - tmp = mwindow->createWidget - ("DaedricText", - 20,130, - 500, 30, - MyGUI::ALIGN_LEFT | MyGUI::ALIGN_TOP, - "Daed2"); - tmp->setCaption("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - */ - - // Turn the GUI off at startup - turnGuiOff(NULL); // Start the mouse in the middle of the screen state.X.abs = mWidth / 2; state.Y.abs = mHeight / 2; diff --git a/input/events.d b/input/events.d index f1e234f22c..7b84950a91 100644 --- a/input/events.d +++ b/input/events.d @@ -39,6 +39,7 @@ import monster.monster; import monster.vm.dbg; import ogre.bindings; +import gui.bindings; import input.keys; import input.ois; @@ -53,6 +54,7 @@ import input.ois; // Pause? bool pause = false; +int *guiMode; void toggleFullscreen() { @@ -123,6 +125,8 @@ extern(C) void d_handleMouseMove(MouseState *state) state.X.abs, state.Y.abs, state.Z.abs, state.X.rel, state.Y.rel, state.Z.rel); + if(*guiMode) return; + ogre_rotateCamera( state.X.rel * effMX, state.Y.rel * effMY ); } @@ -169,35 +173,45 @@ extern(C) void d_handleKey(KC keycode, dchar text = 0) // text. Keys k = keyBindings.findMatch(keycode, text); + // These are handled even if we are in gui mode: + if(k) + switch(k) + { + case Keys.ToggleGui: gui_toggleGui(); return; + case Keys.Console: gui_toggleConsole(); return; + case Keys.ScreenShot: takeScreenShot(); return; + default: + } + + if(*guiMode) return; + if(k) switch(k) { case Keys.ToggleBattleMusic: Music.toggle(); - break; + return; - case Keys.MainVolUp: mainVolume(true); break; - case Keys.MainVolDown: mainVolume(false); break; - case Keys.MusVolUp: musVolume(true); break; - case Keys.MusVolDown: musVolume(false); break; - case Keys.SfxVolUp: sfxVolume(true); break; - case Keys.SfxVolDown: sfxVolume(false); break; - case Keys.Mute: Music.toggleMute(); break; - case Keys.Fullscreen: toggleFullscreen(); break; + case Keys.MainVolUp: mainVolume(true); return; + case Keys.MainVolDown: mainVolume(false); return; + case Keys.MusVolUp: musVolume(true); return; + case Keys.MusVolDown: musVolume(false); return; + case Keys.SfxVolUp: sfxVolume(true); return; + case Keys.SfxVolDown: sfxVolume(false); return; + case Keys.Mute: Music.toggleMute(); return; + case Keys.Fullscreen: toggleFullscreen(); return; - case Keys.PhysMode: bullet_nextMode(); break; - case Keys.Nighteye: ogre_toggleLight(); break; - case Keys.ToggleGui: gui_toggleGui(); break; + case Keys.PhysMode: bullet_nextMode(); return; + case Keys.Nighteye: ogre_toggleLight(); return; - case Keys.Debug: break; - case Keys.ScreenShot: takeScreenShot(); break; - case Keys.Pause: togglePause(); break; - case Keys.Exit: exitProgram(); break; + case Keys.Debug: return; + case Keys.Pause: togglePause(); return; + case Keys.Exit: exitProgram(); return; default: assert(k >= 0 && k < keyToString.length); writefln("WARNING: Event %s has no effect", keyToString[k]); } - return false; + return; } // Refresh rate for sfx placements, in seconds. @@ -226,6 +240,9 @@ void initializeInput() // put another import in core.config. I should probably check the // bug list and report it. updateMouseSensitivity(); + + // Get a pointer to the 'guiMode' flag in cpp_ogre.cpp + guiMode = gui_getGuiModePtr(); } extern(C) int ois_isPressed(int keysym); @@ -239,7 +256,7 @@ bool isPressed(Keys key) return false; } -extern(C) int d_frameStarted(float time, int guiMode) +extern(C) int d_frameStarted(float time) { if(doExit) return 0; @@ -257,7 +274,7 @@ extern(C) int d_frameStarted(float time, int guiMode) } // The rest is ignored in pause or GUI mode - if(pause || guiMode == 1) return 1; + if(pause || *guiMode > 0) return 1; // Walking / floating speed, in points per second. const float speed = 300; diff --git a/input/keys.d b/input/keys.d index deae120797..6799b668fc 100644 --- a/input/keys.d +++ b/input/keys.d @@ -67,7 +67,8 @@ enum Keys ToggleBattleMusic, PhysMode, // Toggle physics mode between walking, flying and ghost Nighteye, // Full ambient lighting - ToggleGui, // Turn the GUI on/off + ToggleGui,// Turn the GUI on/off + Console, // Turn console on/off Debug, // Misc @@ -254,6 +255,7 @@ struct KeyBindings keyToString[Keys.PhysMode] = "Toggle Physics Mode"; keyToString[Keys.Nighteye] = "Toggle Nighteye"; keyToString[Keys.ToggleGui] = "Toggle GUI"; + keyToString[Keys.Console] = "Console"; keyToString[Keys.Debug] = "OGRE Test Action"; keyToString[Keys.Pause] = "Pause"; diff --git a/media_mygui/VeraMono.ttf b/media_mygui/VeraMono.ttf new file mode 100644 index 0000000000..139f0b4311 Binary files /dev/null and b/media_mygui/VeraMono.ttf differ diff --git a/media_mygui/core.lang b/media_mygui/core.lang deleted file mode 100644 index 92fc931b2f..0000000000 --- a/media_mygui/core.lang +++ /dev/null @@ -1,14 +0,0 @@ - - - - - "unassigned, escape, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -, =, backspace, tab, q, w, e, r, t, y, u, i, o, p, [, ], enter, lcontrol, a, s, d, f, g, h, j, k, l, ;, ', `, lshift, \, z, x, c, v, b, n, m, comma, ., /, rshift, * on numeric keypad, leftalt, space, - unassigned, escape, !, @, #, $, %, ^, &, *, (, ), _, +, backspace, tab, Q, W, E, R, T, Y, U, I, O, P, {, }, enter, lcontrol, A, S, D, F, G, H, J, K, L, :, double quotes, ~, lshift, |, Z, X, C, V, B, N, M, <, >, ?, rshift, * on numeric keypad, leftalt, space" - - - - 0, 0, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 0, 0, 1081, 1094, 1091, 1082, 1077, 1085, 1075, 1096, 1097, 1079, 1093, 1098, 0, 0, 1092, 1099, 1074, 1072, 1087, 1088, 1086, 1083, 1076, 1078, 1101, 1105, 0, 92, 1103, 1095, 1089, 1084, 1080, 1090, 1100, 1073, 1102, 46, 0, 42, 0, 32, - 0, 0, 33, 34, 8470, 59, 37, 58, 63, 42, 40, 41, 95, 43, 0, 0, 1049, 1062, 1059, 1050, 1045, 1053, 1043, 1064, 1065, 1047, 1061, 1066, 0, 0, 1060, 1067, 1042, 1040, 1055, 1056, 1054, 1051, 1044, 1046, 1069, 1025, 0, 47, 1071, 1063, 1057, 1052, 1048, 1058, 1068, 1041, 1070, 44, 0, 42, 0, 32 - - - diff --git a/media_mygui/core.layer b/media_mygui/core.layer deleted file mode 100644 index 8312126b15..0000000000 --- a/media_mygui/core.layer +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/media_mygui/core.png b/media_mygui/core.png deleted file mode 100644 index d2ef69dcf7..0000000000 Binary files a/media_mygui/core.png and /dev/null differ diff --git a/media_mygui/core.pointer b/media_mygui/core.pointer deleted file mode 100644 index 8fd51d6a42..0000000000 --- a/media_mygui/core.pointer +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/media_mygui/core.skin b/media_mygui/core.skin index ce497b9b2e..94e98defdc 100644 --- a/media_mygui/core.skin +++ b/media_mygui/core.skin @@ -1,16 +1,11 @@ - - - - - - + @@ -18,4 +13,5 @@ + diff --git a/media_mygui/core.xml b/media_mygui/core.xml index 2e403161de..909d1bfb06 100644 --- a/media_mygui/core.xml +++ b/media_mygui/core.xml @@ -16,6 +16,7 @@ + diff --git a/media_mygui/openmw.font.xml b/media_mygui/openmw.font.xml index 858704361a..5a4f6b5805 100644 --- a/media_mygui/openmw.font.xml +++ b/media_mygui/openmw.font.xml @@ -10,6 +10,19 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media_mygui/openmw_console_layout.xml b/media_mygui/openmw_console_layout.xml new file mode 100644 index 0000000000..8c64a1da91 --- /dev/null +++ b/media_mygui/openmw_console_layout.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/media_mygui/openmw_layers.xml b/media_mygui/openmw_layers.xml index 7540cab75a..5f07600d61 100644 --- a/media_mygui/openmw_layers.xml +++ b/media_mygui/openmw_layers.xml @@ -4,9 +4,10 @@ - + - + + diff --git a/media_mygui/openmw_windows.skin.xml b/media_mygui/openmw_windows.skin.xml index 1be14690b1..41962cf856 100644 --- a/media_mygui/openmw_windows.skin.xml +++ b/media_mygui/openmw_windows.skin.xml @@ -174,7 +174,7 @@ - + @@ -240,14 +240,5 @@ - - - - - diff --git a/mscripts/console.mn b/mscripts/console.mn index 35e9888cbb..1d1cee93f1 100644 --- a/mscripts/console.mn +++ b/mscripts/console.mn @@ -27,5 +27,13 @@ class Console // This class contains all the functions available to the ingame // console. -import io; -import game; +import game + +native walk() +native fly() +native ghost() + +native wireframe() +tvf() { wireframe() } + +native fontsize(int size) diff --git a/ogre/cpp_framelistener.cpp b/ogre/cpp_framelistener.cpp index 3ba57ecc2d..ca37bd80c7 100644 --- a/ogre/cpp_framelistener.cpp +++ b/ogre/cpp_framelistener.cpp @@ -26,7 +26,7 @@ // Callbacks to D code. // Called once each frame -extern "C" int32_t d_frameStarted(float time, int guiMode); +extern "C" int32_t d_frameStarted(float time); // Handle events extern "C" void d_handleKey(int keycode, uint32_t text); @@ -54,7 +54,7 @@ public: mGUI->injectFrameEntered(evt.timeSinceLastFrame); // Turn over control to the D code - return d_frameStarted(evt.timeSinceLastFrame, guiMode); + return d_frameStarted(evt.timeSinceLastFrame); } }; @@ -69,6 +69,9 @@ public: << ", " << ((OIS::Keyboard*)(arg.device))->getAsString(arg.key) << "} || Character (" << (char)arg.text << ")\n"; //*/ + if(guiMode) + mGUI->injectKeyPress(arg); + d_handleKey(arg.key, arg.text); return true; } @@ -85,8 +88,8 @@ public: // Monster script. if(guiMode) mGUI->injectMouseMove(arg); - else - d_handleMouseMove(&arg.state); + + d_handleMouseMove(&arg.state); return true; } @@ -112,8 +115,12 @@ public: return true; } - // Unused - bool keyReleased( const OIS::KeyEvent &arg ) { return true; } + bool keyReleased( const OIS::KeyEvent &arg ) + { + if(guiMode) + mGUI->injectKeyRelease(arg); + return true; + } }; MorroFrameListener mFrameListener; diff --git a/ogre/cpp_ogre.cpp b/ogre/cpp_ogre.cpp index 54abe1942f..9b676b8658 100644 --- a/ogre/cpp_ogre.cpp +++ b/ogre/cpp_ogre.cpp @@ -59,7 +59,11 @@ OIS::Keyboard *mKeyboard; // The global GUI object MyGUI::Gui *mGUI; -int guiMode = 0; + +// This is used to determine if we are displaying any gui elements +// right now. If we are (and guiMode > 0), we redirect mouse/keyboard +// input into MyGUI. +int32_t guiMode = 0; // Root node for all objects added to the scene. This is rotated so // that the OGRE coordinate system matches that used internally in @@ -67,7 +71,7 @@ int guiMode = 0; SceneNode *root; // Include the other parts of the code, and make one big object file. -#include "cpp_mygui.cpp" +#include "../gui/cpp_mygui.cpp" #include "cpp_framelistener.cpp" #include "cpp_bsaarchive.cpp" #include "cpp_interface.cpp"