diff --git a/CMakeLists.txt b/CMakeLists.txt index 543d9cb983..6e0c32a22e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 16) +set (OPENMW_VERSION_MINOR 17) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") @@ -96,19 +96,13 @@ ENDIF() set(LIBDIR ${CMAKE_SOURCE_DIR}/libs) -set(MANGLE_INPUT ${LIBDIR}/mangle/input/servers/ois_driver.cpp) -set(MANGLE_ALL ${MANGLE_INPUT}) -source_group(libs\\mangle FILES ${MANGLE_ALL}) - set(OENGINE_OGRE ${LIBDIR}/openengine/ogre/renderer.cpp - ${LIBDIR}/openengine/ogre/mouselook.cpp ${LIBDIR}/openengine/ogre/fader.cpp ${LIBDIR}/openengine/ogre/imagerotate.cpp ${LIBDIR}/openengine/ogre/atlas.cpp ) set(OENGINE_GUI - ${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/manager.cpp ) @@ -135,7 +129,7 @@ set(OENGINE_BULLET set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET}) source_group(libs\\openengine FILES ${OENGINE_ALL}) -set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) +set(OPENMW_LIBS ${OENGINE_ALL}) set(OPENMW_LIBS_HEADER) # Sound setup @@ -257,13 +251,15 @@ if (APPLE) "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) endif (APPLE) +# Set up DEBUG define +set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1) # Set up Ogre plugin folder & debug suffix -# Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) -if (DEFINED CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT APPLE) - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") -else() +if (APPLE) + # Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") +else () + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") endif() add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}") @@ -443,6 +439,7 @@ endif(WIN32) # Extern add_subdirectory (extern/shiny) +add_subdirectory (extern/oics) # Components add_subdirectory (components) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 556b9a1ba2..66d9d50902 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -20,30 +20,31 @@ add_openmw_dir (mwrender ) add_openmw_dir (mwinput - inputmanager + inputmanagerimp ) add_openmw_dir (mwgui - text_input widgets race class birth review window_manager console dialogue + text_input widgets race class birth review windowmanagerimp console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow - confirmationdialog alchemywindow referenceinterface spellwindow + confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu + itemselection ) add_openmw_dir (mwdialogue - dialoguemanager journal journalentry quest topic + dialoguemanagerimp journalimp journalentry quest topic ) add_openmw_dir (mwscript - locals scriptmanager compilercontext interpretercontext cellextensions miscextensions + locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions animationextensions transformationextensions consoleextensions userextensions ) add_openmw_dir (mwsound - soundmanager openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder + soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder ) add_openmw_dir (mwworld @@ -59,12 +60,13 @@ add_openmw_dir (mwclass ) add_openmw_dir (mwmechanics - mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells + mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells activespells npcstats ) add_openmw_dir (mwbase - environment world + environment world scriptmanager dialoguemanager journal soundmanager mechanicsmanager + inputmanager windowmanager ) # Main executable @@ -102,6 +104,7 @@ target_link_libraries(openmw ${MYGUI_PLATFORM_LIBRARIES} "shiny" "shiny.OgrePlatform" + "oics" components ) @@ -112,7 +115,9 @@ endif() if(APPLE) find_library(CARBON_FRAMEWORK Carbon) - target_link_libraries(openmw ${CARBON_FRAMEWORK}) + find_library(COCOA_FRAMEWORK Cocoa) + find_library(IOKIT_FRAMEWORK IOKit) + target_link_libraries(openmw ${CARBON_FRAMEWORK} ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK}) endif(APPLE) if(DPKG_PROGRAM) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 5e9aedf66a..3de4ba8ac1 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -13,15 +13,15 @@ #include #include -#include "mwinput/inputmanager.hpp" +#include "mwinput/inputmanagerimp.hpp" -#include "mwgui/window_manager.hpp" +#include "mwgui/windowmanagerimp.hpp" #include "mwgui/cursorreplace.hpp" -#include "mwscript/scriptmanager.hpp" +#include "mwscript/scriptmanagerimp.hpp" #include "mwscript/extensions.hpp" -#include "mwsound/soundmanager.hpp" +#include "mwsound/soundmanagerimp.hpp" #include "mwworld/class.hpp" #include "mwworld/player.hpp" @@ -29,10 +29,10 @@ #include "mwclass/classes.hpp" -#include "mwdialogue/dialoguemanager.hpp" -#include "mwdialogue/journal.hpp" +#include "mwdialogue/dialoguemanagerimp.hpp" +#include "mwdialogue/journalimp.hpp" -#include "mwmechanics/mechanicsmanager.hpp" +#include "mwmechanics/mechanicsmanagerimp.hpp" void OMW::Engine::executeLocalScripts() @@ -67,7 +67,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) mEnvironment.setFrameDuration (evt.timeSinceLastFrame); // update input - MWBase::Environment::get().getInputManager()->update(); + MWBase::Environment::get().getInputManager()->update(evt.timeSinceLastFrame); // sound if (mUseSound) @@ -270,6 +270,10 @@ void OMW::Engine::go() else if (boost::filesystem::exists(globaldefault)) settings.loadUser(globaldefault); + // Get the path for the keybinder xml file + std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string(); + bool keybinderUserExists = boost::filesystem::exists(keybinderUser); + mFpsLevel = settings.getInt("fps", "HUD"); // load nif overrides @@ -352,6 +356,8 @@ void OMW::Engine::go() pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; pos.pos[2] = 0; + mEnvironment.getWorld()->renderPlayer(); + if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName)) { MWBase::Environment::get().getWorld()->indexToPosition (exterior->data.gridX, exterior->data.gridY, @@ -366,9 +372,9 @@ void OMW::Engine::go() // Sets up the input system - mEnvironment.setInputManager (new MWInput::MWInputManager (*mOgre, + mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, MWBase::Environment::get().getWorld()->getPlayer(), - *MWBase::Environment::get().getWindowManager(), mDebug, *this)); + *MWBase::Environment::get().getWindowManager(), mDebug, *this, keybinderUser, keybinderUserExists)); std::cout << "\nPress Q/ESC or close window to exit.\n"; diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp new file mode 100644 index 0000000000..ccffc6b214 --- /dev/null +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -0,0 +1,46 @@ +#ifndef GAME_MWBASE_DIALOGUEMANAGER_H +#define GAME_MWBASE_DIALOGUEMANAGER_H + +#include + +namespace MWWorld +{ + class Ptr; +} + +namespace MWBase +{ + /// \brief Interface for dialogue manager (implemented in MWDialogue) + class DialogueManager + { + DialogueManager (const DialogueManager&); + ///< not implemented + + DialogueManager& operator= (const DialogueManager&); + ///< not implemented + + public: + + DialogueManager() {} + + virtual ~DialogueManager() {} + + virtual void startDialogue (const MWWorld::Ptr& actor) = 0; + + virtual void addTopic (const std::string& topic) = 0; + + virtual void askQuestion (const std::string& question,int choice) = 0; + + virtual void goodbye() = 0; + + ///get the faction of the actor you are talking with + virtual std::string getFaction() const = 0; + + //calbacks for the GUI + virtual void keywordSelected (const std::string& keyword) = 0; + virtual void goodbyeSelected() = 0; + virtual void questionAnswered (const std::string& answer) = 0; + }; +} + +#endif diff --git a/apps/openmw/mwbase/environment.cpp b/apps/openmw/mwbase/environment.cpp index 7218f22ebd..9aaa5af85a 100644 --- a/apps/openmw/mwbase/environment.cpp +++ b/apps/openmw/mwbase/environment.cpp @@ -3,18 +3,14 @@ #include -#include "../mwinput/inputmanager.hpp" - -#include "../mwscript/scriptmanager.hpp" - -#include "../mwsound/soundmanager.hpp" - -#include "../mwdialogue/dialoguemanager.hpp" -#include "../mwdialogue/journal.hpp" - -#include "../mwmechanics/mechanicsmanager.hpp" - #include "world.hpp" +#include "scriptmanager.hpp" +#include "dialoguemanager.hpp" +#include "journal.hpp" +#include "soundmanager.hpp" +#include "mechanicsmanager.hpp" +#include "inputmanager.hpp" +#include "windowmanager.hpp" MWBase::Environment *MWBase::Environment::sThis = 0; @@ -37,37 +33,37 @@ void MWBase::Environment::setWorld (World *world) mWorld = world; } -void MWBase::Environment::setSoundManager (MWSound::SoundManager *soundManager) +void MWBase::Environment::setSoundManager (SoundManager *soundManager) { mSoundManager = soundManager; } -void MWBase::Environment::setScriptManager (MWScript::ScriptManager *scriptManager) +void MWBase::Environment::setScriptManager (ScriptManager *scriptManager) { mScriptManager = scriptManager; } -void MWBase::Environment::setWindowManager (MWGui::WindowManager *windowManager) +void MWBase::Environment::setWindowManager (WindowManager *windowManager) { mWindowManager = windowManager; } -void MWBase::Environment::setMechanicsManager (MWMechanics::MechanicsManager *mechanicsManager) +void MWBase::Environment::setMechanicsManager (MechanicsManager *mechanicsManager) { mMechanicsManager = mechanicsManager; } -void MWBase::Environment::setDialogueManager (MWDialogue::DialogueManager *dialogueManager) +void MWBase::Environment::setDialogueManager (DialogueManager *dialogueManager) { mDialogueManager = dialogueManager; } -void MWBase::Environment::setJournal (MWDialogue::Journal *journal) +void MWBase::Environment::setJournal (Journal *journal) { mJournal = journal; } -void MWBase::Environment::setInputManager (MWInput::MWInputManager *inputManager) +void MWBase::Environment::setInputManager (InputManager *inputManager) { mInputManager = inputManager; } @@ -83,43 +79,43 @@ MWBase::World *MWBase::Environment::getWorld() const return mWorld; } -MWSound::SoundManager *MWBase::Environment::getSoundManager() const +MWBase::SoundManager *MWBase::Environment::getSoundManager() const { assert (mSoundManager); return mSoundManager; } -MWScript::ScriptManager *MWBase::Environment::getScriptManager() const +MWBase::ScriptManager *MWBase::Environment::getScriptManager() const { assert (mScriptManager); return mScriptManager; } -MWGui::WindowManager *MWBase::Environment::getWindowManager() const +MWBase::WindowManager *MWBase::Environment::getWindowManager() const { assert (mWindowManager); return mWindowManager; } -MWMechanics::MechanicsManager *MWBase::Environment::getMechanicsManager() const +MWBase::MechanicsManager *MWBase::Environment::getMechanicsManager() const { assert (mMechanicsManager); return mMechanicsManager; } -MWDialogue::DialogueManager *MWBase::Environment::getDialogueManager() const +MWBase::DialogueManager *MWBase::Environment::getDialogueManager() const { assert (mDialogueManager); return mDialogueManager; } -MWDialogue::Journal *MWBase::Environment::getJournal() const +MWBase::Journal *MWBase::Environment::getJournal() const { assert (mJournal); return mJournal; } -MWInput::MWInputManager *MWBase::Environment::getInputManager() const +MWBase::InputManager *MWBase::Environment::getInputManager() const { assert (mInputManager); return mInputManager; @@ -150,6 +146,9 @@ void MWBase::Environment::cleanup() delete mScriptManager; mScriptManager = 0; + delete mWindowManager; + mWindowManager = 0; + delete mWorld; mWorld = 0; } diff --git a/apps/openmw/mwbase/environment.hpp b/apps/openmw/mwbase/environment.hpp index ad5a6f655e..a80e7ef870 100644 --- a/apps/openmw/mwbase/environment.hpp +++ b/apps/openmw/mwbase/environment.hpp @@ -1,40 +1,16 @@ #ifndef GAME_BASE_INVIRONMENT_H #define GAME_BASE_INVIRONMENT_H -namespace MWSound -{ - class SoundManager; -} - -namespace MWScript -{ - class ScriptManager; -} - -namespace MWGui -{ - class WindowManager; -} - -namespace MWMechanics -{ - class MechanicsManager; -} - -namespace MWDialogue -{ - class DialogueManager; - class Journal; -} - -namespace MWInput -{ - struct MWInputManager; -} - namespace MWBase { class World; + class ScriptManager; + class DialogueManager; + class Journal; + class SoundManager; + class MechanicsManager; + class InputManager; + class WindowManager; /// \brief Central hub for mw-subsystems /// @@ -47,13 +23,13 @@ namespace MWBase static Environment *sThis; World *mWorld; - MWSound::SoundManager *mSoundManager; - MWScript::ScriptManager *mScriptManager; - MWGui::WindowManager *mWindowManager; - MWMechanics::MechanicsManager *mMechanicsManager; - MWDialogue::DialogueManager *mDialogueManager; - MWDialogue::Journal *mJournal; - MWInput::MWInputManager *mInputManager; + SoundManager *mSoundManager; + ScriptManager *mScriptManager; + WindowManager *mWindowManager; + MechanicsManager *mMechanicsManager; + DialogueManager *mDialogueManager; + Journal *mJournal; + InputManager *mInputManager; float mFrameDuration; Environment (const Environment&); @@ -70,38 +46,38 @@ namespace MWBase void setWorld (World *world); - void setSoundManager (MWSound::SoundManager *soundManager); + void setSoundManager (SoundManager *soundManager); - void setScriptManager (MWScript::ScriptManager *scriptManager); + void setScriptManager (MWBase::ScriptManager *scriptManager); - void setWindowManager (MWGui::WindowManager *windowManager); + void setWindowManager (WindowManager *windowManager); - void setMechanicsManager (MWMechanics::MechanicsManager *mechanicsManager); + void setMechanicsManager (MechanicsManager *mechanicsManager); - void setDialogueManager (MWDialogue::DialogueManager *dialogueManager); + void setDialogueManager (DialogueManager *dialogueManager); - void setJournal (MWDialogue::Journal *journal); + void setJournal (Journal *journal); - void setInputManager (MWInput::MWInputManager *inputManager); + void setInputManager (InputManager *inputManager); void setFrameDuration (float duration); ///< Set length of current frame in seconds. World *getWorld() const; - MWSound::SoundManager *getSoundManager() const; + SoundManager *getSoundManager() const; - MWScript::ScriptManager *getScriptManager() const; + ScriptManager *getScriptManager() const; - MWGui::WindowManager *getWindowManager() const; + WindowManager *getWindowManager() const; - MWMechanics::MechanicsManager *getMechanicsManager() const; + MechanicsManager *getMechanicsManager() const; - MWDialogue::DialogueManager *getDialogueManager() const; + DialogueManager *getDialogueManager() const; - MWDialogue::Journal *getJournal() const; + Journal *getJournal() const; - MWInput::MWInputManager *getInputManager() const; + InputManager *getInputManager() const; float getFrameDuration() const; diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp new file mode 100644 index 0000000000..4c73c72b98 --- /dev/null +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -0,0 +1,44 @@ +#ifndef GAME_MWBASE_INPUTMANAGER_H +#define GAME_MWBASE_INPUTMANAGER_H + +#include + +#include + +namespace MWBase +{ + /// \brief Interface for input manager (implemented in MWInput) + class InputManager + { + InputManager (const InputManager&); + ///< not implemented + + InputManager& operator= (const InputManager&); + ///< not implemented + + public: + + InputManager() {} + + virtual ~InputManager() {} + + virtual void update(float dt) = 0; + + virtual void changeInputMode(bool guiMode) = 0; + + virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0; + + virtual void setDragDrop(bool dragDrop) = 0; + + virtual void toggleControlSwitch (const std::string& sw, bool value) = 0; + + virtual std::string getActionDescription (int action) = 0; + virtual std::string getActionBindingName (int action) = 0; + virtual std::vector getActionSorting () = 0; + virtual int getNumActions() = 0; + virtual void enableDetectingBindingMode (int action) = 0; + virtual void resetToDefaultBindings() = 0; + }; +} + +#endif diff --git a/apps/openmw/mwbase/journal.hpp b/apps/openmw/mwbase/journal.hpp new file mode 100644 index 0000000000..b3dfea45b7 --- /dev/null +++ b/apps/openmw/mwbase/journal.hpp @@ -0,0 +1,73 @@ +#ifndef GAME_MWBASE_JOURNAL_H +#define GAME_MWBASE_JOURNAL_H + +#include +#include +#include + +#include "../mwdialogue/journalentry.hpp" +#include "../mwdialogue/topic.hpp" +#include "../mwdialogue/quest.hpp" + +namespace MWBase +{ + /// \brief Interface for the player's journal (implemented in MWDialogue) + class Journal + { + Journal (const Journal&); + ///< not implemented + + Journal& operator= (const Journal&); + ///< not implemented + + public: + + typedef std::deque TEntryContainer; + typedef TEntryContainer::const_iterator TEntryIter; + typedef std::map TQuestContainer; // topc, quest + typedef TQuestContainer::const_iterator TQuestIter; + typedef std::map TTopicContainer; // topic-id, topic-content + typedef TTopicContainer::const_iterator TTopicIter; + + public: + + Journal() {} + + virtual ~Journal() {} + + virtual void addEntry (const std::string& id, int index) = 0; + ///< Add a journal entry. + + virtual void setJournalIndex (const std::string& id, int index) = 0; + ///< Set the journal index without adding an entry. + + virtual int getJournalIndex (const std::string& id) const = 0; + ///< Get the journal index. + + virtual void addTopic (const std::string& topicId, const std::string& infoId) = 0; + + virtual TEntryIter begin() const = 0; + ///< Iterator pointing to the begin of the main journal. + /// + /// \note Iterators to main journal entries will never become invalid. + + virtual TEntryIter end() const = 0; + ///< Iterator pointing past the end of the main journal. + + virtual TQuestIter questBegin() const = 0; + ///< Iterator pointing to the first quest (sorted by topic ID) + + virtual TQuestIter questEnd() const = 0; + ///< Iterator pointing past the last quest. + + virtual TTopicIter topicBegin() const = 0; + ///< Iterator pointing to the first topic (sorted by topic ID) + /// + /// \note The topic ID is identical with the user-visible topic string. + + virtual TTopicIter topicEnd() const = 0; + ///< Iterator pointing past the last topic. + }; +} + +#endif diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp new file mode 100644 index 0000000000..c5f1847af1 --- /dev/null +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -0,0 +1,77 @@ +#ifndef GAME_MWBASE_MECHANICSMANAGER_H +#define GAME_MWBASE_MECHANICSMANAGER_H + +#include +#include + +namespace Ogre +{ + class Vector3; +} + +namespace ESM +{ + struct Class; +} + +namespace MWWorld +{ + class Ptr; + class CellStore; +} + +namespace MWBase +{ + /// \brief Interface for game mechanics manager (implemented in MWMechanics) + class MechanicsManager + { + MechanicsManager (const MechanicsManager&); + ///< not implemented + + MechanicsManager& operator= (const MechanicsManager&); + ///< not implemented + + public: + + MechanicsManager() {} + + virtual ~MechanicsManager() {} + + virtual void addActor (const MWWorld::Ptr& ptr) = 0; + ///< Register an actor for stats management + + virtual void removeActor (const MWWorld::Ptr& ptr) = 0; + ///< Deregister an actor for stats management + + virtual void dropActors (const MWWorld::CellStore *cellStore) = 0; + ///< Deregister all actors in the given cell. + + virtual void watchActor (const MWWorld::Ptr& ptr) = 0; + ///< On each update look for changes in a previously registered actor and update the + /// GUI accordingly. + + virtual void update (std::vector >& movement, + float duration, bool paused) = 0; + ///< Update actor stats and store desired velocity vectors in \a movement + /// + /// \param paused In game type does not currently advance (this usually means some GUI + /// component is up). + + virtual void setPlayerName (const std::string& name) = 0; + ///< Set player name. + + virtual void setPlayerRace (const std::string& id, bool male) = 0; + ///< Set player race. + + virtual void setPlayerBirthsign (const std::string& id) = 0; + ///< Set player birthsign. + + virtual void setPlayerClass (const std::string& id) = 0; + ///< Set player class to stock class. + + virtual void setPlayerClass (const ESM::Class& class_) = 0; + ///< Set player class to custom class. + }; +} + +#endif diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp new file mode 100644 index 0000000000..ae146e0646 --- /dev/null +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -0,0 +1,62 @@ +#ifndef GAME_MWBASE_SCRIPTMANAGER_H +#define GAME_MWBASE_SCRIPTMANAGER_H + +#include + +namespace Interpreter +{ + class Context; +} + +namespace Compiler +{ + class Locals; +} + +namespace MWScript +{ + class GlobalScripts; +} + +namespace MWBase +{ + /// \brief Interface for script manager (implemented in MWScript) + class ScriptManager + { + ScriptManager (const ScriptManager&); + ///< not implemented + + ScriptManager& operator= (const ScriptManager&); + ///< not implemented + + public: + + ScriptManager() {} + + virtual ~ScriptManager() {} + + virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0; + ///< Run the script with the given name (compile first, if not compiled yet) + + virtual bool compile (const std::string& name) = 0; + ///< Compile script with the given namen + /// \return Success? + + virtual std::pair compileAll() = 0; + ///< Compile all scripts + /// \return count, success + + virtual Compiler::Locals& getLocals (const std::string& name) = 0; + ///< Return locals for script \a name. + + virtual MWScript::GlobalScripts& getGlobalScripts() = 0; + + virtual int getLocalIndex (const std::string& scriptId, const std::string& variable, + char type) = 0; + ///< Return index of the variable of the given name and type in the given script. Will + /// throw an exception, if there is no such script or variable or the type does not match. + + }; +} + +#endif diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp new file mode 100644 index 0000000000..dfc619bf98 --- /dev/null +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -0,0 +1,129 @@ +#ifndef GAME_MWBASE_SOUNDMANAGER_H +#define GAME_MWBASE_SOUNDMANAGER_H + +#include + +#include + +#include + +#include "../mwworld/ptr.hpp" + +namespace Ogre +{ + class Vector3; +} + +namespace MWWorld +{ + class CellStore; +} + +namespace MWSound +{ + class Sound; +} + +namespace MWBase +{ + typedef boost::shared_ptr SoundPtr; + + /// \brief Interface for sound manager (implemented in MWSound) + class SoundManager + { + public: + + enum PlayMode { + Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */ + Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */ + Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */ + Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position + * but do not keep it updated (the sound will not move with + * the object and will not stop when the object is deleted. */ + }; + + private: + + SoundManager (const SoundManager&); + ///< not implemented + + SoundManager& operator= (const SoundManager&); + ///< not implemented + + public: + + SoundManager() {} + + virtual ~SoundManager() {} + + virtual void processChangedSettings(const Settings::CategorySettingVector& settings) = 0; + + virtual void stopMusic() = 0; + ///< Stops music if it's playing + + virtual void streamMusic(const std::string& filename) = 0; + ///< Play a soundifle + /// \param filename name of a sound file in "Music/" in the data directory. + + virtual void startRandomTitle() = 0; + ///< Starts a random track from the current playlist + + virtual bool isMusicPlaying() = 0; + ///< Returns true if music is playing + + virtual void playPlaylist(const std::string &playlist) = 0; + ///< Start playing music from the selected folder + /// \param name of the folder that contains the playlist + + virtual void say(MWWorld::Ptr reference, const std::string& filename) = 0; + ///< Make an actor say some text. + /// \param filename name of a sound file in "Sound/" in the data directory. + + virtual void say(const std::string& filename) = 0; + ///< Say some text, without an actor ref + /// \param filename name of a sound file in "Sound/" in the data directory. + + virtual bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const = 0; + ///< Is actor not speaking? + + virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()) = 0; + ///< Stop an actor speaking + + virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch, + int mode=Play_Normal) = 0; + ///< Play a sound, independently of 3D-position + + virtual SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, + float volume, float pitch, int mode=Play_Normal) = 0; + ///< Play a sound from an object + + virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId) = 0; + ///< Stop the given object from playing the given sound, + + virtual void stopSound3D(MWWorld::Ptr reference) = 0; + ///< Stop the given object from playing all sounds. + + virtual void stopSound(const MWWorld::CellStore *cell) = 0; + ///< Stop all sounds for the given cell. + + virtual void stopSound(const std::string& soundId) = 0; + ///< Stop a non-3d looping sound + + virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0; + ///< Is the given sound currently playing on the given object? + + virtual void updateObject(MWWorld::Ptr reference) = 0; + ///< Update the position of all sounds connected to the given object. + + virtual void update(float duration) = 0; + + virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir) = 0; + }; + + inline int operator|(SoundManager::PlayMode a, SoundManager::PlayMode b) + { return static_cast (a) | static_cast (b); } + inline int operator&(SoundManager::PlayMode a, SoundManager::PlayMode b) + { return static_cast (a) & static_cast (b); } +} + +#endif diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp new file mode 100644 index 0000000000..389f816dcb --- /dev/null +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -0,0 +1,220 @@ +#ifndef GAME_MWBASE_WINDOWMANAGER_H +#define GAME_MWBASE_WINDOWMANAGER_H + +#include +#include +#include + +#include + +#include "../mwmechanics/stat.hpp" + +#include "../mwgui/mode.hpp" + +namespace MyGUI +{ + class Gui; + class Widget; + class UString; +} + +namespace OEngine +{ + namespace GUI + { + class Layout; + } +} + +namespace ESM +{ + struct Class; +} + +namespace MWWorld +{ + class CellStore; + class Ptr; +} + +namespace MWGui +{ + class Console; + class SpellWindow; + class TradeWindow; + class ConfirmationDialog; + class CountDialog; + class ScrollWindow; + class BookWindow; + class InventoryWindow; + class ContainerWindow; + class DialogueWindow; +} + +namespace MWBase +{ + /// \brief Interface for widnow manager (implemented in MWGui) + class WindowManager + { + WindowManager (const WindowManager&); + ///< not implemented + + WindowManager& operator= (const WindowManager&); + ///< not implemented + + public: + + typedef std::vector SkillList; + + WindowManager() {} + + virtual ~WindowManager() {} + + /** + * Should be called each frame to update windows/gui elements. + * This could mean updating sizes of gui elements or opening + * new dialogs. + */ + virtual void update() = 0; + + virtual void pushGuiMode (MWGui::GuiMode mode) = 0; + virtual void popGuiMode() = 0; + + virtual void removeGuiMode (MWGui::GuiMode mode) = 0; + ///< can be anywhere in the stack + + virtual MWGui::GuiMode getMode() const = 0; + + virtual bool isGuiMode() const = 0; + + virtual void toggleVisible (MWGui::GuiWindow wnd) = 0; + + /// Disallow all inventory mode windows + virtual void disallowAll() = 0; + + /// Allow one or more windows + virtual void allow (MWGui::GuiWindow wnd) = 0; + + virtual bool isAllowed (MWGui::GuiWindow wnd) const = 0; + + /// \todo investigate, if we really need to expose every single lousy UI element to the outside world + virtual MWGui::DialogueWindow* getDialogueWindow() = 0; + virtual MWGui::ContainerWindow* getContainerWindow() = 0; + virtual MWGui::InventoryWindow* getInventoryWindow() = 0; + virtual MWGui::BookWindow* getBookWindow() = 0; + virtual MWGui::ScrollWindow* getScrollWindow() = 0; + virtual MWGui::CountDialog* getCountDialog() = 0; + virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0; + virtual MWGui::TradeWindow* getTradeWindow() = 0; + virtual MWGui::SpellWindow* getSpellWindow() = 0; + virtual MWGui::Console* getConsole() = 0; + + virtual MyGUI::Gui* getGui() const = 0; + + virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0; + + /// Set value for the given ID. + virtual void setValue (const std::string& id, const MWMechanics::Stat& value) = 0; + virtual void setValue (int parSkill, const MWMechanics::Stat& value) = 0; + virtual void setValue (const std::string& id, const MWMechanics::DynamicStat& value) = 0; + virtual void setValue (const std::string& id, const std::string& value) = 0; + virtual void setValue (const std::string& id, int value) = 0; + + virtual void setPlayerClass (const ESM::Class &class_) = 0; + ///< set current class of player + + virtual void configureSkills (const SkillList& major, const SkillList& minor) = 0; + ///< configure skill groups, each set contains the skill ID for that group. + + virtual void setReputation (int reputation) = 0; + ///< set the current reputation value + + virtual void setBounty (int bounty) = 0; + ///< set the current bounty value + + virtual void updateSkillArea() = 0; + ///< update display of skills, factions, birth sign, reputation and bounty + + virtual void changeCell(MWWorld::CellStore* cell) = 0; + ///< change the active cell + + virtual void setPlayerPos(const float x, const float y) = 0; + ///< set player position in map space + + virtual void setPlayerDir(const float x, const float y) = 0; + ///< set player view direction in map space + + virtual void setFocusObject(const MWWorld::Ptr& focus) = 0; + virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0; + + virtual void setMouseVisible(bool visible) = 0; + virtual void getMousePosition(int &x, int &y) = 0; + virtual void getMousePosition(float &x, float &y) = 0; + virtual void setDragDrop(bool dragDrop) = 0; + virtual bool getWorldMouseOver() = 0; + + virtual void toggleFogOfWar() = 0; + + virtual void toggleFullHelp() = 0; + ///< show extra info in item tooltips (owner, script) + + virtual bool getFullHelp() const = 0; + + virtual void setInteriorMapTexture(const int x, const int y) = 0; + ///< set the index of the map texture that should be used (for interiors) + + /// sets the visibility of the hud health/magicka/stamina bars + virtual void setHMSVisibility(bool visible) = 0; + + /// sets the visibility of the hud minimap + virtual void setMinimapVisibility(bool visible) = 0; + virtual void setWeaponVisibility(bool visible) = 0; + virtual void setSpellVisibility(bool visible) = 0; + + virtual void activateQuickKey (int index) = 0; + + virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0; + virtual void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) = 0; + virtual void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) = 0; + virtual void unsetSelectedSpell() = 0; + virtual void unsetSelectedWeapon() = 0; + + virtual void showCrosshair(bool show) = 0; + virtual bool getSubtitlesEnabled() = 0; + virtual void toggleHud() = 0; + + virtual void disallowMouse() = 0; + virtual void allowMouse() = 0; + virtual void notifyInputActionBound() = 0; + + virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0; + ///< Hides dialog and schedules dialog to be deleted. + + virtual void messageBox (const std::string& message, const std::vector& buttons) = 0; + virtual int readPressedButton() = 0; + ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) + + virtual void onFrame (float frameDuration) = 0; + + /// \todo get rid of this stuff. Move it to the respective UI element classes, if needed. + virtual std::map > getPlayerSkillValues() = 0; + virtual std::map > getPlayerAttributeValues() = 0; + virtual SkillList getPlayerMinorSkills() = 0; + virtual SkillList getPlayerMajorSkills() = 0; + + /** + * Fetches a GMST string from the store, if there is no setting with the given + * ID or it is not a string the default string is returned. + * + * @param id Identifier for the GMST setting, e.g. "aName" + * @param default Default value if the GMST setting cannot be used. + */ + virtual const std::string &getGameSettingString(const std::string &id, const std::string &default_) = 0; + + virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0; + + virtual void executeInConsole (const std::string& path) = 0; + }; +} + +#endif diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index d9e19bead8..19405fb7a1 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -46,6 +46,7 @@ namespace MWWorld namespace MWBase { + /// \brief Interface for the World (implemented in MWWorld) class World { World (const World&); @@ -54,14 +55,6 @@ namespace MWBase World& operator= (const World&); ///< not implemented - protected: - - virtual void - placeObject( - const MWWorld::Ptr &ptr, - MWWorld::CellStore &cell, - const ESM::Position &pos) = 0; - public: enum RenderMode @@ -72,6 +65,12 @@ namespace MWBase Render_Compositors }; + struct DoorMarker + { + std::string name; + float x, y; // world position + }; + World() {} virtual ~World() {} @@ -115,6 +114,15 @@ namespace MWBase virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0; ///< get north vector (OGRE coordinates) for given interior cell + virtual std::vector getDoorMarkers (MWWorld::CellStore* cell) = 0; + ///< get a list of teleport door markers for a given cell, to be displayed on the local map + + virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0; + ///< see MWRender::LocalMap::getInteriorMapPosition + + virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0; + ///< see MWRender::LocalMap::isPositionExplored + virtual MWWorld::Globals::Data& getGlobalVariable (const std::string& name) = 0; virtual MWWorld::Globals::Data getGlobalVariable (const std::string& name) const = 0; @@ -184,9 +192,12 @@ namespace MWBase virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0; + virtual void + moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore &newCell, float x, float y, float z) = 0; + virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0; - virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z) = 0; + virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0; virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const = 0; @@ -252,6 +263,14 @@ namespace MWBase virtual bool isSwimming(const MWWorld::Ptr &object) = 0; virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos) = 0; + + virtual void togglePOV() = 0; + virtual void togglePreviewMode(bool enable) = 0; + virtual bool toggleVanityMode(bool enable, bool force) = 0; + virtual void allowVanityMode(bool allow) = 0; + virtual void togglePlayerLooking(bool enable) = 0; + + virtual void renderPlayer() = 0; }; } diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 9b0082efc1..7b8cbd3dad 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -4,6 +4,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld//cellstore.hpp" #include "../mwworld/ptr.hpp" @@ -12,7 +13,6 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" namespace MWClass @@ -34,7 +34,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Activator::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -104,4 +104,3 @@ namespace MWClass return MWWorld::Ptr(&cell.activators.insert(*ref), &cell); } } - diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 9814b140c1..3d362e8c8d 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -15,11 +16,8 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -39,7 +37,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -64,10 +62,12 @@ namespace MWClass boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action( + new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 4624b94d9c..f1400dc010 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -7,6 +7,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -18,11 +19,8 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -42,7 +40,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Armor::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -67,10 +65,11 @@ namespace MWClass boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } bool Armor::hasItemHealth (const MWWorld::Ptr& ptr) const @@ -272,9 +271,11 @@ namespace MWClass boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index d8166347ef..1e187342d9 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -5,6 +5,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actionread.hpp" @@ -14,11 +16,8 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -38,7 +37,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Book::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index f55d6ed881..21069e667e 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -14,13 +15,10 @@ #include "../mwworld/physicssystem.hpp" #include "../mwgui/tooltips.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -40,7 +38,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Clothing::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -63,12 +61,13 @@ namespace MWClass } boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const + const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Clothing::getScript (const MWWorld::Ptr& ptr) const @@ -223,9 +222,11 @@ namespace MWClass boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index c6d22b3a5a..608fc61227 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" @@ -14,14 +15,11 @@ #include "../mwworld/actionopen.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace { struct CustomData : public MWWorld::CustomData @@ -69,7 +67,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Container::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -94,8 +92,9 @@ namespace MWClass { // TODO check for key std::cout << "Locked container" << std::endl; - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, lockedSound, 1.0, 1.0); - return boost::shared_ptr (new MWWorld::NullAction); + boost::shared_ptr action(new MWWorld::NullAction); + action->setSound(lockedSound); + return action; } else { @@ -110,9 +109,10 @@ namespace MWClass { // Trap activation goes here std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, trapActivationSound, 1.0, 1.0); + boost::shared_ptr action(new MWWorld::NullAction); + action->setSound(trapActivationSound); ptr.getCellRef().trap = ""; - return boost::shared_ptr (new MWWorld::NullAction); + return action; } } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 620f809e7d..f03c0fdb19 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -4,10 +4,11 @@ #include #include "../mwmechanics/creaturestats.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwmechanics/magiceffects.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" @@ -17,7 +18,6 @@ #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" namespace @@ -61,10 +61,10 @@ namespace MWClass data->mCreatureStats.setLevel(ref->base->data.level); - data->mCreatureStats.setHello(ref->base->AI.hello); - data->mCreatureStats.setFight(ref->base->AI.fight); - data->mCreatureStats.setFlee(ref->base->AI.flee); - data->mCreatureStats.setAlarm(ref->base->AI.alarm); + data->mCreatureStats.setHello(ref->base->mAiData.mHello); + data->mCreatureStats.setFight(ref->base->mAiData.mFight); + data->mCreatureStats.setFlee(ref->base->mAiData.mFlee); + data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm); // store ptr.getRefData().setCustomData (data.release()); @@ -104,7 +104,7 @@ namespace MWClass if (!model.empty()) { return "meshes\\" + model; } - return ""; + return ""; } std::string Creature::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index f7a5e5874d..4de877b31d 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -59,6 +59,11 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool + isActor() const { + return true; + } }; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 6939c356e8..f483aa3a88 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/ptr.hpp" @@ -13,14 +14,11 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -81,17 +79,25 @@ namespace MWClass // TODO check for key // TODO report failure to player (message, sound?). Look up behaviour of original MW. std::cout << "Locked!" << std::endl; - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, lockedSound, 1.0, 1.0); - return boost::shared_ptr (new MWWorld::NullAction); + + boost::shared_ptr action(new MWWorld::NullAction); + + action->setSound(lockedSound); + + return action; } if(!ptr.getCellRef().trap.empty()) { // Trap activation std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - MWBase::Environment::get().getSoundManager()->playSound3D(ptr, trapActivationSound, 1.0, 1.0); + + boost::shared_ptr action(new MWWorld::NullAction); + + action->setSound(trapActivationSound); ptr.getCellRef().trap = ""; - return boost::shared_ptr (new MWWorld::NullAction); + + return action; } if (ref->ref.teleport) @@ -100,11 +106,11 @@ namespace MWClass /// \todo remove this if clause once ActionTeleport can also support other actors if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()==actor) { - // the player is using the door - // The reason this is not 3D is that it would get interrupted when you teleport - MWBase::Environment::get().getSoundManager()->playSound(openSound, 1.0, 1.0); - return boost::shared_ptr ( - new MWWorld::ActionTeleport (ref->ref.destCell, ref->ref.doorDest)); + boost::shared_ptr action(new MWWorld::ActionTeleport (ref->ref.destCell, ref->ref.doorDest)); + + action->setSound(openSound); + + return action; } else { @@ -118,8 +124,11 @@ namespace MWClass // TODO return action for rotating the door // This is a little pointless, but helps with testing - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, openSound, 1.0, 1.0); - return boost::shared_ptr (new MWWorld::NullAction); + boost::shared_ptr action(new MWWorld::NullAction); + + action->setSound(openSound); + + return action; } } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index d8c8b4b3b6..f0354de76a 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -5,20 +5,18 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -38,7 +36,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Ingredient::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -63,10 +61,11 @@ namespace MWClass boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index f09d3ce36c..5702215038 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -5,6 +5,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -14,11 +16,8 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" -#include "../mwsound/soundmanager.hpp" - #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -58,7 +57,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, "meshes\\" + model); } if (!ref->base->sound.empty()) { - MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->base->sound, 1.0, 1.0, MWSound::Play_Loop); + MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->base->sound, 1.0, 1.0, MWBase::SoundManager::Play_Loop); } } @@ -95,10 +94,11 @@ namespace MWClass if (!(ref->base->data.flags & ESM::Light::Carry)) return boost::shared_ptr (new MWWorld::NullAction); - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Light::getScript (const MWWorld::Ptr& ptr) const @@ -192,9 +192,11 @@ namespace MWClass boost::shared_ptr Light::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 20441b520c..44498e4797 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -13,14 +14,11 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -40,7 +38,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -65,10 +63,11 @@ namespace MWClass boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const @@ -161,9 +160,11 @@ namespace MWClass boost::shared_ptr Lockpick::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index cb6d40c434..eb44b81037 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -7,6 +7,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -14,14 +15,11 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/manualref.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - #include namespace MWClass @@ -43,7 +41,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Miscellaneous::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -68,10 +66,11 @@ namespace MWClass boost::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Miscellaneous::getScript (const MWWorld::Ptr& ptr) const @@ -189,7 +188,7 @@ namespace MWClass Miscellaneous::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::Ptr newPtr; - + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 72501e8acf..c9b16ae1e3 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -11,11 +11,12 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/movement.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" @@ -26,7 +27,6 @@ #include "../mwrender/actors.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" namespace @@ -100,10 +100,10 @@ namespace MWClass /// \todo do something with npdt12 maybe:p } - data->mCreatureStats.setHello(ref->base->AI.hello); - data->mCreatureStats.setFight(ref->base->AI.fight); - data->mCreatureStats.setFlee(ref->base->AI.flee); - data->mCreatureStats.setAlarm(ref->base->AI.alarm); + data->mCreatureStats.setHello(ref->base->mAiData.mHello); + data->mCreatureStats.setFight(ref->base->mAiData.mFight); + data->mCreatureStats.setFlee(ref->base->mAiData.mFlee); + data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm); // store ptr.getRefData().setCustomData (data.release()); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index e494fbaa70..edb6ca40fa 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -93,6 +93,11 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool + isActor() const { + return true; + } }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index d3f2912ea2..8fef163b1d 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -13,14 +14,11 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/player.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -65,10 +63,12 @@ namespace MWClass boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action( + new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound (getUpSoundId(ptr)); + + return action; } std::string Potion::getScript (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 4500162092..73258e5286 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -13,14 +14,11 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -40,7 +38,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Probe::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -64,10 +62,11 @@ namespace MWClass boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Probe::getScript (const MWWorld::Ptr& ptr) const @@ -160,9 +159,11 @@ namespace MWClass boost::shared_ptr Probe::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr @@ -174,4 +175,3 @@ namespace MWClass return MWWorld::Ptr(&cell.probes.insert(*ref), &cell); } } - diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 829fe311a7..a4240d0c49 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -5,20 +5,18 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -38,7 +36,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Repair::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -63,10 +61,11 @@ namespace MWClass boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } std::string Repair::getScript (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index b459531305..b2397f4aff 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" @@ -13,14 +14,11 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" -#include "../mwsound/soundmanager.hpp" - namespace MWClass { void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -40,7 +38,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Weapon::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -65,10 +63,11 @@ namespace MWClass boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); - return boost::shared_ptr ( - new MWWorld::ActionTake (ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } bool Weapon::hasItemHealth (const MWWorld::Ptr& ptr) const @@ -361,9 +360,11 @@ namespace MWClass boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const { - MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); - return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + action->setSound(getUpSoundId(ptr)); + + return action; } MWWorld::Ptr diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp similarity index 97% rename from apps/openmw/mwdialogue/dialoguemanager.cpp rename to apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 6f3f0c9012..841e36bf46 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -1,5 +1,5 @@ -#include "dialoguemanager.hpp" +#include "dialoguemanagerimp.hpp" #include #include @@ -11,33 +11,30 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/scriptmanager.hpp" +#include "../mwbase/journal.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/refdata.hpp" #include "../mwworld/player.hpp" #include "../mwworld/containerstore.hpp" -#include "../mwinput/inputmanager.hpp" #include "../mwgui/dialogue.hpp" -#include "../mwgui/window_manager.hpp" - -#include "journal.hpp" #include -#include "../mwscript/extensions.hpp" -#include "../mwscript/scriptmanager.hpp" - #include #include #include #include #include +#include #include #include "../mwscript/compilercontext.hpp" #include "../mwscript/interpretercontext.hpp" -#include +#include "../mwscript/extensions.hpp" #include "../mwclass/npc.hpp" #include "../mwmechanics/npcstats.hpp" @@ -599,12 +596,12 @@ namespace MWDialogue } } - void DialogueManager::addTopic(std::string topic) + void DialogueManager::addTopic (const std::string& topic) { mKnownTopics[toLower(topic)] = true; } - void DialogueManager::parseText(std::string text) + void DialogueManager::parseText (std::string text) { std::list::iterator it; for(it = mActorKnownTopics.begin();it != mActorKnownTopics.end();++it) @@ -772,14 +769,14 @@ namespace MWDialogue if (mActor.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mActor.get(); - if (ref->base->hasAI) - services = ref->base->AI.services; + if (ref->base->mHasAI) + services = ref->base->mAiData.mServices; } else if (mActor.getTypeName() == typeid(ESM::Creature).name()) { MWWorld::LiveCellRef* ref = mActor.get(); - if (ref->base->hasAI) - services = ref->base->AI.services; + if (ref->base->mHasAI) + services = ref->base->mAiData.mServices; } if (services & ESM::NPC::Weapon @@ -804,7 +801,7 @@ namespace MWDialogue mChoice = choice; } - void DialogueManager::keywordSelected(std::string keyword) + void DialogueManager::keywordSelected (const std::string& keyword) { if(!mIsInChoice) { @@ -846,11 +843,11 @@ namespace MWDialogue MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); } - void DialogueManager::questionAnswered(std::string answere) + void DialogueManager::questionAnswered (const std::string& answer) { - if(mChoiceMap.find(answere) != mChoiceMap.end()) + if(mChoiceMap.find(answer) != mChoiceMap.end()) { - mChoice = mChoiceMap[answere]; + mChoice = mChoiceMap[answer]; std::vector::const_iterator iter; if(mDialogueMap.find(mLastTopic) != mDialogueMap.end()) @@ -882,13 +879,13 @@ namespace MWDialogue } } - void DialogueManager::printError(std::string error) + void DialogueManager::printError (std::string error) { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->addText(error); } - void DialogueManager::askQuestion(std::string question, int choice) + void DialogueManager::askQuestion (const std::string& question, int choice) { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->askQuestion(question); @@ -896,7 +893,7 @@ namespace MWDialogue mIsInChoice = true; } - std::string DialogueManager::getFaction() + std::string DialogueManager::getFaction() const { if (mActor.getTypeName() != typeid(ESM::NPC).name()) return ""; diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp similarity index 71% rename from apps/openmw/mwdialogue/dialoguemanager.hpp rename to apps/openmw/mwdialogue/dialoguemanagerimp.hpp index d139ddc010..e3e9fd7529 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -1,5 +1,7 @@ -#ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H -#define GAME_MWDIALOG_DIALOGUEMANAGER_H +#ifndef GAME_MWDIALOG_DIALOGUEMANAGERIMP_H +#define GAME_MWDIALOG_DIALOGUEMANAGERIMP_H + +#include "../mwbase/dialoguemanager.hpp" #include @@ -9,11 +11,12 @@ #include #include "../mwworld/ptr.hpp" + #include namespace MWDialogue { - class DialogueManager + class DialogueManager : public MWBase::DialogueManager { bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; @@ -50,21 +53,21 @@ namespace MWDialogue DialogueManager (const Compiler::Extensions& extensions); - void startDialogue (const MWWorld::Ptr& actor); + virtual void startDialogue (const MWWorld::Ptr& actor); - void addTopic(std::string topic); + virtual void addTopic (const std::string& topic); - void askQuestion(std::string question,int choice); + virtual void askQuestion (const std::string& question,int choice); - void goodbye(); + virtual void goodbye(); ///get the faction of the actor you are talking with - std::string getFaction(); + virtual std::string getFaction() const; //calbacks for the GUI - void keywordSelected(std::string keyword); - void goodbyeSelected(); - void questionAnswered(std::string answere); + virtual void keywordSelected (const std::string& keyword); + virtual void goodbyeSelected(); + virtual void questionAnswered (const std::string& answer); }; } diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp index 9a3270439f..3e86401852 100644 --- a/apps/openmw/mwdialogue/journalentry.hpp +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MMDIALOGUE_JOURNALENTRY_H -#define GAME_MMDIALOGUE_JOURNALENTRY_H +#ifndef GAME_MWDIALOGUE_JOURNALENTRY_H +#define GAME_MWDIALOGUE_JOURNALENTRY_H #include diff --git a/apps/openmw/mwdialogue/journal.cpp b/apps/openmw/mwdialogue/journalimp.cpp similarity index 95% rename from apps/openmw/mwdialogue/journal.cpp rename to apps/openmw/mwdialogue/journalimp.cpp index ad10be3aa8..d626cd3159 100644 --- a/apps/openmw/mwdialogue/journal.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -1,10 +1,12 @@ -#include "journal.hpp" +#include "journalimp.hpp" + +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/messagebox.hpp" namespace MWDialogue diff --git a/apps/openmw/mwdialogue/journal.hpp b/apps/openmw/mwdialogue/journalimp.hpp similarity index 50% rename from apps/openmw/mwdialogue/journal.hpp rename to apps/openmw/mwdialogue/journalimp.hpp index 62b9f4bed9..7d71fd7d06 100644 --- a/apps/openmw/mwdialogue/journal.hpp +++ b/apps/openmw/mwdialogue/journalimp.hpp @@ -1,9 +1,7 @@ -#ifndef GAME_MMDIALOG_JOURNAL_H +#ifndef GAME_MWDIALOG_JOURNAL_H #define GAME_MWDIALOG_JOURNAL_H -#include -#include -#include +#include "../mwbase/journal.hpp" #include "journalentry.hpp" #include "quest.hpp" @@ -11,19 +9,8 @@ namespace MWDialogue { /// \brief The player's journal - class Journal + class Journal : public MWBase::Journal { - public: - - typedef std::deque TEntryContainer; - typedef TEntryContainer::const_iterator TEntryIter; - typedef std::map TQuestContainer; // topc, quest - typedef TQuestContainer::const_iterator TQuestIter; - typedef std::map TTopicContainer; // topic-id, topic-content - typedef TTopicContainer::const_iterator TTopicIter; - - private: - TEntryContainer mJournal; TQuestContainer mQuests; TTopicContainer mTopics; @@ -34,37 +21,37 @@ namespace MWDialogue Journal(); - void addEntry (const std::string& id, int index); + virtual void addEntry (const std::string& id, int index); ///< Add a journal entry. - void setJournalIndex (const std::string& id, int index); + virtual void setJournalIndex (const std::string& id, int index); ///< Set the journal index without adding an entry. - int getJournalIndex (const std::string& id) const; + virtual int getJournalIndex (const std::string& id) const; ///< Get the journal index. - void addTopic (const std::string& topicId, const std::string& infoId); + virtual void addTopic (const std::string& topicId, const std::string& infoId); - TEntryIter begin() const; + virtual TEntryIter begin() const; ///< Iterator pointing to the begin of the main journal. /// /// \note Iterators to main journal entries will never become invalid. - TEntryIter end() const; + virtual TEntryIter end() const; ///< Iterator pointing past the end of the main journal. - TQuestIter questBegin() const; + virtual TQuestIter questBegin() const; ///< Iterator pointing to the first quest (sorted by topic ID) - TQuestIter questEnd() const; + virtual TQuestIter questEnd() const; ///< Iterator pointing past the last quest. - TTopicIter topicBegin() const; + virtual TTopicIter topicBegin() const; ///< Iterator pointing to the first topic (sorted by topic ID) /// /// \note The topic ID is identical with the user-visible topic string. - TTopicIter topicEnd() const; + virtual TTopicIter topicEnd() const; ///< Iterator pointing past the last topic. }; } diff --git a/apps/openmw/mwdialogue/quest.hpp b/apps/openmw/mwdialogue/quest.hpp index 5fcc894ea4..3afa81fac0 100644 --- a/apps/openmw/mwdialogue/quest.hpp +++ b/apps/openmw/mwdialogue/quest.hpp @@ -1,4 +1,4 @@ -#ifndef GAME_MMDIALOG_QUEST_H +#ifndef GAME_MWDIALOG_QUEST_H #define GAME_MWDIALOG_QUEST_H #include "topic.hpp" diff --git a/apps/openmw/mwdialogue/topic.hpp b/apps/openmw/mwdialogue/topic.hpp index 3ad15903f7..566f60ab00 100644 --- a/apps/openmw/mwdialogue/topic.hpp +++ b/apps/openmw/mwdialogue/topic.hpp @@ -1,4 +1,4 @@ -#ifndef GAME_MMDIALOG_TOPIC_H +#ifndef GAME_MWDIALOG_TOPIC_H #define GAME_MWDIALOG_TOPIC_H #include diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 9d691d371d..5cf09b18a3 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -4,15 +4,13 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/manualref.hpp" #include "../mwworld/containerstore.hpp" -#include "../mwsound/soundmanager.hpp" - -#include "window_manager.hpp" - namespace { std::string getIconPath(MWWorld::Ptr ptr) @@ -28,7 +26,7 @@ namespace namespace MWGui { - AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager) + AlchemyWindow::AlchemyWindow(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_alchemy_window.layout", parWindowManager) , ContainerBase(0) { diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 81c33a96df..53e7178d50 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -10,7 +10,7 @@ namespace MWGui class AlchemyWindow : public WindowBase, public ContainerBase { public: - AlchemyWindow(WindowManager& parWindowManager); + AlchemyWindow(MWBase::WindowManager& parWindowManager); virtual void open(); diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 0f1a04c27b..1a5c2d0f6e 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -1,15 +1,20 @@ #include "birth.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" #include #include +#include "components/esm_store/store.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + +#include "widgets.hpp" + using namespace MWGui; using namespace Widgets; -BirthDialog::BirthDialog(WindowManager& parWindowManager) +BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_birth.layout", parWindowManager) { // Centre dialog @@ -60,9 +65,9 @@ void BirthDialog::setNextButtonShow(bool shown) void BirthDialog::open() { + WindowBase::open(); updateBirths(); updateSpells(); - setVisible(true); } @@ -114,7 +119,7 @@ void BirthDialog::updateBirths() { mBirthList->removeAllItems(); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); ESMS::RecListT::MapType::const_iterator it = store.birthSigns.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.birthSigns.list.end(); @@ -144,7 +149,7 @@ void BirthDialog::updateSpells() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, mSpellArea->getWidth(), 18); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::BirthSign *birth = store.birthSigns.find(mCurrentBirthId); std::string texturePath = std::string("textures\\") + birth->texture; diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index 770e4ba36c..5bd36e8289 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -10,14 +10,13 @@ namespace MWGui { + /// \todo remove using namespace MyGUI; - class WindowManager; - class BirthDialog : public WindowBase { public: - BirthDialog(WindowManager& parWindowManager); + BirthDialog(MWBase::WindowManager& parWindowManager); enum Gender { @@ -29,7 +28,7 @@ namespace MWGui void setBirthId(const std::string &raceId); void setNextButtonShow(bool shown); - void open(); + virtual void open(); // Events typedef delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 1e0301d8ea..57e59657a7 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -4,17 +4,17 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" -#include "../mwinput/inputmanager.hpp" -#include "../mwsound/soundmanager.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" + #include "../mwworld/actiontake.hpp" #include "../mwworld/player.hpp" #include "formatting.hpp" -#include "window_manager.hpp" using namespace MWGui; -BookWindow::BookWindow (WindowManager& parWindowManager) : +BookWindow::BookWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_book.layout", parWindowManager) { getWidget(mCloseButton, "CloseButton"); @@ -98,7 +98,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack); MWWorld::ActionTake take(mBook); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index 9ea0114338..fedb783b25 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -10,7 +10,7 @@ namespace MWGui class BookWindow : public WindowBase { public: - BookWindow(WindowManager& parWindowManager); + BookWindow(MWBase::WindowManager& parWindowManager); void open(MWWorld::Ptr book); void setTakeButtonShow(bool show); @@ -43,4 +43,3 @@ namespace MWGui } #endif - diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index c39e305dc9..7d63f69220 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -9,7 +9,8 @@ #include "mode.hpp" #include "../mwbase/environment.hpp" -#include "../mwsound/soundmanager.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" namespace { @@ -103,11 +104,19 @@ namespace {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} } } }; + + struct ClassPoint + { + const char *id; + // Specialization points to match, in order: Stealth, Combat, Magic + // Note: Order is taken from http://www.uesp.net/wiki/Morrowind:Class_Quiz + unsigned int points[3]; + }; } using namespace MWGui; -CharacterCreation::CharacterCreation(WindowManager* _wm) +CharacterCreation::CharacterCreation(MWBase::WindowManager* _wm) : mNameDialog(0) , mRaceDialog(0) , mClassChoiceDialog(0) @@ -178,64 +187,64 @@ void CharacterCreation::spawnDialog(const char id) switch (id) { case GM_Name: - if(mNameDialog) - mWM->removeDialog(mNameDialog); + mWM->removeDialog(mNameDialog); + mNameDialog = 0; mNameDialog = new TextInputDialog(*mWM); mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name")); mNameDialog->setTextInput(mPlayerName); mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen); mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone); - mNameDialog->open(); + mNameDialog->setVisible(true); break; case GM_Race: - if (mRaceDialog) - mWM->removeDialog(mRaceDialog); + mWM->removeDialog(mRaceDialog); + mRaceDialog = 0; mRaceDialog = new RaceDialog(*mWM); mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen); mRaceDialog->setRaceId(mPlayerRaceId); mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone); mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack); - mRaceDialog->open(); + mRaceDialog->setVisible(true);; break; case GM_Class: - if (mClassChoiceDialog) - mWM->removeDialog(mClassChoiceDialog); + mWM->removeDialog(mClassChoiceDialog); + mClassChoiceDialog = 0; mClassChoiceDialog = new ClassChoiceDialog(*mWM); mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice); - mClassChoiceDialog->open(); + mClassChoiceDialog->setVisible(true); break; case GM_ClassPick: - if (mPickClassDialog) - mWM->removeDialog(mPickClassDialog); + mWM->removeDialog(mPickClassDialog); + mPickClassDialog = 0; mPickClassDialog = new PickClassDialog(*mWM); mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); mPickClassDialog->setClassId(mPlayerClass.name); mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone); mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack); - mPickClassDialog->open(); + mPickClassDialog->setVisible(true); break; case GM_Birth: - if (mBirthSignDialog) - mWM->removeDialog(mBirthSignDialog); + mWM->removeDialog(mBirthSignDialog); + mBirthSignDialog = 0; mBirthSignDialog = new BirthDialog(*mWM); mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen); mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone); mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack); - mBirthSignDialog->open(); + mBirthSignDialog->setVisible(true); break; case GM_ClassCreate: - if (mCreateClassDialog) - mWM->removeDialog(mCreateClassDialog); + mWM->removeDialog(mCreateClassDialog); + mCreateClassDialog = 0; mCreateClassDialog = new CreateClassDialog(*mWM); mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); - mCreateClassDialog->open(); + mCreateClassDialog->setVisible(true); break; case GM_ClassGenerate: mGenerateClassStep = 0; @@ -246,8 +255,8 @@ void CharacterCreation::spawnDialog(const char id) showClassQuestionDialog(); break; case GM_Review: - if (mReviewDialog) - mWM->removeDialog(mReviewDialog); + mWM->removeDialog(mReviewDialog); + mReviewDialog = 0; mReviewDialog = new ReviewDialog(*mWM); mReviewDialog->setPlayerName(mPlayerName); mReviewDialog->setRace(mPlayerRaceId); @@ -259,20 +268,20 @@ void CharacterCreation::spawnDialog(const char id) mReviewDialog->setFatigue(mPlayerFatigue); { - std::map > attributes = mWM->getPlayerAttributeValues(); - for (std::map >::iterator it = attributes.begin(); + std::map > attributes = mWM->getPlayerAttributeValues(); + for (std::map >::iterator it = attributes.begin(); it != attributes.end(); ++it) { - mReviewDialog->setAttribute(it->first, it->second); + mReviewDialog->setAttribute(static_cast (it->first), it->second); } } { - std::map > skills = mWM->getPlayerSkillValues(); - for (std::map >::iterator it = skills.begin(); + std::map > skills = mWM->getPlayerSkillValues(); + for (std::map >::iterator it = skills.begin(); it != skills.end(); ++it) { - mReviewDialog->setSkillValue(it->first, it->second); + mReviewDialog->setSkillValue(static_cast (it->first), it->second); } mReviewDialog->configureSkills(mWM->getPlayerMajorSkills(), mWM->getPlayerMinorSkills()); } @@ -280,7 +289,7 @@ void CharacterCreation::spawnDialog(const char id) mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack); mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog); - mReviewDialog->open(); + mReviewDialog->setVisible(true); break; } } @@ -302,24 +311,24 @@ void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat& v void CharacterCreation::onReviewDialogDone(WindowBase* parWindow) { - if (mReviewDialog) - mWM->removeDialog(mReviewDialog); + mWM->removeDialog(mReviewDialog); + mReviewDialog = 0; mWM->popGuiMode(); } void CharacterCreation::onReviewDialogBack() { - if (mReviewDialog) - mWM->removeDialog(mReviewDialog); + mWM->removeDialog(mReviewDialog); + mReviewDialog = 0; mWM->pushGuiMode(GM_Birth); } void CharacterCreation::onReviewActivateDialog(int parDialog) { - if (mReviewDialog) - mWM->removeDialog(mReviewDialog); + mWM->removeDialog(mReviewDialog); + mReviewDialog = 0; mCreationStage = CSE_ReviewNext; mWM->popGuiMode(); @@ -354,6 +363,7 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) mWM->setPlayerClass(mPlayerClass); } mWM->removeDialog(mPickClassDialog); + mPickClassDialog = 0; } //TODO This bit gets repeated a few times; wrap it in a function @@ -382,6 +392,7 @@ void CharacterCreation::onPickClassDialogBack() if (!classId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId); mWM->removeDialog(mPickClassDialog); + mPickClassDialog = 0; } mWM->popGuiMode(); @@ -390,10 +401,8 @@ void CharacterCreation::onPickClassDialogBack() void CharacterCreation::onClassChoice(int _index) { - if (mClassChoiceDialog) - { - mWM->removeDialog(mClassChoiceDialog); - } + mWM->removeDialog(mClassChoiceDialog); + mClassChoiceDialog = 0; mWM->popGuiMode(); @@ -423,6 +432,7 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow) mWM->setValue("name", mPlayerName); MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName); mWM->removeDialog(mNameDialog); + mNameDialog = 0; } if (mCreationStage == CSE_ReviewNext) @@ -450,6 +460,7 @@ void CharacterCreation::onRaceDialogBack() if (!mPlayerRaceId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); mWM->removeDialog(mRaceDialog); + mRaceDialog = 0; } mWM->popGuiMode(); @@ -465,6 +476,7 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) if (!mPlayerRaceId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); mWM->removeDialog(mRaceDialog); + mRaceDialog = 0; } if (mCreationStage == CSE_ReviewNext) @@ -492,6 +504,7 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) if (!mPlayerBirthSignId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId); mWM->removeDialog(mBirthSignDialog); + mBirthSignDialog = 0; } if (mCreationStage >= CSE_BirthSignChosen) @@ -512,6 +525,7 @@ void CharacterCreation::onBirthSignDialogBack() { MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId()); mWM->removeDialog(mBirthSignDialog); + mBirthSignDialog = 0; } mWM->popGuiMode(); @@ -547,6 +561,7 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) mWM->setPlayerClass(klass); mWM->removeDialog(mCreateClassDialog); + mCreateClassDialog = 0; } if (mCreationStage == CSE_ReviewNext) @@ -568,8 +583,8 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) void CharacterCreation::onCreateClassDialogBack() { - if (mCreateClassDialog) - mWM->removeDialog(mCreateClassDialog); + mWM->removeDialog(mCreateClassDialog); + mCreateClassDialog = 0; mWM->popGuiMode(); mWM->pushGuiMode(GM_Class); @@ -579,8 +594,9 @@ void CharacterCreation::onClassQuestionChosen(int _index) { MWBase::Environment::get().getSoundManager()->stopSay(); - if (mGenerateClassQuestionDialog) - mWM->removeDialog(mGenerateClassQuestionDialog); + mWM->removeDialog(mGenerateClassQuestionDialog); + mGenerateClassQuestionDialog = 0; + if (_index < 0 || _index >= 3) { mWM->popGuiMode(); @@ -657,13 +673,14 @@ void CharacterCreation::showClassQuestionDialog() } } - if (mGenerateClassResultDialog) - mWM->removeDialog(mGenerateClassResultDialog); + mWM->removeDialog(mGenerateClassResultDialog); + mGenerateClassResultDialog = 0; + mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM); mGenerateClassResultDialog->setClassId(mGenerateClass); mGenerateClassResultDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack); mGenerateClassResultDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone); - mGenerateClassResultDialog->open(); + mGenerateClassResultDialog->setVisible(true); return; } @@ -674,8 +691,9 @@ void CharacterCreation::showClassQuestionDialog() return; } - if (mGenerateClassQuestionDialog) - mWM->removeDialog(mGenerateClassQuestionDialog); + mWM->removeDialog(mGenerateClassQuestionDialog); + mGenerateClassQuestionDialog = 0; + mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM); InfoBoxDialog::ButtonList buttons; @@ -685,7 +703,7 @@ void CharacterCreation::showClassQuestionDialog() buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]); mGenerateClassQuestionDialog->setButtons(buttons); mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen); - mGenerateClassQuestionDialog->open(); + mGenerateClassQuestionDialog->setVisible(true); MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps[mGenerateClassStep].mSound); } @@ -695,8 +713,9 @@ void CharacterCreation::onGenerateClassBack() if(mCreationStage < CSE_ClassChosen) mCreationStage = CSE_ClassChosen; - if (mGenerateClassResultDialog) - mWM->removeDialog(mGenerateClassResultDialog); + mWM->removeDialog(mGenerateClassResultDialog); + mGenerateClassResultDialog = 0; + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); mWM->popGuiMode(); @@ -705,8 +724,9 @@ void CharacterCreation::onGenerateClassBack() void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) { - if (mGenerateClassResultDialog) - mWM->removeDialog(mGenerateClassResultDialog); + mWM->removeDialog(mGenerateClassResultDialog); + mGenerateClassResultDialog = 0; + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(mGenerateClass); mPlayerClass = *klass; diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index e9c90877e6..d65763d0cd 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -1,18 +1,15 @@ #ifndef CHARACTER_CREATION_HPP #define CHARACTER_CREATION_HPP -#include "window_manager.hpp" - #include #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwmechanics/stat.hpp" namespace MWGui { - class WindowManager; class WindowBase; class TextInputDialog; @@ -32,7 +29,7 @@ namespace MWGui public: typedef std::vector SkillList; - CharacterCreation(WindowManager* _wm); + CharacterCreation(MWBase::WindowManager* _wm); ~CharacterCreation(); //Show a dialog @@ -61,7 +58,7 @@ namespace MWGui BirthDialog* mBirthSignDialog; ReviewDialog* mReviewDialog; - WindowManager* mWM; + MWBase::WindowManager* mWM; //Player data std::string mPlayerName; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 48e01eb1e9..9ea7b8052e 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -7,7 +7,10 @@ #include -#include "window_manager.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + #include "tooltips.hpp" #undef min @@ -17,7 +20,7 @@ using namespace MWGui; /* GenerateClassResultDialog */ -GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowManager) +GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_generate_class_result.layout", parWindowManager) { // Centre dialog @@ -43,11 +46,6 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan backButton->setCoord(315 - okButtonWidth - backButtonWidth - 6, 219, backButtonWidth, 23); } -void GenerateClassResultDialog::open() -{ - setVisible(true); -} - std::string GenerateClassResultDialog::getClassId() const { return mClassName->getCaption(); @@ -57,8 +55,7 @@ void GenerateClassResultDialog::setClassId(const std::string &classId) { mCurrentClassId = classId; mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds"); - const ESMS::ESMStore &store = mWindowManager.getStore(); - mClassName->setCaption(store.classes.find(mCurrentClassId)->name); + mClassName->setCaption(MWBase::Environment::get().getWorld()->getStore().classes.find(mCurrentClassId)->name); } // widget controls @@ -75,7 +72,7 @@ void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender) /* PickClassDialog */ -PickClassDialog::PickClassDialog(WindowManager& parWindowManager) +PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_class.layout", parWindowManager) { // Centre dialog @@ -141,7 +138,6 @@ void PickClassDialog::open() { updateClasses(); updateStats(); - setVisible(true); } @@ -193,7 +189,7 @@ void PickClassDialog::updateClasses() { mClassList->removeAllItems(); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); ESMS::RecListT::MapType::const_iterator it = store.classes.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.classes.list.end(); @@ -217,7 +213,7 @@ void PickClassDialog::updateStats() { if (mCurrentClassId.empty()) return; - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Class *klass = store.classes.search(mCurrentClassId); if (!klass) return; @@ -281,7 +277,7 @@ void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin) widget->setSize(width, pos); } -InfoBoxDialog::InfoBoxDialog(WindowManager& parWindowManager) +InfoBoxDialog::InfoBoxDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_infobox.layout", parWindowManager) , mCurrentButton(-1) { @@ -339,7 +335,6 @@ void InfoBoxDialog::open() layoutVertically(mMainWidget, 4 + 6); center(); - setVisible(true); } int InfoBoxDialog::getChosenButton() const @@ -365,7 +360,7 @@ void InfoBoxDialog::onButtonClicked(MyGUI::WidgetPtr _sender) /* ClassChoiceDialog */ -ClassChoiceDialog::ClassChoiceDialog(WindowManager& parWindowManager) +ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager) : InfoBoxDialog(parWindowManager) { setText(""); @@ -379,7 +374,7 @@ ClassChoiceDialog::ClassChoiceDialog(WindowManager& parWindowManager) /* CreateClassDialog */ -CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) +CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_create_class.layout", parWindowManager) , mSpecDialog(nullptr) , mAttribDialog(nullptr) @@ -547,35 +542,21 @@ void CreateClassDialog::setNextButtonShow(bool shown) descriptionButton->setCoord(459 - okButtonWidth - backButtonWidth - descriptionButtonWidth - 12, 158, descriptionButtonWidth, 23); } -void CreateClassDialog::open() -{ - setVisible(true); -} - // widget controls void CreateClassDialog::onDialogCancel() { - if (mSpecDialog) - { - mWindowManager.removeDialog(mSpecDialog); - mSpecDialog = 0; - } - if (mAttribDialog) - { - mWindowManager.removeDialog(mAttribDialog); - mAttribDialog = 0; - } - if (mSkillDialog) - { - mWindowManager.removeDialog(mSkillDialog); - mSkillDialog = 0; - } - if (mDescDialog) - { - mWindowManager.removeDialog(mDescDialog); - mDescDialog = 0; - } + mWindowManager.removeDialog(mSpecDialog); + mSpecDialog = 0; + + mWindowManager.removeDialog(mAttribDialog); + mAttribDialog = 0; + + mWindowManager.removeDialog(mSkillDialog); + mSkillDialog = 0; + + mWindowManager.removeDialog(mDescDialog); + mDescDialog = 0; } void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) @@ -701,8 +682,8 @@ void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender) /* SelectSpecializationDialog */ -SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowManager) - : WindowBase("openmw_chargen_select_specialization.layout", parWindowManager) +SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& parWindowManager) + : WindowModal("openmw_chargen_select_specialization.layout", parWindowManager) { // Centre dialog center(); @@ -734,13 +715,10 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); - - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); } SelectSpecializationDialog::~SelectSpecializationDialog() { - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -766,8 +744,8 @@ void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectAttributeDialog */ -SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) - : WindowBase("openmw_chargen_select_attribute.layout", parWindowManager) +SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowManager) + : WindowModal("openmw_chargen_select_attribute.layout", parWindowManager) { // Centre dialog center(); @@ -792,13 +770,10 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); - - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); } SelectAttributeDialog::~SelectAttributeDialog() { - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -818,8 +793,8 @@ void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectSkillDialog */ -SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) - : WindowBase("openmw_chargen_select_skill.layout", parWindowManager) +SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) + : WindowModal("openmw_chargen_select_skill.layout", parWindowManager) { // Centre dialog center(); @@ -891,12 +866,10 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); } SelectSkillDialog::~SelectSkillDialog() { - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -914,8 +887,8 @@ void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender) /* DescriptionDialog */ -DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) - : WindowBase("openmw_chargen_class_description.layout", parWindowManager) +DescriptionDialog::DescriptionDialog(MWBase::WindowManager& parWindowManager) + : WindowModal("openmw_chargen_class_description.layout", parWindowManager) { // Centre dialog center(); @@ -931,13 +904,10 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); - - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); } DescriptionDialog::~DescriptionDialog() { - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 4d8d9fa231..43511cccaa 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -12,14 +12,13 @@ namespace MWGui { + /// \todo remove! using namespace MyGUI; - class WindowManager; - class InfoBoxDialog : public WindowBase { public: - InfoBoxDialog(WindowManager& parWindowManager); + InfoBoxDialog(MWBase::WindowManager& parWindowManager); typedef std::vector ButtonList; @@ -27,7 +26,7 @@ namespace MWGui std::string getText() const; void setButtons(ButtonList &buttons); - void open(); + virtual void open(); int getChosenButton() const; // Events @@ -64,19 +63,17 @@ namespace MWGui Class_Create = 2, Class_Back = 3 }; - ClassChoiceDialog(WindowManager& parWindowManager); + ClassChoiceDialog(MWBase::WindowManager& parWindowManager); }; class GenerateClassResultDialog : public WindowBase { public: - GenerateClassResultDialog(WindowManager& parWindowManager); + GenerateClassResultDialog(MWBase::WindowManager& parWindowManager); std::string getClassId() const; void setClassId(const std::string &classId); - void open(); - // Events typedef delegates::CMultiDelegate0 EventHandle_Void; @@ -99,13 +96,13 @@ namespace MWGui class PickClassDialog : public WindowBase { public: - PickClassDialog(WindowManager& parWindowManager); + PickClassDialog(MWBase::WindowManager& parWindowManager); const std::string &getClassId() const { return mCurrentClassId; } void setClassId(const std::string &classId); void setNextButtonShow(bool shown); - void open(); + virtual void open(); // Events typedef delegates::CMultiDelegate0 EventHandle_Void; @@ -135,10 +132,10 @@ namespace MWGui std::string mCurrentClassId; }; - class SelectSpecializationDialog : public WindowBase + class SelectSpecializationDialog : public WindowModal { public: - SelectSpecializationDialog(WindowManager& parWindowManager); + SelectSpecializationDialog(MWBase::WindowManager& parWindowManager); ~SelectSpecializationDialog(); ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; } @@ -166,10 +163,10 @@ namespace MWGui ESM::Class::Specialization mSpecializationId; }; - class SelectAttributeDialog : public WindowBase + class SelectAttributeDialog : public WindowModal { public: - SelectAttributeDialog(WindowManager& parWindowManager); + SelectAttributeDialog(MWBase::WindowManager& parWindowManager); ~SelectAttributeDialog(); ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; } @@ -199,10 +196,10 @@ namespace MWGui ESM::Attribute::AttributeID mAttributeId; }; - class SelectSkillDialog : public WindowBase + class SelectSkillDialog : public WindowModal { public: - SelectSkillDialog(WindowManager& parWindowManager); + SelectSkillDialog(MWBase::WindowManager& parWindowManager); ~SelectSkillDialog(); ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } @@ -235,10 +232,10 @@ namespace MWGui ESM::Skill::SkillEnum mSkillId; }; - class DescriptionDialog : public WindowBase + class DescriptionDialog : public WindowModal { public: - DescriptionDialog(WindowManager& parWindowManager); + DescriptionDialog(MWBase::WindowManager& parWindowManager); ~DescriptionDialog(); std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } @@ -254,7 +251,7 @@ namespace MWGui class CreateClassDialog : public WindowBase { public: - CreateClassDialog(WindowManager& parWindowManager); + CreateClassDialog(MWBase::WindowManager& parWindowManager); virtual ~CreateClassDialog(); std::string getName() const; @@ -265,7 +262,6 @@ namespace MWGui std::vector getMinorSkills() const; void setNextButtonShow(bool shown); - void open(); // Events typedef delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index 00bdca6382..d22181d60c 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -7,8 +7,8 @@ namespace MWGui { - ConfirmationDialog::ConfirmationDialog(WindowManager& parWindowManager) : - WindowBase("openmw_confirmation_dialog.layout", parWindowManager) + ConfirmationDialog::ConfirmationDialog(MWBase::WindowManager& parWindowManager) : + WindowModal("openmw_confirmation_dialog.layout", parWindowManager) { getWidget(mMessage, "Message"); getWidget(mOkButton, "OkButton"); @@ -32,9 +32,6 @@ namespace MWGui center(); - // make other gui elements inaccessible while this dialog is open - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); - int okButtonWidth = mOkButton->getTextSize().width + 24; mOkButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth, mOkButton->getTop(), @@ -52,19 +49,13 @@ namespace MWGui { eventCancelClicked(); - close(); + setVisible(false); } void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender) { eventOkClicked(); - close(); - } - - void ConfirmationDialog::close() - { setVisible(false); - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } } diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index d278274a03..45941f2ad0 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -5,10 +5,10 @@ namespace MWGui { - class ConfirmationDialog : public WindowBase + class ConfirmationDialog : public WindowModal { public: - ConfirmationDialog(WindowManager& parWindowManager); + ConfirmationDialog(MWBase::WindowManager& parWindowManager); void open(const std::string& message); typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; @@ -26,8 +26,6 @@ namespace MWGui void onCancelButtonClicked(MyGUI::Widget* _sender); void onOkButtonClicked(MyGUI::Widget* _sender); - - void close(); }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 44cb12d2d4..75e2bb3b85 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -10,6 +10,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/manualref.hpp" #include "../mwworld/containerstore.hpp" @@ -18,11 +20,6 @@ #include "../mwclass/container.hpp" -#include "../mwinput/inputmanager.hpp" - -#include "../mwsound/soundmanager.hpp" - -#include "window_manager.hpp" #include "widgets.hpp" #include "countdialog.hpp" #include "tradewindow.hpp" @@ -594,7 +591,7 @@ MWWorld::ContainerStore& ContainerBase::getContainerStore() // ------------------------------------------------------------------------------------------------ -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) +ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) , WindowBase("openmw_container_window.layout", parWindowManager) { diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 88e445a7bb..27c3288ae7 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -127,7 +127,7 @@ namespace MWGui class ContainerWindow : public ContainerBase, public WindowBase { public: - ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + ContainerWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop); virtual ~ContainerWindow(); diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 07f1acb73b..0ed9cf8cac 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -7,8 +7,8 @@ namespace MWGui { - CountDialog::CountDialog(WindowManager& parWindowManager) : - WindowBase("openmw_count_window.layout", parWindowManager) + CountDialog::CountDialog(MWBase::WindowManager& parWindowManager) : + WindowModal("openmw_count_window.layout", parWindowManager) { getWidget(mSlider, "CountSlider"); getWidget(mItemEdit, "ItemEdit"); @@ -40,9 +40,6 @@ namespace MWGui width, mMainWidget->getHeight()); - // make other gui elements inaccessible while this dialog is open - MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit); mSlider->setScrollPosition(maxCount-1); @@ -63,14 +60,14 @@ namespace MWGui void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender) { - close(); + setVisible(false); } void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender) { eventOkClicked(NULL, mSlider->getScrollPosition()+1); - close(); + setVisible(false); } void CountDialog::onEditTextChange(MyGUI::EditBox* _sender) @@ -99,10 +96,4 @@ namespace MWGui { mItemEdit->setCaption(boost::lexical_cast(_position+1)); } - - void CountDialog::close() - { - setVisible(false); - MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); - } } diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index aac17b846d..80da6eea01 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -5,10 +5,10 @@ namespace MWGui { - class CountDialog : public WindowBase + class CountDialog : public WindowModal { public: - CountDialog(WindowManager& parWindowManager); + CountDialog(MWBase::WindowManager& parWindowManager); void open(const std::string& item, const std::string& message, const int maxCount); typedef MyGUI::delegates::CMultiDelegate2 EventHandle_WidgetInt; @@ -30,8 +30,6 @@ namespace MWGui void onOkButtonClicked(MyGUI::Widget* _sender); void onEditTextChange(MyGUI::EditBox* _sender); void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position); - - void close(); }; } diff --git a/apps/openmw/mwgui/cursorreplace.cpp b/apps/openmw/mwgui/cursorreplace.cpp index e66f543266..a4b6a100b0 100644 --- a/apps/openmw/mwgui/cursorreplace.cpp +++ b/apps/openmw/mwgui/cursorreplace.cpp @@ -16,4 +16,5 @@ CursorReplace::CursorReplace() OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45); OEngine::Render::Atlas::createFromFile("atlas1.cfg", "mwgui1", "textures\\"); + OEngine::Render::Atlas::createFromFile("mainmenu.cfg", "mwgui2", "textures\\"); } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 760c89f496..4342b1130a 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -9,10 +9,11 @@ #include #include "../mwbase/environment.hpp" -#include "../mwdialogue/dialoguemanager.hpp" +#include "../mwbase/dialoguemanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "dialogue_history.hpp" -#include "window_manager.hpp" #include "widgets.hpp" #include "list.hpp" #include "tradewindow.hpp" @@ -41,7 +42,7 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su } -DialogueWindow::DialogueWindow(WindowManager& parWindowManager) +DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_dialogue_window.layout", parWindowManager) , mEnabled(true) , mShowTrade(false) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index e2824bead0..e7f2b076cd 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -29,7 +29,7 @@ namespace MWGui class DialogueWindow: public WindowBase, public ReferenceInterface { public: - DialogueWindow(WindowManager& parWindowManager); + DialogueWindow(MWBase::WindowManager& parWindowManager); // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/dialogue_history.cpp b/apps/openmw/mwgui/dialogue_history.cpp index 009f42044d..f72f199ea3 100644 --- a/apps/openmw/mwgui/dialogue_history.cpp +++ b/apps/openmw/mwgui/dialogue_history.cpp @@ -1,5 +1,7 @@ #include "dialogue_history.hpp" -#include "window_manager.hpp" + +#include "../mwbase/windowmanager.hpp" + #include "widgets.hpp" #include "components/esm_store/store.hpp" @@ -71,4 +73,3 @@ void DialogueHistory::addDialogText(const UString& parText) addText(parText); addText("\n"); } - diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index d2eef26ac7..b148335537 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -8,16 +8,15 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" -#include "../mwsound/soundmanager.hpp" - #include "../mwgui/widgets.hpp" #include "inventorywindow.hpp" -#include "window_manager.hpp" #include "container.hpp" #include "console.hpp" @@ -25,9 +24,9 @@ using namespace MWGui; HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) : Layout("openmw_hud.layout") - , health(NULL) - , magicka(NULL) - , stamina(NULL) + , mHealth(NULL) + , mMagicka(NULL) + , mStamina(NULL) , mWeapImage(NULL) , mSpellImage(NULL) , mWeapStatus(NULL) @@ -37,10 +36,10 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mMinimap(NULL) , mCompass(NULL) , mCrosshair(NULL) - , fpsbox(NULL) - , fpscounter(NULL) - , trianglecounter(NULL) - , batchcounter(NULL) + , mFpsBox(NULL) + , mFpsCounter(NULL) + , mTriangleCounter(NULL) + , mBatchCounter(NULL) , mHealthManaStaminaBaseLeft(0) , mWeapBoxBaseLeft(0) , mSpellBoxBaseLeft(0) @@ -58,10 +57,9 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) // Energy bars getWidget(mHealthFrame, "HealthFrame"); - getWidget(health, "Health"); - getWidget(magicka, "Magicka"); - getWidget(stamina, "Stamina"); - + getWidget(mHealth, "Health"); + getWidget(mMagicka, "Magicka"); + getWidget(mStamina, "Stamina"); mHealthManaStaminaBaseLeft = mHealthFrame->getLeft(); MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame; @@ -94,9 +92,10 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(mMinimapBox, "MiniMapBox"); mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight(); - mMinimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(mMinimap, "MiniMap"); getWidget(mCompass, "Compass"); + getWidget(mMinimapButton, "MiniMapButton"); + mMinimapButton->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(mCellNameBox, "CellName"); getWidget(mWeaponSpellBox, "WeaponSpellName"); @@ -105,8 +104,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setFpsLevel(fpsLevel); - getWidget(trianglecounter, "TriangleCounter"); - getWidget(batchcounter, "BatchCounter"); + getWidget(mTriangleCounter, "TriangleCounter"); + getWidget(mBatchCounter, "BatchCounter"); setEffect("icons\\s\\tx_s_chameleon.dds"); @@ -119,7 +118,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) void HUD::setFpsLevel(int level) { - fpscounter = 0; + mFpsCounter = 0; MyGUI::Widget* fps; getWidget(fps, "FPSBoxAdv"); @@ -129,32 +128,32 @@ void HUD::setFpsLevel(int level) if (level == 2) { - getWidget(fpsbox, "FPSBoxAdv"); - fpsbox->setVisible(true); - getWidget(fpscounter, "FPSCounterAdv"); + getWidget(mFpsBox, "FPSBoxAdv"); + mFpsBox->setVisible(true); + getWidget(mFpsCounter, "FPSCounterAdv"); } else if (level == 1) { - getWidget(fpsbox, "FPSBox"); - fpsbox->setVisible(true); - getWidget(fpscounter, "FPSCounter"); + getWidget(mFpsBox, "FPSBox"); + mFpsBox->setVisible(true); + getWidget(mFpsCounter, "FPSCounter"); } } void HUD::setFPS(float fps) { - if (fpscounter) - fpscounter->setCaption(boost::lexical_cast((int)fps)); + if (mFpsCounter) + mFpsCounter->setCaption(boost::lexical_cast((int)fps)); } void HUD::setTriangleCount(unsigned int count) { - trianglecounter->setCaption(boost::lexical_cast(count)); + mTriangleCounter->setCaption(boost::lexical_cast(count)); } void HUD::setBatchCount(unsigned int count) { - batchcounter->setCaption(boost::lexical_cast(count)); + mBatchCounter->setCaption(boost::lexical_cast(count)); } void HUD::setEffect(const char *img) @@ -177,20 +176,20 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& v switch (i) { case 0: - health->setProgressRange (value.getModified()); - health->setProgressPosition (value.getCurrent()); + mHealth->setProgressRange (value.getModified()); + mHealth->setProgressPosition (value.getCurrent()); getWidget(w, "HealthFrame"); w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); break; case 1: - magicka->setProgressRange (value.getModified()); - magicka->setProgressPosition (value.getCurrent()); + mMagicka->setProgressRange (value.getModified()); + mMagicka->setProgressPosition (value.getCurrent()); getWidget(w, "MagickaFrame"); w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); break; case 2: - stamina->setProgressRange (value.getModified()); - stamina->setProgressPosition (value.getCurrent()); + mStamina->setProgressRange (value.getModified()); + mStamina->setProgressPosition (value.getCurrent()); getWidget(w, "FatigueFrame"); w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); break; @@ -198,46 +197,11 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& v } } -void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible) -{ - int weapDx = 0, spellDx = 0; - if (!hmsVisible) - spellDx = weapDx = mWeapBoxBaseLeft - mHealthManaStaminaBaseLeft; - - if (!weapVisible) - spellDx += mSpellBoxBaseLeft - mWeapBoxBaseLeft; - - mWeaponVisible = weapVisible; - mSpellVisible = spellVisible; - if (!mWeaponVisible && !mSpellVisible) - mWeaponSpellBox->setVisible(false); - - health->setVisible(hmsVisible); - stamina->setVisible(hmsVisible); - magicka->setVisible(hmsVisible); - mWeapBox->setPosition(mWeapBoxBaseLeft - weapDx, mWeapBox->getTop()); - mWeapBox->setVisible(weapVisible); - mSpellBox->setPosition(mSpellBoxBaseLeft - spellDx, mSpellBox->getTop()); - mSpellBox->setVisible(spellVisible); -} - -void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible) -{ - const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); - - // effect box can have variable width -> variable left coordinate - int effectsDx = 0; - if (!minimapBoxVisible) - effectsDx = (viewSize.width - mMinimapBoxBaseRight) - (viewSize.width - mEffectBoxBaseRight); - - mMapVisible = minimapBoxVisible; - mMinimapBox->setVisible(minimapBoxVisible); - mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop()); - mEffectBox->setVisible(effectBoxVisible); -} - void HUD::onWorldClicked(MyGUI::Widget* _sender) { + if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ()) + return; + if (mDragAndDrop->mIsOnDragAndDrop) { // drop item into the gameworld @@ -518,3 +482,68 @@ void HUD::unsetSelectedWeapon() mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); mWeapBox->clearUserStrings(); } + +void HUD::setCrosshairVisible(bool visible) +{ + mCrosshair->setVisible (visible); +} + +void HUD::setHmsVisible(bool visible) +{ + mHealth->setVisible(visible); + mMagicka->setVisible(visible); + mStamina->setVisible(visible); + updatePositions(); +} + +void HUD::setWeapVisible(bool visible) +{ + mWeapBox->setVisible(visible); + updatePositions(); +} + +void HUD::setSpellVisible(bool visible) +{ + mSpellBox->setVisible(visible); + updatePositions(); +} + +void HUD::setEffectVisible(bool visible) +{ + mEffectBox->setVisible (visible); + updatePositions(); +} + +void HUD::setMinimapVisible(bool visible) +{ + mMinimapBox->setVisible (visible); + updatePositions(); +} + +void HUD::updatePositions() +{ + int weapDx = 0, spellDx = 0; + if (!mHealth->getVisible()) + spellDx = weapDx = mWeapBoxBaseLeft - mHealthManaStaminaBaseLeft; + + if (!mWeapBox->getVisible()) + spellDx += mSpellBoxBaseLeft - mWeapBoxBaseLeft; + + mWeaponVisible = mWeapBox->getVisible(); + mSpellVisible = mSpellBox->getVisible(); + if (!mWeaponVisible && !mSpellVisible) + mWeaponSpellBox->setVisible(false); + + mWeapBox->setPosition(mWeapBoxBaseLeft - weapDx, mWeapBox->getTop()); + mSpellBox->setPosition(mSpellBoxBaseLeft - spellDx, mSpellBox->getTop()); + + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // effect box can have variable width -> variable left coordinate + int effectsDx = 0; + if (!mMinimapBox->getVisible ()) + effectsDx = (viewSize.width - mMinimapBoxBaseRight) - (viewSize.width - mEffectBoxBaseRight); + + mMapVisible = mMinimapBox->getVisible (); + mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop()); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 485c788fc3..de4228e87c 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -18,8 +18,14 @@ namespace MWGui void setFPS(float fps); void setTriangleCount(unsigned int count); void setBatchCount(unsigned int count); - void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); - void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); + + void setHmsVisible(bool visible); + void setWeapVisible(bool visible); + void setSpellVisible(bool visible); + + void setEffectVisible(bool visible); + void setMinimapVisible(bool visible); + void setFpsLevel(const int level); void setSelectedSpell(const std::string& spellId, int successChancePercent); @@ -28,6 +34,8 @@ namespace MWGui void unsetSelectedSpell(); void unsetSelectedWeapon(); + void setCrosshairVisible(bool visible); + void onFrame(float dt); void onResChange(int width, int height); @@ -35,12 +43,14 @@ namespace MWGui bool getWorldMouseOver() { return mWorldMouseOver; } - MyGUI::ProgressPtr health, magicka, stamina; + private: + MyGUI::ProgressPtr mHealth, mMagicka, mStamina; MyGUI::Widget* mHealthFrame; MyGUI::Widget *mWeapBox, *mSpellBox; MyGUI::ImageBox *mWeapImage, *mSpellImage; MyGUI::ProgressPtr mWeapStatus, mSpellStatus; MyGUI::Widget *mEffectBox, *mMinimapBox; + MyGUI::Button* mMinimapButton; MyGUI::ImageBox* mEffect1; MyGUI::ScrollView* mMinimap; MyGUI::ImageBox* mCompass; @@ -48,12 +58,13 @@ namespace MWGui MyGUI::TextBox* mCellNameBox; MyGUI::TextBox* mWeaponSpellBox; - MyGUI::WidgetPtr fpsbox; - MyGUI::TextBox* fpscounter; - MyGUI::TextBox* trianglecounter; - MyGUI::TextBox* batchcounter; + MyGUI::Widget* mDummy; + + MyGUI::WidgetPtr mFpsBox; + MyGUI::TextBox* mFpsCounter; + MyGUI::TextBox* mTriangleCounter; + MyGUI::TextBox* mBatchCounter; - private: // bottom left elements int mHealthManaStaminaBaseLeft, mWeapBoxBaseLeft, mSpellBoxBaseLeft; // bottom right elements @@ -81,5 +92,7 @@ namespace MWGui void onWeaponClicked(MyGUI::Widget* _sender); void onMagicClicked(MyGUI::Widget* _sender); void onMapClicked(MyGUI::Widget* _sender); + + void updatePositions(); }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 926c351722..7b68f7b6d6 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -9,6 +9,8 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" @@ -17,11 +19,6 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/inventorystore.hpp" -#include "../mwsound/soundmanager.hpp" - -#include "../mwclass/container.hpp" - -#include "window_manager.hpp" #include "widgets.hpp" #include "bookwindow.hpp" #include "scrollwindow.hpp" @@ -43,7 +40,7 @@ namespace namespace MWGui { - InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) + InventoryWindow::InventoryWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) , WindowPinnableBase("openmw_inventory_window.layout", parWindowManager) , mTrading(false) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 82da3efea7..fbdb79977a 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -9,7 +9,7 @@ namespace MWGui class InventoryWindow : public ContainerBase, public WindowPinnableBase { public: - InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + InventoryWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop); virtual void open(); diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp new file mode 100644 index 0000000000..d93a621ac2 --- /dev/null +++ b/apps/openmw/mwgui/itemselection.cpp @@ -0,0 +1,45 @@ +#include "itemselection.hpp" + +namespace MWGui +{ + + ItemSelectionDialog::ItemSelectionDialog(const std::string &label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager) + : ContainerBase(NULL) + , WindowModal("openmw_itemselection_dialog.layout", parWindowManager) + { + mFilter = filter; + + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + + MyGUI::TextBox* l; + getWidget(l, "Label"); + l->setCaptionWithReplacing (label); + + MyGUI::Button* cancelButton; + getWidget(cancelButton, "CancelButton"); + cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemSelectionDialog::onCancelButtonClicked); + + int dx = (cancelButton->getTextSize().width + 24) - cancelButton->getWidth(); + cancelButton->setCoord(cancelButton->getLeft() - dx, + cancelButton->getTop(), + cancelButton->getTextSize ().width + 24, + cancelButton->getHeight()); + + center(); + } + + void ItemSelectionDialog::onSelectedItemImpl(MWWorld::Ptr item) + { + eventItemSelected(item); + } + + void ItemSelectionDialog::onCancelButtonClicked(MyGUI::Widget* sender) + { + eventDialogCanceled(); + } + +} diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp new file mode 100644 index 0000000000..cab125f1f8 --- /dev/null +++ b/apps/openmw/mwgui/itemselection.hpp @@ -0,0 +1,28 @@ +#include "container.hpp" + +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + + class ItemSelectionDialog : public ContainerBase, public WindowModal + { + public: + ItemSelectionDialog(const std::string& label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager); + + typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; + typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Item; + + EventHandle_Item eventItemSelected; + EventHandle_Void eventDialogCanceled; + + + private: + virtual void onReferenceUnavailable() { ; } + + virtual void onSelectedItemImpl(MWWorld::Ptr item); + + void onCancelButtonClicked(MyGUI::Widget* sender); + }; + +} diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 8b50c9ef1d..597c27c6df 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -2,12 +2,11 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/journal.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" -#include "../mwdialogue/journal.hpp" - -#include "../mwsound/soundmanager.hpp" - -#include "window_manager.hpp" +#include "../mwdialogue/journalentry.hpp" namespace { @@ -82,7 +81,7 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) } -MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) +MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_journal.layout", parWindowManager) , mLastPos(0) , mVisible(false) diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 0c85ebf081..a62e488030 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -10,13 +10,11 @@ namespace MWGui { - class WindowManager; - class JournalWindow : public WindowBase { public: - JournalWindow(WindowManager& parWindowManager); - void open(); + JournalWindow(MWBase::WindowManager& parWindowManager); + virtual void open(); virtual void setVisible(bool visible); // only used to play close sound diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp new file mode 100644 index 0000000000..e98b75e9be --- /dev/null +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -0,0 +1,84 @@ +#include "mainmenu.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + +namespace MWGui +{ + + MainMenu::MainMenu(int w, int h) + : OEngine::GUI::Layout("openmw_mainmenu.layout") + , mButtonBox(0) + { + onResChange(w,h); + } + + void MainMenu::onResChange(int w, int h) + { + setCoord(0,0,w,h); + + int height = 64 * 3; + + if (mButtonBox) + MyGUI::Gui::getInstance ().destroyWidget(mButtonBox); + + mButtonBox = mMainWidget->createWidget("", MyGUI::IntCoord(w/2 - 64, h/2 - height/2, 128, height), MyGUI::Align::Default); + int curH = 0; + + mReturn = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mReturn->setImageResource ("Menu_Return"); + mReturn->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::returnToGame); + curH += 64; + + + /* + mNewGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mNewGame->setImageResource ("Menu_NewGame"); + curH += 64; + + mLoadGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mLoadGame->setImageResource ("Menu_LoadGame"); + curH += 64; + + + mSaveGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mSaveGame->setImageResource ("Menu_SaveGame"); + curH += 64; + */ + + mOptions = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mOptions->setImageResource ("Menu_Options"); + mOptions->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::showOptions); + curH += 64; + + /* + mCredits = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mCredits->setImageResource ("Menu_Credits"); + curH += 64; + */ + + mExitGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); + mExitGame->setImageResource ("Menu_ExitGame"); + mExitGame->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::exitGame); + curH += 64; + } + + void MainMenu::returnToGame(MyGUI::Widget* sender) + { + MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); + } + + void MainMenu::showOptions(MyGUI::Widget* sender) + { + MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); + } + + void MainMenu::exitGame(MyGUI::Widget* sender) + { + Ogre::Root::getSingleton ().queueEndRendering (); + } + +} diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index 06c59396fc..fd583d1876 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -6,11 +6,24 @@ namespace MWGui class MainMenu : public OEngine::GUI::Layout { public: - MainMenu(int w, int h) - : Layout("openmw_mainmenu.layout") - { - setCoord(0,0,w,h); - } + MainMenu(int w, int h); + + void onResChange(int w, int h); + + private: + MyGUI::Button* mReturn; + MyGUI::Button* mNewGame; + MyGUI::Button* mLoadGame; + MyGUI::Button* mSaveGame; + MyGUI::Button* mOptions; + MyGUI::Button* mCredits; + MyGUI::Button* mExitGame; + + MyGUI::Widget* mButtonBox; + + void returnToGame(MyGUI::Widget* sender); + void showOptions(MyGUI::Widget* sender); + void exitGame(MyGUI::Widget* sender); }; } diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 4ebeb38742..0d6300baad 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -1,8 +1,13 @@ #include "map_window.hpp" -#include "window_manager.hpp" #include +#include + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" + using namespace MWGui; LocalMapBase::LocalMapBase() @@ -88,13 +93,34 @@ void LocalMapBase::applyFogOfWar() } } +void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2) +{ + applyFogOfWar (); +} + +void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2) +{ + applyFogOfWar (); +} + void LocalMapBase::setActiveCell(const int x, const int y, bool interior) { if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell + + // clear all previous markers + for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i) + { + if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker") + { + MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i)); + } + } + for (int mx=0; mx<3; ++mx) { for (int my=0; my<3; ++my) { + // map std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" + boost::lexical_cast(y + (interior ? (my-1) : -1*(my-1))); @@ -107,12 +133,78 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior) box->setImageTexture(image); else box->setImageTexture("black.png"); + + + // door markers + + // interior map only consists of one cell, so handle the markers only once + if (interior && (mx != 2 || my != 2)) + continue; + + MWWorld::CellStore* cell; + if (interior) + cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix); + else + cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1)); + + std::vector doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell); + + for (std::vector::iterator it = doors.begin(); it != doors.end(); ++it) + { + MWBase::World::DoorMarker marker = *it; + + // convert world coordinates to normalized cell coordinates + MyGUI::IntCoord widgetCoord; + float nX,nY; + int cellDx, cellDy; + if (!interior) + { + const int cellSize = 8192; + + nX = (marker.x - cellSize * (x+mx-1)) / cellSize; + nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize; + + widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8); + } + else + { + Ogre::Vector2 position (marker.x, -marker.y); + MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy); + + widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8); + } + + static int counter = 0; + ++counter; + MyGUI::Button* markerWidget = mLocalMap->createWidget("ButtonImage", + widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(counter)); + markerWidget->setImageResource("DoorMarker"); + markerWidget->setUserString("ToolTipType", "Layout"); + markerWidget->setUserString("ToolTipLayout", "TextToolTip"); + markerWidget->setUserString("Caption_Text", marker.name); + markerWidget->setUserString("IsMarker", "true"); + markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused); + markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused); + + MarkerPosition markerPos; + markerPos.interior = interior; + markerPos.cellX = interior ? cellDx : x + mx - 1; + markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1); + markerPos.nX = nX; + markerPos.nY = nY; + + markerWidget->setUserData(markerPos); + } + + } } mInterior = interior; mCurX = x; mCurY = y; mChanged = false; + + // fog of war applyFogOfWar(); // set the compass texture again, because MyGUI determines sorting of ImageBox widgets @@ -154,7 +246,7 @@ void LocalMapBase::setPlayerDir(const float x, const float y) // ------------------------------------------------------------------------------------------ -MapWindow::MapWindow(WindowManager& parWindowManager) : +MapWindow::MapWindow(MWBase::WindowManager& parWindowManager) : MWGui::WindowPinnableBase("openmw_map_window.layout", parWindowManager), mGlobal(false) { diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp index 8d3392b827..1203233bf9 100644 --- a/apps/openmw/mwgui/map_window.hpp +++ b/apps/openmw/mwgui/map_window.hpp @@ -18,6 +18,15 @@ namespace MWGui void toggleFogOfWar(); + struct MarkerPosition + { + bool interior; + int cellX; + int cellY; + float nX; + float nY; + }; + protected: int mCurX, mCurY; bool mInterior; @@ -32,6 +41,9 @@ namespace MWGui void applyFogOfWar(); + void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2); + void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2); + OEngine::GUI::Layout* mLayout; bool mMapDragAndDrop; @@ -45,11 +57,11 @@ namespace MWGui class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase { public: - MapWindow(WindowManager& parWindowManager); + MapWindow(MWBase::WindowManager& parWindowManager); virtual ~MapWindow(){} void setCellName(const std::string& cellName); - + private: void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 2b00ca05ce..b660af7dd4 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -2,7 +2,7 @@ using namespace MWGui; -MessageBoxManager::MessageBoxManager (WindowManager *windowManager) +MessageBoxManager::MessageBoxManager (MWBase::WindowManager *windowManager) { mWindowManager = windowManager; // defines diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 75393ec947..5e4c468d56 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -5,13 +5,13 @@ #include #include "window_base.hpp" -#include "window_manager.hpp" + +#include "../mwbase/windowmanager.hpp" #undef MessageBox namespace MWGui { - class InteractiveMessageBox; class MessageBoxManager; class MessageBox; @@ -25,27 +25,27 @@ namespace MWGui class MessageBoxManager { public: - MessageBoxManager (WindowManager* windowManager); + MessageBoxManager (MWBase::WindowManager* windowManager); void onFrame (float frameDuration); void createMessageBox (const std::string& message); bool createInteractiveMessageBox (const std::string& message, const std::vector& buttons); bool isInteractiveMessageBox (); - + void removeMessageBox (float time, MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox); void setMessageBoxSpeed (int speed); - + int readPressedButton (); - - WindowManager *mWindowManager; - + + MWBase::WindowManager *mWindowManager; + private: std::vector mMessageBoxes; InteractiveMessageBox* mInterMessageBoxe; std::vector mTimers; float mMessageBoxSpeed; }; - + class MessageBox : public OEngine::GUI::Layout { public: @@ -53,9 +53,9 @@ namespace MWGui void setMessage (const std::string& message); int getHeight (); void update (int height); - + bool mMarkedToDelete; - + protected: MessageBoxManager& mMessageBoxManager; int mHeight; @@ -65,16 +65,16 @@ namespace MWGui int mBottomPadding; int mNextBoxPadding; }; - + class InteractiveMessageBox : public OEngine::GUI::Layout { public: InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons); void mousePressed (MyGUI::Widget* _widget); int readPressedButton (); - + bool mMarkedToDelete; - + private: MessageBoxManager& mMessageBoxManager; MyGUI::EditPtr mMessageWidget; diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 8b502ce7c9..2d6f69871b 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -32,7 +32,9 @@ namespace MWGui GM_Review, // interactive MessageBox - GM_InterMessageBox + GM_InterMessageBox, + + GM_QuickKeysMenu }; // Windows shown in inventory mode diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp new file mode 100644 index 0000000000..5b7115dbea --- /dev/null +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -0,0 +1,630 @@ +#include "quickkeysmenu.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwworld/actionequip.hpp" +#include "../mwmechanics/spells.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellsuccess.hpp" +#include "../mwgui/inventorywindow.hpp" +#include "../mwgui/bookwindow.hpp" +#include "../mwgui/scrollwindow.hpp" + +#include "windowmanagerimp.hpp" +#include "itemselection.hpp" + + +namespace +{ + bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right) + { + int cmp = MWWorld::Class::get(left).getName(left).compare( + MWWorld::Class::get(right).getName(right)); + return cmp < 0; + } + + bool sortSpells(const std::string& left, const std::string& right) + { + const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left); + const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right); + + int cmp = a->name.compare(b->name); + return cmp < 0; + } +} + +namespace MWGui +{ + + QuickKeysMenu::QuickKeysMenu(MWBase::WindowManager& parWindowManager) + : WindowBase("openmw_quickkeys_menu.layout", parWindowManager) + , mAssignDialog(0) + , mItemSelectionDialog(0) + , mMagicSelectionDialog(0) + { + getWidget(mOkButton, "OKButton"); + getWidget(mInstructionLabel, "InstructionLabel"); + + mMainWidget->setSize(mMainWidget->getWidth(), + mMainWidget->getHeight() + (mInstructionLabel->getTextSize().height - mInstructionLabel->getHeight())); + + int okButtonWidth = mOkButton->getTextSize ().width + 24; + mOkButton->setCoord(mOkButton->getLeft() - (okButtonWidth - mOkButton->getWidth()), + mOkButton->getTop(), + okButtonWidth, + mOkButton->getHeight()); + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onOkButtonClicked); + + center(); + + + for (int i = 0; i < 10; ++i) + { + MyGUI::Button* button; + getWidget(button, "QuickKey" + boost::lexical_cast(i+1)); + + button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); + + unassign(button, i); + + mQuickKeyButtons.push_back(button); + + } + } + + QuickKeysMenu::~QuickKeysMenu() + { + delete mAssignDialog; + delete mItemSelectionDialog; + delete mMagicSelectionDialog; + } + + void QuickKeysMenu::unassign(MyGUI::Widget* key, int index) + { + while (key->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (key->getChildAt(0)); + + key->setUserData(Type_Unassigned); + + MyGUI::TextBox* textBox = key->createWidgetReal("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default); + textBox->setTextAlign (MyGUI::Align::Center); + textBox->setCaption (boost::lexical_cast(index+1)); + textBox->setNeedMouseFocus (false); + } + + void QuickKeysMenu::onQuickKeyButtonClicked(MyGUI::Widget* sender) + { + int index = -1; + for (int i = 0; i < 10; ++i) + { + if (sender == mQuickKeyButtons[i] || sender->getParent () == mQuickKeyButtons[i]) + { + index = i; + break; + } + } + assert(index != -1); + mSelectedIndex = index; + + { + // open assign dialog + if (!mAssignDialog) + mAssignDialog = new QuickKeysMenuAssign(mWindowManager, this); + mAssignDialog->setVisible (true); + } + } + + void QuickKeysMenu::onOkButtonClicked (MyGUI::Widget *sender) + { + mWindowManager.removeGuiMode(GM_QuickKeysMenu); + } + + + void QuickKeysMenu::onItemButtonClicked(MyGUI::Widget* sender) + { + if (!mItemSelectionDialog ) + { + mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All, mWindowManager); + mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem); + mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItemCancel); + } + mItemSelectionDialog->setVisible(true); + mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + mItemSelectionDialog->drawItems (); + + mAssignDialog->setVisible (false); + } + + void QuickKeysMenu::onMagicButtonClicked(MyGUI::Widget* sender) + { + if (!mMagicSelectionDialog ) + { + mMagicSelectionDialog = new MagicSelectionDialog(mWindowManager, this); + } + mMagicSelectionDialog->setVisible(true); + + mAssignDialog->setVisible (false); + } + + void QuickKeysMenu::onUnassignButtonClicked(MyGUI::Widget* sender) + { + unassign(mQuickKeyButtons[mSelectedIndex], mSelectedIndex); + mAssignDialog->setVisible (false); + } + + void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender) + { + mAssignDialog->setVisible (false); + } + + void QuickKeysMenu::onAssignItem(MWWorld::Ptr item) + { + MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + + button->setUserData(Type_Item); + + MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); + std::string backgroundTex = "textures\\menu_icon_barter.dds"; + frame->setImageTexture (backgroundTex); + frame->setImageCoord (MyGUI::IntCoord(4, 4, 40, 40)); + frame->setUserString ("ToolTipType", "ItemPtr"); + frame->setUserData(item); + frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); + + + MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(item).getInventoryIcon(item); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture (path); + image->setNeedMouseFocus (false); + + mItemSelectionDialog->setVisible(false); + } + + void QuickKeysMenu::onAssignItemCancel() + { + mItemSelectionDialog->setVisible(false); + } + + void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item) + { + MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + + button->setUserData(Type_MagicItem); + + MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); + std::string backgroundTex = "textures\\menu_icon_select_magic_magic.dds"; + frame->setImageTexture (backgroundTex); + frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40)); + frame->setUserString ("ToolTipType", "ItemPtr"); + frame->setUserData(item); + frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); + + MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(item).getInventoryIcon(item); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture (path); + image->setNeedMouseFocus (false); + + mMagicSelectionDialog->setVisible(false); + } + + void QuickKeysMenu::onAssignMagic (const std::string& spellId) + { + MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + + button->setUserData(Type_Magic); + + MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); + std::string backgroundTex = "textures\\menu_icon_select_magic.dds"; + frame->setImageTexture (backgroundTex); + frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40)); + frame->setUserString ("ToolTipType", "Spell"); + frame->setUserString ("Spell", spellId); + frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); + + MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + + // use the icon of the first effect + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->effects.list.front().effectID); + std::string path = effect->icon; + int slashPos = path.find("\\"); + path.insert(slashPos+1, "b_"); + path = std::string("icons\\") + path; + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + + image->setImageTexture (path); + image->setNeedMouseFocus (false); + + mMagicSelectionDialog->setVisible(false); + } + + void QuickKeysMenu::onAssignMagicCancel () + { + mMagicSelectionDialog->setVisible(false); + } + + void QuickKeysMenu::activateQuickKey(int index) + { + MyGUI::Button* button = mQuickKeyButtons[index-1]; + + QuickKeyType type = *button->getUserData(); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.getSpells(); + + if (type == Type_Magic) + { + std::string spellId = button->getChildAt(0)->getUserString("Spell"); + spells.setSelectedSpell(spellId); + store.setSelectedEnchantItem(store.end()); + mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); + } + else if (type == Type_Item) + { + MWWorld::Ptr item = *button->getChildAt (0)->getUserData(); + + // make sure the item is available + if (item.getRefData ().getCount() == 0) + { + MWBase::Environment::get().getWindowManager ()->messageBox ( + "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item), std::vector()); + return; + } + + boost::shared_ptr action = MWWorld::Class::get(item).use(item); + + action->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + + // this is necessary for books/scrolls: if they are already in the player's inventory, + // the "Take" button should not be visible. + // NOTE: the take button is "reset" when the window opens, so we can safely do the following + // without screwing up future book windows + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); + + // since we changed equipping status, update the inventory window + mWindowManager.getInventoryWindow()->drawItems(); + } + else if (type == Type_MagicItem) + { + MWWorld::Ptr item = *button->getChildAt (0)->getUserData(); + + // make sure the item is available + if (item.getRefData ().getCount() == 0) + { + MWBase::Environment::get().getWindowManager ()->messageBox ( + "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item), std::vector()); + return; + } + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = store.begin(); + for (; it != store.end(); ++it) + { + if (*it == item) + { + break; + } + } + assert(it != store.end()); + + // equip, if it can be equipped + if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) + { + // Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping + + MWWorld::ActionEquip action(item); + action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); + + // since we changed equipping status, update the inventory window + mWindowManager.getInventoryWindow()->drawItems(); + } + + store.setSelectedEnchantItem(it); + spells.setSelectedSpell(""); + mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge % + } + } + + // --------------------------------------------------------------------------------------------------------- + + QuickKeysMenuAssign::QuickKeysMenuAssign (MWBase::WindowManager &parWindowManager, QuickKeysMenu* parent) + : WindowModal("openmw_quickkeys_menu_assign.layout", parWindowManager) + , mParent(parent) + { + getWidget(mLabel, "Label"); + getWidget(mItemButton, "ItemButton"); + getWidget(mMagicButton, "MagicButton"); + getWidget(mUnassignButton, "UnassignButton"); + getWidget(mCancelButton, "CancelButton"); + + mItemButton->eventMouseButtonClick += MyGUI::newDelegate(mParent, &QuickKeysMenu::onItemButtonClicked); + mMagicButton->eventMouseButtonClick += MyGUI::newDelegate(mParent, &QuickKeysMenu::onMagicButtonClicked); + mUnassignButton->eventMouseButtonClick += MyGUI::newDelegate(mParent, &QuickKeysMenu::onUnassignButtonClicked); + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(mParent, &QuickKeysMenu::onCancelButtonClicked); + + + int maxWidth = mItemButton->getTextSize ().width + 24; + maxWidth = std::max(maxWidth, mMagicButton->getTextSize ().width + 24); + maxWidth = std::max(maxWidth, mUnassignButton->getTextSize ().width + 24); + maxWidth = std::max(maxWidth, mCancelButton->getTextSize ().width + 24); + + mMainWidget->setSize(maxWidth + 24, mMainWidget->getHeight()); + mLabel->setSize(maxWidth, mLabel->getHeight()); + + mItemButton->setCoord((maxWidth - mItemButton->getTextSize().width-24)/2 + 8, + mItemButton->getTop(), + mItemButton->getTextSize().width + 24, + mItemButton->getHeight()); + mMagicButton->setCoord((maxWidth - mMagicButton->getTextSize().width-24)/2 + 8, + mMagicButton->getTop(), + mMagicButton->getTextSize().width + 24, + mMagicButton->getHeight()); + mUnassignButton->setCoord((maxWidth - mUnassignButton->getTextSize().width-24)/2 + 8, + mUnassignButton->getTop(), + mUnassignButton->getTextSize().width + 24, + mUnassignButton->getHeight()); + mCancelButton->setCoord((maxWidth - mCancelButton->getTextSize().width-24)/2 + 8, + mCancelButton->getTop(), + mCancelButton->getTextSize().width + 24, + mCancelButton->getHeight()); + + center(); + } + + + // --------------------------------------------------------------------------------------------------------- + + MagicSelectionDialog::MagicSelectionDialog(MWBase::WindowManager &parWindowManager, QuickKeysMenu* parent) + : WindowModal("openmw_magicselection_dialog.layout", parWindowManager) + , mParent(parent) + , mWidth(0) + , mHeight(0) + { + getWidget(mCancelButton, "CancelButton"); + getWidget(mMagicList, "MagicList"); + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MagicSelectionDialog::onCancelButtonClicked); + + int dx = (mCancelButton->getTextSize().width + 24) - mCancelButton->getWidth(); + mCancelButton->setCoord(mCancelButton->getLeft() - dx, + mCancelButton->getTop(), + mCancelButton->getTextSize ().width + 24, + mCancelButton->getHeight()); + + center(); + } + + void MagicSelectionDialog::onCancelButtonClicked (MyGUI::Widget *sender) + { + mParent->onAssignMagicCancel (); + } + + void MagicSelectionDialog::open () + { + WindowModal::open(); + + while (mMagicList->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (mMagicList->getChildAt (0)); + + mHeight = 0; + + const int spellHeight = 18; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.getSpells(); + + /// \todo lots of copy&pasted code from SpellWindow + + // retrieve powers & spells, sort by name + std::vector spellList; + + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) + { + spellList.push_back(*it); + } + + std::vector powers; + std::vector::iterator it = spellList.begin(); + while (it != spellList.end()) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + if (spell->data.type == ESM::Spell::ST_Power) + { + powers.push_back(*it); + it = spellList.erase(it); + } + else if (spell->data.type == ESM::Spell::ST_Ability + || spell->data.type == ESM::Spell::ST_Blight + || spell->data.type == ESM::Spell::ST_Curse + || spell->data.type == ESM::Spell::ST_Disease) + { + it = spellList.erase(it); + } + else + ++it; + } + std::sort(powers.begin(), powers.end(), sortSpells); + std::sort(spellList.begin(), spellList.end(), sortSpells); + + // retrieve usable magic items & sort + std::vector items; + for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) + { + std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it); + if (enchantId != "") + { + // only add items with "Cast once" or "Cast on use" + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId); + int type = enchant->data.type; + if (type != ESM::Enchantment::CastOnce + && type != ESM::Enchantment::WhenUsed) + continue; + + items.push_back(*it); + } + } + std::sort(items.begin(), items.end(), sortItems); + + + int height = estimateHeight(items.size() + powers.size() + spellList.size()); + bool scrollVisible = height > mMagicList->getHeight(); + mWidth = mMagicList->getWidth() - scrollVisible * 18; + + + // powers + addGroup("#{sPowers}", ""); + + for (std::vector::const_iterator it = powers.begin(); it != powers.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mMagicList->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &MagicSelectionDialog::onMouseWheel); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &MagicSelectionDialog::onSpellSelected); + + mHeight += spellHeight; + } + + // other spells + addGroup("#{sSpells}", ""); + for (std::vector::const_iterator it = spellList.begin(); it != spellList.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mMagicList->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &MagicSelectionDialog::onMouseWheel); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &MagicSelectionDialog::onSpellSelected); + + mHeight += spellHeight; + } + + + // enchanted items + addGroup("#{sMagicItem}", ""); + + for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + MWWorld::Ptr item = *it; + + // check if the item is currently equipped (will display in a different color) + bool equipped = false; + for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) + { + if (store.getSlot(i) != store.end() && *store.getSlot(i) == item) + { + equipped = true; + break; + } + } + + MyGUI::Button* t = mMagicList->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(MWWorld::Class::get(item).getName(item)); + t->setTextAlign(MyGUI::Align::Left); + t->setUserData(item); + t->setUserString("ToolTipType", "ItemPtr"); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &MagicSelectionDialog::onEnchantedItemSelected); + t->eventMouseWheel += MyGUI::newDelegate(this, &MagicSelectionDialog::onMouseWheel); + + mHeight += spellHeight; + } + + + mMagicList->setCanvasSize (mWidth, std::max(mMagicList->getHeight(), mHeight)); + + } + + void MagicSelectionDialog::addGroup(const std::string &label, const std::string& label2) + { + if (mMagicList->getChildCount() > 0) + { + MyGUI::ImageBox* separator = mMagicList->createWidget("MW_HLine", + MyGUI::IntCoord(4, mHeight, mWidth-8, 18), + MyGUI::Align::Left | MyGUI::Align::Top); + separator->setNeedMouseFocus(false); + mHeight += 18; + } + + MyGUI::TextBox* groupWidget = mMagicList->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth, 24), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + groupWidget->setCaptionWithReplacing(label); + groupWidget->setTextAlign(MyGUI::Align::Left); + groupWidget->setNeedMouseFocus(false); + + if (label2 != "") + { + MyGUI::TextBox* groupWidget2 = mMagicList->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth-4, 24), + MyGUI::Align::Left | MyGUI::Align::Top); + groupWidget2->setCaptionWithReplacing(label2); + groupWidget2->setTextAlign(MyGUI::Align::Right); + groupWidget2->setNeedMouseFocus(false); + } + + mHeight += 24; + } + + + void MagicSelectionDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel) + { + if (mMagicList->getViewOffset().top + _rel*0.3 > 0) + mMagicList->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mMagicList->setViewOffset(MyGUI::IntPoint(0, mMagicList->getViewOffset().top + _rel*0.3)); + } + + void MagicSelectionDialog::onEnchantedItemSelected(MyGUI::Widget* _sender) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Ptr item = *_sender->getUserData(); + + mParent->onAssignMagicItem (item); + } + + void MagicSelectionDialog::onSpellSelected(MyGUI::Widget* _sender) + { + mParent->onAssignMagic (_sender->getUserString("Spell")); + } + + int MagicSelectionDialog::estimateHeight(int numSpells) const + { + int height = 0; + height += 24 * 3 + 18 * 2; // group headings + height += numSpells * 18; + return height; + } + +} diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp new file mode 100644 index 0000000000..345ffa0c87 --- /dev/null +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -0,0 +1,107 @@ +#ifndef MWGUI_QUICKKEYS_H +#define MWGUI_QUICKKEYS_H + + +#include "../mwworld/ptr.hpp" + +#include "window_base.hpp" + +namespace MWGui +{ + + class QuickKeysMenuAssign; + class ItemSelectionDialog; + class MagicSelectionDialog; + + class QuickKeysMenu : public WindowBase + { + public: + QuickKeysMenu(MWBase::WindowManager& parWindowManager); + ~QuickKeysMenu(); + + + void onItemButtonClicked(MyGUI::Widget* sender); + void onMagicButtonClicked(MyGUI::Widget* sender); + void onUnassignButtonClicked(MyGUI::Widget* sender); + void onCancelButtonClicked(MyGUI::Widget* sender); + + void onAssignItem (MWWorld::Ptr item); + void onAssignItemCancel (); + void onAssignMagicItem (MWWorld::Ptr item); + void onAssignMagic (const std::string& spellId); + void onAssignMagicCancel (); + + void activateQuickKey(int index); + + enum QuickKeyType + { + Type_Item, + Type_Magic, + Type_MagicItem, + Type_Unassigned + }; + + + private: + MyGUI::EditBox* mInstructionLabel; + MyGUI::Button* mOkButton; + + std::vector mQuickKeyButtons; + + QuickKeysMenuAssign* mAssignDialog; + ItemSelectionDialog* mItemSelectionDialog; + MagicSelectionDialog* mMagicSelectionDialog; + + int mSelectedIndex; + + + void onQuickKeyButtonClicked(MyGUI::Widget* sender); + void onOkButtonClicked(MyGUI::Widget* sender); + + void unassign(MyGUI::Widget* key, int index); + }; + + class QuickKeysMenuAssign : public WindowModal + { + public: + QuickKeysMenuAssign(MWBase::WindowManager& parWindowManager, QuickKeysMenu* parent); + + private: + MyGUI::TextBox* mLabel; + MyGUI::Button* mItemButton; + MyGUI::Button* mMagicButton; + MyGUI::Button* mUnassignButton; + MyGUI::Button* mCancelButton; + + QuickKeysMenu* mParent; + }; + + class MagicSelectionDialog : public WindowModal + { + public: + MagicSelectionDialog(MWBase::WindowManager& parWindowManager, QuickKeysMenu* parent); + + virtual void open(); + + private: + MyGUI::Button* mCancelButton; + MyGUI::ScrollView* mMagicList; + + int mWidth; + int mHeight; + + QuickKeysMenu* mParent; + + void onCancelButtonClicked (MyGUI::Widget* sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onEnchantedItemSelected(MyGUI::Widget* _sender); + void onSpellSelected(MyGUI::Widget* _sender); + int estimateHeight(int numSpells) const; + + + void addGroup(const std::string& label, const std::string& label2); + }; +} + + +#endif diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index f90a9eddec..a597dcadb7 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -8,14 +8,17 @@ #include -#include "window_manager.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + #include "widgets.hpp" #include "tooltips.hpp" using namespace MWGui; using namespace Widgets; -RaceDialog::RaceDialog(WindowManager& parWindowManager) +RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_race.layout", parWindowManager) , mGenderIndex(0) , mFaceIndex(0) @@ -110,7 +113,6 @@ void RaceDialog::open() updateRaces(); updateSkills(); updateSpellPowers(); - setVisible(true); } @@ -209,7 +211,7 @@ void RaceDialog::updateRaces() { mRaceList->removeAllItems(); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); ESMS::RecListT::MapType::const_iterator it = store.races.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.races.list.end(); @@ -243,7 +245,7 @@ void RaceDialog::updateSkills() const int lineHeight = 18; MyGUI::IntCoord coord1(0, 0, mSkillList->getWidth(), 18); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.races.find(mCurrentRaceId); int count = sizeof(race->data.bonus)/sizeof(race->data.bonus[0]); // TODO: Find a portable macro for this ARRAYSIZE? for (int i = 0; i < count; ++i) @@ -281,7 +283,7 @@ void RaceDialog::updateSpellPowers() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, mSpellPowerList->getWidth(), 18); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.races.find(mCurrentRaceId); std::vector::const_iterator it = race->powers.list.begin(); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index b523b86902..2e9e09a3e4 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -24,7 +24,7 @@ namespace MWGui class RaceDialog : public WindowBase { public: - RaceDialog(WindowManager& parWindowManager); + RaceDialog(MWBase::WindowManager& parWindowManager); enum Gender { @@ -43,7 +43,7 @@ namespace MWGui // setHair() void setNextButtonShow(bool shown); - void open(); + virtual void open(); // Events typedef delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 7061f65c17..4a9cc778a6 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -7,7 +7,10 @@ #include -#include "window_manager.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + #include "widgets.hpp" #include "tooltips.hpp" @@ -19,7 +22,7 @@ using namespace Widgets; const int ReviewDialog::sLineHeight = 18; -ReviewDialog::ReviewDialog(WindowManager& parWindowManager) +ReviewDialog::ReviewDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_chargen_review.layout", parWindowManager) , mLastPos(0) { @@ -107,7 +110,6 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) void ReviewDialog::open() { updateSkillArea(); - setVisible(true); } void ReviewDialog::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -138,7 +140,7 @@ void ReviewDialog::setPlayerName(const std::string &name) void ReviewDialog::setRace(const std::string &raceId) { mRaceId = raceId; - const ESM::Race *race = mWindowManager.getStore().races.search(mRaceId); + const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().races.search(mRaceId); if (race) { ToolTips::createRaceToolTip(mRaceWidget, race); @@ -156,7 +158,7 @@ void ReviewDialog::setClass(const ESM::Class& class_) void ReviewDialog::setBirthSign(const std::string& signId) { mBirthSignId = signId; - const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(mBirthSignId); + const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.search(mBirthSignId); if (sign) { mBirthSignWidget->setCaption(sign->name); diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 27b1670333..f6d3732323 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -30,7 +30,7 @@ namespace MWGui }; typedef std::vector SkillList; - ReviewDialog(WindowManager& parWindowManager); + ReviewDialog(MWBase::WindowManager& parWindowManager); void setPlayerName(const std::string &name); void setRace(const std::string &raceId); @@ -46,7 +46,7 @@ namespace MWGui void configureSkills(const SkillList& major, const SkillList& minor); void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat& value); - void open(); + virtual void open(); // Events typedef delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 00e5a01dc1..ff83b0e3e4 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -2,17 +2,17 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" -#include "../mwinput/inputmanager.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" + #include "../mwworld/actiontake.hpp" #include "../mwworld/player.hpp" -#include "../mwsound/soundmanager.hpp" #include "formatting.hpp" -#include "window_manager.hpp" using namespace MWGui; -ScrollWindow::ScrollWindow (WindowManager& parWindowManager) : +ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_scroll.layout", parWindowManager) { getWidget(mTextView, "TextView"); @@ -62,7 +62,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack); MWWorld::ActionTake take(mScroll); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index d58596b4be..b8f52fb658 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -10,7 +10,7 @@ namespace MWGui class ScrollWindow : public WindowBase { public: - ScrollWindow (WindowManager& parWindowManager); + ScrollWindow (MWBase::WindowManager& parWindowManager); void open (MWWorld::Ptr scroll); void setTakeButtonShow(bool show); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 4488096fe9..2599ea0b26 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -12,14 +12,12 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/inputmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwrender/renderingmanager.hpp" -#include "../mwsound/soundmanager.hpp" - -#include "../mwinput/inputmanager.hpp" - -#include "window_manager.hpp" #include "confirmationdialog.hpp" namespace @@ -83,10 +81,12 @@ namespace namespace MWGui { - SettingsWindow::SettingsWindow(WindowManager& parWindowManager) : + SettingsWindow::SettingsWindow(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_settings_window.layout", parWindowManager) { getWidget(mOkButton, "OkButton"); + getWidget(mSubtitlesButton, "SubtitlesButton"); + getWidget(mCrosshairButton, "CrosshairButton"); getWidget(mResolutionList, "ResolutionList"); getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mToolTipDelaySlider, "ToolTipDelaySlider"); @@ -117,7 +117,15 @@ namespace MWGui getWidget(mMiscShadows, "MiscShadows"); getWidget(mShadowsDebug, "ShadowsDebug"); getWidget(mUnderwaterButton, "UnderwaterButton"); + getWidget(mControlsBox, "ControlsBox"); + getWidget(mResetControlsButton, "ResetControlsButton"); + getWidget(mInvertYButton, "InvertYButton"); + getWidget(mUISensitivitySlider, "UISensitivitySlider"); + getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); + mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mUnderwaterButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled); @@ -156,6 +164,9 @@ namespace MWGui mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(), okSize, mOkButton->getHeight()); + mResetControlsButton->setSize (mResetControlsButton->getTextSize ().width + 24, mResetControlsButton->getHeight()); + mResetControlsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindings); + // fill resolution list Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); Ogre::StringVector videoModes = rs->getConfigOptions()["Video Mode"].possibleValues; @@ -185,6 +196,9 @@ namespace MWGui int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); mToolTipDelaySlider->setScrollPosition(tooltip_delay); + mSubtitlesButton->setCaptionWithReplacing(Settings::Manager::getBool("subtitles", "GUI") ? "#{sOn}" : "#{sOff}"); + mCrosshairButton->setCaptionWithReplacing(Settings::Manager::getBool("crosshair", "HUD") ? "#{sOn}" : "#{sOff}"); + float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin); mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1)); MyGUI::TextBox* fovText; @@ -221,6 +235,16 @@ namespace MWGui mMiscShadows->setCaptionWithReplacing(Settings::Manager::getBool("misc shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); mShadowsDebug->setCaptionWithReplacing(Settings::Manager::getBool("debug", "Shadows") ? "#{sOn}" : "#{sOff}"); + float cameraSens = (Settings::Manager::getFloat("camera sensitivity", "Input")-0.2)/(5.0-0.2); + mCameraSensitivitySlider->setScrollPosition (cameraSens * (mCameraSensitivitySlider->getScrollRange()-1)); + float uiSens = (Settings::Manager::getFloat("ui sensitivity", "Input")-0.2)/(5.0-0.2); + mUISensitivitySlider->setScrollPosition (uiSens * (mUISensitivitySlider->getScrollRange()-1)); + mCameraSensitivitySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mUISensitivitySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + + + mInvertYButton->setCaptionWithReplacing(Settings::Manager::getBool("invert y axis", "Input") ? "#{sOn}" : "#{sOff}"); + std::string shaders; if (!Settings::Manager::getBool("shaders", "Objects")) shaders = "off"; @@ -264,6 +288,7 @@ namespace MWGui dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); dialog->eventCancelClicked.clear(); + dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionCancel); } void SettingsWindow::onResolutionAccept() @@ -383,6 +408,12 @@ namespace MWGui Settings::Manager::setBool("misc shadows", "Shadows", newState); else if (_sender == mShadowsDebug) Settings::Manager::setBool("debug", "Shadows", newState); + else if (_sender == mInvertYButton) + Settings::Manager::setBool("invert y axis", "Input", newState); + else if (_sender == mCrosshairButton) + Settings::Manager::setBool("crosshair", "HUD", newState); + else if (_sender == mSubtitlesButton) + Settings::Manager::setBool("subtitles", "GUI", newState); apply(); } @@ -500,6 +531,10 @@ namespace MWGui Settings::Manager::setFloat("footsteps volume", "Sound", val); else if (scroller == mMusicVolumeSlider) Settings::Manager::setFloat("music volume", "Sound", val); + else if (scroller == mUISensitivitySlider) + Settings::Manager::setFloat("ui sensitivity", "Input", (1-val) * 0.2 + val * 5.f); + else if (scroller == mCameraSensitivitySlider) + Settings::Manager::setFloat("camera sensitivity", "Input", (1-val) * 0.2 + val * 5.f); apply(); } @@ -512,4 +547,78 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); MWBase::Environment::get().getInputManager()->processChangedSettings(changed); } + + void SettingsWindow::updateControlsBox() + { + while (mControlsBox->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mControlsBox->getChildAt(0)); + + std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); + + const int h = 18; + const int w = mControlsBox->getWidth() - 28; + int curH = 0; + for (std::vector::const_iterator it = actions.begin(); it != actions.end(); ++it) + { + std::string desc = MWBase::Environment::get().getInputManager()->getActionDescription (*it); + if (desc == "") + continue; + + std::string binding = MWBase::Environment::get().getInputManager()->getActionBindingName (*it); + + MyGUI::TextBox* leftText = mControlsBox->createWidget("SandText", MyGUI::IntCoord(0,curH,w,h), MyGUI::Align::Default); + leftText->setCaptionWithReplacing(desc); + + MyGUI::Button* rightText = mControlsBox->createWidget("SandTextButton", MyGUI::IntCoord(0,curH,w,h), MyGUI::Align::Default); + rightText->setCaptionWithReplacing(binding); + rightText->setTextAlign (MyGUI::Align::Right); + rightText->setUserData(*it); // save the action id for callbacks + rightText->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onRebindAction); + rightText->eventMouseWheel += MyGUI::newDelegate(this, &SettingsWindow::onInputTabMouseWheel); + curH += h; + } + + mControlsBox->setCanvasSize (mControlsBox->getWidth(), std::max(curH, mControlsBox->getHeight())); + } + + void SettingsWindow::onRebindAction(MyGUI::Widget* _sender) + { + int actionId = *_sender->getUserData(); + + static_cast(_sender)->setCaptionWithReplacing("#{sNone}"); + + MWBase::Environment::get().getWindowManager ()->messageBox ("#{sControlsMenu3}", std::vector()); + MWBase::Environment::get().getWindowManager ()->disallowMouse(); + + MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId); + + } + + void SettingsWindow::onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel) + { + if (mControlsBox->getViewOffset().top + _rel*0.3 > 0) + mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mControlsBox->setViewOffset(MyGUI::IntPoint(0, mControlsBox->getViewOffset().top + _rel*0.3)); + } + + void SettingsWindow::onResetDefaultBindings(MyGUI::Widget* _sender) + { + ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + dialog->open("#{sNotifyMessage66}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindingsAccept); + dialog->eventCancelClicked.clear(); + } + + void SettingsWindow::onResetDefaultBindingsAccept() + { + MWBase::Environment::get().getInputManager ()->resetToDefaultBindings (); + updateControlsBox (); + } + + void SettingsWindow::open() + { + updateControlsBox (); + } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 63fbed46b6..d1f35ed710 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -13,7 +13,11 @@ namespace MWGui class SettingsWindow : public WindowBase { public: - SettingsWindow(WindowManager& parWindowManager); + SettingsWindow(MWBase::WindowManager& parWindowManager); + + virtual void open(); + + void updateControlsBox(); private: static int const sFovMin = 30; @@ -26,6 +30,8 @@ namespace MWGui MyGUI::ScrollBar* mMenuTransparencySlider; MyGUI::ScrollBar* mToolTipDelaySlider; + MyGUI::Button* mSubtitlesButton; + MyGUI::Button* mCrosshairButton; // graphics MyGUI::ListBox* mResolutionList; @@ -60,6 +66,13 @@ namespace MWGui MyGUI::ScrollBar* mFootstepsVolumeSlider; MyGUI::ScrollBar* mMusicVolumeSlider; + // controls + MyGUI::ScrollView* mControlsBox; + MyGUI::Button* mResetControlsButton; + MyGUI::Button* mInvertYButton; + MyGUI::ScrollBar* mUISensitivitySlider; + MyGUI::ScrollBar* mCameraSensitivitySlider; + void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); void onTextureFilteringToggled(MyGUI::Widget* _sender); @@ -72,9 +85,13 @@ namespace MWGui void onShadersToggled(MyGUI::Widget* _sender); void onShadowTextureSize(MyGUI::Widget* _sender); + void onRebindAction(MyGUI::Widget* _sender); + void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel); + void onResetDefaultBindings(MyGUI::Widget* _sender); + void onResetDefaultBindingsAccept (); + void apply(); }; } #endif - diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 8f81a1761d..bd671cab62 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -8,17 +8,17 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwmechanics/spells.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/spellsuccess.hpp" -#include "../mwsound/soundmanager.hpp" - -#include "window_manager.hpp" #include "inventorywindow.hpp" #include "confirmationdialog.hpp" @@ -43,7 +43,7 @@ namespace namespace MWGui { - SpellWindow::SpellWindow(WindowManager& parWindowManager) + SpellWindow::SpellWindow(MWBase::WindowManager& parWindowManager) : WindowPinnableBase("openmw_spell_window.layout", parWindowManager) , mHeight(0) , mWidth(0) @@ -351,34 +351,10 @@ namespace MWGui if (_sender->getUserString("Equipped") == "false" && !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) { - // sound - MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0); - // Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping - /// \todo the following code is pretty much copy&paste from ActionEquip, put it in a function? - // slots that this item can be equipped in - std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - - // equip the item in the first free slot - for (std::vector::const_iterator slot=slots.first.begin(); - slot!=slots.first.end(); ++slot) - { - // if all slots are occupied, replace the last slot - if (slot == --slots.first.end()) - { - store.equip(*slot, it); - break; - } - - if (store.getSlot(*slot) == store.end()) - { - // slot is not occupied - store.equip(*slot, it); - break; - } - } - /// \todo scripts? + MWWorld::ActionEquip action(item); + action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); // since we changed equipping status, update the inventory window mWindowManager.getInventoryWindow()->drawItems(); diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 87e4783ba2..caa67fd740 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -8,7 +8,7 @@ namespace MWGui class SpellWindow : public WindowPinnableBase { public: - SpellWindow(WindowManager& parWindowManager); + SpellWindow(MWBase::WindowManager& parWindowManager); void updateSpells(); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 190d195945..32dac71deb 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -8,20 +8,21 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwmechanics/npcstats.hpp" -#include "window_manager.hpp" #include "tooltips.hpp" using namespace MWGui; const int StatsWindow::sLineHeight = 18; -StatsWindow::StatsWindow (WindowManager& parWindowManager) +StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) : WindowPinnableBase("openmw_stats_window.layout", parWindowManager) , mSkillAreaWidget(NULL) , mSkillClientWidget(NULL) @@ -56,7 +57,7 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) { 0, 0 } }; - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); for (int i=0; names[i][0]; ++i) { setText (names[i][0], store.gameSettings.find (names[i][1])->str); @@ -382,12 +383,12 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, float modified = stat.getModified(); int progressPercent = (modified - float(static_cast(modified))) * 100; - const ESM::Skill* skill = mWindowManager.getStore().skills.search(skillId); + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); assert(skill); std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; - const ESM::Attribute* attr = mWindowManager.getStore().attributes.search(skill->data.attribute); + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->data.attribute); assert(attr); std::string state = "normal"; @@ -442,7 +443,7 @@ void StatsWindow::updateSkillArea() if (!mMiscSkills.empty()) addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); - const ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); // race tooltip const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); @@ -484,8 +485,8 @@ void StatsWindow::updateSkillArea() text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->ranks[it->second+1]; ESM::RankData rankData = faction->data.rankData[it->second+1]; - const ESM::Attribute* attr1 = mWindowManager.getStore().attributes.search(faction->data.attribute1); - const ESM::Attribute* attr2 = mWindowManager.getStore().attributes.search(faction->data.attribute2); + const ESM::Attribute* attr1 = MWBase::Environment::get().getWorld()->getStore().attributes.search(faction->data.attribute1); + const ESM::Attribute* attr2 = MWBase::Environment::get().getWorld()->getStore().attributes.search(faction->data.attribute2); assert(attr1 && attr2); text += "\n#BF9959#{" + attr1->name + "}: " + boost::lexical_cast(rankData.attribute1) @@ -495,7 +496,7 @@ void StatsWindow::updateSkillArea() text += "\n#BF9959"; for (int i=0; i<6; ++i) { - const ESM::Skill* skill = mWindowManager.getStore().skills.search(faction->data.skillID[i]); + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(faction->data.skillID[i]); assert(skill); text += "#{"+ESM::Skill::sSkillNameIds[faction->data.skillID[i]]+"}"; if (i<5) diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 2469c12e9c..a46ab7531d 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -22,7 +22,7 @@ namespace MWGui typedef std::vector SkillList; - StatsWindow(WindowManager& parWindowManager); + StatsWindow(MWBase::WindowManager& parWindowManager); /// automatically updates all the data in the stats window, but only if it has changed. void onFrame(); @@ -82,4 +82,3 @@ namespace MWGui }; } #endif - diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index 7d5b0cc6db..b724bab15f 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -1,9 +1,10 @@ #include "text_input.hpp" -#include "window_manager.hpp" + +#include "../mwbase/windowmanager.hpp" using namespace MWGui; -TextInputDialog::TextInputDialog(WindowManager& parWindowManager) +TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_text_input.layout", parWindowManager) { // Centre dialog @@ -44,7 +45,6 @@ void TextInputDialog::open() { // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); - setVisible(true); } // widget controls diff --git a/apps/openmw/mwgui/text_input.hpp b/apps/openmw/mwgui/text_input.hpp index 835d5deaa5..8fb0e58194 100644 --- a/apps/openmw/mwgui/text_input.hpp +++ b/apps/openmw/mwgui/text_input.hpp @@ -18,14 +18,14 @@ namespace MWGui class TextInputDialog : public WindowBase { public: - TextInputDialog(WindowManager& parWindowManager); + TextInputDialog(MWBase::WindowManager& parWindowManager); std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); } void setNextButtonShow(bool shown); void setTextLabel(const std::string &label); - void open(); + virtual void open(); protected: void onOkClicked(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 679c7a59eb..16ee279230 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -8,16 +8,17 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" -#include "window_manager.hpp" +#include "map_window.hpp" #include "widgets.hpp" using namespace MWGui; using namespace MyGUI; -ToolTips::ToolTips(WindowManager* windowManager) : +ToolTips::ToolTips(MWBase::WindowManager* windowManager) : Layout("openmw_tooltips.layout") , mGameMode(true) , mWindowManager(windowManager) @@ -150,7 +151,19 @@ void ToolTips::onFrame(float frameDuration) { return; } - else if (type == "ItemPtr") + + // special handling for markers on the local map: the tooltip should only be visible + // if the marker is not hidden due to the fog of war. + if (focus->getUserString ("IsMarker") == "true") + { + LocalMapBase::MarkerPosition pos = *focus->getUserData(); + + if (!MWBase::Environment::get().getWorld ()->isPositionExplored (pos.nX, pos.nY, pos.cellX, pos.cellY, pos.interior)) + return; + } + + + if (type == "ItemPtr") { mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); @@ -199,7 +212,8 @@ void ToolTips::onFrame(float frameDuration) it != userStrings.end(); ++it) { if (it->first == "ToolTipType" - || it->first == "ToolTipLayout") + || it->first == "ToolTipLayout" + || it->first == "IsMarker") continue; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 036bdfaa34..700f5f7238 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -9,8 +9,6 @@ namespace MWGui { - class WindowManager; - // Info about tooltip that is supplied by the MWWorld::Class object struct ToolTipInfo { @@ -29,7 +27,7 @@ namespace MWGui class ToolTips : public OEngine::GUI::Layout { public: - ToolTips(WindowManager* windowManager); + ToolTips(MWBase::WindowManager* windowManager); void onFrame(float frameDuration); @@ -45,7 +43,7 @@ namespace MWGui void setFocusObject(const MWWorld::Ptr& focus); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); - ///< set the screen-space position of the tooltip for focused object + ///< set the screen-space position of the tooltip for focused object static std::string getValueString(const int value, const std::string& prefix); ///< @return "prefix: value" or "" if value is 0 @@ -71,7 +69,7 @@ namespace MWGui private: MyGUI::Widget* mDynamicToolTipBox; - WindowManager* mWindowManager; + MWBase::WindowManager* mWindowManager; MWWorld::Ptr mFocusObject; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index d9f9692ffa..9abd97bb7e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -4,17 +4,17 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/manualref.hpp" -#include "../mwsound/soundmanager.hpp" -#include "window_manager.hpp" #include "inventorywindow.hpp" namespace MWGui { - TradeWindow::TradeWindow(WindowManager& parWindowManager) : + TradeWindow::TradeWindow(MWBase::WindowManager& parWindowManager) : WindowBase("openmw_trade_window.layout", parWindowManager) , ContainerBase(NULL) // no drag&drop , mCurrentBalance(0) @@ -291,14 +291,14 @@ namespace MWGui if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->hasAI) - services = ref->base->AI.services; + if (ref->base->mHasAI) + services = ref->base->mAiData.mServices; } else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->base->hasAI) - services = ref->base->AI.services; + if (ref->base->mHasAI) + services = ref->base->mAiData.mServices; } /// \todo what about potions, there doesn't seem to be a flag for them?? diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index b391fd8fa2..1daeefa960 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -23,7 +23,7 @@ namespace MWGui class TradeWindow : public ContainerBase, public WindowBase { public: - TradeWindow(WindowManager& parWindowManager); + TradeWindow(MWBase::WindowManager& parWindowManager); void startTrade(MWWorld::Ptr actor); diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index c54ac6e389..40ee1c7adf 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -1,9 +1,13 @@ #include "widgets.hpp" -#include "window_manager.hpp" -#include "components/esm_store/store.hpp" #include +#include "components/esm_store/store.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" + #undef min #undef max @@ -190,7 +194,7 @@ void MWAttribute::initialiseOverride() assignWidget(mAttributeNameWidget, "StatName"); assignWidget(mAttributeValueWidget, "StatValue"); - + MyGUI::ButtonPtr button; assignWidget(button, "StatNameButton"); if (button) @@ -224,7 +228,7 @@ void MWSpell::setSpellId(const std::string &spellId) void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags) { - const ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Spell *spell = store.spells.search(mId); MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found"); @@ -255,7 +259,7 @@ void MWSpell::updateWidgets() { if (mSpellNameWidget && mWindowManager) { - const ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Spell *spell = store.spells.search(mId); if (spell) static_cast(mSpellNameWidget)->setCaption(spell->name); @@ -384,7 +388,7 @@ void MWSpellEffect::updateWidgets() if (!mWindowManager) return; - const ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::MagicEffect *magicEffect = store.magicEffects.search(mEffectParams.mEffectID); if (!magicEffect) return; diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index d4947895b1..9a2762369c 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -10,14 +10,19 @@ #undef MYGUI_EXPORT #define MYGUI_EXPORT +namespace MWBase +{ + class WindowManager; +} + /* This file contains various custom widgets used in OpenMW. */ namespace MWGui { + /// \todo remove! using namespace MyGUI; - class WindowManager; namespace Widgets { @@ -81,12 +86,12 @@ namespace MWGui typedef MWMechanics::Stat SkillValue; - void setWindowManager(WindowManager *m) { mManager = m; } + void setWindowManager(MWBase::WindowManager *m) { mManager = m; } /// \todo remove void setSkillId(ESM::Skill::SkillEnum skillId); void setSkillNumber(int skillId); void setSkillValue(const SkillValue& value); - WindowManager *getWindowManager() const { return mManager; } + MWBase::WindowManager *getWindowManager() const { return mManager; } ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } const SkillValue& getSkillValue() const { return mValue; } @@ -109,7 +114,7 @@ namespace MWGui void updateWidgets(); - WindowManager *mManager; + MWBase::WindowManager *mManager; ESM::Skill::SkillEnum mSkillId; SkillValue mValue; MyGUI::WidgetPtr mSkillNameWidget, mSkillValueWidget; @@ -124,11 +129,11 @@ namespace MWGui typedef MWMechanics::Stat AttributeValue; - void setWindowManager(WindowManager *m) { mManager = m; } + void setWindowManager(MWBase::WindowManager *m) { mManager = m; } void setAttributeId(int attributeId); void setAttributeValue(const AttributeValue& value); - WindowManager *getWindowManager() const { return mManager; } + MWBase::WindowManager *getWindowManager() const { return mManager; } int getAttributeId() const { return mId; } const AttributeValue& getAttributeValue() const { return mValue; } @@ -151,7 +156,7 @@ namespace MWGui void updateWidgets(); - WindowManager *mManager; + MWBase::WindowManager *mManager; int mId; AttributeValue mValue; MyGUI::WidgetPtr mAttributeNameWidget, mAttributeValueWidget; @@ -170,7 +175,7 @@ namespace MWGui typedef MWMechanics::Stat SpellValue; - void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } + void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellId(const std::string &id); /** @@ -192,7 +197,7 @@ namespace MWGui private: void updateWidgets(); - WindowManager* mWindowManager; + MWBase::WindowManager* mWindowManager; std::string mId; MyGUI::TextBox* mSpellNameWidget; }; @@ -212,7 +217,7 @@ namespace MWGui EF_Constant = 0x02 // constant effect means that duration will not be displayed }; - void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } + void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setEffectList(const SpellEffectList& list); static SpellEffectList effectListFromESM(const ESM::EffectList* effects); @@ -234,7 +239,7 @@ namespace MWGui private: void updateWidgets(); - WindowManager* mWindowManager; + MWBase::WindowManager* mWindowManager; SpellEffectList mEffectList; }; typedef MWEffectList* MWEffectListPtr; @@ -247,7 +252,7 @@ namespace MWGui typedef ESM::ENAMstruct SpellEffectValue; - void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } + void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellEffect(const SpellEffectParams& params); std::string effectIDToString(const short effectID); @@ -262,12 +267,12 @@ namespace MWGui virtual ~MWSpellEffect(); virtual void initialiseOverride(); - + private: void updateWidgets(); - WindowManager* mWindowManager; + MWBase::WindowManager* mWindowManager; SpellEffectParams mEffectParams; MyGUI::ImageBox* mImageWidget; MyGUI::TextBox* mTextWidget; diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp index 4330579311..38bee9ea30 100644 --- a/apps/openmw/mwgui/window_base.cpp +++ b/apps/openmw/mwgui/window_base.cpp @@ -1,27 +1,26 @@ #include "window_base.hpp" -#include "window_manager.hpp" #include +#include "../mwbase/windowmanager.hpp" + using namespace MWGui; -WindowBase::WindowBase(const std::string& parLayout, WindowManager& parWindowManager) +WindowBase::WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) : Layout(parLayout) , mWindowManager(parWindowManager) { } -void WindowBase::open() -{ -} - void WindowBase::setVisible(bool visible) { bool wasVisible = mMainWidget->getVisible(); mMainWidget->setVisible(visible); - if (!wasVisible && visible) + if (visible) open(); + else if (wasVisible && !visible) + close(); } void WindowBase::center() @@ -39,3 +38,18 @@ void WindowBase::center() coord.top = (gameWindowSize.height - coord.height)/2; mMainWidget->setCoord(coord); } + +WindowModal::WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager) + : WindowBase(parLayout, parWindowManager) +{ +} + +void WindowModal::open() +{ + MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget); +} + +void WindowModal::close() +{ + MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget); +} diff --git a/apps/openmw/mwgui/window_base.hpp b/apps/openmw/mwgui/window_base.hpp index 9cfdbe2612..afdf4d065b 100644 --- a/apps/openmw/mwgui/window_base.hpp +++ b/apps/openmw/mwgui/window_base.hpp @@ -3,6 +3,11 @@ #include +namespace MWBase +{ + class WindowManager; +} + namespace MWGui { class WindowManager; @@ -10,13 +15,14 @@ namespace MWGui class WindowBase: public OEngine::GUI::Layout { public: - WindowBase(const std::string& parLayout, WindowManager& parWindowManager); + WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); // Events typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; - virtual void open(); - virtual void setVisible(bool visible); // calls open() if visible is true and was false before + virtual void open() {} + virtual void close () {} + virtual void setVisible(bool visible); void center(); /** Event : Dialog finished, OK button clicked.\n @@ -25,9 +31,21 @@ namespace MWGui EventHandle_WindowBase eventDone; protected: - WindowManager& mWindowManager; + /// \todo remove + MWBase::WindowManager& mWindowManager; + }; + + + /* + * "Modal" windows cause the rest of the interface to be unaccessible while they are visible + */ + class WindowModal : public WindowBase + { + public: + WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + virtual void open(); + virtual void close(); }; } #endif - diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp deleted file mode 100644 index 3653615a69..0000000000 --- a/apps/openmw/mwgui/window_manager.hpp +++ /dev/null @@ -1,317 +0,0 @@ -#ifndef MWGUI_WINDOWMANAGER_H -#define MWGUI_WINDOWMANAGER_H - -/** - This class owns and controls all the MW specific windows in the - GUI. It can enable/disable Gui mode, and is responsible for sending - and retrieving information from the Gui. - - MyGUI should be initialized separately before creating instances of - this class. -**/ - -#include "MyGUI_UString.h" - -#include -#include -#include -#include - -#include "../mwmechanics/stat.hpp" - -#include "mode.hpp" - -namespace MyGUI -{ - class Gui; - class Widget; -} - -namespace Compiler -{ - class Extensions; -} - -namespace MWWorld -{ - class Ptr; - class CellStore; -} - -namespace MWMechanics -{ - class MechanicsManager; -} - -namespace OEngine -{ - namespace GUI - { - class Layout; - } -} - -namespace MWGui -{ - class WindowBase; - class HUD; - class MapWindow; - class MainMenu; - class StatsWindow; - class InventoryWindow; - class Console; - class JournalWindow; - class CharacterCreation; - class ContainerWindow; - class DragAndDrop; - class InventoryWindow; - class ToolTips; - class ScrollWindow; - class BookWindow; - class TextInputDialog; - class InfoBoxDialog; - class DialogueWindow; - class MessageBoxManager; - class CountDialog; - class TradeWindow; - class SettingsWindow; - class ConfirmationDialog; - class AlchemyWindow; - class SpellWindow; - - struct ClassPoint - { - const char *id; - // Specialization points to match, in order: Stealth, Combat, Magic - // Note: Order is taken from http://www.uesp.net/wiki/Morrowind:Class_Quiz - unsigned int points[3]; - }; - - class WindowManager - { - public: - typedef std::pair Faction; - typedef std::vector FactionList; - typedef std::vector SkillList; - - WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, bool consoleOnlyScripts); - virtual ~WindowManager(); - - /** - * Should be called each frame to update windows/gui elements. - * This could mean updating sizes of gui elements or opening - * new dialogs. - */ - void update(); - - void pushGuiMode(GuiMode mode); - void popGuiMode(); - void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack - - GuiMode getMode() const - { - if (mGuiModes.empty()) - throw std::runtime_error ("getMode() called, but there is no active mode"); - return mGuiModes.back(); - } - - bool isGuiMode() const { return !mGuiModes.empty(); } - - void toggleVisible(GuiWindow wnd) - { - mShown = (mShown & wnd) ? (GuiWindow) (mShown & ~wnd) : (GuiWindow) (mShown | wnd); - updateVisible(); - } - - // Disallow all inventory mode windows - void disallowAll() - { - mAllowed = GW_None; - updateVisible(); - } - - // Allow one or more windows - void allow(GuiWindow wnd) - { - mAllowed = (GuiWindow)(mAllowed | wnd); - updateVisible(); - } - - bool isAllowed(GuiWindow wnd) const - { - return mAllowed & wnd; - } - - MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} - MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} - MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;} - MWGui::BookWindow* getBookWindow() {return mBookWindow;} - MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} - MWGui::CountDialog* getCountDialog() {return mCountDialog;} - MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} - MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} - MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} - MWGui::Console* getConsole() {return mConsole;} - - MyGUI::Gui* getGui() const { return mGui; } - - void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) - { - mFPS = fps; - mTriangleCount = triangleCount; - mBatchCount = batchCount; - } - -// MWMechanics::DynamicStat getValue(const std::string& id); - - ///< Set value for the given ID. - void setValue (const std::string& id, const MWMechanics::Stat& value); - void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setValue (const std::string& id, const std::string& value); - void setValue (const std::string& id, int value); - - void setPlayerClass (const ESM::Class &class_); ///< set current class of player - void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. - void setReputation (int reputation); ///< set the current reputation value - void setBounty (int bounty); ///< set the current bounty value - void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty - - void changeCell(MWWorld::CellStore* cell); ///< change the active cell - void setPlayerPos(const float x, const float y); ///< set player position in map space - void setPlayerDir(const float x, const float y); ///< set player view direction in map space - - void setFocusObject(const MWWorld::Ptr& focus); - void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); - - void setMouseVisible(bool visible); - void getMousePosition(int &x, int &y); - void getMousePosition(float &x, float &y); - void setDragDrop(bool dragDrop); - bool getWorldMouseOver(); - - void toggleFogOfWar(); - void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) - bool getFullHelp() const; - - void setInteriorMapTexture(const int x, const int y); - ///< set the index of the map texture that should be used (for interiors) - - // sets the visibility of the hud health/magicka/stamina bars - void setHMSVisibility(bool visible); - // sets the visibility of the hud minimap - void setMinimapVisibility(bool visible); - void setWeaponVisibility(bool visible); - void setSpellVisibility(bool visible); - - void setSelectedSpell(const std::string& spellId, int successChancePercent); - void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); - void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); - void unsetSelectedSpell(); - void unsetSelectedWeapon(); - - template - void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. - void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. - - void messageBox (const std::string& message, const std::vector& buttons); - int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) - - void onFrame (float frameDuration); - - std::map > getPlayerSkillValues() { return mPlayerSkillValues; } - std::map > getPlayerAttributeValues() { return mPlayerAttributes; } - SkillList getPlayerMinorSkills() { return mPlayerMinorSkills; } - SkillList getPlayerMajorSkills() { return mPlayerMajorSkills; } - - /** - * Fetches a GMST string from the store, if there is no setting with the given - * ID or it is not a string the default string is returned. - * - * @param id Identifier for the GMST setting, e.g. "aName" - * @param default Default value if the GMST setting cannot be used. - */ - const std::string &getGameSettingString(const std::string &id, const std::string &default_); - - const ESMS::ESMStore& getStore() const; - - void processChangedSettings(const Settings::CategorySettingVector& changed); - - void executeInConsole (const std::string& path); - - private: - OEngine::GUI::MyGUIManager *mGuiManager; - HUD *mHud; - MapWindow *mMap; - MainMenu *mMenu; - ToolTips *mToolTips; - StatsWindow *mStatsWindow; - MessageBoxManager *mMessageBoxManager; - Console *mConsole; - JournalWindow* mJournal; - DialogueWindow *mDialogueWindow; - ContainerWindow *mContainerWindow; - DragAndDrop* mDragAndDrop; - InventoryWindow *mInventoryWindow; - ScrollWindow* mScrollWindow; - BookWindow* mBookWindow; - CountDialog* mCountDialog; - TradeWindow* mTradeWindow; - SettingsWindow* mSettingsWindow; - ConfirmationDialog* mConfirmationDialog; - AlchemyWindow* mAlchemyWindow; - SpellWindow* mSpellWindow; - - CharacterCreation* mCharGen; - - // Various stats about player as needed by window manager - ESM::Class mPlayerClass; - std::string mPlayerName; - std::string mPlayerRaceId; - std::map > mPlayerAttributes; - SkillList mPlayerMajorSkills, mPlayerMinorSkills; - std::map > mPlayerSkillValues; - MWMechanics::DynamicStat mPlayerHealth, mPlayerMagicka, mPlayerFatigue; - - - MyGUI::Gui *mGui; // Gui - std::vector mGuiModes; - - std::vector mGarbageDialogs; - void cleanupGarbage(); - - GuiWindow mShown; // Currently shown windows in inventory mode - - /* Currently ALLOWED windows in inventory mode. This is used at - the start of the game, when windows are enabled one by one - through script commands. You can manipulate this through using - allow() and disableAll(). - */ - GuiWindow mAllowed; - - void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings - - int mShowFPSLevel; - float mFPS; - unsigned int mTriangleCount; - unsigned int mBatchCount; - - void onDialogueWindowBye(); - - /** - * Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, - * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result - */ - void onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result); - }; - - template - void WindowManager::removeDialog(T*& dialog) - { - OEngine::GUI::Layout *d = static_cast(dialog); - removeDialog(d); - dialog = 0; - } -} - -#endif diff --git a/apps/openmw/mwgui/window_pinnable_base.cpp b/apps/openmw/mwgui/window_pinnable_base.cpp index ecdf311c6e..4ddf49d27b 100644 --- a/apps/openmw/mwgui/window_pinnable_base.cpp +++ b/apps/openmw/mwgui/window_pinnable_base.cpp @@ -1,9 +1,10 @@ #include "window_pinnable_base.hpp" -#include "window_manager.hpp" + +#include "../mwbase/windowmanager.hpp" using namespace MWGui; -WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager) +WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) : WindowBase(parLayout, parWindowManager), mPinned(false), mVisible(false) { MyGUI::WindowPtr t = static_cast(mMainWidget); @@ -30,4 +31,3 @@ void WindowPinnableBase::onWindowButtonPressed(MyGUI::Window* sender, const std: eventDone(this); } - diff --git a/apps/openmw/mwgui/window_pinnable_base.hpp b/apps/openmw/mwgui/window_pinnable_base.hpp index 86bc3b85c8..250dde1f85 100644 --- a/apps/openmw/mwgui/window_pinnable_base.hpp +++ b/apps/openmw/mwgui/window_pinnable_base.hpp @@ -10,13 +10,13 @@ namespace MWGui class WindowPinnableBase: public WindowBase { public: - WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager); + WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); void setVisible(bool b); bool pinned() { return mPinned; } private: void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName); - + protected: virtual void onPinToggled() = 0; @@ -26,4 +26,3 @@ namespace MWGui } #endif - diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp similarity index 81% rename from apps/openmw/mwgui/window_manager.cpp rename to apps/openmw/mwgui/windowmanagerimp.cpp index 659af04470..faaa41783b 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1,4 +1,25 @@ -#include "window_manager.hpp" +#include "windowmanagerimp.hpp" + +#include +#include + +#include "MyGUI_UString.h" + +#include +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/inputmanager.hpp" + +#include "../mwworld/ptr.hpp" +#include "../mwworld/cellstore.hpp" + +#include "console.hpp" +#include "journalwindow.hpp" +#include "charactercreation.hpp" #include "text_input.hpp" #include "review.hpp" #include "dialogue.hpp" @@ -20,23 +41,7 @@ #include "confirmationdialog.hpp" #include "alchemywindow.hpp" #include "spellwindow.hpp" - -#include "../mwmechanics/mechanicsmanager.hpp" -#include "../mwinput/inputmanager.hpp" - -#include "../mwbase/environment.hpp" - -#include "../mwworld/ptr.hpp" -#include "../mwworld/cellstore.hpp" - -#include "console.hpp" -#include "journalwindow.hpp" -#include "charactercreation.hpp" - -#include - -#include -#include +#include "quickkeysmenu.hpp" using namespace MWGui; @@ -79,6 +84,9 @@ WindowManager::WindowManager( , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) + , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) + , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) + , mHudEnabled(true) { // Set up the GUI system @@ -129,6 +137,9 @@ WindowManager::WindowManager( mConfirmationDialog = new ConfirmationDialog(*this); mAlchemyWindow = new AlchemyWindow(*this); mSpellWindow = new SpellWindow(*this); + mQuickKeysMenu = new QuickKeysMenu(*this); + + mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); // The HUD is always on mHud->setVisible(true); @@ -155,7 +166,6 @@ WindowManager::WindowManager( WindowManager::~WindowManager() { - delete mGuiManager; delete mConsole; delete mMessageBoxManager; delete mHud; @@ -178,6 +188,8 @@ WindowManager::~WindowManager() delete mSpellWindow; cleanupGarbage(); + + delete mGuiManager; } void WindowManager::cleanupGarbage() @@ -219,17 +231,23 @@ void WindowManager::updateVisible() mSettingsWindow->setVisible(false); mAlchemyWindow->setVisible(false); mSpellWindow->setVisible(false); + mQuickKeysMenu->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); bool gameMode = !isGuiMode(); + mInputBlocker->setVisible (gameMode); + if (gameMode) mToolTips->enterGameMode(); else mToolTips->enterGuiMode(); + if (gameMode) + MyGUI::InputManager::getInstance ().setKeyFocusWidget (NULL); + setMinimapVisibility((mAllowed & GW_Map) && !mMap->pinned()); setWeaponVisibility((mAllowed & GW_Inventory) && !mInventoryWindow->pinned()); setSpellVisibility((mAllowed & GW_Magic) && !mSpellWindow->pinned()); @@ -242,6 +260,9 @@ void WindowManager::updateVisible() GuiMode mode = mGuiModes.back(); switch(mode) { + case GM_QuickKeysMenu: + mQuickKeysMenu->setVisible (true); + break; case GM_MainMenu: mMenu->setVisible(true); break; @@ -300,7 +321,6 @@ void WindowManager::updateVisible() break; case GM_Journal: mJournal->setVisible(true); - mJournal->open(); break; default: // Unsupported mode, switch back to game @@ -339,10 +359,12 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) +void WindowManager::setValue (int parSkill, const MWMechanics::Stat& value) { - mStatsWindow->setValue(parSkill, value); - mCharGen->setValue(parSkill, value); + /// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we + /// allow custom skills. + mStatsWindow->setValue(static_cast (parSkill), value); + mCharGen->setValue(static_cast (parSkill), value); mPlayerSkillValues[parSkill] = value; } @@ -425,7 +447,6 @@ void WindowManager::updateSkillArea() void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) { - assert(dialog); if (!dialog) return; dialog->setVisible(false); @@ -492,11 +513,6 @@ void WindowManager::onFrame (float frameDuration) mConsole->checkReferenceAvailable(); } -const ESMS::ESMStore& WindowManager::getStore() const -{ - return MWBase::Environment::get().getWorld()->getStore(); -} - void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) { if (!(cell->cell->data.flags & ESM::Cell::Interior)) @@ -551,12 +567,12 @@ void WindowManager::setPlayerDir(const float x, const float y) void WindowManager::setHMSVisibility(bool visible) { - mHud->setBottomLeftVisibility(visible, mHud->mWeapBox->getVisible(), mHud->mSpellBox->getVisible()); + mHud->setHmsVisible (visible); } void WindowManager::setMinimapVisibility(bool visible) { - mHud->setBottomRightVisibility(mHud->mEffectBox->getVisible(), visible); + mHud->setMinimapVisible (visible); } void WindowManager::toggleFogOfWar() @@ -587,13 +603,13 @@ bool WindowManager::getFullHelp() const void WindowManager::setWeaponVisibility(bool visible) { - mHud->setBottomLeftVisibility(mHud->health->getVisible(), visible, mHud->mSpellBox->getVisible()); + mHud->setWeapVisible (visible); } void WindowManager::setSpellVisibility(bool visible) { - mHud->setBottomLeftVisibility(mHud->health->getVisible(), mHud->mWeapBox->getVisible(), visible); - mHud->setBottomRightVisibility(visible, mHud->mMinimapBox->getVisible()); + mHud->setSpellVisible (visible); + mHud->setEffectVisible (visible); } void WindowManager::setMouseVisible(bool visible) @@ -631,6 +647,10 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector { changeRes = true; } + else if (it->first == "HUD" && it->second == "crosshair") + mCrosshairEnabled = Settings::Manager::getBool ("crosshair", "HUD"); + else if (it->first == "GUI" && it->second == "subtitles") + mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI"); } if (changeRes) @@ -639,11 +659,14 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector int y = Settings::Manager::getInt("resolution y", "Video"); mHud->onResChange(x, y); mConsole->onResChange(x, y); + mMenu->onResChange(x, y); mSettingsWindow->center(); mAlchemyWindow->center(); mScrollWindow->center(); mBookWindow->center(); + mQuickKeysMenu->center(); mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); + mInputBlocker->setSize(MyGUI::IntSize(x,y)); } } @@ -745,3 +768,117 @@ void WindowManager::executeInConsole (const std::string& path) { mConsole->executeFile (path); } + +void WindowManager::wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) +{ + mFPS = fps; + mTriangleCount = triangleCount; + mBatchCount = batchCount; +} + +MyGUI::Gui* WindowManager::getGui() const { return mGui; } + +MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; } +MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; } +MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } +MWGui::BookWindow* WindowManager::getBookWindow() { return mBookWindow; } +MWGui::ScrollWindow* WindowManager::getScrollWindow() { return mScrollWindow; } +MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } +MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } +MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } +MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; } +MWGui::Console* WindowManager::getConsole() { return mConsole; } + +bool WindowManager::isAllowed (GuiWindow wnd) const +{ + return mAllowed & wnd; +} + +void WindowManager::allow (GuiWindow wnd) +{ + mAllowed = (GuiWindow)(mAllowed | wnd); + updateVisible(); +} + +void WindowManager::disallowAll() +{ + mAllowed = GW_None; + updateVisible(); +} + +void WindowManager::toggleVisible (GuiWindow wnd) +{ + mShown = (mShown & wnd) ? (GuiWindow) (mShown & ~wnd) : (GuiWindow) (mShown | wnd); + updateVisible(); +} + +bool WindowManager::isGuiMode() const +{ + return !mGuiModes.empty(); +} + +MWGui::GuiMode WindowManager::getMode() const +{ + if (mGuiModes.empty()) + throw std::runtime_error ("getMode() called, but there is no active mode"); + + return mGuiModes.back(); +} + +std::map > WindowManager::getPlayerSkillValues() +{ + return mPlayerSkillValues; +} + +std::map > WindowManager::getPlayerAttributeValues() +{ + return mPlayerAttributes; +} + +WindowManager::SkillList WindowManager::getPlayerMinorSkills() +{ + return mPlayerMinorSkills; +} + +WindowManager::SkillList WindowManager::getPlayerMajorSkills() +{ + return mPlayerMajorSkills; +} + +void WindowManager::disallowMouse() +{ + mInputBlocker->setVisible (true); +} + +void WindowManager::allowMouse() +{ + mInputBlocker->setVisible (!isGuiMode ()); +} + +void WindowManager::notifyInputActionBound () +{ + mSettingsWindow->updateControlsBox (); + allowMouse(); +} + + +void WindowManager::showCrosshair (bool show) +{ + mHud->setCrosshairVisible (show && mCrosshairEnabled); +} + +void WindowManager::activateQuickKey (int index) +{ + mQuickKeysMenu->activateQuickKey(index); +} + +bool WindowManager::getSubtitlesEnabled () +{ + return mSubtitlesEnabled; +} + +void WindowManager::toggleHud () +{ + mHudEnabled = !mHudEnabled; + mHud->setVisible (mHudEnabled); +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp new file mode 100644 index 0000000000..38411bb18c --- /dev/null +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -0,0 +1,272 @@ +#ifndef MWGUI_WINDOWMANAGERIMP_H +#define MWGUI_WINDOWMANAGERIMP_H + +/** + This class owns and controls all the MW specific windows in the + GUI. It can enable/disable Gui mode, and is responsible for sending + and retrieving information from the Gui. + + MyGUI should be initialized separately before creating instances of + this class. +**/ + +#include +#include + +#include + +#include "../mwbase/windowmanager.hpp" + +namespace MyGUI +{ + class Gui; + class Widget; + class UString; +} + +namespace Compiler +{ + class Extensions; +} + +namespace OEngine +{ + namespace GUI + { + class Layout; + class MyGUIManager; + } + + namespace Render + { + class OgreRenderer; + } +} + +namespace MWGui +{ + class WindowBase; + class HUD; + class MapWindow; + class MainMenu; + class StatsWindow; + class InventoryWindow; + class JournalWindow; + class CharacterCreation; + class DragAndDrop; + class ToolTips; + class TextInputDialog; + class InfoBoxDialog; + class MessageBoxManager; + class SettingsWindow; + class AlchemyWindow; + class QuickKeysMenu; + + class WindowManager : public MWBase::WindowManager + { + public: + typedef std::pair Faction; + typedef std::vector FactionList; + + WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, bool consoleOnlyScripts); + virtual ~WindowManager(); + + /** + * Should be called each frame to update windows/gui elements. + * This could mean updating sizes of gui elements or opening + * new dialogs. + */ + virtual void update(); + + virtual void pushGuiMode(GuiMode mode); + virtual void popGuiMode(); + virtual void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack + + virtual GuiMode getMode() const; + + virtual bool isGuiMode() const; + + virtual void toggleVisible(GuiWindow wnd); + + // Disallow all inventory mode windows + virtual void disallowAll(); + + // Allow one or more windows + virtual void allow(GuiWindow wnd); + + virtual bool isAllowed(GuiWindow wnd) const; + + /// \todo investigate, if we really need to expose every single lousy UI element to the outside world + virtual MWGui::DialogueWindow* getDialogueWindow(); + virtual MWGui::ContainerWindow* getContainerWindow(); + virtual MWGui::InventoryWindow* getInventoryWindow(); + virtual MWGui::BookWindow* getBookWindow(); + virtual MWGui::ScrollWindow* getScrollWindow(); + virtual MWGui::CountDialog* getCountDialog(); + virtual MWGui::ConfirmationDialog* getConfirmationDialog(); + virtual MWGui::TradeWindow* getTradeWindow(); + virtual MWGui::SpellWindow* getSpellWindow(); + virtual MWGui::Console* getConsole(); + + virtual MyGUI::Gui* getGui() const; + + virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount); + + ///< Set value for the given ID. + virtual void setValue (const std::string& id, const MWMechanics::Stat& value); + virtual void setValue (int parSkill, const MWMechanics::Stat& value); + virtual void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + virtual void setValue (const std::string& id, const std::string& value); + virtual void setValue (const std::string& id, int value); + + virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player + virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. + virtual void setReputation (int reputation); ///< set the current reputation value + virtual void setBounty (int bounty); ///< set the current bounty value + virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty + + virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell + virtual void setPlayerPos(const float x, const float y); ///< set player position in map space + virtual void setPlayerDir(const float x, const float y); ///< set player view direction in map space + + virtual void setFocusObject(const MWWorld::Ptr& focus); + virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); + + virtual void setMouseVisible(bool visible); + virtual void getMousePosition(int &x, int &y); + virtual void getMousePosition(float &x, float &y); + virtual void setDragDrop(bool dragDrop); + virtual bool getWorldMouseOver(); + + virtual void toggleFogOfWar(); + virtual void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) + virtual bool getFullHelp() const; + + virtual void setInteriorMapTexture(const int x, const int y); + ///< set the index of the map texture that should be used (for interiors) + + // sets the visibility of the hud health/magicka/stamina bars + virtual void setHMSVisibility(bool visible); + // sets the visibility of the hud minimap + virtual void setMinimapVisibility(bool visible); + virtual void setWeaponVisibility(bool visible); + virtual void setSpellVisibility(bool visible); + + virtual void activateQuickKey (int index); + + virtual void setSelectedSpell(const std::string& spellId, int successChancePercent); + virtual void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); + virtual void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + virtual void unsetSelectedSpell(); + virtual void unsetSelectedWeapon(); + + virtual void showCrosshair(bool show); + virtual bool getSubtitlesEnabled(); + virtual void toggleHud(); + + virtual void disallowMouse(); + virtual void allowMouse(); + virtual void notifyInputActionBound(); + + virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. + + virtual void messageBox (const std::string& message, const std::vector& buttons); + virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) + + virtual void onFrame (float frameDuration); + + /// \todo get rid of this stuff. Move it to the respective UI element classes, if needed. + virtual std::map > getPlayerSkillValues(); + virtual std::map > getPlayerAttributeValues(); + virtual SkillList getPlayerMinorSkills(); + virtual SkillList getPlayerMajorSkills(); + + /** + * Fetches a GMST string from the store, if there is no setting with the given + * ID or it is not a string the default string is returned. + * + * @param id Identifier for the GMST setting, e.g. "aName" + * @param default Default value if the GMST setting cannot be used. + */ + virtual const std::string &getGameSettingString(const std::string &id, const std::string &default_); + + virtual void processChangedSettings(const Settings::CategorySettingVector& changed); + + virtual void executeInConsole (const std::string& path); + + private: + OEngine::GUI::MyGUIManager *mGuiManager; + HUD *mHud; + MapWindow *mMap; + MainMenu *mMenu; + ToolTips *mToolTips; + StatsWindow *mStatsWindow; + MessageBoxManager *mMessageBoxManager; + Console *mConsole; + JournalWindow* mJournal; + DialogueWindow *mDialogueWindow; + ContainerWindow *mContainerWindow; + DragAndDrop* mDragAndDrop; + InventoryWindow *mInventoryWindow; + ScrollWindow* mScrollWindow; + BookWindow* mBookWindow; + CountDialog* mCountDialog; + TradeWindow* mTradeWindow; + SettingsWindow* mSettingsWindow; + ConfirmationDialog* mConfirmationDialog; + AlchemyWindow* mAlchemyWindow; + SpellWindow* mSpellWindow; + QuickKeysMenu* mQuickKeysMenu; + + CharacterCreation* mCharGen; + + MyGUI::Widget* mInputBlocker; + + bool mCrosshairEnabled; + bool mSubtitlesEnabled; + bool mHudEnabled; + + /// \todo get rid of this stuff. Move it to the respective UI element classes, if needed. + // Various stats about player as needed by window manager + ESM::Class mPlayerClass; + std::string mPlayerName; + std::string mPlayerRaceId; + std::map > mPlayerAttributes; + SkillList mPlayerMajorSkills, mPlayerMinorSkills; + std::map > mPlayerSkillValues; + MWMechanics::DynamicStat mPlayerHealth, mPlayerMagicka, mPlayerFatigue; + + + MyGUI::Gui *mGui; // Gui + std::vector mGuiModes; + + std::vector mGarbageDialogs; + void cleanupGarbage(); + + GuiWindow mShown; // Currently shown windows in inventory mode + + /* Currently ALLOWED windows in inventory mode. This is used at + the start of the game, when windows are enabled one by one + through script commands. You can manipulate this through using + allow() and disableAll(). + */ + GuiWindow mAllowed; + + void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings + + int mShowFPSLevel; + float mFPS; + unsigned int mTriangleCount; + unsigned int mBatchCount; + + void onDialogueWindowBye(); + + /** + * Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, + * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result + */ + void onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result); + }; +} + +#endif diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp deleted file mode 100644 index 6bda77ea8e..0000000000 --- a/apps/openmw/mwinput/inputmanager.cpp +++ /dev/null @@ -1,508 +0,0 @@ -#include "inputmanager.hpp" - -#include -#include - -#include - -#include -#include -#include - -#include "../mwgui/window_manager.hpp" - -#include -#include - -#include - -#include "../engine.hpp" - -#include "../mwworld/player.hpp" - -#include "../mwrender/player.hpp" - -#include -#include -#include -#include - -namespace MWInput -{ - enum Actions - { - A_Quit, // Exit the program - - A_Screenshot, // Take a screenshot - - A_Inventory, // Toggle inventory screen - - A_Console, // Toggle console screen - - A_MoveLeft, // Move player left / right - A_MoveRight, - A_MoveForward, // Forward / Backward - A_MoveBackward, - - A_Activate, - - A_Use, //Use weapon, spell, etc. - A_Jump, - A_AutoMove, //Toggle Auto-move forward - A_Rest, //Rest - A_Journal, //Journal - A_Weapon, //Draw/Sheath weapon - A_Spell, //Ready/Unready Casting - A_AlwaysRun, //Toggle Always Run - A_CycleSpellLeft, //cycling through spells - A_CycleSpellRight, - A_CycleWeaponLeft,//Cycling through weapons - A_CycleWeaponRight, - A_ToggleSneak, //Toggles Sneak, add Push-Sneak later - A_ToggleWalk, //Toggle Walking/Running - A_Crouch, - - A_QuickSave, - A_QuickLoad, - A_QuickMenu, - A_GameMenu, - A_ToggleWeapon, - A_ToggleSpell, - - A_Settings, // Temporary hotkey - - A_LAST // Marker for the last item - }; - - // Class that handles all input and key bindings for OpenMW - class InputImpl - { - OEngine::Input::DispatcherPtr disp; - OEngine::Render::OgreRenderer &ogre; - OEngine::Render::ExitListener exit; - Mangle::Input::OISDriver input; - OEngine::Input::Poller poller; - OEngine::Render::MouseLookEventPtr mouse; - OEngine::GUI::EventInjectorPtr guiEvents; - MWWorld::Player &player; - MWGui::WindowManager &windows; - OMW::Engine& mEngine; - - bool mDragDrop; - - std::map mControlSwitch; - - /* InputImpl Methods */ -public: - void adjustMouseRegion(int width, int height) - { - input.adjustMouseClippingSize(width, height); - } -private: - void toggleSpell() - { - if (windows.isGuiMode()) return; - - MWMechanics::DrawState_ state = player.getDrawState(); - if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing) - { - player.setDrawState(MWMechanics::DrawState_Spell); - std::cout << "Player has now readied his hands for spellcasting!\n"; - } - else - { - player.setDrawState(MWMechanics::DrawState_Nothing); - std::cout << "Player does not have any kind of attack ready now.\n"; - } - } - - void toggleWeapon() - { - if (windows.isGuiMode()) return; - - MWMechanics::DrawState_ state = player.getDrawState(); - if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - { - player.setDrawState(MWMechanics::DrawState_Weapon); - std::cout << "Player is now drawing his weapon.\n"; - } - else - { - player.setDrawState(MWMechanics::DrawState_Nothing); - std::cout << "Player does not have any kind of attack ready now.\n"; - } - } - - void screenshot() - { - mEngine.screenshot(); - - std::vector empty; - windows.messageBox ("Screenshot saved", empty); - } - - void showSettings() - { - if (mDragDrop) - return; - - if (!windows.isGuiMode() || windows.getMode() != MWGui::GM_Settings) - windows.pushGuiMode(MWGui::GM_Settings); - } - - /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ - void toggleInventory() - { - using namespace MWGui; - - if (mDragDrop) - return; - - bool gameMode = !windows.isGuiMode(); - - // Toggle between game mode and inventory mode - if(gameMode) - windows.pushGuiMode(GM_Inventory); - else if(windows.getMode() == GM_Inventory) - windows.popGuiMode(); - - // .. but don't touch any other mode. - } - - // Toggle console - void toggleConsole() - { - using namespace MWGui; - - if (mDragDrop) - return; - - bool gameMode = !windows.isGuiMode(); - - // Switch to console mode no matter what mode we are currently - // in, except of course if we are already in console mode - if (!gameMode) - { - if (windows.getMode() == GM_Console) - windows.popGuiMode(); - else - windows.pushGuiMode(GM_Console); - } - else - windows.pushGuiMode(GM_Console); - } - - void toggleJournal() - { - using namespace MWGui; - - // Toggle between game mode and journal mode - bool gameMode = !windows.isGuiMode(); - - if(gameMode) - windows.pushGuiMode(GM_Journal); - else if(windows.getMode() == GM_Journal) - windows.popGuiMode(); - // .. but don't touch any other mode. - } - - void activate() - { - mEngine.activate(); - } - - void toggleAutoMove() - { - if (windows.isGuiMode()) return; - player.setAutoMove (!player.getAutoMove()); - } - - void toggleWalking() - { - if (windows.isGuiMode()) return; - player.toggleRunning(); - } - - // Exit program now button (which is disabled in GUI mode) - void exitNow() - { - if(!windows.isGuiMode()) - exit.exitNow(); - } - - public: - InputImpl(OEngine::Render::OgreRenderer &_ogre, - MWWorld::Player &_player, - MWGui::WindowManager &_windows, - bool debug, - OMW::Engine& engine) - : ogre(_ogre), - exit(ogre.getWindow()), - input(ogre.getWindow(), !debug), - poller(input), - player(_player), - windows(_windows), - mEngine (engine), - mDragDrop(false) - { - using namespace OEngine::Input; - using namespace OEngine::Render; - using namespace OEngine::GUI; - using namespace Mangle::Input; - using namespace OIS; - - disp = DispatcherPtr(new Dispatcher(A_LAST)); - - // Bind MW-specific functions - disp->funcs.bind(A_Quit, boost::bind(&InputImpl::exitNow, this), - "Quit program"); - disp->funcs.bind(A_Screenshot, boost::bind(&InputImpl::screenshot, this), - "Screenshot"); - disp->funcs.bind(A_Inventory, boost::bind(&InputImpl::toggleInventory, this), - "Toggle inventory screen"); - disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this), - "Toggle console"); - disp->funcs.bind(A_Journal, boost::bind(&InputImpl::toggleJournal, this), - "Toggle journal"); - disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this), - "Activate"); - disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this), - "Auto Move"); - disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this), - "Toggle Walk/Run"); - disp->funcs.bind(A_ToggleWeapon,boost::bind(&InputImpl::toggleWeapon,this), - "Draw Weapon"); - disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this), - "Ready hands"); - disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this), - "Show settings window"); - // Add the exit listener - ogre.getRoot()->addFrameListener(&exit); - - // Set up the mouse handler and tell it about the player camera - mouse = MouseLookEventPtr(new MouseLookEvent(player.getRenderer()->getCamera())); - - // This event handler pumps events into MyGUI - guiEvents = EventInjectorPtr(new EventInjector(windows.getGui())); - - // Hook 'mouse' and 'disp' up as event handlers into 'input' - // (the OIS driver and event source.) We do this through an - // EventList which dispatches the event to multiple handlers for - // us. - { - EventList *lst = new EventList; - input.setEvent(EventPtr(lst)); - lst->add(mouse,Event::EV_MouseMove); - lst->add(disp,Event::EV_KeyDown); - lst->add(guiEvents,Event::EV_ALL); - } - - changeInputMode(false); - - /********************************** - Key binding section - - The rest of this function has hard coded key bindings, and is - intended to be replaced by user defined bindings later. - **********************************/ - - // Key bindings for keypress events - // NOTE: These keys do not require constant polling - use in conjuction with variables in loops. - - disp->bind(A_Quit, KC_Q); - disp->bind(A_Quit, KC_ESCAPE); - disp->bind(A_Screenshot, KC_SYSRQ); - disp->bind(A_Inventory, KC_I); - disp->bind(A_Console, KC_F1); - disp->bind(A_Journal, KC_J); - disp->bind(A_Activate, KC_SPACE); - disp->bind(A_AutoMove, KC_Z); - disp->bind(A_ToggleSneak, KC_X); - disp->bind(A_ToggleWalk, KC_C); - disp->bind(A_ToggleWeapon,KC_F); - disp->bind(A_ToggleSpell,KC_R); - disp->bind(A_Settings, KC_F2); - - // Key bindings for polled keys - // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame. - - // Arrow keys - poller.bind(A_MoveLeft, KC_LEFT); - poller.bind(A_MoveRight, KC_RIGHT); - poller.bind(A_MoveForward, KC_UP); - poller.bind(A_MoveBackward, KC_DOWN); - - // WASD keys - poller.bind(A_MoveLeft, KC_A); - poller.bind(A_MoveRight, KC_D); - poller.bind(A_MoveForward, KC_W); - poller.bind(A_MoveBackward, KC_S); - - poller.bind(A_Jump, KC_E); - poller.bind(A_Crouch, KC_LCONTROL); - - mControlSwitch["playercontrols"] = true; - mControlSwitch["playerfighting"] = true; - mControlSwitch["playerjumping"] = true; - mControlSwitch["playerlooking"] = true; - mControlSwitch["playermagic"] = true; - mControlSwitch["playerviewswitch"] = true; - mControlSwitch["vanitymode"] = true; - } - - void setDragDrop(bool dragDrop) - { - mDragDrop = dragDrop; - } - - //NOTE: Used to check for movement keys - void update () - { - // Tell OIS to handle all input events - input.capture(); - - // Update windows/gui as a result of input events - // For instance this could mean opening a new window/dialog, - // by doing this after the input events are handled we - // ensure that window/gui changes appear quickly while - // avoiding that window/gui changes does not happen in - // event callbacks (which may crash) - windows.update(); - - // Disable movement in Gui mode - - if (windows.isGuiMode()) return; - - // Configure player movement according to keyboard input. Actual movement will - // be done in the physics system. - if (mControlSwitch["playercontrols"]) { - if (poller.isDown(A_MoveLeft)) - { - player.setAutoMove (false); - player.setLeftRight (1); - } - else if (poller.isDown(A_MoveRight)) - { - player.setAutoMove (false); - player.setLeftRight (-1); - } - else - player.setLeftRight (0); - - if (poller.isDown(A_MoveForward)) - { - player.setAutoMove (false); - player.setForwardBackward (1); - } - else if (poller.isDown(A_MoveBackward)) - { - player.setAutoMove (false); - player.setForwardBackward (-1); - } - else - player.setForwardBackward (0); - } - - if (poller.isDown(A_Jump) && mControlSwitch["playerjumping"]) - player.setUpDown (1); - else if (poller.isDown(A_Crouch)) - player.setUpDown (-1); - else - player.setUpDown (0); - } - - // Switch between gui modes. Besides controlling the Gui windows - // this also makes sure input is directed to the right place - void changeInputMode(bool guiMode) - { - // Are we in GUI mode now? - if(guiMode) - { - // Disable mouse look - mouse->setCamera(NULL); - - // Enable GUI events - guiEvents->enabled = true; - } - else - { - // Start mouse-looking again. TODO: This should also allow - // for other ways to disable mouselook, like paralyzation. - mouse->setCamera(player.getRenderer()->getCamera()); - - // Disable GUI events - guiEvents->enabled = false; - } - } - - void toggleControlSwitch(std::string sw, bool value) - { - if (mControlSwitch[sw] == value) { - return; - } - /// \note 7 switches at all, if-else is relevant - if (sw == "playercontrols") { - player.setLeftRight(0); - player.setForwardBackward(0); - player.setAutoMove(false); - } else if (sw == "playerjumping") { - /// \fixme maybe crouching at this time - player.setUpDown(0); - } - mControlSwitch[sw] = value; - } - - }; - - /***CONSTRUCTOR***/ - MWInputManager::MWInputManager(OEngine::Render::OgreRenderer &ogre, - MWWorld::Player &player, - MWGui::WindowManager &windows, - bool debug, - OMW::Engine& engine) - { - impl = new InputImpl(ogre,player,windows,debug, engine); - } - - /***DESTRUCTOR***/ - MWInputManager::~MWInputManager() - { - delete impl; - } - - void MWInputManager::update() - { - impl->update(); - } - - void MWInputManager::setDragDrop(bool dragDrop) - { - impl->setDragDrop(dragDrop); - } - - void MWInputManager::changeInputMode(bool guiMode) - { - impl->changeInputMode(guiMode); - } - - void MWInputManager::processChangedSettings(const Settings::CategorySettingVector& changed) - { - bool changeRes = false; - for (Settings::CategorySettingVector::const_iterator it = changed.begin(); - it != changed.end(); ++it) - { - if (it->first == "Video" && ( - it->second == "resolution x" - || it->second == "resolution y")) - changeRes = true; - } - - if (changeRes) - impl->adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video")); - } - - void MWInputManager::toggleControlSwitch(std::string sw, bool value) - { - impl->toggleControlSwitch(sw, value); - } -} diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp deleted file mode 100644 index 2486f82d67..0000000000 --- a/apps/openmw/mwinput/inputmanager.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _MWINPUT_MWINPUTMANAGER_H -#define _MWINPUT_MWINPUTMANAGER_H - -#include "../mwgui/mode.hpp" - -#include - -namespace OEngine -{ - namespace Render - { - class OgreRenderer; - } -} - -namespace MWWorld -{ - class Player; -} - -namespace MWGui -{ - class WindowManager; -} - -namespace OMW -{ - class Engine; -} - -namespace MWInput -{ - // Forward declaration of the real implementation. - class InputImpl; - - /* Class that handles all input and key bindings for OpenMW. - - This class is just an interface. All the messy details are in - inputmanager.cpp. - */ - struct MWInputManager - { - InputImpl *impl; - - public: - MWInputManager(OEngine::Render::OgreRenderer &_ogre, - MWWorld::Player&_player, - MWGui::WindowManager &_windows, - bool debug, - OMW::Engine& engine); - ~MWInputManager(); - - void update(); - - void changeInputMode(bool guiMode); - - void processChangedSettings(const Settings::CategorySettingVector& changed); - - void setDragDrop(bool dragDrop); - - void toggleControlSwitch(std::string sw, bool value); - }; -} -#endif diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp new file mode 100644 index 0000000000..f47ea8bb16 --- /dev/null +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -0,0 +1,880 @@ +#include "inputmanagerimp.hpp" + +#if defined(__APPLE__) && !defined(__LP64__) +#include +#endif + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +#include "../engine.hpp" + +#include "../mwworld/player.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" + +namespace MWInput +{ + InputManager::InputManager(OEngine::Render::OgreRenderer &ogre, + MWWorld::Player &player, + MWBase::WindowManager &windows, + bool debug, + OMW::Engine& engine, + const std::string& userFile, bool userFileExists) + : mOgre(ogre) + , mPlayer(player) + , mWindows(windows) + , mEngine(engine) + , mMouseLookEnabled(true) + , mMouseX(ogre.getWindow()->getWidth ()/2.f) + , mMouseY(ogre.getWindow()->getHeight ()/2.f) + , mUserFile(userFile) + , mDragDrop(false) + , mGuiCursorEnabled(false) + , mInvertY (Settings::Manager::getBool("invert y axis", "Input")) + , mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input")) + , mUISensitivity (Settings::Manager::getFloat("ui sensitivity", "Input")) + , mCameraYMultiplier (Settings::Manager::getFloat("camera y multiplier", "Input")) + , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) + , mPreviewPOVDelay(0.f) + , mTimeIdle(0.f) + { + Ogre::RenderWindow* window = ogre.getWindow (); + size_t windowHnd; + + resetIdleTime(); + + window->getCustomAttribute("WINDOW", &windowHnd); + + std::ostringstream windowHndStr; + OIS::ParamList pl; + + windowHndStr << windowHnd; + pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); + + // Set non-exclusive mouse and keyboard input if the user requested + // it. + if (debug) + { + #if defined OIS_WIN32_PLATFORM + pl.insert(std::make_pair(std::string("w32_mouse"), + std::string("DISCL_FOREGROUND" ))); + pl.insert(std::make_pair(std::string("w32_mouse"), + std::string("DISCL_NONEXCLUSIVE"))); + pl.insert(std::make_pair(std::string("w32_keyboard"), + std::string("DISCL_FOREGROUND"))); + pl.insert(std::make_pair(std::string("w32_keyboard"), + std::string("DISCL_NONEXCLUSIVE"))); + #elif defined OIS_LINUX_PLATFORM + pl.insert(std::make_pair(std::string("x11_mouse_grab"), + std::string("false"))); + pl.insert(std::make_pair(std::string("x11_mouse_hide"), + std::string("false"))); + pl.insert(std::make_pair(std::string("x11_keyboard_grab"), + std::string("false"))); + pl.insert(std::make_pair(std::string("XAutoRepeatOn"), + std::string("true"))); + #endif + } + +#if defined(__APPLE__) && !defined(__LP64__) + // Give the application window focus to receive input events + ProcessSerialNumber psn = { 0, kCurrentProcess }; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); +#endif + + mInputManager = OIS::InputManager::createInputSystem( pl ); + + // Create all devices + mKeyboard = static_cast(mInputManager->createInputObject + ( OIS::OISKeyboard, true )); + mMouse = static_cast(mInputManager->createInputObject + ( OIS::OISMouse, true )); + + mKeyboard->setEventCallback (this); + mMouse->setEventCallback (this); + + adjustMouseRegion (window->getWidth(), window->getHeight()); + + MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mMouse->getMouseState ().Z.abs); + + std::string file = userFileExists ? userFile : ""; + mInputCtrl = new ICS::InputControlSystem(file, true, this, NULL, A_Last); + + loadKeyDefaults(); + + for (int i = 0; i < A_Last; ++i) + { + mInputCtrl->getChannel (i)->addListener (this); + } + + mControlSwitch["playercontrols"] = true; + mControlSwitch["playerfighting"] = true; + mControlSwitch["playerjumping"] = true; + mControlSwitch["playerlooking"] = true; + mControlSwitch["playermagic"] = true; + mControlSwitch["playerviewswitch"] = true; + mControlSwitch["vanitymode"] = true; + + changeInputMode(false); + } + + InputManager::~InputManager() + { + mInputCtrl->save (mUserFile); + + delete mInputCtrl; + + mInputManager->destroyInputObject(mKeyboard); + mInputManager->destroyInputObject(mMouse); + OIS::InputManager::destroyInputSystem(mInputManager); + } + + void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) + { + if (mDragDrop) + return; + + resetIdleTime (); + + int action = channel->getNumber(); + if (currentValue == 1) + { + // trigger action activated + switch (action) + { + case A_GameMenu: + toggleMainMenu (); + break; + case A_Quit: + exitNow(); + break; + case A_Screenshot: + screenshot(); + break; + case A_Inventory: + toggleInventory (); + break; + case A_Console: + toggleConsole (); + break; + case A_Activate: + resetIdleTime(); + activate(); + break; + case A_Journal: + toggleJournal (); + break; + case A_AutoMove: + toggleAutoMove (); + break; + case A_ToggleSneak: + /// \todo implement + break; + case A_ToggleWalk: + toggleWalking (); + break; + case A_ToggleWeapon: + toggleWeapon (); + break; + case A_ToggleSpell: + toggleSpell (); + break; + case A_QuickKey1: + quickKey(1); + break; + case A_QuickKey2: + quickKey(2); + break; + case A_QuickKey3: + quickKey(3); + break; + case A_QuickKey4: + quickKey(4); + break; + case A_QuickKey5: + quickKey(5); + break; + case A_QuickKey6: + quickKey(6); + break; + case A_QuickKey7: + quickKey(7); + break; + case A_QuickKey8: + quickKey(8); + break; + case A_QuickKey9: + quickKey(9); + break; + case A_QuickKey10: + quickKey(10); + break; + case A_QuickKeysMenu: + showQuickKeysMenu(); + break; + case A_ToggleHUD: + mWindows.toggleHud(); + break; + } + } + } + + void InputManager::update(float dt) + { + // Tell OIS to handle all input events + mKeyboard->capture(); + mMouse->capture(); + + // update values of channels (as a result of pressed keys) + mInputCtrl->update(dt); + + // Update windows/gui as a result of input events + // For instance this could mean opening a new window/dialog, + // by doing this after the input events are handled we + // ensure that window/gui changes appear quickly while + // avoiding that window/gui changes does not happen in + // event callbacks (which may crash) + mWindows.update(); + + // Disable movement in Gui mode + if (mWindows.isGuiMode()) return; + + + // Configure player movement according to keyboard input. Actual movement will + // be done in the physics system. + if (mControlSwitch["playercontrols"]) + { + if (actionIsActive(A_MoveLeft)) + { + mPlayer.setAutoMove (false); + mPlayer.setLeftRight (1); + } + else if (actionIsActive(A_MoveRight)) + { + mPlayer.setAutoMove (false); + mPlayer.setLeftRight (-1); + } + else + mPlayer.setLeftRight (0); + + if (actionIsActive(A_MoveForward)) + { + mPlayer.setAutoMove (false); + mPlayer.setForwardBackward (1); + } + else if (actionIsActive(A_MoveBackward)) + { + mPlayer.setAutoMove (false); + mPlayer.setForwardBackward (-1); + } + else + mPlayer.setForwardBackward (0); + + if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) + mPlayer.setUpDown (1); + else if (actionIsActive(A_Crouch)) + mPlayer.setUpDown (-1); + else + mPlayer.setUpDown (0); + + if (mControlSwitch["playerviewswitch"]) { + + // work around preview mode toggle when pressing Alt+Tab + if (actionIsActive(A_TogglePOV) && !mKeyboard->isModifierDown (OIS::Keyboard::Alt)) { + if (mPreviewPOVDelay <= 0.5 && + (mPreviewPOVDelay += dt) > 0.5) + { + mPreviewPOVDelay = 1.f; + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + } + } else { + if (mPreviewPOVDelay > 0.5) { + //disable preview mode + MWBase::Environment::get().getWorld()->togglePreviewMode(false); + } else if (mPreviewPOVDelay > 0.f) { + MWBase::Environment::get().getWorld()->togglePOV(); + } + mPreviewPOVDelay = 0.f; + } + } + } + if (actionIsActive(A_MoveForward) || + actionIsActive(A_MoveBackward) || + actionIsActive(A_MoveLeft) || + actionIsActive(A_MoveRight) || + actionIsActive(A_Jump) || + actionIsActive(A_Crouch) || + actionIsActive(A_TogglePOV)) + { + resetIdleTime(); + } else { + updateIdleTime(dt); + } + } + + void InputManager::setDragDrop(bool dragDrop) + { + mDragDrop = dragDrop; + } + + void InputManager::changeInputMode(bool guiMode) + { + // Are we in GUI mode now? + if(guiMode) + { + // Disable mouse look + mMouseLookEnabled = false; + + mWindows.showCrosshair (false); + + // Enable GUI events + mGuiCursorEnabled = true; + } + else + { + // Enable mouse look + mMouseLookEnabled = true; + + mWindows.showCrosshair (false); + + // Disable GUI events + mGuiCursorEnabled = false; + } + } + + void InputManager::processChangedSettings(const Settings::CategorySettingVector& changed) + { + bool changeRes = false; + for (Settings::CategorySettingVector::const_iterator it = changed.begin(); + it != changed.end(); ++it) + { + if (it->first == "Video" && (it->second == "resolution x" || it->second == "resolution y")) + changeRes = true; + + if (it->first == "Input" && it->second == "invert y axis") + mInvertY = Settings::Manager::getBool("invert y axis", "Input"); + + if (it->first == "Input" && it->second == "camera sensitivity") + mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input"); + + if (it->first == "Input" && it->second == "ui sensitivity") + mUISensitivity = Settings::Manager::getFloat("ui sensitivity", "Input"); + + } + + if (changeRes) + adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video")); + } + + void InputManager::toggleControlSwitch (const std::string& sw, bool value) + { + if (mControlSwitch[sw] == value) { + return; + } + /// \note 7 switches at all, if-else is relevant + if (sw == "playercontrols" && !value) { + mPlayer.setLeftRight(0); + mPlayer.setForwardBackward(0); + mPlayer.setAutoMove(false); + mPlayer.setUpDown(0); + } else if (sw == "playerjumping" && !value) { + /// \fixme maybe crouching at this time + mPlayer.setUpDown(0); + } else if (sw == "vanitymode") { + MWBase::Environment::get().getWorld()->allowVanityMode(value); + } else if (sw == "playerlooking") { + MWBase::Environment::get().getWorld()->togglePlayerLooking(value); + } + mControlSwitch[sw] = value; + } + + void InputManager::adjustMouseRegion(int width, int height) + { + const OIS::MouseState &ms = mMouse->getMouseState(); + ms.width = width; + ms.height = height; + } + + bool InputManager::keyPressed( const OIS::KeyEvent &arg ) + { + mInputCtrl->keyPressed (arg); + unsigned int text = arg.text; +#ifdef __APPLE__ // filter \016 symbol for F-keys on OS X + if ((arg.key >= OIS::KC_F1 && arg.key <= OIS::KC_F10) || + (arg.key >= OIS::KC_F11 && arg.key <= OIS::KC_F15)) { + text = 0; + } +#endif + + MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(arg.key), text); + + return true; + } + + bool InputManager::keyReleased( const OIS::KeyEvent &arg ) + { + mInputCtrl->keyReleased (arg); + + MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(arg.key)); + + return true; + } + + bool InputManager::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) + { + mInputCtrl->mousePressed (arg, id); + + MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, MyGUI::MouseButton::Enum(id)); + + if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) + { + MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); + if (b) + { + MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + } + } + + return true; + } + + bool InputManager::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) + { + mInputCtrl->mouseReleased (arg, id); + + MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, MyGUI::MouseButton::Enum(id)); + + return true; + } + + bool InputManager::mouseMoved( const OIS::MouseEvent &arg ) + { + mInputCtrl->mouseMoved (arg); + + resetIdleTime (); + + if (mGuiCursorEnabled) + { + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // We keep track of our own mouse position, so that moving the mouse while in + // game mode does not move the position of the GUI cursor + mMouseX += float(arg.state.X.rel) * mUISensitivity; + mMouseY += float(arg.state.Y.rel) * mUISensitivity * mUIYMultiplier; + mMouseX = std::max(0.f, std::min(mMouseX, float(viewSize.width))); + mMouseY = std::max(0.f, std::min(mMouseY, float(viewSize.height))); + + MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), arg.state.Z.abs); + } + + if (mMouseLookEnabled) + { + resetIdleTime(); + + float x = arg.state.X.rel * mCameraSensitivity * 0.2; + float y = arg.state.Y.rel * mCameraSensitivity * 0.2 * (mInvertY ? -1 : 1) * mUIYMultiplier; + + MWBase::World *world = MWBase::Environment::get().getWorld(); + world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true); + } + + return true; + } + + void InputManager::toggleMainMenu() + { + if (mWindows.isGuiMode () && (mWindows.getMode () == MWGui::GM_MainMenu || mWindows.getMode () == MWGui::GM_Settings)) + mWindows.popGuiMode(); + else + mWindows.pushGuiMode (MWGui::GM_MainMenu); + } + + void InputManager::toggleSpell() + { + if (mWindows.isGuiMode()) return; + + MWMechanics::DrawState_ state = mPlayer.getDrawState(); + if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing) + { + mPlayer.setDrawState(MWMechanics::DrawState_Spell); + std::cout << "Player has now readied his hands for spellcasting!\n" << std::endl; + } + else + { + mPlayer.setDrawState(MWMechanics::DrawState_Nothing); + std::cout << "Player does not have any kind of attack ready now.\n" << std::endl; + } + } + + void InputManager::toggleWeapon() + { + if (mWindows.isGuiMode()) return; + + MWMechanics::DrawState_ state = mPlayer.getDrawState(); + if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) + { + mPlayer.setDrawState(MWMechanics::DrawState_Weapon); + std::cout << "Player is now drawing his weapon.\n" << std::endl; + } + else + { + mPlayer.setDrawState(MWMechanics::DrawState_Nothing); + std::cout << "Player does not have any kind of attack ready now.\n" << std::endl; + } + } + + void InputManager::screenshot() + { + mEngine.screenshot(); + + std::vector empty; + mWindows.messageBox ("Screenshot saved", empty); + } + + void InputManager::toggleInventory() + { + bool gameMode = !mWindows.isGuiMode(); + + // Toggle between game mode and inventory mode + if(gameMode) + mWindows.pushGuiMode(MWGui::GM_Inventory); + else if(mWindows.getMode() == MWGui::GM_Inventory) + mWindows.popGuiMode(); + + // .. but don't touch any other mode. + } + + void InputManager::toggleConsole() + { + bool gameMode = !mWindows.isGuiMode(); + + // Switch to console mode no matter what mode we are currently + // in, except of course if we are already in console mode + if (!gameMode) + { + if (mWindows.getMode() == MWGui::GM_Console) + mWindows.popGuiMode(); + else + mWindows.pushGuiMode(MWGui::GM_Console); + } + else + mWindows.pushGuiMode(MWGui::GM_Console); + } + + void InputManager::toggleJournal() + { + // Toggle between game mode and journal mode + bool gameMode = !mWindows.isGuiMode(); + + if(gameMode) + mWindows.pushGuiMode(MWGui::GM_Journal); + else if(mWindows.getMode() == MWGui::GM_Journal) + mWindows.popGuiMode(); + // .. but don't touch any other mode. + } + + void InputManager::quickKey (int index) + { + mWindows.activateQuickKey (index); + } + + void InputManager::showQuickKeysMenu() + { + if (!mWindows.isGuiMode ()) + mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu); + } + + void InputManager::activate() + { + mEngine.activate(); + } + + void InputManager::toggleAutoMove() + { + if (mWindows.isGuiMode()) return; + mPlayer.setAutoMove (!mPlayer.getAutoMove()); + } + + void InputManager::toggleWalking() + { + if (mWindows.isGuiMode()) return; + mPlayer.toggleRunning(); + } + + // Exit program now button (which is disabled in GUI mode) + void InputManager::exitNow() + { + if(!mWindows.isGuiMode()) + Ogre::Root::getSingleton().queueEndRendering (); + } + + void InputManager::resetIdleTime() + { + if (mTimeIdle < 0) { + MWBase::Environment::get().getWorld()->toggleVanityMode(false, false); + } + mTimeIdle = 0.f; + } + + void InputManager::updateIdleTime(float dt) + { + if (mTimeIdle >= 0.f) { + mTimeIdle += dt; + } + if (mTimeIdle > 30.f) { + MWBase::Environment::get().getWorld()->toggleVanityMode(true, false); + mTimeIdle = -1.f; + } + } + + bool InputManager::actionIsActive (int id) + { + return mInputCtrl->getChannel (id)->getValue () == 1; + } + + void InputManager::loadKeyDefaults (bool force) + { + // using hardcoded key defaults is inevitable, if we want the configuration files to stay valid + // across different versions of OpenMW (in the case where another input action is added) + std::map defaultKeyBindings; + + defaultKeyBindings[A_Activate] = OIS::KC_SPACE; + defaultKeyBindings[A_MoveBackward] = OIS::KC_S; + defaultKeyBindings[A_MoveForward] = OIS::KC_W; + defaultKeyBindings[A_MoveLeft] = OIS::KC_A; + defaultKeyBindings[A_MoveRight] = OIS::KC_D; + defaultKeyBindings[A_ToggleWeapon] = OIS::KC_F; + defaultKeyBindings[A_ToggleSpell] = OIS::KC_R; + defaultKeyBindings[A_QuickKeysMenu] = OIS::KC_F1; + defaultKeyBindings[A_Console] = OIS::KC_F2; + defaultKeyBindings[A_Crouch] = OIS::KC_LCONTROL; + defaultKeyBindings[A_AutoMove] = OIS::KC_Q; + defaultKeyBindings[A_Jump] = OIS::KC_E; + defaultKeyBindings[A_Journal] = OIS::KC_J; + defaultKeyBindings[A_Rest] = OIS::KC_T; + defaultKeyBindings[A_GameMenu] = OIS::KC_ESCAPE; + defaultKeyBindings[A_TogglePOV] = OIS::KC_TAB; + defaultKeyBindings[A_QuickKey1] = OIS::KC_1; + defaultKeyBindings[A_QuickKey2] = OIS::KC_2; + defaultKeyBindings[A_QuickKey3] = OIS::KC_3; + defaultKeyBindings[A_QuickKey4] = OIS::KC_4; + defaultKeyBindings[A_QuickKey5] = OIS::KC_5; + defaultKeyBindings[A_QuickKey6] = OIS::KC_6; + defaultKeyBindings[A_QuickKey7] = OIS::KC_7; + defaultKeyBindings[A_QuickKey8] = OIS::KC_8; + defaultKeyBindings[A_QuickKey9] = OIS::KC_9; + defaultKeyBindings[A_QuickKey10] = OIS::KC_0; + defaultKeyBindings[A_Screenshot] = OIS::KC_SYSRQ; + defaultKeyBindings[A_ToggleHUD] = OIS::KC_F12; + + std::map defaultMouseButtonBindings; + defaultMouseButtonBindings[A_Inventory] = OIS::MB_Right; + defaultMouseButtonBindings[A_Use] = OIS::MB_Left; + + for (int i = 0; i < A_Last; ++i) + { + ICS::Control* control; + bool controlExists = mInputCtrl->getChannel(i)->getControlsCount () != 0; + if (!controlExists) + { + control = new ICS::Control(boost::lexical_cast(i), false, true, 0, ICS::ICS_MAX, ICS::ICS_MAX); + mInputCtrl->addControl(control); + control->attachChannel(mInputCtrl->getChannel(i), ICS::Channel::DIRECT); + } + else + { + control = mInputCtrl->getChannel(i)->getAttachedControls ().front().control; + } + + if (!controlExists || force || + ( mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE) == OIS::KC_UNASSIGNED + && mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS + )) + { + clearAllBindings (control); + + if (defaultKeyBindings.find(i) != defaultKeyBindings.end()) + mInputCtrl->addKeyBinding(control, static_cast(defaultKeyBindings[i]), ICS::Control::INCREASE); + else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()) + mInputCtrl->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); + } + } + } + + std::string InputManager::getActionDescription (int action) + { + std::map descriptions; + + descriptions[A_Activate] = "sActivate"; + descriptions[A_MoveBackward] = "sBack"; + descriptions[A_MoveForward] = "sForward"; + descriptions[A_MoveLeft] = "sLeft"; + descriptions[A_MoveRight] = "sRight"; + descriptions[A_ToggleWeapon] = "sReady_Weapon"; + descriptions[A_ToggleSpell] = "sReady_Magic"; + descriptions[A_Console] = "sConsoleTitle"; + descriptions[A_Crouch] = "sCrouch_Sneak"; + descriptions[A_AutoMove] = "sAuto_Run"; + descriptions[A_Jump] = "sJump"; + descriptions[A_Journal] = "sJournal"; + descriptions[A_Rest] = "sRestKey"; + descriptions[A_Inventory] = "sInventory"; + descriptions[A_TogglePOV] = "sTogglePOVCmd"; + descriptions[A_QuickKeysMenu] = "sQuickMenu"; + descriptions[A_QuickKey1] = "sQuick1Cmd"; + descriptions[A_QuickKey2] = "sQuick2Cmd"; + descriptions[A_QuickKey3] = "sQuick3Cmd"; + descriptions[A_QuickKey4] = "sQuick4Cmd"; + descriptions[A_QuickKey5] = "sQuick5Cmd"; + descriptions[A_QuickKey6] = "sQuick6Cmd"; + descriptions[A_QuickKey7] = "sQuick7Cmd"; + descriptions[A_QuickKey8] = "sQuick8Cmd"; + descriptions[A_QuickKey9] = "sQuick9Cmd"; + descriptions[A_QuickKey10] = "sQuick10Cmd"; + + if (descriptions[action] == "") + return ""; // not configurable + + return "#{" + descriptions[action] + "}"; + } + + std::string InputManager::getActionBindingName (int action) + { + if (mInputCtrl->getChannel (action)->getControlsCount () == 0) + return "#{sNone}"; + + ICS::Control* c = mInputCtrl->getChannel (action)->getAttachedControls ().front().control; + + if (mInputCtrl->getKeyBinding (c, ICS::Control::INCREASE) != OIS::KC_UNASSIGNED) + return mInputCtrl->keyCodeToString (mInputCtrl->getKeyBinding (c, ICS::Control::INCREASE)); + else if (mInputCtrl->getMouseButtonBinding (c, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) + return "#{sMouse} " + boost::lexical_cast(mInputCtrl->getMouseButtonBinding (c, ICS::Control::INCREASE)); + else + return "#{sNone}"; + } + + std::vector InputManager::getActionSorting() + { + std::vector ret; + ret.push_back(A_MoveForward); + ret.push_back(A_MoveBackward); + ret.push_back(A_MoveLeft); + ret.push_back(A_MoveRight); + ret.push_back(A_TogglePOV); + ret.push_back(A_Crouch); + ret.push_back(A_Activate); + ret.push_back(A_ToggleWeapon); + ret.push_back(A_ToggleSpell); + ret.push_back(A_AutoMove); + ret.push_back(A_Jump); + ret.push_back(A_Inventory); + ret.push_back(A_Journal); + ret.push_back(A_Rest); + ret.push_back(A_Console); + ret.push_back(A_QuickKeysMenu); + ret.push_back(A_QuickKey1); + ret.push_back(A_QuickKey2); + ret.push_back(A_QuickKey3); + ret.push_back(A_QuickKey4); + ret.push_back(A_QuickKey5); + ret.push_back(A_QuickKey6); + ret.push_back(A_QuickKey7); + ret.push_back(A_QuickKey8); + ret.push_back(A_QuickKey9); + ret.push_back(A_QuickKey10); + + return ret; + } + + void InputManager::enableDetectingBindingMode (int action) + { + ICS::Control* c = mInputCtrl->getChannel (action)->getAttachedControls ().front().control; + + mInputCtrl->enableDetectingBindingState (c, ICS::Control::INCREASE); + } + + void InputManager::mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction) + { + // we don't want mouse movement bindings + return; + } + + void InputManager::keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , OIS::KeyCode key, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::keyBindingDetected (ICS, control, key, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::mouseButtonBindingDetected (ICS, control, button, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int axis, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::joystickAxisBindingDetected (ICS, control, deviceId, axis, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, control, deviceId, button, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::joystickPOVBindingDetected (ICS, control, deviceId, pov, axis, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int slider, ICS::Control::ControlChangingDirection direction) + { + clearAllBindings(control); + ICS::DetectingBindingListener::joystickSliderBindingDetected (ICS, control, deviceId, slider, direction); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + } + + void InputManager::clearAllBindings (ICS::Control* control) + { + // right now we don't really need multiple bindings for the same action, so remove all others first + if (mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE) != OIS::KC_UNASSIGNED) + mInputCtrl->removeKeyBinding (mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE)); + if (mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) + mInputCtrl->removeMouseButtonBinding (mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE)); + + /// \todo add joysticks here once they are added + } + + void InputManager::resetToDefaultBindings() + { + loadKeyDefaults(true); + } +} diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp new file mode 100644 index 0000000000..2572ec1152 --- /dev/null +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -0,0 +1,243 @@ +#ifndef _MWINPUT_MWINPUTMANAGERIMP_H +#define _MWINPUT_MWINPUTMANAGERIMP_H + +#include "../mwgui/mode.hpp" + +#include + +#include "../mwbase/inputmanager.hpp" + +namespace OEngine +{ + namespace Render + { + class OgreRenderer; + } +} + +namespace MWWorld +{ + class Player; +} + +namespace MWBase +{ + class WindowManager; +} + +namespace OMW +{ + class Engine; +} + +namespace ICS +{ + class InputControlSystem; +} + +namespace OIS +{ + class Keyboard; + class Mouse; + class InputManager; +} + +#include +#include + +#include +#include + +namespace MWInput +{ + + /** + * @brief Class that handles all input and key bindings for OpenMW. + */ + class InputManager : public MWBase::InputManager, public OIS::KeyListener, public OIS::MouseListener, public ICS::ChannelListener, public ICS::DetectingBindingListener + { + public: + InputManager(OEngine::Render::OgreRenderer &_ogre, + MWWorld::Player&_player, + MWBase::WindowManager &_windows, + bool debug, + OMW::Engine& engine, + const std::string& userFile, bool userFileExists); + + virtual ~InputManager(); + + virtual void update(float dt); + + virtual void changeInputMode(bool guiMode); + + virtual void processChangedSettings(const Settings::CategorySettingVector& changed); + + virtual void setDragDrop(bool dragDrop); + + virtual void toggleControlSwitch (const std::string& sw, bool value); + + virtual std::string getActionDescription (int action); + virtual std::string getActionBindingName (int action); + virtual int getNumActions() { return A_Last; } + virtual std::vector getActionSorting (); + virtual void enableDetectingBindingMode (int action); + virtual void resetToDefaultBindings(); + + public: + virtual bool keyPressed( const OIS::KeyEvent &arg ); + virtual bool keyReleased( const OIS::KeyEvent &arg ); + + virtual bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ); + virtual bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ); + virtual bool mouseMoved( const OIS::MouseEvent &arg ); + + virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue); + + virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction); + + virtual void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , OIS::KeyCode key, ICS::Control::ControlChangingDirection direction); + + virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction); + + virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int axis, ICS::Control::ControlChangingDirection direction); + + virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction); + + virtual void joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction); + + virtual void joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , int deviceId, int slider, ICS::Control::ControlChangingDirection direction); + + void clearAllBindings (ICS::Control* control); + + private: + OEngine::Render::OgreRenderer &mOgre; + MWWorld::Player &mPlayer; + MWBase::WindowManager &mWindows; + OMW::Engine& mEngine; + + ICS::InputControlSystem* mInputCtrl; + + OIS::Keyboard* mKeyboard; + OIS::Mouse* mMouse; + OIS::InputManager* mInputManager; + + std::string mUserFile; + + bool mDragDrop; + + bool mInvertY; + + float mCameraSensitivity; + float mUISensitivity; + float mCameraYMultiplier; + float mUIYMultiplier; + float mPreviewPOVDelay; + float mTimeIdle; + + bool mMouseLookEnabled; + bool mGuiCursorEnabled; + + float mMouseX; + float mMouseY; + + std::map mControlSwitch; + + private: + void adjustMouseRegion(int width, int height); + + void resetIdleTime(); + void updateIdleTime(float dt); + + private: + void toggleMainMenu(); + void toggleSpell(); + void toggleWeapon(); + void toggleInventory(); + void toggleConsole(); + void screenshot(); + void toggleJournal(); + void activate(); + void toggleWalking(); + void toggleAutoMove(); + void exitNow(); + + void quickKey (int index); + void showQuickKeysMenu(); + + bool actionIsActive (int id); + + void loadKeyDefaults(bool force = false); + + private: + enum Actions + { + // please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files + + A_GameMenu, + + A_Quit, // Exit the program + + A_Screenshot, // Take a screenshot + + A_Inventory, // Toggle inventory screen + + A_Console, // Toggle console screen + + A_MoveLeft, // Move player left / right + A_MoveRight, + A_MoveForward, // Forward / Backward + A_MoveBackward, + + A_Activate, + + A_Use, //Use weapon, spell, etc. + A_Jump, + A_AutoMove, //Toggle Auto-move forward + A_Rest, //Rest + A_Journal, //Journal + A_Weapon, //Draw/Sheath weapon + A_Spell, //Ready/Unready Casting + A_AlwaysRun, //Toggle Always Run + A_CycleSpellLeft, //cycling through spells + A_CycleSpellRight, + A_CycleWeaponLeft,//Cycling through weapons + A_CycleWeaponRight, + A_ToggleSneak, //Toggles Sneak, add Push-Sneak later + A_ToggleWalk, //Toggle Walking/Running + A_Crouch, + + A_QuickSave, + A_QuickLoad, + A_QuickMenu, + A_ToggleWeapon, + A_ToggleSpell, + + A_TogglePOV, + + A_QuickKey1, + A_QuickKey2, + A_QuickKey3, + A_QuickKey4, + A_QuickKey5, + A_QuickKey6, + A_QuickKey7, + A_QuickKey8, + A_QuickKey9, + A_QuickKey10, + + A_QuickKeysMenu, + + A_ToggleHUD, + + A_Last // Marker for the last item + }; + }; +} +#endif diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp similarity index 95% rename from apps/openmw/mwmechanics/mechanicsmanager.cpp rename to apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fe5485d615..2ac146c2f7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1,16 +1,15 @@ -#include "mechanicsmanager.hpp" +#include "mechanicsmanagerimp.hpp" #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" -#include "../mwgui/window_manager.hpp" - namespace MWMechanics { void MechanicsManager::buildPlayer() @@ -67,15 +66,18 @@ namespace MWMechanics static_cast (male ? attribute->male : attribute->female)); } - for (int i=0; i<7; ++i) + for (int i=0; i<27; ++i) { - int index = race->data.bonus[i].skill; - - if (index>=0 && index<27) - { - npcStats.getSkill (index).setBase ( - npcStats.getSkill (index).getBase() + race->data.bonus[i].bonus); - } + int bonus = 0; + + for (int i2=0; i2<7; ++i2) + if (race->data.bonus[i2].skill==i) + { + bonus = race->data.bonus[i2].bonus; + break; + } + + npcStats.getSkill (i).setBase (5 + bonus); } for (std::vector::const_iterator iter (race->powers.list.begin()); @@ -265,8 +267,8 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->getPlayer().getClass().name); mUpdatePlayer = false; - MWGui::WindowManager::SkillList majorSkills (5); - MWGui::WindowManager::SkillList minorSkills (5); + MWBase::WindowManager::SkillList majorSkills (5); + MWBase::WindowManager::SkillList minorSkills (5); for (int i=0; i<5; ++i) { diff --git a/apps/openmw/mwmechanics/mechanicsmanager.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp similarity index 60% rename from apps/openmw/mwmechanics/mechanicsmanager.hpp rename to apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 97bb369fda..d5fd3b6f2f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -1,8 +1,7 @@ -#ifndef GAME_MWMECHANICS_MECHANICSMANAGER_H -#define GAME_MWMECHANICS_MECHANICSMANAGER_H +#ifndef GAME_MWMECHANICS_MECHANICSMANAGERIMP_H +#define GAME_MWMECHANICS_MECHANICSMANAGERIMP_H -#include -#include +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/ptr.hpp" @@ -22,7 +21,7 @@ namespace MWWorld namespace MWMechanics { - class MechanicsManager + class MechanicsManager : public MWBase::MechanicsManager { MWWorld::Ptr mWatched; CreatureStats mWatchedCreature; @@ -38,43 +37,41 @@ namespace MWMechanics public: - MechanicsManager (); + MechanicsManager(); - void configureGUI(); - - void addActor (const MWWorld::Ptr& ptr); + virtual void addActor (const MWWorld::Ptr& ptr); ///< Register an actor for stats management - void removeActor (const MWWorld::Ptr& ptr); + virtual void removeActor (const MWWorld::Ptr& ptr); ///< Deregister an actor for stats management - void dropActors (const MWWorld::CellStore *cellStore); + virtual void dropActors (const MWWorld::CellStore *cellStore); ///< Deregister all actors in the given cell. - void watchActor (const MWWorld::Ptr& ptr); + virtual void watchActor (const MWWorld::Ptr& ptr); ///< On each update look for changes in a previously registered actor and update the /// GUI accordingly. - void update (std::vector >& movement, float duration, - bool paused); + virtual void update (std::vector >& movement, + float duration, bool paused); ///< Update actor stats and store desired velocity vectors in \a movement /// /// \param paused In game type does not currently advance (this usually means some GUI /// component is up). - void setPlayerName (const std::string& name); + virtual void setPlayerName (const std::string& name); ///< Set player name. - void setPlayerRace (const std::string& id, bool male); + virtual void setPlayerRace (const std::string& id, bool male); ///< Set player race. - void setPlayerBirthsign (const std::string& id); + virtual void setPlayerBirthsign (const std::string& id); ///< Set player birthsign. - void setPlayerClass (const std::string& id); + virtual void setPlayerClass (const std::string& id); ///< Set player class to stock class. - void setPlayerClass (const ESM::Class& class_); + virtual void setPlayerClass (const ESM::Class& class_); ///< Set player class to custom class. }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index 1ab1bb11fd..e4778be693 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -8,6 +8,8 @@ #include "../mwworld/class.hpp" #include "../mwmechanics/creaturestats.hpp" +#include + #include "npcstats.hpp" namespace MWMechanics diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index a64397d49b..415d172414 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -132,3 +132,25 @@ void Actors::update (float duration){ for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) iter->second->runAnimation(duration); } + +void +Actors::updateObjectCell(const MWWorld::Ptr &ptr) +{ + Ogre::SceneNode *node; + MWWorld::CellStore *newCell = ptr.getCell(); + + if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) { + node = mMwRoot->createChildSceneNode(); + mCellSceneNodes[newCell] = node; + } else { + node = mCellSceneNodes[newCell]; + } + node->addChild(ptr.getRefData().getBaseNode()); + if (mAllActors.find(ptr) != mAllActors.end()) { + /// \note Update key (Ptr's are compared only with refdata so mCell + /// on key is outdated), maybe redundant + Animation *anim = mAllActors[ptr]; + mAllActors.erase(ptr); + mAllActors[ptr] = anim; + } +} diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index 4b0b2e572c..073c5d51f1 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -15,7 +15,7 @@ namespace MWRender{ OEngine::Render::OgreRenderer &mRend; std::map mCellSceneNodes; Ogre::SceneNode* mMwRoot; - std::map mAllActors; + std::map mAllActors; @@ -45,6 +45,8 @@ namespace MWRender{ void update (float duration); + /// Updates containing cell for object rendering data + void updateObjectCell(const MWWorld::Ptr &ptr); }; } #endif diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 962f19a57f..e254a2f0a9 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -4,10 +4,11 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" - -#include "../mwgui/window_manager.hpp" +#include "../mwbase/windowmanager.hpp" #include "renderconst.hpp" #include "renderingmanager.hpp" @@ -269,6 +270,34 @@ void LocalMap::render(const float x, const float y, mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd); } +void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) +{ + pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle); + + Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); + + x = std::ceil((pos.x - min.x)/sSize)-1; + y = std::ceil((pos.y - min.y)/sSize)-1; + + nX = (pos.x - min.x - sSize*x)/sSize; + nY = (pos.y - min.y - sSize*y)/sSize; +} + +bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interior) +{ + std::string texName = (interior ? mInteriorName + "_" : "Cell_") + coordStr(x, y); + + if (mBuffers.find(texName) == mBuffers.end()) + return false; + + int texU = (sFogOfWarResolution-1) * nX; + int texV = (sFogOfWarResolution-1) * nY; + + Ogre::uint32 clr = mBuffers[texName][texV * sFogOfWarResolution + texU]; + uint8 alpha = (clr >> 24); + return alpha < 200; +} + void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation) { if (sFogOfWarSkip != 0) @@ -280,16 +309,14 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni // retrieve the x,y grid coordinates the player is in int x,y; - Vector3 _pos(position.x, 0, position.z); - Vector2 pos(_pos.x, _pos.z); + float u,v; + + Vector2 pos(position.x, position.z); if (mInterior) - { - pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle); - } + getInteriorMapPosition(pos, u,v, x,y); - - Vector3 playerdirection = -mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis(); + Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis(); Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); @@ -302,14 +329,10 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni } else { - x = std::ceil((pos.x - min.x)/sSize)-1; - y = std::ceil((pos.y - min.y)/sSize)-1; - MWBase::Environment::get().getWindowManager()->setInteriorMapTexture(x,y); } // convert from world coordinates to texture UV coordinates - float u,v; std::string texBaseName; if (!mInterior) { @@ -319,9 +342,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni } else { - u = (pos.x - min.x - sSize*x)/sSize; - v = (pos.y - min.y - sSize*y)/sSize; - texBaseName = mInteriorName + "_"; } diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index c5cd908fc3..056d2498a3 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -58,6 +58,18 @@ namespace MWRender */ void saveFogOfWar(MWWorld::CellStore* cell); + + /** + * Get the interior map texture index and normalized position + * on this texture, given a world position (in ogre coordinates) + */ + void getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y); + + /** + * Check if a given position is explored by the player (i.e. not obscured by fog of war) + */ + bool isPositionExplored (float nX, float nY, int x, int y, bool interior); + private: OEngine::Render::OgreRenderer* mRendering; MWRender::RenderingManager* mRenderingManager; diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index ecd1328c44..a76ef09d1f 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -11,6 +11,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/class.hpp" #include "renderconst.hpp" @@ -474,3 +475,23 @@ void Objects::rebuildStaticGeometry() it->second->build(); } } + +void +Objects::updateObjectCell(const MWWorld::Ptr &ptr) +{ + Ogre::SceneNode *node; + MWWorld::CellStore *newCell = ptr.getCell(); + + if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) { + node = mMwRoot->createChildSceneNode(); + mCellSceneNodes[newCell] = node; + } else { + node = mCellSceneNodes[newCell]; + } + node->addChild(ptr.getRefData().getBaseNode()); + + /// \note Still unaware how to move aabb and static w/o full rebuild, + /// moving static objects may cause problems + insertMesh(ptr, MWWorld::Class::get(ptr).getModel(ptr)); +} + diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 443f25ecf3..8594e4fe40 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -95,6 +95,9 @@ public: void setMwRoot(Ogre::SceneNode* root); void rebuildStaticGeometry(); + + /// Updates containing cell for object rendering data + void updateObjectCell(const MWWorld::Ptr &ptr); }; } #endif diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 27ae28e14e..3ccc080221 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -1,34 +1,365 @@ - #include "player.hpp" #include +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" + +#include "../mwworld/ptr.hpp" +#include "../mwworld/refdata.hpp" + +#include "npcanimation.hpp" namespace MWRender { Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) - : mCamera (camera), mNode (node) - {} - - void Player::setRot(float x, float y, float z) + : mCamera(camera), + mPlayerNode(node), + mCameraNode(mPlayerNode->createChildSceneNode()), + mFirstPersonView(true), + mPreviewMode(false), + mFreeLook(true), + mHeight(128.f), + mCameraDistance(300.f), + mDistanceAdjusted(false) { - Ogre::SceneNode *sceneNode = mNode; - Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); - Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); + mVanity.enabled = false; + mVanity.allowed = true; + mVanity.forced = false; - // we are only interested in X and Y rotation + mCameraNode->attachObject(mCamera); + mCameraNode->setPosition(0.f, 0.f, mHeight); - // Rotate around X axis - Ogre::Quaternion xr(Ogre::Radian(x), Ogre::Vector3::UNIT_X); + mPreviewCam.yaw = 0.f; + mPreviewCam.offset = 400.f; + } + + bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) + { + if (mVanity.enabled) { + toggleVanityMode(false); + } - // Rotate around Y axis - Ogre::Quaternion yr(Ogre::Radian(-z), Ogre::Vector3::UNIT_Y); + Ogre::Vector3 trueRot = rot; - pitchNode->setOrientation(xr); - yawNode->setOrientation(yr); + /// \note rotate player on forced vanity + if (mVanity.forced) { + if (mFreeLook) { + float diff = (adjust) ? rot.z : mMainCam.yaw - rot.z; + + mVanity.enabled = false; + rotateCamera(rot, adjust); + mVanity.enabled = true; + + compensateYaw(diff); + } + trueRot.z = 0.f; + } + + if (mFreeLook || mVanity.enabled || mPreviewMode) { + rotateCamera(trueRot, adjust); + } + + /// \note if vanity mode is forced by TVM then rotate player + return (!mVanity.enabled && !mPreviewMode) || mVanity.forced; + } + + void Player::rotateCamera(const Ogre::Vector3 &rot, bool adjust) + { + if (adjust) { + setYaw(getYaw() + rot.z); + setPitch(getPitch() + rot.x); + } else { + setYaw(rot.z); + setPitch(rot.x); + } + Ogre::Quaternion xr( + Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), + Ogre::Vector3::UNIT_X + ); + Ogre::Quaternion zr( + Ogre::Radian(getYaw()), + Ogre::Vector3::NEGATIVE_UNIT_Z + ); + if (!mVanity.enabled && !mPreviewMode) { + mPlayerNode->setOrientation(zr); + mCameraNode->setOrientation(xr); + } else { + mCameraNode->setOrientation(zr * xr); + } + updateListener(); } std::string Player::getHandle() const { - return mNode->getName(); + return mPlayerNode->getName(); + } + + void Player::attachTo(const MWWorld::Ptr &ptr) + { + ptr.getRefData().setBaseNode(mPlayerNode); + } + + void Player::updateListener() + { + Ogre::Vector3 pos = mCamera->getRealPosition(); + Ogre::Vector3 dir = mCamera->getRealDirection(); + + Ogre::Real xch; + xch = pos.y, pos.y = -pos.z, pos.z = xch; + xch = dir.y, dir.y = -dir.z, dir.z = xch; + + MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir); + } + + void Player::update(float duration) + { + // only show the crosshair in game mode and in first person mode. + MWBase::Environment::get().getWindowManager ()->showCrosshair + (!MWBase::Environment::get().getWindowManager ()->isGuiMode () && (mFirstPersonView && !mVanity.enabled && !mPreviewMode)); + + if (mAnimation) { + mAnimation->runAnimation(duration); + } + mPlayerNode->setVisible( + mVanity.enabled || mPreviewMode || !mFirstPersonView, + false + ); + + if (mFirstPersonView && !mVanity.enabled) { + return; + } + if (mVanity.enabled) { + Ogre::Vector3 rot(0.f, 0.f, 0.f); + rot.z = Ogre::Degree(3.f * duration).valueRadians(); + rotateCamera(rot, true); + } + } + + void Player::toggleViewMode() + { + mFirstPersonView = !mFirstPersonView; + if (mFirstPersonView) { + mCamera->setPosition(0.f, 0.f, 0.f); + setLowHeight(false); + } else { + mCamera->setPosition(0.f, 0.f, mCameraDistance); + setLowHeight(true); + } + } + + void Player::allowVanityMode(bool allow) + { + if (!allow && mVanity.enabled && !mVanity.forced) { + toggleVanityMode(false); + } + mVanity.allowed = allow; + } + + bool Player::toggleVanityMode(bool enable, bool force) + { + if ((mVanity.forced && !force) || + (!mVanity.allowed && (force || enable))) + { + return false; + } else if (mVanity.enabled == enable) { + return true; + } + mVanity.enabled = enable; + mVanity.forced = force && enable; + + float offset = mPreviewCam.offset; + Ogre::Vector3 rot(0.f, 0.f, 0.f); + if (mVanity.enabled) { + rot.x = Ogre::Degree(-30.f).valueRadians(); + mMainCam.offset = mCamera->getPosition().z; + + setLowHeight(true); + } else { + rot.x = getPitch(); + offset = mMainCam.offset; + + setLowHeight(!mFirstPersonView); + } + rot.z = getYaw(); + mCamera->setPosition(0.f, 0.f, offset); + rotateCamera(rot, false); + + return true; + } + + void Player::togglePreviewMode(bool enable) + { + if (mPreviewMode == enable) { + return; + } + mPreviewMode = enable; + float offset = mCamera->getPosition().z; + if (mPreviewMode) { + mMainCam.offset = offset; + offset = mPreviewCam.offset; + + setLowHeight(true); + } else { + mPreviewCam.offset = offset; + offset = mMainCam.offset; + + setLowHeight(!mFirstPersonView); + } + mCamera->setPosition(0.f, 0.f, offset); + rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); + } + + float Player::getYaw() + { + if (mVanity.enabled || mPreviewMode) { + return mPreviewCam.yaw; + } + return mMainCam.yaw; + } + + void Player::setYaw(float angle) + { + if (angle > Ogre::Math::PI) { + angle -= Ogre::Math::TWO_PI; + } else if (angle < -Ogre::Math::PI) { + angle += Ogre::Math::TWO_PI; + } + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.yaw = angle; + } else { + mMainCam.yaw = angle; + } + } + + float Player::getPitch() + { + if (mVanity.enabled || mPreviewMode) { + return mPreviewCam.pitch; + } + return mMainCam.pitch; + } + + void Player::setPitch(float angle) + { + float limit = Ogre::Math::HALF_PI; + if (mVanity.forced || mPreviewMode) { + limit /= 2; + } + if (angle > limit) { + angle = limit - 0.01; + } else if (angle < -limit) { + angle = -limit + 0.01; + } + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.pitch = angle; + } else { + mMainCam.pitch = angle; + } + } + + void Player::setCameraDistance(float dist, bool adjust, bool override) + { + if (mFirstPersonView && !mPreviewMode && !mVanity.enabled) { + return; + } + Ogre::Vector3 v(0.f, 0.f, dist); + if (adjust) { + v += mCamera->getPosition(); + } + if (v.z > 800.f) { + v.z = 800.f; + } else if (v.z < 10.f) { + v.z = 10.f; + } + mCamera->setPosition(v); + + if (override) { + if (mVanity.enabled || mPreviewMode) { + mPreviewCam.offset = v.z; + } else if (!mFirstPersonView) { + mCameraDistance = v.z; + } + } else { + mDistanceAdjusted = true; + } + } + + void Player::setCameraDistance() + { + if (mDistanceAdjusted) { + if (mVanity.enabled || mPreviewMode) { + mCamera->setPosition(0, 0, mPreviewCam.offset); + } else if (!mFirstPersonView) { + mCamera->setPosition(0, 0, mCameraDistance); + } + } + mDistanceAdjusted = false; + } + + void Player::setAnimation(NpcAnimation *anim) + { + mAnimation = anim; + } + + void Player::setHeight(float height) + { + mHeight = height; + mCameraNode->setPosition(0.f, 0.f, mHeight); + } + + float Player::getHeight() + { + return mHeight * mPlayerNode->getScale().z; + } + + bool Player::getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera) + { + float xch; + camera = mCamera->getRealPosition(); + xch = camera.z, camera.z = camera.y, camera.y = -xch; + player = mPlayerNode->getPosition(); + + return mFirstPersonView && !mVanity.enabled && !mPreviewMode; + } + + Ogre::Vector3 Player::getPosition() + { + return mPlayerNode->getPosition(); + } + + void Player::getSightAngles(float &pitch, float &yaw) + { + pitch = mMainCam.pitch; + yaw = mMainCam.yaw; + } + + void Player::compensateYaw(float diff) + { + mPreviewCam.yaw -= diff; + Ogre::Quaternion zr( + Ogre::Radian(mPreviewCam.yaw), + Ogre::Vector3::NEGATIVE_UNIT_Z + ); + Ogre::Quaternion xr( + Ogre::Radian(mPreviewCam.pitch), + Ogre::Vector3::UNIT_X); + mCameraNode->setOrientation(zr * xr); + } + + void Player::togglePlayerLooking(bool enable) + { + mFreeLook = enable; + } + + void Player::setLowHeight(bool low) + { + if (low) { + mCameraNode->setPosition(0.f, 0.f, mHeight * 0.85); + } else { + mCameraNode->setPosition(0.f, 0.f, mHeight); + } } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 0ba936f6f9..8dd313b7fa 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -5,29 +5,108 @@ namespace Ogre { + class Vector3; class Camera; class SceneNode; } +namespace MWWorld +{ + class Ptr; +} + namespace MWRender { + class NpcAnimation; /// \brief Player character rendering and camera control class Player { + struct CamData { + float pitch, yaw, offset; + }; + Ogre::Camera *mCamera; - Ogre::SceneNode* mNode; - public: + Ogre::SceneNode *mPlayerNode; + Ogre::SceneNode *mCameraNode; - Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); + NpcAnimation *mAnimation; - Ogre::Camera *getCamera() { return mCamera; } + bool mFirstPersonView; + bool mPreviewMode; + bool mFreeLook; - /// Set where the player is looking at. Uses Morrowind (euler) angles - void setRot(float x, float y, float z); + struct { + bool enabled, allowed, forced; + } mVanity; - std::string getHandle() const; - Ogre::SceneNode* getNode() {return mNode;} + float mHeight, mCameraDistance; + CamData mMainCam, mPreviewCam; + + bool mDistanceAdjusted; + + /// Updates sound manager listener data + void updateListener(); + + void rotateCamera(const Ogre::Vector3 &rot, bool adjust); + + float getYaw(); + void setYaw(float angle); + + float getPitch(); + void setPitch(float angle); + + void compensateYaw(float diff); + + void setLowHeight(bool low = true); + + public: + + Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); + + /// Set where the player is looking at. Uses Morrowind (euler) angles + /// \param rot Rotation angles in radians + /// \return true if player object needs to bo rotated physically + bool rotate(const Ogre::Vector3 &rot, bool adjust); + + std::string getHandle() const; + + /// Attach camera to object + /// \note there is no protection from attaching the same camera to + /// several different objects + void attachTo(const MWWorld::Ptr &); + + void toggleViewMode(); + + bool toggleVanityMode(bool enable, bool force = false); + void allowVanityMode(bool allow); + + void togglePreviewMode(bool enable); + + void update(float duration); + + /// Set camera distance for current mode. Don't work on 1st person view. + /// \param adjust Indicates should distance be adjusted or set. + /// \param override If true new distance will be used as default. + /// If false, default distance can be restored with setCameraDistance(). + void setCameraDistance(float dist, bool adjust = false, bool override = true); + + /// Restore default camera distance for current mode. + void setCameraDistance(); + + void setAnimation(MWRender::NpcAnimation *anim); + + void setHeight(float height); + float getHeight(); + + /// Stores player and camera world positions in passed arguments + /// \return true if camera at the eye-place + bool getPosition(Ogre::Vector3 &player, Ogre::Vector3 &camera); + Ogre::Vector3 getPosition(); + + void getSightAngles(float &pitch, float &yaw); + + void togglePlayerLooking(bool enable); }; } diff --git a/apps/openmw/mwrender/renderinginterface.hpp b/apps/openmw/mwrender/renderinginterface.hpp index 03935bef60..8ae2c0f8f9 100644 --- a/apps/openmw/mwrender/renderinginterface.hpp +++ b/apps/openmw/mwrender/renderinginterface.hpp @@ -1,16 +1,17 @@ #ifndef _GAME_RENDERING_INTERFACE_H #define _GAME_RENDERING_INTERFACE_H -namespace MWRender{ - class Objects; - class Actors; - class Player; + +namespace MWRender +{ + class Objects; + class Actors; -class RenderingInterface{ + class RenderingInterface + { public: virtual MWRender::Objects& getObjects() = 0; - virtual MWRender::Player& getPlayer() = 0; virtual MWRender::Actors& getActors() = 0; virtual ~RenderingInterface(){}; }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 9eb08d77d7..edeb0fe127 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -18,21 +18,22 @@ #include #include +#include #include #include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwbase/environment.hpp" +#include "../mwbase/inputmanager.hpp" // FIXME +#include "../mwbase/windowmanager.hpp" // FIXME #include "../mwworld/ptr.hpp" #include "../mwworld/player.hpp" -#include "../mwgui/window_manager.hpp" // FIXME -#include "../mwinput/inputmanager.hpp" // FIXME - #include "shadows.hpp" #include "localmap.hpp" #include "water.hpp" #include "compositors.hpp" +#include "npcanimation.hpp" using namespace MWRender; using namespace Ogre; @@ -40,7 +41,7 @@ using namespace Ogre; namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine) - :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) + :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine) { // select best shader mode bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); @@ -130,14 +131,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const SceneNode *rt = mRendering.getScene()->getRootSceneNode(); mMwRoot = rt->createChildSceneNode(); mMwRoot->pitch(Degree(-90)); + mObjects.setMwRoot(mMwRoot); mActors.setMwRoot(mMwRoot); Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player"); - playerNode->pitch(Degree(90)); - Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); - Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); - cameraPitchNode->attachObject(mRendering.getCamera()); + mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mShadows = new Shadows(&mRendering); @@ -147,7 +146,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); - mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mSun = 0; mDebugging = new Debugging(mMwRoot, engine); @@ -183,10 +181,6 @@ MWRender::Actors& RenderingManager::getActors(){ return mActors; } -MWRender::Player& RenderingManager::getPlayer(){ - return (*mPlayer); -} - OEngine::Render::Fader* RenderingManager::getFader() { return mRendering.getFader(); @@ -251,14 +245,73 @@ void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale){ } -void RenderingManager::rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation){ -} -void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store){ +bool +RenderingManager::rotateObject( + const MWWorld::Ptr &ptr, + Ogre::Vector3 &rot, + bool adjust) +{ + bool isActive = ptr.getRefData().getBaseNode() != 0; + bool isPlayer = isActive && ptr.getRefData().getHandle() == "player"; + bool force = true; + + if (isPlayer) { + force = mPlayer->rotate(rot, adjust); + } + MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); + if (adjust) { + /// \note Stored and passed in radians + float *f = ptr.getRefData().getPosition().rot; + rot.x += f[0], rot.y += f[1], rot.z += f[2]; + } + if (!isPlayer && isActive) { + Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); + + ptr.getRefData().getBaseNode()->setOrientation(xr * yr * zr); + } + return force; } -void RenderingManager::update (float duration){ +void +RenderingManager::moveObjectToCell( + const MWWorld::Ptr& ptr, + const Ogre::Vector3& pos, + MWWorld::CellStore *store) +{ + Ogre::SceneNode *child = + mRendering.getScene()->getSceneNode(ptr.getRefData().getHandle()); + + Ogre::SceneNode *parent = child->getParentSceneNode(); + parent->removeChild(child); + + if (MWWorld::Class::get(ptr).isActor()) { + mActors.updateObjectCell(ptr); + } else { + mObjects.updateObjectCell(ptr); + } + child->setPosition(pos); +} + +void RenderingManager::update (float duration) +{ + Ogre::Vector3 orig, dest; + mPlayer->setCameraDistance(); + if (!mPlayer->getPosition(orig, dest)) { + orig.z += mPlayer->getHeight() * mMwRoot->getScale().z; + + btVector3 btOrig(orig.x, orig.y, orig.z); + btVector3 btDest(dest.x, dest.y, dest.z); + std::pair test = + mPhysicsEngine->rayTest(btOrig, btDest); + if (!test.first.empty()) { + mPlayer->setCameraDistance(test.second * orig.distance(dest), false, false); + } + } + mPlayer->update(duration); mActors.update (duration); mObjects.update (duration); @@ -271,7 +324,23 @@ void RenderingManager::update (float duration){ mRendering.update(duration); - mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() ); + MWWorld::RefData &data = + MWBase::Environment::get() + .getWorld() + ->getPlayer() + .getPlayer() + .getRefData(); + + float *fpos = data.getPosition().pos; + + /// \note only for LocalMap::updatePlayer() + Ogre::Vector3 pos(fpos[0], -fpos[2], -fpos[1]); + + Ogre::SceneNode *node = data.getBaseNode(); + Ogre::Quaternion orient = + node->convertLocalToWorldOrientation(node->_getDerivedOrientation()); + + mLocalMap->updatePlayer(pos, orient); if (mWater) { Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); @@ -732,6 +801,7 @@ void RenderingManager::windowResized(Ogre::RenderWindow* rw) void RenderingManager::windowClosed(Ogre::RenderWindow* rw) { + Ogre::Root::getSingleton ().queueEndRendering (); } bool RenderingManager::waterShaderSupported() @@ -770,4 +840,37 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i } } +void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr) +{ + mPlayer->attachTo(ptr); +} + +void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) +{ + MWRender::NpcAnimation *anim = + new MWRender::NpcAnimation( + ptr, + mRendering, + MWWorld::Class::get(ptr).getInventoryStore(ptr) + ); + mPlayer->setAnimation(anim); +} + +void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) +{ + eyepos = mPlayer->getPosition(); + eyepos.z += mPlayer->getHeight(); + mPlayer->getSightAngles(pitch, yaw); +} + +void RenderingManager::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) +{ + return mLocalMap->getInteriorMapPosition (position, nX, nY, x, y); +} + +bool RenderingManager::isPositionExplored (float nX, float nY, int x, int y, bool interior) +{ + return mLocalMap->isPositionExplored(nX, nY, x, y, interior); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 12cbee9b87..de24491504 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -56,11 +56,30 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine); virtual ~RenderingManager(); + void togglePOV() { + mPlayer->toggleViewMode(); + } + void togglePreviewMode(bool enable) { + mPlayer->togglePreviewMode(enable); + } - virtual MWRender::Player& getPlayer(); /// \todo move this to private again as soon as - /// MWWorld::Player has been rewritten to not need access - /// to internal details of the rendering system anymore + bool toggleVanityMode(bool enable, bool force) { + return mPlayer->toggleVanityMode(enable, force); + } + + void allowVanityMode(bool allow) { + mPlayer->allowVanityMode(allow); + } + + void togglePlayerLooking(bool enable) { + mPlayer->togglePlayerLooking(enable); + } + + void getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); + + void attachCameraTo(const MWWorld::Ptr &ptr); + void renderPlayer(const MWWorld::Ptr &ptr); SkyManager* getSkyManager(); Compositors* getCompositors(); @@ -89,11 +108,17 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position); void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale); - void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation); + + /// Rotates object accordingly to its type + /// \param rot euler angles in radians + /// \param adjust indicates should rotation be set or adjusted + /// \return true if object needs to be rotated physically + bool rotateObject (const MWWorld::Ptr& ptr, Ogre::Vector3 &rot, bool adjust = false); void setWaterHeight(const float height); void toggleWater(); + /// Moves object rendering part to proper container /// \param store Cell the object was in previously (\a ptr has already been updated to the new cell). void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::CellStore *store); @@ -159,6 +184,12 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList static bool waterShaderSupported(); + virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y); + ///< see MWRender::LocalMap::getInteriorMapPosition + + virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior); + ///< see MWRender::LocalMap::isPositionExplored + protected: virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 9e551ba2a8..eba605d0c2 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -280,7 +280,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mMoonRed(false) { mSceneMgr = pMwRoot->getCreator(); - mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); + mRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates mRootNode->setInheritOrientation(false); } @@ -405,6 +405,9 @@ void SkyManager::update(float duration) { if (!mEnabled) return; + mCamera->getParentSceneNode ()->needUpdate (); + mRootNode->setPosition(mCamera->getDerivedPosition()); + // UV Scroll the clouds mCloudAnimationTimer += duration * mCloudSpeed * (MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", @@ -666,12 +669,13 @@ Ogre::SceneNode* SkyManager::getSunNode() void SkyManager::setSkyPosition(const Ogre::Vector3& position) { - mRootNode->_setDerivedPosition(position); + mRootNode->setPosition(position); } void SkyManager::resetSkyPosition() { - mRootNode->setPosition(0,0,0); + mCamera->getParentSceneNode ()->needUpdate (); + mRootNode->setPosition(mCamera->getDerivedPosition()); } void SkyManager::scaleSky(float scale) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index d5b93b7cbe..e79f308cd5 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -32,7 +32,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), mReflectionRenderActive(false), mRendering(rend), - mOldFarClip(0), mOldFarClip2(0), mWaterTimer(0.f) { mSky = rend->getSkyManager(); @@ -207,6 +206,7 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) { if (evt.source == mReflectionTarget) { + mCamera->getParentSceneNode ()->needUpdate (); mReflectionCamera->setOrientation(mCamera->getDerivedOrientation()); mReflectionCamera->setPosition(mCamera->getDerivedPosition()); mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance()); @@ -215,11 +215,9 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) mReflectionCamera->setFOVy(mCamera->getFOVy()); mReflectionRenderActive = true; - /// \todo the reflection render (and probably all renderingmanager-updates) lag behind 1 camera frame for some reason Vector3 pos = mCamera->getRealPosition(); pos.y = mTop*2 - pos.y; mSky->setSkyPosition(pos); - mSky->scaleSky(mCamera->getFarClipDistance() / 50.f); mReflectionCamera->enableReflection(mWaterPlane); } } @@ -229,7 +227,6 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) if (evt.source == mReflectionTarget) { mSky->resetSkyPosition(); - mSky->scaleSky(1); mReflectionCamera->disableReflection(); mReflectionCamera->disableCustomNearClipPlane(); mReflectionRenderActive = false; @@ -269,34 +266,19 @@ void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &in // We don't want the sky to get clipped by custom near clip plane (the water plane) if (queueGroupId < 20 && mReflectionRenderActive) { - mOldFarClip = mReflectionCamera->getFarClipDistance (); mReflectionCamera->disableCustomNearClipPlane(); - mReflectionCamera->setFarClipDistance (1000000000); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } - else if (queueGroupId == RQG_UnderWater) - {/* - mOldFarClip2 = mCamera->getFarClipDistance (); - mCamera->setFarClipDistance (1000000000); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); - */} } void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) { if (queueGroupId < 20 && mReflectionRenderActive) { - mReflectionCamera->setFarClipDistance (mOldFarClip); if (!mIsUnderwater) mReflectionCamera->enableCustomNearClipPlane(mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } - if (queueGroupId == RQG_UnderWater) - { - /* - mCamera->setFarClipDistance (mOldFarClip2); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); - */} } void Water::update(float dt) diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index f56ba7410c..dcb76533b0 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -50,9 +50,6 @@ namespace MWRender { bool mToggled; int mTop; - int mOldFarClip; - int mOldFarClip2; - float mWaterTimer; bool mReflectionRenderActive; diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 57e786b118..139a5cc6cf 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -3,14 +3,15 @@ #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/scriptmanager.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/class.hpp" -#include "scriptmanager.hpp" - namespace MWScript { CompilerContext::CompilerContext (Type type) diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 084698c5b5..bd14e7b8dd 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -8,19 +8,16 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/inputmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" #include "../mwmechanics/npcstats.hpp" -#include "../mwinput/inputmanager.hpp" - #include "interpretercontext.hpp" #include "ref.hpp" -#include - namespace MWScript { namespace Control @@ -41,11 +38,6 @@ namespace MWScript MWBase::Environment::get() .getInputManager() ->toggleControlSwitch(mControl, mEnable); - - if (mEnable) - std::cout << "enable: " << mControl << std::endl; - else - std::cout << "disable: " << mControl << std::endl; } }; diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index ec8ab59b41..21c21acf00 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -7,8 +7,9 @@ #include #include -#include "../mwdialogue/journal.hpp" -#include "../mwdialogue/dialoguemanager.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/dialoguemanager.hpp" +#include "../mwbase/journal.hpp" #include "interpretercontext.hpp" #include "ref.hpp" @@ -84,7 +85,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { - MWDialogue::DialogueManager* dialogue = MWBase::Environment::get().getDialogueManager(); + MWBase::DialogueManager* dialogue = MWBase::Environment::get().getDialogueManager(); while(arg0>0) { std::string question = runtime.getStringLiteral (runtime[0].mInteger); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 1ea5f8e3ec..dbc8159d18 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -181,4 +181,5 @@ op 0x2000170: user4, explicit reference (console only, requires --script-console op 0x2000171: user4 (implicit reference, console only, requires --script-console switch) op 0x2000172: GetStartingAngle op 0x2000173: GetStartingAngle, explicit reference -opcodes 0x2000174-0x3ffffff unused +op 0x2000174: ToggleVanityMode +opcodes 0x2000175-0x3ffffff unused diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 3f4cec7235..6407bf0cbb 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -6,13 +6,15 @@ #include #include +#include "../mwbase/environment.hpp" +#include "../mwbase/scriptmanager.hpp" + #include "interpretercontext.hpp" -#include "scriptmanager.hpp" namespace MWScript { - GlobalScripts::GlobalScripts (const ESMS::ESMStore& store, ScriptManager& scriptManager) - : mStore (store), mScriptManager (scriptManager) + GlobalScripts::GlobalScripts (const ESMS::ESMStore& store) + : mStore (store) { addScript ("Main"); @@ -63,9 +65,8 @@ namespace MWScript { MWScript::InterpreterContext interpreterContext ( &iter->second.second, MWWorld::Ptr()); - mScriptManager.run (iter->first, interpreterContext); + MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext); } } - } } diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 3d62e4d7a0..cc2f7ffdd4 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -13,17 +13,14 @@ namespace ESMS namespace MWScript { - class ScriptManager; - class GlobalScripts { const ESMS::ESMStore& mStore; - ScriptManager& mScriptManager; std::map > mScripts; // running, local variables public: - GlobalScripts (const ESMS::ESMStore& store, ScriptManager& scriptManager); + GlobalScripts (const ESMS::ESMStore& store); void addScript (const std::string& name); diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 8e5897298b..d740e5feba 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -8,9 +8,7 @@ #include #include "../mwbase/environment.hpp" - -#include "../mwgui/window_manager.hpp" -#include "../mwinput/inputmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "interpretercontext.hpp" diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 3a824473e9..075ac56462 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -5,20 +5,18 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/scriptmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" -#include "../mwgui/window_manager.hpp" - -#include "../mwinput/inputmanager.hpp" - #include "locals.hpp" #include "globalscripts.hpp" -#include "scriptmanager.hpp" namespace MWScript { diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 0c328e0da9..864c1a1eed 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -207,6 +207,32 @@ namespace MWScript } }; + class OpToggleVanityMode : public Interpreter::Opcode0 + { + static bool sActivate; + + public: + + virtual void execute(Interpreter::Runtime &runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + MWBase::World *world = + MWBase::Environment::get().getWorld(); + + if (world->toggleVanityMode(sActivate, true)) { + context.report( + (sActivate) ? "Vanity Mode -> On" : "Vanity Mode -> Off" + ); + sActivate = !sActivate; + } else { + context.report("Vanity Mode -> No"); + } + } + }; + bool OpToggleVanityMode::sActivate = true; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -222,6 +248,7 @@ namespace MWScript const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; const int opcodeDontSaveObject = 0x2000153; + const int opcodeToggleVanityMode = 0x2000174; void registerExtensions (Compiler::Extensions& extensions) { @@ -244,6 +271,8 @@ namespace MWScript extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); + extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode); + extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -263,6 +292,7 @@ namespace MWScript interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject); + interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode); } } } diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp similarity index 98% rename from apps/openmw/mwscript/scriptmanager.cpp rename to apps/openmw/mwscript/scriptmanagerimp.cpp index d8bd269c69..0b33d43fa7 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -1,5 +1,5 @@ -#include "scriptmanager.hpp" +#include "scriptmanagerimp.hpp" #include #include @@ -21,7 +21,7 @@ namespace MWScript Compiler::Context& compilerContext) : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext), - mOpcodesInstalled (false), mGlobalScripts (store, *this) + mOpcodesInstalled (false), mGlobalScripts (store) {} bool ScriptManager::compile (const std::string& name) diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp similarity index 75% rename from apps/openmw/mwscript/scriptmanager.hpp rename to apps/openmw/mwscript/scriptmanagerimp.hpp index a466f903dd..bacc232b2c 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -10,6 +10,8 @@ #include #include +#include "../mwbase/scriptmanager.hpp" + #include "globalscripts.hpp" namespace ESMS @@ -30,7 +32,7 @@ namespace Interpreter namespace MWScript { - class ScriptManager + class ScriptManager : public MWBase::ScriptManager { Compiler::StreamErrorHandler mErrorHandler; const ESMS::ESMStore& mStore; @@ -51,23 +53,24 @@ namespace MWScript ScriptManager (const ESMS::ESMStore& store, bool verbose, Compiler::Context& compilerContext); - void run (const std::string& name, Interpreter::Context& interpreterContext); + virtual void run (const std::string& name, Interpreter::Context& interpreterContext); ///< Run the script with the given name (compile first, if not compiled yet) - bool compile (const std::string& name); + virtual bool compile (const std::string& name); ///< Compile script with the given namen /// \return Success? - std::pair compileAll(); + virtual std::pair compileAll(); ///< Compile all scripts /// \return count, success - Compiler::Locals& getLocals (const std::string& name); + virtual Compiler::Locals& getLocals (const std::string& name); ///< Return locals for script \a name. - GlobalScripts& getGlobalScripts(); + virtual GlobalScripts& getGlobalScripts(); - int getLocalIndex (const std::string& scriptId, const std::string& variable, char type); + virtual int getLocalIndex (const std::string& scriptId, const std::string& variable, + char type); ///< Return index of the variable of the given name and type in the given script. Will /// throw an exception, if there is no such script or variable or the type does not match. }; diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index 3e05d72d3c..35e66241eb 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -9,8 +9,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" - -#include "../mwsound/soundmanager.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "interpretercontext.hpp" #include "ref.hpp" @@ -38,7 +38,9 @@ namespace MWScript runtime.pop(); MWBase::Environment::get().getSoundManager()->say (ptr, file); - context.messageBox (text); + + if (MWBase::Environment::get().getWindowManager ()->getSubtitlesEnabled()) + context.messageBox (text); } }; @@ -116,7 +118,7 @@ namespace MWScript std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWSound::Play_Loop : 0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWBase::SoundManager::Play_Loop : 0); } }; @@ -142,7 +144,7 @@ namespace MWScript Interpreter::Type_Float pitch = runtime[0].mFloat; runtime.pop(); - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, volume, pitch, mLoop ? MWSound::Play_Loop : 0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, volume, pitch, mLoop ? MWBase::SoundManager::Play_Loop : 0); } }; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 0cbbe8398e..5113c9dbff 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -16,6 +16,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/dialoguemanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -26,7 +27,6 @@ #include "interpretercontext.hpp" #include "ref.hpp" -#include "../mwdialogue/dialoguemanager.hpp" namespace MWScript { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index ac4baa8b29..e5169d878b 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -8,7 +8,7 @@ #include "openal_output.hpp" #include "sound_decoder.hpp" #include "sound.hpp" -#include "soundmanager.hpp" +#include "soundmanagerimp.hpp" #ifndef ALC_ALL_DEVICES_SPECIFIER #define ALC_ALL_DEVICES_SPECIFIER 0x1013 @@ -263,7 +263,7 @@ void OpenAL_SoundStream::update() { ALfloat gain = mVolume*mBaseVolume; ALfloat pitch = mPitch; - if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -400,7 +400,7 @@ void OpenAL_Sound::update() { ALfloat gain = mVolume*mBaseVolume; ALfloat pitch = mPitch; - if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -420,7 +420,7 @@ void OpenAL_Sound3D::update() ALfloat pitch = mPitch; if(mPos.squaredDistance(mOutput.mPos) > mMaxDistance*mMaxDistance) gain = 0.0f; - else if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + else if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) { gain *= 0.9f; pitch *= 0.7f; @@ -642,7 +642,7 @@ void OpenAL_Output::bufferFinished(ALuint buf) } -SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, int flags) +MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, int flags) { boost::shared_ptr sound; ALuint src=0, buf=0; @@ -674,7 +674,7 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float alSourcef(src, AL_MAX_DISTANCE, 1000.0f); alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); - if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) { volume *= 0.9f; pitch *= 0.7f; @@ -683,7 +683,7 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float alSourcef(src, AL_PITCH, pitch); alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE); + alSourcei(src, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); throwALerror(); alSourcei(src, AL_BUFFER, buf); @@ -693,7 +693,7 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float return sound; } -SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, +MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, float min, float max, int flags) { boost::shared_ptr sound; @@ -726,7 +726,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector alSourcef(src, AL_MAX_DISTANCE, max); alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f); - if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) { volume *= 0.9f; pitch *= 0.7f; @@ -736,7 +736,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector alSourcef(src, AL_PITCH, pitch); alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE); - alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE); + alSourcei(src, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE); throwALerror(); alSourcei(src, AL_BUFFER, buf); @@ -747,7 +747,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector } -SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch, int flags) +MWBase::SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch, int flags) { boost::shared_ptr sound; ALuint src; @@ -759,7 +759,7 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa try { - if((flags&Play_Loop)) + if((flags&MWBase::SoundManager::Play_Loop)) std::cout <<"Warning: cannot loop stream "<open(fname); @@ -779,7 +779,7 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa alSourcef(src, AL_MAX_DISTANCE, 1000.0f); alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); - if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater) { volume *= 0.9f; pitch *= 0.7f; diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index d62d20286a..90917c53c7 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -42,10 +42,10 @@ namespace MWSound virtual void init(const std::string &devname=""); virtual void deinit(); - virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags); - virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, + virtual MWBase::SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags); + virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, float min, float max, int flags); - virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags); + virtual MWBase::SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags); virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 0cba6abca4..729147f75a 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -3,7 +3,7 @@ #include -#include "soundmanager.hpp" +#include "soundmanagerimp.hpp" namespace MWSound { @@ -35,7 +35,7 @@ namespace MWSound , mPitch(1.0f) , mMinDistance(20.0f) /* 1 * min_range_scale */ , mMaxDistance(12750.0f) /* 255 * max_range_scale */ - , mFlags(Play_Normal) + , mFlags(MWBase::SoundManager::Play_Normal) { } virtual ~Sound() { } diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 100b2208c4..2680ec1dbe 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -6,7 +6,7 @@ #include -#include "soundmanager.hpp" +#include "soundmanagerimp.hpp" #include "../mwworld/ptr.hpp" @@ -24,10 +24,10 @@ namespace MWSound virtual void init(const std::string &devname="") = 0; virtual void deinit() = 0; - virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0; - virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, + virtual MWBase::SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0; + virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, float min, float max, int flags) = 0; - virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags) = 0; + virtual MWBase::SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags) = 0; virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp similarity index 92% rename from apps/openmw/mwsound/soundmanager.cpp rename to apps/openmw/mwsound/soundmanagerimp.cpp index c6332d9f32..4b10624a5c 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -1,11 +1,9 @@ -#include "soundmanager.hpp" +#include "soundmanagerimp.hpp" #include #include #include -#include - #include #include "../mwbase/environment.hpp" @@ -13,8 +11,6 @@ #include "../mwworld/player.hpp" -#include "../mwrender/player.hpp" - #include "sound_output.hpp" #include "sound_decoder.hpp" #include "sound.hpp" @@ -219,10 +215,10 @@ namespace MWSound // The range values are not tested float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; - const ESM::Position &pos = ptr.getCellRef().pos; + const ESM::Position &pos = ptr.getRefData().getPosition(); const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); - SoundPtr sound = mOutput->playSound3D(filePath, objpos, basevol, 1.0f, + MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, basevol, 1.0f, 20.0f, 12750.0f, Play_Normal); sound->mPos = objpos; sound->mBaseVolume = basevol; @@ -244,7 +240,7 @@ namespace MWSound float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; - SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); + MWBase::SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); sound->mBaseVolume = basevol; mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound")); @@ -277,9 +273,9 @@ namespace MWSound - SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode) + MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode) { - SoundPtr sound; + MWBase::SoundPtr sound; if(!mOutput->isInitialized()) return sound; try @@ -305,10 +301,10 @@ namespace MWSound return sound; } - SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId, + MWBase::SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId, float volume, float pitch, int mode) { - SoundPtr sound; + MWBase::SoundPtr sound; if(!mOutput->isInitialized()) return sound; try @@ -317,7 +313,7 @@ namespace MWSound float basevol = mMasterVolume * mSFXVolume; float min, max; std::string file = lookup(soundId, basevol, min, max); - const ESM::Position &pos = ptr.getCellRef().pos; + const ESM::Position &pos = ptr.getRefData().getPosition();; const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); sound = mOutput->playSound3D(file, objpos, volume*basevol, pitch, min, max, mode); @@ -410,7 +406,7 @@ namespace MWSound void SoundManager::updateObject(MWWorld::Ptr ptr) { - const ESM::Position &pos = ptr.getCellRef().pos; + const ESM::Position &pos = ptr.getRefData().getPosition();; const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); SoundMap::iterator snditer = mActiveSounds.begin(); while(snditer != mActiveSounds.end()) @@ -491,25 +487,20 @@ namespace MWSound if(!isMusicPlaying()) startRandomTitle(); - const ESM::Cell *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell; - Ogre::Camera *cam = MWBase::Environment::get().getWorld()->getPlayer().getRenderer()->getCamera(); - Ogre::Vector3 nPos, nDir, nUp; - nPos = cam->getRealPosition(); - nDir = cam->getRealDirection(); - nUp = cam->getRealUp(); + MWWorld::Ptr player = + MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + const ESM::Cell *cell = player.getCell()->cell; Environment env = Env_Normal; - if((cell->data.flags&cell->HasWater) && nPos.y < cell->water) + if((cell->data.flags&cell->HasWater) && mListenerPos.z < cell->water) env = Env_Underwater; - // The output handler is expecting vectors oriented like the game - // (that is, -Z goes down, +Y goes forward), but that's not what we - // get from Ogre's camera, so we have to convert. - const Ogre::Vector3 pos(nPos[0], -nPos[2], nPos[1]); - const Ogre::Vector3 at(nDir[0], -nDir[2], nDir[1]); - const Ogre::Vector3 up(nUp[0], -nUp[2], nUp[1]); - - mOutput->updateListener(pos, at, up, env); + mOutput->updateListener( + mListenerPos, + mListenerDir, + Ogre::Vector3::UNIT_Z, + env + ); // Check if any sounds are finished playing, and trash them SoundMap::iterator snditer = mActiveSounds.begin(); @@ -567,6 +558,12 @@ namespace MWSound } } + void SoundManager::setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir) + { + mListenerPos = pos; + mListenerDir = dir; + } + // Default readAll implementation, for decoders that can't do anything // better void Sound_Decoder::readAll(std::vector &output) diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp similarity index 57% rename from apps/openmw/mwsound/soundmanager.hpp rename to apps/openmw/mwsound/soundmanagerimp.hpp index 83195390c0..956ad57127 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -7,19 +7,15 @@ #include +#include #include #include +#include "../mwbase/soundmanager.hpp" + #include "../mwworld/ptr.hpp" - -namespace Ogre -{ - class Root; - class Camera; -} - namespace MWSound { class Sound_Output; @@ -27,27 +23,13 @@ namespace MWSound class Sound; typedef boost::shared_ptr DecoderPtr; - typedef boost::shared_ptr SoundPtr; - - enum PlayMode { - Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */ - Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */ - Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */ - Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position - * but do not keep it updated (the sound will not move with - * the object and will not stop when the object is deleted. */ - }; - static inline int operator|(const PlayMode &a, const PlayMode &b) - { return (int)a | (int)b; } - static inline int operator&(const PlayMode &a, const PlayMode &b) - { return (int)a & (int)b; } enum Environment { Env_Normal, Env_Underwater, }; - class SoundManager + class SoundManager : public MWBase::SoundManager { Ogre::ResourceGroupManager& mResourceMgr; @@ -65,9 +47,12 @@ namespace MWSound std::string mCurrentPlaylist; typedef std::pair PtrIDPair; - typedef std::map SoundMap; + typedef std::map SoundMap; SoundMap mActiveSounds; + Ogre::Vector3 mListenerPos; + Ogre::Vector3 mListenerDir; + std::string lookup(const std::string &soundId, float &volume, float &min, float &max); void streamMusicFull(const std::string& filename); @@ -84,67 +69,69 @@ namespace MWSound public: SoundManager(bool useSound); - ~SoundManager(); + virtual ~SoundManager(); - void processChangedSettings(const Settings::CategorySettingVector& settings); + virtual void processChangedSettings(const Settings::CategorySettingVector& settings); - void stopMusic(); + virtual void stopMusic(); ///< Stops music if it's playing - void streamMusic(const std::string& filename); + virtual void streamMusic(const std::string& filename); ///< Play a soundifle /// \param filename name of a sound file in "Music/" in the data directory. - void startRandomTitle(); + virtual void startRandomTitle(); ///< Starts a random track from the current playlist - bool isMusicPlaying(); + virtual bool isMusicPlaying(); ///< Returns true if music is playing - void playPlaylist(const std::string &playlist); + virtual void playPlaylist(const std::string &playlist); ///< Start playing music from the selected folder /// \param name of the folder that contains the playlist - void say(MWWorld::Ptr reference, const std::string& filename); + virtual void say(MWWorld::Ptr reference, const std::string& filename); ///< Make an actor say some text. /// \param filename name of a sound file in "Sound/" in the data directory. - void say(const std::string& filename); + virtual void say(const std::string& filename); ///< Say some text, without an actor ref /// \param filename name of a sound file in "Sound/" in the data directory. - bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const; + virtual bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const; ///< Is actor not speaking? - void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()); + virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()); ///< Stop an actor speaking - SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal); + virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal); ///< Play a sound, independently of 3D-position - SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, + virtual MWBase::SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, float volume, float pitch, int mode=Play_Normal); ///< Play a sound from an object - void stopSound3D(MWWorld::Ptr reference, const std::string& soundId); + virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId); ///< Stop the given object from playing the given sound, - void stopSound3D(MWWorld::Ptr reference); + virtual void stopSound3D(MWWorld::Ptr reference); ///< Stop the given object from playing all sounds. - void stopSound(const MWWorld::CellStore *cell); + virtual void stopSound(const MWWorld::CellStore *cell); ///< Stop all sounds for the given cell. - void stopSound(const std::string& soundId); + virtual void stopSound(const std::string& soundId); ///< Stop a non-3d looping sound - bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const; + virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const; ///< Is the given sound currently playing on the given object? - void updateObject(MWWorld::Ptr reference); + virtual void updateObject(MWWorld::Ptr reference); ///< Update the position of all sounds connected to the given object. - void update(float duration); + virtual void update(float duration); + + virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir); }; } diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index 0a57d5f675..748f6aff78 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -2,18 +2,31 @@ #include "action.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" -#include "../mwsound/soundmanager.hpp" +#include "../mwbase/soundmanager.hpp" -MWWorld::Action::Action() {} +MWWorld::Action::Action (bool teleport) : mTeleport (teleport) +{} MWWorld::Action::~Action() {} void MWWorld::Action::execute (const Ptr& actor) { if (!mSoundId.empty()) - MWBase::Environment::get().getSoundManager()->playSound3D (actor, mSoundId, 1.0, 1.0, - MWSound::Play_NoTrack); + { + if (mTeleport == true) + { + //this is a teleport action, so we need to call playSound + MWBase::Environment::get().getSoundManager()->playSound(mSoundId, 1.0, 1.0, + MWBase::SoundManager::Play_NoTrack); + } + else + { + MWBase::Environment::get().getSoundManager()->playSound3D (actor, mSoundId, 1.0, 1.0, + MWBase::SoundManager::Play_NoTrack); + } + } executeImp (actor); } diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index a00f679517..511a7002da 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -11,6 +11,7 @@ namespace MWWorld class Action { std::string mSoundId; + bool mTeleport; // not implemented Action (const Action& action); @@ -18,9 +19,10 @@ namespace MWWorld virtual void executeImp (const Ptr& actor) = 0; - public: + public: - Action(); + Action (bool teleport = false); + ///< \param teleport action will teleport the actor virtual ~Action(); diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index a7ee4fd0e3..bba75bc499 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -1,7 +1,7 @@ #include "actionalchemy.hpp" #include "../mwbase/environment.hpp" -#include "../mwgui/window_manager.hpp" +#include "../mwbase/windowmanager.hpp" namespace MWWorld { diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index c73ef91494..15a9f510dd 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -1,9 +1,8 @@ #include "actionopen.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" -#include "../mwclass/container.hpp" -#include "../mwgui/window_manager.hpp" #include "../mwgui/container.hpp" #include "class.hpp" diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index c81d79e03b..5c6ab93c12 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -1,7 +1,8 @@ #include "actionread.hpp" #include "../mwbase/environment.hpp" -#include "../mwgui/window_manager.hpp" +#include "../mwbase/windowmanager.hpp" + #include "../mwgui/bookwindow.hpp" #include "../mwgui/scrollwindow.hpp" diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index 5207f1a100..90f3c000e2 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -3,8 +3,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" - -#include "../mwgui/window_manager.hpp" +#include "../mwbase/windowmanager.hpp" #include "class.hpp" #include "containerstore.hpp" diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 78171bbe5a..d94cb67f41 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -2,8 +2,7 @@ #include "actiontalk.hpp" #include "../mwbase/environment.hpp" -#include "../mwgui/window_manager.hpp" -#include "../mwdialogue/dialoguemanager.hpp" +#include "../mwbase/dialoguemanager.hpp" namespace MWWorld { diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 9c87d37ae5..ae5ffc3b90 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -8,8 +8,9 @@ namespace MWWorld { ActionTeleport::ActionTeleport (const std::string& cellName, const ESM::Position& position) - : mCellName (cellName), mPosition (position) - {} + : Action (true), mCellName (cellName), mPosition (position) + { + } void ActionTeleport::executeImp (const Ptr& actor) { diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index cffaf70eae..822aa78d6e 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -167,67 +167,71 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce else return Ptr(); } + MWWorld::Ptr ptr; if (MWWorld::LiveCellRef *ref = cell.activators.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.potions.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.appas.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.armors.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.books.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.clothes.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.containers.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.creatures.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.doors.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.ingreds.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.creatureLists.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.itemLists.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.lights.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.lockpicks.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.miscItems.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.npcs.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.probes.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.repairs.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.statics.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.weapons.find (name)) - return Ptr (ref, &cell); + ptr = Ptr (ref, &cell); + if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) { + return ptr; + } return Ptr(); } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 0be0ef6516..3ec4a2e782 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -69,7 +69,7 @@ namespace MWWorld { for (typename std::list::iterator iter (list.begin()); iter!=list.end(); ++iter) { - if (iter->ref.refID==name) + if (iter->mData.getCount() > 0 && iter->ref.refID == name) return &*iter; } @@ -155,6 +155,20 @@ namespace MWWorld forEachImp (functor, weapons); } + bool operator==(const CellStore &cell) { + return this->cell->name == cell.cell->name && + this->cell->data.gridX == cell.cell->data.gridX && + this->cell->data.gridY == cell.cell->data.gridY; + } + + bool operator!=(const CellStore &cell) { + return !(*this == cell); + } + + bool isExterior() const { + return cell->isExterior(); + } + private: template diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 1bc592798c..3c3b0e34be 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -21,7 +21,7 @@ namespace MWRender namespace MWMechanics { - struct CreatureStats; + class CreatureStats; class NpcStats; struct Movement; } @@ -220,6 +220,11 @@ namespace MWWorld virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const; + + virtual bool + isActor() const { + return false; + } }; } diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 45b3cab268..e55eca0ae7 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -7,7 +7,7 @@ namespace MWMechanics { - struct NpcStats; + class NpcStats; } namespace MWWorld diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index d1e39c8b7b..0af9511cf7 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -11,7 +11,7 @@ #include -#include "../mwbase/world.hpp" // FIXME +//#include "../mwbase/world.hpp" // FIXME #include "ptr.hpp" #include "class.hpp" @@ -42,32 +42,38 @@ namespace MWWorld return mEngine; } - std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) - { - std::string handle = ""; + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) + { + btVector3 dir(0, 1, 0); + dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir.setX(-dir.x()); - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay( - mRender.getViewport()->getWidth()/2, - mRender.getViewport()->getHeight()/2); - //let's avoid the capsule shape of the player. - centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); + btVector3 origin( + mPlayerData.eyepos.x, + mPlayerData.eyepos.y, + mPlayerData.eyepos.z); + origin += dir * 5; - return mEngine->rayTest(from,to); + btVector3 dest = origin + dir * 500; + return mEngine->rayTest(origin, dest); } std::vector < std::pair > PhysicsSystem::getFacedObjects () { - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay( - mRender.getViewport()->getWidth()/2, - mRender.getViewport()->getHeight()/2); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); + btVector3 dir(0, 1, 0); + dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); + dir = dir.rotate(btVector3(0, 0, 1), mPlayerData.yaw); + dir.setX(-dir.x()); - return mEngine->rayTest2(from,to); + btVector3 origin( + mPlayerData.eyepos.x, + mPlayerData.eyepos.y, + mPlayerData.eyepos.z); + origin += dir * 5; + + btVector3 dest = origin + dir * 500; + return mEngine->rayTest2(origin, dest); } std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) @@ -172,8 +178,10 @@ namespace MWWorld OEngine::Physic::PhysicActor* act = it->second; act->setWalkDirection(btVector3(0,0,0)); } - playerMove::playercmd& pm_ref = playerphysics->cmd; - + + playerMove::playercmd& pm_ref = playerphysics->cmd; + + pm_ref.rightmove = 0; pm_ref.forwardmove = 0; pm_ref.upmove = 0; @@ -184,39 +192,21 @@ namespace MWWorld iter!=actors.end(); ++iter) { //dirty stuff to get the camera orientation. Must be changed! - - Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first); - Ogre::Vector3 dir; - Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); - Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); - Ogre::Quaternion yawQuat = yawNode->getOrientation(); - Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); - - - //playerphysics->ps.snappingImplemented = false; - //playerphysics->ps.speed = 240; - - playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); - - playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() * -1 + 90; - if(playerphysics->ps.viewangles.y < 0) - playerphysics->ps.viewangles.y += 360; - - - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - - pm_ref.rightmove = -iter->second.x; - pm_ref.forwardmove = -iter->second.y; - pm_ref.upmove = iter->second.z; + if (iter->first == "player") { + playerphysics->ps.viewangles.x = + Ogre::Radian(mPlayerData.pitch).valueDegrees(); + playerphysics->ps.viewangles.y = + Ogre::Radian(mPlayerData.yaw).valueDegrees() + 90; + + + pm_ref.rightmove = -iter->second.x; + pm_ref.forwardmove = -iter->second.y; + pm_ref.upmove = iter->second.z; + } } - - - - - mEngine->stepSimulation(dt); } @@ -413,4 +403,11 @@ namespace MWWorld return true; } + + void PhysicsSystem::updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw) + { + mPlayerData.eyepos = eyepos; + mPlayerData.pitch = pitch; + mPlayerData.yaw = yaw; + } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 4ed8d59f60..949aa9d452 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -70,7 +70,14 @@ namespace MWWorld bool getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max); + void updatePlayerData(Ogre::Vector3 &eyepos, float pitch, float yaw); + private: + struct { + Ogre::Vector3 eyepos; + float pitch, yaw; + } mPlayerData; + OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; bool mFreeFly; @@ -80,7 +87,6 @@ namespace MWWorld PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); }; - } #endif diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 54e5a625fc..0f05ae24da 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -6,8 +6,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" -#include "../mwrender/player.hpp" - #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" @@ -15,8 +13,8 @@ namespace MWWorld { - Player::Player (MWRender::Player *renderer, const ESM::NPC *player, const MWBase::World& world) : - mCellStore (0), mRenderer (renderer), mClass (0), + Player::Player (const ESM::NPC *player, const MWBase::World& world) : + mCellStore (0), mClass (0), mAutoMove (false), mForwardBackward (0) { mPlayer.base = player; @@ -28,7 +26,6 @@ namespace MWWorld float* playerPos = mPlayer.mData.getPosition().pos; playerPos[0] = playerPos[1] = playerPos[2] = 0; - mPlayer.mData.setBaseNode(renderer->getNode()); /// \todo Do not make a copy of classes defined in esm/p records. mClass = new ESM::Class (*world.getStore().classes.find (player->cls)); } @@ -38,11 +35,6 @@ namespace MWWorld delete mClass; } - void Player::setRot(float x, float y, float z) - { - mRenderer->setRot(x, y, z); - } - void Player::setClass (const ESM::Class& class_) { ESM::Class *new_class = new ESM::Class (class_); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index d2058dea6c..68df2ec6df 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -14,11 +14,6 @@ namespace MWBase class World; } -namespace MWRender -{ - class Player; -} - namespace MWWorld { class CellStore; @@ -28,7 +23,6 @@ namespace MWWorld { LiveCellRef mPlayer; MWWorld::CellStore *mCellStore; - MWRender::Player *mRenderer; std::string mName; bool mMale; std::string mRace; @@ -38,13 +32,10 @@ namespace MWWorld int mForwardBackward; public: - Player(MWRender::Player *renderer, const ESM::NPC *player, const MWBase::World& world); + Player(const ESM::NPC *player, const MWBase::World& world); ~Player(); - /// Set where the player is looking at. Uses Morrowind (euler) angles - void setRot(float x, float y, float z); - void setCell (MWWorld::CellStore *cellStore) { mCellStore = cellStore; @@ -56,8 +47,6 @@ namespace MWWorld return ptr; } - MWRender::Player *getRenderer() { return mRenderer; } - void setName (const std::string& name) { mName = name; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c768fce26d..eb03e9a7bd 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,13 +1,12 @@ #include "scene.hpp" +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" /// FIXME - -#include "../mwmechanics/mechanicsmanager.hpp" - -#include "../mwsound/soundmanager.hpp" - -#include "../mwgui/window_manager.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "player.hpp" #include "localscripts.hpp" @@ -145,15 +144,20 @@ namespace MWWorld mPhysics->setCurrentWater(hasWater, cell->cell->water); MWBase::World *world = MWBase::Environment::get().getWorld(); + world->getPlayer().setCell(cell); + MWWorld::Ptr player = world->getPlayer().getPlayer(); if (adjustPlayerPos) { world->moveObject(player, pos.pos[0], pos.pos[1], pos.pos[2]); - MWBase::Environment::get().getWorld()->getPlayer().setRot (pos.rot[0], pos.rot[1], pos.rot[2]); - } - world->getPlayer().setCell(cell); - MWMechanics::MechanicsManager *mechMgr = + float x = Ogre::Radian(pos.rot[0]).valueDegrees(); + float y = Ogre::Radian(pos.rot[1]).valueDegrees(); + float z = Ogre::Radian(pos.rot[2]).valueDegrees(); + world->rotateObject(player, x, y, z); + } + + MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager(); mechMgr->addActor(player); @@ -232,7 +236,7 @@ namespace MWWorld // adjust player - playerCellChange (MWBase::Environment::get().getWorld()->getExterior(X, Y), position, adjustPlayerPos); + playerCellChange (mCurrentCell, position, adjustPlayerPos); // Sky system MWBase::Environment::get().getWorld()->adjustSky(); @@ -345,7 +349,7 @@ namespace MWWorld mRendering.addObject(ptr); MWWorld::Class::get(ptr).insertObject(ptr, *mPhysics); } - + void Scene::removeObjectFromScene (const Ptr& ptr) { MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); @@ -358,10 +362,7 @@ namespace MWWorld { CellStoreCollection::iterator active = mActiveCells.begin(); while (active != mActiveCells.end()) { - if ((*active)->cell->name == cell.cell->name && - (*active)->cell->data.gridX == cell.cell->data.gridX && - (*active)->cell->data.gridY == cell.cell->data.gridY) - { + if (**active == cell) { return true; } ++active; diff --git a/apps/openmw/mwworld/timestamp.cpp b/apps/openmw/mwworld/timestamp.cpp index e2f3d6c634..126d5490c5 100644 --- a/apps/openmw/mwworld/timestamp.cpp +++ b/apps/openmw/mwworld/timestamp.cpp @@ -76,12 +76,12 @@ namespace MWWorld TimeStamp operator+ (const TimeStamp& stamp, double hours) { - return TimeStamp (stamp) + hours; + return TimeStamp (stamp) += hours; } TimeStamp operator+ (double hours, const TimeStamp& stamp) { - return TimeStamp (stamp) + hours; + return TimeStamp (stamp) += hours; } double operator- (const TimeStamp& left, const TimeStamp& right) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index b5f2e3a575..0adf87dae9 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -9,11 +9,10 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/soundmanager.hpp" #include "../mwrender/renderingmanager.hpp" -#include "../mwsound/soundmanager.hpp" - #include "player.hpp" using namespace Ogre; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d5046db2d4..73efdd8164 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -4,16 +4,13 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" - -#include "../mwsound/soundmanager.hpp" - -#include "../mwgui/window_manager.hpp" - #include "player.hpp" #include "manualref.hpp" #include "cellfunctors.hpp" @@ -51,7 +48,7 @@ namespace for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter) { - if(iter->mData.getBaseNode()){ + if(iter->mData.getCount() > 0 && iter->mData.getBaseNode()){ if (iter->mData.getHandle()==handle) { return &*iter; @@ -189,8 +186,9 @@ namespace MWWorld mEsm.open (masterPath.string()); mStore.load (mEsm); - MWRender::Player* play = &(mRendering->getPlayer()); - mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this); + mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this); + mRendering->attachCameraTo(mPlayer->getPlayer()); + mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); // global variables @@ -543,49 +541,82 @@ namespace MWWorld } } - bool World::moveObjectImp (const Ptr& ptr, float x, float y, float z) + void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z) { - bool ret = false; - ptr.getRefData().getPosition().pos[0] = x; - ptr.getRefData().getPosition().pos[1] = y; - ptr.getRefData().getPosition().pos[2] = z; - if (ptr==mPlayer->getPlayer()) - { - //std::cout << "X:" << ptr.getRefData().getPosition().pos[0] << " Z: " << ptr.getRefData().getPosition().pos[1] << "\n"; + ESM::Position &pos = ptr.getRefData().getPosition(); + pos.pos[0] = x, pos.pos[1] = y, pos.pos[2] = z; + Ogre::Vector3 vec(x, y, z); - Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); - if (currentCell) - { - if (!(currentCell->cell->data.flags & ESM::Cell::Interior)) - { - // exterior -> adjust loaded cells - int cellX = 0; - int cellY = 0; - - positionToIndex (x, y, cellX, cellY); - - if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) - { - mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); - ret = true; - } + CellStore *currCell = ptr.getCell(); + bool isPlayer = ptr == mPlayer->getPlayer(); + bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; + if (*currCell != newCell) { + if (isPlayer) { + if (!newCell.isExterior()) { + changeToInteriorCell(newCell.cell->name, pos); + } else { + int cellX = newCell.cell->data.gridX; + int cellY = newCell.cell->data.gridY; + mWorldScene->changeCell(cellX, cellY, pos, false); } + } else { + if (!mWorldScene->isCellActive(*currCell)) { + copyObjectToCell(ptr, newCell, pos); + } else if (!mWorldScene->isCellActive(newCell)) { + MWWorld::Class::get(ptr).copyToCell(ptr, newCell); + mWorldScene->removeObjectFromScene(ptr); + mLocalScripts.remove(ptr); + haveToMove = false; + } else { + MWWorld::Ptr copy = + MWWorld::Class::get(ptr).copyToCell(ptr, newCell); + + mRendering->moveObjectToCell(copy, vec, currCell); + + if (MWWorld::Class::get(ptr).isActor()) { + MWBase::MechanicsManager *mechMgr = + MWBase::Environment::get().getMechanicsManager(); + + mechMgr->removeActor(ptr); + mechMgr->addActor(copy); + } else { + std::string script = + MWWorld::Class::get(ptr).getScript(ptr); + if (!script.empty()) { + mLocalScripts.remove(ptr); + mLocalScripts.add(script, copy); + } + } + } + ptr.getRefData().setCount(0); } } + if (haveToMove) { + mRendering->moveObject(ptr, vec); + mPhysics->moveObject (ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode()); + } + } - /// \todo cell change for non-player ref + bool World::moveObjectImp(const Ptr& ptr, float x, float y, float z) + { + CellStore *cell = ptr.getCell(); + if (cell->isExterior()) { + int cellX, cellY; + positionToIndex(x, y, cellX, cellY); - mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); + cell = getExterior(cellX, cellY); + } + moveObject(ptr, *cell, x, y, z); - return ret; + return cell != ptr.getCell(); } void World::moveObject (const Ptr& ptr, float x, float y, float z) { moveObjectImp(ptr, x, y, z); - mPhysics->moveObject (ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode()); + } void World::scaleObject (const Ptr& ptr, float scale) @@ -598,19 +629,26 @@ namespace MWWorld mPhysics->scaleObject( ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode()); } - void World::rotateObject (const Ptr& ptr,float x,float y,float z) + void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) { - MWWorld::Class::get(ptr).adjustRotation(ptr,x,y,z); + Ogre::Vector3 rot; + rot.x = Ogre::Degree(x).valueRadians(); + rot.y = Ogre::Degree(y).valueRadians(); + rot.z = Ogre::Degree(z).valueRadians(); - ptr.getRefData().getPosition().rot[0] = Ogre::Degree(x).valueRadians(); - ptr.getRefData().getPosition().rot[1] = Ogre::Degree(y).valueRadians(); - ptr.getRefData().getPosition().rot[2] = Ogre::Degree(z).valueRadians(); + if (mRendering->rotateObject(ptr, rot, adjust)) { + float *objRot = ptr.getRefData().getPosition().rot; + objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; + + + if (ptr.getRefData().getBaseNode() != 0) { + mPhysics->rotateObject( + ptr.getRefData().getHandle(), + ptr.getRefData().getBaseNode() + ); + } + } - Ogre::Quaternion rotx(Ogre::Degree(-x),Ogre::Vector3::UNIT_X); - Ogre::Quaternion roty(Ogre::Degree(-y),Ogre::Vector3::UNIT_Y); - Ogre::Quaternion rotz(Ogre::Degree(-z),Ogre::Vector3::UNIT_Z); - ptr.getRefData().getBaseNode()->setOrientation(rotx*roty*rotz); - mPhysics->rotateObject(ptr.getRefData().getHandle(),ptr.getRefData().getBaseNode()); } void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const @@ -711,8 +749,11 @@ namespace MWWorld std::ostringstream stream; stream << "$dynamic" << mNextDynamicRecord++; + ESM::Potion record2 (record); + record2.mId = stream.str(); + const ESM::Potion *created = - &mStore.potions.list.insert (std::make_pair (stream.str(), record)).first->second; + &mStore.potions.list.insert (std::make_pair (stream.str(), record2)).first->second; mStore.all.insert (std::make_pair (stream.str(), ESM::REC_ALCH)); @@ -772,6 +813,11 @@ namespace MWWorld /// \todo split this function up into subfunctions mWorldScene->update (duration); + + float pitch, yaw; + Ogre::Vector3 eyepos; + mRendering->getPlayerData(eyepos, pitch, yaw); + mPhysics->updatePlayerData(eyepos, pitch, yaw); mWeatherManager->update (duration); @@ -979,7 +1025,7 @@ namespace MWWorld Ogre::Vector2 World::getNorthVector (CellStore* cell) { - MWWorld::CellRefList statics = cell->statics; + MWWorld::CellRefList& statics = cell->statics; MWWorld::LiveCellRef* ref = statics.find("northmarker"); if (!ref) return Vector2(0, 1); @@ -989,6 +1035,64 @@ namespace MWWorld return d; } + std::vector World::getDoorMarkers (CellStore* cell) + { + std::vector result; + + MWWorld::CellRefList& doors = cell->doors; + std::list< MWWorld::LiveCellRef >& refList = doors.list; + for (std::list< MWWorld::LiveCellRef >::iterator it = refList.begin(); it != refList.end(); ++it) + { + MWWorld::LiveCellRef& ref = *it; + + if (ref.ref.teleport) + { + World::DoorMarker newMarker; + + std::string dest; + if (ref.ref.destCell != "") + { + // door leads to an interior, use interior name + dest = ref.ref.destCell; + } + else + { + // door leads to exterior, use cell name (if any), otherwise translated region name + int x,y; + positionToIndex (ref.ref.doorDest.pos[0], ref.ref.doorDest.pos[1], x, y); + const ESM::Cell* cell = mStore.cells.findExt(x,y); + if (cell->name != "") + dest = cell->name; + else + { + const ESM::Region* region = mStore.regions.search(cell->region); + dest = region->name; + } + } + + newMarker.name = dest; + + ESM::Position pos = ref.mData.getPosition (); + + newMarker.x = pos.pos[0]; + newMarker.y = pos.pos[1]; + result.push_back(newMarker); + } + } + + return result; + } + + void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) + { + mRendering->getInteriorMapPosition(position, nX, nY, x, y); + } + + bool World::isPositionExplored (float nX, float nY, int x, int y, bool interior) + { + return mRendering->isPositionExplored(nX, nY, x, y, interior); + } + void World::setWaterHeight(const float height) { mRendering->setWaterHeight(height); @@ -1021,7 +1125,7 @@ namespace MWWorld pos.pos[1] = -result.second[2]; pos.pos[2] = result.second[1]; - placeObject(object, *cell, pos); + copyObjectToCell(object, *cell, pos); object.getRefData().setCount(0); return true; @@ -1039,7 +1143,7 @@ namespace MWWorld } void - World::placeObject(const Ptr &object, CellStore &cell, const ESM::Position &pos) + World::copyObjectToCell(const Ptr &object, CellStore &cell, const ESM::Position &pos) { /// \todo add searching correct cell for position specified MWWorld::Ptr dropped = @@ -1082,7 +1186,7 @@ namespace MWWorld mPhysics->castRay(orig, dir, len); pos.pos[2] = hit.second.z; - placeObject(object, *cell, pos); + copyObjectToCell(object, *cell, pos); object.getRefData().setCount(0); } @@ -1117,4 +1221,9 @@ namespace MWWorld } return pos.z < cell.water; } + + void World::renderPlayer() + { + mRendering->renderPlayer(mPlayer->getPlayer()); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f80b88be2c..1d932bce2c 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -90,7 +90,7 @@ namespace MWWorld ///< @return true if the active cell (cell player is in) changed virtual void - placeObject(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); + copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); public: @@ -140,6 +140,15 @@ namespace MWWorld virtual Ogre::Vector2 getNorthVector (CellStore* cell); ///< get north vector (OGRE coordinates) for given interior cell + virtual std::vector getDoorMarkers (MWWorld::CellStore* cell); + ///< get a list of teleport door markers for a given cell, to be displayed on the local map + + virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y); + ///< see MWRender::LocalMap::getInteriorMapPosition + + virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior); + ///< see MWRender::LocalMap::isPositionExplored + virtual Globals::Data& getGlobalVariable (const std::string& name); virtual Globals::Data getGlobalVariable (const std::string& name) const; @@ -206,10 +215,13 @@ namespace MWWorld virtual void deleteObject (const Ptr& ptr); virtual void moveObject (const Ptr& ptr, float x, float y, float z); + virtual void moveObject (const Ptr& ptr, CellStore &newCell, float x, float y, float z); virtual void scaleObject (const Ptr& ptr, float scale); - virtual void rotateObject (const Ptr& ptr,float x,float y,float z); + /// Rotates object, uses degrees + /// \param adjust indicates rotation should be set or adjusted + virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const; @@ -273,6 +285,28 @@ namespace MWWorld virtual bool isSwimming(const MWWorld::Ptr &object); virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos); + + virtual void togglePOV() { + mRendering->togglePOV(); + } + + virtual void togglePreviewMode(bool enable) { + mRendering->togglePreviewMode(enable); + } + + virtual bool toggleVanityMode(bool enable, bool force) { + return mRendering->toggleVanityMode(enable, force); + } + + virtual void allowVanityMode(bool allow) { + mRendering->allowVanityMode(allow); + } + + virtual void togglePlayerLooking(bool enable) { + mRendering->togglePlayerLooking(enable); + } + + virtual void renderPlayer(); }; } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index c0585d5ee5..1bc5e65f8b 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -43,7 +43,7 @@ add_component_dir (esm loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat - loadweap records + loadweap records aipackage ) add_component_dir (misc diff --git a/components/esm/aipackage.cpp b/components/esm/aipackage.cpp new file mode 100644 index 0000000000..a2fd8beb19 --- /dev/null +++ b/components/esm/aipackage.cpp @@ -0,0 +1,37 @@ +#include "aipackage.hpp" + +namespace ESM +{ + void AIPackageList::load(ESMReader &esm) + { + while (esm.hasMoreSubs()) { + // initialize every iteration + AIPackage pack; + esm.getSubName(); + if (esm.retSubName() == 0x54444e43) { // CNDT + mList.back().mCellName = esm.getHString(); + } else if (esm.retSubName() == AI_Wander) { + pack.mType = AI_Wander; + esm.getHExact(&pack.mWander, 14); + mList.push_back(pack); + } else if (esm.retSubName() == AI_Travel) { + pack.mType = AI_Travel; + esm.getHExact(&pack.mTravel, 16); + mList.push_back(pack); + } else if (esm.retSubName() == AI_Escort || + esm.retSubName() == AI_Follow) + { + pack.mType = + (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow; + esm.getHExact(&pack.mTarget, 48); + mList.push_back(pack); + } else if (esm.retSubName() == AI_Activate) { + pack.mType = AI_Activate; + esm.getHExact(&pack.mActivate, 33); + mList.push_back(pack); + } else { // not AI package related data, so leave + return; + } + } + } +} diff --git a/components/esm/aipackage.hpp b/components/esm/aipackage.hpp new file mode 100644 index 0000000000..3a8547402a --- /dev/null +++ b/components/esm/aipackage.hpp @@ -0,0 +1,95 @@ +#ifndef OPENMW_ESM_AIPACKAGE_H +#define OPENMW_ESM_AIPACKAGE_H + +#include "esm_reader.hpp" + +#include + +namespace ESM +{ + #pragma pack(push) + #pragma pack(1) + + struct AIData + { + // These are probabilities + char mHello, mU1, mFight, mFlee, mAlarm, mU2, mU3, mU4; + // The last u's might be the skills that this NPC can train you + // in? + int mServices; // See the Services enum + }; // 12 bytes + + struct AIWander + { + short mDistance; + short mDuration; + unsigned char mTimeOfDay; + unsigned char mIdle[8]; + unsigned char mUnk; + }; + + struct AITravel + { + float mX, mY, mZ; + long mUnk; + }; + + struct AITarget + { + float mX, mY, mZ; + short mDuration; + NAME32 mId; + short mUnk; + }; + + struct AIActivate + { + NAME32 mName; + unsigned char mUnk; + }; + + #pragma pack(pop) + + enum + { + AI_Wander = 0x575f4941, + AI_Travel = 0x545f4941, + AI_Follow = 0x465f4941, + AI_Escort = 0x455f4941, + AI_Activate = 0x415f4941, + }; + + /// \note Used for storaging packages in a single container + /// w/o manual memory allocation accordingly to policy standards + struct AIPackage + { + int mType; + + // Anonymous union + union + { + AIWander mWander; + AITravel mTravel; + AITarget mTarget; + AIActivate mActivate; + }; + + /// \note for AITarget only, placed here to stick with union, + /// overhead should be not so awful + std::string mCellName; + }; + + struct AIPackageList + { + std::vector mList; + + /// \note This breaks consistency of subrecords reading: + /// after calling it subrecord name is already read, so + /// it needs to use retSubName() if needed. But, hey, there + /// is only one field left (XSCL) and only two records uses AI + void load(ESMReader &esm); + }; +} + +#endif + diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 13f1f4a019..66c0710a68 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -49,23 +49,23 @@ union NAME_T char name[LEN]; int32_t val; - bool operator==(const char *str) + bool operator==(const char *str) const { for(int i=0; i mTransport; + AIPackageList mAiPackage; + + std::string name, model, race, cls, faction, script; + + // body parts + std::string hair, head; std::string mId; - // Implementation moved to load_impl.cpp - void load(ESMReader &esm, const std::string& id); + // Implementation moved to load_impl.cpp + void load(ESMReader &esm, const std::string& id); }; } #endif diff --git a/components/files/ogreplugin.cpp b/components/files/ogreplugin.cpp index c434114b37..ca90fd30e1 100644 --- a/components/files/ogreplugin.cpp +++ b/components/files/ogreplugin.cpp @@ -6,7 +6,11 @@ namespace Files { bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot) { + // Append plugin suffix if debugging. +#if defined(DEBUG) pluginName = pluginName + OGRE_PLUGIN_DEBUG_SUFFIX; +#endif + #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE std::ostringstream verStream; verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 4393749fbb..0fdeaae3d9 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -471,7 +471,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam float glossiness = 0.0f; float alpha = 1.0f; int alphaFlags = -1; - ubyte alphaTest = 0; +// ubyte alphaTest = 0; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -523,7 +523,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam if (a) { alphaFlags = a->flags; - alphaTest = a->data.threshold; +// alphaTest = a->data.threshold; } // Material diff --git a/components/to_utf8/gen_iconv.cpp b/components/to_utf8/gen_iconv.cpp index cc7cc191ab..dea68c1fa2 100644 --- a/components/to_utf8/gen_iconv.cpp +++ b/components/to_utf8/gen_iconv.cpp @@ -1,7 +1,6 @@ // This program generates the file tables_gen.hpp #include -#include using namespace std; #include @@ -10,9 +9,11 @@ using namespace std; void tab() { cout << " "; } // write one number with a space in front of it and a comma after it -void num(unsigned char i, bool last) +void num(char i, bool last) { - cout << " (char)0x" << (unsigned)i; + // Convert i to its integer value, i.e. -128 to 127. Printing it directly + // would result in non-printable characters in the source code, which is bad. + cout << " " << static_cast(i); if(!last) cout << ","; } @@ -80,8 +81,6 @@ int write_table(const std::string &charset, const std::string &tableName) int main() { - cout << hex; - // Write header guard cout << "#ifndef COMPONENTS_TOUTF8_TABLE_GEN_H\n#define COMPONENTS_TOUTF8_TABLE_GEN_H\n\n"; diff --git a/components/to_utf8/tables_gen.hpp b/components/to_utf8/tables_gen.hpp index 1084ca28f9..9c32f0427d 100644 --- a/components/to_utf8/tables_gen.hpp +++ b/components/to_utf8/tables_gen.hpp @@ -10,785 +10,785 @@ namespace ToUTF8 /// Serbian (Latin script), Romanian and Albanian. static char windows_1250[] = { - (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x8, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x9, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xa, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xb, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xc, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xd, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xe, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xf, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x10, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x11, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x12, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x13, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x14, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x15, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x16, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x17, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x18, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x19, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x21, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x22, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x23, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x24, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x25, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x26, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x27, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x28, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x29, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x30, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x31, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x32, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x33, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x34, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x35, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x36, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x37, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x38, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x39, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x40, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x41, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x42, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x43, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x44, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x45, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x46, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x47, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x48, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x49, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x50, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x51, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x52, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x53, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x54, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x55, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x56, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x57, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x58, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x59, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x60, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x61, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x62, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x63, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x64, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x65, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x66, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x67, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x68, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x69, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x70, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x71, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x72, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x73, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x74, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x75, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x76, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x77, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x78, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x79, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x82, (char)0xac, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0x9a, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0x9e, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa6, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa1, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0xb0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xb9, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xb9, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0x98, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x99, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9c, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9d, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa2, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x93, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x94, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x84, (char)0xa2, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xba, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x81, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x9e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xac, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x85, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x9f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x9d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xbc, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x94, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x81, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0xb9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x86, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x8c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x89, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x8e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x90, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x83, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x93, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x94, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x90, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x96, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x97, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x95, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x83, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x8d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x99, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x8f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc4, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x88, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x99, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xaf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbc, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x99, (char)0x0, (char)0x0, (char)0x0 + 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 2, 0, 0, 0, 0, + 1, 3, 0, 0, 0, 0, + 1, 4, 0, 0, 0, 0, + 1, 5, 0, 0, 0, 0, + 1, 6, 0, 0, 0, 0, + 1, 7, 0, 0, 0, 0, + 1, 8, 0, 0, 0, 0, + 1, 9, 0, 0, 0, 0, + 1, 10, 0, 0, 0, 0, + 1, 11, 0, 0, 0, 0, + 1, 12, 0, 0, 0, 0, + 1, 13, 0, 0, 0, 0, + 1, 14, 0, 0, 0, 0, + 1, 15, 0, 0, 0, 0, + 1, 16, 0, 0, 0, 0, + 1, 17, 0, 0, 0, 0, + 1, 18, 0, 0, 0, 0, + 1, 19, 0, 0, 0, 0, + 1, 20, 0, 0, 0, 0, + 1, 21, 0, 0, 0, 0, + 1, 22, 0, 0, 0, 0, + 1, 23, 0, 0, 0, 0, + 1, 24, 0, 0, 0, 0, + 1, 25, 0, 0, 0, 0, + 1, 26, 0, 0, 0, 0, + 1, 27, 0, 0, 0, 0, + 1, 28, 0, 0, 0, 0, + 1, 29, 0, 0, 0, 0, + 1, 30, 0, 0, 0, 0, + 1, 31, 0, 0, 0, 0, + 1, 32, 0, 0, 0, 0, + 1, 33, 0, 0, 0, 0, + 1, 34, 0, 0, 0, 0, + 1, 35, 0, 0, 0, 0, + 1, 36, 0, 0, 0, 0, + 1, 37, 0, 0, 0, 0, + 1, 38, 0, 0, 0, 0, + 1, 39, 0, 0, 0, 0, + 1, 40, 0, 0, 0, 0, + 1, 41, 0, 0, 0, 0, + 1, 42, 0, 0, 0, 0, + 1, 43, 0, 0, 0, 0, + 1, 44, 0, 0, 0, 0, + 1, 45, 0, 0, 0, 0, + 1, 46, 0, 0, 0, 0, + 1, 47, 0, 0, 0, 0, + 1, 48, 0, 0, 0, 0, + 1, 49, 0, 0, 0, 0, + 1, 50, 0, 0, 0, 0, + 1, 51, 0, 0, 0, 0, + 1, 52, 0, 0, 0, 0, + 1, 53, 0, 0, 0, 0, + 1, 54, 0, 0, 0, 0, + 1, 55, 0, 0, 0, 0, + 1, 56, 0, 0, 0, 0, + 1, 57, 0, 0, 0, 0, + 1, 58, 0, 0, 0, 0, + 1, 59, 0, 0, 0, 0, + 1, 60, 0, 0, 0, 0, + 1, 61, 0, 0, 0, 0, + 1, 62, 0, 0, 0, 0, + 1, 63, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 1, 65, 0, 0, 0, 0, + 1, 66, 0, 0, 0, 0, + 1, 67, 0, 0, 0, 0, + 1, 68, 0, 0, 0, 0, + 1, 69, 0, 0, 0, 0, + 1, 70, 0, 0, 0, 0, + 1, 71, 0, 0, 0, 0, + 1, 72, 0, 0, 0, 0, + 1, 73, 0, 0, 0, 0, + 1, 74, 0, 0, 0, 0, + 1, 75, 0, 0, 0, 0, + 1, 76, 0, 0, 0, 0, + 1, 77, 0, 0, 0, 0, + 1, 78, 0, 0, 0, 0, + 1, 79, 0, 0, 0, 0, + 1, 80, 0, 0, 0, 0, + 1, 81, 0, 0, 0, 0, + 1, 82, 0, 0, 0, 0, + 1, 83, 0, 0, 0, 0, + 1, 84, 0, 0, 0, 0, + 1, 85, 0, 0, 0, 0, + 1, 86, 0, 0, 0, 0, + 1, 87, 0, 0, 0, 0, + 1, 88, 0, 0, 0, 0, + 1, 89, 0, 0, 0, 0, + 1, 90, 0, 0, 0, 0, + 1, 91, 0, 0, 0, 0, + 1, 92, 0, 0, 0, 0, + 1, 93, 0, 0, 0, 0, + 1, 94, 0, 0, 0, 0, + 1, 95, 0, 0, 0, 0, + 1, 96, 0, 0, 0, 0, + 1, 97, 0, 0, 0, 0, + 1, 98, 0, 0, 0, 0, + 1, 99, 0, 0, 0, 0, + 1, 100, 0, 0, 0, 0, + 1, 101, 0, 0, 0, 0, + 1, 102, 0, 0, 0, 0, + 1, 103, 0, 0, 0, 0, + 1, 104, 0, 0, 0, 0, + 1, 105, 0, 0, 0, 0, + 1, 106, 0, 0, 0, 0, + 1, 107, 0, 0, 0, 0, + 1, 108, 0, 0, 0, 0, + 1, 109, 0, 0, 0, 0, + 1, 110, 0, 0, 0, 0, + 1, 111, 0, 0, 0, 0, + 1, 112, 0, 0, 0, 0, + 1, 113, 0, 0, 0, 0, + 1, 114, 0, 0, 0, 0, + 1, 115, 0, 0, 0, 0, + 1, 116, 0, 0, 0, 0, + 1, 117, 0, 0, 0, 0, + 1, 118, 0, 0, 0, 0, + 1, 119, 0, 0, 0, 0, + 1, 120, 0, 0, 0, 0, + 1, 121, 0, 0, 0, 0, + 1, 122, 0, 0, 0, 0, + 1, 123, 0, 0, 0, 0, + 1, 124, 0, 0, 0, 0, + 1, 125, 0, 0, 0, 0, + 1, 126, 0, 0, 0, 0, + 1, 127, 0, 0, 0, 0, + 3, -30, -126, -84, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -102, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -98, 0, 0, + 3, -30, -128, -90, 0, 0, + 3, -30, -128, -96, 0, 0, + 3, -30, -128, -95, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -80, 0, 0, + 2, -59, -96, 0, 0, 0, + 3, -30, -128, -71, 0, 0, + 2, -59, -102, 0, 0, 0, + 2, -59, -92, 0, 0, 0, + 2, -59, -67, 0, 0, 0, + 2, -59, -71, 0, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -104, 0, 0, + 3, -30, -128, -103, 0, 0, + 3, -30, -128, -100, 0, 0, + 3, -30, -128, -99, 0, 0, + 3, -30, -128, -94, 0, 0, + 3, -30, -128, -109, 0, 0, + 3, -30, -128, -108, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -124, -94, 0, 0, + 2, -59, -95, 0, 0, 0, + 3, -30, -128, -70, 0, 0, + 2, -59, -101, 0, 0, 0, + 2, -59, -91, 0, 0, 0, + 2, -59, -66, 0, 0, 0, + 2, -59, -70, 0, 0, 0, + 2, -62, -96, 0, 0, 0, + 2, -53, -121, 0, 0, 0, + 2, -53, -104, 0, 0, 0, + 2, -59, -127, 0, 0, 0, + 2, -62, -92, 0, 0, 0, + 2, -60, -124, 0, 0, 0, + 2, -62, -90, 0, 0, 0, + 2, -62, -89, 0, 0, 0, + 2, -62, -88, 0, 0, 0, + 2, -62, -87, 0, 0, 0, + 2, -59, -98, 0, 0, 0, + 2, -62, -85, 0, 0, 0, + 2, -62, -84, 0, 0, 0, + 2, -62, -83, 0, 0, 0, + 2, -62, -82, 0, 0, 0, + 2, -59, -69, 0, 0, 0, + 2, -62, -80, 0, 0, 0, + 2, -62, -79, 0, 0, 0, + 2, -53, -101, 0, 0, 0, + 2, -59, -126, 0, 0, 0, + 2, -62, -76, 0, 0, 0, + 2, -62, -75, 0, 0, 0, + 2, -62, -74, 0, 0, 0, + 2, -62, -73, 0, 0, 0, + 2, -62, -72, 0, 0, 0, + 2, -60, -123, 0, 0, 0, + 2, -59, -97, 0, 0, 0, + 2, -62, -69, 0, 0, 0, + 2, -60, -67, 0, 0, 0, + 2, -53, -99, 0, 0, 0, + 2, -60, -66, 0, 0, 0, + 2, -59, -68, 0, 0, 0, + 2, -59, -108, 0, 0, 0, + 2, -61, -127, 0, 0, 0, + 2, -61, -126, 0, 0, 0, + 2, -60, -126, 0, 0, 0, + 2, -61, -124, 0, 0, 0, + 2, -60, -71, 0, 0, 0, + 2, -60, -122, 0, 0, 0, + 2, -61, -121, 0, 0, 0, + 2, -60, -116, 0, 0, 0, + 2, -61, -119, 0, 0, 0, + 2, -60, -104, 0, 0, 0, + 2, -61, -117, 0, 0, 0, + 2, -60, -102, 0, 0, 0, + 2, -61, -115, 0, 0, 0, + 2, -61, -114, 0, 0, 0, + 2, -60, -114, 0, 0, 0, + 2, -60, -112, 0, 0, 0, + 2, -59, -125, 0, 0, 0, + 2, -59, -121, 0, 0, 0, + 2, -61, -109, 0, 0, 0, + 2, -61, -108, 0, 0, 0, + 2, -59, -112, 0, 0, 0, + 2, -61, -106, 0, 0, 0, + 2, -61, -105, 0, 0, 0, + 2, -59, -104, 0, 0, 0, + 2, -59, -82, 0, 0, 0, + 2, -61, -102, 0, 0, 0, + 2, -59, -80, 0, 0, 0, + 2, -61, -100, 0, 0, 0, + 2, -61, -99, 0, 0, 0, + 2, -59, -94, 0, 0, 0, + 2, -61, -97, 0, 0, 0, + 2, -59, -107, 0, 0, 0, + 2, -61, -95, 0, 0, 0, + 2, -61, -94, 0, 0, 0, + 2, -60, -125, 0, 0, 0, + 2, -61, -92, 0, 0, 0, + 2, -60, -70, 0, 0, 0, + 2, -60, -121, 0, 0, 0, + 2, -61, -89, 0, 0, 0, + 2, -60, -115, 0, 0, 0, + 2, -61, -87, 0, 0, 0, + 2, -60, -103, 0, 0, 0, + 2, -61, -85, 0, 0, 0, + 2, -60, -101, 0, 0, 0, + 2, -61, -83, 0, 0, 0, + 2, -61, -82, 0, 0, 0, + 2, -60, -113, 0, 0, 0, + 2, -60, -111, 0, 0, 0, + 2, -59, -124, 0, 0, 0, + 2, -59, -120, 0, 0, 0, + 2, -61, -77, 0, 0, 0, + 2, -61, -76, 0, 0, 0, + 2, -59, -111, 0, 0, 0, + 2, -61, -74, 0, 0, 0, + 2, -61, -73, 0, 0, 0, + 2, -59, -103, 0, 0, 0, + 2, -59, -81, 0, 0, 0, + 2, -61, -70, 0, 0, 0, + 2, -59, -79, 0, 0, 0, + 2, -61, -68, 0, 0, 0, + 2, -61, -67, 0, 0, 0, + 2, -59, -93, 0, 0, 0, + 2, -53, -103, 0, 0, 0 }; /// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic /// and other languages static char windows_1251[] = { - (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x8, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x9, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xa, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xb, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xc, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xd, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xe, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xf, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x10, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x11, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x12, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x13, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x14, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x15, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x16, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x17, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x18, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x19, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x21, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x22, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x23, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x24, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x25, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x26, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x27, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x28, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x29, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x30, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x31, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x32, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x33, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x34, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x35, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x36, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x37, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x38, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x39, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x40, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x41, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x42, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x43, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x44, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x45, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x46, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x47, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x48, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x49, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x50, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x51, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x52, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x53, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x54, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x55, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x56, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x57, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x58, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x59, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x60, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x61, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x62, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x63, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x64, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x65, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x66, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x67, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x68, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x69, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x70, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x71, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x72, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x73, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x74, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x75, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x76, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x77, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x78, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x79, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x83, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9a, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x93, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9e, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa6, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa1, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x82, (char)0xac, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xb0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x89, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xb9, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x8a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x8c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x8b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x8f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x92, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x98, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x99, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9c, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9d, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa2, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x93, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x94, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x84, (char)0xa2, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x99, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xba, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x9c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x9f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x8e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x9e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x88, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd2, (char)0x90, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x81, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xac, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x86, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x96, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd2, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x84, (char)0x96, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x94, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x85, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x95, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x97, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x90, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x92, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x93, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x94, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x95, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x96, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x97, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x99, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0x9f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xaa, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xac, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xaf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xb9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xbc, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd0, (char)0xbf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x80, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x81, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x83, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x85, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x86, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x88, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x89, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xd1, (char)0x8f, (char)0x0, (char)0x0, (char)0x0 + 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 2, 0, 0, 0, 0, + 1, 3, 0, 0, 0, 0, + 1, 4, 0, 0, 0, 0, + 1, 5, 0, 0, 0, 0, + 1, 6, 0, 0, 0, 0, + 1, 7, 0, 0, 0, 0, + 1, 8, 0, 0, 0, 0, + 1, 9, 0, 0, 0, 0, + 1, 10, 0, 0, 0, 0, + 1, 11, 0, 0, 0, 0, + 1, 12, 0, 0, 0, 0, + 1, 13, 0, 0, 0, 0, + 1, 14, 0, 0, 0, 0, + 1, 15, 0, 0, 0, 0, + 1, 16, 0, 0, 0, 0, + 1, 17, 0, 0, 0, 0, + 1, 18, 0, 0, 0, 0, + 1, 19, 0, 0, 0, 0, + 1, 20, 0, 0, 0, 0, + 1, 21, 0, 0, 0, 0, + 1, 22, 0, 0, 0, 0, + 1, 23, 0, 0, 0, 0, + 1, 24, 0, 0, 0, 0, + 1, 25, 0, 0, 0, 0, + 1, 26, 0, 0, 0, 0, + 1, 27, 0, 0, 0, 0, + 1, 28, 0, 0, 0, 0, + 1, 29, 0, 0, 0, 0, + 1, 30, 0, 0, 0, 0, + 1, 31, 0, 0, 0, 0, + 1, 32, 0, 0, 0, 0, + 1, 33, 0, 0, 0, 0, + 1, 34, 0, 0, 0, 0, + 1, 35, 0, 0, 0, 0, + 1, 36, 0, 0, 0, 0, + 1, 37, 0, 0, 0, 0, + 1, 38, 0, 0, 0, 0, + 1, 39, 0, 0, 0, 0, + 1, 40, 0, 0, 0, 0, + 1, 41, 0, 0, 0, 0, + 1, 42, 0, 0, 0, 0, + 1, 43, 0, 0, 0, 0, + 1, 44, 0, 0, 0, 0, + 1, 45, 0, 0, 0, 0, + 1, 46, 0, 0, 0, 0, + 1, 47, 0, 0, 0, 0, + 1, 48, 0, 0, 0, 0, + 1, 49, 0, 0, 0, 0, + 1, 50, 0, 0, 0, 0, + 1, 51, 0, 0, 0, 0, + 1, 52, 0, 0, 0, 0, + 1, 53, 0, 0, 0, 0, + 1, 54, 0, 0, 0, 0, + 1, 55, 0, 0, 0, 0, + 1, 56, 0, 0, 0, 0, + 1, 57, 0, 0, 0, 0, + 1, 58, 0, 0, 0, 0, + 1, 59, 0, 0, 0, 0, + 1, 60, 0, 0, 0, 0, + 1, 61, 0, 0, 0, 0, + 1, 62, 0, 0, 0, 0, + 1, 63, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 1, 65, 0, 0, 0, 0, + 1, 66, 0, 0, 0, 0, + 1, 67, 0, 0, 0, 0, + 1, 68, 0, 0, 0, 0, + 1, 69, 0, 0, 0, 0, + 1, 70, 0, 0, 0, 0, + 1, 71, 0, 0, 0, 0, + 1, 72, 0, 0, 0, 0, + 1, 73, 0, 0, 0, 0, + 1, 74, 0, 0, 0, 0, + 1, 75, 0, 0, 0, 0, + 1, 76, 0, 0, 0, 0, + 1, 77, 0, 0, 0, 0, + 1, 78, 0, 0, 0, 0, + 1, 79, 0, 0, 0, 0, + 1, 80, 0, 0, 0, 0, + 1, 81, 0, 0, 0, 0, + 1, 82, 0, 0, 0, 0, + 1, 83, 0, 0, 0, 0, + 1, 84, 0, 0, 0, 0, + 1, 85, 0, 0, 0, 0, + 1, 86, 0, 0, 0, 0, + 1, 87, 0, 0, 0, 0, + 1, 88, 0, 0, 0, 0, + 1, 89, 0, 0, 0, 0, + 1, 90, 0, 0, 0, 0, + 1, 91, 0, 0, 0, 0, + 1, 92, 0, 0, 0, 0, + 1, 93, 0, 0, 0, 0, + 1, 94, 0, 0, 0, 0, + 1, 95, 0, 0, 0, 0, + 1, 96, 0, 0, 0, 0, + 1, 97, 0, 0, 0, 0, + 1, 98, 0, 0, 0, 0, + 1, 99, 0, 0, 0, 0, + 1, 100, 0, 0, 0, 0, + 1, 101, 0, 0, 0, 0, + 1, 102, 0, 0, 0, 0, + 1, 103, 0, 0, 0, 0, + 1, 104, 0, 0, 0, 0, + 1, 105, 0, 0, 0, 0, + 1, 106, 0, 0, 0, 0, + 1, 107, 0, 0, 0, 0, + 1, 108, 0, 0, 0, 0, + 1, 109, 0, 0, 0, 0, + 1, 110, 0, 0, 0, 0, + 1, 111, 0, 0, 0, 0, + 1, 112, 0, 0, 0, 0, + 1, 113, 0, 0, 0, 0, + 1, 114, 0, 0, 0, 0, + 1, 115, 0, 0, 0, 0, + 1, 116, 0, 0, 0, 0, + 1, 117, 0, 0, 0, 0, + 1, 118, 0, 0, 0, 0, + 1, 119, 0, 0, 0, 0, + 1, 120, 0, 0, 0, 0, + 1, 121, 0, 0, 0, 0, + 1, 122, 0, 0, 0, 0, + 1, 123, 0, 0, 0, 0, + 1, 124, 0, 0, 0, 0, + 1, 125, 0, 0, 0, 0, + 1, 126, 0, 0, 0, 0, + 1, 127, 0, 0, 0, 0, + 2, -48, -126, 0, 0, 0, + 2, -48, -125, 0, 0, 0, + 3, -30, -128, -102, 0, 0, + 2, -47, -109, 0, 0, 0, + 3, -30, -128, -98, 0, 0, + 3, -30, -128, -90, 0, 0, + 3, -30, -128, -96, 0, 0, + 3, -30, -128, -95, 0, 0, + 3, -30, -126, -84, 0, 0, + 3, -30, -128, -80, 0, 0, + 2, -48, -119, 0, 0, 0, + 3, -30, -128, -71, 0, 0, + 2, -48, -118, 0, 0, 0, + 2, -48, -116, 0, 0, 0, + 2, -48, -117, 0, 0, 0, + 2, -48, -113, 0, 0, 0, + 2, -47, -110, 0, 0, 0, + 3, -30, -128, -104, 0, 0, + 3, -30, -128, -103, 0, 0, + 3, -30, -128, -100, 0, 0, + 3, -30, -128, -99, 0, 0, + 3, -30, -128, -94, 0, 0, + 3, -30, -128, -109, 0, 0, + 3, -30, -128, -108, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -124, -94, 0, 0, + 2, -47, -103, 0, 0, 0, + 3, -30, -128, -70, 0, 0, + 2, -47, -102, 0, 0, 0, + 2, -47, -100, 0, 0, 0, + 2, -47, -101, 0, 0, 0, + 2, -47, -97, 0, 0, 0, + 2, -62, -96, 0, 0, 0, + 2, -48, -114, 0, 0, 0, + 2, -47, -98, 0, 0, 0, + 2, -48, -120, 0, 0, 0, + 2, -62, -92, 0, 0, 0, + 2, -46, -112, 0, 0, 0, + 2, -62, -90, 0, 0, 0, + 2, -62, -89, 0, 0, 0, + 2, -48, -127, 0, 0, 0, + 2, -62, -87, 0, 0, 0, + 2, -48, -124, 0, 0, 0, + 2, -62, -85, 0, 0, 0, + 2, -62, -84, 0, 0, 0, + 2, -62, -83, 0, 0, 0, + 2, -62, -82, 0, 0, 0, + 2, -48, -121, 0, 0, 0, + 2, -62, -80, 0, 0, 0, + 2, -62, -79, 0, 0, 0, + 2, -48, -122, 0, 0, 0, + 2, -47, -106, 0, 0, 0, + 2, -46, -111, 0, 0, 0, + 2, -62, -75, 0, 0, 0, + 2, -62, -74, 0, 0, 0, + 2, -62, -73, 0, 0, 0, + 2, -47, -111, 0, 0, 0, + 3, -30, -124, -106, 0, 0, + 2, -47, -108, 0, 0, 0, + 2, -62, -69, 0, 0, 0, + 2, -47, -104, 0, 0, 0, + 2, -48, -123, 0, 0, 0, + 2, -47, -107, 0, 0, 0, + 2, -47, -105, 0, 0, 0, + 2, -48, -112, 0, 0, 0, + 2, -48, -111, 0, 0, 0, + 2, -48, -110, 0, 0, 0, + 2, -48, -109, 0, 0, 0, + 2, -48, -108, 0, 0, 0, + 2, -48, -107, 0, 0, 0, + 2, -48, -106, 0, 0, 0, + 2, -48, -105, 0, 0, 0, + 2, -48, -104, 0, 0, 0, + 2, -48, -103, 0, 0, 0, + 2, -48, -102, 0, 0, 0, + 2, -48, -101, 0, 0, 0, + 2, -48, -100, 0, 0, 0, + 2, -48, -99, 0, 0, 0, + 2, -48, -98, 0, 0, 0, + 2, -48, -97, 0, 0, 0, + 2, -48, -96, 0, 0, 0, + 2, -48, -95, 0, 0, 0, + 2, -48, -94, 0, 0, 0, + 2, -48, -93, 0, 0, 0, + 2, -48, -92, 0, 0, 0, + 2, -48, -91, 0, 0, 0, + 2, -48, -90, 0, 0, 0, + 2, -48, -89, 0, 0, 0, + 2, -48, -88, 0, 0, 0, + 2, -48, -87, 0, 0, 0, + 2, -48, -86, 0, 0, 0, + 2, -48, -85, 0, 0, 0, + 2, -48, -84, 0, 0, 0, + 2, -48, -83, 0, 0, 0, + 2, -48, -82, 0, 0, 0, + 2, -48, -81, 0, 0, 0, + 2, -48, -80, 0, 0, 0, + 2, -48, -79, 0, 0, 0, + 2, -48, -78, 0, 0, 0, + 2, -48, -77, 0, 0, 0, + 2, -48, -76, 0, 0, 0, + 2, -48, -75, 0, 0, 0, + 2, -48, -74, 0, 0, 0, + 2, -48, -73, 0, 0, 0, + 2, -48, -72, 0, 0, 0, + 2, -48, -71, 0, 0, 0, + 2, -48, -70, 0, 0, 0, + 2, -48, -69, 0, 0, 0, + 2, -48, -68, 0, 0, 0, + 2, -48, -67, 0, 0, 0, + 2, -48, -66, 0, 0, 0, + 2, -48, -65, 0, 0, 0, + 2, -47, -128, 0, 0, 0, + 2, -47, -127, 0, 0, 0, + 2, -47, -126, 0, 0, 0, + 2, -47, -125, 0, 0, 0, + 2, -47, -124, 0, 0, 0, + 2, -47, -123, 0, 0, 0, + 2, -47, -122, 0, 0, 0, + 2, -47, -121, 0, 0, 0, + 2, -47, -120, 0, 0, 0, + 2, -47, -119, 0, 0, 0, + 2, -47, -118, 0, 0, 0, + 2, -47, -117, 0, 0, 0, + 2, -47, -116, 0, 0, 0, + 2, -47, -115, 0, 0, 0, + 2, -47, -114, 0, 0, 0, + 2, -47, -113, 0, 0, 0 }; /// Latin alphabet used by English and some other Western languages static char windows_1252[] = { - (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x8, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x9, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xa, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xb, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xc, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xd, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xe, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0xf, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x10, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x11, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x12, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x13, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x14, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x15, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x16, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x17, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x18, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x19, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x1f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x21, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x22, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x23, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x24, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x25, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x26, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x27, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x28, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x29, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x2f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x30, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x31, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x32, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x33, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x34, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x35, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x36, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x37, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x38, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x39, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x3f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x40, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x41, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x42, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x43, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x44, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x45, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x46, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x47, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x48, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x49, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x4f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x50, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x51, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x52, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x53, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x54, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x55, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x56, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x57, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x58, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x59, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x5f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x60, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x61, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x62, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x63, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x64, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x65, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x66, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x67, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x68, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x69, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x6f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x70, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x71, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x72, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x73, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x74, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x75, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x76, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x77, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x78, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x79, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7a, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7b, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7c, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7d, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7e, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x7f, (char)0x0, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x82, (char)0xac, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0x9a, (char)0x0, (char)0x0, - (char)0x2, (char)0xc6, (char)0x92, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9e, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa6, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa1, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x86, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xb0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xb9, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x92, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x2, (char)0xc5, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x3, (char)0xe2, (char)0x80, (char)0x98, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x99, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9c, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x9d, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xa2, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x93, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0x94, (char)0x0, (char)0x0, - (char)0x2, (char)0xcb, (char)0x9c, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x84, (char)0xa2, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x3, (char)0xe2, (char)0x80, (char)0xba, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0x93, (char)0x0, (char)0x0, (char)0x0, - (char)0x1, (char)0x20, (char)0x0, (char)0x0, (char)0x0, (char)0x0, // not part of this charset - (char)0x2, (char)0xc5, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc5, (char)0xb8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xaa, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xac, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xaf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xb9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbc, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc2, (char)0xbf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x80, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x81, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x82, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x83, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x84, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x85, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x86, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x87, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x88, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x89, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x8f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x90, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x91, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x92, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x93, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x94, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x95, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x96, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x97, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x98, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x99, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9a, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9b, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9c, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9d, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9e, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0x9f, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xa9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xaa, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xab, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xac, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xad, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xae, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xaf, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb0, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb1, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb2, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb3, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb4, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb5, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb6, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb7, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb8, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xb9, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xba, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbb, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbc, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbd, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbe, (char)0x0, (char)0x0, (char)0x0, - (char)0x2, (char)0xc3, (char)0xbf, (char)0x0, (char)0x0, (char)0x0 + 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 2, 0, 0, 0, 0, + 1, 3, 0, 0, 0, 0, + 1, 4, 0, 0, 0, 0, + 1, 5, 0, 0, 0, 0, + 1, 6, 0, 0, 0, 0, + 1, 7, 0, 0, 0, 0, + 1, 8, 0, 0, 0, 0, + 1, 9, 0, 0, 0, 0, + 1, 10, 0, 0, 0, 0, + 1, 11, 0, 0, 0, 0, + 1, 12, 0, 0, 0, 0, + 1, 13, 0, 0, 0, 0, + 1, 14, 0, 0, 0, 0, + 1, 15, 0, 0, 0, 0, + 1, 16, 0, 0, 0, 0, + 1, 17, 0, 0, 0, 0, + 1, 18, 0, 0, 0, 0, + 1, 19, 0, 0, 0, 0, + 1, 20, 0, 0, 0, 0, + 1, 21, 0, 0, 0, 0, + 1, 22, 0, 0, 0, 0, + 1, 23, 0, 0, 0, 0, + 1, 24, 0, 0, 0, 0, + 1, 25, 0, 0, 0, 0, + 1, 26, 0, 0, 0, 0, + 1, 27, 0, 0, 0, 0, + 1, 28, 0, 0, 0, 0, + 1, 29, 0, 0, 0, 0, + 1, 30, 0, 0, 0, 0, + 1, 31, 0, 0, 0, 0, + 1, 32, 0, 0, 0, 0, + 1, 33, 0, 0, 0, 0, + 1, 34, 0, 0, 0, 0, + 1, 35, 0, 0, 0, 0, + 1, 36, 0, 0, 0, 0, + 1, 37, 0, 0, 0, 0, + 1, 38, 0, 0, 0, 0, + 1, 39, 0, 0, 0, 0, + 1, 40, 0, 0, 0, 0, + 1, 41, 0, 0, 0, 0, + 1, 42, 0, 0, 0, 0, + 1, 43, 0, 0, 0, 0, + 1, 44, 0, 0, 0, 0, + 1, 45, 0, 0, 0, 0, + 1, 46, 0, 0, 0, 0, + 1, 47, 0, 0, 0, 0, + 1, 48, 0, 0, 0, 0, + 1, 49, 0, 0, 0, 0, + 1, 50, 0, 0, 0, 0, + 1, 51, 0, 0, 0, 0, + 1, 52, 0, 0, 0, 0, + 1, 53, 0, 0, 0, 0, + 1, 54, 0, 0, 0, 0, + 1, 55, 0, 0, 0, 0, + 1, 56, 0, 0, 0, 0, + 1, 57, 0, 0, 0, 0, + 1, 58, 0, 0, 0, 0, + 1, 59, 0, 0, 0, 0, + 1, 60, 0, 0, 0, 0, + 1, 61, 0, 0, 0, 0, + 1, 62, 0, 0, 0, 0, + 1, 63, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 1, 65, 0, 0, 0, 0, + 1, 66, 0, 0, 0, 0, + 1, 67, 0, 0, 0, 0, + 1, 68, 0, 0, 0, 0, + 1, 69, 0, 0, 0, 0, + 1, 70, 0, 0, 0, 0, + 1, 71, 0, 0, 0, 0, + 1, 72, 0, 0, 0, 0, + 1, 73, 0, 0, 0, 0, + 1, 74, 0, 0, 0, 0, + 1, 75, 0, 0, 0, 0, + 1, 76, 0, 0, 0, 0, + 1, 77, 0, 0, 0, 0, + 1, 78, 0, 0, 0, 0, + 1, 79, 0, 0, 0, 0, + 1, 80, 0, 0, 0, 0, + 1, 81, 0, 0, 0, 0, + 1, 82, 0, 0, 0, 0, + 1, 83, 0, 0, 0, 0, + 1, 84, 0, 0, 0, 0, + 1, 85, 0, 0, 0, 0, + 1, 86, 0, 0, 0, 0, + 1, 87, 0, 0, 0, 0, + 1, 88, 0, 0, 0, 0, + 1, 89, 0, 0, 0, 0, + 1, 90, 0, 0, 0, 0, + 1, 91, 0, 0, 0, 0, + 1, 92, 0, 0, 0, 0, + 1, 93, 0, 0, 0, 0, + 1, 94, 0, 0, 0, 0, + 1, 95, 0, 0, 0, 0, + 1, 96, 0, 0, 0, 0, + 1, 97, 0, 0, 0, 0, + 1, 98, 0, 0, 0, 0, + 1, 99, 0, 0, 0, 0, + 1, 100, 0, 0, 0, 0, + 1, 101, 0, 0, 0, 0, + 1, 102, 0, 0, 0, 0, + 1, 103, 0, 0, 0, 0, + 1, 104, 0, 0, 0, 0, + 1, 105, 0, 0, 0, 0, + 1, 106, 0, 0, 0, 0, + 1, 107, 0, 0, 0, 0, + 1, 108, 0, 0, 0, 0, + 1, 109, 0, 0, 0, 0, + 1, 110, 0, 0, 0, 0, + 1, 111, 0, 0, 0, 0, + 1, 112, 0, 0, 0, 0, + 1, 113, 0, 0, 0, 0, + 1, 114, 0, 0, 0, 0, + 1, 115, 0, 0, 0, 0, + 1, 116, 0, 0, 0, 0, + 1, 117, 0, 0, 0, 0, + 1, 118, 0, 0, 0, 0, + 1, 119, 0, 0, 0, 0, + 1, 120, 0, 0, 0, 0, + 1, 121, 0, 0, 0, 0, + 1, 122, 0, 0, 0, 0, + 1, 123, 0, 0, 0, 0, + 1, 124, 0, 0, 0, 0, + 1, 125, 0, 0, 0, 0, + 1, 126, 0, 0, 0, 0, + 1, 127, 0, 0, 0, 0, + 3, -30, -126, -84, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -102, 0, 0, + 2, -58, -110, 0, 0, 0, + 3, -30, -128, -98, 0, 0, + 3, -30, -128, -90, 0, 0, + 3, -30, -128, -96, 0, 0, + 3, -30, -128, -95, 0, 0, + 2, -53, -122, 0, 0, 0, + 3, -30, -128, -80, 0, 0, + 2, -59, -96, 0, 0, 0, + 3, -30, -128, -71, 0, 0, + 2, -59, -110, 0, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 2, -59, -67, 0, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 1, 32, 0, 0, 0, 0, // not part of this charset + 3, -30, -128, -104, 0, 0, + 3, -30, -128, -103, 0, 0, + 3, -30, -128, -100, 0, 0, + 3, -30, -128, -99, 0, 0, + 3, -30, -128, -94, 0, 0, + 3, -30, -128, -109, 0, 0, + 3, -30, -128, -108, 0, 0, + 2, -53, -100, 0, 0, 0, + 3, -30, -124, -94, 0, 0, + 2, -59, -95, 0, 0, 0, + 3, -30, -128, -70, 0, 0, + 2, -59, -109, 0, 0, 0, + 1, 32, 0, 0, 0, 0, // not part of this charset + 2, -59, -66, 0, 0, 0, + 2, -59, -72, 0, 0, 0, + 2, -62, -96, 0, 0, 0, + 2, -62, -95, 0, 0, 0, + 2, -62, -94, 0, 0, 0, + 2, -62, -93, 0, 0, 0, + 2, -62, -92, 0, 0, 0, + 2, -62, -91, 0, 0, 0, + 2, -62, -90, 0, 0, 0, + 2, -62, -89, 0, 0, 0, + 2, -62, -88, 0, 0, 0, + 2, -62, -87, 0, 0, 0, + 2, -62, -86, 0, 0, 0, + 2, -62, -85, 0, 0, 0, + 2, -62, -84, 0, 0, 0, + 2, -62, -83, 0, 0, 0, + 2, -62, -82, 0, 0, 0, + 2, -62, -81, 0, 0, 0, + 2, -62, -80, 0, 0, 0, + 2, -62, -79, 0, 0, 0, + 2, -62, -78, 0, 0, 0, + 2, -62, -77, 0, 0, 0, + 2, -62, -76, 0, 0, 0, + 2, -62, -75, 0, 0, 0, + 2, -62, -74, 0, 0, 0, + 2, -62, -73, 0, 0, 0, + 2, -62, -72, 0, 0, 0, + 2, -62, -71, 0, 0, 0, + 2, -62, -70, 0, 0, 0, + 2, -62, -69, 0, 0, 0, + 2, -62, -68, 0, 0, 0, + 2, -62, -67, 0, 0, 0, + 2, -62, -66, 0, 0, 0, + 2, -62, -65, 0, 0, 0, + 2, -61, -128, 0, 0, 0, + 2, -61, -127, 0, 0, 0, + 2, -61, -126, 0, 0, 0, + 2, -61, -125, 0, 0, 0, + 2, -61, -124, 0, 0, 0, + 2, -61, -123, 0, 0, 0, + 2, -61, -122, 0, 0, 0, + 2, -61, -121, 0, 0, 0, + 2, -61, -120, 0, 0, 0, + 2, -61, -119, 0, 0, 0, + 2, -61, -118, 0, 0, 0, + 2, -61, -117, 0, 0, 0, + 2, -61, -116, 0, 0, 0, + 2, -61, -115, 0, 0, 0, + 2, -61, -114, 0, 0, 0, + 2, -61, -113, 0, 0, 0, + 2, -61, -112, 0, 0, 0, + 2, -61, -111, 0, 0, 0, + 2, -61, -110, 0, 0, 0, + 2, -61, -109, 0, 0, 0, + 2, -61, -108, 0, 0, 0, + 2, -61, -107, 0, 0, 0, + 2, -61, -106, 0, 0, 0, + 2, -61, -105, 0, 0, 0, + 2, -61, -104, 0, 0, 0, + 2, -61, -103, 0, 0, 0, + 2, -61, -102, 0, 0, 0, + 2, -61, -101, 0, 0, 0, + 2, -61, -100, 0, 0, 0, + 2, -61, -99, 0, 0, 0, + 2, -61, -98, 0, 0, 0, + 2, -61, -97, 0, 0, 0, + 2, -61, -96, 0, 0, 0, + 2, -61, -95, 0, 0, 0, + 2, -61, -94, 0, 0, 0, + 2, -61, -93, 0, 0, 0, + 2, -61, -92, 0, 0, 0, + 2, -61, -91, 0, 0, 0, + 2, -61, -90, 0, 0, 0, + 2, -61, -89, 0, 0, 0, + 2, -61, -88, 0, 0, 0, + 2, -61, -87, 0, 0, 0, + 2, -61, -86, 0, 0, 0, + 2, -61, -85, 0, 0, 0, + 2, -61, -84, 0, 0, 0, + 2, -61, -83, 0, 0, 0, + 2, -61, -82, 0, 0, 0, + 2, -61, -81, 0, 0, 0, + 2, -61, -80, 0, 0, 0, + 2, -61, -79, 0, 0, 0, + 2, -61, -78, 0, 0, 0, + 2, -61, -77, 0, 0, 0, + 2, -61, -76, 0, 0, 0, + 2, -61, -75, 0, 0, 0, + 2, -61, -74, 0, 0, 0, + 2, -61, -73, 0, 0, 0, + 2, -61, -72, 0, 0, 0, + 2, -61, -71, 0, 0, 0, + 2, -61, -70, 0, 0, 0, + 2, -61, -69, 0, 0, 0, + 2, -61, -68, 0, 0, 0, + 2, -61, -67, 0, 0, 0, + 2, -61, -66, 0, 0, 0, + 2, -61, -65, 0, 0, 0 }; } diff --git a/credits.txt b/credits.txt index 3a942bfd8a..62e41ff0bf 100644 --- a/credits.txt +++ b/credits.txt @@ -1,59 +1,114 @@ -CREDITS +Contributors + +The OpenMW project was started in 2008 by Nicolay Korslund. +In the course of years many people have contributed to the project. + +If you feel your name is missing from this list, +please notify a developer. + + +Programmers: +Marc Zinnschlag (Zini) - Lead Programmer/Project Manager -Current Developers: Aleksandar Jovanov -Alexander “Ace†Olofsson -Artem “greye†Kotsynyak +Alexander Olofsson (Ace) +Artem Kotsynyak (greye) athile BrotherBrick -Cris “Mirceam†Mihalache +Cris Mihalache (Mirceam) +Douglas Diniz (Dgdiniz) +Eli2 gugus / gus -Jacob “Yacoby†Essex -Jannik “scrawl†Heller -Jason “jhooks†Hooks -Karl-Felix “k1ll†Glatzer -Lukasz “lgro†Gromanowski -Marc “Zini†Zinnschlag -Michael “werdanith†Papageorgiou -Nikolay “corristo†Kasyanov -Pieter “pvdk†van der Kloet -Roman "Kromgart" Melnik -Sebastian “swick†Wick -Sylvain "Garvek" T. +Jacob Essex (Yacoby) +Jannik Heller (scrawl) +Jason Hooks (jhooks) +Karl-Felix Glatzer (k1ll) +Lukasz Gromanowski (lgro) +Michael Mc Donnell +Michael Papageorgiou (werdanith) +Nikolay Kasyanov (corristo) +Pieter van der Kloet (pvdk) +Roman Melnik (Kromgart) +Sebastian Wick (swick) +Sylvain T. (Garvek) -Retired Developers: + +Packagers: +Alexander Olofsson (Ace) - Windows +BrotherBrick - Ubuntu Linux +Edmondo Tommasina - Gentoo Linux +Kenny Armstrong (artorius) - Fedora Linux +Nikolay Kasyanov (corristo) - Mac OS X +Sandy Carter (bwrsandman) - Arch Linux + + +Public Relations: +ElderTroll - Release Manager +sir_herrbatka - News Writer +WeirdSexy - Podcaster + + +Website: +juanmnzsk8 - Spanish News Writer +Julien Voisin (jvoisin/ap0) - French News Writer +Kingpix - Italian News Writer +Lukasz Gromanowski (lgro) - Website Administrator +Nikolay Kasyanov (corristo) - Russian News Writer +Okulo - Dutch News Writer +penguinroad - Indonesian News Writer +Ryan Sardonic (Wry) - Wiki Editor +sir_herrbatka - Forum Admin/Polish News Writer +spyboot - German News Writer + + +Formula Research: +Epsilon +fragonard +Greendogo +HiPhish +modred11 +Myckel +natirips +Sadler + + +Artwork: +Necrod - OpenMW Logo +raevol - Wordpress Theme + + +Inactive Contributors: Ardekantur Armin Preiml Diggory Hardy Jan Borsodi -Jan-Peter “peppe†Nilsson +Jan-Peter Nilsson (peppe) Josua Grawitter +Lordrea Nicolay Korslund sergoz Star-Demon Yuri Krupenin -PR team and Translators: -Julien (jvoisin/ap0) Voisin -sirherrbatka -ElderTroll -spyboot -corristo -Okulo -penguinroad -Kingpix -Reverser and Research: -natirips -Sadler -fragonard -Greendogo -Myckel -modred11 -HiPhish +Additional Credits: +In this section we would like to thank people not part of OpenMW for their work. -OpenMW: -Thanks to DokterDume for kindly providing us with the Moon and Star logo used as the application icon and project logo. +Thanks to Maxim Nikolaev, +for allowing us to use his excellent Morrowind fan-art on our website and in other places. -Launcher: -Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Files tab. +Thanks to DokterDume, +for kindly providing us with the Moon and Star logo, +used as the application icon and project logo. + +Thanks to Kevin Ryan, +for creating the icon used for the Data Files tab of the OpenMW Launcher. + +Thanks to Georg Duffner, +for the open-source EB Garamond fontface. + +Thanks to Dongle, +for his Daedric fontface, see Daedric Font License.txt for his license terms. + +Thanks to Bitstream Inc. +for their Bitstream Vera fontface, see Bitstream Vera License.txt for their license terms. diff --git a/extern/oics/CMakeLists.txt b/extern/oics/CMakeLists.txt new file mode 100644 index 0000000000..7c14387a4b --- /dev/null +++ b/extern/oics/CMakeLists.txt @@ -0,0 +1,20 @@ +set(OICS_LIBRARY "oics") + +# Sources + +set(OICS_SOURCE_FILES + ICSChannel.cpp + ICSControl.cpp + ICSInputControlSystem.cpp + ICSInputControlSystem_keyboard.cpp + ICSInputControlSystem_mouse.cpp + ICSInputControlSystem_joystick.cpp + tinyxml.cpp + tinyxmlparser.cpp + tinyxmlerror.cpp + tinystr.cpp +) + +add_library(${OICS_LIBRARY} STATIC ${OICS_SOURCE_FILES}) + +link_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/extern/oics/ICSChannel.cpp b/extern/oics/ICSChannel.cpp new file mode 100644 index 0000000000..703f2207c9 --- /dev/null +++ b/extern/oics/ICSChannel.cpp @@ -0,0 +1,258 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +#define B1(t) (t*t) +#define B2(t) (2*t*(1-t)) +#define B3(t) ((1-t)*(1-t)) + +namespace ICS +{ + Channel::Channel(int number, float initialValue + , float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep) + : mNumber(number) + , mValue(initialValue) + , mSymmetricAt(symmetricAt) + , mBezierStep(bezierStep) + { + mBezierMidPoint.x = bezierMidPointX; + mBezierMidPoint.y = bezierMidPointY; + + setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep); + } + + float Channel::getValue() + { + if(mValue == 0 || mValue == 1) + { + return mValue; + } + + BezierFunction::iterator it = mBezierFunction.begin(); + //size_t size_minus_1 = mBezierFunction.size() - 1; + BezierFunction::iterator last = mBezierFunction.end(); + last--; + for ( ; it != last ; ) + { + BezierPoint left = (*it); + BezierPoint right = (*(++it)); + + if( (left.x <= mValue) && (right.x > mValue) ) + { + float val = left.y - (left.x - mValue) * (left.y - right.y) / (left.x - right.x); + + return std::max(0.0,std::min(1.0, val)); + } + } + + return -1; + } + + void Channel::setValue(float value) + { + float previousValue = this->getValue(); + + mValue = value; + + if(previousValue != value) + { + notifyListeners(previousValue); + } + } + + void Channel::notifyListeners(float previousValue) + { + std::list::iterator pos = mListeners.begin(); + while (pos != mListeners.end()) + { + ((ChannelListener* )(*pos))->channelChanged((Channel*)this, this->getValue(), previousValue); + ++pos; + } + } + + void Channel::addControl(Control* control, Channel::ChannelDirection dir, float percentage) + { + ControlChannelBinderItem ccBinderItem; + ccBinderItem.control = control; + ccBinderItem.direction = dir; + ccBinderItem.percentage = percentage; + + mAttachedControls.push_back(ccBinderItem); + } + + Channel::ControlChannelBinderItem Channel::getAttachedControlBinding(Control* control) + { + for(std::vector::iterator it = mAttachedControls.begin() ; + it != mAttachedControls.end() ; it++) + { + if((*it).control == control) + { + return (*it); + } + } + + ControlChannelBinderItem nullBinderItem; + nullBinderItem.control = NULL; + nullBinderItem.direction = Channel/*::ChannelDirection*/::DIRECT; + nullBinderItem.percentage = 0; + return nullBinderItem; + } + + void Channel::update() + { + if(this->getControlsCount() == 1) + { + ControlChannelBinderItem ccBinderItem = mAttachedControls.back(); + float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue(); + + if(ccBinderItem.direction == ICS::Channel::DIRECT) + { + this->setValue(ccBinderItem.control->getInitialValue() + (ccBinderItem.percentage * diff)); + } + else + { + this->setValue(ccBinderItem.control->getInitialValue() - (ccBinderItem.percentage * diff)); + } + } + else + { + float val = 0; + std::vector::const_iterator it; + for(it=mAttachedControls.begin(); it!=mAttachedControls.end(); ++it) + { + ControlChannelBinderItem ccBinderItem = (*it); + float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue(); + + if(ccBinderItem.direction == ICS::Channel::DIRECT) + { + val += (ccBinderItem.percentage * diff); + } + else + { + val -= (ccBinderItem.percentage * diff); + } + } + + if(mAttachedControls.size() > 0) + { + this->setValue(mAttachedControls.begin()->control->getInitialValue() + val); + } + } + } + + void Channel::setBezierFunction(float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep) + { + mBezierMidPoint.x = bezierMidPointX; + mBezierMidPoint.y = bezierMidPointY; + mBezierStep = bezierStep; + mSymmetricAt = symmetricAt; + + mBezierFunction.clear(); + + BezierPoint start; + start.x = 0; + start.y = 0; + + BezierPoint end; + end.x = 1; + end.y = 1; + mBezierFunction.push_front(end); + + FilterInterval interval; + interval.startX = start.x; + interval.startY = start.y; + interval.midX = mBezierMidPoint.x; + interval.midY = mBezierMidPoint.y; + interval.endX = end.x; + interval.endY = end.y; + interval.step = bezierStep; + mIntervals.push_back(interval); + + if(!(mBezierMidPoint.x == 0.5 && mBezierMidPoint.y == 0.5)) + { + float t = mBezierStep; + while(t < 1) + { + BezierPoint p; + p.x = start.x * B1(t) + mBezierMidPoint.x * B2(t) + end.x * B3(t); + p.y = start.y * B1(t) + mBezierMidPoint.y * B2(t) + end.y * B3(t); + mBezierFunction.push_front(p); + + t += mBezierStep; + } + } + + mBezierFunction.push_front(start); + } + + void Channel::addBezierInterval(float startX, float startY, float midX, float midY + , float endX, float endY, float step) + { + FilterInterval interval; + interval.startX = startX; + interval.startY = startY; + interval.midX = midX; + interval.midY = midY; + interval.endX = endX; + interval.endY = endY; + interval.step = step; + mIntervals.push_back(interval); + + float t = 0; + while(t <= 1) + { + BezierPoint p; + p.x = startX * B1(t) + midX * B2(t) + endX * B3(t); + p.y = startY * B1(t) + midY * B2(t) + endY * B3(t); + + BezierFunction::iterator it = mBezierFunction.begin(); + while( it != mBezierFunction.end() ) + { + BezierPoint left = (*it); + BezierPoint right; + ++it; + if( it != mBezierFunction.end() ) + { + right = (*it); + } + else + { + right.x = endX; + right.y = endY; + } + + if(p.x > left.x && p.x < right.x) + { + mBezierFunction.insert(it, p); + break; + } + } + + t += 1.0f / ((endX-startX)/step); + } + } +} \ No newline at end of file diff --git a/extern/oics/ICSChannel.h b/extern/oics/ICSChannel.h new file mode 100644 index 0000000000..f98f0d94d3 --- /dev/null +++ b/extern/oics/ICSChannel.h @@ -0,0 +1,122 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#ifndef _Channel_H_ +#define _Channel_H_ + +#include "ICSPrerequisites.h" + +#include "ICSChannelListener.h" + +namespace ICS +{ + struct FilterInterval{ + //std::string type; //! @todo uncomment when more types implemented + float startX; + float startY; + float midX; + float midY; + float endX; + float endY; + float step; + }; + + typedef std::list IntervalList; + + class DllExport Channel + { + public: + enum ChannelDirection + { + INVERSE = -1, DIRECT = 1 + }; + + typedef struct { + ChannelDirection direction; + float percentage; + Control* control; + } ControlChannelBinderItem; + + + Channel(int number, float initialValue = 0.5 + , float bezierMidPointY = 0.5, float bezierMidPointX = 0.5 + , float symmetricAt = 0, float bezierStep = 0.2); //! @todo implement symetry + ~Channel(){}; + + void setValue(float value); + float getValue(); + + inline int getNumber(){ return mNumber; }; + + void addControl(Control* control, Channel::ChannelDirection dir, float percentage); + inline size_t getControlsCount(){ return mAttachedControls.size(); }; + std::vector getAttachedControls(){ return mAttachedControls; }; + ControlChannelBinderItem getAttachedControlBinding(Control* control); + + void addListener(ChannelListener* ob){ mListeners.push_back(ob); }; + void removeListener(ChannelListener* ob){ mListeners.remove(ob); }; + + void update(); + + void setBezierFunction(float bezierMidPointY, float bezierMidPointX = 0.5 + , float symmetricAt = 0, float bezierStep = 0.2); + + void addBezierInterval(float startX, float startY, float midX, float midY + , float endX, float endY, float step = 0.1); + + IntervalList& getIntervals(){ return mIntervals; }; + + protected: + + int mNumber; + float mValue; + + struct BezierPoint{ + float x; + float y; + bool operator < (const BezierPoint& other){ return x < other.x; } + }; + + typedef std::list BezierFunction; + + BezierPoint mBezierMidPoint; + BezierFunction mBezierFunction; + float mSymmetricAt; + float mBezierStep; + + IntervalList mIntervals; + + std::vector mAttachedControls; + + std::list mListeners; + void notifyListeners(float previousValue); + + }; + +} + + +#endif \ No newline at end of file diff --git a/extern/oics/ICSChannelListener.h b/extern/oics/ICSChannelListener.h new file mode 100644 index 0000000000..d520b3bceb --- /dev/null +++ b/extern/oics/ICSChannelListener.h @@ -0,0 +1,46 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#ifndef _ChannelListener_H_ +#define _ChannelListener_H_ + +#include "ICSPrerequisites.h" + +#include "ICSChannel.h" + +namespace ICS +{ + + class DllExport ChannelListener + { + public: + virtual void channelChanged(Channel* channel, float currentValue, float previousValue) = 0; + }; + +} + + +#endif \ No newline at end of file diff --git a/extern/oics/ICSControl.cpp b/extern/oics/ICSControl.cpp new file mode 100644 index 0000000000..d43733727f --- /dev/null +++ b/extern/oics/ICSControl.cpp @@ -0,0 +1,161 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +#include "ICSControl.h" + +namespace ICS +{ + Control::Control(const std::string name, bool autoChangeDirectionOnLimitsAfterStop, bool autoReverseToInitialValue + , float initialValue, float stepSize, float stepsPerSeconds, bool axisBindable) + : mName(name) + , mValue(initialValue) + , mInitialValue(initialValue) + , mStepSize(stepSize) + , mStepsPerSeconds(stepsPerSeconds) + , mAutoReverseToInitialValue(autoReverseToInitialValue) + , mIgnoreAutoReverse(false) + , mAutoChangeDirectionOnLimitsAfterStop(autoChangeDirectionOnLimitsAfterStop) + , mAxisBindable(axisBindable) + , currentChangingDirection(STOP) + { + + } + + Control::~Control() + { + mAttachedChannels.clear(); + } + + void Control::setValue(float value) + { + float previousValue = mValue; + + mValue = std::max(0.0,std::min(1.0,value)); + + if(mValue != previousValue) + { + updateChannels(); + + notifyListeners(previousValue); + } + } + + void Control::attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage) + { + mAttachedChannels.push_back(channel); + channel->addControl(this, direction, percentage); + } + + void Control::updateChannels() + { + std::list::iterator pos = mAttachedChannels.begin(); + while (pos != mAttachedChannels.end()) + { + ((Channel* )(*pos))->update(); + ++pos; + } + } + + void Control::notifyListeners(float previousValue) + { + std::list::iterator pos = mListeners.begin(); + while (pos != mListeners.end()) + { + ((ControlListener* )(*pos))->controlChanged((Control*)this, this->getValue(), previousValue); + ++pos; + } + } + + void Control::setChangingDirection(ControlChangingDirection direction) + { + currentChangingDirection = direction; + mPendingActions.push_back(direction); + } + + void Control::update(float timeSinceLastFrame) + { + if(mPendingActions.size() > 0) + { + size_t timedActionsCount = 0; + + std::list::iterator cached_end = mPendingActions.end(); + for(std::list::iterator it = mPendingActions.begin() ; + it != cached_end ; it++) + { + if( (*it) != Control::STOP ) + { + timedActionsCount++; + } + } + + float timeSinceLastFramePart = timeSinceLastFrame / std::max(1, timedActionsCount); + for(std::list::iterator it = mPendingActions.begin() ; + it != cached_end ; it++) + { + if( (*it) != Control::STOP ) + { + this->setValue(mValue + + (((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))); + } + else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) + { + + if(mValue > mInitialValue) + { + this->setValue( std::max( mInitialValue, + mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)))); + } + else if(mValue < mInitialValue) + { + this->setValue( std::min( mInitialValue, + mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)))); + } + } + } + mPendingActions.clear(); + } + else if( currentChangingDirection != Control::STOP ) + { + this->setValue(mValue + + (((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame))); + } + else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) + { + if(mValue > mInitialValue) + { + this->setValue( std::max( mInitialValue, + mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFrame)))); + } + else if(mValue < mInitialValue) + { + this->setValue( std::min( mInitialValue, + mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFrame)))); + } + } + } +} diff --git a/extern/oics/ICSControl.h b/extern/oics/ICSControl.h new file mode 100644 index 0000000000..73f1d5494b --- /dev/null +++ b/extern/oics/ICSControl.h @@ -0,0 +1,107 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#ifndef _Control_H_ +#define _Control_H_ + +#include "ICSPrerequisites.h" + +#include "ICSChannel.h" +#include "ICSControlListener.h" + +namespace ICS +{ + + class DllExport Control + { + public: + + enum ControlChangingDirection + { + DECREASE = -1, STOP = 0, INCREASE = 1 + }; + + Control(const std::string name, bool autoChangeDirectionOnLimitsAfterStop = false, bool autoReverseToInitialValue = false, float initialValue = 0.5, float stepSize = 0.1, float stepsPerSeconds = 2.0, bool axisBindable = true); + ~Control(); + + void setChangingDirection(ControlChangingDirection direction); + inline ControlChangingDirection getChangingDirection(){ return currentChangingDirection; }; + + void setValue(float value); + inline float getValue(){ return mValue; }; + inline float getInitialValue(){ return mInitialValue; }; + + void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0); + std::list getAttachedChannels(){ return mAttachedChannels; }; + + inline float getStepSize(){ return mStepSize; }; + inline float getStepsPerSeconds(){ return mStepsPerSeconds; }; + + inline void setIgnoreAutoReverse(bool value){ mIgnoreAutoReverse = value; }; // mouse disable autoreverse + inline bool isAutoReverseIgnored(){ return mIgnoreAutoReverse; }; + inline bool getAutoReverse(){ return mAutoReverseToInitialValue; }; + + inline bool getAutoChangeDirectionOnLimitsAfterStop(){ return mAutoChangeDirectionOnLimitsAfterStop; }; + + inline std::string getName(){ return mName; }; + + inline bool isAxisBindable(){ return mAxisBindable; }; + inline void setAxisBindable(bool value){ mAxisBindable = value; }; + + inline void addListener(ControlListener* ob){ mListeners.push_back(ob); }; + inline void removeListener(ControlListener* ob){ mListeners.remove(ob); }; + + void update(float timeSinceLastFrame); + + protected: + float mValue; + float mInitialValue; + std::string mName; + float mStepSize; + float mStepsPerSeconds; + bool mAutoReverseToInitialValue; + bool mIgnoreAutoReverse; + bool mAutoChangeDirectionOnLimitsAfterStop; + bool mAxisBindable; + + Control::ControlChangingDirection currentChangingDirection; + std::list mAttachedChannels; + + std::list mListeners; + + std::list mPendingActions; + + protected: + + void updateChannels(); + void notifyListeners(float previousValue); + + }; + +} + + +#endif \ No newline at end of file diff --git a/extern/oics/ICSControlListener.h b/extern/oics/ICSControlListener.h new file mode 100644 index 0000000000..067b2d6f24 --- /dev/null +++ b/extern/oics/ICSControlListener.h @@ -0,0 +1,46 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#ifndef _ControlListener_H_ +#define _ControlListener_H_ + +#include "ICSPrerequisites.h" + +#include "ICSControl.h" + +namespace ICS +{ + + class DllExport ControlListener + { + public: + virtual void controlChanged(Control* control, float currentValue, float previousValue) = 0; + }; + +} + + +#endif \ No newline at end of file diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp new file mode 100644 index 0000000000..1702c853ed --- /dev/null +++ b/extern/oics/ICSInputControlSystem.cpp @@ -0,0 +1,929 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +namespace ICS +{ + InputControlSystem::InputControlSystem(std::string file, bool active + , DetectingBindingListener* detectingBindingListener + , InputControlSystemLog* log, size_t channelCount) + : mFileName(file) + , mDetectingBindingListener(detectingBindingListener) + , mDetectingBindingControl(NULL) + , mLog(log) + , mXmouseAxisBinded(false), mYmouseAxisBinded(false) + { + ICS_LOG(" - Creating InputControlSystem - "); + + this->mActive = active; + + this->fillOISKeysMap(); + + ICS_LOG("Channel count = " + ToString(channelCount) ); + for(size_t i=0;iLoadFile(); + + if(xmlDoc->Error()) + { + std::ostringstream message; + message << "TinyXml reported an error reading \""+ file + "\". Row " << + (int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " << + xmlDoc->ErrorDesc() ; + ICS_LOG(message.str()); + + delete xmlDoc; + return; + } + + xmlRoot = xmlDoc->RootElement(); + if(std::string(xmlRoot->Value()) != "Controller") { + ICS_LOG("Error: Invalid Controller file. Missing element."); + delete xmlDoc; + return; + } + + TiXmlElement* xmlControl = xmlRoot->FirstChildElement("Control"); + + size_t controlChannelCount = 0; + while(xmlControl) + { + TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); + while(xmlChannel) + { + controlChannelCount = std::max(channelCount, FromString(xmlChannel->Attribute("number"))); + + xmlChannel = xmlChannel->NextSiblingElement("Channel"); + } + + xmlControl = xmlControl->NextSiblingElement("Control"); + } + + if(controlChannelCount > channelCount) + { + size_t dif = controlChannelCount - channelCount; + ICS_LOG("Warning: default channel count exceeded. Adding " + ToString(dif) + " channels" ); + for(size_t i = channelCount ; i < controlChannelCount ; i++) + { + mChannels.push_back(new Channel((int)i)); + } + } + + ICS_LOG("Applying filters to channels"); + // + // + // + // + + TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter"); + while(xmlChannelFilter) + { + int ch = FromString(xmlChannelFilter->Attribute("number")); + + TiXmlElement* xmlInterval = xmlChannelFilter->FirstChildElement("Interval"); + while(xmlInterval) + { + std::string type = xmlInterval->Attribute("type"); + + if(type == "bezier") + { + float step = 0.1; + + float startX = FromString(xmlInterval->Attribute("startX")); + float startY = FromString(xmlInterval->Attribute("startY")); + float midX = FromString(xmlInterval->Attribute("midX")); + float midY = FromString(xmlInterval->Attribute("midY")); + float endX = FromString(xmlInterval->Attribute("endX")); + float endY = FromString(xmlInterval->Attribute("endY")); + + step = FromString(xmlInterval->Attribute("step")); + + ICS_LOG("Applying Bezier filter to channel [number=" + + ToString(ch) + ", startX=" + + ToString(startX) + ", startY=" + + ToString(startY) + ", midX=" + + ToString(midX) + ", midY=" + + ToString(midY) + ", endX=" + + ToString(endX) + ", endY=" + + ToString(endY) + ", step=" + + ToString(step) + "]"); + + mChannels.at(ch)->addBezierInterval(startX, startY, midX, midY, endX, endY, step); + } + + xmlInterval = xmlInterval->NextSiblingElement("Interval"); + } + + + xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter"); + } + + xmlControl = xmlRoot->FirstChildElement("Control"); + while(xmlControl) + { + bool axisBindable = true; + if(xmlControl->Attribute("axisBindable")) + { + axisBindable = (std::string( xmlControl->Attribute("axisBindable") ) == "true"); + } + + ICS_LOG("Adding Control [name=" + + std::string( xmlControl->Attribute("name") ) + ", autoChangeDirectionOnLimitsAfterStop=" + + std::string( xmlControl->Attribute("autoChangeDirectionOnLimitsAfterStop") ) + ", autoReverseToInitialValue=" + + std::string( xmlControl->Attribute("autoReverseToInitialValue") ) + ", initialValue=" + + std::string( xmlControl->Attribute("initialValue") ) + ", stepSize=" + + std::string( xmlControl->Attribute("stepSize") ) + ", stepsPerSeconds=" + + std::string( xmlControl->Attribute("stepsPerSeconds") ) + ", axisBindable=" + + std::string( (axisBindable)? "true" : "false" ) + "]"); + + float _stepSize = 0; + if(xmlControl->Attribute("stepSize")) + { + std::string value(xmlControl->Attribute("stepSize")); + if(value == "MAX") + { + _stepSize = ICS_MAX; + } + else + { + _stepSize = FromString(value.c_str()); + } + } + else + { + ICS_LOG("Warning: no stepSize value found. Default value is 0."); + } + + float _stepsPerSeconds = 0; + if(xmlControl->Attribute("stepsPerSeconds")) + { + std::string value(xmlControl->Attribute("stepsPerSeconds")); + if(value == "MAX") + { + _stepsPerSeconds = ICS_MAX; + } + else + { + _stepsPerSeconds = FromString(value.c_str()); + } + } + else + { + ICS_LOG("Warning: no stepSize value found. Default value is 0."); + } + + addControl( new Control(xmlControl->Attribute("name") + , std::string( xmlControl->Attribute("autoChangeDirectionOnLimitsAfterStop") ) == "true" + , std::string( xmlControl->Attribute("autoReverseToInitialValue") ) == "true" + , FromString(xmlControl->Attribute("initialValue")) + , _stepSize + , _stepsPerSeconds + , axisBindable) ); + + loadKeyBinders(xmlControl); + + loadMouseAxisBinders(xmlControl); + + loadMouseButtonBinders(xmlControl); + + loadJoystickAxisBinders(xmlControl); + + loadJoystickButtonBinders(xmlControl); + + loadJoystickPOVBinders(xmlControl); + + loadJoystickSliderBinders(xmlControl); + + // Attach controls to channels + TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); + while(xmlChannel) + { + ICS_LOG("\tAttaching control to channel [number=" + + std::string( xmlChannel->Attribute("number") ) + ", direction=" + + std::string( xmlChannel->Attribute("direction") ) + "]"); + + float percentage = 1; + if(xmlChannel->Attribute("percentage")) + { + if(StringIsNumber(xmlChannel->Attribute("percentage"))) + { + float val = FromString(xmlChannel->Attribute("percentage")); + if(val > 1 || val < 0) + { + ICS_LOG("ERROR: attaching percentage value range is [0,1]"); + } + else + { + percentage = val; + } + } + else + { + ICS_LOG("ERROR: attaching percentage value range is [0,1]"); + } + } + + int chNumber = FromString(xmlChannel->Attribute("number")); + if(std::string(xmlChannel->Attribute("direction")) == "DIRECT") + { + mControls.back()->attachChannel(mChannels[ chNumber ],Channel::DIRECT, percentage); + } + else if(std::string(xmlChannel->Attribute("direction")) == "INVERSE") + { + mControls.back()->attachChannel(mChannels[ chNumber ],Channel::INVERSE, percentage); + } + + xmlChannel = xmlChannel->NextSiblingElement("Channel"); + } + + xmlControl = xmlControl->NextSiblingElement("Control"); + } + + std::vector::const_iterator o; + for(o = mChannels.begin(); o != mChannels.end(); ++o) + { + (*o)->update(); + } + + delete xmlDoc; + } + + ICS_LOG(" - InputControlSystem Created - "); + } + + InputControlSystem::~InputControlSystem() + { + ICS_LOG(" - Deleting InputControlSystem (" + mFileName + ") - "); + + mJoystickIDList.clear(); + + std::vector::const_iterator o; + for(o = mChannels.begin(); o != mChannels.end(); ++o) + { + delete (*o); + } + mChannels.clear(); + + std::vector::const_iterator o2; + for(o2 = mControls.begin(); o2 != mControls.end(); ++o2) + { + delete (*o2); + } + mControls.clear(); + + mControlsKeyBinderMap.clear(); + mControlsMouseButtonBinderMap.clear(); + mControlsJoystickButtonBinderMap.clear(); + + mKeys.clear(); + mKeyCodes.clear(); + + ICS_LOG(" - InputControlSystem deleted - "); + } + + std::string InputControlSystem::getBaseFileName() + { + size_t found = mFileName.find_last_of("/\\"); + std::string file = mFileName.substr(found+1); + + return file.substr(0, file.find_last_of(".")); + } + + bool InputControlSystem::save(std::string fileName) + { + if(fileName != "") + { + mFileName = fileName; + } + + TiXmlDocument doc( mFileName.c_str() ); + + TiXmlDeclaration dec; + dec.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); + doc.InsertEndChild(dec); + + TiXmlElement Controller( "Controller" ); + + for(std::vector::const_iterator o = mChannels.begin() ; o != mChannels.end(); o++) + { + ICS::IntervalList intervals = (*o)->getIntervals(); + + if(intervals.size() > 1) // all channels have a default linear filter + { + TiXmlElement ChannelFilter( "ChannelFilter" ); + + ChannelFilter.SetAttribute("number", ToString((*o)->getNumber()).c_str()); + + ICS::IntervalList::const_iterator interval = intervals.begin(); + while( interval != intervals.end() ) + { + // if not default linear filter + if(!( interval->step == 0.2f + && interval->startX == 0.0f + && interval->startY == 0.0f + && interval->midX == 0.5f + && interval->midY == 0.5f + && interval->endX == 1.0f + && interval->endY == 1.0f )) + { + TiXmlElement XMLInterval( "Interval" ); + + XMLInterval.SetAttribute("type", "bezier"); + XMLInterval.SetAttribute("step", ToString(interval->step).c_str()); + + XMLInterval.SetAttribute("startX", ToString(interval->startX).c_str()); + XMLInterval.SetAttribute("startY", ToString(interval->startY).c_str()); + XMLInterval.SetAttribute("midX", ToString(interval->midX).c_str()); + XMLInterval.SetAttribute("midY", ToString(interval->midY).c_str()); + XMLInterval.SetAttribute("endX", ToString(interval->endX).c_str()); + XMLInterval.SetAttribute("endY", ToString(interval->endY).c_str()); + + ChannelFilter.InsertEndChild(XMLInterval); + } + + interval++; + } + + Controller.InsertEndChild(ChannelFilter); + } + } + + for(std::vector::const_iterator o = mControls.begin() ; o != mControls.end(); o++) + { + TiXmlElement control( "Control" ); + + control.SetAttribute( "name", (*o)->getName().c_str() ); + if((*o)->getAutoChangeDirectionOnLimitsAfterStop()) + { + control.SetAttribute( "autoChangeDirectionOnLimitsAfterStop", "true" ); + } + else + { + control.SetAttribute( "autoChangeDirectionOnLimitsAfterStop", "false" ); + } + if((*o)->getAutoReverse()) + { + control.SetAttribute( "autoReverseToInitialValue", "true" ); + } + else + { + control.SetAttribute( "autoReverseToInitialValue", "false" ); + } + control.SetAttribute( "initialValue", ToString((*o)->getInitialValue()).c_str() ); + + if((*o)->getStepSize() == ICS_MAX) + { + control.SetAttribute( "stepSize", "MAX" ); + } + else + { + control.SetAttribute( "stepSize", ToString((*o)->getStepSize()).c_str() ); + } + + if((*o)->getStepsPerSeconds() == ICS_MAX) + { + control.SetAttribute( "stepsPerSeconds", "MAX" ); + } + else + { + control.SetAttribute( "stepsPerSeconds", ToString((*o)->getStepsPerSeconds()).c_str() ); + } + + if(!(*o)->isAxisBindable()) + { + control.SetAttribute( "axisBindable", "false" ); + } + + if(getKeyBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) != OIS::KC_UNASSIGNED) + { + TiXmlElement keyBinder( "KeyBinder" ); + + keyBinder.SetAttribute( "key", keyCodeToString( + getKeyBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + keyBinder.SetAttribute( "direction", "INCREASE" ); + control.InsertEndChild(keyBinder); + } + + if(getKeyBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) != OIS::KC_UNASSIGNED) + { + TiXmlElement keyBinder( "KeyBinder" ); + + keyBinder.SetAttribute( "key", keyCodeToString( + getKeyBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); + keyBinder.SetAttribute( "direction", "DECREASE" ); + control.InsertEndChild(keyBinder); + } + + if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) + != InputControlSystem/*::NamedAxis*/::UNASSIGNED) + { + TiXmlElement binder( "MouseBinder" ); + + InputControlSystem::NamedAxis axis = + getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE); + if(axis == InputControlSystem/*::NamedAxis*/::X) + { + binder.SetAttribute( "axis", "X" ); + } + else if(axis == InputControlSystem/*::NamedAxis*/::Y) + { + binder.SetAttribute( "axis", "Y" ); + } + else if(axis == InputControlSystem/*::NamedAxis*/::Z) + { + binder.SetAttribute( "axis", "Z" ); + } + + binder.SetAttribute( "direction", "INCREASE" ); + control.InsertEndChild(binder); + } + + if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) + != InputControlSystem/*::NamedAxis*/::UNASSIGNED) + { + TiXmlElement binder( "MouseBinder" ); + + InputControlSystem::NamedAxis axis = + getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE); + if(axis == InputControlSystem/*::NamedAxis*/::X) + { + binder.SetAttribute( "axis", "X" ); + } + else if(axis == InputControlSystem/*::NamedAxis*/::Y) + { + binder.SetAttribute( "axis", "Y" ); + } + else if(axis == InputControlSystem/*::NamedAxis*/::Z) + { + binder.SetAttribute( "axis", "Z" ); + } + + binder.SetAttribute( "direction", "DECREASE" ); + control.InsertEndChild(binder); + } + + if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "MouseButtonBinder" ); + + unsigned int button = getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE); + if(button == OIS::/*MouseButtonID::*/MB_Left) + { + binder.SetAttribute( "button", "LEFT" ); + } + else if(button == OIS::/*MouseButtonID::*/MB_Middle) + { + binder.SetAttribute( "button", "MIDDLE" ); + } + else if(button == OIS::/*MouseButtonID::*/MB_Right) + { + binder.SetAttribute( "button", "RIGHT" ); + } + else + { + binder.SetAttribute( "button", ToString(button).c_str() ); + } + binder.SetAttribute( "direction", "INCREASE" ); + control.InsertEndChild(binder); + } + + if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "MouseButtonBinder" ); + + unsigned int button = getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE); + if(button == OIS::/*MouseButtonID::*/MB_Left) + { + binder.SetAttribute( "button", "LEFT" ); + } + else if(button == OIS::/*MouseButtonID::*/MB_Middle) + { + binder.SetAttribute( "button", "MIDDLE" ); + } + else if(button == OIS::/*MouseButtonID::*/MB_Right) + { + binder.SetAttribute( "button", "RIGHT" ); + } + else + { + binder.SetAttribute( "button", ToString(button).c_str() ); + } + binder.SetAttribute( "direction", "DECREASE" ); + control.InsertEndChild(binder); + } + + JoystickIDList::const_iterator it = mJoystickIDList.begin(); + while(it != mJoystickIDList.end()) + { + int deviceId = *it; + + if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickAxisBinder" ); + + binder.SetAttribute( "axis", ToString( + getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickAxisBinder" ); + + binder.SetAttribute( "axis", ToString( + getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); + + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "JoystickButtonBinder" ); + + binder.SetAttribute( "button", ToString( + getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "JoystickButtonBinder" ); + + binder.SetAttribute( "button", ToString( + getJoystickButtonBinding(*o, *it, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); + + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE).index >= 0) + { + TiXmlElement binder( "JoystickPOVBinder" ); + + POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE); + + binder.SetAttribute( "pov", ToString(POVPair.index).c_str() ); + + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + if(POVPair.axis == ICS::InputControlSystem::EastWest) + { + binder.SetAttribute( "axis", "EastWest" ); + } + else + { + binder.SetAttribute( "axis", "NorthSouth" ); + } + + control.InsertEndChild(binder); + } + + if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE).index >= 0) + { + TiXmlElement binder( "JoystickPOVBinder" ); + + POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE); + + binder.SetAttribute( "pov", ToString(POVPair.index).c_str() ); + + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + if(POVPair.axis == ICS::InputControlSystem::EastWest) + { + binder.SetAttribute( "axis", "EastWest" ); + } + else + { + binder.SetAttribute( "axis", "NorthSouth" ); + } + + control.InsertEndChild(binder); + } + + if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickSliderBinder" ); + + binder.SetAttribute( "slider", ToString( + getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickSliderBinder" ); + + binder.SetAttribute( "slider", ToString( + getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); + + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); + + control.InsertEndChild(binder); + } + + it++; + } + + + std::list channels = (*o)->getAttachedChannels(); + for(std::list::iterator it = channels.begin() ; + it != channels.end() ; it++) + { + TiXmlElement binder( "Channel" ); + + binder.SetAttribute( "number", ToString((*it)->getNumber()).c_str() ); + + Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction; + if(direction == Channel/*::ChannelDirection*/::DIRECT) + { + binder.SetAttribute( "direction", "DIRECT" ); + } + else + { + binder.SetAttribute( "direction", "INVERSE" ); + } + + float percentage = (*it)->getAttachedControlBinding(*o).percentage; + binder.SetAttribute( "percentage", ToString(percentage).c_str() ); + + control.InsertEndChild(binder); + } + + Controller.InsertEndChild(control); + } + + doc.InsertEndChild(Controller); + return doc.SaveFile(); + } + + void InputControlSystem::update(float lTimeSinceLastFrame) + { + if(mActive) + { + std::vector::const_iterator it; + for(it=mControls.begin(); it!=mControls.end(); ++it) + { + (*it)->update(lTimeSinceLastFrame); + } + } + + //! @todo Future versions should consider channel exponentials and mixtures, so + // after updating Controls, Channels should be updated according to their values + } + + float InputControlSystem::getChannelValue(int i) + { + return std::max(0.0,std::min(1.0,mChannels[i]->getValue())); + } + + float InputControlSystem::getControlValue(int i) + { + return mControls[i]->getValue(); + } + + void InputControlSystem::addJoystick(int deviceId) + { + ICS_LOG("Adding joystick (device id: " + ToString(deviceId) + ")"); + + for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++) + { + if(mControlsJoystickAxisBinderMap[deviceId].find(j) == mControlsJoystickAxisBinderMap[deviceId].end()) + { + ControlAxisBinderItem controlJoystickBinderItem; + controlJoystickBinderItem.direction = Control::STOP; + controlJoystickBinderItem.control = NULL; + mControlsJoystickAxisBinderMap[deviceId][j] = controlJoystickBinderItem; + } + } + + mJoystickIDList.push_back(deviceId); + } + + Control* InputControlSystem::findControl(std::string name) + { + if(mActive) + { + std::vector::const_iterator it; + for(it = mControls.begin(); it != mControls.end(); ++it) + { + if( ((Control*)(*it))->getName() == name) + { + return (Control*)(*it); + } + } + } + + return NULL; + } + + void InputControlSystem::enableDetectingBindingState(Control* control + , Control::ControlChangingDirection direction) + { + mDetectingBindingControl = control; + mDetectingBindingDirection = direction; + + mMouseAxisBindingInitialValues[0] = ICS_MOUSE_AXIS_BINDING_NULL_VALUE; + } + + void InputControlSystem::cancelDetectingBindingState() + { + mDetectingBindingControl = NULL; + } + + void InputControlSystem::fillOISKeysMap() + { + mKeys["UNASSIGNED"]= OIS::KC_UNASSIGNED; + mKeys["ESCAPE"]= OIS::KC_ESCAPE; + mKeys["1"]= OIS::KC_1; + mKeys["2"]= OIS::KC_2; + mKeys["3"]= OIS::KC_3; + mKeys["4"]= OIS::KC_4; + mKeys["5"]= OIS::KC_5; + mKeys["6"]= OIS::KC_6; + mKeys["7"]= OIS::KC_7; + mKeys["8"]= OIS::KC_8; + mKeys["9"]= OIS::KC_9; + mKeys["0"]= OIS::KC_0; + mKeys["MINUS"]= OIS::KC_MINUS; + mKeys["EQUALS"]= OIS::KC_EQUALS; + mKeys["BACK"]= OIS::KC_BACK; + mKeys["TAB"]= OIS::KC_TAB; + mKeys["Q"]= OIS::KC_Q; + mKeys["W"]= OIS::KC_W; + mKeys["E"]= OIS::KC_E; + mKeys["R"]= OIS::KC_R; + mKeys["T"]= OIS::KC_T; + mKeys["Y"]= OIS::KC_Y; + mKeys["U"]= OIS::KC_U; + mKeys["I"]= OIS::KC_I; + mKeys["O"]= OIS::KC_O; + mKeys["P"]= OIS::KC_P; + mKeys["LBRACKET"]= OIS::KC_LBRACKET; + mKeys["RBRACKET"]= OIS::KC_RBRACKET; + mKeys["RETURN"]= OIS::KC_RETURN; + mKeys["LCONTROL"]= OIS::KC_LCONTROL; + mKeys["A"]= OIS::KC_A; + mKeys["S"]= OIS::KC_S; + mKeys["D"]= OIS::KC_D; + mKeys["F"]= OIS::KC_F; + mKeys["G"]= OIS::KC_G; + mKeys["H"]= OIS::KC_H; + mKeys["J"]= OIS::KC_J; + mKeys["K"]= OIS::KC_K; + mKeys["L"]= OIS::KC_L; + mKeys["SEMICOLON"]= OIS::KC_SEMICOLON; + mKeys["APOSTROPHE"]= OIS::KC_APOSTROPHE; + mKeys["GRAVE"]= OIS::KC_GRAVE; + mKeys["LSHIFT"]= OIS::KC_LSHIFT; + mKeys["BACKSLASH"]= OIS::KC_BACKSLASH; + mKeys["Z"]= OIS::KC_Z; + mKeys["X"]= OIS::KC_X; + mKeys["C"]= OIS::KC_C; + mKeys["V"]= OIS::KC_V; + mKeys["B"]= OIS::KC_B; + mKeys["N"]= OIS::KC_N; + mKeys["M"]= OIS::KC_M; + mKeys["COMMA"]= OIS::KC_COMMA; + mKeys["PERIOD"]= OIS::KC_PERIOD; + mKeys["SLASH"]= OIS::KC_SLASH; + mKeys["RSHIFT"]= OIS::KC_RSHIFT; + mKeys["MULTIPLY"]= OIS::KC_MULTIPLY; + mKeys["LMENU"]= OIS::KC_LMENU; + mKeys["SPACE"]= OIS::KC_SPACE; + mKeys["CAPITAL"]= OIS::KC_CAPITAL; + mKeys["F1"]= OIS::KC_F1; + mKeys["F2"]= OIS::KC_F2; + mKeys["F3"]= OIS::KC_F3; + mKeys["F4"]= OIS::KC_F4; + mKeys["F5"]= OIS::KC_F5; + mKeys["F6"]= OIS::KC_F6; + mKeys["F7"]= OIS::KC_F7; + mKeys["F8"]= OIS::KC_F8; + mKeys["F9"]= OIS::KC_F9; + mKeys["F10"]= OIS::KC_F10; + mKeys["F11"]= OIS::KC_F11; + mKeys["F12"]= OIS::KC_F12; + mKeys["NUMLOCK"]= OIS::KC_NUMLOCK; + mKeys["SCROLL"]= OIS::KC_SCROLL; + mKeys["NUMPAD7"]= OIS::KC_NUMPAD7; + mKeys["NUMPAD8"]= OIS::KC_NUMPAD8; + mKeys["NUMPAD9"]= OIS::KC_NUMPAD9; + mKeys["SUBTRACT"]= OIS::KC_SUBTRACT; + mKeys["NUMPAD4"]= OIS::KC_NUMPAD4; + mKeys["NUMPAD5"]= OIS::KC_NUMPAD5; + mKeys["NUMPAD6"]= OIS::KC_NUMPAD6; + mKeys["ADD"]= OIS::KC_ADD; + mKeys["NUMPAD1"]= OIS::KC_NUMPAD1; + mKeys["NUMPAD2"]= OIS::KC_NUMPAD2; + mKeys["NUMPAD3"]= OIS::KC_NUMPAD3; + mKeys["NUMPAD0"]= OIS::KC_NUMPAD0; + mKeys["DECIMAL"]= OIS::KC_DECIMAL; + mKeys["RCONTROL"]= OIS::KC_RCONTROL; + mKeys["DIVIDE"]= OIS::KC_DIVIDE; + mKeys["SYSRQ"]= OIS::KC_SYSRQ; + mKeys["RMENU"]= OIS::KC_RMENU; + mKeys["PAUSE"]= OIS::KC_PAUSE; + mKeys["HOME"]= OIS::KC_HOME; + mKeys["UP"]= OIS::KC_UP; + mKeys["PGUP"]= OIS::KC_PGUP; + mKeys["LEFT"]= OIS::KC_LEFT; + mKeys["RIGHT"]= OIS::KC_RIGHT; + mKeys["END"]= OIS::KC_END; + mKeys["DOWN"]= OIS::KC_DOWN; + mKeys["PGDOWN"]= OIS::KC_PGDOWN; + mKeys["INSERT"]= OIS::KC_INSERT; + mKeys["DELETE"]= OIS::KC_DELETE; + mKeys["LWIN"]= OIS::KC_LWIN; + mKeys["RWIN"]= OIS::KC_RWIN; + mKeys["APPS"]= OIS::KC_APPS; + + mKeys["NUMPADENTER"]= OIS::KC_NUMPADENTER; + + for(std::map::iterator it = mKeys.begin() + ; it != mKeys.end() ; it++) + { + mKeyCodes[ it->second ] = it->first; + } + } + + std::string InputControlSystem::keyCodeToString(OIS::KeyCode key) + { + return mKeyCodes[key]; + } + + OIS::KeyCode InputControlSystem::stringToKeyCode(std::string key) + { + return mKeys[key]; + } +} \ No newline at end of file diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h new file mode 100644 index 0000000000..f1c12d3b59 --- /dev/null +++ b/extern/oics/ICSInputControlSystem.h @@ -0,0 +1,256 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#ifndef _InputControlSystem_H_ +#define _InputControlSystem_H_ + +#include "ICSPrerequisites.h" + +#include "ICSControl.h" +#include "ICSChannel.h" + +#define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() ); +#define ICS_MAX_JOYSTICK_AXIS 16 +#define ICS_MOUSE_BINDING_MARGIN 30 +#define ICS_JOYSTICK_AXIS_BINDING_MARGIN 10000 +#define ICS_JOYSTICK_SLIDER_BINDING_MARGIN 10000 +#define ICS_MOUSE_AXIS_BINDING_NULL_VALUE std::numeric_limits::max() + +namespace ICS +{ + class DllExport InputControlSystemLog + { + public: + virtual void logMessage(const char* text) = 0; + }; + + class DllExport InputControlSystem : + public OIS::MouseListener, + public OIS::KeyListener, + public OIS::JoyStickListener + { + + public: + + enum NamedAxis { X = -1, Y = -2, Z = -3, UNASSIGNED = -4 }; + enum POVAxis { NorthSouth = 0, EastWest = 1 }; + + typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions + + typedef std::list JoystickIDList; + + typedef struct + { + int index; + POVAxis axis; + } POVBindingPair; + + InputControlSystem(std::string file = "", bool active = true + , DetectingBindingListener* detectingBindingListener = NULL + , InputControlSystemLog* log = NULL, size_t channelCount = 16); + ~InputControlSystem(); + + std::string getFileName(){ return mFileName; }; + std::string getBaseFileName(); + + void setDetectingBindingListener(DetectingBindingListener* detectingBindingListener){ mDetectingBindingListener = detectingBindingListener; }; + DetectingBindingListener* getDetectingBindingListener(){ return mDetectingBindingListener; }; + + // in seconds + void update(float timeSinceLastFrame); + + inline Channel* getChannel(int i){ return mChannels[i]; }; + float getChannelValue(int i); + inline int getChannelCount(){ return (int)mChannels.size(); }; + + inline Control* getControl(int i){ return mControls[i]; }; + float getControlValue(int i); + inline int getControlCount(){ return (int)mControls.size(); }; + inline void addControl(Control* control){ mControls.push_back(control); }; + + Control* findControl(std::string name); + + inline void activate(){ this->mActive = true; }; + inline void deactivate(){ this->mActive = false; }; + + void addJoystick(int deviceId); + JoystickIDList& getJoystickIdList(){ return mJoystickIDList; }; + + // MouseListener + bool mouseMoved(const OIS::MouseEvent &evt); + bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID); + bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID); + + // KeyListener + bool keyPressed(const OIS::KeyEvent &evt); + bool keyReleased(const OIS::KeyEvent &evt); + + // JoyStickListener + bool buttonPressed(const OIS::JoyStickEvent &evt, int button); + bool buttonReleased(const OIS::JoyStickEvent &evt, int button); + bool axisMoved(const OIS::JoyStickEvent &evt, int axis); + bool povMoved(const OIS::JoyStickEvent &evt, int index); + bool sliderMoved(const OIS::JoyStickEvent &evt, int index); + + void addKeyBinding(Control* control, OIS::KeyCode key, Control::ControlChangingDirection direction); + void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction); + void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction); + void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction); + void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction); + void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction); + void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction); + void removeKeyBinding(OIS::KeyCode key); + void removeMouseAxisBinding(NamedAxis axis); + void removeMouseButtonBinding(unsigned int button); + void removeJoystickAxisBinding(int deviceId, int axis); + void removeJoystickButtonBinding(int deviceId, unsigned int button); + void removeJoystickPOVBinding(int deviceId, int index, POVAxis axis); + void removeJoystickSliderBinding(int deviceId, int index); + + OIS::KeyCode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction); + NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction); + unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction); + int getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); + unsigned int getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); + POVBindingPair getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); + int getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); + + std::string keyCodeToString(OIS::KeyCode key); + OIS::KeyCode stringToKeyCode(std::string key); + + void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction); + void cancelDetectingBindingState(); + + bool save(std::string fileName = ""); + + protected: + + void loadKeyBinders(TiXmlElement* xmlControlNode); + void loadMouseAxisBinders(TiXmlElement* xmlControlNode); + void loadMouseButtonBinders(TiXmlElement* xmlControlNode); + void loadJoystickAxisBinders(TiXmlElement* xmlControlNode); + void loadJoystickButtonBinders(TiXmlElement* xmlControlNode); + void loadJoystickPOVBinders(TiXmlElement* xmlControlNode); + void loadJoystickSliderBinders(TiXmlElement* xmlControlNode); + + void addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction); + void removeMouseAxisBinding_(int axis); + + protected: + + typedef struct { + Control::ControlChangingDirection direction; + Control* control; + } ControlKeyBinderItem; + + typedef ControlKeyBinderItem ControlAxisBinderItem; + typedef ControlKeyBinderItem ControlButtonBinderItem; + typedef ControlKeyBinderItem ControlPOVBinderItem; + typedef ControlKeyBinderItem ControlSliderBinderItem; + + typedef struct { + Control* control; + Control::ControlChangingDirection direction; + } PendingActionItem; + + std::list mPendingActions; + + std::string mFileName; + + typedef std::map ControlsKeyBinderMapType; // + typedef std::map ControlsAxisBinderMapType; // + typedef std::map ControlsButtonBinderMapType; // + typedef std::map ControlsPOVBinderMapType; // + typedef std::map ControlsSliderBinderMapType; // + + typedef std::map JoystickAxisBinderMapType; // > + typedef std::map JoystickButtonBinderMapType; // > + typedef std::map > JoystickPOVBinderMapType; // > > + typedef std::map JoystickSliderBinderMapType; // > + + ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // + ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // + JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // > + JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // > + JoystickPOVBinderMapType mControlsJoystickPOVBinderMap; // > > + JoystickSliderBinderMapType mControlsJoystickSliderBinderMap; // > + + std::vector mControls; + std::vector mChannels; + + ControlsKeyBinderMapType mControlsKeyBinderMap; + std::map mKeys; + std::map mKeyCodes; + + bool mActive; + InputControlSystemLog* mLog; + + DetectingBindingListener* mDetectingBindingListener; + Control* mDetectingBindingControl; + Control::ControlChangingDirection mDetectingBindingDirection; + + bool mXmouseAxisBinded; + bool mYmouseAxisBinded; + + JoystickIDList mJoystickIDList; + + int mMouseAxisBindingInitialValues[3]; + + private: + + void fillOISKeysMap(); + }; + + class DllExport DetectingBindingListener + { + public: + virtual void keyBindingDetected(InputControlSystem* ICS, Control* control + , OIS::KeyCode key, Control::ControlChangingDirection direction); + + virtual void mouseAxisBindingDetected(InputControlSystem* ICS, Control* control + , InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction); + + virtual void mouseButtonBindingDetected(InputControlSystem* ICS, Control* control + , unsigned int button, Control::ControlChangingDirection direction); + + virtual void joystickAxisBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int axis, Control::ControlChangingDirection direction); + + virtual void joystickButtonBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, unsigned int button, Control::ControlChangingDirection direction); + + virtual void joystickPOVBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction); + + virtual void joystickSliderBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int slider, Control::ControlChangingDirection direction); + }; + + static const float ICS_MAX = std::numeric_limits::max(); +} + + +#endif diff --git a/extern/oics/ICSInputControlSystem_joystick.cpp b/extern/oics/ICSInputControlSystem_joystick.cpp new file mode 100644 index 0000000000..1e66599ead --- /dev/null +++ b/extern/oics/ICSInputControlSystem_joystick.cpp @@ -0,0 +1,665 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +namespace ICS +{ + // load xml + void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder"); + while(xmlJoystickBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlJoystickBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlJoystickBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + addJoystickAxisBinding(mControls.back(), FromString(xmlJoystickBinder->Attribute("deviceId")) + , FromString(xmlJoystickBinder->Attribute("axis")), dir); + + xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder"); + } + } + + void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder"); + while(xmlJoystickButtonBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + addJoystickButtonBinding(mControls.back(), FromString(xmlJoystickButtonBinder->Attribute("deviceId")) + , FromString(xmlJoystickButtonBinder->Attribute("button")), dir); + + xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder"); + } + } + + void InputControlSystem::loadJoystickPOVBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlJoystickPOVBinder = xmlControlNode->FirstChildElement("JoystickPOVBinder"); + while(xmlJoystickPOVBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + InputControlSystem::POVAxis axis = /*POVAxis::*/NorthSouth; + if(std::string(xmlJoystickPOVBinder->Attribute("axis")) == "EastWest") + { + axis = /*POVAxis::*/EastWest; + } + + addJoystickPOVBinding(mControls.back(), FromString(xmlJoystickPOVBinder->Attribute("deviceId")) + , FromString(xmlJoystickPOVBinder->Attribute("pov")), axis, dir); + + xmlJoystickPOVBinder = xmlJoystickPOVBinder->NextSiblingElement("JoystickPOVBinder"); + } + } + + void InputControlSystem::loadJoystickSliderBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlJoystickSliderBinder = xmlControlNode->FirstChildElement("JoystickSliderBinder"); + while(xmlJoystickSliderBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + addJoystickSliderBinding(mControls.back(), FromString(xmlJoystickSliderBinder->Attribute("deviceId")) + , FromString(xmlJoystickSliderBinder->Attribute("slider")), dir); + + xmlJoystickSliderBinder = xmlJoystickSliderBinder->NextSiblingElement("JoystickSliderBinder"); + } + } + + // add bindings + void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding AxisBinder [deviceid=" + + ToString(deviceId) + ", axis=" + + ToString(axis) + ", direction=" + + ToString(direction) + "]"); + + ControlAxisBinderItem controlAxisBinderItem; + controlAxisBinderItem.control = control; + controlAxisBinderItem.direction = direction; + mControlsJoystickAxisBinderMap[ deviceId ][ axis ] = controlAxisBinderItem; + } + + void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding JoystickButtonBinder [deviceId=" + + ToString(deviceId) + ", button=" + + ToString(button) + ", direction=" + + ToString(direction) + "]"); + + ControlButtonBinderItem controlJoystickButtonBinderItem; + controlJoystickButtonBinderItem.direction = direction; + controlJoystickButtonBinderItem.control = control; + mControlsJoystickButtonBinderMap[ deviceId ][ button ] = controlJoystickButtonBinderItem; + } + + void InputControlSystem::addJoystickPOVBinding(Control* control, int deviceId, int index, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding JoystickPOVBinder [deviceId=" + + ToString(deviceId) + ", pov=" + + ToString(index) + ", axis=" + + ToString(axis) + ", direction=" + + ToString(direction) + "]"); + + ControlPOVBinderItem ControlPOVBinderItem; + ControlPOVBinderItem.direction = direction; + ControlPOVBinderItem.control = control; + mControlsJoystickPOVBinderMap[ deviceId ][ index ][ axis ] = ControlPOVBinderItem; + } + + void InputControlSystem::addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding JoystickSliderBinder [deviceId=" + + ToString(deviceId) + ", direction=" + + ToString(index) + ", direction=" + + ToString(direction) + "]"); + + ControlSliderBinderItem ControlSliderBinderItem; + ControlSliderBinderItem.direction = direction; + ControlSliderBinderItem.control = control; + mControlsJoystickSliderBinderMap[ deviceId ][ index ] = ControlSliderBinderItem; + } + + // get bindings + int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) + { + if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) + { + ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].begin(); + while(it != mControlsJoystickAxisBinderMap[deviceId].end()) + { + if(it->first >= 0 && it->second.control == control && it->second.direction == direction) + { + return it->first; + } + it++; + } + } + + return /*NamedAxis::*/UNASSIGNED; + } + + unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) + { + if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].begin(); + while(it != mControlsJoystickButtonBinderMap[deviceId].end()) + { + if(it->second.control == control && it->second.direction == direction) + { + return it->first; + } + it++; + } + } + + return ICS_MAX_DEVICE_BUTTONS; + } + + InputControlSystem::POVBindingPair InputControlSystem::getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) + { + POVBindingPair result; + result.index = -1; + + if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end()) + { + //ControlsAxisBinderMapType::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin(); + std::map::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin(); + while(it != mControlsJoystickPOVBinderMap[deviceId].end()) + { + ControlsPOVBinderMapType::const_iterator it2 = it->second.begin(); + while(it2 != it->second.end()) + { + if(it2->second.control == control && it2->second.direction == direction) + { + result.index = it->first; + result.axis = (POVAxis)it2->first; + return result; + } + it2++; + } + + it++; + } + } + + return result; + } + + int InputControlSystem::getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) + { + if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end()) + { + ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].begin(); + while(it != mControlsJoystickSliderBinderMap[deviceId].end()) + { + if(it->second.control == control && it->second.direction == direction) + { + return it->first; + } + it++; + } + } + + return /*NamedAxis::*/UNASSIGNED; + } + + // remove bindings + void InputControlSystem::removeJoystickAxisBinding(int deviceId, int axis) + { + if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) + { + ControlsButtonBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].find(axis); + if(it != mControlsJoystickAxisBinderMap[deviceId].end()) + { + mControlsJoystickAxisBinderMap[deviceId].erase(it); + } + } + } + + void InputControlSystem::removeJoystickButtonBinding(int deviceId, unsigned int button) + { + if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].find(button); + if(it != mControlsJoystickButtonBinderMap[deviceId].end()) + { + mControlsJoystickButtonBinderMap[deviceId].erase(it); + } + } + } + + void InputControlSystem::removeJoystickPOVBinding(int deviceId, int index, POVAxis axis) + { + if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end()) + { + std::map::iterator it = mControlsJoystickPOVBinderMap[deviceId].find(index); + if(it != mControlsJoystickPOVBinderMap[deviceId].end()) + { + if(it->second.find(axis) != it->second.end()) + { + mControlsJoystickPOVBinderMap[deviceId].find(index)->second.erase( it->second.find(axis) ); + } + } + } + } + + void InputControlSystem::removeJoystickSliderBinding(int deviceId, int index) + { + if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end()) + { + ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].find(index); + if(it != mControlsJoystickSliderBinderMap[deviceId].end()) + { + mControlsJoystickSliderBinderMap[deviceId].erase(it); + } + } + } + + // joyStick listeners + bool InputControlSystem::buttonPressed(const OIS::JoyStickEvent &evt, int button) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickButtonBinderMap.find(evt.device->getID()) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.device->getID()].find(button); + if(it != mControlsJoystickButtonBinderMap[evt.device->getID()].end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->joystickButtonBindingDetected(this, + mDetectingBindingControl, evt.device->getID(), button, mDetectingBindingDirection); + } + } + + return true; + } + + bool InputControlSystem::buttonReleased(const OIS::JoyStickEvent &evt, int button) + { + if(mActive) + { + if(mControlsJoystickButtonBinderMap.find(evt.device->getID()) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.device->getID()].find(button); + if(it != mControlsJoystickButtonBinderMap[evt.device->getID()].end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + } + return true; + } + + bool InputControlSystem::axisMoved(const OIS::JoyStickEvent &evt, int axis) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickAxisBinderMap.find(evt.device->getID()) != mControlsJoystickAxisBinderMap.end()) + { + ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.device->getID() ][ axis ]; // joystic axis start at 0 index + Control* ctrl = joystickBinderItem.control; + if(ctrl) + { + ctrl->setIgnoreAutoReverse(true); + if(joystickBinderItem.direction == Control::INCREASE) + { + float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; + float valDisplaced = (float)( evt.state.mAxes[axis].abs - OIS::JoyStick::MIN_AXIS); + + ctrl->setValue( valDisplaced / axisRange ); + } + else if(joystickBinderItem.direction == Control::DECREASE) + { + float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; + float valDisplaced = (float)(evt.state.mAxes[axis].abs - OIS::JoyStick::MIN_AXIS); + + ctrl->setValue( 1 - ( valDisplaced / axisRange ) ); + } + } + } + } + else if(mDetectingBindingListener) + { + //ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.device->getID() ][ axis ]; // joystic axis start at 0 index + //Control* ctrl = joystickBinderItem.control; + //if(ctrl && ctrl->isAxisBindable()) + if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable()) + { + if( abs( evt.state.mAxes[axis].abs ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN) + { + mDetectingBindingListener->joystickAxisBindingDetected(this, + mDetectingBindingControl, evt.device->getID(), axis, mDetectingBindingDirection); + } + } + } + } + + return true; + } + + bool InputControlSystem::povMoved(const OIS::JoyStickEvent &evt, int index) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickPOVBinderMap.find(evt.device->getID()) != mControlsJoystickPOVBinderMap.end()) + { + std::map::const_iterator i = mControlsJoystickPOVBinderMap[ evt.device->getID() ].find(index); + if(i != mControlsJoystickPOVBinderMap[ evt.device->getID() ].end()) + { + if(evt.state.mPOV[index].direction != OIS::Pov::West + && evt.state.mPOV[index].direction != OIS::Pov::East + && evt.state.mPOV[index].direction != OIS::Pov::Centered) + { + ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth ); + if(it != i->second.end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + if(evt.state.mPOV[index].direction == OIS::Pov::North + || evt.state.mPOV[index].direction == OIS::Pov::NorthWest + || evt.state.mPOV[index].direction == OIS::Pov::NorthEast) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction)); + } + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + + if(evt.state.mPOV[index].direction != OIS::Pov::North + && evt.state.mPOV[index].direction != OIS::Pov::South + && evt.state.mPOV[index].direction != OIS::Pov::Centered) + { + ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/EastWest ); + if(it != i->second.end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + if(evt.state.mPOV[index].direction == OIS::Pov::East + || evt.state.mPOV[index].direction == OIS::Pov::NorthEast + || evt.state.mPOV[index].direction == OIS::Pov::SouthEast) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction)); + } + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + + if(evt.state.mPOV[index].direction == OIS::Pov::Centered) + { + ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth ); + if(it != i->second.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + + it = i->second.find( /*POVAxis::*/EastWest ); + if(it != i->second.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + } + } + } + else if(mDetectingBindingListener) + { + if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable()) + { + if(evt.state.mPOV[index].direction == OIS::Pov::West + || evt.state.mPOV[index].direction == OIS::Pov::East + || evt.state.mPOV[index].direction == OIS::Pov::North + || evt.state.mPOV[index].direction == OIS::Pov::South) + { + POVAxis povAxis = NorthSouth; + if(evt.state.mPOV[index].direction == OIS::Pov::West + || evt.state.mPOV[index].direction == OIS::Pov::East) + { + povAxis = EastWest; + } + + mDetectingBindingListener->joystickPOVBindingDetected(this, + mDetectingBindingControl, evt.device->getID(), index, povAxis, mDetectingBindingDirection); + } + } + } + } + + return true; + } + + bool InputControlSystem::sliderMoved(const OIS::JoyStickEvent &evt, int index) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickSliderBinderMap.find(evt.device->getID()) != mControlsJoystickSliderBinderMap.end()) + { + ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ]; + Control* ctrl = joystickBinderItem.control; + if(ctrl) + { + ctrl->setIgnoreAutoReverse(true); + if(joystickBinderItem.direction == Control::INCREASE) + { + float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; + float valDisplaced = (float)( evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS); + + ctrl->setValue( valDisplaced / axisRange ); + } + else if(joystickBinderItem.direction == Control::DECREASE) + { + float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; + float valDisplaced = (float)(evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS); + + ctrl->setValue( 1 - ( valDisplaced / axisRange ) ); + } + } + } + } + else if(mDetectingBindingListener) + { + /*ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ]; + Control* ctrl = joystickBinderItem.control; + if(ctrl && ctrl->isAxisBindable()) + {*/ + if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable()) + { + if( abs( evt.state.mSliders[index].abX ) > ICS_JOYSTICK_SLIDER_BINDING_MARGIN) + { + mDetectingBindingListener->joystickSliderBindingDetected(this, + mDetectingBindingControl, evt.device->getID(), index, mDetectingBindingDirection); + } + } + } + } + + return true; + } + + // joystick auto bindings + void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int axis, Control::ControlChangingDirection direction) + { + // if the joystick axis is used by another control, remove it + ICS->removeJoystickAxisBinding(deviceId, axis); + + // if the control has an axis assigned, remove it + int oldAxis = ICS->getJoystickAxisBinding(control, deviceId, direction); + if(oldAxis != InputControlSystem::UNASSIGNED) + { + ICS->removeJoystickAxisBinding(deviceId, oldAxis); + } + + ICS->addJoystickAxisBinding(control, deviceId, axis, direction); + ICS->cancelDetectingBindingState(); + } + void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, unsigned int button, Control::ControlChangingDirection direction) + { + // if the joystick button is used by another control, remove it + ICS->removeJoystickButtonBinding(deviceId, button); + + // if the control has a joystick button assigned, remove it + unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceId, direction); + if(oldButton != ICS_MAX_DEVICE_BUTTONS) + { + ICS->removeJoystickButtonBinding(deviceId, oldButton); + } + + ICS->addJoystickButtonBinding(control, deviceId, button, direction); + ICS->cancelDetectingBindingState(); + } + + + void DetectingBindingListener::joystickPOVBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction) + { + // if the joystick slider is used by another control, remove it + ICS->removeJoystickPOVBinding(deviceId, pov, axis); + + // if the control has a joystick button assigned, remove it + ICS::InputControlSystem::POVBindingPair oldPOV = ICS->getJoystickPOVBinding(control, deviceId, direction); + if(oldPOV.index >= 0 && oldPOV.axis == axis) + { + ICS->removeJoystickPOVBinding(deviceId, oldPOV.index, oldPOV.axis); + } + + ICS->addJoystickPOVBinding(control, deviceId, pov, axis, direction); + ICS->cancelDetectingBindingState(); + } + + void DetectingBindingListener::joystickSliderBindingDetected(InputControlSystem* ICS, Control* control + , int deviceId, int slider, Control::ControlChangingDirection direction) + { + // if the joystick slider is used by another control, remove it + ICS->removeJoystickSliderBinding(deviceId, slider); + + // if the control has a joystick slider assigned, remove it + int oldSlider = ICS->getJoystickSliderBinding(control, deviceId, direction); + if(oldSlider != InputControlSystem::/*NamedAxis::*/UNASSIGNED) + { + ICS->removeJoystickSliderBinding(deviceId, oldSlider); + } + + ICS->addJoystickSliderBinding(control, deviceId, slider, direction); + ICS->cancelDetectingBindingState(); + } +} \ No newline at end of file diff --git a/extern/oics/ICSInputControlSystem_keyboard.cpp b/extern/oics/ICSInputControlSystem_keyboard.cpp new file mode 100644 index 0000000000..8ef81d9794 --- /dev/null +++ b/extern/oics/ICSInputControlSystem_keyboard.cpp @@ -0,0 +1,156 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +namespace ICS +{ + void InputControlSystem::loadKeyBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlKeyBinder = xmlControlNode->FirstChildElement("KeyBinder"); + while(xmlKeyBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlKeyBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlKeyBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + addKeyBinding(mControls.back(), mKeys[xmlKeyBinder->Attribute("key")], dir); + + xmlKeyBinder = xmlKeyBinder->NextSiblingElement("KeyBinder"); + } + } + + void InputControlSystem::addKeyBinding(Control* control, OIS::KeyCode key, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding KeyBinder [key=" + + keyCodeToString(key) + ", direction=" + + ToString(direction) + "]"); + + ControlKeyBinderItem controlKeyBinderItem; + controlKeyBinderItem.control = control; + controlKeyBinderItem.direction = direction; + mControlsKeyBinderMap[ key ] = controlKeyBinderItem; + } + + void InputControlSystem::removeKeyBinding(OIS::KeyCode key) + { + ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key); + if(it != mControlsKeyBinderMap.end()) + { + mControlsKeyBinderMap.erase(it); + } + } + + OIS::KeyCode InputControlSystem::getKeyBinding(Control* control + , ICS::Control::ControlChangingDirection direction) + { + ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.begin(); + while(it != mControlsKeyBinderMap.end()) + { + if(it->second.control == control && it->second.direction == direction) + { + return it->first; + } + it++; + } + + return OIS::KC_UNASSIGNED; + } + bool InputControlSystem::keyPressed(const OIS::KeyEvent &evt) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.key); + if(it != mControlsKeyBinderMap.end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->keyBindingDetected(this, + mDetectingBindingControl, evt.key, mDetectingBindingDirection); + } + } + + return true; + } + + bool InputControlSystem::keyReleased(const OIS::KeyEvent &evt) + { + if(mActive) + { + ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.key); + if(it != mControlsKeyBinderMap.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + + return true; + } + + void DetectingBindingListener::keyBindingDetected(InputControlSystem* ICS, Control* control + , OIS::KeyCode key, Control::ControlChangingDirection direction) + { + // if the key is used by another control, remove it + ICS->removeKeyBinding(key); + + // if the control has a key assigned, remove it + OIS::KeyCode oldKey = ICS->getKeyBinding(control, direction); + if(oldKey != OIS::KC_UNASSIGNED) + { + ICS->removeKeyBinding(oldKey); + } + + ICS->addKeyBinding(control, key, direction); + ICS->cancelDetectingBindingState(); + } + +} \ No newline at end of file diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp new file mode 100644 index 0000000000..c62f1765e6 --- /dev/null +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -0,0 +1,397 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSInputControlSystem.h" + +namespace ICS +{ + // load xml + void InputControlSystem::loadMouseAxisBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlMouseBinder = xmlControlNode->FirstChildElement("MouseBinder"); + while(xmlMouseBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlMouseBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlMouseBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + NamedAxis axis = /*NamedAxis::*/ X; + if((*xmlMouseBinder->Attribute("axis")) == 'Y') + { + axis = /*NamedAxis::*/ Y; + } + else if((*xmlMouseBinder->Attribute("axis")) == 'Z') + { + axis = /*NamedAxis::*/ Z; + } + + addMouseAxisBinding(mControls.back(), axis, dir); + + xmlMouseBinder = xmlMouseBinder->NextSiblingElement("MouseBinder"); + } + } + + void InputControlSystem::loadMouseButtonBinders(TiXmlElement* xmlControlNode) + { + TiXmlElement* xmlMouseButtonBinder = xmlControlNode->FirstChildElement("MouseButtonBinder"); + while(xmlMouseButtonBinder) + { + Control::ControlChangingDirection dir = Control::STOP; + if(std::string(xmlMouseButtonBinder->Attribute("direction")) == "INCREASE") + { + dir = Control::INCREASE; + } + else if(std::string(xmlMouseButtonBinder->Attribute("direction")) == "DECREASE") + { + dir = Control::DECREASE; + } + + int button = 0; + if(std::string(xmlMouseButtonBinder->Attribute("button")) == "LEFT") + { + button = OIS::/*MouseButtonID::*/MB_Left; + } + else if(std::string(xmlMouseButtonBinder->Attribute("button")) == "RIGHT") + { + button = OIS::/*MouseButtonID::*/MB_Right; + } + else if(std::string(xmlMouseButtonBinder->Attribute("button")) == "MIDDLE") + { + button = OIS::/*MouseButtonID::*/MB_Middle; + } + else + { + button = FromString(xmlMouseButtonBinder->Attribute("button")); + } + + addMouseButtonBinding(mControls.back(), button, dir); + + xmlMouseButtonBinder = xmlMouseButtonBinder->NextSiblingElement("MouseButtonBinder"); + } + } + + + // add bindings + void InputControlSystem::addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction) + { + if(axis == /*NamedAxis::*/X) + { + mXmouseAxisBinded = true; + } + else if(axis == /*NamedAxis::*/Y) + { + mYmouseAxisBinded = true; + } + + addMouseAxisBinding_(control, axis, direction); + } + + /*protected*/ void InputControlSystem::addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding AxisBinder [axis=" + + ToString(axis) + ", direction=" + + ToString(direction) + "]"); + + ControlAxisBinderItem controlAxisBinderItem; + controlAxisBinderItem.control = control; + controlAxisBinderItem.direction = direction; + mControlsMouseAxisBinderMap[ axis ] = controlAxisBinderItem; + } + + void InputControlSystem::addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction) + { + ICS_LOG("\tAdding MouseButtonBinder [button=" + + ToString(button) + ", direction=" + + ToString(direction) + "]"); + + ControlButtonBinderItem controlMouseButtonBinderItem; + controlMouseButtonBinderItem.direction = direction; + controlMouseButtonBinderItem.control = control; + mControlsMouseButtonBinderMap[ button ] = controlMouseButtonBinderItem; + } + + // get bindings + InputControlSystem::NamedAxis InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction) + { + ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.begin(); + while(it != mControlsMouseAxisBinderMap.end()) + { + if(it->first < 0 && it->second.control == control && it->second.direction == direction) + { + return (InputControlSystem::NamedAxis)(it->first); + } + it++; + } + + return /*NamedAxis::*/UNASSIGNED; + } + + //int InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction) + //{ + // ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.begin(); + // while(it != mControlsMouseAxisBinderMap.end()) + // { + // if(it->first >= 0 && it->second.control == control && it->second.direction == direction) + // { + // return it->first; + // } + // it++; + // } + + // return /*NamedAxis::*/UNASSIGNED; + //} + + unsigned int InputControlSystem::getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction) + { + ControlsButtonBinderMapType::iterator it = mControlsMouseButtonBinderMap.begin(); + while(it != mControlsMouseButtonBinderMap.end()) + { + if(it->second.control == control && it->second.direction == direction) + { + return it->first; + } + it++; + } + + return ICS_MAX_DEVICE_BUTTONS; + } + + // remove bindings + void InputControlSystem::removeMouseAxisBinding(NamedAxis axis) + { + if(axis == /*NamedAxis::*/X) + { + mXmouseAxisBinded = false; + } + else if(axis == /*NamedAxis::*/Y) + { + mYmouseAxisBinded = false; + } + + removeMouseAxisBinding_(axis); + } + /*protected*/ void InputControlSystem::removeMouseAxisBinding_(int axis) + { + ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.find(axis); + if(it != mControlsMouseAxisBinderMap.end()) + { + mControlsMouseAxisBinderMap.erase(it); + } + } + + + void InputControlSystem::removeMouseButtonBinding(unsigned int button) + { + ControlsButtonBinderMapType::iterator it = mControlsMouseButtonBinderMap.find(button); + if(it != mControlsMouseButtonBinderMap.end()) + { + mControlsMouseButtonBinderMap.erase(it); + } + } + + // mouse Listeners + bool InputControlSystem::mouseMoved(const OIS::MouseEvent &evt) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mXmouseAxisBinded && evt.state.X.rel) + { + ControlAxisBinderItem mouseBinderItem = mControlsMouseAxisBinderMap[ /*NamedAxis::*/X ]; + Control* ctrl = mouseBinderItem.control; + ctrl->setIgnoreAutoReverse(true); + if(mouseBinderItem.direction == Control::INCREASE) + { + ctrl->setValue( float( (evt.state.X.abs) / float(evt.state.width) ) ); + } + else if(mouseBinderItem.direction == Control::DECREASE) + { + ctrl->setValue( 1 - float( evt.state.X.abs / float(evt.state.width) ) ); + } + } + + if(mYmouseAxisBinded && evt.state.Y.rel) + { + ControlAxisBinderItem mouseBinderItem = mControlsMouseAxisBinderMap[ /*NamedAxis::*/Y ]; + Control* ctrl = mouseBinderItem.control; + ctrl->setIgnoreAutoReverse(true); + if(mouseBinderItem.direction == Control::INCREASE) + { + ctrl->setValue( float( (evt.state.Y.abs) / float(evt.state.height) ) ); + } + else if(mouseBinderItem.direction == Control::DECREASE) + { + ctrl->setValue( 1 - float( evt.state.Y.abs / float(evt.state.height) ) ); + } + } + + //! @todo Whats the range of the Z axis? + /*if(evt.state.Z.rel) + { + ControlAxisBinderItem mouseBinderItem = mControlsAxisBinderMap[ NamedAxis::Z ]; + Control* ctrl = mouseBinderItem.control; + ctrl->setIgnoreAutoReverse(true); + if(mouseBinderItem.direction == Control::INCREASE) + { + ctrl->setValue( float( (evt.state.Z.abs) / float(evt.state.¿width?) ) ); + } + else if(mouseBinderItem.direction == Control::DECREASE) + { + ctrl->setValue( float( (1 - evt.state.Z.abs) / float(evt.state.¿width?) ) ); + } + }*/ + } + else if(mDetectingBindingListener) + { + if(mDetectingBindingControl->isAxisBindable()) + { + if(mMouseAxisBindingInitialValues[0] == ICS_MOUSE_AXIS_BINDING_NULL_VALUE) + { + mMouseAxisBindingInitialValues[0] = 0; + mMouseAxisBindingInitialValues[1] = 0; + mMouseAxisBindingInitialValues[2] = 0; + } + + mMouseAxisBindingInitialValues[0] += evt.state.X.rel; + mMouseAxisBindingInitialValues[1] += evt.state.Y.rel; + mMouseAxisBindingInitialValues[2] += evt.state.Z.rel; + + if( abs(mMouseAxisBindingInitialValues[0]) > ICS_MOUSE_BINDING_MARGIN ) + { + mDetectingBindingListener->mouseAxisBindingDetected(this, + mDetectingBindingControl, X, mDetectingBindingDirection); + } + else if( abs(mMouseAxisBindingInitialValues[1]) > ICS_MOUSE_BINDING_MARGIN ) + { + mDetectingBindingListener->mouseAxisBindingDetected(this, + mDetectingBindingControl, Y, mDetectingBindingDirection); + } + else if( abs(mMouseAxisBindingInitialValues[2]) > ICS_MOUSE_BINDING_MARGIN ) + { + mDetectingBindingListener->mouseAxisBindingDetected(this, + mDetectingBindingControl, Z, mDetectingBindingDirection); + } + } + } + } + + return true; + } + + bool InputControlSystem::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); + if(it != mControlsMouseButtonBinderMap.end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->mouseButtonBindingDetected(this, + mDetectingBindingControl, btn, mDetectingBindingDirection); + } + } + + return true; + } + + bool InputControlSystem::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) + { + if(mActive) + { + ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); + if(it != mControlsMouseButtonBinderMap.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + + return true; + } + + // mouse auto bindings + void DetectingBindingListener::mouseAxisBindingDetected(InputControlSystem* ICS, Control* control + , InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction) + { + // if the mouse axis is used by another control, remove it + ICS->removeMouseAxisBinding(axis); + + // if the control has an axis assigned, remove it + InputControlSystem::NamedAxis oldAxis = ICS->getMouseAxisBinding(control, direction); + if(oldAxis != InputControlSystem::UNASSIGNED) + { + ICS->removeMouseAxisBinding(oldAxis); + } + + ICS->addMouseAxisBinding(control, axis, direction); + ICS->cancelDetectingBindingState(); + } + + void DetectingBindingListener::mouseButtonBindingDetected(InputControlSystem* ICS, Control* control + , unsigned int button, Control::ControlChangingDirection direction) + { + // if the mouse button is used by another control, remove it + ICS->removeMouseButtonBinding(button); + + // if the control has a mouse button assigned, remove it + unsigned int oldButton = ICS->getMouseButtonBinding(control, direction); + if(oldButton != ICS_MAX_DEVICE_BUTTONS) + { + ICS->removeMouseButtonBinding(oldButton); + } + + ICS->addMouseButtonBinding(control, button, direction); + ICS->cancelDetectingBindingState(); + } + +} \ No newline at end of file diff --git a/extern/oics/ICSPrerequisites.cpp b/extern/oics/ICSPrerequisites.cpp new file mode 100644 index 0000000000..2824950ed1 --- /dev/null +++ b/extern/oics/ICSPrerequisites.cpp @@ -0,0 +1,27 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +#include "ICSPrerequisites.h" diff --git a/extern/oics/ICSPrerequisites.h b/extern/oics/ICSPrerequisites.h new file mode 100644 index 0000000000..3b5d1935b4 --- /dev/null +++ b/extern/oics/ICSPrerequisites.h @@ -0,0 +1,110 @@ +/* ------------------------------------------------------- +Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es) + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of +the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------- */ + +//! @todo add mouse wheel support + +#ifndef _InputControlSystem_Prerequisites_H_ +#define _InputControlSystem_Prerequisites_H_ + +/// Include external headers +#include +#include +#include +#include +#include +#include + +#include "tinyxml.h" + +#include +#include +#include +#include +#include + +/// Define the dll export qualifier if compiling for Windows + +/* +#ifdef ICS_PLATFORM_WIN32 + #ifdef ICS_LIB + #define DllExport __declspec (dllexport) + #else + #define DllExport __declspec (dllimport) + #endif +#else + #define DllExport +#endif +*/ +#define DllExport + +// Define some macros +#define ICS_DEPRECATED __declspec(deprecated("Deprecated. It will be removed in future versions.")) + +/// Version defines +#define ICS_VERSION_MAJOR 0 +#define ICS_VERSION_MINOR 3 +#define ICS_VERSION_PATCH 1 + +#define ICS_MAX_DEVICE_BUTTONS 30 + +namespace ICS +{ + template + bool StringIsNumber ( const std::string &Text ) + { + std::stringstream ss(Text); + T result; + return ss >> result ? true : false; + } + + // from http://www.cplusplus.com/forum/articles/9645/ + template + std::string ToString ( T value ) + { + std::stringstream ss; + ss << value; + return ss.str(); + } + + // from http://www.cplusplus.com/forum/articles/9645/ + template + T FromString ( const std::string &Text )//Text not by const reference so that the function can be used with a + { //character array as argument + std::stringstream ss(Text); + T result; + return ss >> result ? result : 0; + } + + class InputControlSystem; + class Channel; + class ChannelListener; + class Control; + class ControlListener; + class DetectingBindingListener; + class InputControlSystemLog; +} + +#endif diff --git a/extern/oics/tinystr.cpp b/extern/oics/tinystr.cpp new file mode 100644 index 0000000000..681250714b --- /dev/null +++ b/extern/oics/tinystr.cpp @@ -0,0 +1,116 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005. + */ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/extern/oics/tinystr.h b/extern/oics/tinystr.h new file mode 100644 index 0000000000..419e647e16 --- /dev/null +++ b/extern/oics/tinystr.h @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp new file mode 100644 index 0000000000..841a41cd39 --- /dev/null +++ b/extern/oics/tinyxml.cpp @@ -0,0 +1,1888 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + return 0; + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return &node->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const char* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s ); + } + else { + *i = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const std::string* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s->c_str() ); + } + else { + *i = 0; + } + } + return s; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const char* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s ); + } + else { + *d = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const std::string* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s->c_str() ); + } + else { + *d = 0; + } + } + return s; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); + #else + sprintf( buf, "%d", val ); + #endif + SetAttribute( name, buf ); +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + std::ostringstream oss; + oss << val; + SetAttribute( name, oss.str() ); +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); + #else + sprintf( buf, "%f", val ); + #endif + SetAttribute( name, buf ); +} + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING _name( cname ); + TIXML_STRING _value( cvalue ); + #else + const char* _name = cname; + const char* _value = cvalue; + #endif + + TiXmlAttribute* node = attributeSet.Find( _name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + // See STL_STRING_BUG below. + //StringToBuffer buf( value ); + + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + // See STL_STRING_BUG below. +// StringToBuffer buf( value ); +// +// if ( buf.buffer && SaveFile( buf.buffer ) ) +// return true; +// +// return false; + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // Add an extra string to avoid the crash. + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + const char* lastPos = buf; + const char* p = buf; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + if ( *p == 0xa ) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append( lastPos, (p-lastPos+1) ); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert( p <= (buf+length) ); + } + else if ( *p == 0xd ) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ( (p-lastPos) > 0 ) { + data.append( lastPos, p-lastPos ); // do not add the CR + } + data += (char)0xa; // a proper newline + + if ( *(p+1) == 0xa ) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert( p <= (buf+length) ); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert( p <= (buf+length) ); + } + } + else { + ++p; + } + } + // Handle any left over characters. + if ( p-lastPos ) { + data.append( lastPos, p-lastPos ); + } + delete [] buf; + buf = 0; + + Parse( data.c_str(), 0, encoding ); + + if ( Error() ) + return false; + else + return true; +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); + #else + sprintf (buf, "%lf", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} +*/ +#endif + + +const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} +*/ + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/extern/oics/tinyxml.h b/extern/oics/tinyxml.h new file mode 100644 index 0000000000..e69913b59c --- /dev/null +++ b/extern/oics/tinyxml.h @@ -0,0 +1,1802 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ +//#define TIXML_USE_STL + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 3; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simple called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + + #endif + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + /* + This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" + but template specialization is hard to get working cross-compiler. Leaving the bug for now. + + // The above will fail for std::string because the space character is used as a seperator. + // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string + template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + */ + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + TiXmlDocument* doc = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + +// int tabsize = 4; +// if ( document ) +// tabsize = document->TabSize(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/mainmenu.cfg b/files/mygui/mainmenu.cfg new file mode 100644 index 0000000000..7aaf8c1c72 --- /dev/null +++ b/files/mygui/mainmenu.cfg @@ -0,0 +1,95 @@ +[settings] + size_x = 512 + size_y = 512 + + +[menu_newgame.dds] + x = 0 + y = 0 + +[menu_newgame_pressed.dds] + x = 128 + y = 0 + +[menu_newgame_over.dds] + x = 256 + y = 0 + + +[menu_loadgame.dds] + x = 384 + y = 0 + +[menu_loadgame_pressed.dds] + x = 0 + y = 64 + +[menu_loadgame_over.dds] + x = 128 + y = 64 + + +[menu_options.dds] + x = 256 + y = 64 + +[menu_options_pressed.dds] + x = 384 + y = 64 + +[menu_options_over.dds] + x = 0 + y = 128 + + +[menu_credits.dds] + x = 128 + y = 128 + +[menu_credits_pressed.dds] + x = 256 + y = 128 + +[menu_credits_over.dds] + x = 384 + y = 128 + + +[menu_exitgame.dds] + x = 0 + y = 192 + +[menu_exitgame_pressed.dds] + x = 128 + y = 192 + +[menu_exitgame_over.dds] + x = 256 + y = 192 + + +[menu_savegame.dds] + x = 384 + y = 192 + +[menu_savegame_pressed.dds] + x = 0 + y = 256 + +[menu_savegame_over.dds] + x = 128 + y = 256 + + +[menu_return.dds] + x = 256 + y = 256 + +[menu_return_pressed.dds] + x = 384 + y = 256 + +[menu_return_over.dds] + x = 0 + y = 320 + diff --git a/files/mygui/markers.png b/files/mygui/markers.png new file mode 100644 index 0000000000..76b6b9913b Binary files /dev/null and b/files/mygui/markers.png differ diff --git a/files/mygui/openmw.font.xml b/files/mygui/openmw.font.xml index 73d491e04e..cb5dd648f8 100644 --- a/files/mygui/openmw.font.xml +++ b/files/mygui/openmw.font.xml @@ -12,6 +12,7 @@ + diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index cf353a205e..e4c6f0765e 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -76,18 +76,21 @@ - + - - + + + + + diff --git a/files/mygui/openmw_itemselection_dialog.layout b/files/mygui/openmw_itemselection_dialog.layout new file mode 100644 index 0000000000..81376d6d5c --- /dev/null +++ b/files/mygui/openmw_itemselection_dialog.layout @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 56f800ea34..7a8d586d2e 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -4,8 +4,6 @@ - - diff --git a/files/mygui/openmw_magicselection_dialog.layout b/files/mygui/openmw_magicselection_dialog.layout new file mode 100644 index 0000000000..31ad7b4c9f --- /dev/null +++ b/files/mygui/openmw_magicselection_dialog.layout @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_mainmenu.layout b/files/mygui/openmw_mainmenu.layout index bf17be7f70..4479a121f6 100644 --- a/files/mygui/openmw_mainmenu.layout +++ b/files/mygui/openmw_mainmenu.layout @@ -2,16 +2,5 @@ - - - - - - - - - - - - + diff --git a/files/mygui/openmw_map_window_skin.xml b/files/mygui/openmw_map_window_skin.xml index fbb7af7aef..0c6050969d 100644 --- a/files/mygui/openmw_map_window_skin.xml +++ b/files/mygui/openmw_map_window_skin.xml @@ -5,7 +5,7 @@ - - + + diff --git a/files/mygui/openmw_quickkeys_menu.layout b/files/mygui/openmw_quickkeys_menu.layout new file mode 100644 index 0000000000..a45f2896fd --- /dev/null +++ b/files/mygui/openmw_quickkeys_menu.layout @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_quickkeys_menu_assign.layout b/files/mygui/openmw_quickkeys_menu_assign.layout new file mode 100644 index 0000000000..4bbd9f1fa5 --- /dev/null +++ b/files/mygui/openmw_quickkeys_menu_assign.layout @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index f1a8b0dfc7..5a695515d4 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -1,6 +1,8 @@ + + @@ -44,6 +46,10 @@ + + + + @@ -113,6 +119,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index a14606ade9..c8eae518f7 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -41,6 +41,18 @@ + + + + + + + + + + + + @@ -82,6 +94,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -121,11 +181,11 @@ - + - + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index a723e307c8..8fab98da24 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -29,7 +29,9 @@ vsync = false menu transparency = 0.84 # 0 - instantly, 1 - max. delay -tooltip delay = 0.2 +tooltip delay = 0 + +subtitles = false [General] # Camera field of view @@ -85,6 +87,8 @@ debug = false # 2: advanced FPS display (batches, triangles) fps = 0 +crosshair = true + [Objects] shaders = true @@ -144,3 +148,16 @@ sfx volume = 1.0 music volume = 0.4 footsteps volume = 0.6 voice volume = 1.0 + + +[Input] + +invert y axis = false + +camera sensitivity = 1.0 + +ui sensitivity = 1.0 + +camera y multiplier = 1.0 + +ui y multiplier = 1.0 diff --git a/libs/mangle/.gitignore b/libs/mangle/.gitignore deleted file mode 100644 index cd24d78972..0000000000 --- a/libs/mangle/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -upload_docs.sh -docs -*~ diff --git a/libs/mangle/Doxyfile b/libs/mangle/Doxyfile deleted file mode 100644 index f3e0180029..0000000000 --- a/libs/mangle/Doxyfile +++ /dev/null @@ -1,1510 +0,0 @@ -# Doxyfile 1.5.8 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Mangle - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 1 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, -# Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = YES - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = sound stream vfs input - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = */tests/* - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = docs - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. - -GENERATE_TREEVIEW = NONE - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Options related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/libs/mangle/LICENSE.txt b/libs/mangle/LICENSE.txt deleted file mode 100644 index ccfcc9f220..0000000000 --- a/libs/mangle/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ -Minimal Abstraction Game Layer (Mangle) is licensed under the -'zlib/libpng' license: - ----- - -Copyright (c) 2009 Nicolay Korslund - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. - diff --git a/libs/mangle/README.txt b/libs/mangle/README.txt deleted file mode 100644 index f4849bebda..0000000000 --- a/libs/mangle/README.txt +++ /dev/null @@ -1,129 +0,0 @@ -Welcome to Mangle v0.1 ----------------------- - -Written by: Nicolay Korslund (korslund@gmail.com) -License: zlib/png (see LICENSE.txt) -WWW: http://asm-soft.com/mangle/ -Documentation: http://asm-soft.com/mangle/docs - - - -Mangle is the project name for a small set of generic interfaces for -various game middleware libraries, such as sound, input, graphics, and -so on. You can imagine that it stands for "Minimal Abstraction Game -Layer", if you like. It will consist of several more or less -independent modules, one for each of these areas. These may be used -together to build an entire game engine, or they can be used -individually as separate libraries. - -However, Mangle does NOT actually implement a game engine, or any new -fundamental functionality. More on that below. - -Currently there's modules for sound and streams / archives (virtual -file systems.) More will come in the future (including input, 2D/3D -graphics, GUI, physics, and more.) - - -Main idea ---------- - -The idea behind Mangle is to provide a uniform, consistent interface -to other game libraries. The library does not provide ANY -functionality on its own. Instead it connects to a backend -implementation of your choice (or of your making.) - -The Sound module, for example, currently has backends for OpenAL -(output only), FFmpeg (input only) and for Audiere. Hopefully we'll -add IrrKlang, FMod, DirectSound, Miles and more in the future. It can -combine libraries to get more complete functionality (like using -OpenAL for output and FFmpeg to decode sound files), and it's also -easy to write your own backend if you're using a different (or -home-brewed) sound system. - -Regardless of what backend you use, the front-end interfaces (found -eg. in sound/output.h) is identical, and as a library user you -shouldn't notice much difference at all if you swap one backend for -another at a later point. It should Just Work. - -The interfaces themselves are also quite simple. Setting up a sound -stream from FFmpeg or other decoder into OpenAL can be quite hairy - -but with Mangle the hairy parts have already been written for you. You -just plug the parts together. - -The goal in the long run is to support a wide variety of game-related -libraries, and as many backend libraries (free and commercial) as -possible, so that you the user will have to write as little code as -possible. - - - -What is it good for -------------------- - -The main point of Mangle, as we said above, is that it connects to any -library of your choice "behind the scenes" but provides the same, -super-simple interface front-end for all of them. There can benefit -you in many ways: - -- If you want to use a new library that Mangle support. You don't have - to scour the net for tutorials and usage examples, since much of the - common usage code is already included in the implementation classes. - -- If you don't want to pollute your code with library-specific code. - The Mangle interfaces can help you keep your code clean, and its - user interface is often simpler than the exteral library one. - -- If you want to quickly connect different libraries together, it - really helps if they speak a common language. The Mangle interfaces - are exactly that - a common language between libraries. Do you need - Audiere to load sounds from a weird archive format only implemented - for PhysFS, all channeled through the OGRE resource system? No - problem! - -- If you are creating a library that depends on a specific feature - (such as sound), but you don't want to lock your users into any - specific sound library. Mangle works as an abstraction that lets - your users select their own implementation. - -- If you want to support multiple backends for your game/app, or want - to make it possible to easily switch backends later. You can select - backends at compile time or even at runtime. For example you might - want to switch to to a commercial sound library at a later stage in - development, or you may want to use a different input library on - console platforms than on PC. - -The Mangle implementations are extremely light-weight - often just one -or two cpp/h pairs per module. You can plug them directly into your -program, there's no separate library building step required. - -Since the library aims to be very modularly put together, you can -also, in many cases, just copy-and-paste the parts you need and ignore -the rest. Or modify stuff without fearing that the whole 'system' will -come crashing down, because there is no big 'system' to speak of. - - -Past and future ---------------- - -Mangle started out as (and still is) a spin-off from OpenMW, another -project I am personally working on ( http://openmw.com/ ). OpenMW is -an attempt to recreate the engine behind the commercial game -Morrowind, using only open source software. - -The projects are still tightly interlinked, and they will continue to -be until OpenMW is finished. Most near-future work on Mangle will be -focused chiefly on OpenMW at the moment. However I will gladly include -external contributions and suggestions that are not OpenMW-related if -someone sends them to me. - - -Conclusion ----------- - -As you might have guessed, Mangle is more a concept in development -than a finished library right now. - -All feedback, ideas, concepts, questions and code are very -welcome. Send them to: korslund@gmail.com - -I will put up a forum later as well if there's enough interest. diff --git a/libs/mangle/input/clients/ogre_input_capture.hpp b/libs/mangle/input/clients/ogre_input_capture.hpp deleted file mode 100644 index 2e77dc10b1..0000000000 --- a/libs/mangle/input/clients/ogre_input_capture.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MANGLE_INPUT_OGREINPUTFRAME_H -#define MANGLE_INPUT_OGREINPUTFRAME_H - -/* - This Ogre FrameListener calls capture() on an input driver every frame. - */ - -#include -#include "../driver.hpp" - -namespace Mangle { -namespace Input { - - struct OgreInputCapture : Ogre::FrameListener - { - Mangle::Input::Driver &driver; - - OgreInputCapture(Mangle::Input::Driver &drv) - : driver(drv) {} - - bool frameStarted(const Ogre::FrameEvent &evt) - { - driver.capture(); - return true; - } - }; -}} - -#endif diff --git a/libs/mangle/input/driver.hpp b/libs/mangle/input/driver.hpp deleted file mode 100644 index f4ba159c52..0000000000 --- a/libs/mangle/input/driver.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef MANGLE_INPUT_DRIVER_H -#define MANGLE_INPUT_DRIVER_H - -#include "event.hpp" - -namespace Mangle -{ - namespace Input - { - /** Input::Driver is the main interface to any input system that - handles keyboard and/or mouse input, along with any other - input source like joysticks. - - It is really a generalized event system, and could also be - used for non-input related events. The definition of the event - codes and structures are entirely dependent on the - implementation. - - A system-independent key code list will be found in keys.hpp, - and input drivers should privide optional translations to/from - this list for full compatibility. - */ - struct Driver - { - Driver() {} - virtual ~Driver() {} - - /** Captures input and produces the relevant events from it. An - event callback must be set with setEvent(), or all events - will be ignored. - */ - virtual void capture() = 0; - - /** Check the state of a given key or button. The key/button - definitions depends on the driver. - */ - virtual bool isDown(int index) = 0; - - /** Show or hide system mouse cursor - */ - virtual void showMouse(bool show) = 0; - - /** Set the event handler for input events. The evt->event() - function is called for each event. The meaning of the index - and *p parameters will be specific to each driver and to - each input system. - */ - void setEvent(EventPtr evt) - { event = evt; } - - /** Instigate an event. Is used internally for all events, but - can also be called from the outside to "fake" events from - this driver. - */ - void makeEvent(Event::Type type, int index, const void *p=NULL) - { - if(event) - event->event(type,index,p); - } - - private: - /// Holds the event callback set byt setEvent() - EventPtr event; - }; - - typedef boost::shared_ptr DriverPtr; - } -} -#endif diff --git a/libs/mangle/input/event.hpp b/libs/mangle/input/event.hpp deleted file mode 100644 index dc7b470887..0000000000 --- a/libs/mangle/input/event.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MANGLE_INPUT_EVENT_H -#define MANGLE_INPUT_EVENT_H - -#include "../tools/shared_ptr.hpp" - -namespace Mangle -{ - namespace Input - { - /** Generic callback for input events. The meaning of the - parameters depend on the system producing the events. - */ - struct Event - { - /// Event types - enum Type - { - EV_Unknown = 1, // Unknown event type - EV_KeyDown = 2, // Keyboard button was pressed - EV_KeyUp = 4, // Keyboard button was released - EV_Keyboard = 6, // All keyboard events - - EV_MouseMove = 8, // Mouse movement - EV_MouseDown = 16, // Mouse button pressed - EV_MouseUp = 32, // Mouse button released - EV_Mouse = 56, // All mouse events - - EV_ALL = 63 // All events - }; - - /** - Called upon all events. The first parameter give the event - type, the second gives additional data (usually the local - keysym or button index as defined by the driver), and the - pointer points to the full custom event structure provided by - the driver (the type may vary depending on the EventType, - this is defined in the Driver documentation.) - */ - virtual void event(Type type, int index, const void *p) = 0; - virtual ~Event() {} - }; - - typedef boost::shared_ptr EventPtr; - } -} -#endif diff --git a/libs/mangle/input/filters/eventlist.hpp b/libs/mangle/input/filters/eventlist.hpp deleted file mode 100644 index b3e2ff8f24..0000000000 --- a/libs/mangle/input/filters/eventlist.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MANGLE_INPUT_EVENTLIST_H -#define MANGLE_INPUT_EVENTLIST_H - -#include "../event.hpp" -#include - -namespace Mangle -{ - namespace Input - { - /** And Event handler that distributes each event to a list of - other handlers. Supports filtering events by their Type - parameter. - */ - struct EventList : Event - { - struct Filter - { - EventPtr evt; - int flags; - }; - std::vector list; - - void add(EventPtr e, int flags = EV_ALL) - { - Filter f; - f.evt = e; - f.flags = flags; - list.push_back(f); - } - - virtual void event(Type type, int index, const void *p) - { - std::vector::iterator it; - - for(it=list.begin(); it!=list.end(); it++) - { - if(type & it->flags) - it->evt->event(type,index,p); - } - } - }; - - typedef boost::shared_ptr EventListPtr; - } -} -#endif diff --git a/libs/mangle/input/servers/ois_driver.cpp b/libs/mangle/input/servers/ois_driver.cpp deleted file mode 100644 index 07ba3e83a7..0000000000 --- a/libs/mangle/input/servers/ois_driver.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "ois_driver.hpp" - -#include -#include -#include -#include - -#ifdef __APPLE_CC__ -#include -#endif - -using namespace Mangle::Input; -using namespace OIS; - -struct Mangle::Input::OISListener : OIS::KeyListener, OIS::MouseListener -{ - OISDriver &drv; - - OISListener(OISDriver &driver) - : drv(driver) {} - - bool keyPressed( const OIS::KeyEvent &arg ) - { - drv.makeEvent(Event::EV_KeyDown, arg.key, &arg); - return true; - } - - bool keyReleased( const OIS::KeyEvent &arg ) - { - drv.makeEvent(Event::EV_KeyUp, arg.key, &arg); - return true; - } - - bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) - { - // Mouse button events are handled as key events - // TODO: Translate mouse buttons into pseudo-keysyms - drv.makeEvent(Event::EV_MouseDown, id, &arg); - return true; - } - - bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) - { - // TODO: ditto - drv.makeEvent(Event::EV_MouseUp, id, &arg); - return true; - } - - bool mouseMoved( const OIS::MouseEvent &arg ) - { - drv.makeEvent(Event::EV_MouseMove, -1, &arg); - return true; - } -}; - -OISDriver::OISDriver(Ogre::RenderWindow *window, bool exclusive) -{ - assert(window); - - size_t windowHnd; - - window->getCustomAttribute("WINDOW", &windowHnd); - - std::ostringstream windowHndStr; - ParamList pl; - - windowHndStr << windowHnd; - pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); - - // Set non-exclusive mouse and keyboard input if the user requested - // it. - if(!exclusive) - { -#if defined OIS_WIN32_PLATFORM - pl.insert(std::make_pair(std::string("w32_mouse"), - std::string("DISCL_FOREGROUND" ))); - pl.insert(std::make_pair(std::string("w32_mouse"), - std::string("DISCL_NONEXCLUSIVE"))); - pl.insert(std::make_pair(std::string("w32_keyboard"), - std::string("DISCL_FOREGROUND"))); - pl.insert(std::make_pair(std::string("w32_keyboard"), - std::string("DISCL_NONEXCLUSIVE"))); -#elif defined OIS_LINUX_PLATFORM - pl.insert(std::make_pair(std::string("x11_mouse_grab"), - std::string("false"))); - pl.insert(std::make_pair(std::string("x11_mouse_hide"), - std::string("false"))); - pl.insert(std::make_pair(std::string("x11_keyboard_grab"), - std::string("false"))); - pl.insert(std::make_pair(std::string("XAutoRepeatOn"), - std::string("true"))); -#endif - } - -#ifdef __APPLE_CC__ - // Give the application window focus to receive input events - ProcessSerialNumber psn = { 0, kCurrentProcess }; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); -#endif - - inputMgr = InputManager::createInputSystem( pl ); - - // Create all devices - keyboard = static_cast(inputMgr->createInputObject - ( OISKeyboard, true )); - mouse = static_cast(inputMgr->createInputObject - ( OISMouse, true )); - - // Set mouse region - const MouseState &ms = mouse->getMouseState(); - ms.width = window->getWidth(); - ms.height = window->getHeight(); - - // Set up the input listener - listener = new OISListener(*this); - keyboard-> setEventCallback(listener); - mouse-> setEventCallback(listener); -} - -OISDriver::~OISDriver() -{ - // Delete the listener object - delete listener; - - if(inputMgr == NULL) return; - - // Kill the input systems. This will reset input options such as key - // repeat rate. - inputMgr->destroyInputObject(keyboard); - inputMgr->destroyInputObject(mouse); - InputManager::destroyInputSystem(inputMgr); - inputMgr = NULL; -} - -void OISDriver::capture() -{ - // Capture keyboard and mouse events - keyboard->capture(); - mouse->capture(); -} - -bool OISDriver::isDown(int index) -{ - // TODO: Extend to mouse buttons as well - return keyboard->isKeyDown((OIS::KeyCode)index); -} - -void OISDriver::adjustMouseClippingSize(int width, int height) -{ - const OIS::MouseState &ms = mouse->getMouseState(); - ms.width = width; - ms.height = height; -} diff --git a/libs/mangle/input/servers/ois_driver.hpp b/libs/mangle/input/servers/ois_driver.hpp deleted file mode 100644 index 81633542fb..0000000000 --- a/libs/mangle/input/servers/ois_driver.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MANGLE_INPUT_OIS_DRIVER_H -#define MANGLE_INPUT_OIS_DRIVER_H - -#include "../driver.hpp" - -namespace OIS -{ - class InputManager; - class Mouse; - class Keyboard; -} - -namespace Ogre -{ - class RenderWindow; -} - -namespace Mangle -{ - namespace Input - { - struct OISListener; - - /** Input driver for OIS, the input manager typically used with - Ogre. - */ - struct OISDriver : Driver - { - /// If exclusive=true, then we capture mouse and keyboard from - /// the OS. - OISDriver(Ogre::RenderWindow *window, bool exclusive=true); - ~OISDriver(); - - void adjustMouseClippingSize(int width, int height); - - void capture(); - bool isDown(int index); - /// Not currently supported. - void showMouse(bool) {} - - private: - OIS::InputManager *inputMgr; - OIS::Mouse *mouse; - OIS::Keyboard *keyboard; - - OISListener *listener; - }; - } -} -#endif diff --git a/libs/mangle/input/servers/sdl_driver.cpp b/libs/mangle/input/servers/sdl_driver.cpp deleted file mode 100644 index 93884a6e6c..0000000000 --- a/libs/mangle/input/servers/sdl_driver.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "sdl_driver.hpp" - -#include - -using namespace Mangle::Input; - -void SDLDriver::capture() -{ - // Poll for events - SDL_Event evt; - while(SDL_PollEvent(&evt)) - { - Event::Type type = Event::EV_Unknown; - int index = -1; - - switch(evt.type) - { - // For key events, send the keysym as the index. - case SDL_KEYDOWN: - type = Event::EV_KeyDown; - index = evt.key.keysym.sym; - break; - case SDL_KEYUP: - type = Event::EV_KeyUp; - index = evt.key.keysym.sym; - break; - case SDL_MOUSEMOTION: - type = Event::EV_MouseMove; - break; - // Add more event types later - } - - // Pass the event along, using -1 as index for unidentified - // event types. - makeEvent(type, index, &evt); - } -} - -bool SDLDriver::isDown(int index) -{ - int num; - Uint8 *keys = SDL_GetKeyState(&num); - assert(index >= 0 && index < num); - - // The returned array from GetKeyState is indexed by the - // SDLK_KEYNAME enums and is just a list of bools. If the indexed - // value is true, the button is down. - return keys[index]; -} - -void SDLDriver::showMouse(bool show) -{ - SDL_ShowCursor(show?SDL_ENABLE:SDL_DISABLE); -} diff --git a/libs/mangle/input/servers/sdl_driver.hpp b/libs/mangle/input/servers/sdl_driver.hpp deleted file mode 100644 index b71346cba1..0000000000 --- a/libs/mangle/input/servers/sdl_driver.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MANGLE_INPUT_SDL_DRIVER_H -#define MANGLE_INPUT_SDL_DRIVER_H - -#include "../driver.hpp" - -namespace Mangle -{ - namespace Input - { - /** Input driver for SDL. As the input system of SDL is seldomly - used alone (most often along with the video system), it is - assumed that you do your own initialization and cleanup of SDL - before and after using this driver. - - The Event.event() calls will be given the proper EV_ type, the - key index (for key up/down events), and a pointer to the full - SDL_Event structure. - */ - struct SDLDriver : Driver - { - void capture(); - bool isDown(int index); - void showMouse(bool); - }; - } -} -#endif diff --git a/libs/mangle/input/tests/.gitignore b/libs/mangle/input/tests/.gitignore deleted file mode 100644 index 460c76f00b..0000000000 --- a/libs/mangle/input/tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*_test -ogre.cfg diff --git a/libs/mangle/input/tests/Makefile b/libs/mangle/input/tests/Makefile deleted file mode 100644 index 8760adfe73..0000000000 --- a/libs/mangle/input/tests/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -GCC=g++ -Wall - -all: sdl_driver_test ois_driver_test evtlist_test - -sdl_driver_test: sdl_driver_test.cpp - $(GCC) $< ../servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL - -ois_driver_test: ois_driver_test.cpp - $(GCC) $< ../servers/ois_driver.cpp -o $@ -I/usr/local/include/OGRE/ -lOgreMain -lOIS -lboost_filesystem - -evtlist_test: evtlist_test.cpp ../filters/eventlist.hpp ../event.hpp - $(GCC) $< -o $@ - -clean: - rm *_test diff --git a/libs/mangle/input/tests/common.cpp b/libs/mangle/input/tests/common.cpp deleted file mode 100644 index 0c7c76466b..0000000000 --- a/libs/mangle/input/tests/common.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "../driver.hpp" -#include -using namespace std; -using namespace Mangle::Input; - -Driver *input; - -struct MyCB : Event -{ - void event(Event::Type type, int i, const void *p) - { - cout << "got event: type=" << type << " index=" << i << endl; - } -}; - -void mainLoop(int argc, int quitKey) -{ - cout << "Hold the Q key to quit:\n"; - input->setEvent(EventPtr(new MyCB)); - while(!input->isDown(quitKey)) - { - input->capture(); - usleep(20000); - - if(argc == 1) - { - cout << "You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly\n"; - break; - } - } - - delete input; - cout << "\nBye bye!\n"; -} diff --git a/libs/mangle/input/tests/evtlist_test.cpp b/libs/mangle/input/tests/evtlist_test.cpp deleted file mode 100644 index fbd980cbd9..0000000000 --- a/libs/mangle/input/tests/evtlist_test.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include "../filters/eventlist.hpp" - -using namespace std; -using namespace Mangle::Input; - -struct MyEvent : Event -{ - int ii; - MyEvent(int i) : ii(i) {} - - void event(Event::Type type, int i, const void *p) - { - cout << " #" << ii << " got event: type=" << type << " index=" << i << endl; - } -}; - -EventList lst; - -int iii=1; -void make(int flags) -{ - lst.add(EventPtr(new MyEvent(iii++)), flags); -} - -void send(Event::Type type) -{ - cout << "Sending type " << type << endl; - lst.event(type,0,NULL); -} - -int main() -{ - make(Event::EV_ALL); - make(Event::EV_KeyDown); - make(Event::EV_KeyUp | Event::EV_MouseDown); - - send(Event::EV_Unknown); - send(Event::EV_KeyDown); - send(Event::EV_KeyUp); - send(Event::EV_MouseDown); - - cout << "Enough of that\n"; - return 0; -} diff --git a/libs/mangle/input/tests/ois_driver_test.cpp b/libs/mangle/input/tests/ois_driver_test.cpp deleted file mode 100644 index 386f24055e..0000000000 --- a/libs/mangle/input/tests/ois_driver_test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "common.cpp" - -#include "../servers/ois_driver.hpp" -#include -#include -#include - -bool isFile(const char *name) -{ - boost::filesystem::path cfg_file_path(name); - return boost::filesystem::exists(cfg_file_path); -} - -using namespace Ogre; -using namespace OIS; - -Root *root; -RenderWindow *window; - -void setupOgre() -{ - // Disable logging - new LogManager; - Log *log = LogManager::getSingleton().createLog(""); - log->setDebugOutputEnabled(false); - - bool useConfig = isFile("ogre.cfg"); - - // Set up Root - root = new Root("plugins.cfg", "ogre.cfg", ""); - - // Configure - if(!useConfig) - root->showConfigDialog(); - else - root->restoreConfig(); - - // Initialize OGRE window - window = root->initialise(true, "test", ""); -} - -int main(int argc, char** argv) -{ - setupOgre(); - input = new OISDriver(window); - - mainLoop(argc, KC_Q); - - delete root; - return 0; -} diff --git a/libs/mangle/input/tests/output/evtlist_test.out b/libs/mangle/input/tests/output/evtlist_test.out deleted file mode 100644 index 180dcc58a8..0000000000 --- a/libs/mangle/input/tests/output/evtlist_test.out +++ /dev/null @@ -1,12 +0,0 @@ -Sending type 1 - #1 got event: type=1 index=0 -Sending type 2 - #1 got event: type=2 index=0 - #2 got event: type=2 index=0 -Sending type 4 - #1 got event: type=4 index=0 - #3 got event: type=4 index=0 -Sending type 16 - #1 got event: type=16 index=0 - #3 got event: type=16 index=0 -Enough of that diff --git a/libs/mangle/input/tests/output/ois_driver_test.out b/libs/mangle/input/tests/output/ois_driver_test.out deleted file mode 100644 index 7d273fd46d..0000000000 --- a/libs/mangle/input/tests/output/ois_driver_test.out +++ /dev/null @@ -1,5 +0,0 @@ -Hold the Q key to quit: -got event: type=8 index=-1 -You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly - -Bye bye! diff --git a/libs/mangle/input/tests/output/sdl_driver_test.out b/libs/mangle/input/tests/output/sdl_driver_test.out deleted file mode 100644 index 2df2e4014e..0000000000 --- a/libs/mangle/input/tests/output/sdl_driver_test.out +++ /dev/null @@ -1,5 +0,0 @@ -Hold the Q key to quit: -got event: type=1 index=-1 -You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly - -Bye bye! diff --git a/libs/mangle/input/tests/plugins.cfg b/libs/mangle/input/tests/plugins.cfg deleted file mode 100644 index 57ec54e1a0..0000000000 --- a/libs/mangle/input/tests/plugins.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# Defines plugins to load - -# Define plugin folder -PluginFolder=/usr/local/lib/OGRE/ - -# Define plugins -Plugin=RenderSystem_GL -Plugin=Plugin_ParticleFX -Plugin=Plugin_OctreeSceneManager -# Plugin=Plugin_CgProgramManager - - diff --git a/libs/mangle/input/tests/sdl_driver_test.cpp b/libs/mangle/input/tests/sdl_driver_test.cpp deleted file mode 100644 index 5db6dbba8f..0000000000 --- a/libs/mangle/input/tests/sdl_driver_test.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "common.cpp" - -#include "../servers/sdl_driver.hpp" -#include - -int main(int argc, char** argv) -{ - SDL_Init(SDL_INIT_VIDEO); - SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE); - input = new SDLDriver(); - - mainLoop(argc, SDLK_q); - - SDL_Quit(); - return 0; -} diff --git a/libs/mangle/input/tests/test.sh b/libs/mangle/input/tests/test.sh deleted file mode 100755 index 2d07708adc..0000000000 --- a/libs/mangle/input/tests/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -make || exit - -mkdir -p output - -PROGS=*_test - -for a in $PROGS; do - if [ -f "output/$a.out" ]; then - echo "Running $a:" - ./$a | diff output/$a.out - - else - echo "Creating $a.out" - ./$a > "output/$a.out" - git add "output/$a.out" - fi -done diff --git a/libs/mangle/rend2d/driver.hpp b/libs/mangle/rend2d/driver.hpp deleted file mode 100644 index 08a15b0aeb..0000000000 --- a/libs/mangle/rend2d/driver.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef MANGLE_REND2D_DRIVER_H -#define MANGLE_REND2D_DRIVER_H - -#include -#include "sprite.hpp" - -namespace Mangle -{ - namespace Rend2D - { - /** - The driver is the connection to the backend system that powers - 2D sprite rendering. For example the backend could be SDL or - any other 2D-capable graphics library. - */ - struct Driver - { - /// Get the screen sprite - virtual Sprite *getScreen() = 0; - - /// Sets the video mode. - virtual void setVideoMode(int width, int height, int bpp=32, bool fullscreen=false) = 0; - - /** Update the screen. Until this function is called, none of - the changes written to the screen sprite will be visible. - */ - virtual void update() = 0; - - /// Set the window title, as well as the title of the window - /// when "iconified" - virtual void setWindowTitle(const std::string &title, - const std::string &icon) = 0; - - /// Set the window title - void setWindowTitle(const std::string &title) { setWindowTitle(title,title); } - - /// Load sprite from an image file. Thows an exception on - /// failure. - virtual Sprite* loadImage(const std::string &file) = 0; - - /// Load a sprite from an image file stored in memory. Throws - /// exception on failure. - virtual Sprite* loadImage(const void* data, size_t size) = 0; - - /** @brief Set gamma value for all colors. - - Note: Setting this in windowed mode will affect the ENTIRE - SCREEN! - */ - virtual void setGamma(float gamma) = 0; - - /// Set gamma individually for red, green, blue - virtual void setGamma(float red, float green, float blue) = 0; - - /// Get screen width - virtual int width() = 0; - - /// Get screen height - virtual int height() = 0; - }; - } -} -#endif diff --git a/libs/mangle/rend2d/servers/sdl_driver.cpp b/libs/mangle/rend2d/servers/sdl_driver.cpp deleted file mode 100644 index 84a17933ff..0000000000 --- a/libs/mangle/rend2d/servers/sdl_driver.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "sdl_driver.hpp" - -#include -#include -#include -#include - -using namespace Mangle::Rend2D; - -const SpriteData *SDL_Sprite::lock() -{ - // Make sure we aren't already locked - assert(!data.pixels); - - // Lock the surface and set up the data structure - SDL_LockSurface(surface); - - data.pixels = surface->pixels; - data.w = surface->w; - data.h = surface->h; - data.pitch = surface->pitch; - data.bypp = surface->format->BytesPerPixel; - - return &data; -} - -void SDL_Sprite::unlock() -{ - if(data.pixels) - { - SDL_UnlockSurface(surface); - data.pixels = NULL; - } -} - -// This is a really crappy and slow implementation, only intended for -// testing purposes. Use lock/unlock for faster pixel drawing. -void SDL_Sprite::pixel(int x, int y, int color) -{ - SDL_LockSurface(surface); - - int bpp = surface->format->BytesPerPixel; - char *p = (char*)surface->pixels + y*surface->pitch + x*bpp; - - switch(bpp) - { - case 1: *p = color; break; - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - p[0] = (color >> 16) & 0xff; - p[1] = (color >> 8) & 0xff; - p[2] = color & 0xff; - } - else - { - p[0] = color & 0xff; - p[1] = (color >> 8) & 0xff; - p[2] = (color >> 16) & 0xff; - } - break; - case 4: - *(int*)p = color; - break; - } - SDL_UnlockSurface(surface); -} - -void SDL_Sprite::draw(Sprite *s, // Must be SDL_Sprite - int x, int y, // Destination position - int sx, int sy, // Source position - int w, int h // Amount to draw. -1 means remainder. - ) -{ - // Get source surface - SDL_Sprite *other = dynamic_cast(s); - assert(other != NULL); - SDL_Surface *img = other->getSurface(); - - // Check coordinate validity - assert(sx <= img->w && sy <= img->h); - assert(x <= surface->w && y <= surface->h); - assert(sx >= 0 && sy >= 0); - - // Compute width and height if necessary - if(w == -1) w = img->w - sx; - if(h == -1) h = img->h - sy; - - // Check them if they're valid - assert(w >= 0 && w <= img->w); - assert(h >= 0 && h <= img->h); - - SDL_Rect dest; - dest.x = x; - dest.y = y; - dest.w = w; - dest.h = h; - - SDL_Rect src; - src.x = sx; - src.y = sy; - src.w = w; - src.h = h; - - // Do the Blitman - SDL_BlitSurface(img, &src, surface, &dest); -} - -SDL_Sprite::SDL_Sprite(SDL_Surface *s, bool autoDelete) - : surface(s), autoDel(autoDelete) -{ - assert(surface != NULL); - data.pixels = NULL; -} - -SDL_Sprite::~SDL_Sprite() -{ - if(autoDel) - SDL_FreeSurface(surface); -} - -void SDL_Sprite::fill(int value) -{ - SDL_FillRect(surface, NULL, value); -} - -int SDL_Sprite::width() { return surface->w; } -int SDL_Sprite::height() { return surface->h; } - -SDLDriver::SDLDriver() : display(NULL), realDisp(NULL), softDouble(false) -{ - if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1) - throw std::runtime_error("Error initializing SDL video"); -} -SDLDriver::~SDLDriver() -{ - if(display) delete display; - SDL_Quit(); -} - -void SDLDriver::setVideoMode(int width, int height, int bpp, bool fullscreen) -{ - unsigned int flags; - - if(display) delete display; - - if (fullscreen) - // Assume fullscreen mode allows a double-bufferd hardware - // mode. We need more test code for this to be safe though. - flags = SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF; - else - flags = SDL_SWSURFACE; - - // Create the surface and check it - realDisp = SDL_SetVideoMode(width, height, bpp, flags); - if(realDisp == NULL) - throw std::runtime_error("Failed setting SDL video mode"); - - // Code for software double buffering. I haven't found this to be - // any speed advantage at all in windowed mode (it's slower, as one - // would expect.) Not properly tested in fullscreen mode with - // hardware buffers, but it will probably only be an improvement if - // we do excessive writing (ie. write each pixel on average more - // than once) or try to read from the display buffer. - if(softDouble) - { - // Make a new surface with the same attributes as the real - // display surface. - SDL_Surface *back = SDL_DisplayFormat(realDisp); - assert(back != NULL); - - // Create a sprite representing the double buffer - display = new SDL_Sprite(back); - } - else - { - // Create a sprite directly representing the display surface. - // The 'false' parameter means do not autodelete the screen - // surface upon exit (since SDL manages it) - display = new SDL_Sprite(realDisp, false); - } -} - -/// Update the screen -void SDLDriver::update() -{ - // Blit the soft double buffer onto the real display buffer - if(softDouble) - SDL_BlitSurface(display->getSurface(), NULL, realDisp, NULL ); - - if(realDisp) - SDL_Flip(realDisp); -} - -/// Set the window title, as well as the title of the window when -/// "iconified" -void SDLDriver::setWindowTitle(const std::string &title, - const std::string &icon) -{ - SDL_WM_SetCaption( title.c_str(), icon.c_str() ); -} - -// Convert the given surface to display format. -static SDL_Surface* convertImage(SDL_Surface* surf) -{ - if(surf != NULL) - { - // Convert the image to the display buffer format, for faster - // blitting - SDL_Surface *surf2 = SDL_DisplayFormat(surf); - SDL_FreeSurface(surf); - surf = surf2; - } - return surf; -} - -/// Load sprite from an image file, using SDL_image. -Sprite* SDLDriver::loadImage(const std::string &file) -{ - SDL_Surface *surf = IMG_Load(file.c_str()); - surf = convertImage(surf); - if(surf == NULL) - throw std::runtime_error("SDL failed to load image file '" + file + "'"); - return spriteFromSDL(surf); -} - -/// Load sprite from an SDL_RWops structure. autoFree determines -/// whether the RWops struct should be closed/freed after use. -Sprite* SDLDriver::loadImage(SDL_RWops *src, bool autoFree) -{ - SDL_Surface *surf = IMG_Load_RW(src, autoFree); - surf = convertImage(surf); - if(surf == NULL) - throw std::runtime_error("SDL failed to load image"); - return spriteFromSDL(surf); -} - -/// Load a sprite from an image file stored in memory. Uses -/// SDL_image. -Sprite* SDLDriver::loadImage(const void* data, size_t size) -{ - SDL_RWops *rw = SDL_RWFromConstMem(data, size); - return loadImage(rw, true); -} - -void SDLDriver::setGamma(float red, float green, float blue) -{ - SDL_SetGamma(red,green,blue); -} - -/// Convert an existing SDL surface into a sprite -Sprite* SDLDriver::spriteFromSDL(SDL_Surface *surf, bool autoFree) -{ - assert(surf); - return new SDL_Sprite(surf, autoFree); -} - -void SDLDriver::sleep(int ms) { SDL_Delay(ms); } -unsigned int SDLDriver::ticks() { return SDL_GetTicks(); } diff --git a/libs/mangle/rend2d/servers/sdl_driver.hpp b/libs/mangle/rend2d/servers/sdl_driver.hpp deleted file mode 100644 index 0f205ba34c..0000000000 --- a/libs/mangle/rend2d/servers/sdl_driver.hpp +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef MANGLE_DRAW2D_SDL_H -#define MANGLE_DRAW2D_SDL_H - -#include "../driver.hpp" - -// Predeclarations keep the streets safe at night -struct SDL_Surface; -struct SDL_RWops; - -namespace Mangle -{ - namespace Rend2D - { - /// SDL-implementation of Sprite - struct SDL_Sprite : Sprite - { - /** Draw a sprite in the given position. Can only draw other SDL - sprites. - */ - void draw(Sprite *s, // Must be SDL_Sprite - int x, int y, // Destination position - int sx=0, int sy=0, // Source position - int w=-1, int h=-1 // Amount to draw. -1 means remainder. - ); - - SDL_Sprite(SDL_Surface *s, bool autoDelete=true); - ~SDL_Sprite(); - - // Information retrieval - int width(); - int height(); - SDL_Surface *getSurface() { return surface; } - - // Fill with a given pixel value - void fill(int value); - - // Set one pixel - void pixel(int x, int y, int value); - - const SpriteData *lock(); - void unlock(); - - private: - // The SDL surface - SDL_Surface* surface; - - // Used for locking - SpriteData data; - - // If true, delete this surface when the canvas is destructed - bool autoDel; - }; - - class SDLDriver : public Driver - { - // The main display surface - SDL_Sprite *display; - - // The actual display surface. May or may not be the same - // surface pointed to by 'display' above, depending on the - // softDouble flag. - SDL_Surface *realDisp; - - // If true, we do software double buffering. - bool softDouble; - - public: - SDLDriver(); - ~SDLDriver(); - - /// Sets the video mode. Will create the window if it is not - /// already set up. Note that for SDL, bpp=0 means use current - /// bpp. - void setVideoMode(int width, int height, int bpp=0, bool fullscreen=false); - - /// Update the screen - void update(); - - /// Set the window title, as well as the title of the window - /// when "iconified" - void setWindowTitle(const std::string &title, - const std::string &icon); - - // Include overloads from our Glorious parent - using Driver::setWindowTitle; - - /// Load sprite from an image file, using SDL_image. - Sprite* loadImage(const std::string &file); - - /// Load sprite from an SDL_RWops structure. autoFree determines - /// whether the RWops struct should be closed/freed after use. - Sprite* loadImage(SDL_RWops *src, bool autoFree=false); - - /// Load a sprite from an image file stored in memory. Uses - /// SDL_image. - Sprite* loadImage(const void* data, size_t size); - - /// Set gamma value - void setGamma(float gamma) { setGamma(gamma,gamma,gamma); } - - /// Set gamma individually for red, green, blue - void setGamma(float red, float green, float blue); - - /// Convert an existing SDL surface into a sprite - Sprite* spriteFromSDL(SDL_Surface *surf, bool autoFree = true); - - // Get width and height - int width() { return display ? display->width() : 0; } - int height() { return display ? display->height() : 0; } - - /// Get the screen sprite - Sprite *getScreen() { return display; } - - /// Not really a graphic-related function, but very - /// handly. Sleeps the given number of milliseconds using - /// SDL_Delay(). - void sleep(int ms); - - /// Get the number of ticks since SDL initialization, using - /// SDL_GetTicks(). - unsigned int ticks(); - }; - } -} -#endif diff --git a/libs/mangle/rend2d/servers/sdl_gl_driver.cpp b/libs/mangle/rend2d/servers/sdl_gl_driver.cpp deleted file mode 100644 index db519e0911..0000000000 --- a/libs/mangle/rend2d/servers/sdl_gl_driver.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include "sdl_gl_driver.hpp" - -#include -#include -#include -#include -#include - -using namespace Mangle::Rend2D; - -void SDLGL_Sprite::draw(Sprite *s, // Must be SDLGL_Sprite - int x, int y, // Destination position - int sx, int sy, // Source position - int w, int h // Amount to draw. -1 means remainder. - ) -{ - // Get source surface - SDLGL_Sprite *other = dynamic_cast(s); - assert(other != NULL); - SDL_Surface *img = other->getSurface(); - - // Check coordinate validity - assert(sx <= img->w && sy <= img->h); - assert(x <= surface->w && y <= surface->h); - assert(sx >= 0 && sy >= 0); - - // Compute width and height if necessary - if(w == -1) w = img->w - sx; - if(h == -1) h = img->h - sy; - - // Check them if they're valid - assert(w >= 0 && w <= img->w); - assert(h >= 0 && h <= img->h); - - SDL_Rect dest; - dest.x = x; - dest.y = y; - dest.w = w; - dest.h = h; - - SDL_Rect src; - src.x = sx; - src.y = sy; - src.w = w; - src.h = h; - - // Do the Blitman - SDL_BlitSurface(img, &src, surface, &dest); -} - -SDLGL_Sprite::SDLGL_Sprite(SDL_Surface *s, bool autoDelete) - : surface(s), autoDel(autoDelete) -{ - assert(surface != NULL); -} - -SDLGL_Sprite::~SDLGL_Sprite() -{ - if(autoDel) - SDL_FreeSurface(surface); -} - -void SDLGL_Sprite::fill(int value) -{ - SDL_FillRect(surface, NULL, value); -} - -int SDLGL_Sprite::width() { return surface->w; } -int SDLGL_Sprite::height() { return surface->h; } - -SDLGLDriver::SDLGLDriver() : display(NULL), realDisp(NULL) -{ - if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1) - throw std::runtime_error("Error initializing SDL video"); -} -SDLGLDriver::~SDLGLDriver() -{ - if(display) delete display; - SDL_Quit(); -} - -// Surface used for the screen. Since OpenGL surfaces must have sizes -// that are powers of 2, we have to "fake" the returned display size -// to match the screen, not the surface itself. If we don't use this, -// the client program will get confused about the actual size of our -// screen, thinking it is bigger than it is. -struct FakeSizeSprite : SDLGL_Sprite -{ - int fakeW, fakeH; - - FakeSizeSprite(SDL_Surface *s, int fw, int fh) - : SDLGL_Sprite(s), fakeW(fw), fakeH(fh) - {} - - int width() { return fakeW; } - int height() { return fakeH; } -}; - -static int makePow2(int num) -{ - assert(num); - if((num & (num-1)) != 0) - { - int cnt = 0; - while(num) - { - num >>= 1; - cnt++; - } - num = 1 << cnt; - } - return num; -} - -void SDLGLDriver::setVideoMode(int width, int height, int bpp, bool fullscreen) -{ - unsigned int flags; - - if(display) delete display; - - flags = SDL_OPENGL; - - if (fullscreen) - flags |= SDL_FULLSCREEN; - - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); - SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1 ); - - // Create the surface and check it - screen = SDL_SetVideoMode(width, height, bpp, flags); - if(screen == NULL) - throw std::runtime_error("Failed setting SDL video mode"); - - // Expand width and height to be powers of 2 - int width2 = makePow2(width); - int height2 = makePow2(height); - - // Create a new SDL surface of this size - const SDL_PixelFormat& fmt = *(screen->format); - realDisp = SDL_CreateRGBSurface(SDL_SWSURFACE,width2,height2, - fmt.BitsPerPixel, - fmt.Rmask,fmt.Gmask,fmt.Bmask,fmt.Amask); - - // Create a sprite directly representing the display surface. This - // allows the user to blit to it directly. - display = new FakeSizeSprite(realDisp, width, height); - - // Set up the OpenGL format - nOfColors = fmt.BytesPerPixel; - - if(nOfColors == 4) - { - if (fmt.Rmask == 0x000000ff) - texture_format = GL_RGBA; - else - texture_format = GL_BGRA; - } - else if(nOfColors == 3) - { - if (fmt.Rmask == 0x000000ff) - texture_format = GL_RGB; - else - texture_format = GL_BGR; - } - else - assert(0 && "unsupported screen format"); - - glEnable(GL_TEXTURE_2D); - - // Have OpenGL generate a texture object handle for us - glGenTextures( 1, &texture ); - - // Bind the texture object - glBindTexture( GL_TEXTURE_2D, texture ); - - // Set the texture's stretching properties - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); -} - -void SDLGLDriver::updateNoSwap() -{ - if(!realDisp) return; - - // Fist, set up the screen texture: - - // Bind the texture object - glBindTexture( GL_TEXTURE_2D, texture ); - - // Edit the texture object's image data - glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, realDisp->w, realDisp->h, 0, - texture_format, GL_UNSIGNED_BYTE, realDisp->pixels ); - - glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); - - // OpenGL barf. Set up the projection to match our screen - int vPort[4]; - glGetIntegerv(GL_VIEWPORT, vPort); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, vPort[2], 0, vPort[3], -1, 1); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glBegin( GL_QUADS ); - - // Needed to move the screen into the right place - int diff = screen->h - realDisp->h; - - // Bottom-left vertex (corner) - glTexCoord2i( 0, 1 ); - glVertex3f(0,diff,0); - - // Bottom-right vertex (corner) - glTexCoord2i( 1, 1 ); - glVertex3f( realDisp->w, diff, 0.f ); - - // Top-right vertex (corner) - glTexCoord2i( 1, 0 ); - glVertex3f( realDisp->w, screen->h, 0.f ); - - // Top-left vertex (corner) - glTexCoord2i( 0, 0 ); - glVertex3f( 0, screen->h, 0.f ); - glEnd(); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - -void SDLGLDriver::swap() -{ - SDL_GL_SwapBuffers(); -} - -void SDLGLDriver::update() -{ - updateNoSwap(); - swap(); -} - -/// Set the window title, as well as the title of the window when -/// "iconified" -void SDLGLDriver::setWindowTitle(const std::string &title, - const std::string &icon) -{ - SDL_WM_SetCaption( title.c_str(), icon.c_str() ); -} - -// Convert the given surface to display format. -static SDL_Surface* convertImage(SDL_Surface* surf) -{ - if(surf != NULL) - { - // Convert the image to the display buffer format, for faster - // blitting - SDL_Surface *surf2 = SDL_DisplayFormat(surf); - SDL_FreeSurface(surf); - surf = surf2; - } - return surf; -} - -/// Load sprite from an image file, using SDL_image. -Sprite* SDLGLDriver::loadImage(const std::string &file) -{ - SDL_Surface *surf = IMG_Load(file.c_str()); - surf = convertImage(surf); - if(surf == NULL) - throw std::runtime_error("SDL failed to load image file '" + file + "'"); - return spriteFromSDL(surf); -} - -/// Load sprite from an SDL_RWops structure. autoFree determines -/// whether the RWops struct should be closed/freed after use. -Sprite* SDLGLDriver::loadImage(SDL_RWops *src, bool autoFree) -{ - SDL_Surface *surf = IMG_Load_RW(src, autoFree); - surf = convertImage(surf); - if(surf == NULL) - throw std::runtime_error("SDL failed to load image"); - return spriteFromSDL(surf); -} - -/// Load a sprite from an image file stored in memory. Uses -/// SDL_image. -Sprite* SDLGLDriver::loadImage(const void* data, size_t size) -{ - SDL_RWops *rw = SDL_RWFromConstMem(data, size); - return loadImage(rw, true); -} - -void SDLGLDriver::setGamma(float red, float green, float blue) -{ - SDL_SetGamma(red,green,blue); -} - -/// Convert an existing SDL surface into a sprite -Sprite* SDLGLDriver::spriteFromSDL(SDL_Surface *surf, bool autoFree) -{ - assert(surf); - return new SDLGL_Sprite(surf, autoFree); -} - -void SDLGLDriver::sleep(int ms) { SDL_Delay(ms); } -unsigned int SDLGLDriver::ticks() { return SDL_GetTicks(); } diff --git a/libs/mangle/rend2d/servers/sdl_gl_driver.hpp b/libs/mangle/rend2d/servers/sdl_gl_driver.hpp deleted file mode 100644 index d116e3659b..0000000000 --- a/libs/mangle/rend2d/servers/sdl_gl_driver.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef MANGLE_DRAW2D_SDLGL_H -#define MANGLE_DRAW2D_SDLGL_H - -/** This driver is similar to SDLDriver, except that it uses SDL on - top of OpenGL. - - I've decided to make it a separate file instead of just adding - optional OpenGL support to the original, so that pure SDL users - don't have to add OpenGL as a dependency. - */ - -#include "../driver.hpp" - -// Predeclarations keep the streets safe at night -struct SDL_Surface; -struct SDL_RWops; - -namespace Mangle -{ - namespace Rend2D - { - /// SDL-implementation of Sprite - struct SDLGL_Sprite : Sprite - { - /** Draw a sprite in the given position. Can only draw other SDL - sprites. - */ - void draw(Sprite *s, // Must be SDLGL_Sprite - int x, int y, // Destination position - int sx=0, int sy=0, // Source position - int w=-1, int h=-1 // Amount to draw. -1 means remainder. - ); - - SDLGL_Sprite(SDL_Surface *s, bool autoDelete=true); - ~SDLGL_Sprite(); - - // Information retrieval - virtual int width(); - virtual int height(); - SDL_Surface *getSurface() { return surface; } - - // Fill with a given pixel value - void fill(int value); - - private: - // The SDL surface - SDL_Surface* surface; - - // If true, delete this surface when the canvas is destructed - bool autoDel; - }; - - class SDLGLDriver : public Driver - { - // The main display surface - SDLGL_Sprite *display; - - // The screen surface. This is completely unused. - SDL_Surface *screen; - - // The display surface and main GL texture. These are used when - // drawing the entire screen as one surface, as a drop-in - // replacement for SDLDriver. - SDL_Surface *realDisp; - unsigned int texture; - int nOfColors, texture_format; - - public: - SDLGLDriver(); - ~SDLGLDriver(); - - /// Sets the video mode. Will create the window if it is not - /// already set up. Note that for SDL, bpp=0 means use current - /// bpp. - void setVideoMode(int width, int height, int bpp=0, bool fullscreen=false); - - /// Update the screen - void update(); - - /// Calls SDL_GL_SwapBuffers - void swap(); - - /// Draw surface to screen but do not call SDL_GL_SwapBuffers() - void updateNoSwap(); - - /// Set the window title, as well as the title of the window - /// when "iconified" - void setWindowTitle(const std::string &title, - const std::string &icon); - - // Include overloads from our Glorious parent - using Driver::setWindowTitle; - - /// Load sprite from an image file, using SDL_image. - Sprite* loadImage(const std::string &file); - - /// Load sprite from an SDL_RWops structure. autoFree determines - /// whether the RWops struct should be closed/freed after use. - Sprite* loadImage(SDL_RWops *src, bool autoFree=false); - - /// Load a sprite from an image file stored in memory. Uses - /// SDL_image. - Sprite* loadImage(const void* data, size_t size); - - /// Set gamma value - void setGamma(float gamma) { setGamma(gamma,gamma,gamma); } - - /// Set gamma individually for red, green, blue - void setGamma(float red, float green, float blue); - - /// Convert an existing SDL surface into a sprite - Sprite* spriteFromSDL(SDL_Surface *surf, bool autoFree = true); - - // Get width and height - int width() { return display ? display->width() : 0; } - int height() { return display ? display->height() : 0; } - - /// Get the screen sprite - Sprite *getScreen() { return display; } - - /// Not really a graphic-related function, but very - /// handly. Sleeps the given number of milliseconds using - /// SDL_Delay(). - void sleep(int ms); - - /// Get the number of ticks since SDL initialization, using - /// SDL_GetTicks(). - unsigned int ticks(); - }; - } -} -#endif diff --git a/libs/mangle/rend2d/sprite.hpp b/libs/mangle/rend2d/sprite.hpp deleted file mode 100644 index f49da6cb6d..0000000000 --- a/libs/mangle/rend2d/sprite.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef MANGLE_REND2D_SPRITE_H -#define MANGLE_REND2D_SPRITE_H - -namespace Mangle -{ - namespace Rend2D - { - /** - A pointer to sprite data for direct drawing. Only to be used - while the corresponding sprite is locked. - */ - struct SpriteData - { - void *pixels; // Pixel data - int w, h; // Width and height - int pitch, bypp; // Pitch (bytes) and bytes per pixel - }; - - /** - A Sprite is either a bitmap to be drawn or an output of area - for blitting other bitmaps, or both. They are created by the - Driver. - */ - struct Sprite - { - /// Draw a sprite in the given position - virtual void draw(Sprite *s, // The sprite to draw - int x, int y, // Destination position - int sx=0, int sy=0, // Source position - int w=-1, int h=-1 // Amount to draw. -1 means remainder. - ) = 0; - - virtual ~Sprite() {} - - // Information retrieval - virtual int width() = 0; - virtual int height() = 0; - - /// Fill the sprite with the given pixel value. The pixel format - /// depends on the format of the sprite. - virtual void fill(int value) = 0; - - /// Set one pixel value. The pixel format depends on the sprite - /// format. This is not expected to be fast, and in some - /// implementations may not work at all. - virtual void pixel(int x, int y, int value) {} - - /// Lock sprite for direct drawing, and return a struct - /// containing the necessary pointer. When finished, unlock the - /// sprite with unlock(). May return NULL, if so then direct - /// drawing is not possible. - virtual const SpriteData *lock() { return NULL; } - virtual void unlock() {} - }; - } -} -#endif diff --git a/libs/mangle/rend2d/tests/.gitignore b/libs/mangle/rend2d/tests/.gitignore deleted file mode 100644 index 8144904045..0000000000 --- a/libs/mangle/rend2d/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*_test diff --git a/libs/mangle/rend2d/tests/Makefile b/libs/mangle/rend2d/tests/Makefile deleted file mode 100644 index d430f60a93..0000000000 --- a/libs/mangle/rend2d/tests/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -GCC=g++ -Wall -Werror - -all: sdl_test sdl_move_test sdlgl_move_test - -sdl_test: sdl_test.cpp - $(GCC) $< ../servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image - -sdl_move_test: sdl_move_test.cpp ../servers/sdl_driver.cpp - $(GCC) $^ -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image - -sdlgl_move_test: sdlgl_move_test.cpp ../servers/sdl_gl_driver.cpp - $(GCC) $^ -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image -lGL - -clean: - rm *_test diff --git a/libs/mangle/rend2d/tests/output/sdl_move_test.out b/libs/mangle/rend2d/tests/output/sdl_move_test.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/mangle/rend2d/tests/output/sdl_test.out b/libs/mangle/rend2d/tests/output/sdl_test.out deleted file mode 100644 index 4528e1a98a..0000000000 --- a/libs/mangle/rend2d/tests/output/sdl_test.out +++ /dev/null @@ -1,11 +0,0 @@ -Loading SDL driver. -Creating window. -Current mode: 640x480 -Setting fancy title, cause we like fancy titles. -Loading tile1-blue.png from file. -Loading tile1-yellow.png from memory. -Going bananas. -Taking a breather. -WOW DID YOU SEE THAT!? -Mucking about with the gamma settings -Done. diff --git a/libs/mangle/rend2d/tests/output/sdlgl_move_test.out b/libs/mangle/rend2d/tests/output/sdlgl_move_test.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/mangle/rend2d/tests/sdl_move_test.cpp b/libs/mangle/rend2d/tests/sdl_move_test.cpp deleted file mode 100644 index bfbca98fa7..0000000000 --- a/libs/mangle/rend2d/tests/sdl_move_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -using namespace std; - -#include "../servers/sdl_driver.hpp" - -using namespace Mangle::Rend2D; - -int main() -{ - SDLDriver sdl; - - sdl.setVideoMode(640,480,0,false); - sdl.setWindowTitle("Testing 123"); - Sprite *screen = sdl.getScreen(); - const char* imgName = "tile1-blue.png"; - Sprite *image = sdl.loadImage(imgName); - - for(int frames=0; frames<170; frames++) - { - screen->fill(0); - for(int j=0; j<10; j++) - for(int i=0; i<25; i++) - screen->draw(image, 2*frames+30*j, 20*i); - sdl.update(); - sdl.sleep(10); - } - return 0; -} diff --git a/libs/mangle/rend2d/tests/sdl_test.cpp b/libs/mangle/rend2d/tests/sdl_test.cpp deleted file mode 100644 index 0355112e61..0000000000 --- a/libs/mangle/rend2d/tests/sdl_test.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -using namespace std; - -#include "../servers/sdl_driver.hpp" - -using namespace Mangle::Rend2D; - -int main() -{ - cout << "Loading SDL driver.\n"; - SDLDriver sdl; - - cout << "Creating window.\n"; - sdl.setVideoMode(640,480); - cout << "Current mode: " << sdl.width() << "x" << sdl.height() << endl; - - cout << "Setting fancy title, cause we like fancy titles.\n"; - sdl.setWindowTitle("Chief executive window"); - - // Display surface - Sprite *screen = sdl.getScreen(); - - const char* imgName = "tile1-blue.png"; - cout << "Loading " << imgName << " from file.\n"; - Sprite *image = sdl.loadImage(imgName); - - const char* imgName2 = "tile1-yellow.png"; - cout << "Loading " << imgName2 << " from memory.\n"; - Sprite *image2; - { - // This is hard-coded for file sizes below 500 bytes, so obviously - // you shouldn't mess with the image files. - ifstream file(imgName2, ios::binary); - char buf[500]; - file.read(buf, 500); - int size = file.gcount(); - image2 = sdl.loadImage(buf, size); - } - - cout << "Going bananas.\n"; - for(int i=1; i<20; i++) - screen->draw(image, 30*i, 20*i); - - cout << "Taking a breather.\n"; - sdl.update(); - for(int i=1; i<20; i++) - screen->draw(image2, 30*(20-i), 20*i); - sdl.sleep(800); - sdl.update(); - cout << "WOW DID YOU SEE THAT!?\n"; - sdl.sleep(800); - - cout << "Mucking about with the gamma settings\n"; - sdl.setGamma(2.0, 0.1, 0.8); - sdl.sleep(100); - sdl.setGamma(0.6, 2.1, 2.1); - sdl.sleep(100); - sdl.setGamma(1.6); - sdl.sleep(100); - - cout << "Done.\n"; - return 0; -} diff --git a/libs/mangle/rend2d/tests/sdlgl_move_test.cpp b/libs/mangle/rend2d/tests/sdlgl_move_test.cpp deleted file mode 100644 index b769ee837d..0000000000 --- a/libs/mangle/rend2d/tests/sdlgl_move_test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -using namespace std; - -#include "../servers/sdl_gl_driver.hpp" - -using namespace Mangle::Rend2D; - -int main() -{ - SDLGLDriver sdl; - - sdl.setVideoMode(640,480,0,false); - sdl.setWindowTitle("Testing 123"); - Sprite *screen = sdl.getScreen(); - const char* imgName = "tile1-blue.png"; - Sprite *image = sdl.loadImage(imgName); - - for(int frames=0; frames<170; frames++) - { - screen->fill(0); - for(int j=0; j<10; j++) - for(int i=0; i<25; i++) - screen->draw(image, 2*frames+30*j, 20*i); - sdl.update(); - sdl.sleep(5); - } - - return 0; -} diff --git a/libs/mangle/rend2d/tests/test.sh b/libs/mangle/rend2d/tests/test.sh deleted file mode 100755 index 2d07708adc..0000000000 --- a/libs/mangle/rend2d/tests/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -make || exit - -mkdir -p output - -PROGS=*_test - -for a in $PROGS; do - if [ -f "output/$a.out" ]; then - echo "Running $a:" - ./$a | diff output/$a.out - - else - echo "Creating $a.out" - ./$a > "output/$a.out" - git add "output/$a.out" - fi -done diff --git a/libs/mangle/rend2d/tests/tile1-blue.png b/libs/mangle/rend2d/tests/tile1-blue.png deleted file mode 100644 index 066e6f8eb9..0000000000 Binary files a/libs/mangle/rend2d/tests/tile1-blue.png and /dev/null differ diff --git a/libs/mangle/rend2d/tests/tile1-yellow.png b/libs/mangle/rend2d/tests/tile1-yellow.png deleted file mode 100644 index 2aaf9015d3..0000000000 Binary files a/libs/mangle/rend2d/tests/tile1-yellow.png and /dev/null differ diff --git a/libs/mangle/testall.sh b/libs/mangle/testall.sh deleted file mode 100755 index b93fee2159..0000000000 --- a/libs/mangle/testall.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -function run() -{ - echo "TESTING $1" - cd "$1/tests/" - ./test.sh - cd ../../ -} - -run stream -run vfs -run sound -run input -run rend2d -run . diff --git a/libs/mangle/tests/.gitignore b/libs/mangle/tests/.gitignore deleted file mode 100644 index 8144904045..0000000000 --- a/libs/mangle/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*_test diff --git a/libs/mangle/tests/Makefile b/libs/mangle/tests/Makefile deleted file mode 100644 index d912c0784b..0000000000 --- a/libs/mangle/tests/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -GCC=g++ -I../ - -all: ogrevfs_audiere_openal_test - -I_OGRE=$(shell pkg-config --cflags OGRE) -L_OGRE=$(shell pkg-config --libs OGRE) -L_OPENAL=$(shell pkg-config --libs openal) -L_AUDIERE=-laudiere - -ogrevfs_audiere_openal_test: ogrevfs_audiere_openal_test.cpp ../vfs/servers/ogre_vfs.cpp ../sound/sources/audiere_source.cpp ../sound/outputs/openal_out.cpp ../stream/clients/audiere_file.cpp - $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) $(L_OPENAL) $(L_AUDIERE) - -clean: - rm *_test diff --git a/libs/mangle/tests/ogrevfs_audiere_openal_test.cpp b/libs/mangle/tests/ogrevfs_audiere_openal_test.cpp deleted file mode 100644 index 4936538c55..0000000000 --- a/libs/mangle/tests/ogrevfs_audiere_openal_test.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - This example combines: - - - the OGRE VFS system (to read from zip) - - Audiere (for decoding sound data) - - OpenAL (for sound playback) - - */ - -#include "sound/filters/openal_audiere.hpp" -#include "vfs/servers/ogre_vfs.hpp" -#include -#include - -using namespace Ogre; -using namespace Mangle; -using namespace std; - -int main() -{ - // Disable Ogre logging - new LogManager; - Log *log = LogManager::getSingleton().createLog(""); - log->setDebugOutputEnabled(false); - - // Set up Root - Root *root = new Root("","",""); - - // Add zip file with a sound in it - root->addResourceLocation("sound.zip", "Zip", "General"); - - // Ogre file system - VFS::OgreVFS vfs; - - // The main sound system - Sound::OpenAL_Audiere_Factory mg; - Sound::SoundPtr snd = mg.load(vfs.open("owl.ogg")); - - cout << "Playing 'owl.ogg' from 'sound.zip'\n"; - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - - return 0; -} diff --git a/libs/mangle/tests/output/ogrevfs_audiere_openal_test.out b/libs/mangle/tests/output/ogrevfs_audiere_openal_test.out deleted file mode 100644 index 28ea8a71b7..0000000000 --- a/libs/mangle/tests/output/ogrevfs_audiere_openal_test.out +++ /dev/null @@ -1 +0,0 @@ -Playing 'owl.ogg' from 'sound.zip' diff --git a/libs/mangle/tests/sound.zip b/libs/mangle/tests/sound.zip deleted file mode 100644 index fd32b35299..0000000000 Binary files a/libs/mangle/tests/sound.zip and /dev/null differ diff --git a/libs/mangle/tests/test.sh b/libs/mangle/tests/test.sh deleted file mode 100755 index 2d07708adc..0000000000 --- a/libs/mangle/tests/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -make || exit - -mkdir -p output - -PROGS=*_test - -for a in $PROGS; do - if [ -f "output/$a.out" ]; then - echo "Running $a:" - ./$a | diff output/$a.out - - else - echo "Creating $a.out" - ./$a > "output/$a.out" - git add "output/$a.out" - fi -done diff --git a/libs/mangle/tools/shared_ptr.hpp b/libs/mangle/tools/shared_ptr.hpp deleted file mode 100644 index 3d073fc24f..0000000000 --- a/libs/mangle/tools/shared_ptr.hpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file should include whatever it needs to define the boost/tr1 -// shared_ptr<> and weak_ptr<> templates. -#include diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h index aa10a6bff5..aef028ba4b 100644 --- a/libs/openengine/bullet/pmove.h +++ b/libs/openengine/bullet/pmove.h @@ -55,7 +55,7 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); #define CONTENTS_FOG 64 static const float pm_accelerate = 10.0f; static const float pm_stopspeed = 100.0f; -static const float pm_friction = 6.0f; +static const float pm_friction = 12.0f; static const float pm_flightfriction = 3.0f; static const float pm_waterfriction = 1.0f; static const float pm_airaccelerate = 1.0f; diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 2329ed652c..57b729db10 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -102,8 +102,8 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& - const btVector3 btstart(start.x, start.y, start.z); - const btVector3 btend(end.x, end.y, end.z); + const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); + const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); diff --git a/libs/openengine/gui/events.cpp b/libs/openengine/gui/events.cpp deleted file mode 100644 index 35b01158bc..0000000000 --- a/libs/openengine/gui/events.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include - -#include "events.hpp" - -using namespace OIS; -using namespace OEngine::GUI; - -EventInjector::EventInjector(MyGUI::Gui *g) - : gui(g), enabled(true) - , mMouseX(0) - , mMouseY(0) -{ - assert(gui); - const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); - mMouseX = viewSize.width/2; - mMouseY = viewSize.height/2; -} - -void EventInjector::event(Type type, int index, const void *p) -{ - if(!enabled) return; - - if(type & EV_Keyboard) - { - KeyEvent *key = (KeyEvent*)p; - MyGUI::KeyCode code = MyGUI::KeyCode::Enum(key->key); - if(type == EV_KeyDown) - { - /* - This is just a first approximation. Apparently, OIS is - unable to provide reliable unicode characters on all - platforms. At least that's what I surmise from the amount - of workaround that the MyGUI folks have put in place for - this. See Common/Input/OIS/InputManager.cpp in the MyGUI - sources for details. - - If the work they have done there is indeed necessary (I - haven't tested that it is, although I have had dubious - experinces with OIS events in the past), then we should - probably adapt all that code here. Or even better, - directly into the OIS input manager in Mangle. - - Note that all this only affects the 'text' field, and - should thus only affect typed text in input boxes (which - is still pretty significant.) - */ - MyGUI::Char text = (MyGUI::Char)key->text; - MyGUI::InputManager::getInstance().injectKeyPress(code,text); - } - else - { - MyGUI::InputManager::getInstance().injectKeyRelease(code); - } - } - else if(type & EV_Mouse) - { - MouseEvent *mouse = (MouseEvent*)p; - MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); - - const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); - - // Update mouse position - mMouseX += mouse->state.X.rel; - mMouseY += mouse->state.Y.rel; - mMouseX = std::max(0, std::min(mMouseX, viewSize.width)); - mMouseY = std::max(0, std::min(mMouseY, viewSize.height)); - - if(type == EV_MouseDown) - MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, id); - else if(type == EV_MouseUp) - MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, id); - else - MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mouse->state.Z.abs); - } -} diff --git a/libs/openengine/gui/events.hpp b/libs/openengine/gui/events.hpp deleted file mode 100644 index 10c5309bc3..0000000000 --- a/libs/openengine/gui/events.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef OENGINE_MYGUI_EVENTS_H -#define OENGINE_MYGUI_EVENTS_H - -#include - -namespace MyGUI -{ - class Gui; -} - -namespace OEngine { -namespace GUI -{ - /** Event handler that injects OIS events into MyGUI - */ - class EventInjector : public Mangle::Input::Event - { - MyGUI::Gui *gui; - - int mMouseX; - int mMouseY; - - public: - bool enabled; - - EventInjector(MyGUI::Gui *g); - void event(Type type, int index, const void *p); - }; - - typedef boost::shared_ptr EventInjectorPtr; -}} -#endif diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 9c6ca37eb1..58929ba8b5 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -36,6 +36,7 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool void MyGUIManager::shutdown() { + mGui->shutdown (); delete mGui; if(mPlatform) { diff --git a/libs/openengine/ogre/exitlistener.hpp b/libs/openengine/ogre/exitlistener.hpp deleted file mode 100644 index 5a9d1ff68f..0000000000 --- a/libs/openengine/ogre/exitlistener.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef OENGINE_OGRE_EXITLISTEN_H -#define OENGINE_OGRE_EXITLISTEN_H - -/* - This FrameListener simply exits the rendering loop when the window - is closed. You can also tell it to exit manually by setting the exit - member to true; - */ - -#include -#include - -namespace OEngine { -namespace Render -{ - struct ExitListener : Ogre::FrameListener - { - Ogre::RenderWindow *window; - bool exit; - - ExitListener(Ogre::RenderWindow *wnd) - : window(wnd), exit(false) {} - - bool frameStarted(const Ogre::FrameEvent &evt) - { - if(window->isClosed()) - exit = true; - - return !exit; - } - - // Function equivalent of setting exit=true. Handy when you need a - // delegate to bind to an event. - void exitNow() { exit = true; } - }; -}} -#endif diff --git a/libs/openengine/ogre/fader.hpp b/libs/openengine/ogre/fader.hpp index f76ac51ef9..efb12a5d2d 100644 --- a/libs/openengine/ogre/fader.hpp +++ b/libs/openengine/ogre/fader.hpp @@ -9,8 +9,6 @@ inspired by http://www.ogre3d.org/tikiwiki/FadeEffectOverlay (heavily adjusted) */ -#include - namespace Ogre { class TextureUnitState; diff --git a/libs/openengine/ogre/mouselook.cpp b/libs/openengine/ogre/mouselook.cpp deleted file mode 100644 index 841bab603a..0000000000 --- a/libs/openengine/ogre/mouselook.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "mouselook.hpp" - -#include -#include -#include - -using namespace OIS; -using namespace Ogre; -using namespace OEngine::Render; - -void MouseLookEvent::event(Type type, int index, const void *p) -{ - if(type != EV_MouseMove || camera == NULL) return; - - MouseEvent *arg = (MouseEvent*)(p); - - float x = arg->state.X.rel * sensX; - float y = arg->state.Y.rel * sensY; - - camera->getParentSceneNode()->getParentSceneNode()->yaw(Degree(-x)); - camera->getParentSceneNode()->pitch(Degree(-y)); - if(flipProt) - { - // The camera before pitching - /*Quaternion nopitch = camera->getParentSceneNode()->getOrientation(); - - camera->getParentSceneNode()->pitch(Degree(-y)); - - // Apply some failsafe measures against the camera flipping - // upside down. Is the camera close to pointing straight up or - // down? - if(Ogre::Vector3(camera->getParentSceneNode()->getOrientation()*Ogre::Vector3::UNIT_Y)[1] <= 0.1) - // If so, undo the last pitch - camera->getParentSceneNode()->setOrientation(nopitch);*/ - //camera->getU - - // Angle of rotation around the X-axis. - float pitchAngle = (2 * Ogre::Degree(Ogre::Math::ACos(camera->getParentSceneNode()->getOrientation().w)).valueDegrees()); - - // Just to determine the sign of the angle we pick up above, the - // value itself does not interest us. - float pitchAngleSign = camera->getParentSceneNode()->getOrientation().x; - - // Limit the pitch between -90 degress and +90 degrees, Quake3-style. - if (pitchAngle > 90.0f) - { - if (pitchAngleSign > 0) - // Set orientation to 90 degrees on X-axis. - camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), - Ogre::Math::Sqrt(0.5f), 0, 0)); - else if (pitchAngleSign < 0) - // Sets orientation to -90 degrees on X-axis. - camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f), - -Ogre::Math::Sqrt(0.5f), 0, 0)); - } - } -} diff --git a/libs/openengine/ogre/mouselook.hpp b/libs/openengine/ogre/mouselook.hpp deleted file mode 100644 index 6e09ff4a10..0000000000 --- a/libs/openengine/ogre/mouselook.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef OENGINE_OGRE_MOUSELOOK_H -#define OENGINE_OGRE_MOUSELOOK_H - -/* - A mouse-look class for Ogre. Accepts input events from Mangle::Input - and translates them. - - You can adjust the mouse sensibility and switch to a different - camera. The mouselook class also has an optional wrap protection - that keeps the camera from flipping upside down. - - You can disable the mouse looker at any time by calling - setCamera(NULL), and reenable it by setting the camera back. - - NOTE: The current implementation will ONLY work for native OIS - events. - */ - -#include - -namespace Ogre -{ - class Camera; -} - -namespace OEngine { -namespace Render -{ - class MouseLookEvent : public Mangle::Input::Event - { - Ogre::Camera* camera; - float sensX, sensY; // Mouse sensibility - bool flipProt; // Flip protection - - public: - MouseLookEvent(Ogre::Camera *cam=NULL, - float sX=0.2, float sY=0.2, - bool prot=true) - : camera(cam) - , sensX(sX) - , sensY(sY) - , flipProt(prot) - {} - - void setCamera(Ogre::Camera *cam) - { camera = cam; } - void setSens(float sX, float sY) - { sensX = sX; sensY = sY; } - void setProt(bool p) { flipProt = p; } - - void event(Type type, int index, const void *p); - }; - - typedef boost::shared_ptr MouseLookEventPtr; -}} -#endif diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 70bbf7940e..e342f4c5f7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -17,9 +17,28 @@ #include #include +#if defined(__APPLE__) && !defined(__LP64__) +#include +#endif + using namespace Ogre; using namespace OEngine::Render; +#if defined(__APPLE__) && !defined(__LP64__) + +CustomRoot::CustomRoot(const Ogre::String& pluginFileName, + const Ogre::String& configFileName, + const Ogre::String& logFileName) +: Ogre::Root(pluginFileName, configFileName, logFileName) +{} + +bool CustomRoot::isQueuedEnd() const +{ + return mQueuedEnd; +} + +#endif + void OgreRenderer::cleanup() { delete mFader; @@ -31,7 +50,32 @@ void OgreRenderer::cleanup() void OgreRenderer::start() { +#if defined(__APPLE__) && !defined(__LP64__) + // OSX Carbon Message Pump + do { + EventRef event = NULL; + EventTargetRef targetWindow; + targetWindow = GetEventDispatcherTarget(); + + // If we are unable to get the target then we no longer care about events. + if (!targetWindow) return; + + // Grab the next event while possible + while (ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &event) == noErr) + { + // Dispatch the event + SendEventToEventTarget(event, targetWindow); + ReleaseEvent(event); + } + + if (!mRoot->renderOneFrame()) { + break; + } + + } while (!mRoot->isQueuedEnd()); +#else mRoot->startRendering(); +#endif } bool OgreRenderer::loadPlugins() const @@ -90,7 +134,11 @@ void OgreRenderer::configure(const std::string &logPath, // Disable logging log->setDebugOutputEnabled(false); +#if defined(__APPLE__) && !defined(__LP64__) + mRoot = new CustomRoot("", "", ""); +#else mRoot = new Root("", "", ""); +#endif #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) loadPlugins(); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 247c8f95a2..9b7003368e 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -27,9 +27,15 @@ #include "OgreTexture.h" #include +#if defined(__APPLE__) && !defined(__LP64__) +#include +#endif + namespace Ogre { +#if !defined(__APPLE__) || defined(__LP64__) class Root; +#endif class RenderWindow; class SceneManager; class Camera; @@ -48,10 +54,25 @@ namespace OEngine std::string fsaa; }; +#if defined(__APPLE__) && !defined(__LP64__) + class CustomRoot : public Ogre::Root { + public: + bool isQueuedEnd() const; + + CustomRoot(const Ogre::String& pluginFileName = "plugins.cfg", + const Ogre::String& configFileName = "ogre.cfg", + const Ogre::String& logFileName = "Ogre.log"); + }; +#endif + class Fader; class OgreRenderer { +#if defined(__APPLE__) && !defined(__LP64__) + CustomRoot *mRoot; +#else Ogre::Root *mRoot; +#endif Ogre::RenderWindow *mWindow; Ogre::SceneManager *mScene; Ogre::Camera *mCamera; diff --git a/readme.txt b/readme.txt index ce3d115e37..a254e2672b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.16.0 +Version: 0.17.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org @@ -97,6 +97,38 @@ Allowed options: CHANGELOG +0.17.0 + +Bug #225: Valgrind reports about 40MB of leaked memory +Bug #241: Some physics meshes still don't match +Bug #248: Some textures are too dark +Bug #300: Dependency on proprietary CG toolkit +Bug #302: Some objects don't collide although they should +Bug #308: Freeze in Balmora, Meldor: Armorer +Bug #313: openmw without a ~/.config/openmw folder segfault. +Bug #317: adding non-existing spell via console locks game +Bug #318: Wrong character normals +Bug #341: Building with Ogre Debug libraries does not use debug version of plugins +Bug #347: Crash when running openmw with --start="XYZ" +Bug #353: FindMyGUI.cmake breaks path on Windows +Bug #359: WindowManager throws exception at destruction +Bug #364: Laggy input on OS X due to bug in Ogre's event pump implementation +Feature #33: Allow objects to cross cell-borders +Feature #59: Dropping Items (replaced stopgap implementation with a proper one) +Feature #93: Main Menu +Feature #96/329/330/331/332/333: Player Control +Feature #180: Object rotation and scaling. +Feature #272: Incorrect NIF material sharing +Feature #314: Potion usage +Feature #324: Skill Gain +Feature #342: Drain/fortify dynamic stats/attributes magic effects +Feature #350: Allow console only script instructions +Feature #352: Run scripts in console on startup +Task #107: Refactor mw*-subsystems +Task #325: Make CreatureStats into a class +Task #345: Use Ogre's animation system +Task #351: Rewrite Action class to support automatic sound playing + 0.16.0 Bug #250: OpenMW launcher erratic behaviour