diff --git a/CMakeLists.txt b/CMakeLists.txt index ca747f9a56..6dbd27a68c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,14 +255,8 @@ if (APPLE) "${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}) + if (${CMAKE_BUILD_TYPE} MATCHES "Release" OR + ${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo") set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL}) else() set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG}) @@ -278,8 +272,7 @@ endif (APPLE) # Compiler settings if (CMAKE_COMPILER_IS_GNUCC) - #add_definitions (-Wall -Werror) - add_definitions (-Wall) + add_definitions (-Wall -Wextra -Wno-unused-parameter -Wno-unused-but-set-parameter -Wno-reorder) endif (CMAKE_COMPILER_IS_GNUCC) if(DPKG_PROGRAM) @@ -418,6 +411,45 @@ if (WIN32) set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE") + + # Play a bit with the warning levels + + set(WARNINGS "/Wall") # Since windows can only disable specific warnings, not enable them + + set(WARNINGS_DISABLE + # Warnings that aren't enabled normally and don't need to be enabled + # They're unneeded and sometimes completely retarded warnings that /Wall enables + # Not going to bother commenting them as they tend to warn on every standard library files + 4061 4263 4264 4266 4350 4514 4548 4571 4610 4619 4623 4625 4626 4628 4640 4668 4710 4711 4820 4826 4917 4946 + + # Warnings that are thrown on standard libraries and not OpenMW + 4347 # Non-template function with same name and parameter count as template function + 4365 # Variable signed/unsigned mismatch + 4510 4512 # Unable to generate copy constructor/assignment operator as it's not public in the base + 4706 # Assignment in conditional expression + 4738 # Storing 32-bit float result in memory, possible loss of performance + 4986 # Undocumented warning that occurs in the crtdbg.h file + 4996 # Function was declared deprecated + + # OpenMW specific warnings + 4099 # Type mismatch, declared class or struct is defined with other type + 4100 # Unreferenced formal parameter (-Wunused-parameter) + 4127 # Conditional expression is constant + 4242 # Storing value in a variable of a smaller type, possible loss of data + 4244 # Storing value of one type in variable of another (size_t in int, for example) + 4305 # Truncating value (double to float, for example) + 4309 # Variable overflow, trying to store 128 in a signed char for example + 4355 # Using 'this' in member initialization list + 4701 # Potentially uninitialized local variable used + ) + + foreach(d ${WARNINGS_DISABLE}) + set(WARNINGS "${WARNINGS} /wd${d}") + endforeach(d) + + set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS}) + set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) + set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif(MSVC) # Same for MinGW diff --git a/README_Mac.md b/README_Mac.md index 39382e0c9d..dc39183680 100644 --- a/README_Mac.md +++ b/README_Mac.md @@ -1,80 +1,79 @@ -NOTE: This README is for ardekantur's Mac branch of OpenMW. A README -for the main branch has yet to be written. If you want to submit one, -please send me a message! +#Getting OpenMW Working on OS X -OpenMW -====== +## Initial setup +First of all, clone OpenMW repo. -From the [official website][]: + $ git clone github.com/zinnschlag/openmw -> OpenMW is an attempt to reimplement the popular role playing game - Morrowind. It aims to be a fully playable, open source - implementation of the game. You must own Morrowind to use OpenMW. +Or use your github url if you forked. +About dependencies: I prefer not to install them globally (i. e. in /usr/local/), so I'm installing them in directory in my home directory. If OpenMW sources is in $HOME/path/openmw, I'm using $HOME/path/libs/root as prefix for boost and other libs. -About This Project ------------------- +It's useful to create env var for lib install prefix: + + $ export OMW_LIB_PREFIX=$HOME/path/libs/root` -This specific repository is a branch of OpenMW intended to keep pace -with development of the project in order to provide a Mac build for -interested parties to contribute. This is not an official, sanctioned -branch of the OpenMW project. I will only be able to answer specific -questions about getting this project running on Mac OS X, **no other -platform**. I will not even be able to guarantee my changes maintain -backwards compatibility against builds in other operating systems. You -have been warned. +Most of libs can be installed from [Homebrew][homebrew]. Only mpg123 needs to be installed from source (due to lack of universal compilation support). I think that some of libs can be installed from MacPorts or Fink too. +As OpenMW currently only supports i386 architecture on OS X, denendencies also should support it. Set some env vars in current terminal: -Getting OpenMW Working ----------------------- - -1. Clone this repository. -2. Note about libs: I prefer not to install them globally (i. e. in /usr/local/), so I installing them in directory in my home directory. If OpenMW sources is in $HOME/path/openmw, I'm using $HOME/path/libs/root as prefix for boost and other libs. - It's useful to create env var for lib install prefix: - $ export OMW_LIB_PREFIX=$HOME/path/libs/root - -3. First of all, set for current terminal some env vars: $ export CFLAGS="-arch i386" $ export CXXFLAGS="-arch i386" $ export LDFLAGS="-arch i386" - All libs will build with correct architecture. - If you close your terminal, you should set env vars again before pcoceeding to next steps! -4. Download [boost][] (tested with 1.45) and install it with the following command: +If you close your terminal, you should set env vars again before pcoceeding to next steps! + +## Boost +Download [boost][boost] and install it with the following command: $ cd /path/to/boost/source $ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX $ ./bjam --build-dir=build --layout=versioned \ --toolset=darwin architecture=x86 address-model=32 \ --link-shared,static --prefix=$OMW_LIB_PREFIX install + + +Alternatively you can install boost with homebrew: + $ brew install boost --universal -5. Download [Ogre][] SDK (tested with 1.7.2), unpack it and move -`lib/Release/Ogre.framework` into `Library/Frameworks`. +I think MacPorts also should support universal build for boost. -6. Download [OIS][] and use the XCode project provided in - `ois/Mac/XCode-2.2`. Be sure to set your build architecture to - `i386` and your SDK platform to either 10.5 or 10.6. Once it - builds, move `ois/Mac/XCode-2.2/build/Debug/OIS.framework` to - `/Library/Frameworks`. +## Ogre +Download [Ogre][] SDK (tested with 1.7.3), unpack it somewhere and move +`lib/Release/Ogre.framework` into `/Library/Frameworks`. + +## OIS +Download patched [OIS][] and use the XCode project provided. Be sure to set your build architecture to + `i386`. Once it built, locate built OIS.framework with Xcode and move it to `/Library/Frameworks`. + +## mpg123 +Download [MPG 123][mpg123] and build it: -7. Download [mpg123][] and build it: $ cd /path/to/mpg123/source $ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \ --disable-dependency-tracking \ --with-optimization=4 \ - --with-audio=coreaudio \ - --with-default-audio=coreaudio \ + --with-audio=dummy \ + --with-default-audio=dummy \ --with-cpu=sse_alone \ $ make install -8. Download [libsndfile][] and build it: +## libsndfile +Download [libsndfile][] and build it: + $ cd /path/to/libsndfile/source $ ./configure --prefix=$OMW_LIB_PREFIX \ --disable-dependency-tracking $ make install -9. Download [Bullet][] and build it: +or install with homebrew: + + $ brew install libsndfile --universal + +## Bullet +Download [Bullet][] and build it: + $ cd /path/to/bullet/source $ mkdir build $ cd build @@ -87,12 +86,25 @@ Getting OpenMW Working -G"Unix Makefiles" ../ $ make install -10. Generate the Makefile for OpenMW as follows and build OpenMW: +or install with homebrew: + + $ brew install bullet --HEAD --universal + +I prefer head because 2.79 has some issue which causes OpenMW to lag. Also you can edit formula and install 2.77, which is stable and haven't mentioned issue. + +## Qt +Install [Qt][qt]. Qt SDK distributed by Nokia is not an option because it's 64 bit only, and OpenMW currently doesn't build for 64 bit on OS X. I'm installing it from Homebrew: + + $ brew install qt --universal + +## Run CMake +Generate the Makefile for OpenMW as follows and build OpenMW: + $ mkdir /path/to/openmw/build/dir $ cd /path/to/open/build/dir $ cmake \ -D CMAKE_OSX_ARCHITECTURES=i386 \ - -D OGRESDK=/path/to/ogre/sdk \ + -D OGRE_SDK=/path/to/ogre/sdk \ -D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \ -D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \ -D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \ @@ -106,27 +118,43 @@ Getting OpenMW Working -D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \ -G "Unix Makefiles" /path/to/openmw/source/dir $ make - You can use -G"Xcode" if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles" - if you prefer Eclipse. You also can specify -D CMAKE_BUILD_TYPE=Debug for debug - build. + +You can use `-G"Xcode"` if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles" +if you prefer Eclipse. You also can specify `-D CMAKE_BUILD_TYPE=Debug` for debug +build. As for CMake 2.8.7 and Xcode 4.3, Xcode generator is broken. Sadly Eclipse CDT also cannot import generated project at least on my machine. -11. Copy your Morrowind `Data Files` directory into the OpenMW build dir - with the name `data` or create symlink: - $ ln -s /path/to/morrowind/data/files /path/to/openmw/build/dir/data +If all libs installed via homebrew (excluding mpg123), then command would be even simplier: + + $ cmake \ + -D CMAKE_OSX_ARCHITECTURES="i386" \ + -D OGRE_SDK=/path/to/ogre/sdk \ + -D MPG123_LIBRARY=$OMW_LIB_PREFIX/lib/libmpg123.a \ + -D MPG123_INCLUDE_DIR=$OMW_LIB_PREFIX/include \ + -G "Unix Makefiles" /path/to/openmw/source/dir + $ make + +Note for users with recent Xcode versions: you must explicitly specify what set of compilers do you use! If not, gcc will be used for C and Clang for C++. Just add this two -D's to command: `-D CMAKE_C_COMPILER=/usr/bin/clang` and `-D CMAKE_CXX_COMPILER=/usr/bin/clang` + +Note for Xcode 4.3 users: you should specify full path to used SDK, because current CMake (2.8.7) couldn't find SDKs inside Xcode app bundle: + + -D CMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk" + +# Run +From your build directory run: -12. From your build directory run: $ OpenMW.app/Contents/MacOS/openmw - or: +or: + $ open OpenMW.app - Enjoy! - - +Enjoy! +[homebrew]: https://github.com/mxcl/homebrew [boost]: http://www.boost.org [Ogre]: http://www.ogre3d.org [Bullet]: http://bulletphysics.org -[OIS]: http://wgois.sf.net +[OIS]: https://github.com/corristo/ois-fork [mpg123]: http://www.mpg123.de [libsndfile]: http://www.mega-nerd.com/libsndfile [official website]: http://openmw.com [Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/ +[qt]: http://qt.nokia.com/ \ No newline at end of file diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index da7ff86964..e95fb572f3 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -53,6 +56,8 @@ namespace MWClass boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -71,4 +76,14 @@ namespace MWClass registerClass (typeid (ESM::Apparatus).name(), instance); } + + std::string Apparatus::getUpSoundId (const MWWorld::Ptr& ptr) const + { + return std::string("Item Apparatus Up"); + } + + std::string Apparatus::getDownSoundId (const MWWorld::Ptr& ptr) const + { + return std::string("Item Apparatus Down"); + } } diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 86223cf604..c0849e1fe2 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 2dc8614307..e1c2734f0e 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -9,12 +9,15 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" + #include "../mwworld/inventorystore.hpp" #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -57,6 +60,8 @@ namespace MWClass boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -116,7 +121,7 @@ namespace MWClass return std::make_pair (slots, false); } - int Armor::getEuqipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + int Armor::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const { ESMS::LiveCellRef *ref = ptr.get(); @@ -142,13 +147,13 @@ namespace MWClass if (typeGmst.empty()) return -1; - float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->f; + float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->i; - if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f<= + if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f>= ref->base->data.weight) return ESM::Skill::LightArmor; - if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f<= + if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f>= ref->base->data.weight) return ESM::Skill::MediumArmor; @@ -161,4 +166,26 @@ namespace MWClass registerClass (typeid (ESM::Armor).name(), instance); } + + std::string Armor::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + int es = getEquipmentSkill(ptr, environment); + if (es == ESM::Skill::LightArmor) + return std::string("Item Armor Light Up"); + else if (es == ESM::Skill::MediumArmor) + return std::string("Item Armor Medium Up"); + else + return std::string("Item Armor Heavy Up"); + } + + std::string Armor::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + int es = getEquipmentSkill(ptr, environment); + if (es == ESM::Skill::LightArmor) + return std::string("Item Armor Light Down"); + else if (es == ESM::Skill::MediumArmor) + return std::string("Item Armor Medium Down"); + else + return std::string("Item Armor Heavy Down"); + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 6c78a535ab..2b66ff8280 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -35,12 +35,18 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr, + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 576e521eec..0a81ebafb7 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -55,6 +58,8 @@ namespace MWClass { // TODO implement reading + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -73,4 +78,14 @@ namespace MWClass registerClass (typeid (ESM::Book).name(), instance); } + + std::string Book::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Book Up"); + } + + std::string Book::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Book Down"); + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 12dc27bb2e..ccbbfb4b2d 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 9af59937a7..4fe19ada40 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -7,10 +7,13 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -54,6 +57,8 @@ namespace MWClass boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -106,7 +111,7 @@ namespace MWClass return std::make_pair (slots, false); } - int Clothing::getEuqipmentSkill (const MWWorld::Ptr& ptr, + int Clothing::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const { ESMS::LiveCellRef *ref = @@ -124,4 +129,28 @@ namespace MWClass registerClass (typeid (ESM::Clothing).name(), instance); } + + std::string Clothing::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (ref->base->data.type == 8) + { + return std::string("Item Ring Up"); + } + return std::string("Item Clothes Up"); + } + + std::string Clothing::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (ref->base->data.type == 8) + { + return std::string("Item Ring Down"); + } + return std::string("Item Clothes Down"); + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 448c73a738..171b062461 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -29,12 +29,18 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr, + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index c586069962..c58a25c03e 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -85,7 +85,7 @@ namespace MWClass { // TODO check for key std::cout << "Locked container" << std::endl; - environment.mSoundManager->playSound(lockedSound, 1.0, 1.0); + environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false); return boost::shared_ptr (new MWWorld::NullAction); } else @@ -100,7 +100,7 @@ namespace MWClass { // Trap activation goes here std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0); + environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0, false); ptr.getCellRef().trap = ""; return boost::shared_ptr (new MWWorld::NullAction); } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index bd7af9597a..5654dff698 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -73,7 +73,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->playSound(lockedSound, 1.0, 1.0); + environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false); return boost::shared_ptr (new MWWorld::NullAction); } @@ -81,7 +81,7 @@ namespace MWClass { // Trap activation std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; - environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0); + environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0, false); ptr.getCellRef().trap = ""; return boost::shared_ptr (new MWWorld::NullAction); } @@ -92,6 +92,7 @@ namespace MWClass if (environment.mWorld->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); return boost::shared_ptr ( new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); @@ -109,7 +110,7 @@ namespace MWClass // TODO return action for rotating the door // This is a little pointless, but helps with testing - environment.mSoundManager->playSound(openSound, 1.0, 1.0); + environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0, false); return boost::shared_ptr (new MWWorld::NullAction); } } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index d00e4592da..1a7edf6325 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -51,6 +54,8 @@ namespace MWClass boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -69,4 +74,14 @@ namespace MWClass registerClass (typeid (ESM::Ingredient).name(), instance); } + + std::string Ingredient::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Ingredient Up"); + } + + std::string Ingredient::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Ingredient Down"); + } } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 92d2c4eefe..9463dcf8d7 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index fc3c7a6a94..e2e63a89bb 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -83,6 +83,8 @@ 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, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -114,4 +116,14 @@ namespace MWClass registerClass (typeid (ESM::Light).name(), instance); } + + std::string Light::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Misc Up"); + } + + std::string Light::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Misc Down"); + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 179531808b..46a4d60ba4 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -35,6 +35,12 @@ namespace MWClass /// stay stacked when equipped? static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 5fc6ea9c7d..3dda2f4af0 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -7,10 +7,13 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -55,6 +58,8 @@ namespace MWClass boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -82,4 +87,14 @@ namespace MWClass registerClass (typeid (ESM::Tool).name(), instance); } + + std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Lockpick Up"); + } + + std::string Lockpick::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Lockpick Down"); + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 5465e52155..0c9189c548 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -30,6 +30,12 @@ namespace MWClass /// stay stacked when equipped? static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 8dde84be9b..864fc1e382 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -53,6 +56,8 @@ namespace MWClass boost::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -71,4 +76,28 @@ namespace MWClass registerClass (typeid (ESM::Miscellaneous).name(), instance); } + + std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (ref->base->name =="Gold") + { + 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 + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (ref->base->name =="Gold") + { + return std::string("Item Gold Down"); + } + return std::string("Item Misc Down"); + } } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index de01a64f4b..b07964f990 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index c57c18fd1f..4ab3745900 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -53,6 +56,8 @@ namespace MWClass boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -71,4 +76,14 @@ namespace MWClass registerClass (typeid (ESM::Potion).name(), instance); } + + std::string Potion::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Potion Up"); + } + + std::string Potion::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Potion Down"); + } } diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index fd78bba539..be9e713fba 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index d70cda83d2..4b4d79a73e 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -7,10 +7,13 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -54,6 +57,8 @@ namespace MWClass boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -81,4 +86,14 @@ namespace MWClass registerClass (typeid (ESM::Probe).name(), instance); } + + std::string Probe::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Probe Up"); + } + + std::string Probe::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Probe Down"); + } } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 2aadaa22ec..1507d65aab 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -30,6 +30,12 @@ namespace MWClass /// stay stacked when equipped? static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index f831b6b503..758bf40797 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -53,6 +56,8 @@ namespace MWClass boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -71,4 +76,14 @@ namespace MWClass registerClass (typeid (ESM::Repair).name(), instance); } + + std::string Repair::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Repair Up"); + } + + std::string Repair::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + return std::string("Item Repair Down"); + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index a5864ab35a..17b606f4cb 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -26,6 +26,12 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index e4cb4582b2..20db0cf38f 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -7,10 +7,13 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/environment.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwrender/objects.hpp" +#include "../mwsound/soundmanager.hpp" + namespace MWClass { void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -54,6 +57,8 @@ namespace MWClass boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { + environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); + return boost::shared_ptr ( new MWWorld::ActionTake (ptr)); } @@ -103,7 +108,7 @@ namespace MWClass return std::make_pair (slots, stack); } - int Weapon::getEuqipmentSkill (const MWWorld::Ptr& ptr, + int Weapon::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const { ESMS::LiveCellRef *ref = @@ -140,4 +145,96 @@ namespace MWClass registerClass (typeid (ESM::Weapon).name(), instance); } + + std::string Weapon::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + int type = ref->base->data.type; + // Ammo + if (type == 12 || type == 13) + { + return std::string("Item Ammo Up"); + } + // Bow + if (type == 9) + { + return std::string("Item Weapon Bow Up"); + } + // Crossbow + if (type == 10) + { + return std::string("Item Weapon Crossbow Up"); + } + // Longblades, One hand and Two + if (type == 1 || type == 2) + { + return std::string("Item Weapon Longblade Up"); + } + // Shortblade and thrown weapons + // thrown weapons may not be entirely correct + if (type == 0 || type == 11) + { + return std::string("Item Weapon Shortblade Up"); + } + // Spear + if (type == 6) + { + return std::string("Item Weapon Spear Up"); + } + // Blunts and Axes + if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8) + { + return std::string("Item Weapon Blunt Up"); + } + + return std::string("Item Misc Up"); + } + + std::string Weapon::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + int type = ref->base->data.type; + // Ammo + if (type == 12 || type == 13) + { + return std::string("Item Ammo Down"); + } + // Bow + if (type == 9) + { + return std::string("Item Weapon Bow Down"); + } + // Crossbow + if (type == 10) + { + return std::string("Item Weapon Crossbow Down"); + } + // Longblades, One hand and Two + if (type == 1 || type == 2) + { + return std::string("Item Weapon Longblade Down"); + } + // Shortblade and thrown weapons + // thrown weapons may not be entirely correct + if (type == 0 || type == 11) + { + return std::string("Item Weapon Shortblade Down"); + } + // Spear + if (type == 6) + { + return std::string("Item Weapon Spear Down"); + } + // Blunts and Axes + if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8) + { + return std::string("Item Weapon Blunt Down"); + } + + return std::string("Item Misc Down"); + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 2b6dfb5a8f..f863c0bfe2 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -35,12 +35,18 @@ namespace MWClass ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr, + virtual int getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. static void registerSelf(); + + virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the pick up sound Id + + virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; + ///< Return the put down sound Id }; } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 0e2e692d3f..3fd6e7892e 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -50,7 +50,7 @@ namespace MWGui return isGood(); } - catch (const Compiler::SourceException& error) + catch (const Compiler::SourceException&) { // error has already been reported via error handler } @@ -342,7 +342,7 @@ namespace MWGui if( ( matches.front().find(' ') != string::npos ) ) { if( !has_front_quote ) output.append(string("\"")); - return output.append(matches.front() + string("\" ")); + return output.append(matches.front() + string("\" ")); } else if( has_front_quote ) { return output.append(matches.front() + string("\" ")); @@ -361,7 +361,7 @@ namespace MWGui /* Append the longest match to the end of the output string*/ output.append(matches.front().substr( 0, i)); return output; - } + } } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 9df987dc18..7b0d7015c0 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -111,7 +111,6 @@ namespace MWRender{ Nif::NiTriShapeCopy& copy = *allshapesiter; std::vector* allvertices = ©.vertices; - std::vector* allnormals = ©.normals; @@ -182,7 +181,6 @@ namespace MWRender{ std::vector inds = iter->second; int verIndex = iter->first; Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; - Ogre::Vector3 currentNormal = (*allnormals)[verIndex]; Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); Ogre::Bone *bonePtr = 0; @@ -276,7 +274,7 @@ namespace MWRender{ rotmult = bonePtr->getOrientation(); scale = bonePtr->getScale().x; boneSequenceIter++; - + for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) { if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){ @@ -390,7 +388,7 @@ namespace MWRender{ void Animation::handleAnimationTransforms(){ - + Ogre::SkeletonInstance* skel = base->getSkeleton(); @@ -430,11 +428,11 @@ namespace MWRender{ const std::vector & quats = iter->getQuat(); const std::vector & ttime = iter->gettTime(); - + const std::vector & rtime = iter->getrTime(); int rindexJ = rindexI[slot]; - + timeIndex(time, rtime, rindexI[slot], rindexJ, x2); int tindexJ = tindexI[slot]; @@ -447,10 +445,10 @@ namespace MWRender{ Ogre::Quaternion r; bool bTrans = translist1.size() > 0; - + bool bQuats = quats.size() > 0; - + if(skel->hasBone(iter->getBonename())){ Ogre::Bone* bone = skel->getBone(iter->getBonename()); if(bTrans){ @@ -467,10 +465,10 @@ namespace MWRender{ - + } - + slot++; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index e08b86e8de..d1e8071f06 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -66,7 +66,7 @@ class Animation{ void stopScript(); - ~Animation(); + virtual ~Animation(); }; } diff --git a/apps/openmw/mwrender/creatureanimation.hpp b/apps/openmw/mwrender/creatureanimation.hpp index 179991442c..2229eeec98 100644 --- a/apps/openmw/mwrender/creatureanimation.hpp +++ b/apps/openmw/mwrender/creatureanimation.hpp @@ -16,7 +16,7 @@ namespace MWRender{ class CreatureAnimation: public Animation{ public: - ~CreatureAnimation(); + virtual ~CreatureAnimation(); CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); virtual void runAnimation(float timepassed); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index e8ce735f79..e2071957c0 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -20,7 +20,7 @@ class NpcAnimation: public Animation{ public: NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); - ~NpcAnimation(); + 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); virtual void runAnimation(float timepassed); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a8887e64f0..f83e16717a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -215,9 +215,14 @@ void RenderingManager::configureFog(ESMS::CellStore &mCell) void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) { /// \todo make the viewing distance and fog start/end configurable - float low = 3000 / density; - float high = 6200 / density; - + + // right now we load 3x3 cells, so the maximum viewing distance we + // can allow (to prevent objects suddenly popping up) equals: + // 8192 * 0.69 + // ^ cell size ^ minimum density value used (clear weather) + float low = 5652.48 / density / 2.f; + float high = 5652.48 / density; + mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high); mRendering.getCamera()->setFarClipDistance ( high ); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 1b324459a5..e09fa8a422 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -59,7 +59,8 @@ void BillboardObject::setPosition(const Vector3& pPosition) Vector3 BillboardObject::getPosition() const { - return mNode->getPosition(); + Vector3 p = mNode->_getDerivedPosition() - mNode->getParentSceneNode()->_getDerivedPosition(); + return Vector3(p.x, -p.z, p.y); } void BillboardObject::setColour(const ColourValue& pColour) @@ -161,14 +162,20 @@ Moon::Moon( const String& textureName, " in float2 uv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n" " uniform sampler2D texture : TEXUNIT0, \n" + " uniform float4 skyColour, \n" " uniform float4 diffuse, \n" " uniform float4 emissive \n" ") \n" "{ \n" " float4 tex = tex2D(texture, uv); \n" - " oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n" - " float bump = pow((1-diffuse.a),4); \n" - " oColor.rgb += float3(bump, bump, bump)*0.5; \n" + " oColor = float4(emissive.xyz,1) * tex; \n" + // use a circle for the alpha (compute UV distance to center) + // looks a bit bad because its not filtered on the edges, + // but it's cheaper than a seperate alpha texture. + " float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n" + " oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n" + " oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour + " oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump "}"; fshader->setSource(outStream2.str()); fshader->load(); @@ -186,15 +193,19 @@ void Moon::setType(const Moon::Type& type) mType = type; } +void Moon::setSkyColour(const Ogre::ColourValue& colour) +{ + mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("skyColour", colour); +} -/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars 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"; @@ -203,9 +214,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; @@ -338,24 +349,11 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) : mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight->attachObject(night1_ent); - for (unsigned int i=0; igetNumSubEntities(); ++i) - { - MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); - mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); - mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); - mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - - mStarsMaterials[i] = mp; - } - // Stars vertex shader - HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); - vshader3->setParameter("profiles", "vs_2_x arbvp1"); - vshader3->setParameter("entry_point", "main_vp"); + stars_vp->setParameter("profiles", "vs_2_x arbvp1"); + stars_vp->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream4; outStream4 << "void main_vp( \n" @@ -371,10 +369,9 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) : " oFade = (position.z > 50) ? 1.f : 0.f; \n" " oPosition = mul( worldViewProj, position ); \n" "}"; - vshader3->setSource(outStream4.str()); - vshader3->load(); - vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName()); + stars_vp->setSource(outStream4.str()); + stars_vp->load(); + stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); // Stars fragment shader HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, @@ -399,7 +396,20 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) : stars_fp->load(); stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); + + for (unsigned int i=0; igetNumSubEntities(); ++i) + { + MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); + mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); + mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); + mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); + mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); + mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); + mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); + mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); + mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); + mStarsMaterials[i] = mp; + } // Atmosphere (day) mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); @@ -583,6 +593,9 @@ void SkyManager::update(float duration) mSun->setVisible(mSunEnabled); mMasser->setVisible(mMasserEnabled); mSecunda->setVisible(mSecundaEnabled); + + // rotate the whole sky by 360 degrees every 4 days + mRootNode->roll(Degree(mHourDiff*360/96.f)); } void SkyManager::enable() @@ -647,6 +660,8 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) if (mSkyColour != weather.mSkyColor) { mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor); + mMasser->setSkyColour(weather.mSkyColor); + mSecunda->setSkyColour(weather.mSkyColor); mSkyColour = weather.mSkyColor; } @@ -760,6 +775,9 @@ void SkyManager::setSecundaFade(const float fade) void SkyManager::setHour(double hour) { + mHourDiff = mHour - hour; + if (mHourDiff > 0) mHourDiff -= 24; + mHour = hour; } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 2678165e39..2c7b7379a5 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -34,6 +34,8 @@ namespace MWRender Ogre::SceneNode* rootNode ); BillboardObject(); + + virtual ~BillboardObject() {} void setColour(const Ogre::ColourValue& pColour); void setPosition(const Ogre::Vector3& pPosition); @@ -69,6 +71,8 @@ namespace MWRender const Ogre::Vector3& position, Ogre::SceneNode* rootNode ); + + virtual ~Moon() {} enum Phase { @@ -90,6 +94,7 @@ namespace MWRender void setPhase(const Phase& phase); void setType(const Type& type); + void setSkyColour(const Ogre::ColourValue& colour); Phase getPhase() const; unsigned int getPhaseInt() const; @@ -162,7 +167,9 @@ namespace MWRender float mHour; int mDay; int mMonth; - + + float mHourDiff; + BillboardObject* mSun; BillboardObject* mSunGlare; Moon* mMasser; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 2440eda238..a5ba04e261 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -136,7 +136,7 @@ namespace MWSound max = std::max(min, max); } - return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict); + return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict, false); } // Add a sound to the list and play it @@ -145,7 +145,7 @@ namespace MWSound const std::string &id, float volume, float pitch, float min, float max, - bool loop) + bool loop, bool untracked) { try { @@ -157,7 +157,10 @@ namespace MWSound setPos(snd, ptr); snd->play(); - sounds[ptr][id] = WSoundPtr(snd); + if (!untracked) + { + sounds[ptr][id] = WSoundPtr(snd); + } } catch(...) { @@ -290,7 +293,7 @@ namespace MWSound void SoundManager::streamMusic(const std::string& filename) { - std::string filePath = mMusicLibrary.locate(filename, mFSStrict).string(); + std::string filePath = mMusicLibrary.locate(filename, mFSStrict, true).string(); if(!filePath.empty()) { streamMusicFull(filePath); @@ -373,7 +376,7 @@ namespace MWSound void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) { // The range values are not tested - std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict); + std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true); if(!filePath.empty()) add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false); else @@ -397,6 +400,7 @@ namespace MWSound snd->setVolume(volume); snd->setRange(min,max); snd->setPitch(pitch); + snd->setRelative(true); snd->play(); if (loop) @@ -412,13 +416,13 @@ namespace MWSound } void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, - float volume, float pitch, bool loop) + float volume, float pitch, bool loop, bool untracked) { // Look up the sound in the ESM data float min, max; const std::string &file = lookup(soundId, volume, min, max); if (file != "") - add(file, ptr, soundId, volume, pitch, min, max, loop); + add(file, ptr, soundId, volume, pitch, min, max, loop, untracked); } void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId) diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 03c19ce774..bd3b676797 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -87,7 +87,7 @@ namespace MWSound void add(const std::string &file, MWWorld::Ptr ptr, const std::string &id, float volume, float pitch, float min, float max, - bool loop); + bool loop, bool untracked=false); void clearAll(PtrMap::iterator& it); void remove(MWWorld::Ptr ptr, const std::string &id = ""); bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const; @@ -136,7 +136,7 @@ namespace MWSound ///< Play a sound, independently of 3D-position void playSound3D (MWWorld::Ptr reference, const std::string& soundId, - float volume, float pitch, bool loop); + float volume, float pitch, bool loop, bool untracked=false); ///< Play a sound from an object void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = ""); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 96afc89a1b..9d766909f7 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -132,7 +132,7 @@ namespace MWWorld return std::make_pair (std::vector(), false); } - int Class::getEuqipmentSkill (const Ptr& ptr, const Environment& environment) const + int Class::getEquipmentSkill (const Ptr& ptr, const Environment& environment) const { return -1; } @@ -156,4 +156,14 @@ namespace MWWorld { sClasses.insert (std::make_pair (key, instance)); } + + std::string Class::getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const + { + throw std::runtime_error ("class does not have an up sound"); + } + + std::string Class::getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const + { + throw std::runtime_error ("class does not have an down sound"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 49c7bed0e2..67320b3e07 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -149,7 +149,7 @@ namespace MWWorld /// /// Default implementation: return (empty vector, false). - virtual int getEuqipmentSkill (const Ptr& ptr, const Environment& environment) + virtual int getEquipmentSkill (const Ptr& ptr, const Environment& environment) const; /// Return the index of the skill this item corresponds to when equiopped or -1, if there is /// no such skill. @@ -162,6 +162,14 @@ namespace MWWorld ///< If there is no class for this pointer, an exception is thrown. static void registerClass (const std::string& key, boost::shared_ptr instance); + + virtual std::string getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) 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; + ///< 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/weather.cpp b/apps/openmw/mwworld/weather.cpp index eadd4b353e..eab1197c5e 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -488,7 +488,10 @@ WeatherResult WeatherManager::transition(float factor) void WeatherManager::update(float duration) { mWeatherUpdateTime -= duration; - if (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior()) + + bool exterior = (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior()); + + if (exterior) { std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region; boost::algorithm::to_lower(regionstr); @@ -663,7 +666,7 @@ void WeatherManager::update(float duration) mRendering->getSkyManager()->secundaDisable(); } - if (mCurrentWeather == "thunderstorm" && mNextWeather == "") + if (mCurrentWeather == "thunderstorm" && mNextWeather == "" && exterior) { if (mThunderFlash > 0) { @@ -725,6 +728,7 @@ void WeatherManager::update(float duration) // play sounds std::string ambientSnd = (mNextWeather == "" ? mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID : ""); + if (!exterior) ambientSnd = ""; if (ambientSnd != "") { if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end()) @@ -735,6 +739,7 @@ void WeatherManager::update(float duration) } std::string rainSnd = (mNextWeather == "" ? mWeatherSettings[mCurrentWeather].mRainLoopSoundID : ""); + if (!exterior) rainSnd = ""; if (rainSnd != "") { if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end()) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 1a69f4d7b4..1c47e3c710 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -161,9 +161,9 @@ namespace MWWorld { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); - + mRendering = new MWRender::RenderingManager(renderer, resDir, mPhysEngine, environment); - + mWeatherManager = new MWWorld::WeatherManager(mRendering, &environment); boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); @@ -381,7 +381,7 @@ namespace MWWorld mGlobalVariables->setFloat ("gamehour", hour); mRendering->skySetHour (hour); - + mWeatherManager->setHour (hour); if (days>0) @@ -418,10 +418,10 @@ namespace MWWorld mGlobalVariables->setInt ("month", month); mRendering->skySetDate (day, month); - + mWeatherManager->setDate (day, month); - - + + } void World::setMonth (int month) @@ -702,9 +702,9 @@ namespace MWWorld void World::update (float duration) { mWorldScene->update (duration); - + mWeatherManager->update (duration); - + // cast a ray from player to sun to detect if the sun is visible // this is temporary until we find a better place to put this code // currently its here because we need to access the physics system @@ -713,7 +713,7 @@ namespace MWWorld sun = Vector3(sun.x, -sun.z, sun.y); mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); } - + bool World::isCellExterior() const { Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); @@ -726,7 +726,7 @@ namespace MWWorld } return false; } - + bool World::isCellQuasiExterior() const { Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); @@ -739,17 +739,17 @@ namespace MWWorld } return false; } - + int World::getCurrentWeather() const { return mWeatherManager->getWeatherID(); } - + void World::changeWeather(const std::string& region, const unsigned int id) { mWeatherManager->changeWeather(region, id); } - + OEngine::Render::Fader* World::getFader() { return mRendering->getFader(); diff --git a/components/compiler/controlparser.cpp b/components/compiler/controlparser.cpp index c255154b5a..5d74ee9d42 100644 --- a/components/compiler/controlparser.cpp +++ b/components/compiler/controlparser.cpp @@ -95,8 +95,6 @@ namespace Compiler return true; } - - return false; } bool ControlParser::parseWhileBody (int keyword, const TokenLoc& loc, Scanner& scanner) @@ -108,7 +106,7 @@ namespace Compiler Codes expr; mExprParser.append (expr); - Generator::jump (loop, -mCodeBlock.size()-expr.size()); + Generator::jump (loop, -static_cast (mCodeBlock.size()-expr.size())); std::copy (expr.begin(), expr.end(), std::back_inserter (mCode)); @@ -122,7 +120,7 @@ namespace Compiler Codes loop2; - Generator::jump (loop2, -mCodeBlock.size()-expr.size()-skip.size()); + Generator::jump (loop2, -static_cast (mCodeBlock.size()-expr.size()-skip.size())); if (loop.size()!=loop2.size()) throw std::logic_error ( @@ -153,8 +151,6 @@ namespace Compiler return true; } - - return false; } ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals, diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index b0727b0c01..dc63ce335e 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -3,32 +3,68 @@ namespace ESM { -void PathGrid::load(ESMReader &esm) +void Pathgrid::load(ESMReader &esm) { esm.getHNT(data, "DATA", 12); cell = esm.getHNString("NAME"); - // Remember this file position - context = esm.getContext(); + // keep track of total connections so we can reserve edge vector size + int edgeCount = 0; - // Check that the sizes match up. Size = 16 * s2 (path points?) if (esm.isNextSub("PGRP")) { - esm.skipHSub(); + esm.getSubHeader(); int size = esm.getSubSize(); - if (size != 16 * data.s2) - esm.fail("Path grid table size mismatch"); + // Check that the sizes match up. Size = 16 * s2 (path points) + if (size != static_cast (sizeof(Point) * data.s2)) + esm.fail("Path point subrecord size mismatch"); + else + { + int pointCount = data.s2; + points.reserve(pointCount); + for (int i = 0; i < pointCount; ++i) + { + Point p; + esm.getExact(&p, sizeof(Point)); + points.push_back(p); + edgeCount += p.connectionNum; + } + } } - // Size varies. Path grid chances? Connections? Multiples of 4 - // suggest either int or two shorts, or perhaps a float. Study - // it later. if (esm.isNextSub("PGRC")) { - esm.skipHSub(); + esm.getSubHeader(); int size = esm.getSubSize(); - if (size % 4 != 0) + if (size % sizeof(int) != 0) esm.fail("PGRC size not a multiple of 4"); + else + { + int rawConnNum = size / sizeof(int); + std::vector rawConnections; + rawConnections.reserve(rawConnNum); + for (int i = 0; i < rawConnNum; ++i) + { + int currentValue; + esm.getT(currentValue); + rawConnections.push_back(currentValue); + } + + std::vector::const_iterator rawIt = rawConnections.begin(); + int pointIndex = 0; + edges.reserve(edgeCount); + for(PointList::const_iterator it = points.begin(); it != points.end(); it++, pointIndex++) + { + unsigned char connectionNum = (*it).connectionNum; + for (int i = 0; i < connectionNum; ++i) { + Edge edge; + edge.v0 = pointIndex; + edge.v1 = *rawIt; + rawIt++; + edges.push_back(edge); + } + } + } } } diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 8c030d3141..6e2c6e134f 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -9,20 +9,37 @@ namespace ESM /* * Path grid. */ -struct PathGrid +struct Pathgrid { struct DATAstruct { int x, y; // Grid location, matches cell for exterior cells short s1; // ?? Usually but not always a power of 2. Doesn't seem // to have any relation to the size of PGRC. - short s2; // Number of path points? Size of PGRP block is always 16 * s2; + short s2; // Number of path points. }; // 12 bytes + struct Point // path grid point + { + int x, y, z; // Location of point + unsigned char autogenerated; // autogenerated vs. user coloring flag? + unsigned char connectionNum; // number of connections for this point + short unknown; + }; // 16 bytes + + struct Edge // path grid edge + { + int v0, v1; // index of points connected with this edge + }; // 8 bytes + std::string cell; // Cell name DATAstruct data; - ESM_Context context; // Context so we can return here later and - // finish the job + + typedef std::vector PointList; + PointList points; + + typedef std::vector EdgeList; + EdgeList edges; void load(ESMReader &esm); }; diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 20a2e8ff95..678f794c81 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -22,6 +22,8 @@ namespace ESMS struct RecList { + virtual ~RecList() {} + virtual void load(ESMReader &esm, const std::string &id) = 0; virtual int getSize() = 0; virtual void listIdentifier (std::vector& identifier) const = 0; @@ -42,6 +44,8 @@ namespace ESMS template struct RecListT : RecList { + virtual ~RecListT() {} + typedef std::map MapType; MapType list; @@ -90,6 +94,8 @@ namespace ESMS template struct RecListWithIDT : RecList { + virtual ~RecListWithIDT() {} + typedef std::map MapType; MapType list; @@ -139,6 +145,8 @@ namespace ESMS template struct RecIDListT : RecList { + virtual ~RecIDListT() {} + typedef std::map MapType; MapType list; @@ -189,6 +197,8 @@ namespace ESMS */ struct LTexList : RecList { + virtual ~LTexList() {} + // TODO: For multiple ESM/ESP files we need one list per file. std::vector ltex; int count; @@ -223,6 +233,8 @@ namespace ESMS */ struct LandList : RecList { + virtual ~LandList() {} + // Map containing all landscapes typedef std::map LandsCol; typedef std::map Lands; @@ -296,7 +308,7 @@ namespace ESMS identifier.push_back (iter->first); } - ~CellList() + virtual ~CellList() { for (IntCells::iterator it = intCells.begin(); it!=intCells.end(); ++it) delete it->second; @@ -390,9 +402,100 @@ namespace ESMS } }; + struct PathgridList : RecList + { + int count; + + // List of grids for interior cells. Indexed by cell name. + typedef std::map IntGrids; + IntGrids intGrids; + + // List of grids for exterior cells. Indexed as extCells[gridX][gridY]. + typedef std::map, ESM::Pathgrid*> ExtGrids; + ExtGrids extGrids; + + PathgridList() : count(0) {} + + virtual ~PathgridList() + { + for (IntGrids::iterator it = intGrids.begin(); it!=intGrids.end(); ++it) + delete it->second; + + for (ExtGrids::iterator it = extGrids.begin(); it!=extGrids.end(); ++it) + delete it->second; + } + + int getSize() { return count; } + + virtual void listIdentifier (std::vector& identifier) const + { + // do nothing + } + + void load(ESMReader &esm, const std::string &id) + { + count++; + ESM::Pathgrid *grid = new ESM::Pathgrid; + grid->load(esm); + if (grid->data.x == 0 && grid->data.y == 0) + { + intGrids[grid->cell] = grid; + } + else + { + extGrids[std::make_pair(grid->data.x, grid->data.y)] = grid; + } + } + + Pathgrid *find(int cellX, int cellY, std::string cellName) const + { + Pathgrid *result = search(cellX, cellY, cellName); + if (!result) + { + throw std::runtime_error("no pathgrid found for cell " + cellName); + } + return result; + } + + Pathgrid *search(int cellX, int cellY, std::string cellName) const + { + Pathgrid *result = NULL; + if (cellX == 0 && cellY == 0) // possibly interior + { + IntGrids::const_iterator it = intGrids.find(cellName); + if (it != intGrids.end()) + result = it->second; + } + else + { + ExtGrids::const_iterator it = extGrids.find(std::make_pair(cellX, cellY)); + if (it != extGrids.end()) + result = it->second; + } + return result; + } + + Pathgrid *search(const ESM::Cell &cell) const + { + int cellX, cellY; + if (cell.data.flags & ESM::Cell::Interior) + { + cellX = cellY = 0; + } + else + { + cellX = cell.data.gridX; + cellY = cell.data.gridY; + } + return search(cellX, cellY, cell.name); + } + }; + template struct ScriptListT : RecList { + virtual ~ScriptListT() {} + typedef std::map MapType; MapType list; @@ -444,6 +547,8 @@ namespace ESMS template struct IndexListT { + virtual ~IndexListT() {} + typedef std::map MapType; MapType list; diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index e3bbf9e82c..fab04d3e97 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -74,7 +74,8 @@ namespace ESMS ScriptListT