diff --git a/CMakeLists.txt b/CMakeLists.txt index 442710a02..ca3fe0eeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 13) +set (OPENMW_VERSION_MINOR 14) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") @@ -122,6 +122,11 @@ set(OENGINE_BULLET ${LIBDIR}/openengine/bullet/physic.hpp ${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp ${LIBDIR}/openengine/bullet/BulletShapeLoader.h + ${LIBDIR}/openengine/bullet/pmove.cpp + ${LIBDIR}/openengine/bullet/pmove.h + ${LIBDIR}/openengine/bullet/trace.cpp + ${LIBDIR}/openengine/bullet/trace.h + ) set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET}) @@ -209,16 +214,16 @@ include_directories("." link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) -if(APPLE) +if (APPLE) # List used Ogre plugins - SET(USED_OGRE_PLUGINS "RenderSystem_GL" - "Plugin_OctreeSceneManager" - "Plugin_CgProgramManager" - "Plugin_ParticleFX") -endif(APPLE) + SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL} + ${OGRE_Plugin_OctreeSceneManager_LIBRARY_REL} + ${OGRE_Plugin_CgProgramManager_LIBRARY_REL} + ${OGRE_Plugin_ParticleFX_LIBRARY_REL}) +endif (APPLE) -add_subdirectory( files/) -add_subdirectory( files/mygui ) +add_subdirectory(files/) +add_subdirectory(files/mygui) # Specify build paths @@ -255,34 +260,36 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") endif() if (APPLE) + if (${OGRE_PLUGIN_DIR_REL}}) + set(OGRE_PLUGINS_REL_FOUND TRUE) + endif () + + if (${OGRE_PLUGIN_DIR_DBG}) + set(OGRE_PLUGINS_DBG_FOUND TRUE) + endif () + + if (${OGRE_PLUGINS_REL_FOUND}) + set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL}) + else () + set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG}) + endif () + + set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/") + configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac "${OpenMW_BINARY_DIR}/plugins.cfg") + set(OGRE_PLUGIN_DIR_2 ${OGRE_PLUGIN_DIR}) + set(OGRE_PLUGIN_DIR "") + configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac + "${OpenMW_BINARY_DIR}/plugins.cfg.install") + set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_2}) + configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist "${APP_BUNDLE_DIR}/Contents/Info.plist") configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) - - # prepare plugins - if (${CMAKE_BUILD_TYPE} MATCHES "Release") - set(OPENMW_RELEASE_BUILD 1) - endif() - if (${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo") - set(OPENMW_RELEASE_BUILD 1) - endif() - - if (${OPENMW_RELEASE_BUILD}) - set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL}) - else() - set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG}) - endif() - - foreach(plugin ${USED_OGRE_PLUGINS}) - configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib" - "${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib" - COPYONLY) - endforeach() endif (APPLE) @@ -356,12 +363,17 @@ if(DPKG_PROGRAM) endif(DPKG_PROGRAM) if(WIN32) - FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*") - INSTALL(FILES ${files} DESTINATION ".") + FILE(GLOB dll_files "${OpenMW_BINARY_DIR}/Release/*.dll") + INSTALL(FILES ${dll_files} DESTINATION ".") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") INSTALL(FILES - "${OpenMW_SOURCE_DIR}/readme.txt" + "${OpenMW_BINARY_DIR}/plugins.cfg" + "${OpenMW_SOURCE_DIR}/readme.txt" + "${OpenMW_BINARY_DIR}/launcher.qss" "${OpenMW_BINARY_DIR}/settings-default.cfg" + "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" + "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" + "${OpenMW_BINARY_DIR}/Release/openmw.exe" DESTINATION ".") INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") @@ -387,7 +399,7 @@ if(WIN32) SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico") SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico") - # SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") + SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") if(EXISTS ${VCREDIST32}) @@ -520,10 +532,12 @@ if (APPLE) install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - - install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg.install" RENAME "plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + set(CPACK_GENERATOR "DragNDrop") set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) @@ -532,22 +546,25 @@ if (APPLE) set(APPS "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}") set(PLUGINS "") + set(ABSOLUTE_PLUGINS "") - # Scan Plugins dir for *.dylibs - set(PLUGIN_SEARCH_ROOT "${APP_BUNDLE_DIR}/Contents/Plugins") - file(GLOB_RECURSE ALL_PLUGINS "${PLUGIN_SEARCH_ROOT}/*.dylib") + foreach (PLUGIN ${USED_OGRE_PLUGINS}) + get_filename_component(PLUGIN_ABS ${PLUGIN} REALPATH) + set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS}) + endforeach () set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins") - foreach(PLUGIN ${ALL_PLUGINS}) - string(REPLACE "${PLUGIN_SEARCH_ROOT}/" "" PLUGIN_RELATIVE "${PLUGIN}") + install(FILES ${ABSOLUTE_PLUGINS} DESTINATION "${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins" COMPONENT Runtime) + foreach (PLUGIN ${ABSOLUTE_PLUGINS}) + get_filename_component(PLUGIN_RELATIVE ${PLUGIN} NAME) set(PLUGINS ${PLUGINS} "${PLUGIN_INSTALL_BASE}/${PLUGIN_RELATIVE}") - endforeach() + endforeach () #For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail set(DIRS "") # Overriding item resolving during installation, it needed if - # some library already has be "fixed up", i.e. its id name contains @executable_path, + # some library already has been "fixed up", i.e. its id name contains @executable_path, # but library is not embedded in bundle. For example, it's Ogre.framework from Ogre SDK. # Current implementation of GetPrerequsities/BundleUtilities doesn't handle that case. # @@ -565,17 +582,22 @@ if (APPLE) if (item MATCHES \"Frameworks\") # if it is a framework # get last segment of path get_filename_component(fname \"\${item}\" NAME_WE) - find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks) + find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} \${CMAKE_SYSTEM_FRAMEWORK_PATH}) if (ri) - message(STATUS \"found \${ri} for \${item}\") string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item}) set(ri \"\${ri}\${item_part}\") set(\${resolved_item_var} \${ri} PARENT_SCOPE) set(\${resolved_var} 1 PARENT_SCOPE) - set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri}) endif() else() # code path for standard (non-framework) libs (ogre & qt pugins) + get_filename_component(fname \"\${item}\" NAME_WE) + string(REGEX REPLACE \"^lib\" \"\" fname \${fname}) + find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /usr/lib /usr/local/lib) + if (ri) + set(\${resolved_item_var} \${ri} PARENT_SCOPE) + set(\${resolved_var} 1 PARENT_SCOPE) + endif () endif() endif() endfunction(gp_resolve_item_override) @@ -585,10 +607,5 @@ if (APPLE) include(BundleUtilities) fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\") " COMPONENT Runtime) - -include(CPack) - -set(CMAKE_EXE_LINKER_FLAGS "-arch i386") -set(CMAKE_CXX_FLAGS "-arch i386") - + include(CPack) endif (APPLE) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index f37f8dae4..d15bc634a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -25,7 +25,7 @@ add_openmw_dir (mwinput add_openmw_dir (mwgui layouts text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation container - map_window window_pinnable_base cursorreplace inventorywindow + map_window window_pinnable_base cursorreplace inventorywindow tooltips itemwidget ) add_openmw_dir (mwdialogue @@ -44,7 +44,7 @@ add_openmw_dir (mwsound ) add_openmw_dir (mwworld - refdata world physicssystem scene environment globals class action nullaction actionteleport + refdata world physicssystem scene globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors cells localscripts customdata weather inventorystore ptr actionopen ) @@ -58,6 +58,10 @@ add_openmw_dir (mwmechanics mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells ) +add_openmw_dir (mwbase + environment + ) + # Main executable IF(OGRE_STATIC) IF(WIN32) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 2d3c872dd..c1bbeb586 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -50,10 +50,12 @@ #include "mwmechanics/mechanicsmanager.hpp" +#include "mwbase/environment.hpp" + void OMW::Engine::executeLocalScripts() { - MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts(); + MWWorld::LocalScripts& localScripts = MWBase::Environment::get().getWorld()->getLocalScripts(); localScripts.startIteration(); @@ -61,58 +63,17 @@ void OMW::Engine::executeLocalScripts() { std::pair script = localScripts.getNext(); - MWScript::InterpreterContext interpreterContext (mEnvironment, + MWScript::InterpreterContext interpreterContext ( &script.second.getRefData().getLocals(), script.second); - mEnvironment.mScriptManager->run (script.first, interpreterContext); + MWBase::Environment::get().getScriptManager()->run (script.first, interpreterContext); - if (mEnvironment.mWorld->hasCellChanged()) + if (MWBase::Environment::get().getWorld()->hasCellChanged()) break; } localScripts.setIgnore (MWWorld::Ptr()); } -void OMW::Engine::updateFocusReport (float duration) -{ - - if ((mFocusTDiff += duration)>0.25) - { - mFocusTDiff = 0; - - std::string name; - - std::string handle = mEnvironment.mWorld->getFacedHandle(); - - if (!handle.empty()) - { - // the faced handle is not updated immediately, so on a cell change it might - // point to an object that doesn't exist anymore - // therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case - try - { - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - - if (!ptr.isEmpty()){ - name = MWWorld::Class::get (ptr).getName (ptr); - - } - } - catch (std::runtime_error& e) - {} - } - - if (name!=mFocusName) - { - mFocusName = name; - - if (mFocusName.empty()) - std::cout << "Unfocus" << std::endl; - else - std::cout << "Focus: " << name << std::endl; - } - } -} - void OMW::Engine::setAnimationVerbose(bool animverbose){ if(animverbose){ NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true); @@ -124,27 +85,19 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) { try { - mEnvironment.mFrameDuration = evt.timeSinceLastFrame; + mEnvironment.setFrameDuration (evt.timeSinceLastFrame); // update input - mEnvironment.mInputManager->update(); + MWBase::Environment::get().getInputManager()->update(); // sound if (mUseSound) - mEnvironment.mSoundManager->update (evt.timeSinceLastFrame); - - // update GUI - Ogre::RenderWindow* window = mOgre->getWindow(); - mEnvironment.mWindowManager->wmUpdateFps(window->getLastFPS(), - window->getTriangleCount(), - window->getBatchCount()); - - mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration); + MWBase::Environment::get().getSoundManager()->update (evt.timeSinceLastFrame); // global scripts - mEnvironment.mGlobalScripts->run (mEnvironment); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().run(); - bool changed = mEnvironment.mWorld->hasCellChanged(); + bool changed = MWBase::Environment::get().getWorld()->hasCellChanged(); // local scripts executeLocalScripts(); // This does not handle the case where a global script causes a cell @@ -152,28 +105,32 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // frame. // passing of time - if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game) - mEnvironment.mWorld->advanceTime ( - mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600); + if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + MWBase::Environment::get().getWorld()->advanceTime ( + mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600); if (changed) // keep change flag for another frame, if cell changed happend in local script - mEnvironment.mWorld->markCellAsUnchanged(); + MWBase::Environment::get().getWorld()->markCellAsUnchanged(); // update actors std::vector > movement; - mEnvironment.mMechanicsManager->update (movement, mEnvironment.mFrameDuration, - mEnvironment.mWindowManager->getMode()!=MWGui::GM_Game); + MWBase::Environment::get().getMechanicsManager()->update (movement, mEnvironment.getFrameDuration(), + MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game); - if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game) - mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration); + if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + MWBase::Environment::get().getWorld()->doPhysics (movement, mEnvironment.getFrameDuration()); // update world - mEnvironment.mWorld->update (evt.timeSinceLastFrame); + MWBase::Environment::get().getWorld()->update (evt.timeSinceLastFrame); - // report focus object (for debugging) - if (mReportFocus) - updateFocusReport (mEnvironment.mFrameDuration); + // update GUI + Ogre::RenderWindow* window = mOgre->getWindow(); + MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), + window->getTriangleCount(), + window->getBatchCount()); + + MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame); } catch (const std::exception& e) { @@ -191,8 +148,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mNewGame (false) , mUseSound (true) , mCompileAll (false) - , mReportFocus (false) - , mFocusTDiff (0) , mScriptContext (0) , mFSStrict (false) , mCfgMgr(configurationManager) @@ -203,13 +158,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) OMW::Engine::~Engine() { - delete mEnvironment.mWorld; - delete mEnvironment.mSoundManager; - delete mEnvironment.mGlobalScripts; - delete mEnvironment.mMechanicsManager; - delete mEnvironment.mDialogueManager; - delete mEnvironment.mJournal; - delete mEnvironment.mScriptManager; + mEnvironment.cleanup(); delete mScriptContext; delete mOgre; } @@ -219,7 +168,7 @@ OMW::Engine::~Engine() void OMW::Engine::loadBSA() { const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa"); - + for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter) { std::cout << "Adding " << iter->second.string() << std::endl; @@ -303,17 +252,10 @@ void OMW::Engine::setNewGame(bool newGame) mNewGame = newGame; } -void OMW::Engine::setReportFocus (bool report) -{ - mReportFocus = report; -} - // Initialise and enter main loop. void OMW::Engine::go() { - mFocusTDiff = 0; - assert (!mEnvironment.mWorld); assert (!mCellName.empty()); assert (!mMaster.empty()); assert (!mOgre); @@ -339,6 +281,8 @@ void OMW::Engine::go() settings.loadDefault(localdefault); else if (boost::filesystem::exists(globaldefault)) settings.loadDefault(globaldefault); + else + throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed."); // load user settings if they exist, otherwise just load the default settings as user settings const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; @@ -382,69 +326,66 @@ void OMW::Engine::go() MWGui::CursorReplace replacer; // Create the world - mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap); + mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, + mResDir, mNewGame, mEncoding, mFallbackMap)); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); - mEnvironment.mWindowManager = new MWGui::WindowManager(mEnvironment, - mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/")); + mEnvironment.setWindowManager (new MWGui::WindowManager( + mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"))); // Create sound system - mEnvironment.mSoundManager = new MWSound::SoundManager(mUseSound, mEnvironment); + mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); // Create script system - mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, - mEnvironment); + mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full); mScriptContext->setExtensions (&mExtensions); - mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), - mVerboseScripts, *mScriptContext); - - mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(), - *mEnvironment.mScriptManager); + mEnvironment.setScriptManager (new MWScript::ScriptManager (MWBase::Environment::get().getWorld()->getStore(), + mVerboseScripts, *mScriptContext)); // Create game mechanics system - mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment); + mEnvironment.setMechanicsManager (new MWMechanics::MechanicsManager); // Create dialog system - mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment); - mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment,mExtensions); + mEnvironment.setJournal (new MWDialogue::Journal); + mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions)); // load cell ESM::Position pos; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; pos.pos[2] = 0; - if (const ESM::Cell *exterior = mEnvironment.mWorld->getExterior (mCellName)) + if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName)) { - mEnvironment.mWorld->indexToPosition (exterior->data.gridX, exterior->data.gridY, + MWBase::Environment::get().getWorld()->indexToPosition (exterior->data.gridX, exterior->data.gridY, pos.pos[0], pos.pos[1], true); - mEnvironment.mWorld->changeToExteriorCell (pos); + MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); } else { pos.pos[0] = pos.pos[1] = 0; - mEnvironment.mWorld->changeToInteriorCell (mCellName, pos); + MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos); } // Sets up the input system - MWInput::MWInputManager input(*mOgre, mEnvironment.mWorld->getPlayer(), - *mEnvironment.mWindowManager, mDebug, *this); - mEnvironment.mInputManager = &input; + + mEnvironment.setInputManager (new MWInput::MWInputManager (*mOgre, + MWBase::Environment::get().getWorld()->getPlayer(), + *MWBase::Environment::get().getWindowManager(), mDebug, *this)); std::cout << "\nPress Q/ESC or close window to exit.\n"; mOgre->getRoot()->addFrameListener (this); // Play some good 'ol tunes - mEnvironment.mSoundManager->playPlaylist(std::string("Explore")); + MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); // scripts if (mCompileAll) { - std::pair result = mEnvironment.mScriptManager->compileAll(); + std::pair result = MWBase::Environment::get().getScriptManager()->compileAll(); if (result.first) std::cout @@ -465,10 +406,10 @@ void OMW::Engine::go() void OMW::Engine::activate() { - if (mEnvironment.mWindowManager->getMode()!=MWGui::GM_Game) + if (MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game) return; - std::string handle = mEnvironment.mWorld->getFacedHandle(); + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); if (handle.empty()) return; @@ -479,7 +420,7 @@ void OMW::Engine::activate() MWWorld::Ptr ptr; try { - ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + ptr = MWBase::Environment::get().getWorld()->getPtrViaHandle (handle); if (ptr.isEmpty()) return; @@ -489,12 +430,10 @@ void OMW::Engine::activate() return; } - MWScript::InterpreterContext interpreterContext (mEnvironment, - &ptr.getRefData().getLocals(), ptr); + MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); boost::shared_ptr action = - MWWorld::Class::get (ptr).activate (ptr, mEnvironment.mWorld->getPlayer().getPlayer(), - mEnvironment); + MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); interpreterContext.activate (ptr, action); @@ -502,8 +441,8 @@ void OMW::Engine::activate() if (!script.empty()) { - mEnvironment.mWorld->getLocalScripts().setIgnore (ptr); - mEnvironment.mScriptManager->run (script, interpreterContext); + MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr); + MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); } if (!interpreterContext.hasActivationBeenHandled()) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 6eae20cc0..63464a40d 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -10,7 +10,8 @@ #include #include -#include "mwworld/environment.hpp" +#include "mwbase/environment.hpp" + #include "mwworld/ptr.hpp" namespace Compiler @@ -61,6 +62,7 @@ namespace OMW /// \brief Main engine class, that brings together all the components of OpenMW class Engine : private Ogre::FrameListener { + MWBase::Environment mEnvironment; std::string mEncoding; Files::PathContainer mDataDirs; boost::filesystem::path mResDir; @@ -73,12 +75,9 @@ namespace OMW bool mNewGame; bool mUseSound; bool mCompileAll; - bool mReportFocus; - float mFocusTDiff; std::string mFocusName; std::map mFallbackMap; - MWWorld::Environment mEnvironment; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; @@ -100,8 +99,6 @@ namespace OMW void executeLocalScripts(); - void updateFocusReport (float duration); - virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); public: @@ -144,9 +141,6 @@ namespace OMW /// Start as a new game. void setNewGame(bool newGame); - /// Write name of focussed object to cout - void setReportFocus (bool report); - /// Initialise and enter main loop. void go(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index df52faab1..68aa12fb3 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -155,9 +155,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" "\n\twin1252 - Western European (Latin) alphabet, used by default") - ("report-focus", bpo::value()->implicit_value(true) - ->default_value(false), "write name of focussed object to cout") - ("fallback", bpo::value()->default_value(FallbackMap(), "") ->multitoken()->composing(), "fallback values") @@ -265,7 +262,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setSoundUsage(!variables["nosound"].as()); engine.setScriptsVerbosity(variables["script-verbose"].as()); engine.setCompileAll(variables["script-all"].as()); - engine.setReportFocus(variables["report-focus"].as()); engine.setAnimationVerbose(variables["anim-verbose"].as()); engine.setFallbackValues(variables["fallback"].as().mMap); diff --git a/apps/openmw/mwbase/environment.cpp b/apps/openmw/mwbase/environment.cpp new file mode 100644 index 000000000..792e240f4 --- /dev/null +++ b/apps/openmw/mwbase/environment.cpp @@ -0,0 +1,161 @@ + +#include "environment.hpp" + +#include + +#include "../mwinput/inputmanager.hpp" + +#include "../mwscript/scriptmanager.hpp" + +#include "../mwsound/soundmanager.hpp" + +#include "../mwworld/world.hpp" + +#include "../mwdialogue/dialoguemanager.hpp" +#include "../mwdialogue/journal.hpp" + +#include "../mwmechanics/mechanicsmanager.hpp" + +MWBase::Environment *MWBase::Environment::sThis = 0; + +MWBase::Environment::Environment() +: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0), + mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mFrameDuration (0) +{ + assert (!sThis); + sThis = this; +} + +MWBase::Environment::~Environment() +{ + cleanup(); + sThis = 0; +} + +void MWBase::Environment::setWorld (MWWorld::World *world) +{ + mWorld = world; +} + +void MWBase::Environment::setSoundManager (MWSound::SoundManager *soundManager) +{ + mSoundManager = soundManager; +} + +void MWBase::Environment::setScriptManager (MWScript::ScriptManager *scriptManager) +{ + mScriptManager = scriptManager; +} + +void MWBase::Environment::setWindowManager (MWGui::WindowManager *windowManager) +{ + mWindowManager = windowManager; +} + +void MWBase::Environment::setMechanicsManager (MWMechanics::MechanicsManager *mechanicsManager) +{ + mMechanicsManager = mechanicsManager; +} + +void MWBase::Environment::setDialogueManager (MWDialogue::DialogueManager *dialogueManager) +{ + mDialogueManager = dialogueManager; +} + +void MWBase::Environment::setJournal (MWDialogue::Journal *journal) +{ + mJournal = journal; +} + +void MWBase::Environment::setInputManager (MWInput::MWInputManager *inputManager) +{ + mInputManager = inputManager; +} + +void MWBase::Environment::setFrameDuration (float duration) +{ + mFrameDuration = duration; +} + +MWWorld::World *MWBase::Environment::getWorld() const +{ + assert (mWorld); + return mWorld; +} + +MWSound::SoundManager *MWBase::Environment::getSoundManager() const +{ + assert (mSoundManager); + return mSoundManager; +} + +MWScript::ScriptManager *MWBase::Environment::getScriptManager() const +{ + assert (mScriptManager); + return mScriptManager; +} + +MWGui::WindowManager *MWBase::Environment::getWindowManager() const +{ + assert (mWindowManager); + return mWindowManager; +} + +MWMechanics::MechanicsManager *MWBase::Environment::getMechanicsManager() const +{ + assert (mMechanicsManager); + return mMechanicsManager; +} + +MWDialogue::DialogueManager *MWBase::Environment::getDialogueManager() const +{ + assert (mDialogueManager); + return mDialogueManager; +} + +MWDialogue::Journal *MWBase::Environment::getJournal() const +{ + assert (mJournal); + return mJournal; +} + +MWInput::MWInputManager *MWBase::Environment::getInputManager() const +{ + assert (mInputManager); + return mInputManager; +} + +float MWBase::Environment::getFrameDuration() const +{ + return mFrameDuration; +} + +void MWBase::Environment::cleanup() +{ + delete mInputManager; + mInputManager = 0; + + delete mSoundManager; + mSoundManager = 0; + + delete mMechanicsManager; + mMechanicsManager = 0; + + delete mDialogueManager; + mDialogueManager = 0; + + delete mJournal; + mJournal = 0; + + delete mScriptManager; + mScriptManager = 0; + + delete mWorld; + mWorld = 0; +} + +const MWBase::Environment& MWBase::Environment::get() +{ + assert (sThis); + return *sThis; +} diff --git a/apps/openmw/mwbase/environment.hpp b/apps/openmw/mwbase/environment.hpp new file mode 100644 index 000000000..521beee0a --- /dev/null +++ b/apps/openmw/mwbase/environment.hpp @@ -0,0 +1,119 @@ +#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 MWWorld +{ + class World; +} + +namespace MWBase +{ + /// \brief Central hub for mw-subsystems + /// + /// This class allows each mw-subsystem to access any others subsystem's top-level manager class. + /// + /// \attention Environment takes ownership of the manager class instances it is handed over in + /// the set* functions. + class Environment + { + static Environment *sThis; + + MWWorld::World *mWorld; + MWSound::SoundManager *mSoundManager; + MWScript::ScriptManager *mScriptManager; + MWGui::WindowManager *mWindowManager; + MWMechanics::MechanicsManager *mMechanicsManager; + MWDialogue::DialogueManager *mDialogueManager; + MWDialogue::Journal *mJournal; + MWInput::MWInputManager *mInputManager; + float mFrameDuration; + + Environment (const Environment&); + ///< not implemented + + Environment& operator= (const Environment&); + ///< not implemented + + public: + + Environment(); + + ~Environment(); + + void setWorld (MWWorld::World *world); + + void setSoundManager (MWSound::SoundManager *soundManager); + + void setScriptManager (MWScript::ScriptManager *scriptManager); + + void setWindowManager (MWGui::WindowManager *windowManager); + + void setMechanicsManager (MWMechanics::MechanicsManager *mechanicsManager); + + void setDialogueManager (MWDialogue::DialogueManager *dialogueManager); + + void setJournal (MWDialogue::Journal *journal); + + void setInputManager (MWInput::MWInputManager *inputManager); + + void setFrameDuration (float duration); + ///< Set length of current frame in seconds. + + MWWorld::World *getWorld() const; + + MWSound::SoundManager *getSoundManager() const; + + MWScript::ScriptManager *getScriptManager() const; + + MWGui::WindowManager *getWindowManager() const; + + MWMechanics::MechanicsManager *getMechanicsManager() const; + + MWDialogue::DialogueManager *getDialogueManager() const; + + MWDialogue::Journal *getJournal() const; + + MWInput::MWInputManager *getInputManager() const; + + float getFrameDuration() const; + + void cleanup(); + ///< Delete all mw*-subsystems. + + static const Environment& get(); + ///< Return instance of this class. + }; +} + +#endif diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 6749a2bfd..6faaacf31 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -1,13 +1,14 @@ #include "activator.hpp" -#include "../mwrender/objects.hpp" #include #include #include "../mwworld/ptr.hpp" - +#include "../mwrender/objects.hpp" +#include "../mwbase/environment.hpp" +#include "../mwgui/window_manager.hpp" namespace MWClass { @@ -18,7 +19,7 @@ namespace MWClass assert (ref->base != NULL); const std::string &model = ref->base->model; - + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); @@ -27,7 +28,7 @@ namespace MWClass } } - void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -63,4 +64,28 @@ namespace MWClass registerClass (typeid (ESM::Activator).name(), instance); } + + bool Activator::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Activator::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + + std::string text; + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 08be8a5ff..223dd0a36 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -12,12 +12,18 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 4bd23d8d8..24d08b804 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -5,12 +5,17 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" #include "../mwrender/objects.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" + #include "../mwsound/soundmanager.hpp" namespace MWClass @@ -31,7 +36,7 @@ namespace MWClass } } - void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -54,9 +59,9 @@ namespace MWClass } boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -95,8 +100,7 @@ namespace MWClass return std::string("Item Apparatus Down"); } - - std::string Apparatus::getInventoryIcon (const MWWorld::Ptr& ptr) const + std::string Apparatus::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -104,4 +108,36 @@ namespace MWClass return ref->base->icon; } + bool Apparatus::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Apparatus::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + text += "\n" + store.gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality); + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index cf8930780..d281600be 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -12,14 +12,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual std::string getScript (const MWWorld::Ptr& ptr) const; @@ -28,6 +28,12 @@ namespace MWClass virtual int getValue (const MWWorld::Ptr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + static void registerSelf(); virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index e8613c4f5..1598085f3 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -9,13 +9,15 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" - #include "../mwworld/inventorystore.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + #include "../mwrender/objects.hpp" +#include "../mwgui/window_manager.hpp" + #include "../mwsound/soundmanager.hpp" namespace MWClass @@ -36,7 +38,7 @@ namespace MWClass } } - void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -58,9 +60,9 @@ namespace MWClass } boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -121,7 +123,7 @@ namespace MWClass return std::make_pair (slots, false); } - int Armor::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + int Armor::getEquipmentSkill (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -138,8 +140,7 @@ namespace MWClass case ESM::Armor::Boots: typeGmst = "iBootsWeight"; break; case ESM::Armor::LGauntlet: case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break; -/// \todo how to determine if shield light, medium or heavy? -// case ESM::Armor::Shield: + case ESM::Armor::Shield: typeGmst = "iShieldWeight"; break; case ESM::Armor::LBracer: case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break; } @@ -147,13 +148,13 @@ namespace MWClass if (typeGmst.empty()) return -1; - float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->i; + float iWeight = MWBase::Environment::get().getWorld()->getStore().gameSettings.find (typeGmst)->i; - if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f>= + if (iWeight * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fLightMaxMod")->f>= ref->base->data.weight) return ESM::Skill::LightArmor; - if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f>= + if (iWeight * MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fMedMaxMod")->f>= ref->base->data.weight) return ESM::Skill::MediumArmor; @@ -175,9 +176,9 @@ namespace MWClass registerClass (typeid (ESM::Armor).name(), instance); } - std::string Armor::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Armor::getUpSoundId (const MWWorld::Ptr& ptr) const { - int es = getEquipmentSkill(ptr, environment); + int es = getEquipmentSkill(ptr); if (es == ESM::Skill::LightArmor) return std::string("Item Armor Light Up"); else if (es == ESM::Skill::MediumArmor) @@ -186,9 +187,9 @@ namespace MWClass return std::string("Item Armor Heavy Up"); } - std::string Armor::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Armor::getDownSoundId (const MWWorld::Ptr& ptr) const { - int es = getEquipmentSkill(ptr, environment); + int es = getEquipmentSkill(ptr); if (es == ESM::Skill::LightArmor) return std::string("Item Armor Light Down"); else if (es == ESM::Skill::MediumArmor) @@ -197,11 +198,62 @@ namespace MWClass return std::string("Item Armor Heavy Down"); } - std::string Armor::getInventoryIcon (const MWWorld::Ptr& ptr) const + std::string Armor::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); return ref->base->icon; } + + bool Armor::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Armor::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + std::string text; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + // get armor type string (light/medium/heavy) + int armorType = getEquipmentSkill(ptr); + std::string typeText; + if (armorType == ESM::Skill::LightArmor) + typeText = store.gameSettings.search("sLight")->str; + else if (armorType == ESM::Skill::MediumArmor) + typeText = store.gameSettings.search("sMedium")->str; + else + typeText = store.gameSettings.search("sHeavy")->str; + + text += "\n" + store.gameSettings.search("sArmorRating")->str + ": " + MWGui::ToolTips::toString(ref->base->data.armor); + + /// \todo store the current armor health somewhere + text += "\n" + store.gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health); + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight) + " (" + typeText + ")"; + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.enchant = ref->base->enchant; + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 7a8ec185a..02622f66e 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -12,14 +12,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const; @@ -35,20 +35,25 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, - const MWWorld::Environment& environment) const; + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual int getValue (const MWWorld::Ptr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 643f41887..713439ccc 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -5,12 +5,16 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" #include "../mwrender/objects.hpp" +#include "../mwgui/window_manager.hpp" + #include "../mwsound/soundmanager.hpp" namespace MWClass @@ -31,7 +35,7 @@ namespace MWClass } } - void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -54,11 +58,11 @@ namespace MWClass } boost::shared_ptr Book::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { // TODO implement reading - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -87,15 +91,16 @@ namespace MWClass registerClass (typeid (ESM::Book).name(), instance); } - std::string Book::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Book::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Book Up"); } - std::string Book::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Book::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Book Down"); } + std::string Book::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -104,4 +109,39 @@ namespace MWClass return ref->base->icon; } + bool Book::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Book::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.enchant = ref->base->enchant; + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 9496d5c0c..fd6e38e04 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -12,28 +12,34 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual int getValue (const MWWorld::Ptr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index dddebd208..57d5e1a64 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -5,10 +5,15 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/tooltips.hpp" +#include "../mwgui/window_manager.hpp" #include "../mwrender/objects.hpp" @@ -32,7 +37,7 @@ namespace MWClass } } - void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -55,9 +60,9 @@ namespace MWClass } boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -89,7 +94,7 @@ namespace MWClass static const int sMapping[size][2] = { - { ESM::Clothing::Shirt, MWWorld::InventoryStore::Slot_Cuirass }, + { ESM::Clothing::Shirt, MWWorld::InventoryStore::Slot_Shirt }, { ESM::Clothing::Belt, MWWorld::InventoryStore::Slot_Belt }, { ESM::Clothing::Robe, MWWorld::InventoryStore::Slot_Robe }, { ESM::Clothing::Pants, MWWorld::InventoryStore::Slot_Pants }, @@ -111,8 +116,7 @@ namespace MWClass return std::make_pair (slots, false); } - int Clothing::getEquipmentSkill (const MWWorld::Ptr& ptr, - const MWWorld::Environment& environment) const + int Clothing::getEquipmentSkill (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -138,7 +142,7 @@ namespace MWClass registerClass (typeid (ESM::Clothing).name(), instance); } - std::string Clothing::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Clothing::getUpSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -150,7 +154,7 @@ namespace MWClass return std::string("Item Clothes Up"); } - std::string Clothing::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Clothing::getDownSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -169,4 +173,40 @@ namespace MWClass return ref->base->icon; } + + bool Clothing::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Clothing::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.enchant = ref->base->enchant; + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index b27767c13..88797650a 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -12,14 +12,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual std::string getScript (const MWWorld::Ptr& ptr) const; @@ -29,20 +29,25 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, - const MWWorld::Environment& environment) const; + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual int getValue (const MWWorld::Ptr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index f8fda0d5e..ec58a78ae 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -5,11 +5,16 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/customdata.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwworld/actionopen.hpp" @@ -62,7 +67,7 @@ namespace MWClass } } - void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -77,7 +82,7 @@ namespace MWClass } boost::shared_ptr Container::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { const std::string lockedSound = "LockedChest"; const std::string trapActivationSound = "Disarm Trap Fail"; @@ -87,7 +92,7 @@ namespace MWClass { // TODO check for key std::cout << "Locked container" << std::endl; - environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, lockedSound, 1.0, 1.0); return boost::shared_ptr (new MWWorld::NullAction); } else @@ -103,7 +108,7 @@ namespace MWClass { // Trap activation goes here std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, trapActivationSound, 1.0, 1.0); ptr.getCellRef().trap = ""; return boost::shared_ptr (new MWWorld::NullAction); } @@ -141,5 +146,37 @@ namespace MWClass registerClass (typeid (ESM::Container).name(), instance); } + bool Container::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + if (ref->ref.lockLevel > 0) + text += "\n" + store.gameSettings.search("sLockLevel")->str + ": " + MWGui::ToolTips::toString(ref->ref.lockLevel); + if (ref->ref.trap != "") + text += "\n" + store.gameSettings.search("sTrapped")->str; + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 387714176..3b1c8de09 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -14,16 +14,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; ///< Return container store diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 7270fd22b..cf00f361b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -6,12 +6,15 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/customdata.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwgui/window_manager.hpp" + namespace { struct CustomData : public MWWorld::CustomData @@ -74,7 +77,7 @@ namespace MWClass actors.insertCreature(ptr); } - void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -87,14 +90,14 @@ namespace MWClass } } - void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + void Creature::enable (const MWWorld::Ptr& ptr) const { - environment.mMechanicsManager->addActor (ptr); + MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Creature::disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + void Creature::disable (const MWWorld::Ptr& ptr) const { - environment.mMechanicsManager->removeActor (ptr); + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); } std::string Creature::getName (const MWWorld::Ptr& ptr) const @@ -113,7 +116,7 @@ namespace MWClass } boost::shared_ptr Creature::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } @@ -140,4 +143,27 @@ namespace MWClass registerClass (typeid (ESM::Creature).name(), instance); } + + bool Creature::hasToolTip (const MWWorld::Ptr& ptr) const + { + /// \todo We don't want tooltips for Creatures in combat mode. + + return true; + } + + MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + + std::string text; + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 8eb45e838..4a1a8285f 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -20,23 +20,29 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr) const; ///< Enable reference; only does the non-rendering part - virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + virtual void disable (const MWWorld::Ptr& ptr) const; ///< Enable reference; only does the non-rendering part virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual MWWorld::ContainerStore& getContainerStore ( diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 9d6c6a78d..7041de1c6 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -5,13 +5,17 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/player.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" #include "../mwworld/actionteleport.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" + #include "../mwrender/objects.hpp" #include "../mwsound/soundmanager.hpp" @@ -34,7 +38,7 @@ namespace MWClass } } - void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -58,7 +62,7 @@ namespace MWClass } boost::shared_ptr Door::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -73,7 +77,7 @@ namespace MWClass // TODO check for key // TODO report failure to player (message, sound?). Look up behaviour of original MW. std::cout << "Locked!" << std::endl; - environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, lockedSound, 1.0, 1.0); return boost::shared_ptr (new MWWorld::NullAction); } @@ -81,7 +85,7 @@ namespace MWClass { // Trap activation std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound3D(ptr, trapActivationSound, 1.0, 1.0); ptr.getCellRef().trap = ""; return boost::shared_ptr (new MWWorld::NullAction); } @@ -89,11 +93,11 @@ namespace MWClass if (ref->ref.teleport) { // teleport door - if (environment.mWorld->getPlayer().getPlayer()==actor) + 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 - environment.mSoundManager->playSound(openSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound(openSound, 1.0, 1.0); return boost::shared_ptr ( new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); } @@ -110,7 +114,7 @@ namespace MWClass // TODO return action for rotating the door // This is a little pointless, but helps with testing - environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, openSound, 1.0, 1.0); return boost::shared_ptr (new MWWorld::NullAction); } } @@ -142,4 +146,63 @@ namespace MWClass registerClass (typeid (ESM::Door).name(), instance); } + + bool Door::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Door::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + + std::string text; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + if (ref->ref.teleport) + { + std::string dest; + if (ref->ref.destCell != "") + { + // door leads to an interior, use interior name as tooltip + dest = ref->ref.destCell; + } + else + { + // door leads to exterior, use cell name (if any), otherwise translated region name + int x,y; + MWBase::Environment::get().getWorld()->positionToIndex (ref->ref.doorDest.pos[0], ref->ref.doorDest.pos[1], x, y); + const ESM::Cell* cell = store.cells.findExt(x,y); + if (cell->name != "") + dest = cell->name; + else + { + const ESM::Region* region = store.regions.search(cell->region); + dest = region->name; + } + } + text += "\n" + store.gameSettings.search("sTo")->str; + text += "\n"+dest; + } + + if (ref->ref.lockLevel > 0) + text += "\n" + store.gameSettings.search("sLockLevel")->str + ": " + MWGui::ToolTips::toString(ref->ref.lockLevel); + if (ref->ref.trap != "") + text += "\n" + store.gameSettings.search("sTrapped")->str; + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index aecb4224c..63d1c1ab8 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; ///< Lock object diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 25b6eda3b..7a1cea7ff 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -5,9 +5,14 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -31,7 +36,7 @@ namespace MWClass } } - void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -52,9 +57,9 @@ namespace MWClass } boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -83,12 +88,12 @@ namespace MWClass registerClass (typeid (ESM::Ingredient).name(), instance); } - std::string Ingredient::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Ingredient::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Ingredient Up"); } - std::string Ingredient::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Ingredient::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Ingredient Down"); } @@ -100,4 +105,38 @@ namespace MWClass return ref->base->icon; } + + bool Ingredient::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Ingredient::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 198f56b1b..4c45bd69c 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -30,10 +36,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index d1c915210..49c80b011 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -5,11 +5,16 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" #include "../mwworld/nullaction.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwsound/soundmanager.hpp" @@ -39,7 +44,7 @@ namespace MWClass objects.insertLight (ptr, r, g, b, radius); } - void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -52,14 +57,14 @@ namespace MWClass } } - void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + void Light::enable (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); if (!ref->base->sound.empty()) { - environment.mSoundManager->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, MWSound::Play_Loop); } } @@ -75,7 +80,7 @@ namespace MWClass } boost::shared_ptr Light::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -83,7 +88,7 @@ namespace MWClass if (!(ref->base->data.flags & ESM::Light::Carry)) return boost::shared_ptr (new MWWorld::NullAction); - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -125,16 +130,17 @@ namespace MWClass registerClass (typeid (ESM::Light).name(), instance); } - std::string Light::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Light::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Misc Up"); } - std::string Light::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Light::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Misc Down"); } + std::string Light::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -142,4 +148,38 @@ namespace MWClass return ref->base->icon; } + + bool Light::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Light::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 6dbb42267..4f21a0f8e 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -12,9 +12,9 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr) const; ///< Enable reference; only does the non-rendering part /// \attention This is not the same as the script instruction with the same name. References /// should only be enabled while in an active cell. @@ -23,8 +23,14 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual std::string getScript (const MWWorld::Ptr& ptr) const; @@ -39,10 +45,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 20e370ff6..89cff2855 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -5,10 +5,14 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/world.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -32,7 +36,7 @@ namespace MWClass } } - void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -56,9 +60,9 @@ namespace MWClass } boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -96,12 +100,12 @@ namespace MWClass registerClass (typeid (ESM::Tool).name(), instance); } - std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Lockpick Up"); } - std::string Lockpick::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Lockpick::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Lockpick Down"); } @@ -113,4 +117,42 @@ namespace MWClass return ref->base->icon; } + + bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + /// \todo store remaining uses somewhere + + text += "\n" + store.gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses); + text += "\n" + store.gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality); + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index b9e8dc393..b8683c5e9 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -34,10 +40,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 573899543..76444318b 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -5,14 +5,21 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwsound/soundmanager.hpp" +#include + namespace MWClass { void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -31,7 +38,7 @@ namespace MWClass } } - void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -54,9 +61,9 @@ namespace MWClass } boost::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -85,24 +92,24 @@ namespace MWClass registerClass (typeid (ESM::Miscellaneous).name(), instance); } - std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); - if (ref->base->name =="Gold") + if (ref->base->name == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) { return std::string("Item Gold Up"); } return std::string("Item Misc Up"); } - std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); - if (ref->base->name =="Gold") + if (ref->base->name == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) { return std::string("Item Gold Down"); } @@ -116,4 +123,49 @@ namespace MWClass return ref->base->icon; } + + bool Miscellaneous::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Miscellaneous::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + if (ref->ref.soul != "") + { + const ESM::Creature *creature = store.creatures.search(ref->ref.soul); + info.caption += " (" + creature->name + ")"; + } + + std::string text; + + if (ref->base->name == store.gameSettings.search("sGold")->str) + info.caption += " (" + boost::lexical_cast(ref->base->data.value) + ")"; + else + { + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + } + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 4eb12c6ea..46b5b9662 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -30,10 +36,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 43e04ab52..444fe9965 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -14,11 +14,14 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/customdata.hpp" +#include "../mwgui/window_manager.hpp" + +#include "../mwbase/environment.hpp" + namespace { const Ogre::Radian kOgrePi (Ogre::Math::PI); @@ -105,10 +108,13 @@ namespace MWClass void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - renderingInterface.getActors().insertNPC(ptr); + + + renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); + } - void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { @@ -130,14 +136,14 @@ namespace MWClass } - void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + void Npc::enable (const MWWorld::Ptr& ptr) const { - environment.mMechanicsManager->addActor (ptr); + MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Npc::disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + void Npc::disable (const MWWorld::Ptr& ptr) const { - environment.mMechanicsManager->removeActor (ptr); + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); } std::string Npc::getName (const MWWorld::Ptr& ptr) const @@ -163,7 +169,7 @@ namespace MWClass } boost::shared_ptr Npc::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } @@ -281,11 +287,12 @@ namespace MWClass { Ogre::Vector3 vector (0, 0, 0); - vector.x = - getMovementSettings (ptr).mLeftRight * 200; - vector.y = getMovementSettings (ptr).mForwardBackward * 200; + vector.x = - getMovementSettings (ptr).mLeftRight * 127; + vector.y = getMovementSettings (ptr).mForwardBackward * 127; + vector.z = getMovementSettings(ptr).mUpDown * 127; - if (getStance (ptr, Run, false)) - vector *= 2; + //if (getStance (ptr, Run, false)) + // vector *= 2; return vector; } @@ -293,7 +300,29 @@ namespace MWClass void Npc::registerSelf() { boost::shared_ptr instance (new Npc); - std::cout << "class npc:" << typeid (ESM::NPC).name(); registerClass (typeid (ESM::NPC).name(), instance); } + + bool Npc::hasToolTip (const MWWorld::Ptr& ptr) const + { + /// \todo We don't want tooltips for NPCs in combat mode. + + return true; + } + + MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + + std::string text; + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index f210eda5f..38b0ba03f 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -17,12 +17,12 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr) const; ///< Enable reference; only does the non-rendering part - virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + virtual void disable (const MWWorld::Ptr& ptr) const; ///< Enable reference; only does the non-rendering part virtual std::string getName (const MWWorld::Ptr& ptr) const; @@ -38,11 +38,17 @@ namespace MWClass virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; ///< Return container store + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const; ///< Return inventory store virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation virtual std::string getScript (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 6c91a46cd..51d3fefae 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -5,9 +5,14 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -31,7 +36,7 @@ namespace MWClass } } - void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -54,9 +59,9 @@ namespace MWClass } boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -85,17 +90,16 @@ namespace MWClass registerClass (typeid (ESM::Potion).name(), instance); } - std::string Potion::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Potion::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Potion Up"); } - std::string Potion::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Potion::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Potion Down"); } - std::string Potion::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -103,4 +107,40 @@ namespace MWClass return ref->base->icon; } + + bool Potion::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Potion::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + info.effects = &ref->base->effects; + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 64dfc4dc7..74779864a 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -30,10 +36,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 4bc8002df..5161301e0 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -5,10 +5,14 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/world.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -32,7 +36,7 @@ namespace MWClass } } - void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -55,9 +59,9 @@ namespace MWClass return ref->base->name; } boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -95,12 +99,12 @@ namespace MWClass registerClass (typeid (ESM::Probe).name(), instance); } - std::string Probe::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Probe::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Probe Up"); } - std::string Probe::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Probe::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Probe Down"); } @@ -112,4 +116,42 @@ namespace MWClass return ref->base->icon; } + + bool Probe::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Probe::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + /// \todo store remaining uses somewhere + + text += "\n" + store.gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses); + text += "\n" + store.gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality); + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index bb46cbdd5..5e0059e14 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -34,10 +40,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 171f9d411..ce68843ed 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -5,9 +5,13 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -31,7 +35,7 @@ namespace MWClass } } - void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -54,9 +58,9 @@ namespace MWClass } boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -85,12 +89,12 @@ namespace MWClass registerClass (typeid (ESM::Repair).name(), instance); } - std::string Repair::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Repair::getUpSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Repair Up"); } - std::string Repair::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Repair::getDownSoundId (const MWWorld::Ptr& ptr) const { return std::string("Item Repair Down"); } @@ -102,4 +106,41 @@ namespace MWClass return ref->base->icon; } + + bool Repair::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + std::string text; + + /// \todo store remaining uses somewhere + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + text += "\n" + store.gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses); + text += "\n" + store.gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality); + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index c4c4c987e..1e935e154 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr @@ -30,10 +36,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 48750dd01..4a4136816 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -25,7 +25,7 @@ namespace MWClass } } - void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index a4b1d8c54..cd1626c19 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -12,7 +12,7 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 216f8a01c..ed31606d0 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -5,10 +5,15 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/world.hpp" + +#include "../mwgui/window_manager.hpp" +#include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" @@ -32,7 +37,7 @@ namespace MWClass } } - void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -55,9 +60,9 @@ namespace MWClass } boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + const MWWorld::Ptr& actor) const { - environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack); return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); @@ -108,8 +113,7 @@ namespace MWClass return std::make_pair (slots, stack); } - int Weapon::getEquipmentSkill (const MWWorld::Ptr& ptr, - const MWWorld::Environment& environment) const + int Weapon::getEquipmentSkill (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -154,7 +158,7 @@ namespace MWClass registerClass (typeid (ESM::Weapon).name(), instance); } - std::string Weapon::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Weapon::getUpSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -200,7 +204,7 @@ namespace MWClass return std::string("Item Misc Up"); } - std::string Weapon::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + std::string Weapon::getDownSoundId (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -246,7 +250,6 @@ namespace MWClass return std::string("Item Misc Down"); } - std::string Weapon::getInventoryIcon (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -254,4 +257,94 @@ namespace MWClass return ref->base->icon; } + + bool Weapon::hasToolTip (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return (ref->base->name != ""); + } + + MWGui::ToolTipInfo Weapon::getToolTipInfo (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + MWGui::ToolTipInfo info; + info.caption = ref->base->name; + info.icon = ref->base->icon; + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string text; + + // weapon type & damage. arrows / bolts don't have his info. + if (ref->base->data.type < 12) + { + text += "\n" + store.gameSettings.search("sType")->str + " "; + + std::map > mapping; + mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded"); + mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded"); + mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded"); + mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded"); + mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded"); + mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded"); + mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded"); + mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded"); + mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded"); + mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", ""); + mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", ""); + mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", ""); + + std::string type = mapping[ref->base->data.type].first; + std::string oneOrTwoHanded = mapping[ref->base->data.type].second; + + text += store.gameSettings.search(type)->str + + ((oneOrTwoHanded != "") ? ", " + store.gameSettings.search(oneOrTwoHanded)->str : ""); + + // weapon damage + if (ref->base->data.type >= 9) + { + // marksman + text += "\n" + store.gameSettings.search("sAttack")->str + ": " + + MWGui::ToolTips::toString(static_cast(ref->base->data.chop[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->base->data.chop[1])); + } + else + { + // Chop + text += "\n" + store.gameSettings.search("sChop")->str + ": " + + MWGui::ToolTips::toString(static_cast(ref->base->data.chop[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->base->data.chop[1])); + // Slash + text += "\n" + store.gameSettings.search("sSlash")->str + ": " + + MWGui::ToolTips::toString(static_cast(ref->base->data.slash[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->base->data.slash[1])); + // Thrust + text += "\n" + store.gameSettings.search("sThrust")->str + ": " + + MWGui::ToolTips::toString(static_cast(ref->base->data.thrust[0])) + + " - " + MWGui::ToolTips::toString(static_cast(ref->base->data.thrust[1])); + } + } + + /// \todo store the current weapon health somewhere + if (ref->base->data.type < 11) // thrown weapons and arrows/bolts don't have health, only quantity + text += "\n" + store.gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health); + + text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); + text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); + + info.enchant = ref->base->enchant; + + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { + text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); + text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); + } + + info.text = text; + + return info; + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 2f83b25d5..8f0d3a233 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -12,16 +12,22 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + const MWWorld::Ptr& actor) const; ///< Generate action for activation + virtual bool hasToolTip (const MWWorld::Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const; ///< \return Item health data available? @@ -35,8 +41,7 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, - const MWWorld::Environment& environment) const; + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. @@ -45,10 +50,10 @@ namespace MWClass static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 90f0c0231..282fba354 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -9,9 +9,9 @@ #include +#include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/refdata.hpp" #include "../mwworld/player.hpp" @@ -54,6 +54,20 @@ namespace return lowerCase; } + bool stringCompareNoCase (std::string first, std::string second) + { + unsigned int i=0; + while ( (itolower(second[i])) return false; + ++i; + } + if (first.length() bool selectCompare (char comp, T1 value1, T2 value2) @@ -147,6 +161,8 @@ namespace MWDialogue bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice) { + bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); + for (std::vector::const_iterator iter (info.selects.begin()); iter != info.selects.end(); ++iter) { @@ -181,7 +197,10 @@ namespace MWDialogue case 46://Same faction { - MWMechanics::NpcStats PCstats = MWWorld::Class::get(mEnvironment.mWorld->getPlayer().getPlayer()).getNpcStats(mEnvironment.mWorld->getPlayer().getPlayer()); + if (isCreature) + return false; + + MWMechanics::NpcStats PCstats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); MWMechanics::NpcStats NPCstats = MWWorld::Class::get(actor).getNpcStats(actor); int sameFaction = 0; if(!NPCstats.mFactionRank.empty()) @@ -269,6 +288,8 @@ namespace MWDialogue bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const { + bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); + char type = select.selectRule[1]; if (type!='0') @@ -288,12 +309,12 @@ namespace MWDialogue if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || select.type==ESM::VT_Long) { - if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld)) + if (!checkGlobal (comp, toLower (name), select.i, *MWBase::Environment::get().getWorld())) return false; } else if (select.type==ESM::VT_Float) { - if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld)) + if (!checkGlobal (comp, toLower (name), select.f, *MWBase::Environment::get().getWorld())) return false; } else @@ -308,13 +329,13 @@ namespace MWDialogue select.type==ESM::VT_Long) { if (!checkLocal (comp, toLower (name), select.i, actor, - mEnvironment.mWorld->getStore())) + MWBase::Environment::get().getWorld()->getStore())) return false; } else if (select.type==ESM::VT_Float) { if (!checkLocal (comp, toLower (name), select.f, actor, - mEnvironment.mWorld->getStore())) + MWBase::Environment::get().getWorld()->getStore())) return false; } else @@ -326,7 +347,7 @@ namespace MWDialogue case '4'://journal if(select.type==ESM::VT_Int) { - if(!selectCompare(comp,mEnvironment.mJournal->getJournalIndex(toLower(name)),select.i)) return false; + if(!selectCompare(comp,MWBase::Environment::get().getJournal()->getJournalIndex(toLower(name)),select.i)) return false; } else throw std::runtime_error ( @@ -336,7 +357,7 @@ namespace MWDialogue case '5'://item { - MWWorld::Ptr player = mEnvironment.mWorld->getPlayer().getPlayer(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); int sum = 0; @@ -366,6 +387,9 @@ namespace MWDialogue return true; case '8':// not faction + if (isCreature) + return false; + if(select.type==ESM::VT_Int) { ESMS::LiveCellRef* npc = actor.get(); @@ -380,6 +404,9 @@ namespace MWDialogue return true; case '9':// not class + if (isCreature) + return false; + if(select.type==ESM::VT_Int) { ESMS::LiveCellRef* npc = actor.get(); @@ -394,6 +421,9 @@ namespace MWDialogue return true; case 'A'://not Race + if (isCreature) + return false; + if(select.type==ESM::VT_Int) { ESMS::LiveCellRef* npc = actor.get(); @@ -424,13 +454,13 @@ namespace MWDialogue select.type==ESM::VT_Long) { if (checkLocal (comp, toLower (name), select.i, actor, - mEnvironment.mWorld->getStore())) + MWBase::Environment::get().getWorld()->getStore())) return false; } else if (select.type==ESM::VT_Float) { if (checkLocal (comp, toLower (name), select.f, actor, - mEnvironment.mWorld->getStore())) + MWBase::Environment::get().getWorld()->getStore())) return false; } else @@ -450,6 +480,8 @@ namespace MWDialogue bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const { + bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); + // actor id if (!info.actor.empty()) if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor)) @@ -458,6 +490,9 @@ namespace MWDialogue //NPC race if (!info.race.empty()) { + if (isCreature) + return false; + ESMS::LiveCellRef *cellRef = actor.get(); if (!cellRef) @@ -470,6 +505,9 @@ namespace MWDialogue //NPC class if (!info.clas.empty()) { + if (isCreature) + return false; + ESMS::LiveCellRef *cellRef = actor.get(); if (!cellRef) @@ -482,6 +520,9 @@ namespace MWDialogue //NPC faction if (!info.npcFaction.empty()) { + if (isCreature) + return false; + //MWWorld::Class npcClass = MWWorld::Class::get(actor); MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); std::map::iterator it = stats.mFactionRank.find(info.npcFaction); @@ -500,7 +541,7 @@ namespace MWDialogue // TODO check player faction if(!info.pcFaction.empty()) { - MWMechanics::NpcStats stats = MWWorld::Class::get(mEnvironment.mWorld->getPlayer().getPlayer()).getNpcStats(mEnvironment.mWorld->getPlayer().getPlayer()); + MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); std::map::iterator it = stats.mFactionRank.find(info.pcFaction); if(it!=stats.mFactionRank.end()) { @@ -515,20 +556,22 @@ namespace MWDialogue } //check gender - ESMS::LiveCellRef* npc = actor.get(); - if(npc->base->flags&npc->base->Female) + if (!isCreature) { - if(static_cast (info.data.gender)==0) return false; + ESMS::LiveCellRef* npc = actor.get(); + if(npc->base->flags&npc->base->Female) + { + if(static_cast (info.data.gender)==0) return false; + } + else + { + if(static_cast (info.data.gender)==1) return false; + } } - else - { - if(static_cast (info.data.gender)==1) return false; - } - // check cell if (!info.cell.empty()) - if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell) + if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->name != info.cell) return false; // TODO check DATAstruct @@ -540,8 +583,8 @@ namespace MWDialogue return true; } - DialogueManager::DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions) : - mEnvironment (environment),mCompilerContext (MWScript::CompilerContext::Type_Dialgoue, environment), + DialogueManager::DialogueManager (const Compiler::Extensions& extensions) : + mCompilerContext (MWScript::CompilerContext::Type_Dialgoue), mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) { mChoice = -1; @@ -549,10 +592,10 @@ namespace MWDialogue mCompilerContext.setExtensions (&extensions); mDialogueMap.clear(); actorKnownTopics.clear(); - ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list; - for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) + ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; + for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) { - mDialogueMap[it->first] = it->second; + mDialogueMap[toLower(it->first)] = it->second; } } @@ -592,8 +635,8 @@ namespace MWDialogue actorKnownTopics.clear(); //initialise the GUI - mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue); - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); + MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Dialogue); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->startDialogue(MWWorld::Class::get (actor).getName (actor)); //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI @@ -601,9 +644,9 @@ namespace MWDialogue //greeting bool greetingFound = false; - //ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list; - ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list; - for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) + //ESMS::RecListT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; + ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; + for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) { ESM::Dialogue ndialogue = it->second; if(ndialogue.type == ESM::Dialogue::Greeting) @@ -650,7 +693,7 @@ namespace MWDialogue if (!actorScript.empty()) { // grab local variables from actor's script, if available. - locals = mEnvironment.mScriptManager->getLocals (actorScript); + locals = MWBase::Environment::get().getScriptManager()->getLocals (actorScript); } Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false); @@ -677,13 +720,12 @@ namespace MWDialogue void DialogueManager::executeScript(std::string script) { - std::cout << script; std::vector code; if(compile(script,code)) { try { - MWScript::InterpreterContext interpreterContext(mEnvironment,&mActor.getRefData().getLocals(),mActor); + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); Interpreter::Interpreter interpreter; MWScript::installOpcodes (interpreter); interpreter.run (&code[0], code.size(), interpreterContext); @@ -701,9 +743,9 @@ namespace MWDialogue int choice = mChoice; mChoice = -1; actorKnownTopics.clear(); - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); - ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list; - for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); + ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; + for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) { ESM::Dialogue ndialogue = it->second; if(ndialogue.type == ESM::Dialogue::Topic) @@ -713,7 +755,7 @@ namespace MWDialogue { if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true)) { - actorKnownTopics.push_back(it->first); + actorKnownTopics.push_back(toLower(it->first)); //does the player know the topic? if(knownTopics.find(toLower(it->first)) != knownTopics.end()) { @@ -724,7 +766,11 @@ namespace MWDialogue } } } + + // sort again, because the previous sort was case-sensitive + keywordList.sort(stringCompareNoCase); win->setKeywords(keywordList); + mChoice = choice; } @@ -747,7 +793,7 @@ namespace MWDialogue parseText(text); - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->addTitle(keyword); win->addText(iter->response); @@ -767,7 +813,7 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { - mEnvironment.mInputManager->setGuiMode(MWGui::GM_Game); + MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); } void DialogueManager::questionAnswered(std::string answere) @@ -790,7 +836,7 @@ namespace MWDialogue mChoiceMap.clear(); mChoice = -1; mIsInChoice = false; - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); std::string text = iter->response; parseText(text); win->addText(text); @@ -808,20 +854,23 @@ namespace MWDialogue void DialogueManager::printError(std::string error) { - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->addText(error); } void DialogueManager::askQuestion(std::string question, int choice) { - MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow(); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->askQuestion(question); - mChoiceMap[question] = choice; + mChoiceMap[toLower(question)] = choice; mIsInChoice = true; } std::string DialogueManager::getFaction() { + if (mActor.getTypeName() != typeid(ESM::NPC).name()) + return ""; + std::string factionID(""); MWMechanics::NpcStats stats = MWWorld::Class::get(mActor).getNpcStats(mActor); if(stats.mFactionRank.empty()) diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp index d0380fa71..a3e37987d 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.hpp +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -11,17 +11,10 @@ #include "../mwworld/ptr.hpp" #include -namespace MWWorld -{ - class Environment; -} - namespace MWDialogue { class DialogueManager { - MWWorld::Environment& mEnvironment; - bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; @@ -39,7 +32,7 @@ namespace MWDialogue MWScript::CompilerContext mCompilerContext; std::ostream mErrorStream; Compiler::StreamErrorHandler mErrorHandler; - + bool compile (const std::string& cmd,std::vector& code); void executeScript(std::string script); @@ -55,7 +48,7 @@ namespace MWDialogue public: - DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions); + DialogueManager (const Compiler::Extensions& extensions); void startDialogue (const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwdialogue/journal.cpp b/apps/openmw/mwdialogue/journal.cpp index 0715214eb..e0245406e 100644 --- a/apps/openmw/mwdialogue/journal.cpp +++ b/apps/openmw/mwdialogue/journal.cpp @@ -1,7 +1,7 @@ #include "journal.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwgui/window_manager.hpp" #include "../mwgui/messagebox.hpp" @@ -23,31 +23,30 @@ namespace MWDialogue return iter->second; } - Journal::Journal (MWWorld::Environment& environment) - : mEnvironment (environment) + Journal::Journal() {} void Journal::addEntry (const std::string& id, int index) { StampedJournalEntry entry = - StampedJournalEntry::makeFromQuest (id, index, *mEnvironment.mWorld); + StampedJournalEntry::makeFromQuest (id, index, *MWBase::Environment::get().getWorld()); mJournal.push_back (entry); Quest& quest = getQuest (id); - quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here - + quest.addEntry (entry, *MWBase::Environment::get().getWorld()); // we are doing slicing on purpose here + std::vector empty; std::string notification = "Your Journal has been updated."; - mEnvironment.mWindowManager->messageBox (notification, empty); + MWBase::Environment::get().getWindowManager()->messageBox (notification, empty); } void Journal::setJournalIndex (const std::string& id, int index) { Quest& quest = getQuest (id); - quest.setIndex (index, *mEnvironment.mWorld); + quest.setIndex (index, *MWBase::Environment::get().getWorld()); } void Journal::addTopic (const std::string& topicId, const std::string& infoId) @@ -62,7 +61,7 @@ namespace MWDialogue iter = result.first; } - iter->second.addEntry (JournalEntry (topicId, infoId), *mEnvironment.mWorld); + iter->second.addEntry (JournalEntry (topicId, infoId), *MWBase::Environment::get().getWorld()); } int Journal::getJournalIndex (const std::string& id) const diff --git a/apps/openmw/mwdialogue/journal.hpp b/apps/openmw/mwdialogue/journal.hpp index ff1343945..62b9f4bed 100644 --- a/apps/openmw/mwdialogue/journal.hpp +++ b/apps/openmw/mwdialogue/journal.hpp @@ -8,11 +8,6 @@ #include "journalentry.hpp" #include "quest.hpp" -namespace MWWorld -{ - struct Environment; -} - namespace MWDialogue { /// \brief The player's journal @@ -29,7 +24,6 @@ namespace MWDialogue private: - MWWorld::Environment& mEnvironment; TEntryContainer mJournal; TQuestContainer mQuests; TTopicContainer mTopics; @@ -38,7 +32,7 @@ namespace MWDialogue public: - Journal (MWWorld::Environment& environment); + Journal(); void addEntry (const std::string& id, int index); ///< Add a journal entry. diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index e9c15fab4..cb15eaf15 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -25,13 +25,14 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager) birthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth); birthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); + backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); updateBirths(); @@ -46,21 +47,16 @@ void BirthDialog::setNextButtonShow(bool shown) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system. if (shown) - { - okButton->setCaption("Next"); - - // Adjust back button when next is shown - backButton->setCoord(MyGUI::IntCoord(375 - 18, 340, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(431 - 18, 340, 42 + 18, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); else - { - okButton->setCaption("OK"); - backButton->setCoord(MyGUI::IntCoord(375, 340, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(431, 340, 42, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + + int okButtonWidth = okButton->getTextSize().width + 24; + int backButtonWidth = backButton->getTextSize().width + 24; + + okButton->setCoord(473 - okButtonWidth, 340, okButtonWidth, 23); + backButton->setCoord(473 - okButtonWidth - backButtonWidth - 6, 340, backButtonWidth, 23); } void BirthDialog::open() @@ -206,7 +202,7 @@ void BirthDialog::updateSpells() MyGUI::IntCoord spellCoord = coord; spellCoord.height = 24; // TODO: This should be fetched from the skin somehow, or perhaps a widget in the layout as a template? - spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord); + spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord, (category == 0) ? MWEffectList::EF_Constant : 0); coord.top = spellCoord.top; ++i; diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index ce5e744cc..10c4cdcb4 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -8,12 +8,16 @@ #include "dialogue.hpp" #include "mode.hpp" +#include "../mwbase/environment.hpp" +#include "../mwsound/soundmanager.hpp" + namespace { struct Step { const char* mText; const char* mButtons[3]; + const char* mSound; ESM::Class::Specialization mSpecializations[3]; // The specialization for each answer }; @@ -23,6 +27,7 @@ namespace {"Draw your dagger, mercifully endings its life with a single thrust.", "Use herbs from your pack to put it to sleep.", "Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."}, + "vo\\misc\\chargen qa1.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 2 @@ -30,6 +35,7 @@ namespace {"Work in the forge with him casting iron for a new plow.", "Gather herbs for your mother who is preparing dinner.", "Go catch fish at the stream using a net and line."}, + "vo\\misc\\chargen qa2.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 3 @@ -37,6 +43,7 @@ namespace {"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.", "Make up a story that makes your nickname a badge of honor instead of something humiliating.", "Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."}, + "vo\\misc\\chargen qa3.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 4 @@ -44,6 +51,7 @@ namespace {"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.", "Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.", "In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."}, + "vo\\misc\\chargen qa4.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 5 @@ -51,6 +59,7 @@ namespace {"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?", "Decide to put the extra money to good use and purchase items that would help your family?", "Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"}, + "vo\\misc\\chargen qa5.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 6 @@ -58,6 +67,7 @@ namespace {"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.", "Leave the bag there, knowing that it is better not to get involved.", "Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."}, + "vo\\misc\\chargen qa6.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 7 @@ -65,6 +75,7 @@ namespace {"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.", "Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.", "Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."}, + "vo\\misc\\chargen qa7.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 8 @@ -72,6 +83,7 @@ namespace {"Position yourself between the pipe and your mother.", "Grab the hot pipe and try to push it away.", "Push your mother out of the way."}, + "vo\\misc\\chargen qa8.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 9 @@ -79,6 +91,7 @@ namespace {"Drop the sweetroll and step on it, then get ready for the fight.", "Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.", "Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."}, + "vo\\misc\\chargen qa9.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} }, // Question 10 @@ -86,6 +99,7 @@ namespace {"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.", "Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.", "Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."}, + "vo\\misc\\chargen qa10.wav", {ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth} } } }; @@ -93,7 +107,7 @@ namespace using namespace MWGui; -CharacterCreation::CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment) +CharacterCreation::CharacterCreation(WindowManager* _wm) : mNameDialog(0) , mRaceDialog(0) , mDialogueWindow(0) @@ -105,7 +119,6 @@ CharacterCreation::CharacterCreation(WindowManager* _wm, MWWorld::Environment* _ , mBirthSignDialog(0) , mReviewDialog(0) , mWM(_wm) - , mEnvironment(_environment) { mCreationStage = CSE_NotStarted; } @@ -279,8 +292,8 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) { const std::string &classId = mPickClassDialog->getClassId(); if (!classId.empty()) - mEnvironment->mMechanicsManager->setPlayerClass(classId); - const ESM::Class *klass = mEnvironment->mWorld->getStore().classes.find(classId); + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId); + const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(classId); if (klass) { mPlayerClass = *klass; @@ -307,7 +320,7 @@ void CharacterCreation::onPickClassDialogBack() { const std::string classId = mPickClassDialog->getClassId(); if (!classId.empty()) - mEnvironment->mMechanicsManager->setPlayerClass(classId); + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId); mWM->removeDialog(mPickClassDialog); } @@ -345,7 +358,7 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow) { mPlayerName = mNameDialog->getTextInput(); mWM->setValue("name", mPlayerName); - mEnvironment->mMechanicsManager->setPlayerName(mPlayerName); + MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName); mWM->removeDialog(mNameDialog); } @@ -366,7 +379,7 @@ void CharacterCreation::onRaceDialogBack() { mPlayerRaceId = mRaceDialog->getRaceId(); if (!mPlayerRaceId.empty()) - mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); + MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); mWM->removeDialog(mRaceDialog); } @@ -380,7 +393,7 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) mPlayerRaceId = mRaceDialog->getRaceId(); mWM->setValue("race", mPlayerRaceId); if (!mPlayerRaceId.empty()) - mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); + MWBase::Environment::get().getMechanicsManager()->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male); mWM->removeDialog(mRaceDialog); } @@ -402,7 +415,7 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) mPlayerBirthSignId = mBirthSignDialog->getBirthId(); mWM->setBirthSign(mPlayerBirthSignId); if (!mPlayerBirthSignId.empty()) - mEnvironment->mMechanicsManager->setPlayerBirthsign(mPlayerBirthSignId); + MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId); mWM->removeDialog(mBirthSignDialog); } @@ -419,7 +432,7 @@ void CharacterCreation::onBirthSignDialogBack() { if (mBirthSignDialog) { - mEnvironment->mMechanicsManager->setPlayerBirthsign(mBirthSignDialog->getBirthId()); + MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId()); mWM->removeDialog(mBirthSignDialog); } @@ -450,7 +463,7 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) klass.data.skills[i][1] = majorSkills[i]; klass.data.skills[i][0] = minorSkills[i]; } - mEnvironment->mMechanicsManager->setPlayerClass(klass); + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass); mPlayerClass = klass; mWM->setPlayerClass(klass); @@ -478,6 +491,8 @@ void CharacterCreation::onCreateClassDialogBack() void CharacterCreation::onClassQuestionChosen(int _index) { + MWBase::Environment::get().getSoundManager()->stopSay(); + if (mGenerateClassQuestionDialog) mWM->removeDialog(mGenerateClassQuestionDialog); if (_index < 0 || _index >= 3) @@ -583,6 +598,8 @@ void CharacterCreation::showClassQuestionDialog() mGenerateClassQuestionDialog->setButtons(buttons); mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen); mGenerateClassQuestionDialog->open(); + + MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps[mGenerateClassStep].mSound); } void CharacterCreation::onGenerateClassBack() @@ -592,7 +609,7 @@ void CharacterCreation::onGenerateClassBack() if (mGenerateClassResultDialog) mWM->removeDialog(mGenerateClassResultDialog); - mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass); + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); mWM->setGuiMode(GM_Class); } @@ -601,7 +618,7 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) { if (mGenerateClassResultDialog) mWM->removeDialog(mGenerateClassResultDialog); - mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass); + MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); if (mCreationStage == CSE_ReviewNext) mWM->setGuiMode(GM_Review); diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index b01e754d9..222754cdc 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -30,7 +30,7 @@ namespace MWGui public: typedef std::vector SkillList; - CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment); + CharacterCreation(WindowManager* _wm); ~CharacterCreation(); //Show a dialog @@ -56,7 +56,6 @@ namespace MWGui ReviewDialog* mReviewDialog; WindowManager* mWM; - MWWorld::Environment* mEnvironment; //Player data std::string mPlayerName; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 75e534b42..9f1fc5d2a 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -26,14 +26,20 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan getWidget(classImage, "ClassImage"); getWidget(className, "ClassName"); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); + backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked); + + int okButtonWidth = okButton->getTextSize().width + 24; + int backButtonWidth = backButton->getTextSize().width + 24; + okButton->setCoord(315 - okButtonWidth, 219, okButtonWidth, 23); + backButton->setCoord(315 - okButtonWidth - backButtonWidth - 6, 219, backButtonWidth, 23); } void GenerateClassResultDialog::open() @@ -102,7 +108,6 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager) getWidget(classImage, "ClassImage"); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked); @@ -123,21 +128,16 @@ void PickClassDialog::setNextButtonShow(bool shown) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system. if (shown) - { - okButton->setCaption("Next"); - - // Adjust back button when next is shown - backButton->setCoord(MyGUI::IntCoord(382 - 18, 265, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(434 - 18, 265, 42 + 18, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); else - { - okButton->setCaption("OK"); - backButton->setCoord(MyGUI::IntCoord(382, 265, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(434, 265, 42, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + + int okButtonWidth = okButton->getTextSize().width + 24; + int backButtonWidth = backButton->getTextSize().width + 24; + + okButton->setCoord(476 - okButtonWidth, 265, okButtonWidth, 23); + backButton->setCoord(476 - okButtonWidth - backButtonWidth - 6, 265, backButtonWidth, 23); } void PickClassDialog::open() @@ -423,9 +423,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(editName); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr descriptionButton; getWidget(descriptionButton, "DescriptionButton"); + descriptionButton->setCaption(mWindowManager.getGameSettingString("sCreateClassMenu1", "")); descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked); MyGUI::ButtonPtr backButton; @@ -507,32 +507,27 @@ std::vector CreateClassDialog::getMinorSkills() const void CreateClassDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr descriptionButton; - getWidget(descriptionButton, "DescriptionButton"); - MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system. - if (shown) - { - okButton->setCaption("Next"); + MyGUI::ButtonPtr descriptionButton; + getWidget(descriptionButton, "DescriptionButton"); - // Adjust back button when next is shown - descriptionButton->setCoord(MyGUI::IntCoord(207 - 18, 158, 143, 23)); - backButton->setCoord(MyGUI::IntCoord(356 - 18, 158, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(417 - 18, 158, 42 + 18, 23)); - } + if (shown) + okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); else - { - okButton->setCaption("OK"); - descriptionButton->setCoord(MyGUI::IntCoord(207, 158, 143, 23)); - backButton->setCoord(MyGUI::IntCoord(356, 158, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(417, 158, 42, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + + int okButtonWidth = okButton->getTextSize().width + 24; + int backButtonWidth = backButton->getTextSize().width + 24; + int descriptionButtonWidth = descriptionButton->getTextSize().width + 24; + + okButton->setCoord(459 - okButtonWidth, 158, okButtonWidth, 23); + backButton->setCoord(459 - okButtonWidth - backButtonWidth - 6, 158, backButtonWidth, 23); + descriptionButton->setCoord(459 - okButtonWidth - backButtonWidth - descriptionButtonWidth - 12, 158, descriptionButtonWidth, 23); } void CreateClassDialog::open() @@ -679,11 +674,12 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specializationId = ESM::Class::Combat; - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); + int buttonWidth = cancelButton->getTextSize().width + 24; + cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); } // widget controls @@ -728,11 +724,12 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); } - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); + int buttonWidth = cancelButton->getTextSize().width + 24; + cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); } // widget controls @@ -817,11 +814,12 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) } } - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); + int buttonWidth = cancelButton->getTextSize().width + 24; + cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); } // widget controls @@ -847,11 +845,12 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) getWidget(textEdit, "TextEdit"); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked); okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", "")); + int buttonWidth = okButton->getTextSize().width + 24; + okButton->setCoord(234 - buttonWidth, 214, buttonWidth, 24); // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index ac4f4a82a..8e15abddd 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -7,6 +7,8 @@ #include "../mwscript/extensions.hpp" +#include "../mwbase/environment.hpp" + namespace MWGui { class ConsoleInterpreterContext : public MWScript::InterpreterContext @@ -15,15 +17,14 @@ namespace MWGui public: - ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment, - MWWorld::Ptr reference); + ConsoleInterpreterContext (Console& console, MWWorld::Ptr reference); virtual void report (const std::string& message); }; ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console, - MWWorld::Environment& environment, MWWorld::Ptr reference) - : MWScript::InterpreterContext (environment, + MWWorld::Ptr reference) + : MWScript::InterpreterContext ( reference.isEmpty() ? 0 : &reference.getRefData().getLocals(), reference), mConsole (console) {} @@ -88,7 +89,7 @@ namespace MWGui scanner.listKeywords (mNames); // identifier - const ESMS::ESMStore& store = mEnvironment.mWorld->getStore(); + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); for (ESMS::RecListList::const_iterator iter (store.recLists.begin()); iter!=store.recLists.end(); ++iter) @@ -101,11 +102,9 @@ namespace MWGui } } - Console::Console(int w, int h, MWWorld::Environment& environment, - const Compiler::Extensions& extensions) + Console::Console(int w, int h, const Compiler::Extensions& extensions) : Layout("openmw_console_layout.xml"), - mCompilerContext (MWScript::CompilerContext::Type_Console, environment), - mEnvironment (environment) + mCompilerContext (MWScript::CompilerContext::Type_Console) { setCoord(10,10, w-10, h/2); @@ -139,7 +138,7 @@ namespace MWGui void Console::disable() { setVisible(false); - // Remove keyboard focus from the console input whenever the + // Remove keyboard focus from the console input whenever the // console is turned off MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL); } @@ -241,7 +240,7 @@ namespace MWGui { try { - ConsoleInterpreterContext interpreterContext (*this, mEnvironment, MWWorld::Ptr()); + ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr()); Interpreter::Interpreter interpreter; MWScript::installOpcodes (interpreter); std::vector code; diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index eaf4299be..6974d8333 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -23,7 +23,6 @@ namespace MWGui private: MWScript::CompilerContext mCompilerContext; - MWWorld::Environment& mEnvironment; std::vector mNames; bool compile (const std::string& cmd, Compiler::Output& output); @@ -51,7 +50,7 @@ namespace MWGui StringList::iterator current; std::string editString; - Console(int w, int h, MWWorld::Environment& environment, const Compiler::Extensions& extensions); + Console(int w, int h, const Compiler::Extensions& extensions); void enable(); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index ac6681e27..0238446eb 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -3,7 +3,7 @@ #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwdialogue/dialoguemanager.hpp" #include @@ -36,9 +36,8 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su } -DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment) - : WindowBase("openmw_dialogue_window_layout.xml", parWindowManager), - mEnvironment(environment) +DialogueWindow::DialogueWindow(WindowManager& parWindowManager) + : WindowBase("openmw_dialogue_window_layout.xml", parWindowManager) { // Centre dialog center(); @@ -51,10 +50,10 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environm //An EditBox cannot receive mouse click events, so we use an //invisible widget on top of the editbox to receive them - /// \todo scrolling the dialogue history with the mouse wheel doesn't work using this solution getWidget(eventbox, "EventBox"); eventbox->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked); - + eventbox->eventMouseWheel += MyGUI::newDelegate(this, &DialogueWindow::onMouseWheel); + //Topics list getWidget(topicsList, "TopicsList"); topicsList->setScrollVisible(true); @@ -83,12 +82,20 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender) if(color != "#B29154") { UString key = history->getColorTextAt(cursorPosition); - if(color == "#686EBA") mEnvironment.mDialogueManager->keywordSelected(lower_string(key)); + if(color == "#686EBA") MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key)); - if(color == "#572D21") mEnvironment.mDialogueManager->questionAnswered(key); + if(color == "#572D21") MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key)); } } +void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (history->getVScrollPosition() - _rel*0.3 < 0) + history->setVScrollPosition(0); + else + history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3); +} + void DialogueWindow::open() { topicsList->removeAllItems(); @@ -100,7 +107,7 @@ void DialogueWindow::open() void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) { - mEnvironment.mDialogueManager->goodbyeSelected(); + MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); } void DialogueWindow::onSelectTopic(MyGUI::ListBox* _sender, size_t _index) @@ -108,7 +115,7 @@ void DialogueWindow::onSelectTopic(MyGUI::ListBox* _sender, size_t _index) if (_index == MyGUI::ITEM_NONE) return; std::string topic = _sender->getItemNameAt(_index); - mEnvironment.mDialogueManager->keywordSelected(lower_string(topic)); + MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic)); } void DialogueWindow::startDialogue(std::string npcName) @@ -183,6 +190,16 @@ void DialogueWindow::addText(std::string text) void DialogueWindow::addTitle(std::string text) { + // This is called from the dialogue manager, so text is + // case-smashed - thus we have to retrieve the correct case + // of the text through the topic list. + for (size_t i=0; igetItemCount(); ++i) + { + std::string item = topicsList->getItemNameAt(i); + if (lower_string(item) == text) + text = item; + } + history->addDialogHeading(text); } diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index b80a016cb..5921ca57a 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -9,11 +9,6 @@ namespace MWGui class WindowManager; } -namespace MWWorld -{ - class Environment; -} - /* This file contains the dialouge window Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml. @@ -23,17 +18,15 @@ namespace MWGui { class DialogueHistory; - using namespace MyGUI; - class DialogueWindow: public WindowBase { public: - DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + DialogueWindow(WindowManager& parWindowManager); void open(); // Events - typedef delegates::CMultiDelegate0 EventHandle_Void; + typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; /** Event : Dialog finished, OK button clicked.\n signature : void method()\n @@ -52,6 +45,7 @@ namespace MWGui void onSelectTopic(MyGUI::ListBox* _sender, size_t _index); void onByeClicked(MyGUI::Widget* _sender); void onHistoryClicked(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); private: void updateOptions(); @@ -65,8 +59,6 @@ namespace MWGui MyGUI::ProgressPtr pDispositionBar; MyGUI::EditPtr pDispositionText; std::map pTopicsText;// this map links keyword and "real" text. - - MWWorld::Environment& mEnvironment; }; } #endif diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 644bcbc04..e67eda777 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -1,7 +1,7 @@ #include "journalwindow.hpp" #include "window_manager.hpp" #include "../mwdialogue/journal.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwsound/soundmanager.hpp" @@ -118,20 +118,20 @@ void MWGui::JournalWindow::open() { mPageNumber = 0; std::string journalOpenSound = "book open"; - mWindowManager.getEnvironment().mSoundManager->playSound (journalOpenSound, 1.0, 1.0); - if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end()) + MWBase::Environment::get().getSoundManager()->playSound (journalOpenSound, 1.0, 1.0); + if(MWBase::Environment::get().getJournal()->begin()!=MWBase::Environment::get().getJournal()->end()) { book journal; journal.endLine = 0; - for(std::deque::const_iterator it = mWindowManager.getEnvironment().mJournal->begin();it!=mWindowManager.getEnvironment().mJournal->end();it++) + for(std::deque::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();it++) { - std::string a = it->getText(mWindowManager.getEnvironment().mWorld->getStore()); + std::string a = it->getText(MWBase::Environment::get().getWorld()->getStore()); journal = formatText(a,journal,10,17); journal.endLine = journal.endLine +1; journal.pages.back() = journal.pages.back() + std::string("\n"); } - //std::string a = mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); + //std::string a = MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore()); //std::list journal = formatText(a,10,20,1); bool left = true; for(std::list::iterator it = journal.pages.begin(); it != journal.pages.end();it++) @@ -155,7 +155,7 @@ void MWGui::JournalWindow::open() } else { - //std::cout << mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); + //std::cout << MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore()); } } @@ -181,7 +181,7 @@ void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) if(mPageNumber < int(leftPages.size())-1) { std::string nextSound = "book page2"; - mWindowManager.getEnvironment().mSoundManager->playSound (nextSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound (nextSound, 1.0, 1.0); mPageNumber = mPageNumber + 1; displayLeftText(leftPages[mPageNumber]); displayRightText(rightPages[mPageNumber]); @@ -193,7 +193,7 @@ void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender) if(mPageNumber > 0) { std::string prevSound = "book page"; - mWindowManager.getEnvironment().mSoundManager->playSound (prevSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound (prevSound, 1.0, 1.0); mPageNumber = mPageNumber - 1; displayLeftText(leftPages[mPageNumber]); displayRightText(rightPages[mPageNumber]); diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 0e9d57c3c..e0c828fdc 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -29,6 +29,9 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : getWidget(mButton, "WorldButton"); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); + mButton->setCaption(mWindowManager.getGameSettingString("sWorld", "")); + int width = mButton->getTextSize().width + 24; + mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); MyGUI::Button* eventbox; getWidget(eventbox, "EventBox"); @@ -97,7 +100,10 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) mGlobalMap->setVisible(mGlobal); mLocalMap->setVisible(!mGlobal); - mButton->setCaption( mGlobal ? "Local" : "World" ); + mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") : + mWindowManager.getGameSettingString("sLocal", "")); + int width = mButton->getTextSize().width + 24; + mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); } void MapWindow::onPinToggled() diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 880c0bc52..275759c9f 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -69,13 +69,14 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager) setText("SpellPowerT", mWindowManager.getGameSettingString("sRaceMenu7", "Specials")); getWidget(spellPowerList, "SpellPowerList"); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); + backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); updateRaces(); @@ -91,21 +92,16 @@ void RaceDialog::setNextButtonShow(bool shown) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system. if (shown) - { - okButton->setCaption("Next"); - - // Adjust back button when next is shown - backButton->setCoord(MyGUI::IntCoord(471 - 18, 397, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(532 - 18, 397, 42 + 18, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); else - { - okButton->setCaption("OK"); - backButton->setCoord(MyGUI::IntCoord(471, 397, 53, 23)); - okButton->setCoord(MyGUI::IntCoord(532, 397, 42, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + + int okButtonWidth = okButton->getTextSize().width + 24; + int backButtonWidth = backButton->getTextSize().width + 24; + + okButton->setCoord(574 - okButtonWidth, 397, okButtonWidth, 23); + backButton->setCoord(574 - okButtonWidth - backButtonWidth - 6, 397, backButtonWidth, 23); } void RaceDialog::open() diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index cb0d9969c..7dfe514de 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -28,21 +28,25 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) getWidget(nameWidget, "NameText"); getWidget(button, "NameButton"); button->setCaption(mWindowManager.getGameSettingString("sName", "")); + adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);; getWidget(raceWidget, "RaceText"); getWidget(button, "RaceButton"); button->setCaption(mWindowManager.getGameSettingString("sRace", "")); + adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);; getWidget(classWidget, "ClassText"); getWidget(button, "ClassButton"); button->setCaption(mWindowManager.getGameSettingString("sClass", "")); + adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);; getWidget(birthSignWidget, "SignText"); getWidget(button, "SignButton"); button->setCaption(mWindowManager.getGameSettingString("sBirthSign", "")); + adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);; // Setup dynamic stats @@ -86,14 +90,20 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ReviewDialog::onWindowResize); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); + backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked); + + int backButtonWidth = backButton->getTextSize().width + 24; + int okButtonWidth = okButton->getTextSize().width + 24; + okButton->setCoord(502 - okButtonWidth, 372, okButtonWidth, 23); + backButton->setCoord(502 - okButtonWidth - backButtonWidth - 6, 372, backButtonWidth, 23); } void ReviewDialog::open() @@ -181,13 +191,14 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic { float modified = value.getModified(), base = value.getBase(); std::string text = boost::lexical_cast(std::floor(modified)); - ColorStyle style = CS_Normal; + std::string state = "normal"; if (modified > base) - style = CS_Super; + state = "increased"; else if (modified < base) - style = CS_Sub; + state = "decreased"; - setStyledText(widget, style, text); + widget->setCaption(text); + widget->_setWidgetState(state); } } @@ -210,17 +221,6 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec } } -void ReviewDialog::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value) -{ - widget->setCaption(value); - if (style == CS_Super) - widget->setTextColour(MyGUI::Colour(0, 1, 0)); - else if (style == CS_Sub) - widget->setTextColour(MyGUI::Colour(1, 0, 0)); - else - widget->setTextColour(MyGUI::Colour(1, 1, 1)); -} - void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::ImageBox* separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); @@ -240,7 +240,7 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M coord2.top += lineHeight; } -MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillValueWidget; @@ -249,7 +249,8 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st skillNameWidget->setCaption(text); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Default); - setStyledText(skillValueWidget, style, value); + skillValueWidget->setCaption(value); + skillValueWidget->_setWidgetState(state); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -295,12 +296,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId float base = stat.getBase(); float modified = stat.getModified(); - ColorStyle style = CS_Normal; + std::string state = "normal"; if (modified > base) - style = CS_Super; + state = "increased"; else if (modified < base) - style = CS_Sub; - MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); + state = "decreased"; + MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); skillWidgetMap[skillId] = widget; } } diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 588c1b6b5..76ca5a2d7 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -69,17 +69,10 @@ namespace MWGui void onBirthSignClicked(MyGUI::Widget* _sender); private: - enum ColorStyle - { - CS_Sub, - CS_Normal, - CS_Super - }; - void setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value); void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); void updateSkillArea(); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 675e5141f..b007fc1d4 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -72,6 +72,8 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) MyGUI::WindowPtr t = static_cast(mMainWidget); t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); + + setupToolTips(); } void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -109,17 +111,7 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int void StatsWindow::setPlayerName(const std::string& playerName) { static_cast(mMainWidget)->setCaption(playerName); -} - -void StatsWindow::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value) -{ - widget->setCaption(value); - if (style == CS_Super) - widget->setTextColour(MyGUI::Colour(0, 1, 0)); - else if (style == CS_Sub) - widget->setTextColour(MyGUI::Colour(1, 0, 0)); - else - widget->setTextColour(MyGUI::Colour(1, 1, 1)); + adjustWindowCaption(); } void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) @@ -138,12 +130,15 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& valueString << value.getModified(); setText (id, valueString.str()); + MyGUI::TextBox* box; + getWidget(box, id); + if (value.getModified()>value.getBase()) - setTextColor (id, 0, 1, 0); + box->_setWidgetState("increased"); else if (value.getModified()_setWidgetState("decreased"); else - setTextColor (id, 1, 1, 1); + box->_setWidgetState("normal"); break; } @@ -193,13 +188,14 @@ void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechani { float modified = value.getModified(), base = value.getBase(); std::string text = boost::lexical_cast(std::floor(modified)); - ColorStyle style = CS_Normal; + std::string state = "normal"; if (modified > base) - style = CS_Super; + state = "increased"; else if (modified < base) - style = CS_Sub; + state = "decreased"; - setStyledText(widget, style, text); + widget->setCaption(text); + widget->_setWidgetState(state); } } @@ -251,15 +247,20 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My coord2.top += lineHeight; } -MyGUI::TextBox* StatsWindow::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox *skillNameWidget, *skillValueWidget; skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->setUserString("ToolTipType", "Text"); + skillNameWidget->setUserString("ToolTipText", tooltip); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Default); - setStyledText(skillValueWidget, style, value); + skillValueWidget->setUserString("ToolTipType", "Text"); + skillValueWidget->setUserString("ToolTipText", tooltip); + skillValueWidget->setCaption(value); + skillValueWidget->_setWidgetState(state); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -305,12 +306,13 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, float base = stat.getBase(); float modified = stat.getModified(); - ColorStyle style = CS_Normal; + std::string state = "normal"; if (modified > base) - style = CS_Super; + state = "increased"; else if (modified < base) - style = CS_Sub; - MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); + state = "decreased"; + MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "", + boost::lexical_cast(static_cast(modified)), state, coord1, coord2); skillWidgetMap[skillId] = widget; } } @@ -369,8 +371,12 @@ void StatsWindow::updateSkillArea() if (!skillWidgets.empty()) addSeparator(coord1, coord2); - addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), boost::lexical_cast(static_cast(reputation)), CS_Normal, coord1, coord2); - addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), boost::lexical_cast(static_cast(bounty)), CS_Normal, coord1, coord2); + addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), + mWindowManager.getGameSettingString("sSkillsMenuReputationHelp", ""), + boost::lexical_cast(static_cast(reputation)), "normal", coord1, coord2); + addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), + mWindowManager.getGameSettingString("sCrimeHelp", ""), + boost::lexical_cast(static_cast(bounty)), "normal", coord1, coord2); clientHeight = coord1.top; updateScroller(); @@ -386,3 +392,98 @@ void StatsWindow::onPinToggled() { mWindowManager.setHMSVisibility(!mPinned); } + +void StatsWindow::setupToolTips() +{ + + const ESMS::ESMStore &store = mWindowManager.getStore(); + MyGUI::Widget* widget; + + getWidget(widget, "Attrib1"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_strength.dds"); + getWidget(widget, "AttribVal1"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_strength.dds"); + + getWidget(widget, "Attrib2"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_int.dds"); + getWidget(widget, "AttribVal2"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_int.dds"); + + getWidget(widget, "Attrib3"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds"); + getWidget(widget, "AttribVal3"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds"); + + getWidget(widget, "Attrib4"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_agility.dds"); + getWidget(widget, "AttribVal4"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_agility.dds"); + + getWidget(widget, "Attrib5"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_speed.dds"); + getWidget(widget, "AttribVal5"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_speed.dds"); + + getWidget(widget, "Attrib6"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds"); + getWidget(widget, "AttribVal6"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds"); + + getWidget(widget, "Attrib7"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_personality.dds"); + getWidget(widget, "AttribVal7"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_personality.dds"); + + getWidget(widget, "Attrib8"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_luck.dds"); + getWidget(widget, "AttribVal8"); + widget->setUserString("ToolTipType", "ImageCaptionText"); + widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str); + widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str); + widget->setUserString("ToolTipImage", "k\\attribute_luck.dds"); +} diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index f2731e545..ecbc82894 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -43,20 +43,15 @@ namespace MWGui void updateSkillArea(); private: - enum ColorStyle - { - CS_Sub, - CS_Normal, - CS_Super - }; - void setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value); void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); + void setupToolTips(); + void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onWindowResize(MyGUI::Window* window); diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index 8ac07e766..7d84a9b9f 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -12,7 +12,6 @@ TextInputDialog::TextInputDialog(WindowManager& parWindowManager) getWidget(textEdit, "TextEdit"); textEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted); - // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); @@ -25,16 +24,15 @@ void TextInputDialog::setNextButtonShow(bool shown) { MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); + if (shown) - { - okButton->setCaption("Next"); - okButton->setCoord(MyGUI::IntCoord(264 - 18, 60, 42 + 18, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); else - { - okButton->setCaption("OK"); - okButton->setCoord(MyGUI::IntCoord(264, 60, 42, 23)); - } + okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + + int okButtonWidth = okButton->getTextSize().width + 24; + + okButton->setCoord(306 - okButtonWidth, 60, okButtonWidth, 23); } void TextInputDialog::setTextLabel(const std::string &label) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp new file mode 100644 index 000000000..9d7a7ee87 --- /dev/null +++ b/apps/openmw/mwgui/tooltips.cpp @@ -0,0 +1,361 @@ +#include "tooltips.hpp" + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + +#include + +using namespace MWGui; +using namespace MyGUI; + +ToolTips::ToolTips(WindowManager* windowManager) : + Layout("openmw_tooltips.xml") + , mGameMode(true) + , mWindowManager(windowManager) + , mFullHelp(false) +{ + getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); + + mDynamicToolTipBox->setVisible(false); + + // turn off mouse focus so that getMouseFocusWidget returns the correct widget, + // even if the mouse is over the tooltip + mDynamicToolTipBox->setNeedMouseFocus(false); + mMainWidget->setNeedMouseFocus(false); +} + +void ToolTips::onFrame(float frameDuration) +{ + /// \todo Store a MWWorld::Ptr in the widget user data, retrieve it here and construct a tooltip dynamically + + MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); + mDynamicToolTipBox = mMainWidget->createWidget("HUD_Box", + IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), + Align::Stretch, "DynamicToolTipBox"); + + const IntSize &viewSize = RenderManager::getInstance().getViewSize(); + + if (!mGameMode) + { + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); + if (focus == 0) + { + mDynamicToolTipBox->setVisible(false); + return; + } + + IntSize tooltipSize; + + std::string type = focus->getUserString("ToolTipType"); + std::string text = focus->getUserString("ToolTipText"); + + ToolTipInfo info; + if (type == "") + { + mDynamicToolTipBox->setVisible(false); + return; + } + else if (type == "Text") + { + info.text = text; + } + else if (type == "CaptionText") + { + std::string caption = focus->getUserString("ToolTipCaption"); + info.caption = caption; + info.text = text; + } + else if (type == "ImageCaptionText") + { + std::string caption = focus->getUserString("ToolTipCaption"); + std::string image = focus->getUserString("ToolTipImage"); + std::string sizeString = focus->getUserString("ToolTipImageSize"); + + info.text = text; + info.caption = caption; + info.icon = image; + } + tooltipSize = createToolTip(info); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + mDynamicToolTipBox->setVisible(true); + } + else + { + if (!mFocusObject.isEmpty()) + { + IntSize tooltipSize = getToolTipViaPtr(); + + // adjust tooltip size to fit its content, position it above the crosshair + /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind) + setCoord(viewSize.width/2 - (tooltipSize.width)/2.f, + viewSize.height/2 - (tooltipSize.height) - 32, + tooltipSize.width, + tooltipSize.height); + } + else + mDynamicToolTipBox->setVisible(false); + } +} + +void ToolTips::enterGameMode() +{ + mGameMode = true; +} + +void ToolTips::enterGuiMode() +{ + mGameMode = false; +} + +void ToolTips::setFocusObject(const MWWorld::Ptr& focus) +{ + mFocusObject = focus; +} + +IntSize ToolTips::getToolTipViaPtr () +{ + // this the maximum width of the tooltip before it starts word-wrapping + setCoord(0, 0, 300, 300); + + IntSize tooltipSize; + + const MWWorld::Class& object = MWWorld::Class::get (mFocusObject); + if (!object.hasToolTip(mFocusObject)) + { + mDynamicToolTipBox->setVisible(false); + } + else + { + mDynamicToolTipBox->setVisible(true); + + ToolTipInfo info = object.getToolTipInfo(mFocusObject); + tooltipSize = createToolTip(info); + } + + return tooltipSize; +} + +void ToolTips::findImageExtension(std::string& image) +{ + int len = image.size(); + if (len < 4) return; + + if (!Ogre::ResourceGroupManager::getSingleton().resourceExists(Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, image)) + { + // Change texture extension to .dds + image[len-3] = 'd'; + image[len-2] = 'd'; + image[len-1] = 's'; + } +} + +IntSize ToolTips::createToolTip(const ToolTipInfo& info) +{ + std::string caption = info.caption; + std::string image = info.icon; + int imageSize = (image != "") ? 32 : 0; + std::string text = info.text; + + // remove the first newline (easier this way) + if (text.size() > 0 && text[0] == '\n') + text.erase(0, 1); + + const ESM::Enchantment* enchant; + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + if (info.enchant != "") + { + enchant = store.enchants.search(info.enchant); + if (enchant->data.type == ESM::Enchantment::CastOnce) + text += "\n" + store.gameSettings.search("sItemCastOnce")->str; + else if (enchant->data.type == ESM::Enchantment::WhenStrikes) + text += "\n" + store.gameSettings.search("sItemCastWhenStrikes")->str; + else if (enchant->data.type == ESM::Enchantment::WhenUsed) + text += "\n" + store.gameSettings.search("sItemCastWhenUsed")->str; + else if (enchant->data.type == ESM::Enchantment::ConstantEffect) + text += "\n" + store.gameSettings.search("sItemCastConstant")->str; + } + + // this the maximum width of the tooltip before it starts word-wrapping + setCoord(0, 0, 300, 300); + + const IntPoint padding(8, 8); + + const int imageCaptionHPadding = (caption != "" ? 8 : 0); + const int imageCaptionVPadding = (caption != "" ? 4 : 0); + + std::string realImage = "icons\\" + image; + findImageExtension(realImage); + + EditBox* captionWidget = mDynamicToolTipBox->createWidget("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption"); + captionWidget->setProperty("Static", "true"); + captionWidget->setCaption(caption); + IntSize captionSize = captionWidget->getTextSize(); + + int captionHeight = std::max(caption != "" ? captionSize.height : 0, imageSize); + + EditBox* textWidget = mDynamicToolTipBox->createWidget("SandText", IntCoord(0, captionHeight+imageCaptionVPadding, 300, 300-captionHeight-imageCaptionVPadding), Align::Stretch, "ToolTipText"); + textWidget->setProperty("Static", "true"); + textWidget->setProperty("MultiLine", "true"); + textWidget->setProperty("WordWrap", "true"); + textWidget->setCaption(text); + textWidget->setTextAlign(Align::HCenter | Align::Top); + IntSize textSize = textWidget->getTextSize(); + + captionSize += IntSize(imageSize, 0); // adjust for image + IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)), + ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight ); + + if (info.effects != 0) + { + Widget* effectArea = mDynamicToolTipBox->createWidget("", + IntCoord(0, totalSize.height, 300, 300-totalSize.height), + Align::Stretch, "ToolTipEffectArea"); + + IntCoord coord(0, 6, totalSize.width, 24); + + /** + * \todo + * the various potion effects should appear in the tooltip depending if the player + * has enough skill in alchemy to know about the effects of this potion. + */ + + Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget + ("MW_StatName", coord, Align::Default, "ToolTipEffectsWidget"); + effectsWidget->setWindowManager(mWindowManager); + effectsWidget->setEffectList(info.effects); + + std::vector effectItems; + effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_Potion); + totalSize.height += coord.top-6; + totalSize.width = std::max(totalSize.width, coord.width); + } + + if (info.enchant != "") + { + Widget* enchantArea = mDynamicToolTipBox->createWidget("", + IntCoord(0, totalSize.height, 300, 300-totalSize.height), + Align::Stretch, "ToolTipEnchantArea"); + + IntCoord coord(0, 6, totalSize.width, 24); + + Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget + ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); + enchantWidget->setWindowManager(mWindowManager); + enchantWidget->setEffectList(&enchant->effects); + + std::vector enchantEffectItems; + int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0; + enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, true, flag); + totalSize.height += coord.top-6; + totalSize.width = std::max(totalSize.width, coord.width); + + if (enchant->data.type == ESM::Enchantment::WhenStrikes + || enchant->data.type == ESM::Enchantment::WhenUsed) + { + /// \todo store the current enchantment charge somewhere + int charge = enchant->data.charge; + + const int chargeWidth = 204; + + TextBox* chargeText = enchantArea->createWidget("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText"); + chargeText->setCaption(store.gameSettings.search("sCharges")->str); + chargeText->setProperty("Static", "true"); + const int chargeTextWidth = chargeText->getTextSize().width + 5; + + const int chargeAndTextWidth = chargeWidth + chargeTextWidth; + chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18); + + IntCoord chargeCoord; + if (totalSize.width < chargeWidth) + { + totalSize.width = chargeWidth; + chargeCoord = IntCoord(0, coord.top+6, chargeWidth, 18); + } + else + { + chargeCoord = IntCoord((totalSize.width - chargeAndTextWidth)/2 + chargeTextWidth, coord.top+6, chargeWidth, 18); + } + Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget + ("MW_ChargeBar", chargeCoord, Align::Default, "ToolTipEnchantCharge"); + chargeWidget->setValue(charge, charge); + totalSize.height += 24; + } + } + + captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, + (captionHeight-captionSize.height)/2, + captionSize.width-imageSize, + captionSize.height); + + captionWidget->setPosition (captionWidget->getPosition() + padding); + textWidget->setPosition (textWidget->getPosition() + IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter + + if (image != "") + { + ImageBox* imageWidget = mDynamicToolTipBox->createWidget("ImageBox", + IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize), + Align::Left | Align::Top, "ToolTipImage"); + imageWidget->setImageTexture(realImage); + imageWidget->setPosition (imageWidget->getPosition() + padding); + } + + totalSize += IntSize(padding.left*2, padding.top*2); + + return totalSize; +} + +std::string ToolTips::toString(const float value) +{ + std::ostringstream stream; + stream << std::setprecision(3) << value; + return stream.str(); +} + +std::string ToolTips::toString(const int value) +{ + std::ostringstream stream; + stream << value; + return stream.str(); +} + +std::string ToolTips::getValueString(const int value, const std::string& prefix) +{ + if (value == 0) + return ""; + else + return "\n" + prefix + ": " + toString(value); +} + +std::string ToolTips::getMiscString(const std::string& text, const std::string& prefix) +{ + if (text == "") + return ""; + else + return "\n" + prefix + ": " + text; +} + +void ToolTips::toggleFullHelp() +{ + mFullHelp = !mFullHelp; +} + +bool ToolTips::getFullHelp() const +{ + return mFullHelp; +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp new file mode 100644 index 000000000..fafe471a5 --- /dev/null +++ b/apps/openmw/mwgui/tooltips.hpp @@ -0,0 +1,76 @@ + +#ifndef MWGUI_TOOLTIPS_H +#define MWGUI_TOOLTIPS_H + +#include +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + class WindowManager; + + // Info about tooltip that is supplied by the MWWorld::Class object + struct ToolTipInfo + { + public: + ToolTipInfo() : + effects(0) + { + }; + + std::string caption; + std::string text; + std::string icon; + + // enchantment (for cloth, armor, weapons) + std::string enchant; + + // effects (for potions, ingredients) + const ESM::EffectList* effects; + }; + + class ToolTips : public OEngine::GUI::Layout + { + public: + ToolTips(WindowManager* windowManager); + + void onFrame(float frameDuration); + + void enterGameMode(); + void enterGuiMode(); + + void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) + bool getFullHelp() const; + + void setFocusObject(const MWWorld::Ptr& focus); + + static std::string getValueString(const int value, const std::string& prefix); + ///< @return "prefix: value" or "" if value is 0 + + static std::string getMiscString(const std::string& text, const std::string& prefix); + ///< @return "prefix: text" or "" if text is empty + + static std::string toString(const float value); + static std::string toString(const int value); + + private: + MyGUI::Widget* mDynamicToolTipBox; + + WindowManager* mWindowManager; + + MWWorld::Ptr mFocusObject; + + void findImageExtension(std::string& image); + + MyGUI::IntSize getToolTipViaPtr (); + ///< @return requested tooltip size + + MyGUI::IntSize createToolTip(const ToolTipInfo& info); + ///< @return requested tooltip size + + bool mGameMode; + + bool mFullHelp; + }; +} +#endif diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 74603aaf1..0422bb0e2 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -222,7 +222,7 @@ void MWSpell::setSpellId(const std::string &spellId) updateWidgets(); } -void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord) +void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags) { const ESMS::ESMStore &store = mWindowManager->getStore(); const ESM::Spell *spell = store.spells.search(id); @@ -234,9 +234,11 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI: { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); + effect->setFlags(flags); effect->setSpellEffect(*it); effects.push_back(effect); coord.top += effect->getHeight(); + coord.width = std::max(coord.width, effect->getRequestedWidth()); } } @@ -264,12 +266,82 @@ MWSpell::~MWSpell() { } +/* MWEffectList */ + +MWEffectList::MWEffectList() + : mWindowManager(nullptr) + , mEffectList(0) +{ +} + +void MWEffectList::setEffectList(const ESM::EffectList* list) +{ + mEffectList = list; + updateWidgets(); +} + +void MWEffectList::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags) +{ + // We don't know the width of all the elements beforehand, so we do it in + // 2 steps: first, create all widgets and check their width + MWSpellEffectPtr effect = nullptr; + std::vector::const_iterator end = mEffectList->list.end(); + int maxwidth = coord.width; + for (std::vector::const_iterator it = mEffectList->list.begin(); it != end; ++it) + { + effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); + effect->setWindowManager(mWindowManager); + effect->setFlags(flags); + effect->setSpellEffect(*it); + effects.push_back(effect); + + if (effect->getRequestedWidth() > maxwidth) + maxwidth = effect->getRequestedWidth(); + + coord.top += effect->getHeight(); + } + + // then adjust the size for all widgets + for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) + { + effect = static_cast(*it); + bool needcenter = center && (maxwidth > effect->getRequestedWidth()); + int diff = maxwidth - effect->getRequestedWidth(); + if (needcenter) + { + effect->setCoord(diff/2, effect->getCoord().top, effect->getRequestedWidth(), effect->getCoord().height); + } + else + { + effect->setCoord(0, effect->getCoord().top, effect->getRequestedWidth(), effect->getCoord().height); + } + } + + // inform the parent about width + coord.width = maxwidth; +} + +void MWEffectList::updateWidgets() +{ +} + +void MWEffectList::initialiseOverride() +{ + Base::initialiseOverride(); +} + +MWEffectList::~MWEffectList() +{ +} + /* MWSpellEffect */ MWSpellEffect::MWSpellEffect() : mWindowManager(nullptr) , imageWidget(nullptr) , textWidget(nullptr) + , mRequestedWidth(0) + , mFlags(0) { } @@ -290,8 +362,14 @@ void MWSpellEffect::updateWidgets() { if (magicEffect) { - // TODO: Get name of effect from GMST - std::string spellLine = ""; + std::string pt = mWindowManager->getGameSettingString("spoint", ""); + std::string pts = mWindowManager->getGameSettingString("spoints", ""); + std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; + std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); + std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); + + std::string effectIDStr = effectIDToString(effect.effectID); + std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); if (effect.skill >= 0 && effect.skill < ESM::Skill::Length) { spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], ""); @@ -310,26 +388,40 @@ void MWSpellEffect::updateWidgets() }; spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], ""); } - if (effect.magnMin >= 0 || effect.magnMax >= 0) + + if ((effect.magnMin >= 0 || effect.magnMax >= 0) && effectHasMagnitude(effectIDStr)) { if (effect.magnMin == effect.magnMax) - spellLine += " " + boost::lexical_cast(effect.magnMin) + " pts"; + spellLine += " " + boost::lexical_cast(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts); else { - spellLine += " " + boost::lexical_cast(effect.magnMin) + " to " + boost::lexical_cast(effect.magnMin) + " pts"; + spellLine += " " + boost::lexical_cast(effect.magnMin) + to + boost::lexical_cast(effect.magnMax) + " " + pts; } } - if (effect.duration >= 0) + + // constant effects have no duration and no target + if (!(mFlags & MWEffectList::EF_Constant)) { - spellLine += " for " + boost::lexical_cast(effect.duration) + " secs"; + if (effect.duration >= 0 && effectHasDuration(effectIDStr)) + { + spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(effect.duration) + ((effect.duration == 1) ? sec : secs); + } + + // potions have no target + if (!(mFlags & MWEffectList::EF_Potion)) + { + std::string on = mWindowManager->getGameSettingString("sonword", ""); + if (effect.range == ESM::RT_Self) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); + else if (effect.range == ESM::RT_Touch) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); + else if (effect.range == ESM::RT_Target) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); + } } - if (effect.range == ESM::RT_Self) - spellLine += " on Self"; - else if (effect.range == ESM::RT_Touch) - spellLine += " on Touch"; - else if (effect.range == ESM::RT_Target) - spellLine += " on Target"; + static_cast(textWidget)->setCaption(spellLine); + mRequestedWidth = textWidget->getTextSize().width + 24; } else static_cast(textWidget)->setCaption(""); @@ -342,6 +434,249 @@ void MWSpellEffect::updateWidgets() } } +std::string MWSpellEffect::effectIDToString(const short effectID) +{ + // Map effect ID to GMST name + // http://www.uesp.net/morrow/hints/mweffects.shtml + std::map names; + names[85] ="sEffectAbsorbAttribute"; + names[88] ="sEffectAbsorbFatigue"; + names[86] ="sEffectAbsorbHealth"; + names[87] ="sEffectAbsorbSpellPoints"; + names[89] ="sEffectAbsorbSkill"; + names[63] ="sEffectAlmsiviIntervention"; + names[47] ="sEffectBlind"; + names[123] ="sEffectBoundBattleAxe"; + names[129] ="sEffectBoundBoots"; + names[127] ="sEffectBoundCuirass"; + names[120] ="sEffectBoundDagger"; + names[131] ="sEffectBoundGloves"; + names[128] ="sEffectBoundHelm"; + names[125] ="sEffectBoundLongbow"; + names[121] ="sEffectBoundLongsword"; + names[122] ="sEffectBoundMace"; + names[130] ="sEffectBoundShield"; + names[124] ="sEffectBoundSpear"; + names[7] ="sEffectBurden"; + names[50] ="sEffectCalmCreature"; + names[49] ="sEffectCalmHumanoid"; + names[40] ="sEffectChameleon"; + names[44] ="sEffectCharm"; + names[118] ="sEffectCommandCreatures"; + names[119] ="sEffectCommandHumanoids"; + names[132] ="sEffectCorpus"; // NB this typo. (bethesda made it) + names[70] ="sEffectCureBlightDisease"; + names[69] ="sEffectCureCommonDisease"; + names[71] ="sEffectCureCorprusDisease"; + names[73] ="sEffectCureParalyzation"; + names[72] ="sEffectCurePoison"; + names[22] ="sEffectDamageAttribute"; + names[25] ="sEffectDamageFatigue"; + names[23] ="sEffectDamageHealth"; + names[24] ="sEffectDamageMagicka"; + names[26] ="sEffectDamageSkill"; + names[54] ="sEffectDemoralizeCreature"; + names[53] ="sEffectDemoralizeHumanoid"; + names[64] ="sEffectDetectAnimal"; + names[65] ="sEffectDetectEnchantment"; + names[66] ="sEffectDetectKey"; + names[38] ="sEffectDisintegrateArmor"; + names[37] ="sEffectDisintegrateWeapon"; + names[57] ="sEffectDispel"; + names[62] ="sEffectDivineIntervention"; + names[17] ="sEffectDrainAttribute"; + names[20] ="sEffectDrainFatigue"; + names[18] ="sEffectDrainHealth"; + names[19] ="sEffectDrainSpellpoints"; + names[21] ="sEffectDrainSkill"; + names[8] ="sEffectFeather"; + names[14] ="sEffectFireDamage"; + names[4] ="sEffectFireShield"; + names[117] ="sEffectFortifyAttackBonus"; + names[79] ="sEffectFortifyAttribute"; + names[82] ="sEffectFortifyFatigue"; + names[80] ="sEffectFortifyHealth"; + names[81] ="sEffectFortifySpellpoints"; + names[84] ="sEffectFortifyMagickaMultiplier"; + names[83] ="sEffectFortifySkill"; + names[52] ="sEffectFrenzyCreature"; + names[51] ="sEffectFrenzyHumanoid"; + names[16] ="sEffectFrostDamage"; + names[6] ="sEffectFrostShield"; + names[39] ="sEffectInvisibility"; + names[9] ="sEffectJump"; + names[10] ="sEffectLevitate"; + names[41] ="sEffectLight"; + names[5] ="sEffectLightningShield"; + names[12] ="sEffectLock"; + names[60] ="sEffectMark"; + names[43] ="sEffectNightEye"; + names[13] ="sEffectOpen"; + names[45] ="sEffectParalyze"; + names[27] ="sEffectPoison"; + names[56] ="sEffectRallyCreature"; + names[55] ="sEffectRallyHumanoid"; + names[61] ="sEffectRecall"; + names[68] ="sEffectReflect"; + names[100] ="sEffectRemoveCurse"; + names[95] ="sEffectResistBlightDisease"; + names[94] ="sEffectResistCommonDisease"; + names[96] ="sEffectResistCorprusDisease"; + names[90] ="sEffectResistFire"; + names[91] ="sEffectResistFrost"; + names[93] ="sEffectResistMagicka"; + names[98] ="sEffectResistNormalWeapons"; + names[99] ="sEffectResistParalysis"; + names[97] ="sEffectResistPoison"; + names[92] ="sEffectResistShock"; + names[74] ="sEffectRestoreAttribute"; + names[77] ="sEffectRestoreFatigue"; + names[75] ="sEffectRestoreHealth"; + names[76] ="sEffectRestoreSpellPoints"; + names[78] ="sEffectRestoreSkill"; + names[42] ="sEffectSanctuary"; + names[3] ="sEffectShield"; + names[15] ="sEffectShockDamage"; + names[46] ="sEffectSilence"; + names[11] ="sEffectSlowFall"; + names[58] ="sEffectSoultrap"; + names[48] ="sEffectSound"; + names[67] ="sEffectSpellAbsorption"; + names[136] ="sEffectStuntedMagicka"; + names[106] ="sEffectSummonAncestralGhost"; + names[110] ="sEffectSummonBonelord"; + names[108] ="sEffectSummonLeastBonewalker"; + names[134] ="sEffectSummonCenturionSphere"; + names[103] ="sEffectSummonClannfear"; + names[104] ="sEffectSummonDaedroth"; + names[105] ="sEffectSummonDremora"; + names[114] ="sEffectSummonFlameAtronach"; + names[115] ="sEffectSummonFrostAtronach"; + names[113] ="sEffectSummonGoldenSaint"; + names[109] ="sEffectSummonGreaterBonewalker"; + names[112] ="sEffectSummonHunger"; + names[102] ="sEffectSummonScamp"; + names[107] ="sEffectSummonSkeletalMinion"; + names[116] ="sEffectSummonStormAtronach"; + names[111] ="sEffectSummonWingedTwilight"; + names[135] ="sEffectSunDamage"; + names[1] ="sEffectSwiftSwim"; + names[59] ="sEffectTelekinesis"; + names[101] ="sEffectTurnUndead"; + names[133] ="sEffectVampirism"; + names[0] ="sEffectWaterBreathing"; + names[2] ="sEffectWaterWalking"; + names[33] ="sEffectWeaknesstoBlightDisease"; + names[32] ="sEffectWeaknesstoCommonDisease"; + names[34] ="sEffectWeaknesstoCorprusDisease"; + names[28] ="sEffectWeaknesstoFire"; + names[29] ="sEffectWeaknesstoFrost"; + names[31] ="sEffectWeaknesstoMagicka"; + names[36] ="sEffectWeaknesstoNormalWeapons"; + names[35] ="sEffectWeaknesstoPoison"; + names[30] ="sEffectWeaknesstoShock"; + + // bloodmoon + names[138] ="sEffectSummonCreature01"; + names[139] ="sEffectSummonCreature02"; + names[140] ="sEffectSummonCreature03"; + names[141] ="sEffectSummonCreature04"; + names[142] ="sEffectSummonCreature05"; + + // tribunal + names[137] ="sEffectSummonFabricant"; + + assert(names.find(effectID) != names.end() && "Unimplemented effect type"); + + return names[effectID]; +} + +bool MWSpellEffect::effectHasDuration(const std::string& effect) +{ + // lists effects that have no duration (e.g. open lock) + std::vector effectsWithoutDuration; + effectsWithoutDuration.push_back("sEffectOpen"); + effectsWithoutDuration.push_back("sEffectLock"); + effectsWithoutDuration.push_back("sEffectDispel"); + effectsWithoutDuration.push_back("sEffectSunDamage"); + effectsWithoutDuration.push_back("sEffectCorpus"); + effectsWithoutDuration.push_back("sEffectVampirism"); + effectsWithoutDuration.push_back("sEffectMark"); + effectsWithoutDuration.push_back("sEffectRecall"); + effectsWithoutDuration.push_back("sEffectDivineIntervention"); + effectsWithoutDuration.push_back("sEffectAlmsiviIntervention"); + effectsWithoutDuration.push_back("sEffectCureCommonDisease"); + effectsWithoutDuration.push_back("sEffectCureBlightDisease"); + effectsWithoutDuration.push_back("sEffectCureCorprusDisease"); + effectsWithoutDuration.push_back("sEffectCurePoison"); + effectsWithoutDuration.push_back("sEffectCureParalyzation"); + effectsWithoutDuration.push_back("sEffectRemoveCurse"); + effectsWithoutDuration.push_back("sEffectRestoreAttribute"); + + return (std::find(effectsWithoutDuration.begin(), effectsWithoutDuration.end(), effect) == effectsWithoutDuration.end()); +} + +bool MWSpellEffect::effectHasMagnitude(const std::string& effect) +{ + // lists effects that have no magnitude (e.g. invisiblity) + std::vector effectsWithoutMagnitude; + effectsWithoutMagnitude.push_back("sEffectInvisibility"); + effectsWithoutMagnitude.push_back("sEffectStuntedMagicka"); + effectsWithoutMagnitude.push_back("sEffectParalyze"); + effectsWithoutMagnitude.push_back("sEffectSoultrap"); + effectsWithoutMagnitude.push_back("sEffectSilence"); + effectsWithoutMagnitude.push_back("sEffectParalyze"); + effectsWithoutMagnitude.push_back("sEffectInvisibility"); + effectsWithoutMagnitude.push_back("sEffectWaterWalking"); + effectsWithoutMagnitude.push_back("sEffectWaterBreathing"); + effectsWithoutMagnitude.push_back("sEffectSummonScamp"); + effectsWithoutMagnitude.push_back("sEffectSummonClannfear"); + effectsWithoutMagnitude.push_back("sEffectSummonDaedroth"); + effectsWithoutMagnitude.push_back("sEffectSummonDremora"); + effectsWithoutMagnitude.push_back("sEffectSummonAncestralGhost"); + effectsWithoutMagnitude.push_back("sEffectSummonSkeletalMinion"); + effectsWithoutMagnitude.push_back("sEffectSummonBonewalker"); + effectsWithoutMagnitude.push_back("sEffectSummonGreaterBonewalker"); + effectsWithoutMagnitude.push_back("sEffectSummonBonelord"); + effectsWithoutMagnitude.push_back("sEffectSummonWingedTwilight"); + effectsWithoutMagnitude.push_back("sEffectSummonHunger"); + effectsWithoutMagnitude.push_back("sEffectSummonGoldenSaint"); + effectsWithoutMagnitude.push_back("sEffectSummonFlameAtronach"); + effectsWithoutMagnitude.push_back("sEffectSummonFrostAtronach"); + effectsWithoutMagnitude.push_back("sEffectSummonStormAtronach"); + effectsWithoutMagnitude.push_back("sEffectSummonCenturionSphere"); + effectsWithoutMagnitude.push_back("sEffectBoundDagger"); + effectsWithoutMagnitude.push_back("sEffectBoundLongsword"); + effectsWithoutMagnitude.push_back("sEffectBoundMace"); + effectsWithoutMagnitude.push_back("sEffectBoundBattleAxe"); + effectsWithoutMagnitude.push_back("sEffectBoundSpear"); + effectsWithoutMagnitude.push_back("sEffectBoundLongbow"); + effectsWithoutMagnitude.push_back("sEffectBoundCuirass"); + effectsWithoutMagnitude.push_back("sEffectBoundHelm"); + effectsWithoutMagnitude.push_back("sEffectBoundBoots"); + effectsWithoutMagnitude.push_back("sEffectBoundShield"); + effectsWithoutMagnitude.push_back("sEffectBoundGloves"); + effectsWithoutMagnitude.push_back("sEffectStuntedMagicka"); + effectsWithoutMagnitude.push_back("sEffectMark"); + effectsWithoutMagnitude.push_back("sEffectRecall"); + effectsWithoutMagnitude.push_back("sEffectDivineIntervention"); + effectsWithoutMagnitude.push_back("sEffectAlmsiviIntervention"); + effectsWithoutMagnitude.push_back("sEffectCureCommonDisease"); + effectsWithoutMagnitude.push_back("sEffectCureBlightDisease"); + effectsWithoutMagnitude.push_back("sEffectCureCorprusDisease"); + effectsWithoutMagnitude.push_back("sEffectCurePoison"); + effectsWithoutMagnitude.push_back("sEffectCureParalyzation"); + effectsWithoutMagnitude.push_back("sEffectRemoveCurse"); + effectsWithoutMagnitude.push_back("sEffectSummonCreature01"); + effectsWithoutMagnitude.push_back("sEffectSummonCreature02"); + effectsWithoutMagnitude.push_back("sEffectSummonCreature03"); + effectsWithoutMagnitude.push_back("sEffectSummonCreature04"); + effectsWithoutMagnitude.push_back("sEffectSummonCreature05"); + effectsWithoutMagnitude.push_back("sEffectSummonFabricant"); + + return (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effect) == effectsWithoutMagnitude.end()); +} + MWSpellEffect::~MWSpellEffect() { } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index a7916285e..74da7fc93 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -119,14 +119,22 @@ namespace MWGui void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellId(const std::string &id); - void createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord); + + /** + * @param vector to store the created effect widgets + * @param parent widget + * @param coordinates to use, will be expanded if more space is needed + * @param spell category, if this is 0, this means the spell effects are permanent and won't display e.g. duration + * @param various flags, see MWEffectList::EffectFlags + */ + void createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags); const std::string &getSpellId() const { return id; } protected: virtual ~MWSpell(); - virtual void initialiseOverride(); + virtual void initialiseOverride(); private: void updateWidgets(); @@ -137,6 +145,45 @@ namespace MWGui }; typedef MWSpell* MWSpellPtr; + class MYGUI_EXPORT MWEffectList : public Widget + { + MYGUI_RTTI_DERIVED( MWEffectList ); + public: + MWEffectList(); + + typedef MWMechanics::Stat EnchantmentValue; + + enum EffectFlags + { + EF_Potion = 0x01, // potions have no target (target is always the player) + EF_Constant = 0x02 // constant effect means that duration will not be displayed + }; + + void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } + void setEffectList(const ESM::EffectList* list); + + /** + * @param vector to store the created effect widgets + * @param parent widget + * @param coordinates to use, will be expanded if more space is needed + * @param center the effect widgets horizontally + * @param various flags, see MWEffectList::EffectFlags + */ + void createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags); + + protected: + virtual ~MWEffectList(); + + virtual void initialiseOverride(); + + private: + void updateWidgets(); + + WindowManager* mWindowManager; + const ESM::EffectList* mEffectList; + }; + typedef MWEffectList* MWEffectListPtr; + class MYGUI_EXPORT MWSpellEffect : public Widget { MYGUI_RTTI_DERIVED( MWSpellEffect ); @@ -147,9 +194,16 @@ namespace MWGui void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellEffect(SpellEffectValue value); + void setFlags(int flags) { mFlags = flags; } + + std::string effectIDToString(const short effectID); + bool effectHasMagnitude (const std::string& effect); + bool effectHasDuration (const std::string& effect); const SpellEffectValue &getSpellEffect() const { return effect; } + int getRequestedWidth() const { return mRequestedWidth; } + protected: virtual ~MWSpellEffect(); @@ -161,8 +215,10 @@ namespace MWGui WindowManager* mWindowManager; SpellEffectValue effect; + int mFlags; MyGUI::ImageBox* imageWidget; MyGUI::TextBox* textWidget; + int mRequestedWidth; }; typedef MWSpellEffect* MWSpellEffectPtr; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index e72f635bf..ccd51d9db 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -10,10 +10,13 @@ #include "container.hpp" #include "inventorywindow.hpp" #include "itemwidget.hpp" +#include "tooltips.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" +#include "../mwbase/environment.hpp" + #include "console.hpp" #include "journalwindow.hpp" #include "charactercreation.hpp" @@ -26,14 +29,14 @@ using namespace MWGui; -WindowManager::WindowManager(MWWorld::Environment& environment, +WindowManager::WindowManager( const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath) : mGuiManager(NULL) - , environment(environment) , hud(NULL) , map(NULL) , menu(NULL) , stats(NULL) + , mToolTips(NULL) , mMessageBoxManager(NULL) , console(NULL) , mJournal(NULL) @@ -89,17 +92,18 @@ WindowManager::WindowManager(MWWorld::Environment& environment, menu = new MainMenu(w,h); map = new MapWindow(*this); stats = new StatsWindow(*this); - console = new Console(w,h, environment, extensions); + console = new Console(w,h, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); mDialogueWindow = new DialogueWindow(*this,environment); mContainerWindow = new ContainerWindow(*this,environment,mDragAndDrop); mInventoryWindow = new InventoryWindow(*this,environment,mDragAndDrop); + mToolTips = new ToolTips(this); // The HUD is always on hud->setVisible(true); - mCharGen = new CharacterCreation(this, &environment); + mCharGen = new CharacterCreation(this); // Setup player stats for (int i = 0; i < ESM::Attribute::Length; ++i) @@ -115,6 +119,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); @@ -135,6 +140,7 @@ WindowManager::~WindowManager() delete mDialogueWindow; delete mContainerWindow; delete mInventoryWindow; + delete mToolTips; delete mCharGen; delete mDragAndDrop; @@ -160,7 +166,7 @@ void WindowManager::update() if (needModeChange) { needModeChange = false; - environment.mInputManager->setGuiMode(nextMode); + MWBase::Environment::get().getInputManager()->setGuiMode(nextMode); nextMode = GM_Game; } if (showFPSLevel > 0) @@ -171,11 +177,6 @@ void WindowManager::update() } } -MWWorld::Environment& WindowManager::getEnvironment() -{ - return environment; -} - void WindowManager::setNextMode(GuiMode newMode) { nextMode = newMode; @@ -184,7 +185,7 @@ void WindowManager::setNextMode(GuiMode newMode) void WindowManager::setGuiMode(GuiMode newMode) { - environment.mInputManager->setGuiMode(newMode); + MWBase::Environment::get().getInputManager()->setGuiMode(newMode); } void WindowManager::updateVisible() @@ -202,6 +203,11 @@ void WindowManager::updateVisible() // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); + if (mode == GM_Game) + mToolTips->enterGameMode(); + else + mToolTips->enterGuiMode(); + switch(mode) { case GM_Game: // If in game mode, don't show anything. @@ -414,7 +420,7 @@ int WindowManager::readPressedButton () const std::string &WindowManager::getGameSettingString(const std::string &id, const std::string &default_) { - const ESM::GameSetting *setting = environment.mWorld->getStore().gameSettings.search(id); + const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(id); if (setting && setting->type == ESM::VT_String) return setting->str; return default_; @@ -436,11 +442,12 @@ void WindowManager::onFrame (float frameDuration) mMessageBoxManager->onFrame(frameDuration); mInventoryWindow->Update(); mContainerWindow->Update(); + mToolTips->onFrame(frameDuration); } const ESMS::ESMStore& WindowManager::getStore() const { - return environment.mWorld->getStore(); + return MWBase::Environment::get().getWorld()->getStore(); } void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) @@ -451,7 +458,10 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) if (cell->cell->name != "") name = cell->cell->name; else - name = cell->cell->region; + { + const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->region); + name = region->name; + } map->setCellName( name ); @@ -510,3 +520,18 @@ int WindowManager::toggleFps() Settings::Manager::setInt("fps", "HUD", showFPSLevel); return showFPSLevel; } + +void WindowManager::setFocusObject(const MWWorld::Ptr& focus) +{ + mToolTips->setFocusObject(focus); +} + +void WindowManager::toggleFullHelp() +{ + mToolTips->toggleFullHelp(); +} + +bool WindowManager::getFullHelp() const +{ + return mToolTips->getFullHelp(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index a666b5854..9a06b3760 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -34,7 +34,6 @@ namespace Compiler namespace MWWorld { - class Environment; class World; } @@ -65,6 +64,7 @@ namespace MWGui class ContainerWindow; class DragAndDrop; class InventoryWindow; + class ToolTips; class TextInputDialog; class InfoBoxDialog; class DialogueWindow; @@ -85,7 +85,7 @@ namespace MWGui typedef std::vector FactionList; typedef std::vector SkillList; - WindowManager(MWWorld::Environment& environment, const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); + WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); virtual ~WindowManager(); void setGuiMode(GuiMode newMode); @@ -97,8 +97,6 @@ namespace MWGui */ void update(); - MWWorld::Environment& getEnvironment(); - void setMode(GuiMode newMode) { if (newMode==GM_Inventory && allowed==GW_None) @@ -161,7 +159,11 @@ namespace MWGui 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 toggleFogOfWar(); + void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) + bool getFullHelp() const; int toggleFps(); ///< toggle fps display @return resulting fps level @@ -196,10 +198,10 @@ namespace MWGui private: OEngine::GUI::MyGUIManager *mGuiManager; - MWWorld::Environment& environment; HUD *hud; MapWindow *map; MainMenu *menu; + ToolTips *mToolTips; StatsWindow *stats; MessageBoxManager *mMessageBoxManager; Console *console; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 9b5a9ae30..7a56a0adf 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -60,6 +60,7 @@ namespace MWInput A_CycleWeaponRight, A_ToggleSneak, //Toggles Sneak, add Push-Sneak later A_ToggleWalk, //Toggle Walking/Running + A_Crouch, A_QuickSave, A_QuickLoad, @@ -97,34 +98,36 @@ namespace MWInput void toggleSpell() { - DrawState state = player.getDrawState(); - if(state == DrawState_Weapon || state == DrawState_Nothing) - { - player.setDrawState(DrawState_Spell); - std::cout << "Player has now readied his hands for spellcasting!\n"; - } - else - { - player.setDrawState(DrawState_Nothing); - std::cout << "Player does not have any kind of attack ready now.\n"; - } + if (windows.isGuiMode()) return; + DrawState state = player.getDrawState(); + if (state == DrawState_Weapon || state == DrawState_Nothing) + { + player.setDrawState(DrawState_Spell); + std::cout << "Player has now readied his hands for spellcasting!\n"; + } + else + { + player.setDrawState(DrawState_Nothing); + std::cout << "Player does not have any kind of attack ready now.\n"; + } } void toggleWeapon() { - DrawState state = player.getDrawState(); - if(state == DrawState_Spell || state == DrawState_Nothing) - { - player.setDrawState(DrawState_Weapon); - std::cout << "Player is now drawing his weapon.\n"; - } - else - { - player.setDrawState(DrawState_Nothing); - std::cout << "Player does not have any kind of attack ready now.\n"; - } + if (windows.isGuiMode()) return; + DrawState state = player.getDrawState(); + if (state == DrawState_Spell || state == DrawState_Nothing) + { + player.setDrawState(DrawState_Weapon); + std::cout << "Player is now drawing his weapon.\n"; + } + else + { + player.setDrawState(DrawState_Nothing); + std::cout << "Player does not have any kind of attack ready now.\n"; + } } void screenshot() @@ -184,11 +187,13 @@ namespace MWInput void toggleAutoMove() { + if (windows.isGuiMode()) return; player.setAutoMove (!player.getAutoMove()); } void toggleWalking() { + if (windows.isGuiMode()) return; player.toggleRunning(); } @@ -306,6 +311,9 @@ namespace MWInput 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); } //NOTE: Used to check for movement keys @@ -352,6 +360,13 @@ namespace MWInput } else player.setForwardBackward (0); + + if (poller.isDown(A_Jump)) + 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 diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 7d9f748d4..849ab8ea4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -19,10 +19,10 @@ namespace MWMechanics { if (!paused && ptr.getRefData().getHandle()!="player") MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip ( - MWWorld::Class::get (ptr).getNpcStats (ptr), mEnvironment); + MWWorld::Class::get (ptr).getNpcStats (ptr)); } - Actors::Actors (MWWorld::Environment& environment) : mEnvironment (environment), mDuration (0) {} + Actors::Actors() : mDuration (0) {} void Actors::addActor (const MWWorld::Ptr& ptr) { diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 7ff33b63b..ae93fb52e 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -12,16 +12,10 @@ namespace Ogre class Vector3; } -namespace MWWorld -{ - class Environment; -} - namespace MWMechanics { class Actors { - MWWorld::Environment& mEnvironment; std::set mActors; float mDuration; @@ -31,7 +25,7 @@ namespace MWMechanics public: - Actors (MWWorld::Environment& environment); + Actors(); void addActor (const MWWorld::Ptr& ptr); ///< Register an actor for stats management diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index f5711e78e..8bc408be6 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -5,8 +5,9 @@ #include "../mwgui/window_manager.hpp" +#include "../mwbase/environment.hpp" + #include "../mwworld/class.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -14,7 +15,7 @@ namespace MWMechanics { void MechanicsManager::buildPlayer() { - MWWorld::Ptr ptr = mEnvironment.mWorld->getPlayer().getPlayer(); + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); MWMechanics::NpcStats& npcStats = MWWorld::Class::get (ptr).getNpcStats (ptr); @@ -33,10 +34,10 @@ namespace MWMechanics if (mRaceSelected) { const ESM::Race *race = - mEnvironment.mWorld->getStore().races.find ( - mEnvironment.mWorld->getPlayer().getRace()); + MWBase::Environment::get().getWorld()->getStore().races.find ( + MWBase::Environment::get().getWorld()->getPlayer().getRace()); - bool male = mEnvironment.mWorld->getPlayer().isMale(); + bool male = MWBase::Environment::get().getWorld()->getPlayer().isMale(); for (int i=0; i<8; ++i) { @@ -76,11 +77,11 @@ namespace MWMechanics } // birthsign - if (!mEnvironment.mWorld->getPlayer().getBirthsign().empty()) + if (!MWBase::Environment::get().getWorld()->getPlayer().getBirthsign().empty()) { const ESM::BirthSign *sign = - mEnvironment.mWorld->getStore().birthSigns.find ( - mEnvironment.mWorld->getPlayer().getBirthsign()); + MWBase::Environment::get().getWorld()->getStore().birthSigns.find ( + MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); for (std::vector::const_iterator iter (sign->powers.list.begin()); iter!=sign->powers.list.end(); ++iter) @@ -92,7 +93,7 @@ namespace MWMechanics // class if (mClassSelected) { - const ESM::Class& class_ = mEnvironment.mWorld->getPlayer().getClass(); + const ESM::Class& class_ = MWBase::Environment::get().getWorld()->getPlayer().getClass(); for (int i=0; i<2; ++i) { @@ -121,7 +122,7 @@ namespace MWMechanics } typedef ESMS::IndexListT::MapType ContainerType; - const ContainerType& skills = mEnvironment.mWorld->getStore().skills.list; + const ContainerType& skills = MWBase::Environment::get().getWorld()->getStore().skills.list; for (ContainerType::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) { @@ -164,7 +165,7 @@ namespace MWMechanics MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (creature).getCreatureStats (creature); - MagicEffects now = creatureStats.mSpells.getMagicEffects (mEnvironment); + MagicEffects now = creatureStats.mSpells.getMagicEffects(); /// \todo add effects from active spells and equipment @@ -175,9 +176,9 @@ namespace MWMechanics // TODO apply diff to other stats } - MechanicsManager::MechanicsManager (MWWorld::Environment& environment) - : mEnvironment (environment), mUpdatePlayer (true), mClassSelected (false), - mRaceSelected (false), mActors (environment) + MechanicsManager::MechanicsManager() + : mUpdatePlayer (true), mClassSelected (false), + mRaceSelected (false) { buildPlayer(); } @@ -236,7 +237,7 @@ namespace MWMechanics { mWatchedCreature.mAttributes[i] = stats.mAttributes[i]; - mEnvironment.mWindowManager->setValue (attributeNames[i], stats.mAttributes[i]); + MWBase::Environment::get().getWindowManager()->setValue (attributeNames[i], stats.mAttributes[i]); } } @@ -246,7 +247,7 @@ namespace MWMechanics { mWatchedCreature.mDynamic[i] = stats.mDynamic[i]; - mEnvironment.mWindowManager->setValue (dynamicNames[i], stats.mDynamic[i]); + MWBase::Environment::get().getWindowManager()->setValue (dynamicNames[i], stats.mDynamic[i]); } } @@ -259,25 +260,25 @@ namespace MWMechanics { update = true; mWatchedNpc.mSkill[i] = npcStats.mSkill[i]; - mEnvironment.mWindowManager->setValue((ESM::Skill::SkillEnum)i, npcStats.mSkill[i]); + MWBase::Environment::get().getWindowManager()->setValue((ESM::Skill::SkillEnum)i, npcStats.mSkill[i]); } } if (update) - mEnvironment.mWindowManager->updateSkillArea(); + MWBase::Environment::get().getWindowManager()->updateSkillArea(); - mEnvironment.mWindowManager->setValue ("level", stats.mLevel); + MWBase::Environment::get().getWindowManager()->setValue ("level", stats.mLevel); } if (mUpdatePlayer) { // basic player profile; should not change anymore after the creation phase is finished. - mEnvironment.mWindowManager->setValue ("name", mEnvironment.mWorld->getPlayer().getName()); - mEnvironment.mWindowManager->setValue ("race", - mEnvironment.mWorld->getStore().races.find (mEnvironment.mWorld->getPlayer(). + MWBase::Environment::get().getWindowManager()->setValue ("name", MWBase::Environment::get().getWorld()->getPlayer().getName()); + MWBase::Environment::get().getWindowManager()->setValue ("race", + MWBase::Environment::get().getWorld()->getStore().races.find (MWBase::Environment::get().getWorld()->getPlayer(). getRace())->name); - mEnvironment.mWindowManager->setValue ("class", - mEnvironment.mWorld->getPlayer().getClass().name); + MWBase::Environment::get().getWindowManager()->setValue ("class", + MWBase::Environment::get().getWorld()->getPlayer().getClass().name); mUpdatePlayer = false; MWGui::WindowManager::SkillList majorSkills (5); @@ -285,11 +286,11 @@ namespace MWMechanics for (int i=0; i<5; ++i) { - minorSkills[i] = mEnvironment.mWorld->getPlayer().getClass().data.skills[i][0]; - majorSkills[i] = mEnvironment.mWorld->getPlayer().getClass().data.skills[i][1]; + minorSkills[i] = MWBase::Environment::get().getWorld()->getPlayer().getClass().data.skills[i][0]; + majorSkills[i] = MWBase::Environment::get().getWorld()->getPlayer().getClass().data.skills[i][1]; } - mEnvironment.mWindowManager->configureSkills (majorSkills, minorSkills); + MWBase::Environment::get().getWindowManager()->configureSkills (majorSkills, minorSkills); } mActors.update (movement, duration, paused); @@ -297,14 +298,14 @@ namespace MWMechanics void MechanicsManager::setPlayerName (const std::string& name) { - mEnvironment.mWorld->getPlayer().setName (name); + MWBase::Environment::get().getWorld()->getPlayer().setName (name); mUpdatePlayer = true; } void MechanicsManager::setPlayerRace (const std::string& race, bool male) { - mEnvironment.mWorld->getPlayer().setGender (male); - mEnvironment.mWorld->getPlayer().setRace (race); + MWBase::Environment::get().getWorld()->getPlayer().setGender (male); + MWBase::Environment::get().getWorld()->getPlayer().setRace (race); mRaceSelected = true; buildPlayer(); mUpdatePlayer = true; @@ -312,14 +313,14 @@ namespace MWMechanics void MechanicsManager::setPlayerBirthsign (const std::string& id) { - mEnvironment.mWorld->getPlayer().setBirthsign (id); + MWBase::Environment::get().getWorld()->getPlayer().setBirthsign (id); buildPlayer(); mUpdatePlayer = true; } void MechanicsManager::setPlayerClass (const std::string& id) { - mEnvironment.mWorld->getPlayer().setClass (*mEnvironment.mWorld->getStore().classes.find (id)); + MWBase::Environment::get().getWorld()->getPlayer().setClass (*MWBase::Environment::get().getWorld()->getStore().classes.find (id)); mClassSelected = true; buildPlayer(); mUpdatePlayer = true; @@ -327,7 +328,7 @@ namespace MWMechanics void MechanicsManager::setPlayerClass (const ESM::Class& class_) { - mEnvironment.mWorld->getPlayer().setClass (class_); + MWBase::Environment::get().getWorld()->getPlayer().setClass (class_); mClassSelected = true; buildPlayer(); mUpdatePlayer = true; diff --git a/apps/openmw/mwmechanics/mechanicsmanager.hpp b/apps/openmw/mwmechanics/mechanicsmanager.hpp index a121507ce..a26fb98cd 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.hpp @@ -15,16 +15,10 @@ namespace Ogre class Vector3; } -namespace MWWorld -{ - class Environment; -} - namespace MWMechanics { class MechanicsManager { - MWWorld::Environment& mEnvironment; MWWorld::Ptr mWatched; CreatureStats mWatchedCreature; NpcStats mWatchedNpc; @@ -41,7 +35,7 @@ namespace MWMechanics public: - MechanicsManager (MWWorld::Environment& environment); + MechanicsManager (); void configureGUI(); diff --git a/apps/openmw/mwmechanics/movement.hpp b/apps/openmw/mwmechanics/movement.hpp index a555ac010..11eb83151 100644 --- a/apps/openmw/mwmechanics/movement.hpp +++ b/apps/openmw/mwmechanics/movement.hpp @@ -8,8 +8,9 @@ namespace MWMechanics { signed char mLeftRight; // 1: wants to move left, -1: wants to move right signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward + signed char mUpDown; - Movement() : mLeftRight (0), mForwardBackward (0) {} + Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {} }; } diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 916239a84..a53c75dc2 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -3,7 +3,8 @@ #include -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" #include "magiceffects.hpp" @@ -48,13 +49,13 @@ namespace MWMechanics mSelectedSpell.clear(); } - MagicEffects Spells::getMagicEffects (const MWWorld::Environment& environment) const + MagicEffects Spells::getMagicEffects() const { MagicEffects effects; for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { - const ESM::Spell *spell = environment.mWorld->getStore().spells.find (*iter); + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find (*iter); if (spell->data.type==ESM::Spell::ST_Ability || spell->data.type==ESM::Spell::ST_Blight || spell->data.type==ESM::Spell::ST_Disease || spell->data.type==ESM::Spell::ST_Curse) diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index f7606c4ac..d90f5b502 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -9,11 +9,6 @@ namespace ESM struct Spell; } -namespace MWWorld -{ - struct Environment; -} - namespace MWMechanics { class MagicEffects; @@ -49,7 +44,7 @@ namespace MWMechanics ///< If the spell to be removed is the selected spell, the selected spell will be changed to /// no spell (empty string). - MagicEffects getMagicEffects (const MWWorld::Environment& environment) const; + MagicEffects getMagicEffects() const; ///< Return sum of magic effects resulting from abilities, blights, deseases and curses. void clear(); diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 6eb4a182b..152cf3277 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -20,12 +20,12 @@ Actors::~Actors(){ void Actors::setMwRoot(Ogre::SceneNode* root){ mMwRoot = root; } -void Actors::insertNPC(const MWWorld::Ptr& ptr){ +void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv){ - insertBegin(ptr, true, true); - NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend); + insertBegin(ptr, true, true); + NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mRend, inv); - mAllActors[ptr] = anim; + mAllActors[ptr] = anim; } void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ Ogre::SceneNode* cellnode; @@ -68,7 +68,7 @@ void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ void Actors::insertCreature (const MWWorld::Ptr& ptr){ insertBegin(ptr, true, true); - CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend); + CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mRend); //mAllActors.insert(std::pair(ptr,anim)); delete mAllActors[ptr]; mAllActors[ptr] = anim; diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index d49c6e0f8..432bcc297 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -13,7 +13,6 @@ #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" -#include "../mwworld/environment.hpp" #include "npcanimation.hpp" #include "creatureanimation.hpp" #include @@ -23,18 +22,17 @@ namespace MWRender{ OEngine::Render::OgreRenderer &mRend; std::map mCellSceneNodes; Ogre::SceneNode* mMwRoot; - MWWorld::Environment& mEnvironment; std::map mAllActors; public: - Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){} + Actors(OEngine::Render::OgreRenderer& _rend): mRend(_rend) {} ~Actors(); void setMwRoot(Ogre::SceneNode* root); void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertCreature (const MWWorld::Ptr& ptr); - void insertNPC(const MWWorld::Ptr& ptr); + void insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv); bool deleteObject (const MWWorld::Ptr& ptr); ///< \return found? diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index fb710443b..fc6258208 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -4,12 +4,10 @@ namespace MWRender{ std::map Animation::mUniqueIDs; - Animation::Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend) + Animation::Animation(OEngine::Render::OgreRenderer& _rend) : insert(NULL) , mRend(_rend) - , mEnvironment(_env) , vecRotPos() - , shapeparts() , time(0.0f) , startTime(0.0f) , stopTime(0.0f) @@ -19,7 +17,6 @@ namespace MWRender{ , shapeNumber(0) , shapeIndexI() , shapes(NULL) - , entityparts() , transformations(NULL) , textmappings(NULL) , base(NULL) @@ -305,8 +302,8 @@ namespace MWRender{ for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) { - if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){ - Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(*boneSequenceIter); + if(skel->hasBone(*boneSequenceIter)){ + Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); // Computes C = B + AxC*scale transmult = transmult + rotmult * bonePtr->getPosition(); rotmult = rotmult * bonePtr->getOrientation(); @@ -430,14 +427,7 @@ namespace MWRender{ //base->_updateAnimation(); //base->_notifyMoved(); - for(unsigned int i = 0; i < entityparts.size(); i++){ - //Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton(); - //Ogre::Bone* b = skel->getRootBone(); - //b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick - - //entityparts[i]->getAllAnimationStates()->_notifyDirty(); - } std::vector::iterator iter; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 7692c7128..4ab60cff4 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -5,7 +5,6 @@ #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" -#include "../mwworld/environment.hpp" #include #include #include @@ -21,17 +20,16 @@ struct PosAndRot{ }; class Animation{ - + protected: Ogre::SceneNode* insert; OEngine::Render::OgreRenderer &mRend; - MWWorld::Environment& mEnvironment; std::map vecRotPos; static std::map mUniqueIDs; - - - - std::vector* > shapeparts; //All the NiTriShape data that we need for animating an npc + + + + float time; float startTime; @@ -41,14 +39,14 @@ class Animation{ std::vectorrindexI; //Represents a translation index for each bone std::vectortindexI; - + //Only shapes with morphing data will use a shape number int shapeNumber; std::vector > shapeIndexI; //Ogre::SkeletonInstance* skel; std::vector* shapes; //All the NiTriShapeData for a creature - std::vector entityparts; + std::vector* transformations; @@ -58,16 +56,16 @@ class Animation{ void handleAnimationTransforms(); bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); std::string getUniqueID(std::string mesh); - + public: - Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); + Animation(OEngine::Render::OgreRenderer& _rend); virtual void runAnimation(float timepassed) = 0; void startScript(std::string groupname, int mode, int loops); void stopScript(); virtual ~Animation(); - + }; } #endif diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index e0eb5ccc2..9ca3ed731 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -10,7 +10,7 @@ namespace MWRender{ CreatureAnimation::~CreatureAnimation(){ } -CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){ +CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend){ insert = ptr.getRefData().getBaseNode(); ESMS::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwrender/creatureanimation.hpp b/apps/openmw/mwrender/creatureanimation.hpp index 2229eeec9..f50b7904b 100644 --- a/apps/openmw/mwrender/creatureanimation.hpp +++ b/apps/openmw/mwrender/creatureanimation.hpp @@ -7,20 +7,19 @@ #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" -#include "../mwworld/environment.hpp" #include "components/nifogre/ogre_nif_loader.hpp" namespace MWRender{ class CreatureAnimation: public Animation{ - + public: virtual ~CreatureAnimation(); - CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); + CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend); virtual void runAnimation(float timepassed); - + }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index d42672179..be8afbae6 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -8,7 +8,7 @@ #include #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/ptr.hpp" #include #include @@ -138,8 +138,8 @@ ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid) return result; } -Debugging::Debugging(SceneNode *mwRoot, MWWorld::Environment &env, OEngine::Physic::PhysicEngine *engine) : - mMwRoot(mwRoot), mEnvironment(env), mEngine(engine), +Debugging::Debugging(SceneNode *mwRoot, OEngine::Physic::PhysicEngine *engine) : + mMwRoot(mwRoot), mEngine(engine), mSceneMgr(mwRoot->getCreator()), mPathgridEnabled(false), mInteriorPathgridNode(NULL), mPathGridRoot(NULL), @@ -218,7 +218,7 @@ void Debugging::togglePathgrid() void Debugging::enableCellPathgrid(MWWorld::Ptr::CellStore *store) { - ESM::Pathgrid *pathgrid = mEnvironment.mWorld->getStore().pathgrids.search(*store->cell); + ESM::Pathgrid *pathgrid = MWBase::Environment::get().getWorld()->getStore().pathgrids.search(*store->cell); if (!pathgrid) return; Vector3 cellPathGridPos(0, 0, 0); diff --git a/apps/openmw/mwrender/debugging.hpp b/apps/openmw/mwrender/debugging.hpp index ebf3884dc..e12c0647c 100644 --- a/apps/openmw/mwrender/debugging.hpp +++ b/apps/openmw/mwrender/debugging.hpp @@ -23,7 +23,6 @@ namespace Ogre namespace MWWorld { class World; - class Environment; } namespace MWRender @@ -34,7 +33,6 @@ namespace MWRender { OEngine::Physic::PhysicEngine* mEngine; Ogre::SceneManager *mSceneMgr; - MWWorld::Environment& mEnvironment; // Path grid stuff bool mPathgridEnabled; @@ -68,7 +66,7 @@ namespace MWRender Ogre::ManualObject *createPathgridLines(const ESM::Pathgrid *pathgrid); Ogre::ManualObject *createPathgridPoints(const ESM::Pathgrid *pathgrid); public: - Debugging(Ogre::SceneNode* mwRoot, MWWorld::Environment &env, OEngine::Physic::PhysicEngine *engine); + Debugging(Ogre::SceneNode* mwRoot, OEngine::Physic::PhysicEngine *engine); ~Debugging(); bool toggleRenderMode (int mode); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 2cc233a01..ea8902443 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -1,7 +1,7 @@ #include "localmap.hpp" #include "renderingmanager.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwgui/window_manager.hpp" #include "renderconst.hpp" @@ -12,12 +12,11 @@ using namespace MWRender; using namespace Ogre; -LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering, MWWorld::Environment* env) : +LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering) : mInterior(false), mCellX(0), mCellY(0) { mRendering = rend; mRenderingManager = rendering; - mEnvironment = env; mCameraPosNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode(); mCameraRotNode = mCameraPosNode->createChildSceneNode(); @@ -54,12 +53,12 @@ void LocalMap::saveTexture(const std::string& texname, const std::string& filena if (tex.isNull()) return; HardwarePixelBufferSharedPtr readbuffer = tex->getBuffer(); readbuffer->lock(HardwareBuffer::HBL_NORMAL ); - const PixelBox &readrefpb = readbuffer->getCurrentLock(); - uchar *readrefdata = static_cast(readrefpb.data); + const PixelBox &readrefpb = readbuffer->getCurrentLock(); + uchar *readrefdata = static_cast(readrefpb.data); Image img; img = img.loadDynamicImage (readrefdata, tex->getWidth(), - tex->getHeight(), tex->getFormat()); + tex->getHeight(), tex->getFormat()); img.save("./" + filename); readbuffer->unlock(); @@ -82,7 +81,7 @@ void LocalMap::saveFogOfWar(MWWorld::Ptr::CellStore* cell) Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z); Vector2 length = max-min; - + // divide into segments const int segsX = std::ceil( length.x / sSize ); const int segsY = std::ceil( length.y / sSize ); @@ -123,7 +122,7 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell, Vector2 z(mBounds.getMaximum().y, mBounds.getMinimum().y); - const Vector2& north = mEnvironment->mWorld->getNorthVector(cell); + const Vector2& north = MWBase::Environment::get().getWorld()->getNorthVector(cell); Radian angle(std::atan2(-north.x, -north.y)); mAngle = angle.valueRadians(); mCameraRotNode->setOrientation(Quaternion(Math::Cos(angle/2.f), 0, Math::Sin(angle/2.f), 0)); @@ -213,7 +212,7 @@ void LocalMap::render(const float x, const float y, texture, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, - xw*sMapResolution/sSize, yw*sMapResolution/sSize, + xw*sMapResolution/sSize, yw*sMapResolution/sSize, 0, PF_R8G8B8, TU_RENDERTARGET); @@ -236,7 +235,7 @@ void LocalMap::render(const float x, const float y, texture + "_fog", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, - xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize, + xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize, 0, PF_A8R8G8B8, TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); @@ -276,7 +275,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni return; } - // retrieve the x,y grid coordinates the player is in + // 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); @@ -303,7 +302,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni x = std::ceil((pos.x - min.x)/sSize)-1; y = std::ceil((pos.y - min.y)/sSize)-1; - mEnvironment->mWindowManager->setInteriorMapTexture(x,y); + MWBase::Environment::get().getWindowManager()->setInteriorMapTexture(x,y); } // convert from world coordinates to texture UV coordinates @@ -323,8 +322,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni texName = mInteriorName + "_" + coordStr(x,y); } - mEnvironment->mWindowManager->setPlayerPos(u, v); - mEnvironment->mWindowManager->setPlayerDir(playerdirection.x, -playerdirection.z); + MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v); + MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, -playerdirection.z); // explore radius (squared) const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 95685167c..9e03988f3 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -5,11 +5,6 @@ #include -namespace MWWorld -{ - class Environment; -} - namespace MWRender { class RenderingManager; @@ -20,7 +15,7 @@ namespace MWRender class LocalMap { public: - LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering, MWWorld::Environment* env); + LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering); ~LocalMap(); /** @@ -61,7 +56,6 @@ namespace MWRender private: OEngine::Render::OgreRenderer* mRendering; MWRender::RenderingManager* mRenderingManager; - MWWorld::Environment* mEnvironment; // 1024*1024 pixels for a cell static const int sMapResolution = 1024; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a231e8fe7..c35fff1ce 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -2,6 +2,7 @@ #include "../mwworld/world.hpp" #include "renderconst.hpp" +#include "../mwbase/environment.hpp" using namespace Ogre; using namespace NifOgre; @@ -11,9 +12,49 @@ NpcAnimation::~NpcAnimation(){ } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){ +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv): Animation(_rend), mStateID(-1), inv(_inv), timeToChange(0), + robe(inv.end()), helmet(inv.end()), shirt(inv.end()), + cuirass(inv.end()), greaves(inv.end()), + leftpauldron(inv.end()), rightpauldron(inv.end()), + boots(inv.end()), + leftglove(inv.end()), rightglove(inv.end()), skirtiter(inv.end()), + pants(inv.end()), + lclavicle(0), + rclavicle(0), + rupperArm(0), + lupperArm(0), + rUpperLeg(0), + lUpperLeg(0), + lForearm(0), + rForearm(0), + lWrist(0), + rWrist(0), + rKnee(0), + lKnee(0), + neck(0), + rAnkle(0), + lAnkle(0), + groin(0), + lfoot(0), + rfoot(0) + { ESMS::LiveCellRef *ref = ptr.get(); + Ogre::Entity* blank = 0; + std::vector* blankshape = 0; + zero = std::make_pair(blank, blankshape); + chest = std::make_pair(blank, blankshape); + tail = std::make_pair(blank, blankshape); + lFreeFoot = std::make_pair(blank, blankshape); + rFreeFoot = std::make_pair(blank, blankshape); + rhand = std::make_pair(blank, blankshape); + lhand = std::make_pair(blank, blankshape); + skirt = std::make_pair(blank, blankshape); + for (int init = 0; init < 27; init++){ + partslots[init] = -1; //each slot is empty + partpriorities[init] = 0; + } + //Part selection on last character of the file string // " Tri Chest @@ -35,16 +76,22 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O std::string hairID = ref->base->hair; std::string headID = ref->base->head; - std::string npcName = ref->base->name; + headModel = "meshes\\" + + MWBase::Environment::get().getWorld()->getStore().bodyParts.find(headID)->model; + + hairModel = "meshes\\" + + MWBase::Environment::get().getWorld()->getStore().bodyParts.find(hairID)->model; + npcName = ref->base->name; + //ESMStore::Races r = - const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race); + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().races.find(ref->base->race); - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); - bool female = tolower(secondtolast) == 'f'; + isFemale = tolower(secondtolast) == 'f'; std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; + isBeast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; /*std::cout << "Race: " << ref->base->race ; if(female){ @@ -57,7 +104,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O std::string smodel = "meshes\\base_anim.nif"; - if(beast) + if(isBeast) smodel = "meshes\\base_animkna.nif"; insert = ptr.getRefData().getBaseNode(); @@ -66,6 +113,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O NifOgre::NIFLoader::load(smodel); base = mRend.getScene()->createEntity(smodel); + base->setVisibilityFlags(RV_Actors); bool transparent = false; for (unsigned int i=0; igetNumSubEntities(); ++i) @@ -87,6 +135,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones //stay in the same place when we skipanim, or open a gui window @@ -105,167 +154,412 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel); insert->attachObject(base); - if(female) + + if(isFemale) insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); else insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); - std::string headModel = "meshes\\" + - mEnvironment.mWorld->getStore().bodyParts.find(headID)->model; + updateParts(); - std::string hairModel = "meshes\\" + - mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model; - const ESM::BodyPart *chest = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); - const ESM::BodyPart *upperleg = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); - const ESM::BodyPart *groin = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); - const ESM::BodyPart *arml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); //We need two - const ESM::BodyPart *neck = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); - const ESM::BodyPart *knee = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); - const ESM::BodyPart *ankle = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); - const ESM::BodyPart *foot = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); - const ESM::BodyPart *feet = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); - const ESM::BodyPart *tail = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); - const ESM::BodyPart *wristl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); //We need two - const ESM::BodyPart *forearml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); //We need two - const ESM::BodyPart *handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand"); //We need two - const ESM::BodyPart *hair = mEnvironment.mWorld->getStore().bodyParts.search(hairID); - const ESM::BodyPart *head = mEnvironment.mWorld->getStore().bodyParts.search(headID); - if(bodyRaceID == "b_n_argonian_f_") - forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two - if(!handl) - handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands"); - //const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle"); - //const ESM::BodyPart* clavicler = claviclel; - const ESM::BodyPart* handr = handl; - const ESM::BodyPart* forearmr = forearml; - const ESM::BodyPart* wristr = wristl; - const ESM::BodyPart* armr = arml; +} + +void NpcAnimation::updateParts(){ + + bool apparelChanged = false; - if(upperleg){ - insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg"); - insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg"); - + //inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)){ + //A robe was added or removed + removePartGroup(MWWorld::InventoryStore::Slot_Robe); + robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + apparelChanged = true; } - if(foot){ - if(bodyRaceID.compare("b_n_khajiit_m_") == 0) - { - feet = foot; - } - else - { - insertBoundedPart("meshes\\" + foot->model, "Right Foot"); - insertBoundedPart("meshes\\" + foot->model + "*|", "Left Foot"); - } + if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)){ + //A robe was added or removed + removePartGroup(MWWorld::InventoryStore::Slot_Skirt); + skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt); + apparelChanged = true; } - if(groin){ - insertBoundedPart("meshes\\" + groin->model, "Groin"); - } - if(knee) - { - insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e - insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e + if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)){ + apparelChanged = true; + helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet); + removePartGroup(MWWorld::InventoryStore::Slot_Helmet); - } - if(ankle){ - - insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank); - insertBoundedPart("meshes\\" + ankle->model, "Right Ankle"); - } - if (armr){ - insertBoundedPart("meshes\\" + armr->model, "Right Upper Arm"); - } - if(arml){ - insertBoundedPart("meshes\\" + arml->model + "*|", "Left Upper Arm"); - } - - if (forearmr) - { - insertBoundedPart("meshes\\" + forearmr->model, "Right Forearm"); - } - if(forearml) - insertBoundedPart("meshes\\" + forearml->model + "*|", "Left Forearm"); - - if (wristr) - { - insertBoundedPart("meshes\\" + wristr->model, "Right Wrist"); - } - - if(wristl) - insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist"); - - - - - - /*if(claviclel) - insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base); - if(clavicler) - insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/ - - if(neck) - { - insertBoundedPart("meshes\\" + neck->model, "Neck"); - } - if(head) - insertBoundedPart("meshes\\" + head->model, "Head"); - if(hair) - insertBoundedPart("meshes\\" + hair->model, "Head"); - - if (chest){ - insertFreePart("meshes\\" + chest->model, ">\"", insert); - - - } - if (handr){ - insertFreePart("meshes\\" + handr->model , ">?", insert); - - } - if (handl){ - insertFreePart("meshes\\" + handl->model, ">>", insert); - - } - if(tail){ - insertFreePart("meshes\\" + tail->model, ">*", insert); } - if(feet){ - std::string num = getUniqueID(feet->model); - insertFreePart("meshes\\" + feet->model,"><", insert); - insertFreePart("meshes\\" + feet->model,">:", insert); + if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)){ + cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); + removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); + apparelChanged = true; + } - //originalpos = insert->_getWorldAABB().getCenter(); - //originalscenenode = insert->getPosition(); + if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)){ + greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves); + removePartGroup(MWWorld::InventoryStore::Slot_Greaves); + apparelChanged = true; + } + if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)){ + leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); + apparelChanged = true; + + } + if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)){ + rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); + apparelChanged = true; + + } + if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)){ + boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); + removePartGroup(MWWorld::InventoryStore::Slot_Boots); + apparelChanged = true; + + } + if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)){ + leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); + apparelChanged = true; + + } + if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)){ + rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); + apparelChanged = true; + + } + if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)){ + shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt); + removePartGroup(MWWorld::InventoryStore::Slot_Shirt); + apparelChanged = true; + + } + if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)){ + pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants); + removePartGroup(MWWorld::InventoryStore::Slot_Pants); + apparelChanged = true; + + } + + if(apparelChanged){ + + if(robe != inv.end()) + { + MWWorld::Ptr ptr = *robe; + + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + } + if(skirtiter != inv.end()) + { + MWWorld::Ptr ptr = *skirtiter; + + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); + } + + if(helmet != inv.end()){ + removeIndividualPart(ESM::PRT_Hair); + const ESM::Armor *armor = (helmet->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); + + } + if(cuirass != inv.end()){ + const ESM::Armor *armor = (cuirass->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); + + } + if(greaves != inv.end()){ + const ESM::Armor *armor = (greaves->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); + + } + + if(leftpauldron != inv.end()){ + const ESM::Armor *armor = (leftpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); + + } + if(rightpauldron != inv.end()){ + const ESM::Armor *armor = (rightpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); + + } + if(!isBeast && boots != inv.end()){ + if(boots->getTypeName() == typeid(ESM::Clothing).name()){ + const ESM::Clothing *clothes = (boots->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); + } + else if(boots->getTypeName() == typeid(ESM::Armor).name()) + { + const ESM::Armor *armor = (boots->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); + } + + } + if(leftglove != inv.end()){ + if(leftglove->getTypeName() == typeid(ESM::Clothing).name()){ + const ESM::Clothing *clothes = (leftglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); + } + else + { + const ESM::Armor *armor = (leftglove->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); + } + + } + if(rightglove != inv.end()){ + if(rightglove->getTypeName() == typeid(ESM::Clothing).name()){ + const ESM::Clothing *clothes = (rightglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); + } + else + { + const ESM::Armor *armor = (rightglove->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); + } + + } + + if(shirt != inv.end()){ + const ESM::Clothing *clothes = (shirt->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); + } + if(pants != inv.end()){ + const ESM::Clothing *clothes = (pants->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); + } + } + + if(partpriorities[ESM::PRT_Head] < 1){ + addOrReplaceIndividualPart(ESM::PRT_Head, -1,1,headModel); + } + if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1){ + addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1,hairModel); + } + if(partpriorities[ESM::PRT_Neck] < 1){ + const ESM::BodyPart *neckPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "neck"); + if(neckPart) + addOrReplaceIndividualPart(ESM::PRT_Neck, -1,1,"meshes\\" + neckPart->model); + } + if(partpriorities[ESM::PRT_Cuirass] < 1){ + const ESM::BodyPart *chestPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "chest"); + if(chestPart) + addOrReplaceIndividualPart(ESM::PRT_Cuirass, -1,1,"meshes\\" + chestPart->model); + } + + if(partpriorities[ESM::PRT_Groin] < 1){ + const ESM::BodyPart *groinPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "groin"); + if(groinPart) + addOrReplaceIndividualPart(ESM::PRT_Groin, -1,1,"meshes\\" + groinPart->model); + } + if(partpriorities[ESM::PRT_RHand] < 1){ + const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); + if(!handPart) + handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); + if(handPart) + addOrReplaceIndividualPart(ESM::PRT_RHand, -1,1,"meshes\\" + handPart->model); + } + if(partpriorities[ESM::PRT_LHand] < 1){ + const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); + if(!handPart) + handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); + if(handPart) + addOrReplaceIndividualPart(ESM::PRT_LHand, -1,1,"meshes\\" + handPart->model); + } + + if(partpriorities[ESM::PRT_RWrist] < 1){ + const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); + if(wristPart) + addOrReplaceIndividualPart(ESM::PRT_RWrist, -1,1,"meshes\\" + wristPart->model); + } + if(partpriorities[ESM::PRT_LWrist] < 1){ + const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); + if(wristPart) + addOrReplaceIndividualPart(ESM::PRT_LWrist, -1,1,"meshes\\" + wristPart->model); + } + if(partpriorities[ESM::PRT_RForearm] < 1){ + const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); + if(bodyRaceID == "b_n_argonian_f_") + forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); + if(forearmPart) + addOrReplaceIndividualPart(ESM::PRT_RForearm, -1,1,"meshes\\" + forearmPart->model); + } + if(partpriorities[ESM::PRT_LForearm] < 1){ + const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); + if(bodyRaceID == "b_n_argonian_f_") + forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); + if(forearmPart) + addOrReplaceIndividualPart(ESM::PRT_LForearm, -1,1,"meshes\\" + forearmPart->model); + } + if(partpriorities[ESM::PRT_RUpperarm] < 1){ + const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); + if(armPart) + addOrReplaceIndividualPart(ESM::PRT_RUpperarm, -1,1,"meshes\\" + armPart->model); + } + if(partpriorities[ESM::PRT_LUpperarm] < 1){ + const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); + if(armPart) + addOrReplaceIndividualPart(ESM::PRT_LUpperarm, -1,1,"meshes\\" + armPart->model); + } + if(partpriorities[ESM::PRT_RFoot] < 1){ + const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); + if(isBeast && !footPart) + footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); + if(footPart) + addOrReplaceIndividualPart(ESM::PRT_RFoot, -1,1,"meshes\\" + footPart->model); + } + if(partpriorities[ESM::PRT_LFoot] < 1){ + const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); + if(isBeast && !footPart) + footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); + if(footPart) + addOrReplaceIndividualPart(ESM::PRT_LFoot, -1,1,"meshes\\" + footPart->model); + } + if(partpriorities[ESM::PRT_RAnkle] < 1){ + const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); + if(anklePart) + addOrReplaceIndividualPart(ESM::PRT_RAnkle, -1,1,"meshes\\" + anklePart->model); + } + if(partpriorities[ESM::PRT_LAnkle] < 1){ + const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); + if(anklePart) + addOrReplaceIndividualPart(ESM::PRT_LAnkle, -1,1,"meshes\\" + anklePart->model); + } + if(partpriorities[ESM::PRT_RKnee] < 1){ + const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); + if(kneePart) + addOrReplaceIndividualPart(ESM::PRT_RKnee, -1,1,"meshes\\" + kneePart->model); + } + if(partpriorities[ESM::PRT_LKnee] < 1){ + const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); + if(kneePart) + addOrReplaceIndividualPart(ESM::PRT_LKnee, -1,1,"meshes\\" + kneePart->model); + } + if(partpriorities[ESM::PRT_RLeg] < 1){ + const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); + if(legPart) + addOrReplaceIndividualPart(ESM::PRT_RLeg, -1,1,"meshes\\" + legPart->model); + } + if(partpriorities[ESM::PRT_LLeg] < 1){ + const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); + if(legPart) + addOrReplaceIndividualPart(ESM::PRT_LLeg, -1,1,"meshes\\" + legPart->model); + } + if(partpriorities[ESM::PRT_Tail] < 1){ + const ESM::BodyPart *tailPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "tail"); + if(tailPart) + addOrReplaceIndividualPart(ESM::PRT_Tail, -1,1,"meshes\\" + tailPart->model); + } + + + + + + + + } Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ - + NIFLoader::load(mesh); - Entity* ent = mRend.getScene()->createEntity(mesh); - ent->setVisibilityFlags(RV_Actors); + Ogre::Entity* part = mRend.getScene()->createEntity(mesh); + part->setVisibilityFlags(RV_Actors); - base->attachObjectToBone(bonename, ent); - return ent; + base->attachObjectToBone(bonename, part); + return part; } -void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){ - std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; - NIFLoader::load(meshNumbered); - - Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered); - ent->setVisibilityFlags(RV_Actors); - - insert->attachObject(ent); - entityparts.push_back(ent); - shapes = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix)); - if(shapes){ - shapeparts.push_back(shapes); - handleShapes(shapes, ent, base->getSkeleton()); +void NpcAnimation::insertFootPart(int type, const std::string &mesh){ + std::string meshAndSuffix = mesh; + if(type == ESM::PRT_LFoot) + meshAndSuffix += "*|"; + NIFLoader::load(meshAndSuffix); + Ogre::Entity* part = mRend.getScene()->createEntity(meshAndSuffix); + std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(meshAndSuffix)); + if(shape == 0){ + if(type == ESM::PRT_LFoot){ + base->attachObjectToBone("Left Foot", part); + lfoot = part; + } + else if (type == ESM::PRT_RFoot){ + base->attachObjectToBone("Right Foot", part); + rfoot = part; + } + } + else{ + if(type == ESM::PRT_LFoot) + lFreeFoot = insertFreePart(mesh, "::"); + else if (type == ESM::PRT_RFoot) + rFreeFoot = insertFreePart(mesh, ":<"); } + +} +std::pair*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix){ + + std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; + NIFLoader::load(meshNumbered); + + Ogre::Entity* part = mRend.getScene()->createEntity(meshNumbered); + part->setVisibilityFlags(RV_Actors); + + insert->attachObject(part); + + std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix)); + if(shape){ + handleShapes(shape, part, base->getSkeleton()); + } + std::pair*> pair = std::make_pair(part, shape); + return pair; } + + void NpcAnimation::runAnimation(float timepassed){ - + + if(timeToChange > .2){ + + timeToChange = 0; + + updateParts(); + } + + timeToChange += timepassed; + //1. Add the amount of time passed to time //2. Handle the animation transforms dependent on time @@ -283,23 +577,285 @@ void NpcAnimation::runAnimation(float timepassed){ time = startTime + (time - stopTime); } - handleAnimationTransforms(); + handleAnimationTransforms(); + - std::vector*>::iterator shapepartsiter = shapeparts.begin(); - std::vector::iterator entitypartsiter = entityparts.begin(); - while(shapepartsiter != shapeparts.end()) - { vecRotPos.clear(); - std::vector* shapes = *shapepartsiter; - Ogre::Entity* theentity = *entitypartsiter; - handleShapes(shapes, theentity, base->getSkeleton()); - shapepartsiter++; - entitypartsiter++; + if(lFreeFoot.first) + handleShapes(lFreeFoot.second, lFreeFoot.first, base->getSkeleton()); + if(rFreeFoot.first) + handleShapes(rFreeFoot.second, rFreeFoot.first, base->getSkeleton()); + + if(chest.first) + handleShapes(chest.second, chest.first, base->getSkeleton()); + if(tail.first) + handleShapes(tail.second, tail.first, base->getSkeleton()); + if(skirt.first){ + handleShapes(skirt.second, skirt.first, base->getSkeleton()); + } + if(lhand.first) + handleShapes(lhand.second, lhand.first, base->getSkeleton()); + if(rhand.first) + handleShapes(rhand.second, rhand.first, base->getSkeleton()); + +} +} + +void NpcAnimation::removeIndividualPart(int type){ + partpriorities[type] = 0; + partslots[type] = -1; + + if(type == ESM::PRT_Head && head){ //0 + base->detachObjectFromBone(head); + head = 0; } - + else if(type == ESM::PRT_Hair && hair){//1 + base->detachObjectFromBone(hair); + hair = 0; + } + else if(type == ESM::PRT_Neck && neck){//2 + base->detachObjectFromBone(neck); + neck = 0; + } + else if(type == ESM::PRT_Cuirass && chest.first){//3 + insert->detachObject(chest.first); + chest = zero; + } + else if(type == ESM::PRT_Groin && groin){//4 + base->detachObjectFromBone(groin); + groin = 0; + } + else if(type == ESM::PRT_Skirt && skirt.first){//5 + insert->detachObject(skirt.first); + skirt = zero; + } + else if(type == ESM::PRT_RHand && rhand.first){//6 + insert->detachObject(rhand.first); + rhand = zero; + } + else if(type == ESM::PRT_LHand && lhand.first){//7 + insert->detachObject(lhand.first); + lhand = zero; + } + else if(type == ESM::PRT_RWrist && rWrist){//8 + base->detachObjectFromBone(rWrist); + rWrist = 0; + } + else if(type == ESM::PRT_LWrist && lWrist){//9 + base->detachObjectFromBone(lWrist); + lWrist = 0; + } + else if(type == ESM::PRT_Shield){//10 + + } + else if(type == ESM::PRT_RForearm && rForearm){//11 + base->detachObjectFromBone(rForearm); + rForearm = 0; + } + else if(type == ESM::PRT_LForearm && lForearm){//12 + base->detachObjectFromBone(lForearm); + lForearm = 0; + } + else if(type == ESM::PRT_RUpperarm && rupperArm){//13 + base->detachObjectFromBone(rupperArm); + rupperArm = 0; + } + else if(type == ESM::PRT_LUpperarm && lupperArm){//14 + base->detachObjectFromBone(lupperArm); + lupperArm = 0; + } + else if(type == ESM::PRT_RFoot){ //15 + if(rfoot){ + base->detachObjectFromBone(rfoot); + rfoot = 0; + } + else if(rFreeFoot.first){ + insert->detachObject(rFreeFoot.first); + rFreeFoot = zero; + } + } + else if(type == ESM::PRT_LFoot){ //16 + if(lfoot){ + base->detachObjectFromBone(lfoot); + lfoot = 0; + } + else if(lFreeFoot.first){ + insert->detachObject(lFreeFoot.first); + lFreeFoot = zero; + } + } + else if(type == ESM::PRT_RAnkle && rAnkle){ //17 + base->detachObjectFromBone(rAnkle); + rAnkle = 0; + } + else if(type == ESM::PRT_LAnkle && lAnkle){ //18 + base->detachObjectFromBone(lAnkle); + lAnkle = 0; + } + else if(type == ESM::PRT_RKnee && rKnee){ //19 + base->detachObjectFromBone(rKnee); + rKnee = 0; + } + else if(type == ESM::PRT_LKnee && lKnee){ //20 + base->detachObjectFromBone(lKnee); + lKnee = 0; + } + else if(type == ESM::PRT_RLeg && rUpperLeg){ //21 + base->detachObjectFromBone(rUpperLeg); + rUpperLeg = 0; + } + else if(type == ESM::PRT_LLeg && lUpperLeg){ //22 + base->detachObjectFromBone(lUpperLeg); + lUpperLeg = 0; + } + else if(type == ESM::PRT_RPauldron && rclavicle){ //23 + base->detachObjectFromBone(rclavicle); + rclavicle = 0; + } + else if(type == ESM::PRT_LPauldron && lclavicle){ //24 + base->detachObjectFromBone(lclavicle); + lclavicle = 0; + } + else if(type == ESM::PRT_Weapon){ //25 + + } + else if(type == ESM::PRT_Tail && tail.first){ //26 + insert->detachObject(tail.first); + tail = zero; + } + + + + } -} + void NpcAnimation::reserveIndividualPart(int type, int group, int priority){ + if(priority > partpriorities[type]){ + removeIndividualPart(type); + partpriorities[type] = priority; + partslots[type] = group; + } + } + + void NpcAnimation::removePartGroup(int group){ + for(int i = 0; i < 27; i++){ + if(partslots[i] == group){ + removeIndividualPart(i); + } + } + } + bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh){ + if(priority > partpriorities[type]){ + removeIndividualPart(type); + partslots[type] = group; + partpriorities[type] = priority; + switch(type){ + case ESM::PRT_Head: //0 + head = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Hair: //1 + hair = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Neck: //2 + neck = insertBoundedPart(mesh, "Neck"); + break; + case ESM::PRT_Cuirass: //3 + chest = insertFreePart(mesh, ":\""); + break; + case ESM::PRT_Groin: //4 + groin = insertBoundedPart(mesh, "Groin"); + break; + case ESM::PRT_Skirt: //5 + skirt = insertFreePart(mesh, ":|"); + break; + case ESM::PRT_RHand: //6 + rhand = insertFreePart(mesh, ":?"); + break; + case ESM::PRT_LHand: //7 + lhand = insertFreePart(mesh, ":>"); + break; + case ESM::PRT_RWrist: //8 + rWrist = insertBoundedPart(mesh, "Right Wrist"); + break; + case ESM::PRT_LWrist: //9 + lWrist = insertBoundedPart(mesh + "*|", "Left Wrist"); + break; + case ESM::PRT_Shield: //10 + break; + case ESM::PRT_RForearm: //11 + rForearm = insertBoundedPart(mesh, "Right Forearm"); + break; + case ESM::PRT_LForearm: //12 + lForearm = insertBoundedPart(mesh + "*|", "Left Forearm"); + break; + case ESM::PRT_RUpperarm: //13 + rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); + break; + case ESM::PRT_LUpperarm: //14 + lupperArm = insertBoundedPart(mesh + "*|", "Left Upper Arm"); + break; + case ESM::PRT_RFoot: //15 + insertFootPart(type, mesh); + break; + case ESM::PRT_LFoot: //16 + insertFootPart(type, mesh); + break; + case ESM::PRT_RAnkle: //17 + rAnkle = insertBoundedPart(mesh , "Right Ankle"); + break; + case ESM::PRT_LAnkle: //18 + lAnkle = insertBoundedPart(mesh + "*|", "Left Ankle"); + break; + case ESM::PRT_RKnee: //19 + rKnee = insertBoundedPart(mesh , "Right Knee"); + break; + case ESM::PRT_LKnee: //20 + lKnee = insertBoundedPart(mesh + "*|", "Left Knee"); + break; + case ESM::PRT_RLeg: //21 + rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); + break; + case ESM::PRT_LLeg: //22 + lUpperLeg = insertBoundedPart(mesh + "*|", "Left Upper Leg"); + break; + case ESM::PRT_RPauldron: //23 + rclavicle = insertBoundedPart(mesh , "Right Clavicle"); + break; + case ESM::PRT_LPauldron: //24 + lclavicle = insertBoundedPart(mesh + "*|", "Left Clavicle"); + break; + case ESM::PRT_Weapon: //25 + break; + case ESM::PRT_Tail: //26 + tail = insertFreePart(mesh, ":*"); + break; + + + } + return true; + } + return false; + } + + void NpcAnimation::addPartGroup(int group, int priority, std::vector& parts){ + for(std::size_t i = 0; i < parts.size(); i++) + { + ESM::PartReference part = parts[i]; + + const ESM::BodyPart *bodypart = 0; + + if(isFemale) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.female); + if(!bodypart) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.male); + if(bodypart){ + addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); + } + else + reserveIndividualPart(part.part, group, priority); + + } + } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index e2071957c..a37becc26 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -6,25 +6,96 @@ #include #include #include +#include #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" -#include "../mwworld/environment.hpp" #include "components/nifogre/ogre_nif_loader.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwclass/npc.hpp" +#include "../mwworld/containerstore.hpp" +#include "components/esm/loadarmo.hpp" namespace MWRender{ class NpcAnimation: public Animation{ - - - +private: + MWWorld::InventoryStore& inv; + int mStateID; + //Free Parts + std::pair*> chest; + std::pair*> skirt; + std::pair*> lhand; + std::pair*> rhand; + std::pair*> tail; + std::pair*> lFreeFoot; + std::pair*> rFreeFoot; + + int partslots[27]; //Each part slot is taken by clothing, armor, or is empty + int partpriorities[27]; + std::pair*> zero; + + + + //Bounded Parts + Ogre::Entity* lclavicle; + Ogre::Entity* rclavicle; + Ogre::Entity* rupperArm; + Ogre::Entity* lupperArm; + Ogre::Entity* rUpperLeg; + Ogre::Entity* lUpperLeg; + Ogre::Entity* lForearm; + Ogre::Entity* rForearm; + Ogre::Entity* lWrist; + Ogre::Entity* rWrist; + Ogre::Entity* rKnee; + Ogre::Entity* lKnee; + Ogre::Entity* neck; + Ogre::Entity* rAnkle; + Ogre::Entity* lAnkle; + Ogre::Entity* groin; + Ogre::Entity* lfoot; + Ogre::Entity* rfoot; + Ogre::Entity* hair; + Ogre::Entity* head; + + Ogre::SceneNode* insert; + bool isBeast; + bool isFemale; + std::string headModel; + std::string hairModel; + std::string npcName; + std::string bodyRaceID; + float timeToChange; + MWWorld::ContainerStoreIterator robe; + MWWorld::ContainerStoreIterator helmet; + MWWorld::ContainerStoreIterator shirt; + MWWorld::ContainerStoreIterator cuirass; + MWWorld::ContainerStoreIterator greaves; + MWWorld::ContainerStoreIterator leftpauldron; + MWWorld::ContainerStoreIterator rightpauldron; + MWWorld::ContainerStoreIterator boots; + MWWorld::ContainerStoreIterator pants; + MWWorld::ContainerStoreIterator leftglove; + MWWorld::ContainerStoreIterator rightglove; + MWWorld::ContainerStoreIterator skirtiter; + public: - NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); + NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); virtual ~NpcAnimation(); Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); - void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert); + std::pair*> insertFreePart(const std::string &mesh, const std::string suffix); + void insertFootPart(int type, const std::string &mesh); virtual void runAnimation(float timepassed); - + void updateParts(); + void removeIndividualPart(int type); + void reserveIndividualPart(int type, int group, int priority); + + bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh); + void removePartGroup(int group); + void addPartGroup(int group, int priority, std::vector& parts); + + }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index eb7e440cb..27c3f818e 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -8,20 +8,15 @@ using namespace MWRender; -bool Objects::lightConst = false; -float Objects::lightConstValue = 0.0f; - -bool Objects::lightLinear = true; -int Objects::lightLinearMethod = 1; +// These are the Morrowind.ini defaults float Objects::lightLinearValue = 3; float Objects::lightLinearRadiusMult = 1; -bool Objects::lightQuadratic = false; -int Objects::lightQuadraticMethod = 2; float Objects::lightQuadraticValue = 16; float Objects::lightQuadraticRadiusMult = 1; -bool Objects::lightOutQuadInLin = false; +bool Objects::lightOutQuadInLin = true; +bool Objects::lightQuadratic = false; int Objects::uniqueID = 0; @@ -58,8 +53,10 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_) Ogre::SceneNode* insert = cellnode->createChildSceneNode(); const float *f = ptr.getRefData().getPosition().pos; + insert->setPosition(f[0], f[1], f[2]); insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale); + // Convert MW rotation to a quaternion: f = ptr.getCellRef().pos.rot; @@ -132,7 +129,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) } } - if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects")) + if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { insert->attachObject(ent); @@ -144,18 +141,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) { Ogre::StaticGeometry* sg = 0; -/* if (transparent) - { - if( mStaticGeometryAlpha.find(ptr.getCell()) == mStaticGeometryAlpha.end()) - { - uniqueID = uniqueID +1; - sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); - mStaticGeometryAlpha[ptr.getCell()] = sg; - } - else - sg = mStaticGeometryAlpha[ptr.getCell()]; - } - else*/ if (small) + if (small) { if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) { @@ -207,35 +193,61 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f assert(insert); Ogre::Light *light = mRenderer.getScene()->createLight(); light->setDiffuseColour (r, g, b); - mLights.push_back(light->getName()); - float cval=0.0f, lval=0.0f, qval=0.0f; + ESMS::LiveCellRef *ref = + ptr.get(); - if(lightConst) - cval = lightConstValue; + LightInfo info; + info.name = light->getName(); + info.radius = radius; + info.colour = Ogre::ColourValue(r, g, b); - if(!lightOutQuadInLin) + if (ref->base->data.flags & ESM::Light::Negative) + info.colour *= -1; + + info.interior = (ptr.getCell()->cell->data.flags & ESM::Cell::Interior); + + if (ref->base->data.flags & ESM::Light::Flicker) + info.type = LT_Flicker; + else if (ref->base->data.flags & ESM::Light::FlickerSlow) + info.type = LT_FlickerSlow; + else if (ref->base->data.flags & ESM::Light::Pulse) + info.type = LT_Pulse; + else if (ref->base->data.flags & ESM::Light::PulseSlow) + info.type = LT_PulseSlow; + else + info.type = LT_Normal; + + // random starting phase for the animation + info.time = Ogre::Math::RangeRandom(0, 2 * M_PI); + + // adjust the lights depending if we're in an interior or exterior cell + // quadratic means the light intensity falls off quite fast, resulting in a + // dark, atmospheric environment (perfect for exteriors) + // for interiors, we want more "warm" lights, so use linear attenuation. + bool quadratic = false; + if (!lightOutQuadInLin) + quadratic = lightQuadratic; + else { - if(lightLinear) - radius *= lightLinearRadiusMult; - if(lightQuadratic) - radius *= lightQuadraticRadiusMult; + quadratic = !info.interior; + } - if(lightLinear) - lval = lightLinearValue / pow(radius, lightLinearMethod); - if(lightQuadratic) - qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); + if (!quadratic) + { + float r = radius * lightLinearRadiusMult; + float attenuation = lightLinearValue / r; + light->setAttenuation(r*10, 0, attenuation, 0); } else { - // FIXME: - // Do quadratic or linear, depending if we're in an exterior or interior - // cell, respectively. Ignore lightLinear and lightQuadratic. + float r = radius * lightQuadraticRadiusMult; + float attenuation = lightQuadraticValue / pow(r, 2); + light->setAttenuation(r*10, 0, 0, attenuation); } - light->setAttenuation(10*radius, cval, lval, qval); - insert->attachObject(light); + mLights.push_back(info); } bool Objects::deleteObject (const MWWorld::Ptr& ptr) @@ -290,13 +302,6 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store) mRenderer.getScene()->destroyStaticGeometry (sg); sg = 0; } - /*if(mStaticGeometryAlpha.find(store) != mStaticGeometryAlpha.end()) - { - Ogre::StaticGeometry* sg = mStaticGeometryAlpha[store]; - mStaticGeometryAlpha.erase(store); - mRenderer.getScene()->destroyStaticGeometry (sg); - sg = 0; - }*/ if(mBounds.find(store) != mBounds.end()) mBounds.erase(store); @@ -314,11 +319,6 @@ void Objects::buildStaticGeometry(ESMS::CellStore& cell) Ogre::StaticGeometry* sg = mStaticGeometrySmall[&cell]; sg->build(); } - /*if(mStaticGeometryAlpha.find(&cell) != mStaticGeometryAlpha.end()) - { - Ogre::StaticGeometry* sg = mStaticGeometryAlpha[&cell]; - sg->build(); - }*/ } Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell) @@ -328,12 +328,12 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell) void Objects::enableLights() { - std::vector::iterator it = mLights.begin(); + std::vector::iterator it = mLights.begin(); while (it != mLights.end()) { - if (mMwRoot->getCreator()->hasLight(*it)) + if (mMwRoot->getCreator()->hasLight(it->name)) { - mMwRoot->getCreator()->getLight(*it)->setVisible(true); + mMwRoot->getCreator()->getLight(it->name)->setVisible(true); ++it; } else @@ -343,12 +343,12 @@ void Objects::enableLights() void Objects::disableLights() { - std::vector::iterator it = mLights.begin(); + std::vector::iterator it = mLights.begin(); while (it != mLights.end()) { - if (mMwRoot->getCreator()->hasLight(*it)) + if (mMwRoot->getCreator()->hasLight(it->name)) { - mMwRoot->getCreator()->getLight(*it)->setVisible(false); + mMwRoot->getCreator()->getLight(it->name)->setVisible(false); ++it; } else @@ -356,3 +356,90 @@ void Objects::disableLights() } } +void Objects::update(const float dt) +{ + std::vector::iterator it = mLights.begin(); + while (it != mLights.end()) + { + if (mMwRoot->getCreator()->hasLight(it->name)) + { + Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name); + + // Light animation (pulse & flicker) + it->time += dt; + const float phase = std::fmod(static_cast (it->time), (32 * 2 * M_PI)) * 20; + float pulseConstant; + + // These formulas are just guesswork, but they work pretty well + if (it->type == LT_Normal) + { + // Less than 1/255 light modifier for a constant light: + pulseConstant = (const float)(1.0 + sin(phase) / 255.0 ); + } + else if (it->type == LT_Flicker) + { + // Let's do a 50% -> 100% sine wave pulse over 1 second: + // This is 75% +/- 25% + pulseConstant = (const float)(0.75 + sin(phase) * 0.25); + + // Then add a 25% flicker variation: + it->resetTime -= dt; + if (it->resetTime < 0) + { + it->flickerVariation = (rand() % 1000) / 1000 * 0.25; + it->resetTime = 0.5; + } + if (it->resetTime > 0.25) + { + pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime * 2.0f) + pulseConstant * it->resetTime * 2.0f; + } + else + { + pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime * 2.0f) + pulseConstant * (1-it->resetTime * 2.0f); + } + } + else if (it->type == LT_FlickerSlow) + { + // Let's do a 50% -> 100% sine wave pulse over 1 second: + // This is 75% +/- 25% + pulseConstant = (const float)(0.75 + sin(phase / 4.0) * 0.25); + + // Then add a 25% flicker variation: + it->resetTime -= dt; + if (it->resetTime < 0) + { + it->flickerVariation = (rand() % 1000) / 1000 * 0.25; + it->resetTime = 0.5; + } + if (it->resetTime > 0.5) + { + pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime) + pulseConstant * it->resetTime; + } + else + { + pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime) + pulseConstant * (1-it->resetTime); + } + } + else if (it->type == LT_Pulse) + { + // Let's do a 75% -> 125% sine wave pulse over 1 second: + // This is 100% +/- 25% + pulseConstant = (const float)(1.0 + sin(phase) * 0.25); + } + else if (it->type == LT_PulseSlow) + { + // Let's do a 75% -> 125% sine wave pulse over 1 second: + // This is 100% +/- 25% + pulseConstant = (const float)(1.0 + sin(phase / 4.0) * 0.25); + } + else + assert(0 && "Invalid light type"); + + light->setDiffuseColour( it->colour * pulseConstant ); + + ++it; + } + else + it = mLights.erase(it); + } +} diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 0c19f9f33..fb26808b9 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -10,27 +10,55 @@ namespace MWRender{ +/// information about light needed for rendering +enum LightType +{ + // These are all mutually exclusive + LT_Normal=0, + LT_Flicker=1, + LT_FlickerSlow=2, + LT_Pulse=3, + LT_PulseSlow=4 +}; + +struct LightInfo +{ + // Constants + std::string name; // ogre handle + Ogre::ColourValue colour; + float radius; + bool interior; // Does this light belong to an interior or exterior cell + LightType type; + + // Runtime variables + float flickerVariation; // 25% flicker variation, reset once every 0.5 seconds + float flickerSlowVariation; // 25% flicker variation, reset once every 1.0 seconds + float resetTime; + long double time; + + + LightInfo() : + flickerVariation(0), resetTime(0.5), + flickerSlowVariation(0), time(0), interior(true) + { + } +}; + class Objects{ OEngine::Render::OgreRenderer &mRenderer; std::map mCellSceneNodes; std::map mStaticGeometry; std::map mStaticGeometrySmall; - //std::map mStaticGeometryAlpha; std::map mBounds; - std::vector mLights; + std::vector mLights; Ogre::SceneNode* mMwRoot; bool mIsStatic; static int uniqueID; - static bool lightConst; - static float lightConstValue; - static bool lightLinear; - static int lightLinearMethod; static float lightLinearValue; static float lightLinearRadiusMult; static bool lightQuadratic; - static int lightQuadraticMethod; static float lightQuadraticValue; static float lightQuadraticRadiusMult; @@ -40,7 +68,7 @@ class Objects{ ///< Remove all movable objects from \a node. public: - Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){} + Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {} ~Objects(){} void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); @@ -49,6 +77,9 @@ public: void enableLights(); void disableLights(); + void update (const float dt); + ///< per-frame update + Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*); ///< get a bounding box that encloses all objects in the specified cell diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 80b804dce..6d3f67de9 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -65,6 +65,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQueryTotal->createBillboard(Vector3::ZERO); mBBQueryTotal->setMaterialName("QueryTotalPixels"); mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1); + mBBQueryTotal->setVisibilityFlags(RV_OcclusionQuery); mBBNodeReal->attachObject(mBBQueryTotal); mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); @@ -73,6 +74,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQueryVisible->createBillboard(Vector3::ZERO); mBBQueryVisible->setMaterialName("QueryVisiblePixels"); mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1); + mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery); mBBNodeReal->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); @@ -82,6 +84,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQuerySingleObject->createBillboard(Vector3::ZERO); mBBQuerySingleObject->setMaterialName("QueryVisiblePixels"); mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery); + mBBQuerySingleObject->setVisibilityFlags(RV_OcclusionQuery); mObjectNode->attachObject(mBBQuerySingleObject); mRendering->getScene()->addRenderObjectListener(this); diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index 2c7f9e9ac..c4aa093c0 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -52,6 +52,8 @@ enum VisibilityFlags // Sun glare (not visible in reflection) RV_Glare = 128, + RV_OcclusionQuery = 256, + RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water, /// \todo markers (normally hidden) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c1462807f..a95a179c6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -24,8 +24,8 @@ using namespace Ogre; namespace MWRender { -RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) - :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mSunEnabled(0) +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.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); @@ -52,11 +52,16 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // Load resources ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); + // Due to the huge world size of MW, we'll want camera-relative rendering. + // This prevents precision artifacts when moving very far from the origin. + mRendering.getScene()->setCameraRelativeRendering(true); + // disable unsupported effects const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (caps->getNumMultiRenderTargets() < 2) + if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("shader", "Water", false); - if (!caps->isShaderProfileSupported("fp40") && !caps->isShaderProfileSupported("ps_4_0")) + if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) + || !Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); // note that the order is important here @@ -93,19 +98,18 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mShadows = new Shadows(&mRendering); mShaderHelper = new ShaderHelper(this); - mTerrainManager = new TerrainManager(mRendering.getScene(), this, - environment); + mTerrainManager = new TerrainManager(mRendering.getScene(), this); //mSkyManager = 0; - mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment); + mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mSun = 0; - mDebugging = new Debugging(mMwRoot, environment, engine); - mLocalMap = new MWRender::LocalMap(&mRendering, this, &environment); + mDebugging = new Debugging(mMwRoot, engine); + mLocalMap = new MWRender::LocalMap(&mRendering, this); } RenderingManager::~RenderingManager () @@ -208,6 +212,7 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve void RenderingManager::update (float duration){ mActors.update (duration); + mObjects.update (duration); mOcclusionQuery->update(duration); @@ -220,6 +225,8 @@ void RenderingManager::update (float duration){ mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() ); checkUnderwater(); + + mWater->update(); } void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ if(store->cell->data.flags & store->cell->HasWater){ @@ -501,4 +508,14 @@ Shadows* RenderingManager::getShadows() return mShadows; } +void RenderingManager::switchToInterior() +{ + mRendering.getScene()->setCameraRelativeRendering(false); +} + +void RenderingManager::switchToExterior() +{ + mRendering.getScene()->setCameraRelativeRendering(true); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index a563d78c6..0d11b3d57 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -57,7 +57,7 @@ class RenderingManager: private RenderingInterface { virtual MWRender::Actors& getActors(); public: - RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment); + RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine); virtual ~RenderingManager(); @@ -117,6 +117,9 @@ class RenderingManager: private RenderingInterface { Shadows* getShadows(); + void switchToInterior(); + void switchToExterior(); + void setGlare(bool glare); void skyEnable (); void skyDisable (); diff --git a/apps/openmw/mwrender/shaderhelper.cpp b/apps/openmw/mwrender/shaderhelper.cpp index 5354251f8..1d29be2b8 100644 --- a/apps/openmw/mwrender/shaderhelper.cpp +++ b/apps/openmw/mwrender/shaderhelper.cpp @@ -256,9 +256,9 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s } outStream << - " float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n" + " float3 lightingFinal = lightColour.xyz * diffuse.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n" " float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n" - " oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour.xyz, fogValue); \n" + " oColor.xyz = lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue); \n" " oColor.a = tex.a * diffuse.a * vertexColour.a; \n"; if (mrt) outStream << diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index bf5602f43..9a4ae7243 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -66,7 +66,10 @@ void Shadows::recreate() if (split) { mPSSMSetup = new PSSMShadowCameraSetup(); - mPSSMSetup->setSplitPadding(5); + + // Make sure to keep this in sync with the camera's near clip distance! + mPSSMSetup->setSplitPadding(mRendering->getCamera()->getNearClipDistance()); + mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar); const Real adjustFactors[3] = {64, 64, 64}; diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 859da2dc1..da2e7446a 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -10,7 +10,7 @@ #include -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "renderconst.hpp" #include "renderingmanager.hpp" @@ -271,10 +271,10 @@ void Moon::setPhase(const Moon::Phase& phase) { // Colour texture Ogre::String textureName = "textures\\tx_"; - + if (mType == Moon::Type_Secunda) textureName += "secunda_"; else textureName += "masser_"; - + if (phase == Moon::Phase_New) textureName += "new"; else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax"; else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax"; @@ -283,9 +283,9 @@ void Moon::setPhase(const Moon::Phase& phase) else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan"; else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan"; else if (phase == Moon::Phase_Full) textureName += "full"; - + textureName += ".dds"; - + mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName); mPhase = phase; @@ -365,9 +365,8 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock(); } -SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env) - : mEnvironment(env) - , mHour(0.0f) +SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) + : mHour(0.0f) , mDay(0) , mMonth(0) , mSun(NULL) @@ -713,7 +712,7 @@ void SkyManager::update(float duration) if (!mEnabled) return; // UV Scroll the clouds - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", mEnvironment->mWorld->getTimeScaleFactor()/30.f); + mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); /// \todo improve this mMasser->setPhase( static_cast( (int) ((mDay % 32)/4.f)) ); @@ -752,7 +751,7 @@ void SkyManager::update(float duration) mSecunda->setVisible(mSecundaEnabled); // rotate the stars by 360 degrees every 4 days - mAtmosphereNight->roll(Degree(mEnvironment->mWorld->getTimeScaleFactor()*duration*360 / (3600*96.f))); + mAtmosphereNight->roll(Degree(MWBase::Environment::get().getWorld()->getTimeScaleFactor()*duration*360 / (3600*96.f))); } void SkyManager::enable() diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 64d5c16a0..da89d0eb0 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -59,8 +59,8 @@ namespace MWRender Ogre::MaterialPtr mMaterial; Ogre::BillboardSet* mBBSet; }; - - + + /* * The moons need a seperate class because of their shader (which allows them to be partially transparent) */ @@ -104,11 +104,11 @@ namespace MWRender Type mType; Phase mPhase; }; - + class SkyManager { public: - SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env); + SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera); ~SkyManager(); void update(float duration); @@ -176,7 +176,6 @@ namespace MWRender private: bool mCreated; - MWWorld::Environment* mEnvironment; float mHour; int mDay; int mMonth; diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index f9b43655b..90d853f75 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -4,6 +4,8 @@ #include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + #include "terrainmaterial.hpp" #include "terrain.hpp" #include "renderconst.hpp" @@ -17,8 +19,8 @@ namespace MWRender //---------------------------------------------------------------------------------------------- - TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& evn) : - mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) + TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) : + mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) { TerrainMaterialGeneratorPtr matGen; @@ -107,7 +109,7 @@ namespace MWRender const int cellX = store->cell->getGridX(); const int cellY = store->cell->getGridY(); - ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY); + ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); if ( land != NULL ) { if (!land->dataLoaded) @@ -268,7 +270,7 @@ namespace MWRender { //NB: All vtex ids are +1 compared to the ltex ids - assert( (int)mEnvironment.mWorld->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && + assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && "LAND.VTEX must be within the bounds of the LTEX array"); std::string texture; @@ -278,7 +280,7 @@ namespace MWRender } else { - texture = mEnvironment.mWorld->getStore().landTexts.search(ltexIndex-1)->texture; + texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1)->texture; //TODO this is needed due to MWs messed up texture handling texture = texture.substr(0, texture.rfind(".")) + ".dds"; } @@ -434,7 +436,7 @@ namespace MWRender } - ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY); + ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); if ( land != NULL ) { if (!land->dataLoaded) diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index dc4a2388c..c4ff053a6 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -24,7 +24,7 @@ namespace MWRender{ */ class TerrainManager{ public: - TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& env); + TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend); virtual ~TerrainManager(); void setDiffuse(const Ogre::ColourValue& diffuse); @@ -36,7 +36,6 @@ namespace MWRender{ Ogre::TerrainGlobalOptions mTerrainGlobals; Ogre::TerrainGroup mTerrainGroup; - const MWWorld::Environment& mEnvironment; RenderingManager* mRendering; Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile; diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index 9785ec903..a3265b2a5 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -1149,8 +1149,8 @@ namespace Ogre // simple per-pixel lighting with no normal mapping for (int i=0; igetNumberOfLightsSupported(); ++i) { - outStream << " float3 halfAngle"< 0) outStream << diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 71cf56dfd..c81f23f54 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -11,7 +11,8 @@ namespace MWRender Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) : mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), - mReflectionTarget(0), mActive(1), mToggled(1) + mReflectionTarget(0), mActive(1), mToggled(1), + mReflectionRenderActive(false) { mSky = sky; @@ -81,6 +82,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) : mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water"); + mSceneManager->addRenderQueueListener(this); + // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- @@ -161,6 +164,7 @@ void Water::changeCell(const ESM::Cell* cell) void Water::setHeight(const float height) { mTop = height; + mWaterPlane = Plane(Vector3::UNIT_Y, height); mWaterNode->setPosition(0, height, 0); } @@ -172,7 +176,12 @@ void Water::toggle() void Water::checkUnderwater(float y) { - if (!mActive) return; + if (!mActive) + { + CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); + return; + } + if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); @@ -220,17 +229,15 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance()); mReflectionCamera->setAspectRatio(mCamera->getAspectRatio()); mReflectionCamera->setFOVy(mCamera->getFOVy()); + mReflectionRenderActive = true; - // Some messy code to get the skybox to show up at all - // The problem here is that it gets clipped by the water plane - // Therefore scale it up a bit + /// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour.. + /// to circumvent this we just scale the sky up, so it's not that noticable Vector3 pos = mCamera->getRealPosition(); pos.y = mTop*2 - pos.y; mSky->setSkyPosition(pos); - mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f); - - mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop)); - mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop)); + mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f); + mReflectionCamera->enableReflection(mWaterPlane); } } @@ -240,8 +247,9 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) { mSky->resetSkyPosition(); mSky->scaleSky(1); - mReflectionCamera->disableCustomNearClipPlane(); mReflectionCamera->disableReflection(); + mReflectionCamera->disableCustomNearClipPlane(); + mReflectionRenderActive = false; } } @@ -290,4 +298,27 @@ void Water::updateVisible() mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater); } +void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) +{ + // We don't want the sky to get clipped by custom near clip plane (the water plane) + if (queueGroupId < 20 && mReflectionRenderActive) + { + mReflectionCamera->disableCustomNearClipPlane(); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); + } +} + +void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) +{ + if (queueGroupId < 20 && mReflectionRenderActive) + { + mReflectionCamera->enableCustomNearClipPlane(mWaterPlane); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); + } +} + +void Water::update() +{ +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index f14482e2b..c8b8d311e 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -11,7 +11,7 @@ namespace MWRender { class SkyManager; /// Water rendering - class Water : public Ogre::RenderTargetListener + class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; @@ -27,11 +27,17 @@ namespace MWRender { bool mToggled; int mTop; + bool mReflectionRenderActive; + Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); protected: void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + + void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); + void updateVisible(); SkyManager* mSky; @@ -55,6 +61,7 @@ namespace MWRender { void setActive(bool active); void toggle(); + void update(); void setViewportBackground(const Ogre::ColourValue& bg); diff --git a/apps/openmw/mwscript/animationextensions.cpp b/apps/openmw/mwscript/animationextensions.cpp index 184be83db..864a2bf1d 100644 --- a/apps/openmw/mwscript/animationextensions.cpp +++ b/apps/openmw/mwscript/animationextensions.cpp @@ -27,10 +27,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getWorld().skipAnimation (ptr); + MWBase::Environment::get().getWorld()->skipAnimation (ptr); } }; @@ -43,9 +40,6 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - InterpreterContext& context = - static_cast (runtime.getContext()); - std::string group = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -60,7 +54,7 @@ namespace MWScript throw std::runtime_error ("animation mode out of range"); } - context.getWorld().playAnimationGroup (ptr, group, mode, 1); + MWBase::Environment::get().getWorld()->playAnimationGroup (ptr, group, mode, 1); } }; @@ -73,9 +67,6 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - InterpreterContext& context = - static_cast (runtime.getContext()); - std::string group = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -96,7 +87,7 @@ namespace MWScript throw std::runtime_error ("animation mode out of range"); } - context.getWorld().playAnimationGroup (ptr, group, mode, loops); + MWBase::Environment::get().getWorld()->playAnimationGroup (ptr, group, mode, loops); } }; diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index d69c42ab3..a5db5fd5f 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -22,10 +24,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - - runtime.push (context.getWorld().hasCellChanged() ? 1 : 0); + runtime.push (MWBase::Environment::get().getWorld()->hasCellChanged() ? 1 : 0); } }; @@ -35,9 +34,6 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - std::string cell = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -45,16 +41,16 @@ namespace MWScript pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; pos.pos[2] = 0; - if (const ESM::Cell *exterior = context.getWorld().getExterior (cell)) + if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (cell)) { - context.getWorld().indexToPosition (exterior->data.gridX, exterior->data.gridY, + MWBase::Environment::get().getWorld()->indexToPosition (exterior->data.gridX, exterior->data.gridY, pos.pos[0], pos.pos[1], true); - context.getWorld().changeToExteriorCell (pos); + MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); } else { pos.pos[0] = pos.pos[1] = 0; - context.getWorld().changeToInteriorCell (cell, pos); + MWBase::Environment::get().getWorld()->changeToInteriorCell (cell, pos); } } }; @@ -65,9 +61,6 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - Interpreter::Type_Integer x = runtime[0].mInteger; runtime.pop(); @@ -76,12 +69,12 @@ namespace MWScript ESM::Position pos; - context.getWorld().indexToPosition (x, y, pos.pos[0], pos.pos[1], true); + MWBase::Environment::get().getWorld()->indexToPosition (x, y, pos.pos[0], pos.pos[1], true); pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - context.getWorld().changeToExteriorCell (pos); + MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); } }; @@ -91,11 +84,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - bool interior = - context.getWorld().getPlayer().getPlayer().getCell()->cell->data.flags & + MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->data.flags & ESM::Cell::Interior; runtime.push (interior ? 1 : 0); @@ -108,20 +98,17 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - const ESM::Cell *cell = context.getWorld().getPlayer().getPlayer().getCell()->cell; + const ESM::Cell *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell; std::string current = cell->name; if (!(cell->data.flags & ESM::Cell::Interior) && current.empty()) { const ESM::Region *region = - context.getWorld().getStore().regions.find (cell->region); + MWBase::Environment::get().getWorld()->getStore().regions.find (cell->region); current = region->name; } @@ -139,10 +126,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - - MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell(); + MWWorld::Ptr::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); runtime.push (cell->mWaterLevel); } }; @@ -153,18 +137,15 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - Interpreter::Type_Float level = runtime[0].mFloat; - MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell(); + MWWorld::Ptr::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); if (!(cell->cell->data.flags & ESM::Cell::Interior)) throw std::runtime_error("Can't set water level in exterior cell"); cell->mWaterLevel = level; - context.getEnvironment().mWorld->setWaterHeight(cell->mWaterLevel); + MWBase::Environment::get().getWorld()->setWaterHeight(cell->mWaterLevel); } }; @@ -174,18 +155,15 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - Interpreter::Type_Float level = runtime[0].mFloat; - MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell(); + MWWorld::Ptr::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); if (!(cell->cell->data.flags & ESM::Cell::Interior)) throw std::runtime_error("Can't set water level in exterior cell"); - + cell->mWaterLevel +=level; - context.getEnvironment().mWorld->setWaterHeight(cell->mWaterLevel); + MWBase::Environment::get().getWorld()->setWaterHeight(cell->mWaterLevel); } }; diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 15cc599a7..078d0da5e 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -1,48 +1,48 @@ #include "compilercontext.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" namespace MWScript { - CompilerContext::CompilerContext (Type type, const MWWorld::Environment& environment) - : mType (type), mEnvironment (environment) + CompilerContext::CompilerContext (Type type) + : mType (type) {} bool CompilerContext::canDeclareLocals() const { return mType==Type_Full; - } - + } + char CompilerContext::getGlobalType (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariableType (name); - } - + return MWBase::Environment::get().getWorld()->getGlobalVariableType (name); + } + bool CompilerContext::isId (const std::string& name) const { return - mEnvironment.mWorld->getStore().activators.search (name) || - mEnvironment.mWorld->getStore().potions.search (name) || - mEnvironment.mWorld->getStore().appas.search (name) || - mEnvironment.mWorld->getStore().armors.search (name) || - mEnvironment.mWorld->getStore().books.search (name) || - mEnvironment.mWorld->getStore().clothes.search (name) || - mEnvironment.mWorld->getStore().containers.search (name) || - mEnvironment.mWorld->getStore().creatures.search (name) || - mEnvironment.mWorld->getStore().doors.search (name) || - mEnvironment.mWorld->getStore().ingreds.search (name) || - mEnvironment.mWorld->getStore().creatureLists.search (name) || - mEnvironment.mWorld->getStore().itemLists.search (name) || - mEnvironment.mWorld->getStore().lights.search (name) || - mEnvironment.mWorld->getStore().lockpicks.search (name) || - mEnvironment.mWorld->getStore().miscItems.search (name) || - mEnvironment.mWorld->getStore().npcs.search (name) || - mEnvironment.mWorld->getStore().probes.search (name) || - mEnvironment.mWorld->getStore().repairs.search (name) || - mEnvironment.mWorld->getStore().statics.search (name) || - mEnvironment.mWorld->getStore().weapons.search (name); + MWBase::Environment::get().getWorld()->getStore().activators.search (name) || + MWBase::Environment::get().getWorld()->getStore().potions.search (name) || + MWBase::Environment::get().getWorld()->getStore().appas.search (name) || + MWBase::Environment::get().getWorld()->getStore().armors.search (name) || + MWBase::Environment::get().getWorld()->getStore().books.search (name) || + MWBase::Environment::get().getWorld()->getStore().clothes.search (name) || + MWBase::Environment::get().getWorld()->getStore().containers.search (name) || + MWBase::Environment::get().getWorld()->getStore().creatures.search (name) || + MWBase::Environment::get().getWorld()->getStore().doors.search (name) || + MWBase::Environment::get().getWorld()->getStore().ingreds.search (name) || + MWBase::Environment::get().getWorld()->getStore().creatureLists.search (name) || + MWBase::Environment::get().getWorld()->getStore().itemLists.search (name) || + MWBase::Environment::get().getWorld()->getStore().lights.search (name) || + MWBase::Environment::get().getWorld()->getStore().lockpicks.search (name) || + MWBase::Environment::get().getWorld()->getStore().miscItems.search (name) || + MWBase::Environment::get().getWorld()->getStore().npcs.search (name) || + MWBase::Environment::get().getWorld()->getStore().probes.search (name) || + MWBase::Environment::get().getWorld()->getStore().repairs.search (name) || + MWBase::Environment::get().getWorld()->getStore().statics.search (name) || + MWBase::Environment::get().getWorld()->getStore().weapons.search (name); } } - diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 7a3411bba..32b2f1881 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -3,44 +3,36 @@ #include -namespace MWWorld -{ - class Environment; -} - namespace MWScript { class CompilerContext : public Compiler::Context { public: - + enum Type { Type_Full, // global, local, targetted Type_Dialgoue, Type_Console }; - + private: - + Type mType; - const MWWorld::Environment& mEnvironment; - + public: - - CompilerContext (Type type, const MWWorld::Environment& environment); - + + CompilerContext (Type type); + /// Is the compiler allowed to declare local variables? - virtual bool canDeclareLocals() const; - - /// 'l: long, 's': short, 'f': float, ' ': does not exist. + virtual bool canDeclareLocals() const; + + /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; virtual bool isId (const std::string& name) const; - ///< Does \a name match an ID, that can be referenced? + ///< Does \a name match an ID, that can be referenced? }; } #endif - - diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index a0aba5db9..3e8658bf8 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -9,6 +9,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" @@ -29,9 +31,6 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string item = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -41,7 +40,7 @@ namespace MWScript if (count<0) throw std::runtime_error ("second argument for AddItem must be non-negative"); - MWWorld::ManualRef ref (context.getWorld().getStore(), item); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item); ref.getPtr().getRefData().setCount (count); diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 384e13e45..363a09b6b 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/player.hpp" #include "interpretercontext.hpp" @@ -46,7 +48,7 @@ namespace MWScript InterpreterContext& context = static_cast (runtime.getContext()); - bool enabled = context.getWorld().toggleCollisionMode(); + bool enabled = MWBase::Environment::get().getWorld()->toggleCollisionMode(); context.report (enabled ? "Collision -> On" : "Collision -> Off"); } diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index fec539d3e..b99d55999 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -23,16 +23,13 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string quest = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Integer index = runtime[0].mInteger; runtime.pop(); - context.getEnvironment().mJournal->addEntry (quest, index); + MWBase::Environment::get().getJournal()->addEntry (quest, index); } }; @@ -42,16 +39,13 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string quest = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Integer index = runtime[0].mInteger; runtime.pop(); - context.getEnvironment().mJournal->setJournalIndex (quest, index); + MWBase::Environment::get().getJournal()->setJournalIndex (quest, index); } }; @@ -61,13 +55,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string quest = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - int index = context.getEnvironment().mJournal->getJournalIndex (quest); + int index = MWBase::Environment::get().getJournal()->getJournalIndex (quest); runtime.push (index); @@ -80,13 +71,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string topic = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getEnvironment().mDialogueManager->addTopic(topic); + MWBase::Environment::get().getDialogueManager()->addTopic(topic); } }; @@ -96,9 +84,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - MWDialogue::DialogueManager* dialogue = context.getEnvironment().mDialogueManager; + MWDialogue::DialogueManager* dialogue = MWBase::Environment::get().getDialogueManager(); while(arg0>0) { std::string question = runtime.getStringLiteral (runtime[0].mInteger); @@ -124,9 +110,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - context.getEnvironment().mDialogueManager->startDialogue (ptr); + + MWBase::Environment::get().getDialogueManager()->startDialogue (ptr); } }; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 58960aac4..378b2412a 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -144,4 +144,5 @@ op 0x200014d: ModDisposition op 0x200014e: ModDisposition, explicit reference op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference -opcodes 0x2000151-0x3ffffff unused +op 0x2000151: ToggleFullHelp +opcodes 0x2000152-0x3ffffff unused diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 14930b828..eb96ba5e2 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -12,9 +12,9 @@ namespace MWScript : mStore (store), mScriptManager (scriptManager) { addScript ("Main"); - - for (ESMS::RecListT::MapType::const_iterator iter - (store.startScripts.list.begin()); + + for (ESMS::RecListT::MapType::const_iterator iter + (store.startScripts.list.begin()); iter != store.startScripts.list.end(); ++iter) addScript (iter->second.script); } @@ -23,15 +23,15 @@ namespace MWScript { if (mScripts.find (name)==mScripts.end()) if (const ESM::Script *script = mStore.scripts.find (name)) - { + { Locals locals; - + locals.configure (*script); - mScripts.insert (std::make_pair (name, std::make_pair (true, locals))); + mScripts.insert (std::make_pair (name, std::make_pair (true, locals))); } } - + void GlobalScripts::removeScript (const std::string& name) { std::map >::iterator iter = mScripts.find (name); @@ -39,31 +39,30 @@ namespace MWScript if (iter!=mScripts.end()) iter->second.first = false; } - + bool GlobalScripts::isRunning (const std::string& name) const { std::map >::const_iterator iter = mScripts.find (name); - + if (iter==mScripts.end()) return false; - + return iter->second.first; } - - void GlobalScripts::run (MWWorld::Environment& environment) + + void GlobalScripts::run() { for (std::map >::iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) { if (iter->second.first) { - MWScript::InterpreterContext interpreterContext (environment, + MWScript::InterpreterContext interpreterContext ( &iter->second.second, MWWorld::Ptr()); - mScriptManager.run (iter->first, interpreterContext); + mScriptManager.run (iter->first, interpreterContext); } } } } - diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 741968fcd..3d62e4d7a 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -11,11 +11,6 @@ namespace ESMS struct ESMStore; } -namespace MWWorld -{ - class Environment; -} - namespace MWScript { class ScriptManager; @@ -25,21 +20,20 @@ namespace MWScript const ESMS::ESMStore& mStore; ScriptManager& mScriptManager; std::map > mScripts; // running, local variables - + public: - + GlobalScripts (const ESMS::ESMStore& store, ScriptManager& scriptManager); - + void addScript (const std::string& name); - + void removeScript (const std::string& name); - + bool isRunning (const std::string& name) const; - - void run (MWWorld::Environment& environment); + + void run(); ///< run all active global scripts }; } #endif - diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 426378efc..c4d9e9fab 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwgui/window_manager.hpp" #include "../mwinput/inputmanager.hpp" @@ -26,10 +28,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getWindowManager().allow (mWindow); + MWBase::Environment::get().getWindowManager()->allow (mWindow); } }; @@ -45,10 +44,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getInputManager().setGuiMode(mDialogue); + MWBase::Environment::get().getInputManager()->setGuiMode(mDialogue); } }; @@ -63,7 +59,7 @@ namespace MWScript MWWorld::Ptr ptr = context.getReference(); - runtime.push (context.getWindowManager().readPressedButton()); + runtime.push (MWBase::Environment::get().getWindowManager()->readPressedButton()); } }; @@ -73,10 +69,17 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getEnvironment().mWindowManager->toggleFogOfWar(); + MWBase::Environment::get().getWindowManager()->toggleFogOfWar(); + } + }; + + class OpToggleFullHelp : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::Environment::get().getWindowManager()->toggleFullHelp(); } }; @@ -93,6 +96,7 @@ namespace MWScript const int opcodeShowRestMenu = 0x2000018; const int opcodeGetButtonPressed = 0x2000137; const int opcodeToggleFogOfWar = 0x2000145; + const int opcodeToggleFullHelp = 0x2000151; void registerExtensions (Compiler::Extensions& extensions) { @@ -101,7 +105,7 @@ namespace MWScript extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu); extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu); extensions.registerInstruction ("enablestatsreviewmenu", "", - opcodeEnableStatsReviewMenu); +opcodeEnableStatsReviewMenu); extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu); extensions.registerInstruction ("enablemagicmenu", "", opcodeEnableMagicMenu); @@ -117,6 +121,9 @@ namespace MWScript extensions.registerInstruction ("togglefogofwar", "", opcodeToggleFogOfWar); extensions.registerInstruction ("tfow", "", opcodeToggleFogOfWar); + + extensions.registerInstruction ("togglefullhelp", "", opcodeToggleFullHelp); + extensions.registerInstruction ("tfh", "", opcodeToggleFullHelp); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -154,6 +161,8 @@ namespace MWScript interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed); interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar); + + interpreter.installSegment5 (opcodeToggleFullHelp, new OpToggleFullHelp); } } } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 258493782..a369486fa 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -7,6 +7,8 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" #include "../mwgui/window_manager.hpp" @@ -15,6 +17,7 @@ #include "locals.hpp" #include "globalscripts.hpp" +#include "scriptmanager.hpp" namespace MWScript { @@ -23,7 +26,7 @@ namespace MWScript { if (!id.empty()) { - return mEnvironment.mWorld->getPtr (id, activeOnly); + return MWBase::Environment::get().getWorld()->getPtr (id, activeOnly); } else { @@ -39,7 +42,7 @@ namespace MWScript { if (!id.empty()) { - return mEnvironment.mWorld->getPtr (id, activeOnly); + return MWBase::Environment::get().getWorld()->getPtr (id, activeOnly); } else { @@ -50,9 +53,9 @@ namespace MWScript } } - InterpreterContext::InterpreterContext (MWWorld::Environment& environment, + InterpreterContext::InterpreterContext ( MWScript::Locals *locals, MWWorld::Ptr reference) - : mEnvironment (environment), mLocals (locals), mReference (reference), + : mLocals (locals), mReference (reference), mActivationHandled (false) {} @@ -107,7 +110,7 @@ namespace MWScript void InterpreterContext::messageBox (const std::string& message, const std::vector& buttons) { - mEnvironment.mWindowManager->messageBox (message, buttons); + MWBase::Environment::get().getWindowManager()->messageBox (message, buttons); } void InterpreterContext::report (const std::string& message) @@ -117,74 +120,74 @@ namespace MWScript bool InterpreterContext::menuMode() { - return mEnvironment.mWindowManager->isGuiMode(); + return MWBase::Environment::get().getWindowManager()->isGuiMode(); } int InterpreterContext::getGlobalShort (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mShort; + return MWBase::Environment::get().getWorld()->getGlobalVariable (name).mShort; } int InterpreterContext::getGlobalLong (const std::string& name) const { // a global long is internally a float. - return mEnvironment.mWorld->getGlobalVariable (name).mLong; + return MWBase::Environment::get().getWorld()->getGlobalVariable (name).mLong; } float InterpreterContext::getGlobalFloat (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mFloat; + return MWBase::Environment::get().getWorld()->getGlobalVariable (name).mFloat; } void InterpreterContext::setGlobalShort (const std::string& name, int value) { if (name=="gamehour") - mEnvironment.mWorld->setHour (value); + MWBase::Environment::get().getWorld()->setHour (value); else if (name=="day") - mEnvironment.mWorld->setDay (value); + MWBase::Environment::get().getWorld()->setDay (value); else if (name=="month") - mEnvironment.mWorld->setMonth (value); + MWBase::Environment::get().getWorld()->setMonth (value); else - mEnvironment.mWorld->getGlobalVariable (name).mShort = value; + MWBase::Environment::get().getWorld()->getGlobalVariable (name).mShort = value; } void InterpreterContext::setGlobalLong (const std::string& name, int value) { if (name=="gamehour") - mEnvironment.mWorld->setHour (value); + MWBase::Environment::get().getWorld()->setHour (value); else if (name=="day") - mEnvironment.mWorld->setDay (value); + MWBase::Environment::get().getWorld()->setDay (value); else if (name=="month") - mEnvironment.mWorld->setMonth (value); + MWBase::Environment::get().getWorld()->setMonth (value); else - mEnvironment.mWorld->getGlobalVariable (name).mLong = value; + MWBase::Environment::get().getWorld()->getGlobalVariable (name).mLong = value; } void InterpreterContext::setGlobalFloat (const std::string& name, float value) { if (name=="gamehour") - mEnvironment.mWorld->setHour (value); + MWBase::Environment::get().getWorld()->setHour (value); else if (name=="day") - mEnvironment.mWorld->setDay (value); + MWBase::Environment::get().getWorld()->setDay (value); else if (name=="month") - mEnvironment.mWorld->setMonth (value); + MWBase::Environment::get().getWorld()->setMonth (value); else - mEnvironment.mWorld->getGlobalVariable (name).mFloat = value; + MWBase::Environment::get().getWorld()->getGlobalVariable (name).mFloat = value; } bool InterpreterContext::isScriptRunning (const std::string& name) const { - return mEnvironment.mGlobalScripts->isRunning (name); + return MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name); } void InterpreterContext::startScript (const std::string& name) { - mEnvironment.mGlobalScripts->addScript (name); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name); } void InterpreterContext::stopScript (const std::string& name) { - mEnvironment.mGlobalScripts->removeScript (name); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().removeScript (name); } float InterpreterContext::getDistance (const std::string& name, const std::string& id) const @@ -192,7 +195,7 @@ namespace MWScript // TODO handle exterior cells (when ref and ref2 are located in different cells) const MWWorld::Ptr ref2 = getReference (id, false); - const MWWorld::Ptr ref = mEnvironment.mWorld->getPtr (name, true); + const MWWorld::Ptr ref = MWBase::Environment::get().getWorld()->getPtr (name, true); double diff[3]; @@ -233,7 +236,7 @@ namespace MWScript if (!mAction.get()) throw std::runtime_error ("activation failed, because no action to perform"); - mAction->execute (mEnvironment); + mAction->execute(); mActivationHandled = true; } @@ -246,7 +249,7 @@ namespace MWScript float InterpreterContext::getSecondsPassed() const { - return mEnvironment.mFrameDuration; + return MWBase::Environment::get().getFrameDuration(); } bool InterpreterContext::isDisabled (const std::string& id) const @@ -258,38 +261,13 @@ namespace MWScript void InterpreterContext::enable (const std::string& id) { MWWorld::Ptr ref = getReference (id, false); - mEnvironment.mWorld->enable (ref); + MWBase::Environment::get().getWorld()->enable (ref); } void InterpreterContext::disable (const std::string& id) { MWWorld::Ptr ref = getReference (id, false); - mEnvironment.mWorld->disable (ref); - } - - MWWorld::Environment& InterpreterContext::getEnvironment() - { - return mEnvironment; - } - - MWGui::WindowManager& InterpreterContext::getWindowManager() - { - return *mEnvironment.mWindowManager; - } - - MWInput::MWInputManager& InterpreterContext::getInputManager() - { - return *mEnvironment.mInputManager; - } - - MWWorld::World& InterpreterContext::getWorld() - { - return *mEnvironment.mWorld; - } - - MWSound::SoundManager& InterpreterContext::getSoundManager() - { - return *mEnvironment.mSoundManager; + MWBase::Environment::get().getWorld()->disable (ref); } MWWorld::Ptr InterpreterContext::getReference() diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 35b4a169d..40f53337d 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -6,7 +6,6 @@ #include #include "../mwworld/ptr.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/action.hpp" @@ -26,7 +25,6 @@ namespace MWScript class InterpreterContext : public Interpreter::Context { - MWWorld::Environment& mEnvironment; Locals *mLocals; MWWorld::Ptr mReference; @@ -40,8 +38,7 @@ namespace MWScript public: - InterpreterContext (MWWorld::Environment& environment, - MWScript::Locals *locals, MWWorld::Ptr reference); + InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference); ///< The ownership of \a locals is not transferred. 0-pointer allowed. virtual int getLocalShort (int index) const; @@ -110,18 +107,6 @@ namespace MWScript virtual void disable (const std::string& id = ""); - MWWorld::Environment& getEnvironment(); - - /// \todo remove the following functions (extentions should use getEnvironment instead) - - MWWorld::World& getWorld(); - - MWSound::SoundManager& getSoundManager(); - - MWGui::WindowManager& getWindowManager(); - - MWInput::MWInputManager& getInputManager(); - MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index a0770b9a8..4ba523937 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/class.hpp" #include "interpretercontext.hpp" @@ -100,7 +102,7 @@ namespace MWScript static_cast (runtime.getContext()); bool enabled = - context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug); + MWBase::Environment::get().getWorld()->toggleRenderMode (MWWorld::World::Render_CollisionDebug); context.report (enabled ? "Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off"); @@ -117,7 +119,7 @@ namespace MWScript static_cast (runtime.getContext()); bool enabled = - context.getWorld().toggleRenderMode (MWWorld::World::Render_Wireframe); + MWBase::Environment::get().getWorld()->toggleRenderMode (MWWorld::World::Render_Wireframe); context.report (enabled ? "Wireframe Rendering -> On" : "Wireframe Rendering -> Off"); @@ -133,7 +135,7 @@ namespace MWScript static_cast (runtime.getContext()); bool enabled = - context.getWorld().toggleRenderMode (MWWorld::World::Render_Pathgrid); + MWBase::Environment::get().getWorld()->toggleRenderMode (MWWorld::World::Render_Pathgrid); context.report (enabled ? "Path Grid rendering -> On" : "Path Grid Rendering -> Off"); @@ -146,13 +148,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); - context.getWorld().getFader()->fadeIn(time); + MWBase::Environment::get().getWorld()->getFader()->fadeIn(time); } }; @@ -162,13 +161,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); - context.getWorld().getFader()->fadeOut(time); + MWBase::Environment::get().getWorld()->getFader()->fadeOut(time); } }; @@ -178,16 +174,13 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - Interpreter::Type_Float alpha = runtime[0].mFloat; runtime.pop(); Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); - context.getWorld().getFader()->fadeTo(alpha, time); + MWBase::Environment::get().getWorld()->getFader()->fadeTo(alpha, time); } }; @@ -197,10 +190,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getWorld().toggleWater(); + MWBase::Environment::get().getWorld()->toggleWater(); } }; diff --git a/apps/openmw/mwscript/ref.hpp b/apps/openmw/mwscript/ref.hpp index 5ca1ea4d6..28093c4e5 100644 --- a/apps/openmw/mwscript/ref.hpp +++ b/apps/openmw/mwscript/ref.hpp @@ -5,6 +5,8 @@ #include +#include "../mwbase/environment.hpp" + #include "../mwworld/ptr.hpp" #include "../mwworld/world.hpp" @@ -16,13 +18,10 @@ namespace MWScript { MWWorld::Ptr operator() (Interpreter::Runtime& runtime) const { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - return context.getWorld().getPtr (id, false); + return MWBase::Environment::get().getWorld()->getPtr (id, false); } }; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index e93f2deec..506cf049c 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -20,7 +20,7 @@ namespace MWScript Compiler::Context& compilerContext) : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext), - mOpcodesInstalled (false) + mOpcodesInstalled (false), mGlobalScripts (store, *this) {} bool ScriptManager::compile (const std::string& name) @@ -151,4 +151,9 @@ namespace MWScript return iter->second.second; } + + GlobalScripts& ScriptManager::getGlobalScripts() + { + return mGlobalScripts; + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index 35cbc0d1e..35c1fadd9 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -11,6 +11,8 @@ #include #include +#include "globalscripts.hpp" + namespace ESMS { struct ESMStore; @@ -42,8 +44,8 @@ namespace MWScript typedef std::pair, Compiler::Locals> CompiledScript; typedef std::map ScriptCollection; - ScriptCollection mScripts; + GlobalScripts mGlobalScripts; public: @@ -63,6 +65,8 @@ namespace MWScript Compiler::Locals& getLocals (const std::string& name); ///< Return locals for script \a name. + + GlobalScripts& getGlobalScripts(); }; }; diff --git a/apps/openmw/mwscript/skyextensions.cpp b/apps/openmw/mwscript/skyextensions.cpp index a5cc9e213..e16c2ec23 100644 --- a/apps/openmw/mwscript/skyextensions.cpp +++ b/apps/openmw/mwscript/skyextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "interpretercontext.hpp" namespace MWScript @@ -19,11 +21,11 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { + bool enabled = MWBase::Environment::get().getWorld()->toggleSky(); + InterpreterContext& context = static_cast (runtime.getContext()); - bool enabled = context.getWorld().toggleSky(); - context.report (enabled ? "Sky -> On" : "Sky -> Off"); } }; @@ -34,10 +36,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getWorld().setMoonColour (false); + MWBase::Environment::get().getWorld()->setMoonColour (false); } }; @@ -47,10 +46,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.getWorld().setMoonColour (true); + MWBase::Environment::get().getWorld()->setMoonColour (true); } }; @@ -60,10 +56,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - runtime.push (context.getWorld().getMasserPhase()); + runtime.push (MWBase::Environment::get().getWorld()->getMasserPhase()); } }; @@ -73,42 +66,33 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - runtime.push (context.getWorld().getSecundaPhase()); + runtime.push (MWBase::Environment::get().getWorld()->getSecundaPhase()); } }; - + class OpGetCurrentWeather : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - runtime.push (context.getWorld().getCurrentWeather()); + runtime.push (MWBase::Environment::get().getWorld()->getCurrentWeather()); } }; - + class OpChangeWeather : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - std::string region = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - + Interpreter::Type_Integer id = runtime[0].mInteger; runtime.pop(); - - context.getWorld().changeWeather(region, id); + + MWBase::Environment::get().getWorld()->changeWeather(region, id); } }; diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index b4386a8a0..c2b45641a 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" #include "../mwsound/soundmanager.hpp" @@ -36,7 +38,7 @@ namespace MWScript std::string text = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().say (ptr, file); + MWBase::Environment::get().getSoundManager()->say (ptr, file); context.messageBox (text); } }; @@ -50,10 +52,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - - runtime.push (context.getSoundManager().sayDone (ptr)); + runtime.push (MWBase::Environment::get().getSoundManager()->sayDone (ptr)); } }; @@ -63,13 +62,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().streamMusic (sound); + MWBase::Environment::get().getSoundManager()->streamMusic (sound); } }; @@ -79,13 +75,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().playSound (sound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } }; @@ -95,9 +88,6 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -107,7 +97,7 @@ namespace MWScript Interpreter::Type_Float pitch = runtime[0].mFloat; runtime.pop(); - context.getSoundManager().playSound (sound, volume, pitch); + MWBase::Environment::get().getSoundManager()->playSound (sound, volume, pitch); } }; @@ -124,13 +114,10 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.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 ? MWSound::Play_Loop : 0); } }; @@ -147,9 +134,6 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -159,7 +143,7 @@ namespace MWScript Interpreter::Type_Float pitch = runtime[0].mFloat; runtime.pop(); - context.getSoundManager().playSound3D (ptr, sound, volume, pitch, mLoop ? MWSound::Play_Loop : 0); + MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, volume, pitch, mLoop ? MWSound::Play_Loop : 0); } }; @@ -173,13 +157,10 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().stopSound3D (ptr, sound); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr, sound); } }; @@ -192,13 +173,10 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - int index = runtime[0].mInteger; runtime.pop(); - runtime.push (context.getSoundManager().getSoundPlaying ( + runtime.push (MWBase::Environment::get().getSoundManager()->getSoundPlaying ( ptr, runtime.getStringLiteral (index))); } }; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 239f8d768..cad52e593 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -7,8 +7,9 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwworld/class.hpp" -#include "../mwworld/environment.hpp" #include "../mwworld/player.hpp" #include "../mwmechanics/creaturestats.hpp" @@ -351,11 +352,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); + if(arg0==0) { - factionID = context.getEnvironment().mDialogueManager->getFaction(); + factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { @@ -364,7 +364,7 @@ namespace MWScript } if(factionID != "") { - MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0; @@ -380,11 +380,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); + if(arg0==0) { - factionID = context.getEnvironment().mDialogueManager->getFaction(); + factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { @@ -393,7 +392,7 @@ namespace MWScript } if(factionID != "") { - MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0; @@ -413,11 +412,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); + if(arg0==0) { - factionID = context.getEnvironment().mDialogueManager->getFaction(); + factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { @@ -426,7 +424,7 @@ namespace MWScript } if(factionID != "") { - MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] -1; @@ -461,9 +459,7 @@ namespace MWScript factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.begin()->first; } } - MWScript::InterpreterContext& context - = static_cast (runtime.getContext()); - MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(factionID!="") { if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) @@ -481,7 +477,7 @@ namespace MWScript } } }; - + template class OpModDisposition : public Interpreter::Opcode0 { diff --git a/apps/openmw/mwsound/mpgsnd_decoder.cpp b/apps/openmw/mwsound/mpgsnd_decoder.cpp index 9b91b4e74..7f7a84889 100644 --- a/apps/openmw/mwsound/mpgsnd_decoder.cpp +++ b/apps/openmw/mwsound/mpgsnd_decoder.cpp @@ -189,7 +189,7 @@ void MpgSnd_Decoder::readAll(std::vector &output) { size_t pos = output.size(); output.resize(pos + mSndInfo.frames*mSndInfo.channels*2); - sf_readf_short(mSndFile, (short*)(output.data()+pos), mSndInfo.frames); + sf_readf_short(mSndFile, (short*)(&output[0]+pos), mSndInfo.frames); return; } // Fallback in case we don't know the total already diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 615def701..ac4baa8b2 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -222,8 +222,8 @@ void OpenAL_SoundStream::play() for(ALuint i = 0;i < sNumBuffers;i++) { size_t got; - got = mDecoder->read(data.data(), data.size()); - alBufferData(mBuffers[i], mFormat, data.data(), got, mSampleRate); + got = mDecoder->read(&data[0], data.size()); + alBufferData(mBuffers[i], mFormat, &data[0], got, mSampleRate); } throwALerror(); @@ -299,11 +299,11 @@ bool OpenAL_SoundStream::process() if(finished) continue; - got = mDecoder->read(data.data(), data.size()); + got = mDecoder->read(&data[0], data.size()); finished = (got < data.size()); if(got > 0) { - alBufferData(bufid, mFormat, data.data(), got, mSampleRate); + alBufferData(bufid, mFormat, &data[0], got, mSampleRate); alSourceQueueBuffers(mSource, 1, &bufid); } } while(processed > 0); @@ -595,7 +595,7 @@ ALuint OpenAL_Output::getBuffer(const std::string &fname) alGenBuffers(1, &buf); throwALerror(); - alBufferData(buf, format, data.data(), data.size(), srate); + alBufferData(buf, format, &data[0], data.size(), srate); mBufferCache[fname] = buf; mBufferRefs[buf] = 1; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 730d9d9b2..9eefc7a28 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -9,7 +9,8 @@ #include #include -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" + #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -46,9 +47,8 @@ namespace MWSound { - SoundManager::SoundManager(bool useSound, MWWorld::Environment& environment) + SoundManager::SoundManager(bool useSound) : mResourceMgr(Ogre::ResourceGroupManager::getSingleton()) - , mEnvironment(environment) , mOutput(new DEFAULT_OUTPUT(*this)) , mMasterVolume(1.0f) , mSFXVolume(1.0f) @@ -113,7 +113,7 @@ namespace MWSound std::string SoundManager::lookup(const std::string &soundId, float &volume, float &min, float &max) { - const ESM::Sound *snd = mEnvironment.mWorld->getStore().sounds.search(soundId); + const ESM::Sound *snd = MWBase::Environment::get().getWorld()->getStore().sounds.search(soundId); if(snd == NULL) throw std::runtime_error(std::string("Failed to lookup sound ")+soundId); @@ -228,11 +228,47 @@ namespace MWSound } } + void SoundManager::say(const std::string& filename) + { + if(!mOutput->isInitialized()) + return; + try + { + float basevol = mMasterVolume * mSFXVolume; + std::string filePath = "Sound/"+filename; + + SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); + sound->mBaseVolume = basevol; + + mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound")); + } + catch(std::exception &e) + { + std::cout <<"Sound Error: "<second.first == ptr && snditer->second.second == "_say_sound") + { + snditer->first->stop(); + mActiveSounds.erase(snditer++); + } + else + snditer++; + } + } + + SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode) { @@ -380,7 +416,7 @@ namespace MWSound void SoundManager::updateRegionSound(float duration) { - MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); + MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); static int total = 0; static std::string regionName = ""; static float timePassed = 0.0; @@ -397,7 +433,7 @@ namespace MWSound total = 0; } - const ESM::Region *regn = mEnvironment.mWorld->getStore().regions.find(regionName); + const ESM::Region *regn = MWBase::Environment::get().getWorld()->getStore().regions.find(regionName); std::vector::const_iterator soundIter; if(total == 0) { @@ -445,8 +481,8 @@ namespace MWSound if(!isMusicPlaying()) startRandomTitle(); - const ESM::Cell *cell = mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell; - Ogre::Camera *cam = mEnvironment.mWorld->getPlayer().getRenderer()->getCamera(); + 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(); diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index d64db299b..e1816cd1f 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -16,11 +16,6 @@ namespace Ogre class Camera; } -namespace MWWorld -{ - struct Environment; -} - namespace MWSound { class Sound_Output; @@ -52,8 +47,6 @@ namespace MWSound { Ogre::ResourceGroupManager& mResourceMgr; - MWWorld::Environment& mEnvironment; - std::auto_ptr mOutput; float mMasterVolume; @@ -82,7 +75,7 @@ namespace MWSound friend class OpenAL_Output; public: - SoundManager(bool useSound, MWWorld::Environment& environment); + SoundManager(bool useSound); ~SoundManager(); void stopMusic(); @@ -104,11 +97,18 @@ namespace MWSound void say(MWWorld::Ptr reference, const std::string& filename); ///< Make an actor say some text. - /// \param filename name of a sound file in "Sound/Vo/" in the data directory. + /// \param filename name of a sound file in "Sound/" in the data directory. - bool sayDone(MWWorld::Ptr reference) const; + 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; ///< Is actor not speaking? + 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); ///< Play a sound, independently of 3D-position diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index 155819335..d5cf12779 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -3,8 +3,6 @@ namespace MWWorld { - class Environment; - /// \brief Abstract base for actions class Action { @@ -18,7 +16,7 @@ namespace MWWorld virtual ~Action() {} - virtual void execute (Environment& environment) = 0; + virtual void execute() = 0; }; } diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index bbe954049..b1e2e1fc3 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -1,8 +1,9 @@ #include "actiontake.hpp" +#include "../mwbase/environment.hpp" + #include "class.hpp" -#include "environment.hpp" #include "world.hpp" #include "containerstore.hpp" @@ -10,14 +11,14 @@ namespace MWWorld { ActionTake::ActionTake (const MWWorld::Ptr& object) : mObject (object) {} - void ActionTake::execute (Environment& environment) + void ActionTake::execute() { // insert into player's inventory - MWWorld::Ptr player = environment.mWorld->getPtr ("player", true); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true); MWWorld::Class::get (player).getContainerStore (player).add (mObject); // remove from world - environment.mWorld->deleteObject (mObject); + MWBase::Environment::get().getWorld()->deleteObject (mObject); } } diff --git a/apps/openmw/mwworld/actiontake.hpp b/apps/openmw/mwworld/actiontake.hpp index 509ebc6bb..f495fc3c4 100644 --- a/apps/openmw/mwworld/actiontake.hpp +++ b/apps/openmw/mwworld/actiontake.hpp @@ -14,7 +14,7 @@ namespace MWWorld ActionTake (const MWWorld::Ptr& object); - virtual void execute (Environment& environment); + virtual void execute(); }; } diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 7d38c22fd..b33b78832 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -1,7 +1,7 @@ #include "actiontalk.hpp" -#include "environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwdialogue/dialoguemanager.hpp" @@ -9,8 +9,8 @@ namespace MWWorld { ActionTalk::ActionTalk (const Ptr& actor) : mActor (actor) {} - void ActionTalk::execute (Environment& environment) + void ActionTalk::execute() { - environment.mDialogueManager->startDialogue (mActor); + MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } } diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index a60a61660..1b7b9b6d6 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -15,7 +15,7 @@ namespace MWWorld ActionTalk (const Ptr& actor); ///< \param actor The actor the player is talking to - virtual void execute (Environment& environment); + virtual void execute(); }; } diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 207e2c50e..6ebbd7b7f 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -1,7 +1,8 @@ #include "actionteleport.hpp" -#include "environment.hpp" +#include "../mwbase/environment.hpp" + #include "world.hpp" namespace MWWorld @@ -11,11 +12,11 @@ namespace MWWorld : mCellName (cellName), mPosition (position) {} - void ActionTeleportPlayer::execute (Environment& environment) + void ActionTeleportPlayer::execute() { if (mCellName.empty()) - environment.mWorld->changeToExteriorCell (mPosition); + MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition); else - environment.mWorld->changeToInteriorCell (mCellName, mPosition); + MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, mPosition); } } diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index e4c972a9e..00efdc876 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -19,7 +19,7 @@ namespace MWWorld ActionTeleportPlayer (const std::string& cellName, const ESM::Position& position); ///< If cellName is empty, an exterior cell is asumed. - virtual void execute (Environment& environment); + virtual void execute(); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 2dd8aee1e..2e2920513 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -27,17 +27,17 @@ namespace MWWorld } - void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics) const { } - void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const + void Class::enable (const Ptr& ptr) const { } - void Class::disable (const Ptr& ptr, MWWorld::Environment& environment) const + void Class::disable (const Ptr& ptr) const { } @@ -62,14 +62,12 @@ namespace MWWorld throw std::runtime_error ("class does not have item health"); } - boost::shared_ptr Class::activate (const Ptr& ptr, const Ptr& actor, - const Environment& environment) const + boost::shared_ptr Class::activate (const Ptr& ptr, const Ptr& actor) const { return boost::shared_ptr (new NullAction); } - boost::shared_ptr Class::use (const Ptr& ptr, - const Environment& environment) const + boost::shared_ptr Class::use (const Ptr& ptr) const { return boost::shared_ptr (new NullAction); } @@ -134,7 +132,7 @@ namespace MWWorld return std::make_pair (std::vector(), false); } - int Class::getEquipmentSkill (const Ptr& ptr, const Environment& environment) const + int Class::getEquipmentSkill (const Ptr& ptr) const { return -1; } @@ -164,18 +162,29 @@ namespace MWWorld sClasses.insert (std::make_pair (key, instance)); } - std::string Class::getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const + std::string Class::getUpSoundId (const Ptr& ptr) const { throw std::runtime_error ("class does not have an up sound"); } - std::string Class::getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const + std::string Class::getDownSoundId (const Ptr& ptr) const { throw std::runtime_error ("class does not have an down sound"); } + std::string Class::getInventoryIcon (const MWWorld::Ptr& ptr) const { throw std::runtime_error ("class does not have any inventory icon"); } + + MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr) const + { + throw std::runtime_error ("class does not have a tool tip"); + } + + bool Class::hasToolTip (const Ptr& ptr) const + { + return false; + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index eaa0d5f6f..63e417d7e 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -12,6 +12,7 @@ #include "physicssystem.hpp" #include "../mwrender/renderinginterface.hpp" +#include "../mwgui/tooltips.hpp" namespace Ogre { @@ -33,7 +34,6 @@ namespace MWMechanics namespace MWWorld { class Ptr; - class Environment; class ContainerStore; class InventoryStore; @@ -65,15 +65,15 @@ namespace MWWorld /// (default implementation: throw an exception) virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; - virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). - virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const; + virtual void enable (const Ptr& ptr) const; ///< Enable reference; only does the non-rendering part (default implementation: ignore) /// \attention This is not the same as the script instruction with the same name. References /// should only be enabled while in an active cell. - virtual void disable (const Ptr& ptr, MWWorld::Environment& environment) const; + virtual void disable (const Ptr& ptr) const; ///< Enable reference; only does the non-rendering part (default implementation: ignore) /// \attention This is not the same as the script instruction with the same name. References /// should only be enabled while in an active cell. @@ -86,6 +86,12 @@ namespace MWWorld ///< Return creature stats or throw an exception, if class does not have creature stats /// (default implementation: throw an exceoption) + virtual bool hasToolTip (const Ptr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: false) + + virtual MWGui::ToolTipInfo getToolTipInfo (const Ptr& ptr) const; + ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual MWMechanics::NpcStats& getNpcStats (const Ptr& ptr) const; ///< Return NPC stats or throw an exception, if class does not have NPC stats /// (default implementation: throw an exceoption) @@ -97,11 +103,10 @@ namespace MWWorld ///< Return item max health or throw an exception, if class does not have item health /// (default implementation: throw an exceoption) - virtual boost::shared_ptr activate (const Ptr& ptr, const Ptr& actor, - const Environment& environment) const; + virtual boost::shared_ptr activate (const Ptr& ptr, const Ptr& actor) const; ///< Generate action for activation (default implementation: return a null action). - virtual boost::shared_ptr use (const Ptr& ptr, const Environment& environment) + virtual boost::shared_ptr use (const Ptr& ptr) const; ///< Generate action for using via inventory menu (default implementation: return a /// null action). @@ -149,7 +154,7 @@ namespace MWWorld /// /// Default implementation: return (empty vector, false). - virtual int getEquipmentSkill (const Ptr& ptr, const Environment& environment) + virtual int getEquipmentSkill (const Ptr& ptr) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. @@ -167,11 +172,11 @@ namespace MWWorld static void registerClass (const std::string& key, boost::shared_ptr instance); - virtual std::string getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getUpSoundId (const Ptr& ptr) const; ///< Return the up sound ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) - virtual std::string getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const; + virtual std::string getDownSoundId (const Ptr& ptr) const; ///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp deleted file mode 100644 index 3a83f886f..000000000 --- a/apps/openmw/mwworld/environment.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef GAME_WORLD_INVIRONMENT_H -#define GAME_WORLD_INVIRONMENT_H - -namespace MWSound -{ - class SoundManager; -} - -namespace MWScript -{ - class GlobalScripts; - class ScriptManager; -} - -namespace MWGui -{ - class WindowManager; -} - -namespace MWMechanics -{ - class MechanicsManager; -} - -namespace MWDialogue -{ - class DialogueManager; - class Journal; -} - -namespace MWInput -{ - struct MWInputManager; -} - -namespace MWWorld -{ - class World; - - ///< Collection of script-accessable sub-systems - class Environment - { - public: - Environment() - : mWorld (0), mSoundManager (0), mGlobalScripts (0), mScriptManager (0), mWindowManager (0), - mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0), - mInputManager (0) - {} - - World *mWorld; - MWSound::SoundManager *mSoundManager; - MWScript::GlobalScripts *mGlobalScripts; - MWScript::ScriptManager *mScriptManager; - MWGui::WindowManager *mWindowManager; - MWMechanics::MechanicsManager *mMechanicsManager; - MWDialogue::DialogueManager *mDialogueManager; - MWDialogue::Journal *mJournal; - float mFrameDuration; - - // For setting GUI mode - MWInput::MWInputManager *mInputManager; - }; -} - -#endif diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 650418201..576f2371f 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -8,8 +8,6 @@ #include "class.hpp" -#include /// \todo remove after rendering is implemented - void MWWorld::InventoryStore::copySlots (const InventoryStore& store) { // some const-trickery, required because of a flaw in the handling of MW-references and the @@ -96,8 +94,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) return mSlots[slot]; } -void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats, - const Environment& environment) +void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) { TSlots slots; initSlots (slots); @@ -105,7 +102,7 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats, for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { Ptr test = *iter; - int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test, environment); + int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test); std::pair, bool> itemsSlots = MWWorld::Class::get (*iter).getEquipmentSlots (*iter); @@ -125,7 +122,7 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats, { // check skill int oldSkill = - MWWorld::Class::get (old).getEquipmentSkill (old, environment); + MWWorld::Class::get (old).getEquipmentSkill (old); if (testSkill!=-1 || oldSkill!=-1 || testSkill!=oldSkill) { @@ -169,13 +166,5 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats, { mSlots.swap (slots); flagAsModified(); - - /// \todo remove the following line after rendering is implemented - for (std::size_t i=0; imEngine = mEngine; } PhysicsSystem::~PhysicsSystem() { delete mEngine; - + } OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() { return mEngine; } - + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) { std::string handle = ""; @@ -62,6 +66,13 @@ namespace MWWorld return mEngine->rayTest2(from,to); } + void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){ + playerphysics->hasWater = hasWater; + if(hasWater){ + playerphysics->waterHeight = waterHeight; + } + + } btVector3 PhysicsSystem::getRayPoint(float extent) { @@ -72,21 +83,19 @@ namespace MWWorld btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); return result; } - + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { btVector3 _from, _to; _from = btVector3(from.x, from.y, from.z); _to = btVector3(to.x, to.y, to.z); - + std::pair result = mEngine->rayTest(_from, _to); - + return !(result.first == ""); } - - std::vector< std::pair > PhysicsSystem::doPhysics (float duration, - const std::vector >& actors) + void PhysicsSystem::doPhysics(float dt, const std::vector >& actors) { //set the DebugRenderingMode. To disable it,set it to 0 //eng->setDebugRenderingMode(1); @@ -97,48 +106,110 @@ namespace MWWorld OEngine::Physic::PhysicActor* act = it->second; act->setWalkDirection(btVector3(0,0,0)); } + playerMove::playercmd& pm_ref = playerphysics->cmd; + pm_ref.rightmove = 0; + pm_ref.forwardmove = 0; + pm_ref.upmove = 0; + + //playerphysics->ps.move_type = PM_NOCLIP; for (std::vector >::const_iterator iter (actors.begin()); iter!=actors.end(); ++iter) { OEngine::Physic::PhysicActor* act = mEngine->getCharacter(iter->first); - + //if(iter->first == "player") + // std::cout << "This is player\n"; //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(); + + // unused + //Ogre::Quaternion both = yawQuat * pitchQuat; + + playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); + playerphysics->ps.viewangles.z = 0; + playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; + if(mFreeFly) { - Ogre::Quaternion yawQuat = yawNode->getOrientation(); - Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); + + pm_ref.rightmove = -dir1.x; + pm_ref.forwardmove = dir1.z; + pm_ref.upmove = dir1.y; + + + //std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n"; + //playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); + //std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n"; dir = 0.07*(yawQuat*pitchQuat*dir1); } else { + Ogre::Quaternion quat = yawNode->getOrientation(); Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); + + pm_ref.rightmove = -dir1.x; + pm_ref.forwardmove = dir1.z; + pm_ref.upmove = dir1.y; + + + dir = 0.025*(quat*dir1); } + //set the walk direction act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); } - mEngine->stepSimulation(duration); + mEngine->stepSimulation(dt); + } + + std::vector< std::pair > PhysicsSystem::doPhysicsFixed ( + const std::vector >& actors) + { + Pmove(playerphysics); std::vector< std::pair > response; for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { btVector3 newPos = it->second->getPosition(); + Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); + if(it->first == "player"){ + + coord = playerphysics->ps.origin; + //std::cout << "ZCoord: " << coord.z << "\n"; + //std::cout << "Coord" << coord << "\n"; + //coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y + + } + response.push_back(std::pair(it->first, coord)); } + return response; } + void PhysicsSystem::addHeightField (float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts) + { + mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts); + } + + void PhysicsSystem::removeHeightField (int x, int y) + { + mEngine->removeHeightField(x, y); + } + void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh, const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) { @@ -181,7 +252,14 @@ namespace MWWorld { // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow // start positions others than 0, 0, 0 - act->setPosition(btVector3(position.x,position.y,position.z)); + if (handle == "player") + { + playerphysics->ps.origin = position; + } + else + { + act->setPosition(btVector3(position.x,position.y,position.z)); + } } } @@ -202,6 +280,11 @@ namespace MWWorld bool PhysicsSystem::toggleCollisionMode() { + if(playerphysics->ps.move_type==PM_NOCLIP) + playerphysics->ps.move_type=PM_NORMAL; + + else + playerphysics->ps.move_type=PM_NOCLIP; for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { if (it->first=="player") @@ -232,7 +315,12 @@ namespace MWWorld } void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); + + // unused + //Ogre::Vector3 objPos = node->getPosition(); + addObject (node->getName(), model, node->getOrientation(), node->getScale().x, node->getPosition()); } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 7b2d77325..1af6bcca2 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -5,6 +5,7 @@ #include #include #include "ptr.hpp" +#include namespace MWWorld { @@ -15,8 +16,11 @@ namespace MWWorld PhysicsSystem (OEngine::Render::OgreRenderer &_rend); ~PhysicsSystem (); - std::vector< std::pair > doPhysics (float duration, - const std::vector >& actors); + void doPhysics(float duration, const std::vector >& actors); + ///< do physics with dt - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed + + std::vector< std::pair > doPhysicsFixed (const std::vector >& actors); + ///< do physics with fixed timestep - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed void addObject (const std::string& handle, const std::string& mesh, const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); @@ -24,6 +28,12 @@ namespace MWWorld void addActor (const std::string& handle, const std::string& mesh, const Ogre::Vector3& position); + void addHeightField (float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts); + + void removeHeightField (int x, int y); + void removeObject (const std::string& handle); void moveObject (const std::string& handle, const Ogre::Vector3& position); @@ -49,10 +59,13 @@ namespace MWWorld OEngine::Physic::PhysicEngine* getEngine(); + void setCurrentWater(bool hasWater, int waterHeight); + private: OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; bool mFreeFly; + playerMove* playerphysics; PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index d24780ec1..0b1483ff8 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -24,8 +24,6 @@ namespace MWWorld float* playerPos = mPlayer.mData.getPosition().pos; playerPos[0] = playerPos[1] = playerPos[2] = 0; - std::cout << renderer->getHandle(); - 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)); @@ -87,6 +85,14 @@ namespace MWWorld MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; } + void Player::setUpDown(int value) + { + MWWorld::Ptr ptr = getPlayer(); + + + + MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value; + } void Player::toggleRunning() { @@ -102,4 +108,5 @@ namespace MWWorld MWWorld::Ptr ptr = getPlayer(); return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState; } + } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 8dcd9fcc6..e199f17e9 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -116,6 +116,7 @@ namespace MWWorld void setLeftRight (int value); void setForwardBackward (int value); + void setUpDown(int value); void toggleRunning(); }; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 2123b4799..6f9f3ed3e 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,6 +1,7 @@ #include "scene.hpp" #include "world.hpp" +#include "../mwbase/environment.hpp" #include "../mwmechanics/mechanicsmanager.hpp" @@ -9,7 +10,6 @@ #include "../mwgui/window_manager.hpp" #include "ptr.hpp" -#include "environment.hpp" #include "player.hpp" #include "class.hpp" @@ -18,7 +18,7 @@ namespace { template -void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environment& environment, +void insertCellRefList(MWRender::RenderingManager& rendering, T& cellRefList, ESMS::CellStore &cell, MWWorld::PhysicsSystem& physics) { if (!cellRefList.list.empty()) @@ -36,8 +36,8 @@ void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environme try { rendering.addObject(ptr); - class_.insertObject(ptr, physics, environment); - class_.enable (ptr, environment); + class_.insertObject(ptr, physics); + class_.enable (ptr); } catch (const std::exception& e) { @@ -75,23 +75,26 @@ namespace MWWorld // silence annoying g++ warning - for (std::vector::const_iterator iter (functor.mHandles.begin()); - iter!=functor.mHandles.end(); ++iter){ - Ogre::SceneNode* node = *iter; + for (std::vector::const_iterator iter2 (functor.mHandles.begin()); + iter2!=functor.mHandles.end(); ++iter2){ + Ogre::SceneNode* node = *iter2; mPhysics->removeObject (node->getName()); } + + if (!((*iter)->cell->data.flags & ESM::Cell::Interior)) + mPhysics->removeHeightField( (*iter)->cell->data.gridX, (*iter)->cell->data.gridY ); } mRendering.removeCell(*iter); //mPhysics->removeObject("Unnamed_43"); mWorld->getLocalScripts().clearCell (*iter); - mEnvironment.mMechanicsManager->dropActors (*iter); - mEnvironment.mSoundManager->stopSound (*iter); + MWBase::Environment::get().getMechanicsManager()->dropActors (*iter); + MWBase::Environment::get().getSoundManager()->stopSound (*iter); mActiveCells.erase(*iter); - - + + } void Scene::loadCell (Ptr::CellStore *cell) @@ -103,29 +106,45 @@ namespace MWWorld std::pair result = mActiveCells.insert(cell); - if(result.second){ - insertCell(*cell, mEnvironment); - mRendering.cellAdded(cell); - mRendering.configureAmbient(*cell); - mRendering.requestMap(cell); - mRendering.configureAmbient(*cell); - } + if(result.second) + { + insertCell(*cell); + mRendering.cellAdded (cell); + + float verts = ESM::Land::LAND_SIZE; + float worldsize = ESM::Land::REAL_SIZE; + + if (!(cell->cell->data.flags & ESM::Cell::Interior)) + { + ESM::Land* land = mWorld->getStore().lands.search(cell->cell->data.gridX,cell->cell->data.gridY); + mPhysics->addHeightField (land->landData->heights, + cell->cell->data.gridX, cell->cell->data.gridY, + 0, ( worldsize/(verts-1) ), verts); + } + + mRendering.configureAmbient(*cell); + mRendering.requestMap(cell); + mRendering.configureAmbient(*cell); + + } } void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, bool adjustPlayerPos) { + bool hasWater = cell->cell->data.flags & cell->cell->HasWater; + mPhysics->setCurrentWater(hasWater, cell->cell->water); if (adjustPlayerPos) mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]); mWorld->getPlayer().setCell (cell); // TODO orientation - mEnvironment.mMechanicsManager->addActor (mWorld->getPlayer().getPlayer()); - mEnvironment.mMechanicsManager->watchActor (mWorld->getPlayer().getPlayer()); + MWBase::Environment::get().getMechanicsManager()->addActor (mWorld->getPlayer().getPlayer()); + MWBase::Environment::get().getMechanicsManager()->watchActor (mWorld->getPlayer().getPlayer()); - mEnvironment.mWindowManager->changeCell( mCurrentCell ); + MWBase::Environment::get().getWindowManager()->changeCell( mCurrentCell ); } void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) @@ -133,7 +152,7 @@ namespace MWWorld mRendering.preCellChange(mCurrentCell); // remove active - mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); + MWBase::Environment::get().getMechanicsManager()->removeActor (mWorld->getPlayer().getPlayer()); CellStoreCollection::iterator active = mActiveCells.begin(); @@ -203,12 +222,14 @@ namespace MWWorld // Sky system mWorld->adjustSky(); + mRendering.switchToExterior(); + mCellChanged = true; } //We need the ogre renderer and a scene node. - Scene::Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics) - : mCurrentCell (0), mCellChanged (false), mEnvironment (environment), mWorld(world), + Scene::Scene (World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics) + : mCurrentCell (0), mCellChanged (false), mWorld(world), mPhysics(physics), mRendering(rendering) { } @@ -243,13 +264,14 @@ namespace MWWorld Ptr::CellStore *cell = mWorld->getInterior(cellName); loadCell (cell); - + // adjust player mCurrentCell = cell; playerCellChange (cell, position); - + // adjust fog + mRendering.switchToInterior(); mRendering.configureFog(*cell); // Sky system @@ -278,30 +300,29 @@ namespace MWWorld mCellChanged = false; } -void Scene::insertCell(ESMS::CellStore &cell, - MWWorld::Environment& environment) +void Scene::insertCell(ESMS::CellStore &cell) { // Loop through all references in the cell - insertCellRefList(mRendering, environment, cell.activators, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.potions, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.appas, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.armors, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.books, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.clothes, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.containers, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.creatures, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.doors, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.ingreds, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.creatureLists, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.itemLists, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.lights, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.lockpicks, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.miscItems, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.npcs, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.probes, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.repairs, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.statics, cell, *mPhysics); - insertCellRefList(mRendering, environment, cell.weapons, cell, *mPhysics); + insertCellRefList(mRendering, cell.activators, cell, *mPhysics); + insertCellRefList(mRendering, cell.potions, cell, *mPhysics); + insertCellRefList(mRendering, cell.appas, cell, *mPhysics); + insertCellRefList(mRendering, cell.armors, cell, *mPhysics); + insertCellRefList(mRendering, cell.books, cell, *mPhysics); + insertCellRefList(mRendering, cell.clothes, cell, *mPhysics); + insertCellRefList(mRendering, cell.containers, cell, *mPhysics); + insertCellRefList(mRendering, cell.creatures, cell, *mPhysics); + insertCellRefList(mRendering, cell.doors, cell, *mPhysics); + insertCellRefList(mRendering, cell.ingreds, cell, *mPhysics); + insertCellRefList(mRendering, cell.creatureLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.itemLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.lights, cell, *mPhysics); + insertCellRefList(mRendering, cell.lockpicks, cell, *mPhysics); + insertCellRefList(mRendering, cell.miscItems, cell, *mPhysics); + insertCellRefList(mRendering, cell.npcs, cell, *mPhysics); + insertCellRefList(mRendering, cell.probes, cell, *mPhysics); + insertCellRefList(mRendering, cell.repairs, cell, *mPhysics); + insertCellRefList(mRendering, cell.statics, cell, *mPhysics); + insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 4d1bd6fb5..1a9f2f271 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -46,7 +46,6 @@ namespace MWRender namespace MWWorld { - class Environment; class Player; class Scene @@ -62,7 +61,6 @@ namespace MWWorld Ptr::CellStore* mCurrentCell; // the cell, the player is in CellStoreCollection mActiveCells; bool mCellChanged; - Environment& mEnvironment; World *mWorld; PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; @@ -73,7 +71,7 @@ namespace MWWorld public: - Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics); + Scene (World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics); ~Scene(); @@ -100,7 +98,7 @@ namespace MWWorld void markCellAsUnchanged(); - void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); + void insertCell(ESMS::CellStore &cell); void update (float duration); }; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index fb0480171..bcbb96eec 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -9,7 +9,9 @@ #include #include -#include +#include + +#include "../mwbase/environment.hpp" using namespace Ogre; using namespace MWWorld; @@ -34,15 +36,14 @@ const float WeatherGlobals::mThunderFrequency = .4; const float WeatherGlobals::mThunderThreshold = 0.6; const float WeatherGlobals::mThunderSoundDelay = 0.25; -WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::Environment* env) : +WeatherManager::WeatherManager(MWRender::RenderingManager* rendering) : mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0) { mRendering = rendering; - mEnvironment = env; - + #define clr(r,g,b) ColourValue(r/255.f, g/255.f, b/255.f) - + /// \todo read these from Morrowind.ini Weather clear; clear.mCloudTexture = "tx_sky_clear.dds"; @@ -71,7 +72,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E clear.mCloudSpeed = 1.25; clear.mGlareView = 1.0; mWeatherSettings["clear"] = clear; - + Weather cloudy; cloudy.mCloudTexture = "tx_sky_cloudy.dds"; cloudy.mCloudsMaximumPercent = 1.0; @@ -99,7 +100,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E cloudy.mCloudSpeed = 2; cloudy.mGlareView = 1.0; mWeatherSettings["cloudy"] = cloudy; - + Weather foggy; foggy.mCloudTexture = "tx_sky_foggy.dds"; foggy.mCloudsMaximumPercent = 1.0; @@ -127,7 +128,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E foggy.mCloudSpeed = 1.25; foggy.mGlareView = 0.25; mWeatherSettings["foggy"] = foggy; - + Weather thunderstorm; thunderstorm.mCloudTexture = "tx_sky_thunder.dds"; thunderstorm.mCloudsMaximumPercent = 0.66; @@ -156,7 +157,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E thunderstorm.mGlareView = 0; thunderstorm.mRainLoopSoundID = "rain heavy"; mWeatherSettings["thunderstorm"] = thunderstorm; - + Weather rain; rain.mCloudTexture = "tx_sky_rainy.dds"; rain.mCloudsMaximumPercent = 0.66; @@ -185,7 +186,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E rain.mGlareView = 0; rain.mRainLoopSoundID = "rain"; mWeatherSettings["rain"] = rain; - + Weather overcast; overcast.mCloudTexture = "tx_sky_overcast.dds"; overcast.mCloudsMaximumPercent = 1.0; @@ -213,7 +214,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E overcast.mCloudSpeed = 1.5; overcast.mGlareView = 0; mWeatherSettings["overcast"] = overcast; - + Weather ashstorm; ashstorm.mCloudTexture = "tx_sky_ashstorm.dds"; ashstorm.mCloudsMaximumPercent = 1.0; @@ -242,7 +243,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E ashstorm.mGlareView = 0; ashstorm.mAmbientLoopSoundID = "ashstorm"; mWeatherSettings["ashstorm"] = ashstorm; - + Weather blight; blight.mCloudTexture = "tx_sky_blight.dds"; blight.mCloudsMaximumPercent = 1.0; @@ -300,7 +301,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E snow.mCloudSpeed = 1.5; snow.mGlareView = 0; mWeatherSettings["snow"] = snow; - + Weather blizzard; blizzard.mCloudTexture = "tx_bm_sky_blizzard.dds"; blizzard.mCloudsMaximumPercent = 1.0; @@ -484,15 +485,15 @@ WeatherResult WeatherManager::transition(float factor) void WeatherManager::update(float duration) { - mWeatherUpdateTime -= duration * mEnvironment->mWorld->getTimeScaleFactor(); + mWeatherUpdateTime -= duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor(); - bool exterior = (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior()); + bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior()); if (exterior) { - std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region; + std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->region; boost::algorithm::to_lower(regionstr); - + if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) { mCurrentRegion = regionstr; @@ -505,7 +506,7 @@ void WeatherManager::update(float duration) else { // get weather probabilities for the current region - const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr); + const ESM::Region *region = MWBase::Environment::get().getWorld()->getStore().regions.find (regionstr); float clear = region->data.clear/255.f; float cloudy = region->data.cloudy/255.f; @@ -521,7 +522,6 @@ void WeatherManager::update(float duration) // re-scale to 100 percent const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard; - srand(time(NULL)); float random = ((rand()%100)/100.f) * total; //if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear) @@ -553,7 +553,7 @@ void WeatherManager::update(float duration) if (mNextWeather != "") { - mRemainingTransitionTime -= duration * mEnvironment->mWorld->getTimeScaleFactor(); + mRemainingTransitionTime -= duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor(); if (mRemainingTransitionTime < 0) { mCurrentWeather = mNextWeather; @@ -588,8 +588,8 @@ void WeatherManager::update(float duration) int facing = (mHour > 13.f) ? 1 : -1; Vector3 final( - -(1-height)*facing, - -(1-height)*facing, + -(1-height)*facing, + -(1-height)*facing, height); mRendering->setSunDirection(final); @@ -609,13 +609,13 @@ void WeatherManager::update(float duration) float moonHeight = 1-std::abs((night-0.5)*2); int facing = (mHour > 0.f && mHour<12.f) ? 1 : -1; Vector3 masser( - (1-moonHeight)*facing, - (1-moonHeight)*facing, + (1-moonHeight)*facing, + (1-moonHeight)*facing, moonHeight); Vector3 secunda( - (1-moonHeight)*facing*0.8, - (1-moonHeight)*facing*1.25, + (1-moonHeight)*facing*0.8, + (1-moonHeight)*facing*1.25, moonHeight); mRendering->getSkyManager()->setMasserDirection(masser); @@ -676,7 +676,7 @@ void WeatherManager::update(float duration) else if (sound == 1) soundname = WeatherGlobals::mThunderSoundID1; else if (sound == 2) soundname = WeatherGlobals::mThunderSoundID2; else if (sound == 3) soundname = WeatherGlobals::mThunderSoundID3; - mEnvironment->mSoundManager->playSound(soundname, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound(soundname, 1.0, 1.0); mThunderSoundDelay = 1000; } @@ -729,7 +729,7 @@ void WeatherManager::update(float duration) if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end()) { mSoundsPlaying.push_back(ambientSnd); - mEnvironment->mSoundManager->playSound(ambientSnd, 1.0, 1.0, true); + MWBase::Environment::get().getSoundManager()->playSound(ambientSnd, 1.0, 1.0, true); } } @@ -740,7 +740,7 @@ void WeatherManager::update(float duration) if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end()) { mSoundsPlaying.push_back(rainSnd); - mEnvironment->mSoundManager->playSound(rainSnd, 1.0, 1.0, true); + MWBase::Environment::get().getSoundManager()->playSound(rainSnd, 1.0, 1.0, true); } } @@ -750,7 +750,7 @@ void WeatherManager::update(float duration) { if ( *it != ambientSnd && *it != rainSnd) { - mEnvironment->mSoundManager->stopSound(*it); + MWBase::Environment::get().getSoundManager()->stopSound(*it); it = mSoundsPlaying.erase(it); } else @@ -772,7 +772,7 @@ void WeatherManager::setDate(const int day, const int month) unsigned int WeatherManager::getWeatherID() const { // Source: http://www.uesp.net/wiki/Tes3Mod:GetCurrentWeather - + if (mCurrentWeather == "clear") return 0; else if (mCurrentWeather == "cloudy") @@ -793,7 +793,7 @@ unsigned int WeatherManager::getWeatherID() const return 8; else if (mCurrentWeather == "blizzard") return 9; - + else return 0; } diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index b9b40e6fa..5e0388751 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -11,8 +11,6 @@ namespace MWRender namespace MWWorld { - class Environment; - /// Global weather manager properties (according to INI) struct WeatherGlobals { @@ -67,8 +65,8 @@ namespace MWWorld Snow Gravity Scale=0.1 Snow High Kill=700 Snow Low Kill=150 - - + + [Moons] Masser Size=94 Masser Fade In Start=14 @@ -94,14 +92,14 @@ namespace MWWorld Secunda Moon Shadow Early Fade Angle=0.5 Script Color=255,20,20 */ - + static const float mSunriseTime; static const float mSunsetTime; static const float mSunriseDuration; static const float mSunsetDuration; - + static const float mWeatherUpdateTime; - + // morrowind sets these per-weather, but since they are only used by 'thunderstorm' // weather setting anyway, we can just as well set them globally static const float mThunderFrequency; @@ -119,154 +117,153 @@ namespace MWWorld Ogre::String mCloudTexture; Ogre::String mNextCloudTexture; float mCloudBlendFactor; - + Ogre::ColourValue mFogColor; - + Ogre::ColourValue mAmbientColor; - + Ogre::ColourValue mSkyColor; - + Ogre::ColourValue mSunColor; - + Ogre::ColourValue mSunDiscColor; - + float mFogDepth; - + float mWindSpeed; - + float mCloudSpeed; - + float mCloudOpacity; - + float mGlareView; - + bool mNight; // use night skybox float mNightFade; // fading factor for night skybox - + Ogre::String mAmbientLoopSoundID; }; - - + + /// Defines a single weather setting (according to INI) struct Weather { Ogre::String mCloudTexture; - - // Sky (atmosphere) colors + + // Sky (atmosphere) colors Ogre::ColourValue mSkySunriseColor, mSkyDayColor, mSkySunsetColor, mSkyNightColor; - + // Fog colors Ogre::ColourValue mFogSunriseColor, mFogDayColor, mFogSunsetColor, mFogNightColor; - + // Ambient lighting colors Ogre::ColourValue mAmbientSunriseColor, mAmbientDayColor, mAmbientSunsetColor, mAmbientNightColor; - + // Sun (directional) lighting colors Ogre::ColourValue mSunSunriseColor, mSunDayColor, mSunSunsetColor, mSunNightColor; - + // Fog depth/density float mLandFogDayDepth, mLandFogNightDepth; - + // Color modulation for the sun itself during sunset (not completely sure) Ogre::ColourValue mSunDiscSunsetColor; - + // Duration of weather transition (in days) float mTransitionDelta; - + // No idea what this one is used for? float mWindSpeed; - + // Cloud animation speed multiplier float mCloudSpeed; - + // Multiplier for clouds transparency float mCloudsMaximumPercent; - + // Value between 0 and 1, defines the strength of the sun glare effect float mGlareView; - + // Sound effect // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) Ogre::String mAmbientLoopSoundID; - + // Rain sound effect Ogre::String mRainLoopSoundID; - + /// \todo disease chance }; - + /// /// Interface for weather settings /// class WeatherManager { public: - WeatherManager(MWRender::RenderingManager*, MWWorld::Environment*); - + WeatherManager(MWRender::RenderingManager*); + /** * Change the weather in the specified region * @param region that should be changed * @param ID of the weather setting to shift to */ void changeWeather(const std::string& region, const unsigned int id); - + /** * Per-frame update * @param duration */ void update(float duration); - + void setHour(const float hour); - + void setDate(const int day, const int month); - + unsigned int getWeatherID() const; - + private: float mHour; int mDay, mMonth; - + MWRender::RenderingManager* mRendering; - MWWorld::Environment* mEnvironment; - + std::map mWeatherSettings; std::map mRegionOverrides; std::vector mSoundsPlaying; - + Ogre::String mCurrentWeather; Ogre::String mNextWeather; - + std::string mCurrentRegion; - + bool mFirstUpdate; - + float mWeatherUpdateTime; - + float mRemainingTransitionTime; - + float mThunderFlash; float mThunderChance; float mThunderChanceNeeded; float mThunderSoundDelay; - + WeatherResult transition(const float factor); WeatherResult getResult(const Ogre::String& weather); - + void setWeather(const Ogre::String& weather, bool instant=false); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 1c64039d4..4adaf7918 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -6,6 +6,8 @@ #include #include +#include "../mwbase/environment.hpp" + #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" @@ -13,9 +15,9 @@ #include "../mwsound/soundmanager.hpp" +#include "../mwgui/window_manager.hpp" #include "ptr.hpp" -#include "environment.hpp" #include "class.hpp" #include "player.hpp" #include "weather.hpp" @@ -174,18 +176,18 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, - const std::string& master, const boost::filesystem::path& resDir, - bool newGame, Environment& environment, const std::string& encoding, std::map fallbackMap) + const std::string& master, const boost::filesystem::path& resDir, bool newGame, + const std::string& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), - mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this), + mSky (true), mNextDynamicRecord (0), mCells (mStore, mEsm, *this), mNumFacing(0) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); - mRendering = new MWRender::RenderingManager(renderer, resDir, mPhysEngine, environment); + mRendering = new MWRender::RenderingManager(renderer, resDir, mPhysEngine); - mWeatherManager = new MWWorld::WeatherManager(mRendering, &environment); + mWeatherManager = new MWWorld::WeatherManager(mRendering); boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); @@ -209,10 +211,11 @@ namespace MWWorld mGlobalVariables->setInt ("chargenstate", 1); } - mWorldScene = new Scene(environment, this, *mRendering, mPhysics); + mWorldScene = new Scene(this, *mRendering, mPhysics); setFallbackValues(fallbackMap); + lastTick = mTimer.getMilliseconds(); } @@ -357,7 +360,7 @@ namespace MWWorld //render->enable (reference.getRefData().getHandle()); if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end()) - Class::get (reference).enable (reference, mEnvironment); + Class::get (reference).enable (reference); } @@ -372,8 +375,8 @@ namespace MWWorld //render->disable (reference.getRefData().getHandle()); if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){ - Class::get (reference).disable (reference, mEnvironment); - mEnvironment.mSoundManager->stopSound3D (reference); + Class::get (reference).disable (reference); + MWBase::Environment::get().getSoundManager()->stopSound3D (reference); } @@ -547,7 +550,7 @@ namespace MWWorld if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){ // Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed - mEnvironment.mSoundManager->stopSound3D (ptr); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); mPhysics->removeObject (ptr.getRefData().getHandle()); mRendering->removeObject(ptr); @@ -557,8 +560,9 @@ namespace MWWorld } } - void World::moveObjectImp (Ptr ptr, float x, float y, float z) + bool World::moveObjectImp (Ptr ptr, 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; @@ -580,6 +584,7 @@ namespace MWWorld if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) { mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); + ret = true; } } @@ -589,6 +594,8 @@ namespace MWWorld /// \todo cell change for non-player ref mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); + + return ret; } void World::moveObject (Ptr ptr, float x, float y, float z) @@ -630,29 +637,50 @@ namespace MWWorld void World::doPhysics (const std::vector >& actors, float duration) { - std::vector< std::pair > vectors = mPhysics->doPhysics (duration, actors); + mPhysics->doPhysics(duration, actors); - std::vector< std::pair >::iterator player = vectors.end(); + const int tick = 16; // 16 ms ^= 60 Hz - for (std::vector< std::pair >::iterator it = vectors.begin(); - it!= vectors.end(); ++it) + // Game clock part of the loop, contains everything that has to be executed in a fixed timestep + long long dt = mTimer.getMilliseconds() - lastTick; + if (dt >= 100) { - if (it->first=="player") + // throw away wall clock time if necessary to keep the framerate above the minimum of 10 fps + lastTick += (dt - 100); + dt = 100; + } + while (dt >= tick) + { + dt -= tick; + lastTick += tick; + + std::vector< std::pair > vectors = mPhysics->doPhysicsFixed (actors); + + std::vector< std::pair >::iterator player = vectors.end(); + + for (std::vector< std::pair >::iterator it = vectors.begin(); + it!= vectors.end(); ++it) { - player = it; + if (it->first=="player") + { + player = it; + } + else + { + MWWorld::Ptr ptr = getPtrViaHandle (it->first); + moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); + } } - else + + // Make sure player is moved last (otherwise the cell might change in the middle of an update + // loop) + if (player!=vectors.end()) { - MWWorld::Ptr ptr = getPtrViaHandle (it->first); - moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); + if (moveObjectImp (getPtrViaHandle (player->first), + player->second.x, player->second.y, player->second.z) == true) + return; // abort the current loop if the cell has changed } } - - // Make sure player is moved last (otherwise the cell might change in the middle of an update - // loop) - if (player!=vectors.end()) - moveObjectImp (getPtrViaHandle (player->first), - player->second.x, player->second.y, player->second.z); } bool World::toggleCollisionMode() @@ -737,6 +765,17 @@ namespace MWWorld mWeatherManager->update (duration); + // inform the GUI about focused object + try + { + MWBase::Environment::get().getWindowManager()->setFocusObject(getPtrViaHandle(mFacedHandle)); + } + catch (std::runtime_error&) + { + MWWorld::Ptr null; + MWBase::Environment::get().getWindowManager()->setFocusObject(null); + } + if (!mRendering->occlusionQuerySupported()) { // cast a ray from player to sun to detect if the sun is visible @@ -776,7 +815,8 @@ namespace MWWorld std::vector < std::pair < float, std::string > >::iterator it = results.begin(); while (it != results.end()) { - if ( getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) + if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain + || getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself) { it = results.erase(it); } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 8dd370ad7..7359f8b90 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -22,6 +22,8 @@ #include #include +#include + namespace Ogre { class Vector3; @@ -51,7 +53,6 @@ namespace MWRender namespace MWWorld { class WeatherManager; - class Environment; class Player; /// \brief The game world and its visual representation @@ -81,7 +82,6 @@ namespace MWWorld MWWorld::Globals *mGlobalVariables; MWWorld::PhysicsSystem *mPhysics; bool mSky; - Environment& mEnvironment; int mNextDynamicRecord; Cells mCells; @@ -102,16 +102,20 @@ namespace MWWorld int mNumFacing; std::map mFallback; + unsigned long lastTick; + Ogre::Timer mTimer; + int getDaysPerMonth (int month) const; - void moveObjectImp (Ptr ptr, float x, float y, float z); + bool moveObjectImp (Ptr ptr, float x, float y, float z); + ///< @return true if the active cell (cell player is in) changed public: World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, bool newGame, - Environment& environment, const std::string& encoding, std::map fallbackMap); + const std::string& encoding, std::map fallbackMap); ~World(); diff --git a/cmake/FindFreetype.cmake b/cmake/FindFreetype.cmake new file mode 100644 index 000000000..fc36d548e --- /dev/null +++ b/cmake/FindFreetype.cmake @@ -0,0 +1,69 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# - Try to find FreeType +# Once done, this will define +# +# FREETYPE_FOUND - system has FreeType +# FREETYPE_INCLUDE_DIRS - the FreeType include directories +# FREETYPE_LIBRARIES - link these to use FreeType + +include(FindPkgMacros) +findpkg_begin(FREETYPE) + +# Get path, convert backslashes as ${ENV_${var}} +getenv_path(FREETYPE_HOME) + +# construct search paths +set(FREETYPE_PREFIX_PATH ${FREETYPE_HOME} ${ENV_FREETYPE_HOME}) +create_search_paths(FREETYPE) +# redo search if prefix path changed +clear_if_changed(FREETYPE_PREFIX_PATH + FREETYPE_LIBRARY_FWK + FREETYPE_LIBRARY_REL + FREETYPE_LIBRARY_DBG + FREETYPE_INCLUDE_DIR +) + +set(FREETYPE_LIBRARY_NAMES freetype2311 freetype239 freetype238 freetype235 freetype219 freetype) +get_debug_names(FREETYPE_LIBRARY_NAMES) + +use_pkgconfig(FREETYPE_PKGC freetype2) + +# prefer static library over framework +set(CMAKE_FIND_FRAMEWORK "LAST") + +message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") +findpkg_framework(FREETYPE) +message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") + +find_path(FREETYPE_INCLUDE_DIR NAMES freetype/freetype.h HINTS ${FREETYPE_INC_SEARCH_PATH} ${FREETYPE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES freetype2) +find_path(FREETYPE_FT2BUILD_INCLUDE_DIR NAMES ft2build.h HINTS ${FREETYPE_INC_SEARCH_PATH} ${FREETYPE_PKGC_INCLUDE_DIRS}) + +if (SYMBIAN) +set(ORIGINAL_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}) +set(CMAKE_PREFIX_PATH ${CMAKE_SYSYEM_OUT_DIR}) +message(STATUS "Lib will be searched in Symbian out dir: ${CMAKE_SYSYEM_OUT_DIR}") +endif (SYMBIAN) +find_library(FREETYPE_LIBRARY_REL NAMES ${FREETYPE_LIBRARY_NAMES} HINTS ${FREETYPE_LIB_SEARCH_PATH} ${FREETYPE_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel) +find_library(FREETYPE_LIBRARY_DBG NAMES ${FREETYPE_LIBRARY_NAMES_DBG} HINTS ${FREETYPE_LIB_SEARCH_PATH} ${FREETYPE_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug) +if (SYMBIAN) +set(CMAKE_PREFIX_PATH ${ORIGINAL_CMAKE_PREFIX_PATH}) +endif (SYMBIAN) + +make_library_set(FREETYPE_LIBRARY) + +findpkg_finish(FREETYPE) +mark_as_advanced(FREETYPE_FT2BUILD_INCLUDE_DIR) +if (NOT FREETYPE_FT2BUILD_INCLUDE_DIR STREQUAL FREETYPE_INCLUDE_DIR) + set(FREETYPE_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS} ${FREETYPE_FT2BUILD_INCLUDE_DIR}) +endif () + +# Reset framework finding +set(CMAKE_FIND_FRAMEWORK "FIRST") diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index 6731d584c..c79ee5998 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -82,37 +82,49 @@ findpkg_finish ( "MYGUI" ) ELSE (WIN32) #Unix CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) FIND_PACKAGE(PkgConfig) - IF(MYGUI_STATIC) - PKG_SEARCH_MODULE(MYGUI MYGUIStatic MyGUIStatic) - IF (MYGUI_INCLUDE_DIRS) - SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS}) - SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR}) - SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "") - SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") - ELSE (MYGUI_INCLUDE_DIRS) - FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI) - FIND_LIBRARY(MYGUI_LIBRARIES myguistatic PATHS /usr/lib /usr/local/lib) - SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") - SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES}) - STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}") - STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}") - ENDIF (MYGUI_INCLUDE_DIRS) - ELSE(MYGUI_STATIC) - PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI) - IF (MYGUI_INCLUDE_DIRS) - SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS}) - SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR}) - SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "") - SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") - ELSE (MYGUI_INCLUDE_DIRS) - FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI) - FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib) - SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") - SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES}) - STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}") - STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}") - ENDIF (MYGUI_INCLUDE_DIRS) - ENDIF(MYGUI_STATIC) + IF(MYGUI_STATIC) + # don't use pkgconfig on OS X, find freetype & append it's libs to resulting MYGUI_LIBRARIES + IF (NOT APPLE) + PKG_SEARCH_MODULE(MYGUI MYGUIStatic MyGUIStatic) + IF (MYGUI_INCLUDE_DIRS) + SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS}) + SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR}) + SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "") + SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") + ELSE (MYGUI_INCLUDE_DIRS) + FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI) + FIND_LIBRARY(MYGUI_LIBRARIES myguistatic PATHS /usr/lib /usr/local/lib) + SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") + SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES}) + STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}") + STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}") + ENDIF (MYGUI_INCLUDE_DIRS) + ELSE (NOT APPLE) + SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${MYGUI_DEPENDENCIES_DIR} ${OGRE_DEPENDENCIES_DIR}) + FIND_PACKAGE(freetype) + FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI) + FIND_LIBRARY(MYGUI_LIBRARIES MyGUIEngineStatic PATHS /usr/lib /usr/local/lib) + SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") + SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES}) + STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}") + STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}") + ENDIF (NOT APPLE) + ELSE(MYGUI_STATIC) + PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI) + IF (MYGUI_INCLUDE_DIRS) + SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS}) + SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR}) + SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "") + SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") + ELSE (MYGUI_INCLUDE_DIRS) + FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI) + FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib) + SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform") + SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES}) + STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}") + STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}") + ENDIF (MYGUI_INCLUDE_DIRS) + ENDIF(MYGUI_STATIC) ENDIF (WIN32) #Do some preparation @@ -120,17 +132,23 @@ SEPARATE_ARGUMENTS(MYGUI_INCLUDE_DIRS) SEPARATE_ARGUMENTS(MYGUI_LIBRARIES) SEPARATE_ARGUMENTS(MYGUI_PLATFORM_LIBRARIES) +SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} ${FREETYPE_LIBRARIES}) + SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS} CACHE PATH "") SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "") SET(MYGUI_PLATFORM_LIBRARIES ${MYGUI_PLATFORM_LIBRARIES} CACHE STRING "") SET(MYGUI_LIB_DIR ${MYGUI_LIB_DIR} CACHE PATH "") -IF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES) +IF (NOT APPLE OR NOT MYGUI_STATIC) # we need explicit freetype libs only on OS X for static build, for other cases just make it TRUE + SET(FREETYPE_LIBRARIES TRUE) +ENDIF (NOT APPLE OR NOT MYGUI_STATIC) + +IF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES AND FREETYPE_LIBRARIES) SET(MYGUI_FOUND TRUE) -ENDIF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES) +ENDIF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES AND FREETYPE_LIBRARIES) IF (MYGUI_FOUND) -MARK_AS_ADVANCED(MYGUI_LIB_DIR) + MARK_AS_ADVANCED(MYGUI_LIB_DIR) IF (NOT MYGUI_FIND_QUIETLY) MESSAGE(STATUS " libraries : ${MYGUI_LIBRARIES} from ${MYGUI_LIB_DIR}") MESSAGE(STATUS " includes : ${MYGUI_INCLUDE_DIRS}") diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 0e3563b26..fa197d960 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -79,7 +79,7 @@ class DirArchive: public Ogre::FileSystemArchive { passed = filename.substr(0, filename.length() - 2); } - if(filename.at(filename.length() - 2) == '>') + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') passed = filename.substr(0, filename.length() - 6); copy = passed; } @@ -232,7 +232,7 @@ public: { passed = filename.substr(0, filename.length() - 2); } - if(filename.at(filename.length() - 2) == '>') + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') passed = filename.substr(0, filename.length() - 6); // Open the file StreamPtr strm = narc->getFile(passed.c_str()); @@ -254,7 +254,7 @@ bool exists(const String& filename) { { passed = filename.substr(0, filename.length() - 2); } - if(filename.at(filename.length() - 2) == '>') + if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') passed = filename.substr(0, filename.length() - 6); return arc.exists(passed.c_str()); diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp index ddc25e176..8b559b10f 100644 --- a/components/esm/loadarmo.cpp +++ b/components/esm/loadarmo.cpp @@ -11,6 +11,7 @@ void PartReferenceList::load(ESMReader &esm) esm.getHT(pr.part); // The INDX byte pr.male = esm.getHNOString("BNAM"); pr.female = esm.getHNOString("CNAM"); + parts.push_back(pr); } } diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 1d6c9d4a1..16fd0598c 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -13,6 +13,7 @@ void Clothing::load(ESMReader &esm) icon = esm.getHNOString("ITEX"); parts.load(esm); + enchant = esm.getHNOString("ENAM"); } diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index 178258a05..9e7934b15 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -17,7 +17,7 @@ struct Light { Dynamic = 0x001, Carry = 0x002, // Can be carried - Negative = 0x004, // Negative light? + Negative = 0x004, // Negative light - i.e. darkness Flicker = 0x008, Fire = 0x010, OffDefault = 0x020, // Off by default diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index d7a4100aa..48bf050cd 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -90,6 +90,75 @@ namespace ESMS } }; + // Same as RecListT, but does not case-smash the IDs + // Note that lookups (search or find) are still case insensitive + template + struct RecListCaseT : RecList + { + virtual ~RecListCaseT() {} + + typedef std::map MapType; + + MapType list; + + // Load one object of this type + void load(ESMReader &esm, const std::string &id) + { + //std::string id2 = toLower (id); + + list[id].load(esm); + } + + // Find the given object ID, or return NULL if not found. + const X* search(const std::string &id) const + { + std::string id2 = toLower (id); + + for (typename MapType::const_iterator iter = list.begin(); + iter != list.end(); ++iter) + { + if (toLower(iter->first) == id2) + return &iter->second; + } + + return NULL; + } + + // non-const version + X* search(const std::string &id) + { + std::string id2 = toLower (id); + + for (typename MapType::iterator iter = list.begin(); + iter != list.end(); ++iter) + { + if (toLower(iter->first) == id2) + return &iter->second; + } + + return NULL; + } + + // Find the given object ID (throws an exception if not found) + const X* find(const std::string &id) const + { + const X *object = search (id); + + if (!object) + throw std::runtime_error ("object " + id + " not found"); + + return object; + } + + int getSize() { return list.size(); } + + virtual void listIdentifier (std::vector& identifier) const + { + for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) + identifier.push_back (iter->first); + } + }; + /// Modified version of RecListT for records, that need to store their own ID template struct RecListWithIDT : RecList diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index 2b5b977aa..c676601e5 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -71,15 +71,13 @@ void ESMStore::load(ESMReader &esm) if (n.val==ESM::REC_DIAL) { - RecListT& recList = static_cast& > (*it->second); + RecListCaseT& recList = static_cast& > (*it->second); - id = recList.toLower (id); + ESM::Dialogue* d = recList.search (id); - RecListT::MapType::iterator iter = recList.list.find (id); + assert (d != NULL); - assert (iter!=recList.list.end()); - - dialogue = &iter->second; + dialogue = d; } else dialogue = 0; diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index 857682089..507196a86 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -40,9 +40,9 @@ namespace ESMS RecListT clothes; RecListT contChange; RecListT containers; - RecListWithIDT creatures; + RecListWithIDT creatures; RecListT creaChange; - RecListT dialogs; + RecListCaseT dialogs; RecListT doors; RecListT enchants; RecListT factions; @@ -53,7 +53,7 @@ namespace ESMS RecListT lights; RecListT lockpicks; RecListT miscItems; - RecListWithIDT npcs; + RecListWithIDT npcs; RecListT npcChange; RecListT probes; RecListT races; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index ab6a708c0..05d35b85f 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1211,6 +1211,7 @@ void NIFLoader::loadResource(Resource *resource) char suffix = name.at(name.length() - 2); bool addAnim = true; bool hasAnim = false; + bool linkSkeleton = true; //bool baddin = false; bNiTri = true; if(name == "meshes\\base_anim.nif" || name == "meshes\\base_animkna.nif") @@ -1241,6 +1242,17 @@ void NIFLoader::loadResource(Resource *resource) addAnim = false; } + else if(suffix == ':') + { + //baddin = true; + linkSkeleton = false; + bNiTri = true; + std::string sub = name.substr(name.length() - 6, 4); + + if(sub.compare("0000") != 0) + addAnim = false; + + } switch(name.at(name.length() - 1)) { @@ -1379,7 +1391,7 @@ void NIFLoader::loadResource(Resource *resource) } //Don't link on npc parts to eliminate redundant skeletons //Will have to be changed later slightly for robes/skirts - if(triname == "") + if(linkSkeleton) mesh->_notifySkeleton(mSkel); } } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 69f6cbb74..e245dc21d 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -51,6 +51,7 @@ configure_file("${SDIR}/openmw_messagebox_layout.xml" "${DDIR}/openmw_messagebox configure_file("${SDIR}/openmw_interactive_messagebox_layout.xml" "${DDIR}/openmw_interactive_messagebox_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_journal_layout.xml" "${DDIR}/openmw_journal_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_journal_skin.xml" "${DDIR}/openmw_journal_skin.xml" COPYONLY) +configure_file("${SDIR}/openmw_tooltips.xml" "${DDIR}/openmw_tooltips.xml" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml index 1c6893026..b88e99406 100644 --- a/files/mygui/openmw_button.skin.xml +++ b/files/mygui/openmw_button.skin.xml @@ -47,7 +47,6 @@ - @@ -59,11 +58,10 @@ - - - - - + + + + diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml index 7ec926eb0..26ebe17e1 100644 --- a/files/mygui/openmw_chargen_generate_class_result_layout.xml +++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml @@ -1,27 +1,29 @@ - + - + + + - + - + - + diff --git a/files/mygui/openmw_dialogue_window_layout.xml b/files/mygui/openmw_dialogue_window_layout.xml index 29a3b511e..b0e437074 100644 --- a/files/mygui/openmw_dialogue_window_layout.xml +++ b/files/mygui/openmw_dialogue_window_layout.xml @@ -16,7 +16,7 @@ - + diff --git a/files/mygui/openmw_dialogue_window_skin.xml b/files/mygui/openmw_dialogue_window_skin.xml index ecdec8a5c..31ce626be 100644 --- a/files/mygui/openmw_dialogue_window_skin.xml +++ b/files/mygui/openmw_dialogue_window_skin.xml @@ -8,12 +8,12 @@ - - + + - + diff --git a/files/mygui/openmw_edit.skin.xml b/files/mygui/openmw_edit.skin.xml index a86317d62..02fee4b17 100644 --- a/files/mygui/openmw_edit.skin.xml +++ b/files/mygui/openmw_edit.skin.xml @@ -13,7 +13,7 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/files/mygui/openmw_interactive_messagebox_layout.xml b/files/mygui/openmw_interactive_messagebox_layout.xml index 744f21227..b8a71c670 100644 --- a/files/mygui/openmw_interactive_messagebox_layout.xml +++ b/files/mygui/openmw_interactive_messagebox_layout.xml @@ -5,7 +5,7 @@ - + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 0ac8e03ba..02075ad1a 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -180,10 +180,14 @@ - - - - + + + + + + + + @@ -219,7 +223,7 @@ - <_BasisSkin type="MainSkin" offset = "0 0 0 0" align = "ALIGN_LEFT ALIGN_TOP"/> + diff --git a/files/mygui/openmw_messagebox_layout.xml b/files/mygui/openmw_messagebox_layout.xml index 81d1c0a57..c99c00a49 100644 --- a/files/mygui/openmw_messagebox_layout.xml +++ b/files/mygui/openmw_messagebox_layout.xml @@ -8,7 +8,7 @@ - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 6ae14c558..36d97e153 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -93,20 +93,25 @@ + + + + + - + - + - + diff --git a/files/mygui/openmw_text_input_layout.xml b/files/mygui/openmw_text_input_layout.xml index 6a7ad27f0..c8f76b257 100644 --- a/files/mygui/openmw_text_input_layout.xml +++ b/files/mygui/openmw_text_input_layout.xml @@ -4,10 +4,10 @@ - + - + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml new file mode 100644 index 000000000..2d5a5da9f --- /dev/null +++ b/files/mygui/openmw_tooltips.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/files/openmw.bmp b/files/openmw.bmp new file mode 100644 index 000000000..be3fd94ce Binary files /dev/null and b/files/openmw.bmp differ diff --git a/files/plugins.cfg.mac b/files/plugins.cfg.mac index 0c16bddaf..322070832 100644 --- a/files/plugins.cfg.mac +++ b/files/plugins.cfg.mac @@ -1,12 +1,12 @@ # Defines plugins to load # Define plugin folder -PluginFolder= +PluginFolder=${OGRE_PLUGIN_DIR} # Define plugins -Plugin=RenderSystem_GL.dylib -Plugin=Plugin_ParticleFX.dylib -Plugin=Plugin_OctreeSceneManager.dylib -Plugin=Plugin_CgProgramManager +Plugin=RenderSystem_GL.1.8.0 +Plugin=Plugin_ParticleFX.1.8.0 +Plugin=Plugin_OctreeSceneManager.1.8.0 +Plugin=Plugin_CgProgramManager.1.8.0 diff --git a/files/plugins.cfg.win32 b/files/plugins.cfg.win32 index f71e8d325..ea12c0394 100644 --- a/files/plugins.cfg.win32 +++ b/files/plugins.cfg.win32 @@ -4,10 +4,10 @@ PluginFolder=.\ # Define plugins -Plugin=RenderSystem_Direct3D9_d -Plugin=RenderSystem_GL_d -Plugin=Plugin_ParticleFX_d -Plugin=Plugin_OctreeSceneManager_d -Plugin=Plugin_CgProgramManager_d +Plugin=RenderSystem_Direct3D9 +Plugin=RenderSystem_GL +Plugin=Plugin_ParticleFX +Plugin=Plugin_OctreeSceneManager +Plugin=Plugin_CgProgramManager diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 553a82e49..e4a0c020a 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -86,6 +86,7 @@ num lights = 8 [Water] # Enable this to get fancy-looking water with reflections and refractions +# Only available if object shaders are on # All the settings below have no effect if this is false shader = true diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index e7da9f085..42853d8cf 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -1,6 +1,7 @@ #include "physic.hpp" #include #include +#include #include //#include #include "CMotionState.h" @@ -10,6 +11,8 @@ #include "BtOgreGP.h" #include "BtOgreExtras.h" +#include + #define BIT(x) (1<<(x)) namespace OEngine { @@ -161,10 +164,12 @@ namespace Physic // The actual physics solver solver = new btSequentialImpulseConstraintSolver; + //btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache(); pairCache = new btSortedOverlappingPairCache(); + //pairCache->setInternalGhostPairCallback( new btGhostPairCallback() ); - broadphase = new btDbvtBroadphase(pairCache); + broadphase = new btDbvtBroadphase(); // The world. dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); @@ -253,6 +258,60 @@ namespace Physic delete mShapeLoader; } + void PhysicEngine::addHeightField(float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts) + { + const std::string name = "HeightField_" + + boost::lexical_cast(x) + "_" + + boost::lexical_cast(y); + + // find the minimum and maximum heights (needed for bullet) + float minh; + float maxh; + for (int i=0; imaxh) maxh = h; + if (hsetUseDiamondSubdivision(true); + + btVector3 scl(triSize, triSize, 1); + hfShape->setLocalScaling(scl); + + CMotionState* newMotionState = new CMotionState(this,name); + + btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape); + RigidBody* body = new RigidBody(CI,name); + body->collide = true; + body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); + + addRigidBody(body); + } + + void PhysicEngine::removeHeightField(int x, int y) + { + const std::string name = "HeightField_" + + boost::lexical_cast(x) + "_" + + boost::lexical_cast(y); + + removeRigidBody(name); + deleteRigidBody(name); + } + RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) { //get the shape from the .nif @@ -334,7 +393,7 @@ namespace Physic void PhysicEngine::stepSimulation(double deltaT) { - dynamicsWorld->stepSimulation(deltaT,1,1/50.); + dynamicsWorld->stepSimulation(deltaT,10, 1/60.0); if(isDebugCreated) { mDebugDrawer->step(); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8d177efda..ba241b2b7 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -140,6 +140,18 @@ namespace Physic */ RigidBody* createRigidBody(std::string mesh,std::string name,float scale); + /** + * Add a HeightField to the simulation + */ + void addHeightField(float* heights, + int x, int y, float yoffset, + float triSize, float sqrtVerts); + + /** + * Remove a HeightField from the simulation + */ + void removeHeightField(int x, int y); + /** * Add a RigidBody to the simulation */ diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp new file mode 100644 index 000000000..591f1869f --- /dev/null +++ b/libs/openengine/bullet/pmove.cpp @@ -0,0 +1,2095 @@ +/* +This source file is a *modified* version of bg_pmove.c from the Quake 3 Arena source code, +which was released under the GNU GPL (v2) in 2005. +Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc. +*/ + + +#include "pmove.h" + + + +//#include "bprintf.h" + +//#include "..\..\ESMParser\ESMParser\CELL.h" + +//#include "GameTime.h" + +//#include "Object.h" + +//#include "Sound.h" + +//#include "..\..\ESMParser\ESMParser\SNDG.h" +//#include "..\..\ESMParser\ESMParser\SOUN.h" + +#include + +//SceneInstance* global_lastscene = NULL; + +// Forward declaration: +void PM_AirMove(); + +static playerMove* pm = NULL; + +//extern std::map ExtCellLookup; + +static struct playermoveLocal +{ + playermoveLocal() : frametime(1.0f / 20.0f), groundPlane(true), walking(true), msec(50) + { + forward = Ogre::Vector3(0.0f, 0.0f, 0.0f); + right = Ogre::Vector3(0.0f, 0.0f, 0.0f); + up = Ogre::Vector3(0.0f, 0.0f, 0.0f); + + previous_origin = Ogre::Vector3(0.0f, 0.0f, 0.0f); + previous_velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f); + } + + traceResults groundTrace; + + //SceneInstance* scene; + + float frametime; // in seconds (usually something like 0.01f) + float impactSpeed; + + Ogre::Vector3 forward; + Ogre::Vector3 right; + Ogre::Vector3 up; + + int msec; + + Ogre::Vector3 previous_origin, previous_velocity; + + int previous_waterlevel; // the waterlevel before this pmove + + bool groundPlane; // if we're standing on a groundplane this frame + + bool walking; + int waterHeight; + bool hasWater; + bool isInterior; + //Object* traceObj; + +} pml; + +static inline void PM_ClipVelocity(const Ogre::Vector3& in, const Ogre::Vector3& normal, Ogre::Vector3& out, const float overbounce) +{ + float backoff; + //float change; + //int i; + + // backoff = in dot normal + //backoff = DotProduct (in, normal); + backoff = in.dotProduct(normal); + + if ( backoff < 0 ) + backoff *= overbounce; + else + backoff /= overbounce; + + // change = normal * backoff + // out = in - change + /*for ( i=0 ; i<3 ; i++ ) + { + change = normal[i]*backoff; + out[i] = in[i] - change; + + }*/ + float changex = normal.x * backoff; + out.x = in.x - changex; + float changey = normal.y * backoff; + out.y = in.y - changey; + float changez = normal.z * backoff; + out.z = in.z - changez; +} + +float VectorNormalize2( const Ogre::Vector3& v, Ogre::Vector3& out) +{ + float length, ilength; + + length = v.x * v.x+ v.y * v.y + v.z * v.z; + length = sqrt(length); + + if (length) + { +#ifndef Q3_VM // bk0101022 - FPE related +// assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) ); +#endif + ilength = 1 / length; + out.x= v.x * ilength; + out.y = v.y * ilength; + out.z = v.z * ilength; + } else + { +#ifndef Q3_VM // bk0101022 - FPE related +// assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) ); +#endif + //VectorClear( out ); + out.x = 0; out.y = 0; out.z = 0; + } + + return length; + +} + + +float VectorNormalize(Ogre::Vector3& out) +{ + float length, ilength; + + length = out.x * out.x + out.y * out.y + out.z * out.z; + length = sqrt(length); + + if (length) + { +#ifndef Q3_VM // bk0101022 - FPE related +// assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) ); +#endif + ilength = 1 / length; + out.x = out.x * ilength; + out.y = out.y * ilength; + out.z = out.z * ilength; + } + + return length; + +} + +/* +================== +PM_SlideMove + +Returns qtrue if the velocity was clipped in some way +================== +*/ + +bool PM_SlideMove( bool gravity ) +{ + int bumpcount, numbumps; + Ogre::Vector3 dir; + float d; + int numplanes; + Ogre::Vector3 planes[MAX_CLIP_PLANES]; + Ogre::Vector3 primal_velocity; + Ogre::Vector3 clipVelocity; + int i, j, k; + struct traceResults trace; + Ogre::Vector3 end; + float time_left; + float into; + Ogre::Vector3 endVelocity; + Ogre::Vector3 endClipVelocity; + + numbumps = 4; + + // primal_velocity = pm->ps->velocity + //VectorCopy (pm->ps->velocity, primal_velocity); + primal_velocity = pm->ps.velocity; + + if ( gravity ) + { + // endVelocity = pm->ps->velocity - vec3(0, 0, pm->ps->gravity * pml.frametime) + //VectorCopy( pm->ps->velocity, endVelocity ); + endVelocity = pm->ps.velocity; + //endVelocity[2] -= pm->ps->gravity * pml.frametime; + endVelocity.z -= pm->ps.gravity * pml.frametime; + + // pm->ps->velocity = avg(pm->ps->velocity.z, endVelocity.z) + //pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5; + pm->ps.velocity.z= (pm->ps.velocity.z + endVelocity.z) * 0.5f; + + //primal_velocity[2] = endVelocity[2]; + primal_velocity.z = endVelocity.z; + + if ( pml.groundPlane ) + // slide along the ground plane + //PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); + PM_ClipVelocity(pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP); + } + + time_left = pml.frametime; + + // never turn against the ground plane + if ( pml.groundPlane ) + { + numplanes = 1; + + // planes[0] = pml.groundTrace.plane.normal + //VectorCopy( pml.groundTrace.plane.normal, planes[0] ); + planes[0] = pml.groundTrace.planenormal; + } else + numplanes = 0; + + // never turn against original velocity + VectorNormalize2( pm->ps.velocity, planes[numplanes] ); + numplanes++; + + for ( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) + { + + // calculate position we are trying to move to + //VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end ); + end = pm->ps.origin + pm->ps.velocity * time_left; + + // see if we can make it there + //pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj); + newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + + if (trace.allsolid) + { + // entity is completely trapped in another solid + //pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration + pm->ps.velocity.z = 0; + return true; + } + + if (trace.fraction > 0) + // actually covered some distance + //VectorCopy (trace.endpos, pm->ps->origin); + pm->ps.origin = trace.endpos; + + if (trace.fraction == 1) + break; // moved the entire distance + + // save entity for contact8 + //PM_AddTouchEnt( trace.entityNum ); + + time_left -= time_left * trace.fraction; + + if (numplanes >= MAX_CLIP_PLANES) + { + // this shouldn't really happen + //VectorClear( pm->ps->velocity ); + pm->ps.velocity = Ogre::Vector3(0,0,0); + return true; + } + + // + // if this is the same plane we hit before, nudge velocity + // out along it, which fixes some epsilon issues with + // non-axial planes + // + for ( i = 0 ; i < numplanes ; i++ ) + { + if (trace.planenormal.dotProduct(planes[i]) > 0.99) //OGRE::VECTOR3 ? + //if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) + { + // pm->ps->velocity += (trace.plane.normal + pm->ps->velocity) + //VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity ); + pm->ps.velocity = (trace.planenormal + pm->ps.velocity); + break; + } + } + + if ( i < numplanes ) + continue; + + //VectorCopy (trace.plane.normal, planes[numplanes]); + planes[numplanes] = trace.planenormal; + numplanes++; + + // + // modify velocity so it parallels all of the clip planes + // + + // find a plane that it enters + for ( i = 0 ; i < numplanes ; i++ ) + { + //into = DotProduct( pm->ps->velocity, planes[i] ); + into = pm->ps.velocity.dotProduct(planes[i]); + if ( into >= 0.1 ) + continue; // move doesn't interact with the plane + + // see how hard we are hitting things + if ( -into > pml.impactSpeed ) + pml.impactSpeed = -into; + + // slide along the plane + //PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP ); + PM_ClipVelocity(pm->ps.velocity, planes[i], clipVelocity, OVERCLIP); + + // slide along the plane + PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP ); + + // see if there is a second plane that the new move enters + for ( j = 0 ; j < numplanes ; j++ ) + { + if ( j == i ) + continue; + + if (clipVelocity.dotProduct(planes[j]) >= 0.1) + //if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) + continue; // move doesn't interact with the plane + + // try clipping the move to the plane + PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP ); + PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP ); + + // see if it goes back into the first clip plane + if (clipVelocity.dotProduct(planes[i]) >= 0) + //if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) + continue; + + + // slide the original velocity along the crease + //dProduct (planes[i], planes[j], dir); + dir = planes[i].crossProduct(planes[j]) ; + + //VectorNormalize( dir ); + //D3DXVec3Normalize( (D3DXVECTOR3* const)&dir, (const D3DXVECTOR3* const)&dir); + VectorNormalize(dir); + + //d = DotProduct( dir, pm->ps->velocity ); + d = dir.dotProduct(pm->ps.velocity); + + //VectorScale( dir, d, clipVelocity ); + clipVelocity = dir * d; + + //CrossProduct (planes[i], planes[j], dir); + dir = planes[i].crossProduct(planes[j]) ; + + + //VectorNormalize( dir ); + //D3DXVec3Normalize( (D3DXVECTOR3* const)&dir, (const D3DXVECTOR3* const)&dir); + VectorNormalize(dir); + + //d = DotProduct( dir, endVelocity ); + d = dir.dotProduct(endVelocity); + + //VectorScale( dir, d, endClipVelocity ); + endClipVelocity = dir * d; + + // see if there is a third plane the the new move enters + for ( k = 0 ; k < numplanes ; k++ ) + { + if ( k == i || k == j ) + continue; + + if (clipVelocity.dotProduct(planes[k]) >= 0.1) + //if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) + continue; // move doesn't interact with the plane + + // stop dead at a tripple plane interaction + //VectorClear( pm->ps->velocity ); + //printf("Stop dead at a triple plane interaction\n"); + pm->ps.velocity = Ogre::Vector3(0,0,0); + return true; + } + } + + // if we have fixed all interactions, try another move + //VectorCopy( clipVelocity, pm->ps->velocity ); + pm->ps.velocity = clipVelocity; + + //VectorCopy( endClipVelocity, endVelocity ); + endVelocity = endClipVelocity; + break; + } + } + + if ( gravity ) + //VectorCopy( endVelocity, pm->ps->velocity ); + pm->ps.velocity = endVelocity; + + // don't change velocity if in a timer (FIXME: is this correct?) + if ( pm->ps.pm_time ) + //VectorCopy( primal_velocity, pm->ps->velocity ); + pm->ps.velocity = primal_velocity; + + //return ( (qboolean)(bumpcount != 0) ); + return bumpcount != 0; +} + +/* +================== +PM_StepSlideMove + +================== +*/ +int PM_StepSlideMove( bool gravity ) +{ + Ogre::Vector3 start_o, start_v; + Ogre::Vector3 down_o, down_v; + traceResults trace; +// float down_dist, up_dist; +// vec3_t delta, delta2; + Ogre::Vector3 up, down; + float stepSize; + + //std::cout << "StepSlideMove\n"; + // start_o = pm->ps->origin + //VectorCopy (pm->ps->origin, start_o); + start_o = pm->ps.origin; + + // start_v = pm->ps->velocity + //VectorCopy (pm->ps->velocity, start_v); + start_v = pm->ps.velocity; + + if ( PM_SlideMove( gravity ) == false ) + return 1; // we got exactly where we wanted to go first try + + + // down = start_o - vec3(0, 0, STEPSIZE) + //VectorCopy(start_o, down); + down = start_o; + down.z -= STEPSIZE; + + //pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, start_o, down, , 0, pml.scene); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); + newtrace(&trace, start_o, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + + // up = vec3(0, 0, 1) + //VectorSet(up, 0, 0, 1); + up = Ogre::Vector3(0.0f, 0.0f, 1.0f); + + // never step up when you still have up velocity + //if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) + if (pm->ps.velocity.z > 0 && ( + trace.fraction == 1.0 || trace.planenormal.dotProduct(up) < 0.7 + ) ) + return 2; + + // down_o = pm->ps->origin + //VectorCopy (pm->ps->origin, down_o); + down_o = pm->ps.origin; + + // down_v = pm->ps->velocity + //VectorCopy (pm->ps->velocity, down_v); + down_v = pm->ps.velocity; + + // up = start_o + vec3(0, 0, STEPSIZE) + //VectorCopy (start_o, up); + up = start_o; + //up[2] += STEPSIZE; + up.z += STEPSIZE; + + // test the player position if they were a stepheight higher + //pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&up, D3DXVECTOR3(0.0f, STEPSIZE, 0.0f), 0, pml.traceObj); + newtrace(&trace, start_o, up, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + if ( trace.allsolid ) + { + //if ( pm->debugLevel ) + //Com_Printf("%i:bend can't step\n", c_pmove); + //bprintf("bend can't step\n"); + return 3; // can't step up + } + + //stepSize = trace.endpos[2] - start_o[2]; + stepSize = trace.endpos.z - start_o.z; + + // try slidemove from this position + //VectorCopy (trace.endpos, pm->ps->origin); // pm->ps->origin = trace.endpos + pm->ps.origin = trace.endpos; + //VectorCopy (start_v, pm->ps->velocity); // pm->ps->velocity = start_v + pm->ps.velocity = start_v; + + PM_SlideMove( gravity ); + + // push down the final amount + + // down = pm->ps->origin - vec3(0, 0, stepSize) + //VectorCopy (pm->ps->origin, down); + down = pm->ps.origin; + //down[2] -= stepSize; + down.z -= stepSize; + + + //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); + newtrace(&trace, pm->ps.origin, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + if ( !trace.allsolid ) + //VectorCopy (trace.endpos, pm->ps->origin); + pm->ps.origin = trace.endpos; + + if ( trace.fraction < 1.0 ) + //PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); + PM_ClipVelocity(pm->ps.velocity, trace.planenormal, pm->ps.velocity, OVERCLIP); + + { + // use the step move + float delta; + + //delta = pm->ps->origin[2] - start_o[2]; + delta = pm->ps.origin.z - start_o.z; + if ( delta > 2 ) + { + pm->ps.counter = 10; + + /* + if (gravity) + printf("g on: %f ", delta); + else + printf("g off: %f ", delta); + + if ( delta < 7 ) + printf("stepped 3 < x < 7\n"); + //PM_AddEvent( EV_STEP_4 ); + else if ( delta < 11 ) + printf("stepped 7 < x < 11\n"); + //PM_AddEvent( EV_STEP_8 ); + else if ( delta < 15 ) + printf("stepped 11 < x < 15\n"); + //PM_AddEvent( EV_STEP_12 ); + else + printf("stepped 15+\n"); + //PM_AddEvent( EV_STEP_16 ); + */ + } + /*if ( pm->debugLevel ) + Com_Printf("%i:stepped\n", c_pmove);*/ + } + + return 4; +} + +void PM_Friction(void) +{ + + Ogre::Vector3 vec; + float* vel; + float speed, newspeed, control; + float drop; + + vel = &(pm->ps.velocity.x); + + // vec = vel + //VectorCopy( vel, vec ); + vec = pm->ps.velocity; + + if ( pml.walking ) + //vec[2] = 0; // ignore slope movement + vec.z = 0; + + //speed = VectorLength(vec); + speed = vec.length(); + if (speed < 1) + { + vel[0] = 0; + vel[1] = 0; // allow sinking underwater + // FIXME: still have z friction underwater? + //bprintf("Static friction (vec = [%f, %f, %f]) (vec.length = %f)\n", vec.x, vec.y, vec.z, speed); + return; + } + + drop = 0; + + // apply ground friction + if ( pm->ps.waterlevel <= 1 ) + { + if ( pml.walking )//&& !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) + { + // if getting knocked back, no friction + //if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) + { + control = (speed < pm_stopspeed) ? pm_stopspeed : speed; + drop += control * pm_friction * pml.frametime; + } + } + } + + // apply water friction even if just wading + if ( pm->ps.waterlevel ) + drop += speed * pm_waterfriction * pm->ps.waterlevel * pml.frametime; + + // apply flying friction + /*if ( pm->ps->powerups[PW_FLIGHT]) + drop += speed * pm_flightfriction * pml.frametime; + + if ( pm->ps->pm_type == PM_SPECTATOR) + drop += speed * pm_spectatorfriction * pml.frametime;*/ + if (pm->ps.move_type == PM_SPECTATOR) + drop += speed * pm_flightfriction * pml.frametime; + + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0) + newspeed = 0; + + newspeed /= speed; + + // vel *= newspeed + vel[0] = vel[0] * newspeed; + vel[1] = vel[1] * newspeed; + vel[2] = vel[2] * newspeed; +} + +float PM_CmdScale(playerMove::playercmd* const cmd) +{ + int max; + float total; + float scale; + + max = abs( cmd->forwardmove ); + if ( abs( cmd->rightmove ) > max ) + max = abs( cmd->rightmove ); + + if ( abs( cmd->upmove ) > max ) + max = abs( cmd->upmove ); + + if ( !max ) + return 0; + + total = sqrtf( (const float)(cmd->forwardmove * cmd->forwardmove + + cmd->rightmove * cmd->rightmove + cmd->upmove * cmd->upmove) ); + scale = (float)pm->ps.speed * max / ( 127.0f * total ); + if(pm->ps.move_type == PM_NOCLIP) + scale *= 10; + + return scale; +} + +static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel ) +{ +// int i; + float addspeed, accelspeed, currentspeed; + + // currentspeed = pm->ps->velocity dot wishdir + //currentspeed = DotProduct (pm->ps->velocity, wishdir); + currentspeed = pm->ps.velocity.dotProduct(wishdir); + + addspeed = wishspeed - currentspeed; + if (addspeed <= 0) + return; + + accelspeed = accel * pml.frametime * wishspeed; + + // Clamp accelspeed at addspeed + if (accelspeed > addspeed) + accelspeed = addspeed; + + // pm->ps->velocity += accelspeed * wishdir + //for (i=0 ; i<3 ; i++) + //pm->ps->velocity[i] += accelspeed * wishdir[i]; + pm->ps.velocity += (wishdir * accelspeed); +} + +static bool PM_CheckJump(void) +{ + //if ( pm->ps->pm_flags & PMF_RESPAWNED ) + //return qfalse; // don't allow jump until all buttons are up + + if ( pm->cmd.upmove < 10 ) + // not holding jump + return false; + + pm->cmd.upmove = 0; + + // must wait for jump to be released + /*if ( pm->ps->pm_flags & PMF_JUMP_HELD ) + { + // clear upmove so cmdscale doesn't lower running speed + pm->cmd.upmove = 0; + return false; + }*/ + + pml.groundPlane = false; // jumping away + pml.walking = false; + //pm->ps->pm_flags |= PMF_JUMP_HELD; + + pm->ps.groundEntityNum = ENTITYNUM_NONE; + pm->ps.velocity.z = JUMP_VELOCITY; + pm->ps.bSnap = false; + //PM_AddEvent( EV_JUMP ); + + /*if ( pm->cmd.forwardmove >= 0 ) + { + PM_ForceLegsAnim( LEGS_JUMP ); + pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; + } + else + { + PM_ForceLegsAnim( LEGS_JUMPB ); + pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + }*/ + + return true; +} + +static void PM_WaterMove( playerMove* const pm ) +{ + //int i; + //vec3_t wishvel; + Ogre::Vector3 wishvel; + float wishspeed; + //vec3_t wishdir; + Ogre::Vector3 wishdir; + float scale; + float vel; + + pm->ps.bSnap = false; + + /*if ( PM_CheckWaterJump() ) + { + PM_WaterJumpMove(); + return; + }*/ +#if 0 + // jump = head for surface + if ( pm->cmd.upmove >= 10 ) { + if (pm->ps->velocity[2] > -300) { + if ( pm->watertype == CONTENTS_WATER ) { + pm->ps->velocity[2] = 100; + } else if (pm->watertype == CONTENTS_SLIME) { + pm->ps->velocity[2] = 80; + } else { + pm->ps->velocity[2] = 50; + } + } + } +#endif + PM_Friction (); + + if (pm->cmd.forwardmove || pm->cmd.rightmove) + { + //NEEDS TO BE REWRITTEN FOR OGRE TIME--------------------------------------------------- + /* + static const TimeTicks footstep_duration = GetTimeFreq(); // make each splash last 1.0s + static TimeTicks lastStepTime = 0; + const TimeTicks thisStepTime = GetTimeQPC(); + static bool lastWasLeft = false; + if (thisStepTime > lastStepTime) + { + if (pm->cmd.ducking) + lastStepTime = thisStepTime + footstep_duration * 2; // splashes while ducking are twice as slow + else + lastStepTime = thisStepTime + footstep_duration; + + lastWasLeft = !lastWasLeft; + */ + //-----------------jhooks1 + + /* + namestruct defaultCreature; + const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, lastWasLeft ? SNDG::r_swim : SNDG::l_swim); + if (sndg) + { + const namestruct& SOUNID = sndg->soundID; + const SOUN* const soun = SOUN::GetSound(SOUNID); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() ); + } + }*/ + //Sound, ignore for now -- jhooks1 + //} + } + + scale = PM_CmdScale( &pm->cmd ); + // + // user intentions + // + if ( !scale ) + { + /*wishvel[0] = 0; + wishvel[1] = 0; + wishvel[2] = -60; // sink towards bottom + */ + wishvel.x = 0; + wishvel.z = -60; + wishvel.y = 0; + } + else + { + /*for (i=0 ; i<3 ; i++) + wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;*/ + wishvel = pml.forward * scale * pm->cmd.forwardmove + pml.right * scale * pm->cmd.rightmove; + + //wishvel[2] += scale * pm->cmd.upmove; + wishvel.z += pm->cmd.upmove * scale; + } + + //VectorCopy (wishvel, wishdir); + wishdir = wishvel; + wishspeed = VectorNormalize(wishdir); + + if ( wishspeed > pm->ps.speed * pm_swimScale ) + wishspeed = pm->ps.speed * pm_swimScale; + + PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate); + + // make sure we can go up slopes easily under water + //if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 ) + if (pml.groundPlane && pm->ps.velocity.dotProduct(pml.groundTrace.planenormal) < 0.0f) + { + //vel = VectorLength(pm->ps->velocity); + vel = pm->ps.velocity.length(); + + // slide along the ground plane + //PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); + PM_ClipVelocity(pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP); + + VectorNormalize(pm->ps.velocity); + //VectorScale(pm->ps->velocity, vel, pm->ps->velocity); + pm->ps.velocity = pm->ps.velocity * vel; + } + + PM_SlideMove( false ); +} + +/* +=================== +PM_WalkMove + +=================== +*/ +static void PM_WalkMove( playerMove* const pmove ) +{ +// int i; + Ogre::Vector3 wishvel; + float fmove, smove; + Ogre::Vector3 wishdir; + float wishspeed; + float scale; + playerMove::playercmd cmd; + float accelerate; + float vel; + //pm->ps.gravity = 4000; + + if ( pm->ps.waterlevel > 2 && //DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 ) + pml.forward.dotProduct(pml.groundTrace.planenormal) > 0.0f) + { + // begin swimming + PM_WaterMove(pmove); + return; + } + + + if ( PM_CheckJump () ) + { + + // jumped away + if ( pm->ps.waterlevel > 1 ) + PM_WaterMove(pmove); + else + PM_AirMove(); + //printf("Jumped away\n"); + return; + } + + // Footsteps time + if (pmove->cmd.forwardmove || pmove->cmd.rightmove) + { + bool step_underwater = false; + //if (pmove->traceObj) + //{ + + + //jhooks1 - Water handling, deal with later + + + + if (pmove->hasWater) + { + if (pmove->hasWater ) + { + const float waterHeight = pmove->waterHeight; + const float waterSoundStepHeight = waterHeight + halfExtents.y; + if (pmove->ps.origin.y < waterSoundStepHeight) + step_underwater = true; + } + } + //} + + /* + static const TimeTicks footstep_duration = GetTimeFreq() / 2; // make each footstep last 500ms + static TimeTicks lastStepTime = 0; + const TimeTicks thisStepTime = GetTimeQPC(); + static bool lastWasLeft = false; + if (thisStepTime > lastStepTime) + { + if (pmove->cmd.ducking) + lastStepTime = thisStepTime + footstep_duration * 2; // footsteps while ducking are twice as slow + else + lastStepTime = thisStepTime + footstep_duration; + + lastWasLeft = !lastWasLeft; + */ + + if (step_underwater) + { + /* + const namestruct ns(lastWasLeft ? "FootWaterRight" : "FootWaterLeft"); + const SOUN* const soun = SOUN::GetSound(ns); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() ); + }*/ + } + else + { + /* + namestruct defaultCreature; + const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, lastWasLeft ? SNDG::r_foot : SNDG::l_foot); + if (sndg) + { + const namestruct& SOUNID = sndg->soundID; + const SOUN* const soun = SOUN::GetSound(SOUNID); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() ); + } + }*/ + } + } + + + PM_Friction (); + + + //bprintf("vel: (%f, %f, %f)\n", pm->ps.velocity.x, pm->ps.velocity.y, pm->ps.velocity.z); + + fmove = pm->cmd.forwardmove; + smove = pm->cmd.rightmove; + + + cmd = pm->cmd; + scale = PM_CmdScale( &cmd ); + + // set the movementDir so clients can rotate the legs for strafing + //PM_SetMovementDir(); + + // project moves down to flat plane + //pml.forward[2] = 0; + pml.forward.z = 0; + + //pml.right[2] = 0; + pml.right.z = 0; + //std::cout << "Further down" << pm->ps.velocity << "\n"; + + + // project the forward and right directions onto the ground plane + PM_ClipVelocity (pml.forward, pml.groundTrace.planenormal, pml.forward, OVERCLIP ); + PM_ClipVelocity (pml.right, pml.groundTrace.planenormal, pml.right, OVERCLIP ); + //std::cout << "Clip velocity" << pm->ps.velocity << "\n"; + // + + VectorNormalize (pml.forward); + VectorNormalize (pml.right); + //pml.forward = pml.forward.normalise(); + //pml.right = pml.right.normalise(); + //std::cout << "forward2" << pml.forward << "\n"; + //std::cout << "right2" << pml.right << "\n"; + + + // wishvel = (pml.forward * fmove) + (pml.right * smove); + //for ( i = 0 ; i < 3 ; i++ ) + //wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove; + wishvel = pml.forward * fmove + pml.right * smove; + + + //bprintf("f: (%f, %f, %f), s: (%f, %f, %f)\n", fmove, smove); + + + // when going up or down slopes the wish velocity should Not be zero +// wishvel[2] = 0; + + // wishdir = wishvel + //VectorCopy (wishvel, wishdir); + //wishvel = wishdir; + wishdir = wishvel; + + wishspeed = VectorNormalize(wishdir); + //std::cout << "Wishspeed: " << wishspeed << "\n"; + wishspeed *= scale; + //std::cout << "Wishspeed scaled:" << wishspeed << "\n"; + + // clamp the speed lower if ducking + if ( pm->cmd.ducking ) + if ( wishspeed > pm->ps.speed * pm_duckScale ) + wishspeed = pm->ps.speed * pm_duckScale; + + // clamp the speed lower if wading or walking on the bottom + if ( pm->ps.waterlevel ) + { + float waterScale; + + waterScale = pm->ps.waterlevel / 3.0f; + waterScale = 1.0f - ( 1.0f - pm_swimScale ) * waterScale; + if ( wishspeed > pm->ps.speed * waterScale ) + wishspeed = pm->ps.speed * waterScale; + } + + // when a player gets hit, they temporarily lose + // full control, which allows them to be moved a bit + //if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) + //accelerate = pm_airaccelerate; + //else + accelerate = pm_accelerate; + + + PM_Accelerate (wishdir, wishspeed, accelerate); + //std::cout << "Velocityafter: " << pm->ps.velocity << "\n"; + + //Com_Printf("velocity = %1.1f %1.1f %1.1f\n", pm->ps->velocity[0], pm->ps->velocity[1], pm->ps->velocity[2]); + //Com_Printf("velocity1 = %1.1f\n", VectorLength(pm->ps->velocity)); + + //if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) + //pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime; + //else + //{ + // don't reset the z velocity for slopes +// pm->ps->velocity[2] = 0; + //} + + //vel = VectorLength(pm->ps->velocity); + vel = pm->ps.velocity.length(); + //std::cout << "The length" << vel << "\n"; + + // slide along the ground plane + PM_ClipVelocity (pm->ps.velocity, pml.groundTrace.planenormal, + pm->ps.velocity, OVERCLIP ); + //std::cout << "Velocity clipped" << pm->ps.velocity << "\n"; + + // don't decrease velocity when going up or down a slope + VectorNormalize(pm->ps.velocity); + //pm->ps.velocity = pm->ps.velocity.normalise(); + + //std::cout << "Final:" << pm->ps.velocity << "\n"; + //VectorScale(pm->ps->velocity, vel, pm->ps->velocity); + pm->ps.velocity = pm->ps.velocity * vel; + + // don't do anything if standing still + //if (!pm->ps->velocity[0] && !pm->ps->velocity[1]) + if (!pm->ps.velocity.x && !pm->ps.velocity.z) + return; + + PM_StepSlideMove( false ); + + //Com_Printf("velocity2 = %1.1f\n", VectorLength(pm->ps->velocity)); + + +} + +void PM_UpdateViewAngles( playerMove::playerStruct* const ps, playerMove::playercmd* const cmd ) +{ + short temp; + int i; + + //while(1); + + //if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPINTERMISSION) + //return; // no view changes at all + + //if ( ps->pm_type != PM_SPECTATOR && ps->stats[STAT_HEALTH] <= 0 ) + //return; // no view changes at all + + // circularly clamp the angles with deltas + //bprintf("View angles: %i, %i, %i\n", cmd->angles[0], cmd->angles[1], cmd->angles[2]); + for (i = 0 ; i < 3 ; i++) + { + temp = cmd->angles[i];// + ps->delta_angles[i]; + //if ( i == PITCH ) + { + // don't let the player look up or down more than 90 degrees + /*if ( temp > 16000 ) + { + ps->delta_angles[i] = 16000 - cmd->angles[i]; + temp = 16000; + } + else if ( temp < -16000 ) + { + ps->delta_angles[i] = -16000 - cmd->angles[i]; + temp = -16000; + }*/ + } + (&(ps->viewangles.x) )[i] = SHORT2ANGLE(temp); + //cmd->angles[i] += ps->delta_angles[i]; + } + //ps->delta_angles[0] = ps->delta_angles[1] = ps->delta_angles[2] = 0; + +} + +void AngleVectors( const Ogre::Vector3& angles, Ogre::Vector3* const forward, Ogre::Vector3* const right, Ogre::Vector3* const up) +{ + float angle; + static float sr, sp, sy, cr, cp, cy; + // static to help MS compiler fp bugs + + //angle = angles[YAW] * (M_PI*2 / 360); + angle = angles.x * (M_PI * 2.0f / 360.0f); + sp = sinf(angle); + cp = cosf(angle); + + //angle = angles[PITCH] * (M_PI*2 / 360); + angle = angles.y * (-M_PI * 2.0f / 360.0f); + sy = sinf(angle); + cy = cosf(angle); + + //angle = angles[ROLL] * (M_PI*2 / 360); + angle = angles.z * (M_PI * 2.0f / 360.0f); + sr = sinf(angle); + cr = cosf(angle); + + if (forward) + { + forward->x = cp * cy; + forward->y = cp * sy; + forward->z = -sp; + } + if (right) + { + right->x = (-1 * sr * sp * cy + -1 * cr * -sy); + right->y = (-1 * sr * sp * sy + -1 * cr * cy); + right->z = 0; + } + if (up) + { + up->x =(cr * sp * cy + -sr * -sy); + up->y=(cr * sp * sy + -sr * cy); + up->z = cr * cp; + } + +} + +void PM_GroundTraceMissed() +{ + traceResults trace; + Ogre::Vector3 point; + //std::cout << "Ground trace missed\n"; + // we just transitioned into freefall + //if ( pm->debugLevel ) + //Com_Printf("%i:lift\n", c_pmove); + + // if they aren't in a jumping animation and the ground is a ways away, force into it + // if we didn't do the trace, the player would be backflipping down staircases + //VectorCopy( pm->ps->origin, point ); + point = pm->ps.origin; + //point[2] -= 64; + point.z -= 32; + + //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -64.0f, 0.0f), 0, pml.traceObj); + newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + //It hit the ground below + if ( trace.fraction < 1.0 && pm->ps.origin.z > trace.endpos.z) + { + pm->ps.origin = trace.endpos; + pml.walking = true; + pml.groundPlane = true; + pm->ps.groundEntityNum = trace.entityNum; + + } + else{ + pm->ps.groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = false; + pml.walking = false; + pm->ps.bSnap = false; + } + + +} + +static bool PM_CorrectAllSolid(traceResults* const trace) +{ + int i, j, k; + Ogre::Vector3 point; + + //if ( pm->debugLevel ) + //Com_Printf("%i:allsolid\n", c_pmove); + //bprintf("allsolid\n"); + + // jitter around + for (i = -1; i <= 1; i++) + { + for (j = -1; j <= 1; j++) + { + for (k = -1; k <= 1; k++) + { + //VectorCopy(pm->ps->origin, point); + point = pm->ps.origin; + + /*point[0] += (float) i; + point[1] += (float) j; + point[2] += (float) k;*/ + point += Ogre::Vector3( (const float)i, (const float)j, (const float)k); + + //pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); + //tracefunc(trace, *(const D3DXVECTOR3* const)&point, *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0, pml.traceObj); + newtrace(trace, point, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + + if ( !trace->allsolid ) + { + /*point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - 0.25;*/ + point = pm->ps.origin; + point.z -= 0.25f; + + //pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); + //tracefunc(trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); + newtrace(trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + pml.groundTrace = *trace; + return true; + } + } + } + } + + //pm->ps->groundEntityNum = ENTITYNUM_NONE; + pm->ps.groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = false; + pml.walking = false; + + return false; +} + +static void PM_CrashLand( void ) +{ + float delta; + float dist ; + float vel, acc; + float t; + float a, b, c, den; + + // decide which landing animation to use + /*if ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP ) + PM_ForceLegsAnim( LEGS_LANDB ); + else + PM_ForceLegsAnim( LEGS_LAND ); + + pm->ps->legsTimer = TIMER_LAND;*/ + + // calculate the exact velocity on landing + //dist = pm->ps->origin[2] - pml.previous_origin[2]; + + dist = pm->ps.origin.z - pml.previous_origin.z; + + //vel = pml.previous_velocity[2]; + vel = pml.previous_velocity.z; + + //acc = -pm->ps->gravity; + acc = -pm->ps.gravity; + + a = acc / 2; + b = vel; + c = -dist; + + den = b * b - 4 * a * c; + if ( den < 0 ) + return; + + t = (-b - sqrtf( den ) ) / ( 2 * a ); + + delta = vel + t * acc; + delta = delta * delta * 0.0001f; + + // ducking while falling doubles damage + /*if ( pm->ps->pm_flags & PMF_DUCKED ) + delta *= 2;*/ + if (pm->cmd.upmove < -20) + delta *= 2; + + // never take falling damage if completely underwater + if ( pm->ps.waterlevel == 3 ) + return; + + // reduce falling damage if there is standing water + if ( pm->ps.waterlevel == 2 ) + delta *= 0.25; + if ( pm->ps.waterlevel == 1 ) + delta *= 0.5; + + if ( delta < 1 ) + return; +/* + if (delta > 60) + printf("Far crashland: %f\n", delta); + else if (delta > 40) + printf("Medium crashland: %f\n", delta); + else if (delta > 4) + printf("Short crashland: %f\n", delta); +*/ + if (delta > 60) + { + /* + static const namestruct healthDamage("Health Damage"); + const SOUN* const soun = SOUN::GetSound(healthDamage); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() ); + }*/ + } + + if (delta > 3) // We need at least a short crashland to proc the sound effects: + { + bool splashSound = false; + + if (pm->hasWater) + { + + const float waterHeight = pm->waterHeight; + const float waterHeightSplash = waterHeight + halfExtents.y; + if (pm->ps.origin.z < waterHeightSplash) + { + splashSound = true; + } + + } + + + if (splashSound) + { + //Change this later----------------------------------- + /* + const namestruct ns("DefaultLandWater"); + const SOUN* const soun = SOUN::GetSound(ns); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundDatga->GetVolumeFloat() ); + }*/ + } + else + { + //Change this later--------------------------------- + /* + namestruct defaultCreature; + const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, SNDG::land); + if (sndg) + { + const namestruct& SOUNID = sndg->soundID; + const SOUN* const soun = SOUN::GetSound(SOUNID); + if (soun) + { + PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() ); + } + }*/ + } + } + + // create a local entity event to play the sound + + // SURF_NODAMAGE is used for bounce pads where you don't ever + // want to take damage or play a crunch sound + //if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) + { + /*if ( delta > 60 ) + PM_AddEvent( EV_FALL_FAR ); + else if ( delta > 40 ) + { + // this is a pain grunt, so don't play it if dead + if ( pm->ps->stats[STAT_HEALTH] > 0 ) + PM_AddEvent( EV_FALL_MEDIUM ); + } + else if ( delta > 7 ) + PM_AddEvent( EV_FALL_SHORT ); + else + PM_AddEvent( PM_FootstepForSurface() );*/ + } + + // start footstep cycle over + //pm->ps->bobCycle = 0; +} + +static void PM_GroundTrace( void ) +{ + Ogre::Vector3 point; + traceResults trace; + + /*point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - 0.25;*/ + point = pm->ps.origin; + point.z -= 0.25f; + + //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); + //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); + newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + pml.groundTrace = trace; + + // do something corrective if the trace starts in a solid... + if ( trace.allsolid ) { + //std::cout << "ALL SOLID\n"; + if ( !PM_CorrectAllSolid(&trace) ){ + //std::cout << "Returning after correct all solid\n"; + return; + } + } + // if the trace didn't hit anything, we are in free fall + if ( trace.fraction == 1.0) + { + if(pm->ps.snappingImplemented){ + if(pm->ps.bSnap && pm->ps.counter <= 0) + PM_GroundTraceMissed(); + } + + + return; + } + else + { + //It hit something, so we are on the ground + pm->ps.bSnap = true; + + } + // check if getting thrown off the ground + //if ( pm->ps->velocity[2] > 0 && DotProduct( pm->ps->velocity, trace.plane.normal ) > 10 ) + if (pm->ps.velocity.z > 0 && pm->ps.velocity.dotProduct(trace.planenormal) > 10.0f ) + { + //if ( pm->debugLevel ) + //Com_Printf("%i:kickoff\n", c_pmove); + + // go into jump animation + /*if ( pm->cmd.forwardmove >= 0 ) + { + PM_ForceLegsAnim( LEGS_JUMP ); + pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; + } + else + { + PM_ForceLegsAnim( LEGS_JUMPB ); + pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + }*/ + if(!pm->ps.bSnap){ + pm->ps.groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = false; + pml.walking = false; + } + else + { + pml.groundPlane = true; + pml.walking = true; + } + return; + } + + + + + // slopes that are too steep will not be considered onground + //if ( trace.plane.normal[2] < MIN_WALK_NORMAL ) + if (trace.planenormal.z < MIN_WALK_NORMAL) + { + //if ( pm->debugLevel ) + //Com_Printf("%i:steep\n", c_pmove); + + // FIXME: if they can't slide down the slope, let them + // walk (sharp crevices) + pm->ps.groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = true; + pml.walking = false; + return; + } + + pml.groundPlane = true; + pml.walking = true; + + // hitting solid ground will end a waterjump + /*if (pm->ps.pm_flags & PMF_TIME_WATERJUMP) + { + pm->ps->pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND); + pm->ps->pm_time = 0; + }*/ + + if ( pm->ps.groundEntityNum == ENTITYNUM_NONE ) + { + // just hit the ground + /*if ( pm->debugLevel ) + Com_Printf("%i:Land\n", c_pmove);*/ + //bprintf("Land\n"); + + PM_CrashLand(); + + // don't do landing time if we were just going down a slope + //if ( pml.previous_velocity[2] < -200 ) + if (pml.previous_velocity.z < -200) + { + // don't allow another jump for a little while + //pm->ps->pm_flags |= PMF_TIME_LAND; + pm->ps.pm_time = 250; + } + } + + pm->ps.groundEntityNum = trace.entityNum; + + // don't reset the z velocity for slopes +// pm->ps->velocity[2] = 0; + + //PM_AddTouchEnt( trace.entityNum ); +} + +void PM_AirMove() +{ + //int i; + Ogre::Vector3 wishvel; + float fmove, smove; + Ogre::Vector3 wishdir; + float wishspeed; + float scale; + playerMove::playercmd cmd; + //pm->ps.gravity = 800; + PM_Friction(); + + fmove = pm->cmd.forwardmove; + smove = pm->cmd.rightmove; + + cmd = pm->cmd; + scale = PM_CmdScale( &cmd ); + // set the movementDir so clients can rotate the legs for strafing + //PM_SetMovementDir(); + + // project moves down to flat plane + //pml.forward[2] = 0; + pml.forward.z = 0; //Z or Y? + //pml.right[2] = 0; + pml.right.z = 0; + //VectorNormalize (pml.forward); + VectorNormalize(pml.forward); + VectorNormalize(pml.right); + //VectorNormalize (pml.right); + + //for ( i = 0 ; i < 2 ; i++ ) + //wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove; + wishvel = pml.forward * fmove + pml.right * smove; + + //wishvel[2] = 0; + wishvel.z = 0; + + //VectorCopy (wishvel, wishdir); + wishdir = wishvel; + //wishspeed = VectorNormalize(wishdir); + wishspeed = VectorNormalize(wishdir); + + wishspeed *= scale; + + // not on ground, so little effect on velocity + PM_Accelerate (wishdir, wishspeed, pm_airaccelerate); + + // we may have a ground plane that is very steep, even + // though we don't have a groundentity + // slide along the steep plane + if ( pml.groundPlane ) + PM_ClipVelocity (pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP ); + +/*#if 0 + //ZOID: If we are on the grapple, try stair-stepping + //this allows a player to use the grapple to pull himself + //over a ledge + if (pm->ps->pm_flags & PMF_GRAPPLE_PULL) + PM_StepSlideMove ( qtrue ); + else + PM_SlideMove ( qtrue ); +#endif*/ + + /*bprintf("%i ", */PM_StepSlideMove ( true )/* )*/; +} + +static void PM_NoclipMove( void ) +{ + float speed, drop, friction, control, newspeed; +// int i; + Ogre::Vector3 wishvel; + float fmove, smove; + Ogre::Vector3 wishdir; + float wishspeed; + float scale; + + //pm->ps->viewheight = DEFAULT_VIEWHEIGHT; + + // friction + + //speed = VectorLength (pm->ps->velocity); + speed = pm->ps.velocity.length(); + if (speed < 1) + //VectorCopy (vec3_origin, pm->ps->velocity); + pm->ps.velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f); + else + { + drop = 0; + + friction = pm_friction * 1.5f; // extra friction + control = speed < pm_stopspeed ? pm_stopspeed : speed; + drop += control * friction * pml.frametime; + + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0) + newspeed = 0; + newspeed /= speed; + + //VectorScale (pm->ps->velocity, newspeed, pm->ps->velocity); + pm->ps.velocity = pm->ps.velocity * newspeed; + } + + // accelerate + scale = PM_CmdScale( &pm->cmd ); + + fmove = pm->cmd.forwardmove; + smove = pm->cmd.rightmove; + + //for (i=0 ; i<3 ; i++) + //wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove; + + wishvel = pml.forward * fmove + pml.right * smove; + //wishvel[2] += pm->cmd.upmove; + wishvel.z += pm->cmd.upmove; + + //VectorCopy (wishvel, wishdir); + wishdir = wishvel; + wishspeed = VectorNormalize(wishdir); + wishspeed *= scale; + + + PM_Accelerate( wishdir, wishspeed, pm_accelerate ); + + // move + //VectorMA (pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin); + pm->ps.origin = pm->ps.origin + pm->ps.velocity * pml.frametime; +} + +static void PM_DropTimers( void ) +{ + // drop misc timing counter + if ( pm->ps.pm_time ) + { + if ( pml.msec >= pm->ps.pm_time ) + { + //pm->ps->pm_flags &= ~PMF_ALL_TIMES; + pm->ps.pm_time = 0; + } + else + pm->ps.pm_time -= pml.msec; + } + + //bprintf("Time: %i\n", pm->ps.pm_time); + + // drop animation counter + /*if ( pm->ps->legsTimer > 0 ) + { + pm->ps->legsTimer -= pml.msec; + if ( pm->ps->legsTimer < 0 ) + pm->ps->legsTimer = 0; + } + + if ( pm->ps->torsoTimer > 0 ) + { + pm->ps->torsoTimer -= pml.msec; + if ( pm->ps->torsoTimer < 0 ) + pm->ps->torsoTimer = 0; + }*/ +} + +static void PM_FlyMove( void ) +{ + //int i; + Ogre::Vector3 wishvel; + float wishspeed; + Ogre::Vector3 wishdir; + float scale; + + // normal slowdown + PM_Friction (); + + scale = PM_CmdScale( &pm->cmd ); + // + // user intentions + // + if ( !scale ) + { + /*wishvel[0] = 0; + wishvel[1] = 0; + wishvel[2] = 0;*/ + wishvel = Ogre::Vector3(0,0,0); + } + else + { + //for (i=0 ; i<3 ; i++) + //wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove; + wishvel = pml.forward * scale * pm->cmd.forwardmove + pml.right * scale * pm->cmd.rightmove; + + //wishvel[2] += scale * pm->cmd.upmove; + wishvel.z += /*6.35f * */pm->cmd.upmove * scale; + } + + //VectorCopy (wishvel, wishdir); + wishdir = wishvel; + + //wishspeed = VectorNormalize(wishdir); + wishspeed = VectorNormalize(wishdir); + + PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate); + + PM_StepSlideMove( false ); +} + + +void PM_SetWaterLevel( playerMove* const pm ) +{ + Ogre::Vector3 point; + //int cont; + int sample1; + int sample2; + + // + // get waterlevel, accounting for ducking + // + + pm->ps.waterlevel = WL_DRYLAND; + pm->ps.watertype = 0; + + /*point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] + MINS_Z + 1; */ + point.x = pm->ps.origin.x; + point.y = pm->ps.origin.y; + point.z = pm->ps.origin.z + MINS_Z + 1; + + //cont = pm->pointcontents( point, pm->ps->clientNum ); + bool checkWater = (pml.hasWater && pml.waterHeight > point.z); + //if ( cont & MASK_WATER ) + if ( checkWater) + { + sample2 = /*pm->ps.viewheight*/DEFAULT_VIEWHEIGHT - MINS_Z; + sample1 = sample2 / 2; + + pm->ps.watertype = CONTENTS_WATER;//cont; + pm->ps.waterlevel = WL_ANKLE; + //point[2] = pm->ps->origin[2] + MINS_Z + sample1; + point.z = pm->ps.origin.z + MINS_Z + sample1; + checkWater = (pml.hasWater && pml.waterHeight > point.z); + //cont = pm->pointcontents (point, pm->ps->clientNum ); + //if ( cont & MASK_WATER ) + if (checkWater) + { + pm->ps.waterlevel = WL_WAIST; + //point[2] = pm->ps->origin[2] + MINS_Z + sample2; + point.z = pm->ps.origin.z + MINS_Z + sample2; + //cont = pm->pointcontents (point, pm->ps->clientNum ); + //if ( cont & MASK_WATER ) + checkWater = (pml.hasWater && pml.waterHeight > point.z); + if (checkWater ) + pm->ps.waterlevel = WL_UNDERWATER; + } + } +} + +void PmoveSingle (playerMove* const pmove) +{ + pmove->ps.counter--; + //pm = pmove; + + // Aedra doesn't support Q3-style VM traps D: //while(1); + + // this counter lets us debug movement problems with a journal + // by setting a conditional breakpoint fot the previous frame + //c_pmove++; + + // clear results + //pm->numtouch = 0; + pm->ps.watertype = 0; + pm->ps.waterlevel = WL_DRYLAND; + + //if ( pm->ps->stats[STAT_HEALTH] <= 0 ) + //pm->tracemask &= ~CONTENTS_BODY; // corpses can fly through bodies + + + // make sure walking button is clear if they are running, to avoid + // proxy no-footsteps cheats + //if ( abs( pm->cmd.forwardmove ) > 64 || abs( pm->cmd.rightmove ) > 64 ) + //pm->cmd.buttons &= ~BUTTON_WALKING; + + + // set the talk balloon flag + //if ( pm->cmd.buttons & BUTTON_TALK ) + //pm->ps->eFlags |= EF_TALK; + //else + //pm->ps->eFlags &= ~EF_TALK; + + // set the firing flag for continuous beam weapons + /*if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION + && ( pm->cmd.buttons & BUTTON_ATTACK ) && pm->ps->ammo[ pm->ps->weapon ] ) + pm->ps->eFlags |= EF_FIRING; + else + pm->ps->eFlags &= ~EF_FIRING;*/ + + // clear the respawned flag if attack and use are cleared + /*if ( pm->ps->stats[STAT_HEALTH] > 0 && + !( pm->cmd.buttons & (BUTTON_ATTACK | BUTTON_USE_HOLDABLE) ) ) + pm->ps->pm_flags &= ~PMF_RESPAWNED;*/ + + // if talk button is down, dissallow all other input + // this is to prevent any possible intercept proxy from + // adding fake talk balloons + /*if ( pmove->cmd.buttons & BUTTON_TALK ) + { + // keep the talk button set tho for when the cmd.serverTime > 66 msec + // and the same cmd is used multiple times in Pmove + pmove->cmd.buttons = BUTTON_TALK; + pmove->cmd.forwardmove = 0; + pmove->cmd.rightmove = 0; + pmove->cmd.upmove = 0; + }*/ + + // clear all pmove local vars + memset (&pml, 0, sizeof(pml) ); + + // Aedra-specific code: + //pml.scene = global_lastscene; + + + // End Aedra-specific code + pml.hasWater = pmove->hasWater; + pml.isInterior = pmove->isInterior; + pml.waterHeight = pmove->waterHeight; +#ifdef _DEBUG + if (!pml.traceObj) + __debugbreak(); + + if (!pml.traceObj->incellptr) + __debugbreak(); +#endif + + // determine the time + pml.msec = pmove->cmd.serverTime - pm->ps.commandTime; + if ( pml.msec < 1 ) + pml.msec = 1; + else if ( pml.msec > 200 ) + pml.msec = 200; + + //pm->ps->commandTime = pmove->cmd.serverTime; + + // Commented out as a hack + pm->ps.commandTime = pmove->cmd.serverTime; + + // Handle state change procs: + if (pm->cmd.activating != pm->cmd.lastActivatingState) + { + if (!pm->cmd.lastActivatingState && pm->cmd.activating) + pm->cmd.procActivating = playerMove::playercmd::KEYDOWN; + else + pm->cmd.procActivating = playerMove::playercmd::KEYUP; + } + else + { + pm->cmd.procActivating = playerMove::playercmd::NO_CHANGE; + } + pm->cmd.lastActivatingState = pm->cmd.activating; + + if (pm->cmd.dropping != pm->cmd.lastDroppingState) + { + if (!pm->cmd.lastDroppingState && pm->cmd.dropping) + pm->cmd.procDropping = playerMove::playercmd::KEYDOWN; + else + pm->cmd.procDropping = playerMove::playercmd::KEYUP; + } + else + { + pm->cmd.procDropping = playerMove::playercmd::NO_CHANGE; + } + pm->cmd.lastDroppingState = pm->cmd.dropping; + + // save old org in case we get stuck + //VectorCopy (pm->ps->origin, pml.previous_origin); + pml.previous_origin = pm->ps.origin; + + // Copy over the lastframe origin + pmove->ps.lastframe_origin = pmove->ps.origin; + + //pmove->ps.lastframe_origin = pmove->ps.origin; + + // save old velocity for crashlanding + //VectorCopy (pm->ps->velocity, pml.previous_velocity); + pml.previous_velocity = pm->ps.velocity; + + pml.frametime = pml.msec * 0.001f; + + // update the viewangles + //PM_UpdateViewAngles( &(pm->ps), &(pm->cmd) ); + + AngleVectors (pm->ps.viewangles, &(pml.forward), &(pml.right), &(pml.up) ); + + //if ( pm->cmd.upmove < 10 ) + // not holding jump + //pm->ps->pm_flags &= ~PMF_JUMP_HELD; + + // decide if backpedaling animations should be used + /*if ( pm->cmd.forwardmove < 0 ) + pm->ps->pm_flags |= PMF_BACKWARDS_RUN; + else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) + pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN;*/ + + /*if ( pm->ps->pm_type >= PM_DEAD ) + { + pm->cmd.forwardmove = 0; + pm->cmd.rightmove = 0; + pm->cmd.upmove = 0; + }*/ + + if ( pm->ps.move_type == PM_SPECTATOR ) + { + + //PM_CheckDuck (); + PM_FlyMove (); + PM_DropTimers (); + return; + } + + if ( pm->ps.move_type == PM_NOCLIP ) + { + + PM_NoclipMove (); + PM_DropTimers (); + return; + } + + if (pm->ps.move_type == PM_FREEZE){ + + return; // no movement at all + + } + + if ( pm->ps.move_type == PM_INTERMISSION || pm->ps.move_type == PM_SPINTERMISSION){ + return; // no movement at all + } + + // set watertype, and waterlevel + PM_SetWaterLevel(pmove); + pml.previous_waterlevel = pmove->ps.waterlevel; + + // set mins, maxs, and viewheight + //PM_CheckDuck (); + + // set groundentity + PM_GroundTrace(); + + /*if ( pm->ps->pm_type == PM_DEAD ) + PM_DeadMove (); + + PM_DropTimers();*/ + + PM_DropTimers(); + +/*#ifdef MISSIONPACK + if ( pm->ps->powerups[PW_INVULNERABILITY] ) { + PM_InvulnerabilityMove(); + } else +#endif*/ + /*if ( pm->ps->powerups[PW_FLIGHT] ) + // flight powerup doesn't allow jump and has different friction + PM_FlyMove(); + else if (pm->ps->pm_flags & PMF_GRAPPLE_PULL) + { + PM_GrappleMove(); + // We can wiggle a bit + PM_AirMove(); + } + else if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) + PM_WaterJumpMove();*/ + if ( pmove->ps.waterlevel > 1 ) + // swimming + PM_WaterMove(pmove); + else if ( pml.walking ) + { + + // walking on ground + PM_WalkMove(pmove); + //bprintf("WalkMove\n"); + } + else + { + // airborne + //std::cout << "AIRMOVE\n"; + PM_AirMove(); + //bprintf("AirMove\n"); + } + + //PM_Animate(); + + // set groundentity, watertype, and waterlevel + PM_GroundTrace(); + PM_SetWaterLevel(pmove); + + // weapons + /*PM_Weapon(); + + // torso animation + PM_TorsoAnimation(); + + // footstep events / legs animations + PM_Footsteps(); + + // entering / leaving water splashes + PM_WaterEvents(); + + // snap some parts of playerstate to save network bandwidth + trap_SnapVector( pm->ps->velocity );*/ +} + +void Ext_UpdateViewAngles(playerMove* const pm) +{ + playerMove::playerStruct* const ps = &(pm->ps); + playerMove::playercmd* const cmd = &(pm->cmd); + PM_UpdateViewAngles(ps, cmd); +} + +void Pmove (playerMove* const pmove) +{ + // warning: unused variable ‘fmove’ + //int fmove = pmove->cmd.forwardmove; + + pm = pmove; + + int finalTime; + + finalTime = pmove->cmd.serverTime; + + pmove->ps.commandTime = 40; + + if ( finalTime < pmove->ps.commandTime ) + return; // should not happen + + if ( finalTime > pmove->ps.commandTime + 1000 ) + pmove->ps.commandTime = finalTime - 1000; + + pmove->ps.pmove_framecount = (pmove->ps.pmove_framecount + 1) & ( (1 << PS_PMOVEFRAMECOUNTBITS) - 1); + + // chop the move up if it is too long, to prevent framerate + // dependent behavior + while ( pmove->ps.commandTime != finalTime ) + { + int msec; + + msec = finalTime - pmove->ps.commandTime; + + if ( pmove->pmove_fixed ) + { + if ( msec > pmove->pmove_msec ) + msec = pmove->pmove_msec; + } + else + { + if ( msec > 66 ) + msec = 66; + } + + pmove->cmd.serverTime = pmove->ps.commandTime + msec; + + if (pmove->isInterior) + { + PmoveSingle( pmove ); + } + else + { + PmoveSingle( pmove ); + /* + std::map::const_iterator it = ExtCellLookup.find(PositionToCell(pmove->ps.origin) ); + if (it != ExtCellLookup.end() ) + { + pmove->traceObj->incellptr = it->second; + }*/ + } + + //if ( pmove->ps->pm_flags & PMF_JUMP_HELD ) + //pmove->cmd.upmove = 20; + } + + //pmove->ps.last_compute_time = GetTimeQPC(); + //pmove->ps.lerp_multiplier = (pmove->ps.origin - pmove->ps.lastframe_origin);// * (1.000 / 31.0); + + //PM_CheckStuck(); + +} + + diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h new file mode 100644 index 000000000..e46eb9d2e --- /dev/null +++ b/libs/openengine/bullet/pmove.h @@ -0,0 +1,200 @@ +#ifndef OENGINE_BULLET_PMOVE_H +#define OENGINE_BULLET_PMOVE_H +/* +This source file is a *modified* version of various header files from the Quake 3 Arena source code, +which was released under the GNU GPL (v2) in 2005. +Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc. +*/ + +#include +#include +#include +#include "trace.h" +#include "physic.hpp" + + +//#include "GameMath.h" +//#include "GameTime.h" + +// Forwards-declare it! + +/*#ifndef COMPILING_PMOVE +#include "Scene.h" +extern SceneInstance* global_lastscene; +#endif*/ + +static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); + +#define MAX_CLIP_PLANES 5 +#define OVERCLIP 1.001f +//#define STEPSIZE 18 // 18 is way too much +#define STEPSIZE (18 / 2) +#ifndef M_PI + #define M_PI 3.14159265358979323846f +#endif +#define YAW 0 +#define PITCH /*1*/2 +#define ROLL /*2*/1 +#define SHORT2ANGLE(x) ( (x) * (360.0f / 65536.0f) ) +#define ANGLE2SHORT(x) ( (const short)( (x) / (360.0f / 65536.0f) ) ) +#define GENTITYNUM_BITS 10 // don't need to send any more +#define MAX_GENTITIES (1 << GENTITYNUM_BITS) +#define ENTITYNUM_NONE (MAX_GENTITIES - 1) +#define ENTITYNUM_WORLD (MAX_GENTITIES - 2) +#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes +#define JUMP_VELOCITY (270) +#define PS_PMOVEFRAMECOUNTBITS 6 +#define MINS_Z -24 +#define DEFAULT_VIEWHEIGHT 26 +#define CROUCH_VIEWHEIGHT 12 +#define DEAD_VIEWHEIGHT (-16) +#define CONTENTS_SOLID 1 // an eye is never valid in a solid +#define CONTENTS_LAVA 8 +#define CONTENTS_SLIME 16 +#define CONTENTS_WATER 32 +#define CONTENTS_FOG 64 +static const float pm_accelerate = 10.0f; +static const float pm_stopspeed = 100.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; +static const float pm_swimScale = 0.50f; +static const float pm_duckScale = 0.25f; +static const float pm_flyaccelerate = 8.0f; +static const float pm_wateraccelerate = 4.0f; + +enum pmtype_t +{ + PM_NORMAL, // can accelerate and turn + PM_NOCLIP, // noclip movement + PM_SPECTATOR, // still run into walls + PM_DEAD, // no acceleration or turning, but free falling + PM_FREEZE, // stuck in place with no control + PM_INTERMISSION, // no movement or status bar + PM_SPINTERMISSION // no movement or status bar +}; + +enum waterlevel_t +{ + WL_DRYLAND = 0, + WL_ANKLE, + WL_WAIST, + WL_UNDERWATER +}; + + +//#include "bprintf.h" + +struct playerMove +{ + struct playerStruct + { + playerStruct() : gravity(800.0f), speed(480.0f), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1) + { + origin = Ogre::Vector3(733.164f,900.0f, 839.432f); + velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f); + + viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f); + + delta_angles[0] = delta_angles[1] = delta_angles[2] = 0; + + lastframe_origin.x = lastframe_origin.y = lastframe_origin.z = 0; + lerp_multiplier.x = lerp_multiplier.y = lerp_multiplier.z = 0; + } + + inline void SpeedUp(void) + { + //printf("speed up to: %f\n", speed); + speed *= 1.25f; + } + + inline void SpeedDown(void) + { + //printf("speed down to %f\n", speed); + speed /= 1.25f; + } + + Ogre::Vector3 velocity; + Ogre::Vector3 origin; + bool bSnap; + bool snappingImplemented; + int counter; + float gravity; // default = 800 + float speed; // default = 320 + + int commandTime; // the time at which this command was issued (in milliseconds) + + int pm_time; + + Ogre::Vector3 viewangles; + + int groundEntityNum; + + int pmove_framecount; + + int watertype; + waterlevel_t waterlevel; + + signed short delta_angles[3]; + + pmtype_t move_type; + + float last_compute_time; + Ogre::Vector3 lastframe_origin; + Ogre::Vector3 lerp_multiplier; + } ps; + + struct playercmd + { + enum CMDstateChange + { + NO_CHANGE, + KEYDOWN, + KEYUP + }; + + playercmd() : forwardmove(0), rightmove(0), upmove(0), serverTime(50), ducking(false), + activating(false), lastActivatingState(false), procActivating(NO_CHANGE), + dropping(false), lastDroppingState(false), procDropping(NO_CHANGE) + { + angles[0] = angles[1] = angles[2] = 0; + } + + int serverTime; + + short angles[3]; + + signed char forwardmove; + signed char rightmove; + signed char upmove; + + bool ducking; + bool activating; // if the user is holding down the activate button + bool dropping; // if the user is dropping an item + + bool lastActivatingState; + bool lastDroppingState; + + CMDstateChange procActivating; + CMDstateChange procDropping; + } cmd; + + playerMove() : msec(50), pmove_fixed(false), pmove_msec(50), waterHeight(0), isInterior(true), hasWater(false) + { + } + + int msec; + int pmove_msec; + bool pmove_fixed; + int waterHeight; + bool hasWater; + bool isInterior; + //Object* traceObj; + OEngine::Physic::PhysicEngine* mEngine; +}; + +void Pmove (playerMove* const pmove); +void Ext_UpdateViewAngles(playerMove* const pm); +void AngleVectors( const Ogre::Vector3& angles, Ogre::Vector3* const forward, Ogre::Vector3* const right, Ogre::Vector3* const up) ; +#endif diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp new file mode 100644 index 000000000..2d18aaa4d --- /dev/null +++ b/libs/openengine/bullet/trace.cpp @@ -0,0 +1,190 @@ + +#include "trace.h" + + + +#include + + + + + + + +void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object +{ + + //if (!traceobj) + // return; + + //if (!traceobj->incellptr) + // return; + + const Ogre::Vector3 rayDir = end - start; + + // Nudge starting point backwards + //const Position3D nudgestart = start + (rayDir * -0.1f); // by 10% (isn't that too much?) + //const Position3D nudgestart = start; + + NewPhysTraceResults out; + //std::cout << "Starting trace\n"; + //Ogre::Vector3 startReplace = Ogre::Vector3(650,950, 45); + //Ogre::Vector3 endReplace = startReplace; + //endReplace.z -= .25; + + const bool hasHit = NewPhysicsTrace(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0, rotation), isInterior, enginePass); + + if (out.fraction < 0.001f) + results->startsolid = true; + else + results->startsolid = false; + + + //results->allsolid = out.startSolid; + + // If outside and underground, we're solid + /*if (isInterior) + { + const Ogre::Vector3 height = GetGroundPosition(start, CellCoords(traceCell->data->gridX, traceCell->data->gridY) ); + if (start.yPos - height.yPos < (-2.0f * BBHalfExtents.yPos) ) + { + results->allsolid = true; + } + else + results->allsolid = false; + }*/ + + // If inside and out of the tree, we're solid + //else + //{ + results->allsolid = out.startSolid; + //std::cout << "allsolid" << results->allsolid << "\n"; + //} + + if (!hasHit) + { + results->endpos = end; + results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); + results->entityNum = ENTITYNUM_NONE; + results->fraction = 1.0f; + } + else + { + results->fraction = out.fraction; + results->planenormal = out.hitNormal; + results->endpos = rayDir * results->fraction + start; + results->entityNum = ENTITYNUM_WORLD; + /*bprintf("Start: (%f, %f, %f) End: (%f, %f, %f) TraceDir: (%f, %f, %f) HitNormal: (%f, %f, %f) Fraction: %f Hitpos: (%f, %f, %f) CompensatedHitpos: (%f, %f, %f)\n", + start.xPos, start.yPos, start.zPos, + end.xPos, end.yPos, end.zPos, + rayDir.xPos, rayDir.yPos, rayDir.zPos, + results->planenormal.xPos, results->planenormal.yPos, results->planenormal.zPos, results->fraction, + out.endPos.xPos, out.endPos.yPos, out.endPos.zPos, + results->endpos.xPos, results->endpos.yPos, results->endpos.zPos);*/ + } +} + + + +template +const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, + const Ogre::Vector3& BBHalfExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) +{ + //if (!traceobj->incellptr) + // return false; + //if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex()) + // std::cout << "It's convex\n"; + + + + const btVector3 btstart(start.x, start.y, start.z); + const btVector3 btend(end.x, end.y, end.z); + const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z + + const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); + const btTransform from(btrot, btstart); + const btTransform to(btrot, btend); + + // warning: unused variable ... + /* + float x = from.getOrigin().getX(); + float y = from.getOrigin().getY(); + float z = from.getOrigin().getZ(); + float x2 = to.getOrigin().getX(); + float y2 = to.getOrigin().getY(); + float z2 = to.getOrigin().getZ(); + */ + + //std::cout << "BtFrom: " << x << "," << y << "," << z << "\n"; + //std::cout << "BtTo: " << x2 << "," << y2 << "," << z2 << "\n"; + //std::cout << "BtTo: " << to.getOrigin().getX() << "," << to.getOrigin().getY() << "," << to.getOrigin().getZ() << "\n"; + + + btCollisionWorld::ClosestConvexResultCallback + newTraceCallback(btstart, btend); + + newTraceCallback.m_collisionFilterMask = (traceType == collisionWorldTrace) ? Only_Collision : Only_Pickup; + + + enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); + //newTraceCallback. + + + //std::cout << "NUM: " << enginePass->dynamicsWorld->getNumCollisionObjects() << "\n"; + + // Copy the hit data over to our trace results struct: + out->fraction = newTraceCallback.m_closestHitFraction; + + Ogre::Vector3& outhitnormal = out->hitNormal; + const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; + + outhitnormal.x = tracehitnormal.x(); + outhitnormal.y = tracehitnormal.y(); + outhitnormal.z = tracehitnormal.z(); + + Ogre::Vector3& outhitpos = out->endPos; + const btVector3& tracehitpos = newTraceCallback.m_hitPointWorld; + + outhitpos.x = tracehitpos.x(); + outhitpos.y = tracehitpos.y(); + outhitpos.z= tracehitpos.z(); + + // StartSolid test: + { + out->startSolid = false; + //btCollisionObject collision; + //collision.setCollisionShape(const_cast(&newshape) ); + + //CustomContactCallback crb; + + //world.world->contactTest(&collision, crb); + //out->startSolid = crb.hit; + + // If outside and underground, we're solid + if (!isInterior) //Check if we are interior + { + } + + // If inside and out of the tree, we're solid + else + { + btVector3 aabbMin, aabbMax; + enginePass->broadphase->getBroadphaseAabb(aabbMin, aabbMax); + //std::cout << "AABBMIN" << aabbMin.getX() <<"," <startSolid = true; + } + } + } + + const bool hasHit = newTraceCallback.hasHit(); + + + + + return hasHit; +} diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h new file mode 100644 index 000000000..d446b6854 --- /dev/null +++ b/libs/openengine/bullet/trace.h @@ -0,0 +1,62 @@ +#ifndef OENGINE_BULLET_TRACE_H +#define OENGINE_BULLET_TRACE_H + + +#include +#include +#include +//#include +#include +#include + + + +enum traceWorldType +{ + collisionWorldTrace = 1, + pickWorldTrace = 2, + bothWorldTrace = collisionWorldTrace | pickWorldTrace +}; + +enum collaborativePhysicsType +{ + No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass) + Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics) + Only_Pickup = 2, // This object only has pickup physics but no collision physics (example: items dropped on the ground) + Both_Physics = 3 // This object has both kinds of physics (example: activators) +}; + +struct NewPhysTraceResults +{ + Ogre::Vector3 endPos; + Ogre::Vector3 hitNormal; + float fraction; + bool startSolid; + //const Object* hitObj; +}; +struct traceResults +{ + Ogre::Vector3 endpos; + Ogre::Vector3 planenormal; + + float fraction; + + int surfaceFlags; + int contents; + int entityNum; + + bool allsolid; + bool startsolid; +}; + + + +template +const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); +//template const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); +//template const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); + +void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); + + +#endif diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index 05a23e8ae..bda8935af 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -85,7 +85,7 @@ namespace GUI // adjust the size of the window caption so that all text is visible // NOTE: this assumes that mMainWidget is of type Window. MyGUI::TextBox* box = static_cast(mMainWidget)->getCaptionWidget(); - box->setSize(box->getTextSize().width + 48, box->getSize().height); + box->setSize(box->getTextSize().width + 24, box->getSize().height); // in order to trigger alignment updates, we need to update the parent // mygui doesn't provide a proper way of doing this, so we are just changing size @@ -115,6 +115,13 @@ namespace GUI static_cast(pt)->setCaption(caption); } + void setState(const std::string& widget, const std::string& state) + { + MyGUI::Widget* pt; + getWidget(pt, widget); + pt->_setWidgetState(state); + } + void setTextColor(const std::string& name, float r, float g, float b) { MyGUI::Widget* pt; @@ -131,6 +138,13 @@ namespace GUI pt->setImageTexture(imgName); } + void adjustButtonSize(MyGUI::Button* button) + { + // adjust size of button to fit its text + MyGUI::IntSize size = button->getTextSize(); + button->setSize(size.width + 24, button->getSize().height); + } + protected: MyGUI::Widget* mMainWidget; diff --git a/libs/openengine/ogre/imagerotate.cpp b/libs/openengine/ogre/imagerotate.cpp index 1147559d6..11fd5eea6 100644 --- a/libs/openengine/ogre/imagerotate.cpp +++ b/libs/openengine/ogre/imagerotate.cpp @@ -54,7 +54,7 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest TEX_TYPE_2D, width, height, 0, - PF_A8R8G8B8, + PF_FLOAT16_RGBA, TU_RENDERTARGET); RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget(); @@ -63,7 +63,6 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); vp->setBackgroundColour(ColourValue(0,0,0,0)); - vp->setClearEveryFrame(true, FBT_DEPTH); rtt->update(); diff --git a/readme.txt b/readme.txt index e1c24ab52..53f4a4c59 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.13.0 +Version: 0.14.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org @@ -64,8 +64,6 @@ Allowed options: --start arg (=Beshara) set initial cell --master arg master file(s) --plugin arg plugin file(s) - --fps [=arg(=1)] (=0) fps counter detail (0 = off, 1 = fps counter - , 2 = full detail) --anim-verbose [=arg(=1)] (=0) output animation indices files --debug [=arg(=1)] (=0) debug mode --nosound [=arg(=1)] (=0) disable all sounds @@ -89,7 +87,7 @@ Allowed options: win1252 - Western European (Latin) alphabet, used by default - --report-focus [=arg(=1)] (=0) write name of focussed object to cout + --fallback arg fallback values CREDITS @@ -134,6 +132,36 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil CHANGELOG +0.14.0 + +Bug #1: Meshes rendered with wrong orientation +Bug #6/Task #220: Picking up small objects doesn't always work +Bug #127: tcg doesn't work +Bug #178: Compablity problems with Ogre 1.8.0 RC 1 +Bug #211: Wireframe mode (toggleWireframe command) should not apply to Console & other UI +Bug #227: Terrain crashes when moving away from predefined cells +Bug #229: On OS X Launcher cannot launch game if path to binary contains spaces +Bug #235: TGA texture loading problem +Bug #246: wireframe mode does not work in water +Feature #8/#232: Water Rendering +Feature #13: Terrain Rendering +Feature #37: Render Path Grid +Feature #66: Factions +Feature #77: Local Map +Feature #78: Compass/Mini-Map +Feature #97: Render Clothing/Armour +Feature #121: Window Pinning +Feature #205: Auto equip +Feature #217: Contiainer should track changes to its content +Feature #221: NPC Dialogue Window Enhancements +Feature #233: Game settings manager +Feature #240: Spell List and selected spell (no GUI yet) +Feature #243: Draw State +Task #113: Morrowind.ini Importer +Task #215: Refactor the sound code +Task #216: Update MyGUI + + 0.13.0 Bug #145: Fixed sound problems after cell change