From 8d85211fa19fb1a85c098ca6e430b0c14a31dff0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Aug 2010 14:09:09 +0200 Subject: [PATCH 01/25] modified Npc and Creature class to let them store a copy of their own ID --- apps/esmtool/esmtool.cpp | 2 +- apps/openmw/mwworld/manualref.hpp | 17 +++++++ components/esm/loadcrea.hpp | 8 +++- components/esm/loadnpc.hpp | 6 ++- components/esm_store/reclists.hpp | 76 +++++++++++++++++++++++-------- components/esm_store/store.hpp | 4 +- 6 files changed, 88 insertions(+), 25 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index ff8e53824..fe067d85d 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -180,7 +180,7 @@ int main(int argc, char**argv) case REC_CREA: { Creature b; - b.load(esm); + b.load(esm, id); if(quiet) break; cout << " Name: " << b.name << endl; break; diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 4b7edfa43..b4d3f7007 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -36,6 +36,23 @@ namespace MWWorld return false; } + template + bool create (const ESMS::RecListWithIDT& list, const std::string& name) + { + if (const T *instance = list.search (name)) + { + ESMS::LiveCellRef ref; + ref.base = instance; + + mRef = ref; + mPtr = Ptr (&boost::any_cast&> (mRef), 0); + + return true; + } + + return false; + } + public: ManualRef (const ESMS::ESMStore& store, const std::string& name) diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 2a22cebe0..cbf39bd95 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -62,8 +62,12 @@ struct Creature // Defined in loadcont.hpp InventoryList inventory; - void load(ESMReader &esm) + std::string mId; + + void load(ESMReader &esm, const std::string& id) { + mId = id; + model = esm.getHNString("MODL"); original = esm.getHNOString("CNAM"); name = esm.getHNOString("FNAM"); @@ -93,7 +97,7 @@ struct Creature // AI_A - activate? esm.skipRecord(); - } + } }; } #endif diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 0075996ac..61618c731 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -97,8 +97,12 @@ struct NPC std::string name, model, race, cls, faction, script, hair, head; // body parts - void load(ESMReader &esm) + std::string mId; + + void load(ESMReader &esm, const std::string& id) { + mId = id; + npdt52.gold = -10; model = esm.getHNOString("MODL"); diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 5763dc6f9..3b160259c 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -17,16 +17,16 @@ namespace ESMS { virtual void load(ESMReader &esm, const std::string &id) = 0; virtual int getSize() = 0; - + static std::string toLower (const std::string& name) { std::string lowerCase; - + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); - + return lowerCase; - } + } }; typedef std::map RecListList; @@ -53,15 +53,53 @@ namespace ESMS return NULL; return &list.find(id2)->second; } - + // 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(); } + }; + + /// Modified version of RecListT for records, that need to store their own ID + template + struct RecListWithIDT : RecList + { + 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[id2].load(esm, id2); + } + + // Find the given object ID, or return NULL if not found. + const X* search(const std::string &id) const + { + std::string id2 = toLower (id); + if(list.find(id2) == list.end()) + return NULL; + return &list.find(id2)->second; + } + + // 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; } @@ -80,7 +118,7 @@ namespace ESMS void load(ESMReader &esm, const std::string &id) { - std::string id2 = toLower (id); + std::string id2 = toLower (id); X& ref = list[id2]; ref.id = id; @@ -95,18 +133,18 @@ namespace ESMS return NULL; return &list.find(id2)->second; } - + // 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(); } }; @@ -180,7 +218,7 @@ namespace ESMS } } }; - + template struct ScriptListT : RecList { @@ -193,16 +231,16 @@ namespace ESMS { X ref; ref.load (esm); - + std::string realId = toLower (ref.data.name.toString()); - + std::swap (list[realId], ref); } // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = toLower (id); if(list.find(id2) == list.end()) return NULL; return &list.find(id2)->second; @@ -212,15 +250,15 @@ namespace ESMS 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(); } - }; + }; /* We need special lists for: diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index fd4a47d4b..6138014ef 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -40,7 +40,7 @@ namespace ESMS RecListT clothes; RecListT contChange; RecListT containers; - RecListT creatures; + RecListWithIDT creatures; RecListT creaChange; RecListT dialogs; RecListT doors; @@ -53,7 +53,7 @@ namespace ESMS RecListT lights; RecListT lockpicks; RecListT miscItems; - RecListT npcs; + RecListWithIDT npcs; RecListT npcChange; RecListT probes; RecListT races; From 34572f0b197bdee56129d46c239b74bea8263e1a Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 12 Aug 2010 16:13:54 +0200 Subject: [PATCH 02/25] Compiled and linked in sound system (not yet functional) --- CMakeLists.txt | 12 ++++- apps/openmw/CMakeLists.txt | 2 + apps/openmw/engine.cpp | 3 +- apps/openmw/mwsound/soundmanager.cpp | 67 +++++++++++++++++++++++++--- apps/openmw/mwsound/soundmanager.hpp | 28 ++++++------ cmake/FindAudiere.cmake | 57 +++++++++++++++++++++++ libs/mangle | 2 +- libs/openengine | 2 +- 8 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 cmake/FindAudiere.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index cd058c570..34925152a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,15 @@ set(OENGINE_GUI ${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/manager.cpp ) -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI}) +set(OENGINE_SOUND + # Mangle and OEngine sound files are sort of intertwined, so put + # them together here + ${LIBDIR}/openengine/sound/sndmanager.cpp + ${LIBDIR}/mangle/sound/sources/audiere_source.cpp + ${LIBDIR}/mangle/sound/outputs/openal_out.cpp + ${LIBDIR}/mangle/stream/clients/audiere_file.cpp +) +set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND}) source_group(libs\\openengine FILES ${OENGINE_ALL}) set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) @@ -110,6 +118,8 @@ find_package(OGRE REQUIRED) find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread) find_package(OIS REQUIRED) find_package(Iconv REQUIRED) +find_package(OpenAL REQUIRED) +find_package(Audiere REQUIRED) include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a43119c61..c978bc2db 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -183,6 +183,8 @@ target_link_libraries(openmw ${OGRE_LIBRARIES} ${OIS_LIBRARIES} ${Boost_LIBRARIES} + ${OPENAL_LIBRARY} + ${AUDIERE_LIBRARY} ${ICONV_LIBRARIES} caelum MyGUIEngine diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b67bcd0ac..ad12f910b 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -233,7 +233,8 @@ void OMW::Engine::go() mExtensions, mNewGame); // Create sound system - mEnvironment.mSoundManager = new MWSound::SoundManager; + mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), + mOgre.getCamera()); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index bfe51686b..87f6b9bdd 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -1,12 +1,67 @@ #include "soundmanager.hpp" -#include // TODO remove this line, once the real code is in place. - #include +#include + +/* Set up the sound manager to use Audiere for input (reading sound + files) and OpenAL for output. + */ +#include +#define SOUND_FACTORY OpenAL_Audiere_Factory +/* + We could allow several options for libraries via external #defines + if we like, controlled through CMake. The only things that need to + change is the include and #define above, and of course the linker + parameters. + */ + +using namespace Mangle::Sound; + +/* Set the position on a sound based on a Ptr. TODO: We do not support + tracking moving objects yet, once a sound is started it stays in + the same place until it finishes. + + This obviously has to be fixed at some point for player/npc + footstep sounds and the like. However, updating all sounds each + frame is expensive, so there should be a special flag for sounds + that need to track their attached object. + */ +static void setPos(SoundPtr snd, MWWorld::Ptr ref) +{ + // Get sound position from the reference + float *pos = ref.getCellRef().pos.pos; + + // Move the sound. Might need to convert coordinates, test. + snd->setPos(pos[0], pos[1], pos[2]); +} + namespace MWSound { + struct SoundManager::SoundImpl + { + OEngine::Sound::SoundManager mgr; + + SoundImpl() + : mgr(SoundFactoryPtr(new SOUND_FACTORY)) + {} + + std::map mSounds; // object, sound + }; + + SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera) + { + mData = new SoundImpl; + + // TODO: Set up updater and camera listener. + } + + SoundManager::~SoundManager() + { + delete mData; + } + void SoundManager::say (MWWorld::Ptr reference, const std::string& filename, const std::string& text, Interpreter::Context& context) { @@ -43,7 +98,7 @@ namespace MWSound << " at volume " << volume << ", at pitch " << pitch << std::endl; - mSounds[reference.getRefData().getHandle()] = soundId; + mData->mSounds[reference.getRefData().getHandle()] = soundId; } void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId, @@ -53,16 +108,16 @@ namespace MWSound << "sound effect : stop playing sound " << soundId << " from " << reference.getRefData().getHandle() << std::endl; - mSounds[reference.getRefData().getHandle()] = ""; + mData->mSounds[reference.getRefData().getHandle()] = ""; } bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId, Interpreter::Context& context) const { std::map::const_iterator iter = - mSounds.find (reference.getRefData().getHandle()); + mData->mSounds.find (reference.getRefData().getHandle()); - if (iter==mSounds.end()) + if (iter==mData->mSounds.end()) return false; return iter->second==soundId; diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 5a79c0c27..e42331223 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -11,26 +11,28 @@ namespace Interpreter class Context; } +namespace Ogre +{ + class Root; + class Camera; +} + namespace MWSound { - // Note to the sound implementor (can be removed once the implementation is complete): - // - // - the dummy implementation allows only one sound effect per object at a time. I am - // not sure, if that is what Morrowind does. Beyond the dummy code in this class the script - // system does not make any assumption about the number of sound effects. - // - // - all text-output (error messages and such) must be directed through the - // context.messageBox interface. - // - // - the -> script syntax is not implemented yet ( script instructions of the type - // npc_x -> say "file", "text" - // aren't working) + // Note: the -> script syntax is not implemented yet ( script + // instructions of the type npc_x -> say "file", "text" aren't + // working) class SoundManager { - std::map mSounds; // object, sound (for testing only) + // Hide implementation details - engine.cpp is compiling + // enough as it is. + struct SoundImpl; + SoundImpl *mData; public: + SoundManager(Ogre::Root*, Ogre::Camera*); + ~SoundManager(); void say (MWWorld::Ptr reference, const std::string& filename, const std::string& text, Interpreter::Context& context); diff --git a/cmake/FindAudiere.cmake b/cmake/FindAudiere.cmake new file mode 100644 index 000000000..4cc1fb2df --- /dev/null +++ b/cmake/FindAudiere.cmake @@ -0,0 +1,57 @@ +# Locate Audiere +# This module defines +# AUDIERE_LIBRARY +# AUDIERE_FOUND, if false, do not try to link to Audiere +# AUDIERE_INCLUDE_DIR, where to find the headers +# +# Created by Nicolay Korslund for OpenMW (http://openmw.com) +# +# More or less a direct ripoff of FindOpenAL.cmake by Eric Wing. + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + + +FIND_PATH(AUDIERE_INCLUDE_DIR audiere.h + HINTS + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +FIND_LIBRARY(AUDIERE_LIBRARY + NAMES audiere + HINTS + PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt +) + +SET(AUDIERE_FOUND "NO") +IF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) + SET(AUDIERE_FOUND "YES") +ENDIF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) + diff --git a/libs/mangle b/libs/mangle index c7b179d65..fb2d077ca 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit c7b179d6546688208528c8eef681d42b7c1ec7be +Subproject commit fb2d077ca9935374dd46576e643d111feb325c90 diff --git a/libs/openengine b/libs/openengine index c04d72cbe..b9d4dc448 160000 --- a/libs/openengine +++ b/libs/openengine @@ -1 +1 @@ -Subproject commit c04d72cbe380217c2d1d60f8a2c6e4810fe4c050 +Subproject commit b9d4dc448bc3be908653f9dea3c3450fb85ed107 From 8067d6280093b5a7534cf6fec3d3d33ab8374e53 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 12 Aug 2010 16:29:22 +0200 Subject: [PATCH 03/25] Decoupled SoundManager from Interpreter::Context --- apps/openmw/mwscript/interpretercontext.hpp | 1 + apps/openmw/mwscript/soundextensions.cpp | 37 ++++++++++----------- apps/openmw/mwsound/soundmanager.cpp | 20 ++++------- apps/openmw/mwsound/soundmanager.hpp | 22 ++++-------- 4 files changed, 33 insertions(+), 47 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index e63c4838c..ec3c9eb87 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -51,6 +51,7 @@ namespace MWScript virtual void setLocalFloat (int index, float value); + using Interpreter::Context::messageBox; virtual void messageBox (const std::string& message, const std::vector& buttons); diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index 40229475e..c177a87e3 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -25,15 +25,15 @@ namespace MWScript { MWScript::InterpreterContext& context = static_cast (runtime.getContext()); - + std::string file = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); std::string text = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - - context.getSoundManager().say (context.getReference(), file, text, - context); + + context.getSoundManager().say (context.getReference(), file, text); + context.messageBox (text); } }; @@ -46,8 +46,7 @@ namespace MWScript MWScript::InterpreterContext& context = static_cast (runtime.getContext()); - runtime.push (context.getSoundManager().sayDone (context.getReference(), - context)); + runtime.push (context.getSoundManager().sayDone (context.getReference())); } }; @@ -63,7 +62,7 @@ namespace MWScript std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().streamMusic (sound, context); + context.getSoundManager().streamMusic (sound); } }; @@ -79,7 +78,7 @@ namespace MWScript std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().playSound (sound, 1.0, 1.0, context); + context.getSoundManager().playSound (sound, 1.0, 1.0); } }; @@ -101,7 +100,7 @@ namespace MWScript Interpreter::Type_Float pitch = runtime[0].mFloat; runtime.pop(); - context.getSoundManager().playSound (sound, volume, pitch, context); + context.getSoundManager().playSound (sound, volume, pitch); } }; @@ -122,7 +121,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().playSound3D (context.getReference(), sound, - 1.0, 1.0, mLoop, context); + 1.0, 1.0, mLoop); } }; @@ -149,7 +148,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().playSound3D (context.getReference(), sound, volume, - pitch, mLoop, context); + pitch, mLoop); } }; @@ -166,7 +165,7 @@ namespace MWScript std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().stopSound3D (context.getReference(), sound, context); + context.getSoundManager().stopSound3D (context.getReference(), sound); } }; @@ -183,7 +182,7 @@ namespace MWScript runtime.pop(); runtime.push (context.getSoundManager().getSoundPlaying ( - context.getReference(), runtime.getStringLiteral (index), context)); + context.getReference(), runtime.getStringLiteral (index))); } }; @@ -206,7 +205,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().say (context.getWorld().getPtr (id, true), - file, text, context); + file, text); } }; @@ -223,7 +222,7 @@ namespace MWScript runtime.pop(); runtime.push (context.getSoundManager().sayDone ( - context.getWorld().getPtr (id, true), context)); + context.getWorld().getPtr (id, true))); } }; @@ -247,7 +246,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().playSound3D ( - context.getWorld().getPtr (id, true), sound, 1.0, 1.0, mLoop, context); + context.getWorld().getPtr (id, true), sound, 1.0, 1.0, mLoop); } }; @@ -277,7 +276,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().playSound3D ( - context.getWorld().getPtr (id, true), sound, volume, pitch, mLoop, context); + context.getWorld().getPtr (id, true), sound, volume, pitch, mLoop); } }; @@ -298,7 +297,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().stopSound3D ( - context.getWorld().getPtr (id, true), sound, context); + context.getWorld().getPtr (id, true), sound); } }; @@ -319,7 +318,7 @@ namespace MWScript runtime.push (context.getSoundManager().getSoundPlaying ( context.getWorld().getPtr (id, true), - runtime.getStringLiteral (index), context)); + runtime.getStringLiteral (index))); } }; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 87f6b9bdd..b1a1b54e6 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -1,8 +1,6 @@ #include "soundmanager.hpp" -#include - #include /* Set up the sound manager to use Audiere for input (reading sound @@ -63,25 +61,23 @@ namespace MWSound } void SoundManager::say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text, Interpreter::Context& context) + const std::string& text) { std::cout << "sound effect: " << reference.getRefData().getHandle() << " is speaking" << std::endl; - context.messageBox (text); } - bool SoundManager::sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const + bool SoundManager::sayDone (MWWorld::Ptr reference) const { return false; } - void SoundManager::streamMusic (const std::string& filename, Interpreter::Context& context) + void SoundManager::streamMusic (const std::string& filename) { std::cout << "sound effect: playing music" << filename << std::endl; } - void SoundManager::playSound (const std::string& soundId, float volume, float pitch, - Interpreter::Context& context) + void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { std::cout << "sound effect: playing sound " << soundId @@ -90,7 +86,7 @@ namespace MWSound } void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId, - float volume, float pitch, bool loop, Interpreter::Context& context) + float volume, float pitch, bool loop) { std::cout << "sound effect: playing sound " << soundId @@ -101,8 +97,7 @@ namespace MWSound mData->mSounds[reference.getRefData().getHandle()] = soundId; } - void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId, - Interpreter::Context& context) + void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId) { std::cout << "sound effect : stop playing sound " << soundId @@ -111,8 +106,7 @@ namespace MWSound mData->mSounds[reference.getRefData().getHandle()] = ""; } - bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId, - Interpreter::Context& context) const + bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const { std::map::const_iterator iter = mData->mSounds.find (reference.getRefData().getHandle()); diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index e42331223..294804d10 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -6,11 +6,6 @@ #include "../mwworld/ptr.hpp" -namespace Interpreter -{ - class Context; -} - namespace Ogre { class Root; @@ -35,32 +30,29 @@ namespace MWSound ~SoundManager(); void say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text, Interpreter::Context& context); + const std::string& text); ///< Make an actor say some text. /// \param filename name of a sound file in "Sound/Vo/" in the data directory. /// \param text Subtitle - bool sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const; + bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? - void streamMusic (const std::string& filename, Interpreter::Context& context); + void streamMusic (const std::string& filename); ///< Play a soundifle /// \param filename name of a sound file in "Music/" in the data directory. - void playSound (const std::string& soundId, float volume, float pitch, - Interpreter::Context& context); + void playSound (const std::string& soundId, float volume, float pitch); ///< Play a sound, independently of 3D-position void playSound3D (MWWorld::Ptr reference, const std::string& soundId, - float volume, float pitch, bool loop, Interpreter::Context& context); + float volume, float pitch, bool loop); ///< Play a sound from an object - void stopSound3D (MWWorld::Ptr reference, const std::string& soundId, - Interpreter::Context& context); + void stopSound3D (MWWorld::Ptr reference, const std::string& soundId); ///< Stop the given object from playing the given sound. - bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId, - Interpreter::Context& context) const; + bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const; ///< Is the given sound currently playing on the given object? }; } From 7516e4ca53d20065b972368ce9360b0f602c106a Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Thu, 12 Aug 2010 17:58:29 +0200 Subject: [PATCH 04/25] Added music playing as a test --- apps/openmw/engine.cpp | 12 ++++ apps/openmw/mwscript/soundextensions.cpp | 4 +- apps/openmw/mwsound/soundmanager.cpp | 74 ++++++++++++------------ apps/openmw/mwsound/soundmanager.hpp | 8 +-- libs/mangle | 2 +- 5 files changed, 54 insertions(+), 46 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ad12f910b..827966f65 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -267,6 +267,18 @@ void OMW::Engine::go() mOgre.getRoot()->addFrameListener (this); + // Play some good 'ol tunes + std::string music = (mDataDir / "Music/Explore/mx_explore_5.mp3").file_string(); + try + { + std::cout << "Playing " << music << "\n"; + mEnvironment.mSoundManager->streamMusic(music); + } + catch(std::exception &e) + { + std::cout << " Music Error: " << e.what() << "\n"; + } + // Start the main rendering loop mOgre.start(); diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index c177a87e3..58554ef16 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -32,7 +32,7 @@ namespace MWScript std::string text = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - context.getSoundManager().say (context.getReference(), file, text); + context.getSoundManager().say (context.getReference(), file); context.messageBox (text); } }; @@ -205,7 +205,7 @@ namespace MWScript runtime.pop(); context.getSoundManager().say (context.getWorld().getPtr (id, true), - file, text); + file); } }; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b1a1b54e6..4d84964c2 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -2,6 +2,8 @@ #include "soundmanager.hpp" #include +#include +#include /* Set up the sound manager to use Audiere for input (reading sound files) and OpenAL for output. @@ -16,6 +18,8 @@ */ using namespace Mangle::Sound; +typedef OEngine::Sound::SoundManager OEManager; +typedef OEngine::Sound::SoundManagerPtr OEManagerPtr; /* Set the position on a sound based on a Ptr. TODO: We do not support tracking moving objects yet, once a sound is started it stays in @@ -26,10 +30,10 @@ using namespace Mangle::Sound; frame is expensive, so there should be a special flag for sounds that need to track their attached object. */ -static void setPos(SoundPtr snd, MWWorld::Ptr ref) +static void setPos(SoundPtr snd, const MWWorld::Ptr ref) { // Get sound position from the reference - float *pos = ref.getCellRef().pos.pos; + const float *pos = ref.getCellRef().pos.pos; // Move the sound. Might need to convert coordinates, test. snd->setPos(pos[0], pos[1], pos[2]); @@ -39,20 +43,34 @@ namespace MWSound { struct SoundManager::SoundImpl { - OEngine::Sound::SoundManager mgr; + /* This is the sound manager. It loades, stores and deletes + sounds based on the sound factory it is given. + */ + OEManagerPtr mgr; + + /* This class calls update() on the sound manager each frame + using and Ogre::FrameListener + */ + Mangle::Sound::OgreOutputUpdater updater; + + /* This class tracks the movement of an Ogre::Camera and moves + a sound listener automatically to follow it. + */ + Mangle::Sound::OgreListenerMover cameraTracker; SoundImpl() - : mgr(SoundFactoryPtr(new SOUND_FACTORY)) + : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) + , updater(mgr) + , cameraTracker(mgr) {} - - std::map mSounds; // object, sound }; SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera) { mData = new SoundImpl; - // TODO: Set up updater and camera listener. + // Attach the camera to the camera tracker + mData->cameraTracker.followCamera(camera); } SoundManager::~SoundManager() @@ -60,61 +78,45 @@ namespace MWSound delete mData; } - void SoundManager::say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text) + void SoundManager::say (MWWorld::Ptr reference, const std::string& filename) { - std::cout << "sound effect: " << reference.getRefData().getHandle() << " is speaking" << std::endl; - + // Play the sound at the correct position + SoundPtr snd = mData->mgr->play(filename); + setPos(snd, reference); + // TODO: We need to attach it to the reference somehow. A weak + // pointer is probably the best bet } bool SoundManager::sayDone (MWWorld::Ptr reference) const { - return false; + return true; + // TODO: Ask the reference to check its attached 'say' sound. } void SoundManager::streamMusic (const std::string& filename) { - std::cout << "sound effect: playing music" << filename << std::endl; + // Play the sound and tell it to stream, if possible. + mData->mgr->play(filename)->setStreaming(true); } void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { - std::cout - << "sound effect: playing sound " << soundId - << " at volume " << volume << ", at pitch " << pitch - << std::endl; } void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId, float volume, float pitch, bool loop) { - std::cout - << "sound effect: playing sound " << soundId - << " from " << reference.getRefData().getHandle() - << " at volume " << volume << ", at pitch " << pitch - << std::endl; - - mData->mSounds[reference.getRefData().getHandle()] = soundId; + // Not implemented - need both a way to find sounds by id and + // a way to attach them to the reference } void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId) { - std::cout - << "sound effect : stop playing sound " << soundId - << " from " << reference.getRefData().getHandle() << std::endl; - - mData->mSounds[reference.getRefData().getHandle()] = ""; } bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const { - std::map::const_iterator iter = - mData->mSounds.find (reference.getRefData().getHandle()); - - if (iter==mData->mSounds.end()) - return false; - - return iter->second==soundId; + return false; } } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 294804d10..88cf63e1b 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -14,10 +14,6 @@ namespace Ogre namespace MWSound { - // Note: the -> script syntax is not implemented yet ( script - // instructions of the type npc_x -> say "file", "text" aren't - // working) - class SoundManager { // Hide implementation details - engine.cpp is compiling @@ -29,11 +25,9 @@ namespace MWSound SoundManager(Ogre::Root*, Ogre::Camera*); ~SoundManager(); - void say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text); + 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 text Subtitle bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? diff --git a/libs/mangle b/libs/mangle index fb2d077ca..86a811c73 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit fb2d077ca9935374dd46576e643d111feb325c90 +Subproject commit 86a811c736810ef156fd2788be74951c5416ca03 From b94e09e0301bffe812d780cbd89fc8842b466c30 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 12 Aug 2010 18:44:16 +0200 Subject: [PATCH 05/25] fixed a bug that prevented local scripts from running --- apps/openmw/engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 827966f65..b90c1d0a5 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -38,7 +38,7 @@ void OMW::Engine::executeLocalScripts() mEnvironment.mWorld->getLocalScripts().begin()); iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter) { - if (!mIgnoreLocalPtr.isEmpty() && mIgnoreLocalPtr!=iter->second) + if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second) { MWScript::InterpreterContext interpreterContext (mEnvironment, &iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second)); From 0d4f2ab3efc34ddb824ccddd31ac4836f619073e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 12 Aug 2010 19:41:40 +0200 Subject: [PATCH 06/25] disabled escape sequences in script strings (doesn't work with Windows paths) --- components/compiler/scanner.cpp | 78 ++++++++++++++++----------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 6f43f9fde..310fc9ec5 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -48,35 +48,35 @@ namespace Compiler switch (mPutback) { case Putback_Special: - - mPutback = Putback_None; + + mPutback = Putback_None; return parser.parseSpecial (mPutbackCode, mPutbackLoc, *this); - + case Putback_Integer: mPutback = Putback_None; return parser.parseInt (mPutbackInteger, mPutbackLoc, *this); - + case Putback_Float: mPutback = Putback_None; return parser.parseFloat (mPutbackFloat, mPutbackLoc, *this); - + case Putback_Name: - + mPutback = Putback_None; return parser.parseName (mPutbackName, mPutbackLoc, *this); - + case Putback_Keyword: mPutback = Putback_None; return parser.parseKeyword (mPutbackCode, mPutbackLoc, *this); - + case Putback_None: - + break; } - + char c; if (!get (c)) @@ -265,12 +265,12 @@ namespace Compiler cont = parser.parseName (name, loc, *this); return true; } - + int i = 0; std::string lowerCase; lowerCase.reserve (name.size()); - + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); @@ -283,13 +283,13 @@ namespace Compiler cont = parser.parseKeyword (i, loc, *this); return true; } - + if (mExtensions) { if (int keyword = mExtensions->searchKeyword (lowerCase)) { cont = parser.parseKeyword (keyword, loc, *this); - return true; + return true; } } @@ -316,19 +316,20 @@ namespace Compiler name += c; break; } - else if (c=='\\') - { - if (!get (c)) - { - mErrorHandler.error ("incomplete escape sequence", mLoc); - break; - } - } +// ignoring escape sequences for now, because they are messing up stupid Windows path names. +// else if (c=='\\') +// { +// if (!get (c)) +// { +// mErrorHandler.error ("incomplete escape sequence", mLoc); +// break; +// } +// } else if (c=='\n') { mErrorHandler.error ("incomplete string or name", mLoc); break; - } + } } else if (!(c=='"' && name.empty())) { @@ -341,7 +342,7 @@ namespace Compiler if (first && std::isdigit (c)) error = true; } - + name += c; first = false; } @@ -374,7 +375,7 @@ namespace Compiler else { putback (c); - return false; + return false; } } else if (c=='!') @@ -449,8 +450,8 @@ namespace Compiler return false; if (special==S_newline) - mLoc.mLiteral = ""; - + mLoc.mLiteral = ""; + TokenLoc loc (mLoc); mLoc.mLiteral.clear(); @@ -477,40 +478,39 @@ namespace Compiler { while (scanToken (parser)); } - + void Scanner::putbackSpecial (int code, const TokenLoc& loc) { mPutback = Putback_Special; mPutbackCode = code; - mPutbackLoc = loc; + mPutbackLoc = loc; } - + void Scanner::putbackInt (int value, const TokenLoc& loc) { mPutback = Putback_Integer; mPutbackInteger = value; - mPutbackLoc = loc; - } + mPutbackLoc = loc; + } void Scanner::putbackFloat (float value, const TokenLoc& loc) { mPutback = Putback_Float; mPutbackFloat = value; - mPutbackLoc = loc; - } + mPutbackLoc = loc; + } void Scanner::putbackName (const std::string& name, const TokenLoc& loc) { mPutback = Putback_Name; mPutbackName = name; - mPutbackLoc = loc; - } + mPutbackLoc = loc; + } void Scanner::putbackKeyword (int keyword, const TokenLoc& loc) { mPutback = Putback_Keyword; mPutbackCode = keyword; - mPutbackLoc = loc; - } + mPutbackLoc = loc; + } } - From cf4185faef2db62e9baea94eb36c6e0ab2880e39 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 14:43:57 +0200 Subject: [PATCH 07/25] Added sound test (remember to git submodule update) --- CMakeLists.txt | 2 ++ apps/soundtest/CMakeLists.txt | 11 ++++++++ apps/soundtest/main.cpp | 52 +++++++++++++++++++++++++++++++++++ libs/mangle | 2 +- 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 apps/soundtest/CMakeLists.txt create mode 100644 apps/soundtest/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 34925152a..97f8ba6b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,3 +200,5 @@ option(BUILD_ESMTOOL "build ESM inspector" ON) if (BUILD_ESMTOOL) add_subdirectory( apps/esmtool ) endif() + +add_subdirectory( apps/soundtest ) diff --git a/apps/soundtest/CMakeLists.txt b/apps/soundtest/CMakeLists.txt new file mode 100644 index 000000000..81ea7a395 --- /dev/null +++ b/apps/soundtest/CMakeLists.txt @@ -0,0 +1,11 @@ +project(SoundTest) + +# local files + +# Main executable +add_executable(sound_test main.cpp ${OENGINE_SOUND}) + +target_link_libraries(sound_test + ${OPENAL_LIBRARY} + ${AUDIERE_LIBRARY} +) diff --git a/apps/soundtest/main.cpp b/apps/soundtest/main.cpp new file mode 100644 index 000000000..a645d3753 --- /dev/null +++ b/apps/soundtest/main.cpp @@ -0,0 +1,52 @@ +#include + +#include +#include +#include +#include + +using namespace std; +using namespace Mangle::Stream; +using namespace Mangle::Sound; + +AudiereLoader loader; +OpenAL_Factory openal; + +void play(const char* name) +{ + try + { + cout << "Opening " << name << " via Audiere\n"; + SampleSourcePtr samples = loader.load(name); + cout << "Loading entire file into memory\n"; + StreamPtr buf(new BufferStream(samples)); + + // Recreate the stream as a sample source (we're only doing it + // this complicated to test each step individually) + int a,b,c; + samples->getInfo(&a,&b,&c); + samples.reset(new Stream2Samples(buf, a,b,c)); + + cout << "Creating OpenAL sound from data\n"; + SoundPtr snd = openal.loadRaw(samples); + cout << "Playing (abort with Ctrl-C)\n"; + snd->play(); + + while(snd->isPlaying()) + usleep(10000); + cout << "Done playing\n"; + } + catch(exception &e) + { + cout << " ERROR: " << e.what() << "\n"; + } +} + +int main(int argc, char** argv) +{ + if(argc==1) + cout << "Specify sound file (wav, mp3, ogg) on command line.\n"; + for(int i=1; i Date: Fri, 13 Aug 2010 15:51:42 +0200 Subject: [PATCH 08/25] Fixed mistake in NPC record struct --- CMakeLists.txt | 7 ++++-- components/esm/load_impl.cpp | 48 ++++++++++++++++++++++++++++++++++++ components/esm/loadnpc.hpp | 45 ++++----------------------------- 3 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 components/esm/load_impl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 97f8ba6b3..f362f450c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,10 @@ set(ESM_STORE_HEADER source_group(components\\esm_store FILES ${ESM_STORE} ${ESM_STORE_HEADER}) file(GLOB ESM_HEADER ${COMP_DIR}/esm/*.hpp) -source_group(components\\esm FILES ${ESM_HEADER}) +set(ESM + ${COMP_DIR}/esm/load_impl.cpp +) +source_group(components\\esm FILES ${ESM_HEADER} ${ESM}) set(MISC ${COMP_DIR}/misc/stringops.cpp @@ -68,7 +71,7 @@ file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp) source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} - ${COMPILER} ${INTERPRETER}) + ${COMPILER} ${INTERPRETER} ${ESM}) set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER} ${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${INTERPRETER_HEADER}) diff --git a/components/esm/load_impl.cpp b/components/esm/load_impl.cpp new file mode 100644 index 000000000..28ae402de --- /dev/null +++ b/components/esm/load_impl.cpp @@ -0,0 +1,48 @@ +#include "records.hpp" + +/** Implementation for some of the load() functions. Most are found in + the header files themselves, but this is a bit irritating to + compile if you're changing the functions often, as virtually the + entire engine depends on these headers. + */ + +namespace ESM +{ + void NPC::load(ESMReader &esm, const std::string& id) + { + mId = id; + + npdt52.gold = -10; + + model = esm.getHNOString("MODL"); + name = esm.getHNOString("FNAM"); + + race = esm.getHNString("RNAM"); + cls = esm.getHNString("CNAM"); + faction = esm.getHNString("ANAM"); + head = esm.getHNString("BNAM"); + hair = esm.getHNString("KNAM"); + + script = esm.getHNOString("SCRI"); + + esm.getSubNameIs("NPDT"); + esm.getSubHeader(); + if(esm.getSubSize() == 52) esm.getExact(&npdt52, 52); + else if(esm.getSubSize() == 12) esm.getExact(&npdt12, 12); + else esm.fail("NPC_NPDT must be 12 or 52 bytes long"); + + esm.getHNT(flags, "FLAG"); + + inventory.load(esm); + spells.load(esm); + + if(esm.isNextSub("AIDT")) + { + esm.getHExact(&AI, sizeof(AI)); + hasAI = true; + } + else hasAI = false; + + esm.skipRecord(); + } +} diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 61618c731..a699c1cdb 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -57,10 +57,10 @@ struct NPC char strength, intelligence, willpower, agility, speed, endurance, personality, luck; char skills[27]; + char reputation; short health, mana, fatigue; - char disposition; - char reputation; // Was "factionID", but that makes no sense. - char rank, unknown, u2; + char disposition, factionID, rank; + char unknown; int gold; }; // 52 bytes @@ -99,43 +99,8 @@ struct NPC std::string mId; - void load(ESMReader &esm, const std::string& id) - { - mId = id; - - npdt52.gold = -10; - - model = esm.getHNOString("MODL"); - name = esm.getHNOString("FNAM"); - - race = esm.getHNString("RNAM"); - cls = esm.getHNString("CNAM"); - faction = esm.getHNString("ANAM"); - head = esm.getHNString("BNAM"); - hair = esm.getHNString("KNAM"); - - script = esm.getHNOString("SCRI"); - - esm.getSubNameIs("NPDT"); - esm.getSubHeader(); - if(esm.getSubSize() == 52) esm.getExact(&npdt52, 52); - else if(esm.getSubSize() == 12) esm.getExact(&npdt12, 12); - else esm.fail("NPC_NPDT must be 12 or 52 bytes long"); - - esm.getHNT(flags, "FLAG"); - - inventory.load(esm); - spells.load(esm); - - if(esm.isNextSub("AIDT")) - { - esm.getHExact(&AI, sizeof(AI)); - hasAI = true; - } - else hasAI = false; - - esm.skipRecord(); - } + // Implementation moved to load_impl.cpp + void load(ESMReader &esm, const std::string& id); }; } #endif From cad971241116289d40d0f3bab3fc6abb2da57bf2 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 17:11:03 +0200 Subject: [PATCH 09/25] Implemented FFMpeg sound loading. Selecting sound library is controlled through the CMake file. --- CMakeLists.txt | 27 ++++++++- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwsound/soundmanager.cpp | 17 +++--- apps/soundtest/CMakeLists.txt | 2 +- apps/soundtest/main.cpp | 12 +++- cmake/FindFFMPEG.cmake | 90 ++++++++++++++++++++++++++++ libs/mangle | 2 +- 7 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 cmake/FindFFMPEG.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f362f450c..afe467322 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ project(OpenMW) +# Sound source selection +set(USE_AUDIERE "no") +set(USE_FFMPEG "yes") + # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) @@ -93,13 +97,31 @@ set(OENGINE_GUI ${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/manager.cpp ) + +# Sound setup +if (USE_AUDIERE) + set(MANGLE_SOUND_OUTPUT + ${LIBDIR}/mangle/sound/sources/audiere_source.cpp + ${LIBDIR}/mangle/stream/clients/audiere_file.cpp) + find_package(Audiere REQUIRED) + set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY}) + add_definitions(-DOPENMW_USE_AUDIERE) +endif (USE_AUDIERE) + +if (USE_FFMPEG) + set(MANGLE_SOUND_OUTPUT + ${LIBDIR}/mangle/sound/sources/ffmpeg_source.cpp) + find_package(FFMPEG REQUIRED) + set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) + add_definitions(-DOPENMW_USE_FFMPEG) +endif (USE_FFMPEG) + set(OENGINE_SOUND # Mangle and OEngine sound files are sort of intertwined, so put # them together here ${LIBDIR}/openengine/sound/sndmanager.cpp - ${LIBDIR}/mangle/sound/sources/audiere_source.cpp ${LIBDIR}/mangle/sound/outputs/openal_out.cpp - ${LIBDIR}/mangle/stream/clients/audiere_file.cpp + ${MANGLE_SOUND_OUTPUT} ) set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND}) source_group(libs\\openengine FILES ${OENGINE_ALL}) @@ -122,7 +144,6 @@ find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread) find_package(OIS REQUIRED) find_package(Iconv REQUIRED) find_package(OpenAL REQUIRED) -find_package(Audiere REQUIRED) include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c978bc2db..a4a6f6c27 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -184,7 +184,7 @@ target_link_libraries(openmw ${OIS_LIBRARIES} ${Boost_LIBRARIES} ${OPENAL_LIBRARY} - ${AUDIERE_LIBRARY} + ${SOUND_INPUT_LIBRARY} ${ICONV_LIBRARIES} caelum MyGUIEngine diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 4d84964c2..1754fdf28 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -5,17 +5,18 @@ #include #include -/* Set up the sound manager to use Audiere for input (reading sound - files) and OpenAL for output. +/* Set up the sound manager to use Audiere of FFMPEG for input. The + OPENMW_USE_x macros are set in CMakeLists.txt. */ +#ifdef OPENMW_USE_AUDIERE #include #define SOUND_FACTORY OpenAL_Audiere_Factory -/* - We could allow several options for libraries via external #defines - if we like, controlled through CMake. The only things that need to - change is the include and #define above, and of course the linker - parameters. - */ +#endif + +#ifdef OPENMW_USE_FFMPEG +#include +#define SOUND_FACTORY OpenAL_FFMpeg_Factory +#endif using namespace Mangle::Sound; typedef OEngine::Sound::SoundManager OEManager; diff --git a/apps/soundtest/CMakeLists.txt b/apps/soundtest/CMakeLists.txt index 81ea7a395..71c870e04 100644 --- a/apps/soundtest/CMakeLists.txt +++ b/apps/soundtest/CMakeLists.txt @@ -7,5 +7,5 @@ add_executable(sound_test main.cpp ${OENGINE_SOUND}) target_link_libraries(sound_test ${OPENAL_LIBRARY} - ${AUDIERE_LIBRARY} + ${SOUND_INPUT_LIBRARY} ) diff --git a/apps/soundtest/main.cpp b/apps/soundtest/main.cpp index a645d3753..1e88020e1 100644 --- a/apps/soundtest/main.cpp +++ b/apps/soundtest/main.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -9,14 +8,23 @@ using namespace std; using namespace Mangle::Stream; using namespace Mangle::Sound; +#ifdef OPENMW_USE_AUDIERE +#include AudiereLoader loader; +#endif + +#ifdef OPENMW_USE_FFMPEG +#include +FFMpegLoader loader; +#endif + OpenAL_Factory openal; void play(const char* name) { try { - cout << "Opening " << name << " via Audiere\n"; + cout << "Opening " << name << "\n"; SampleSourcePtr samples = loader.load(name); cout << "Loading entire file into memory\n"; StreamPtr buf(new BufferStream(samples)); diff --git a/cmake/FindFFMPEG.cmake b/cmake/FindFFMPEG.cmake new file mode 100644 index 000000000..ff6d0c598 --- /dev/null +++ b/cmake/FindFFMPEG.cmake @@ -0,0 +1,90 @@ +# Find the FFmpeg library +# +# Sets +# FFMPEG_FOUND. If false, don't try to use ffmpeg +# FFMPEG_INCLUDE_DIR +# FFMPEG_LIBRARIES +# +# Modified by Nicolay Korslund for OpenMW + +SET( FFMPEG_FOUND "NO" ) + +FIND_PATH( FFMPEG_avcodec_INCLUDE_DIR avcodec.h + HINTS + PATHS + /usr/include + /usr/local/include + /usr/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg/libavcodec + /usr/local/include/ffmpeg/libavcodec + /usr/include/libavcodec + /usr/local/include/libavcodec +) + +FIND_PATH( FFMPEG_avformat_INCLUDE_DIR avformat.h + HINTS + PATHS + /usr/include + /usr/local/include + /usr/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg/libavformat + /usr/local/include/ffmpeg/libavformat + /usr/include/libavformat + /usr/local/include/libavformat +) + +set(FFMPEG_INCLUDE_DIR ${FFMPEG_avcodec_INCLUDE_DIR} ${FFMPEG_avformat_INCLUDE_DIR}) + +IF( FFMPEG_INCLUDE_DIR ) + +FIND_PROGRAM( FFMPEG_CONFIG ffmpeg-config + /usr/bin + /usr/local/bin + ${HOME}/bin +) + +IF( FFMPEG_CONFIG ) + EXEC_PROGRAM( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS ) + SET( FFMPEG_FOUND "YES" ) + SET( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" ) + +ELSE( FFMPEG_CONFIG ) + + FIND_LIBRARY( FFMPEG_avcodec_LIBRARY avcodec + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + FIND_LIBRARY( FFMPEG_avformat_LIBRARY avformat + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + FIND_LIBRARY( FFMPEG_avutil_LIBRARY avutil + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + ) + + IF( FFMPEG_avcodec_LIBRARY ) + IF( FFMPEG_avformat_LIBRARY ) + + SET( FFMPEG_FOUND "YES" ) + SET( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} ) + IF( FFMPEG_avutil_LIBRARY ) + SET( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} ) + ENDIF( FFMPEG_avutil_LIBRARY ) + + ENDIF( FFMPEG_avformat_LIBRARY ) + ENDIF( FFMPEG_avcodec_LIBRARY ) + +ENDIF( FFMPEG_CONFIG ) + +ENDIF( FFMPEG_INCLUDE_DIR ) diff --git a/libs/mangle b/libs/mangle index f95ea1677..160e8655d 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit f95ea1677cc5c52790e1342aa6d3d6bba950b8be +Subproject commit 160e8655d2503ad93992200d6d131186ede22aa3 From 76492ea60b3073b14bd281ae02b4399ec96ff277 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 13 Aug 2010 18:16:38 +0200 Subject: [PATCH 10/25] cmake improvements for sound options --- CMakeLists.txt | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index afe467322..c62680d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ project(OpenMW) # Sound source selection -set(USE_AUDIERE "no") -set(USE_FFMPEG "yes") +option(USE_AUDIERE "use Audiere for sound" OFF) +option(USE_FFMPEG "use ffmpeg for sound" ON) # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) @@ -13,17 +13,17 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) # source directory: components set(COMP_DIR ${CMAKE_SOURCE_DIR}/components) -set(BSA +set(BSA ${COMP_DIR}/bsa/bsa_archive.cpp ${COMP_DIR}/bsa/bsa_file.cpp) -set(BSA_HEADER +set(BSA_HEADER ${COMP_DIR}/bsa/bsa_archive.hpp ${COMP_DIR}/bsa/bsa_file.hpp) source_group(components\\bsa FILES ${BSA} ${BSA_HEADER}) -set(NIF +set(NIF ${COMP_DIR}/nif/nif_file.cpp) -set(NIF_HEADER +set(NIF_HEADER ${COMP_DIR}/nif/controlled.hpp ${COMP_DIR}/nif/effect.hpp ${COMP_DIR}/nif/nif_types.hpp @@ -35,17 +35,17 @@ set(NIF_HEADER ${COMP_DIR}/nif/data.hpp ${COMP_DIR}/nif/nif_file.hpp ${COMP_DIR}/nif/property.hpp) -source_group(components\\nif FILES ${NIF} ${NIF_HEADER}) +source_group(components\\nif FILES ${NIF} ${NIF_HEADER}) -set(NIFOGRE +set(NIFOGRE ${COMP_DIR}/nifogre/ogre_nif_loader.cpp) -set(NIFOGRE_HEADER +set(NIFOGRE_HEADER ${COMP_DIR}/nifogre/ogre_nif_loader.hpp) -source_group(components\\nifogre FILES ${NIFOGRE} ${NIFOGRE_HEADER}) +source_group(components\\nifogre FILES ${NIFOGRE} ${NIFOGRE_HEADER}) -set(ESM_STORE +set(ESM_STORE ${COMP_DIR}/esm_store/store.cpp) -set(ESM_STORE_HEADER +set(ESM_STORE_HEADER ${COMP_DIR}/esm_store/cell_store.hpp ${COMP_DIR}/esm_store/reclists.hpp ${COMP_DIR}/esm_store/store.hpp) @@ -57,22 +57,22 @@ set(ESM ) source_group(components\\esm FILES ${ESM_HEADER} ${ESM}) -set(MISC +set(MISC ${COMP_DIR}/misc/stringops.cpp ${COMP_DIR}/misc/fileops.cpp) -set(MISC_HEADER +set(MISC_HEADER ${COMP_DIR}/misc/fileops.hpp ${COMP_DIR}/misc/slice_array.hpp ${COMP_DIR}/misc/stringops.hpp) -source_group(components\\misc FILES ${MISC} ${MISC_HEADER}) - +source_group(components\\misc FILES ${MISC} ${MISC_HEADER}) + file(GLOB COMPILER ${COMP_DIR}/compiler/*.cpp) file(GLOB COMPILER_HEADER ${COMP_DIR}/compiler/*.hpp) -source_group(components\\compiler FILES ${COMPILER} ${COMPILER_HEADER}) +source_group(components\\compiler FILES ${COMPILER} ${COMPILER_HEADER}) file(GLOB INTERPRETER ${COMP_DIR}/interpreter/*.cpp) file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp) -source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) +source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} ${COMPILER} ${INTERPRETER} ${ESM}) @@ -128,7 +128,7 @@ source_group(libs\\openengine FILES ${OENGINE_ALL}) set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) set(OPENMW_LIBS_HEADER) - + # Platform specific if (WIN32) set(PLATFORM_INCLUDE_DIR "platform") @@ -192,13 +192,13 @@ endif (CMAKE_COMPILER_IS_GNUCC) # Apple bundling if (APPLE) - set(MISC_FILES + set(MISC_FILES ${CMAKE_SOURCE_DIR}/files/openmw.cfg ${CMAKE_SOURCE_DIR}/files/mac/plugins.cfg ${CMAKE_SOURCE_DIR}/files/mac/ogre.cfg) -install(TARGETS openmw +install(TARGETS openmw BUNDLE DESTINATION . - RUNTIME DESTINATION ../MacOS + RUNTIME DESTINATION ../MacOS COMPONENT Runtime) install(FILES ${MISC_FILES} DESTINATION ../MacOS) set(CPACK_GENERATOR "Bundle") @@ -225,4 +225,4 @@ if (BUILD_ESMTOOL) add_subdirectory( apps/esmtool ) endif() -add_subdirectory( apps/soundtest ) +add_subdirectory( apps/soundtest ) From ebcbff255ec23e3e9a684828e91c7fee613ad2df Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 19:38:58 +0200 Subject: [PATCH 11/25] Changed how avcodec/avformat (ffmpeg) is included --- CMakeLists.txt | 3 +++ libs/mangle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c62680d37..4a0a945f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,7 @@ if (USE_AUDIERE) ${LIBDIR}/mangle/sound/sources/audiere_source.cpp ${LIBDIR}/mangle/stream/clients/audiere_file.cpp) find_package(Audiere REQUIRED) + set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY}) add_definitions(-DOPENMW_USE_AUDIERE) endif (USE_AUDIERE) @@ -112,6 +113,7 @@ if (USE_FFMPEG) set(MANGLE_SOUND_OUTPUT ${LIBDIR}/mangle/sound/sources/ffmpeg_source.cpp) find_package(FFMPEG REQUIRED) + set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) add_definitions(-DOPENMW_USE_FFMPEG) endif (USE_FFMPEG) @@ -148,6 +150,7 @@ include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${ICONV_INCLUDE_DIR} + ${SOUND_INPUT_INCLUDES} ${PLATFORM_INCLUDE_DIR} ${CMAKE_HOME_DIRECTORY}/extern/caelum/include ${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include diff --git a/libs/mangle b/libs/mangle index 160e8655d..dc0c026ce 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit 160e8655d2503ad93992200d6d131186ede22aa3 +Subproject commit dc0c026ce054a96cdd4093237031ca63048a7393 From 912c8b1f2d23055e43f1c11200e57d6b33f72cd5 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 22:30:22 +0200 Subject: [PATCH 12/25] Added mpg123 file reader --- CMakeLists.txt | 17 +++++++--- apps/openmw/CMakeLists.txt | 5 +++ apps/openmw/mwsound/soundmanager.cpp | 5 +++ apps/soundtest/CMakeLists.txt | 3 ++ apps/soundtest/main.cpp | 5 +++ cmake/FindMPG123.cmake | 47 ++++++++++++++++++++++++++++ libs/mangle | 2 +- 7 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 cmake/FindMPG123.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a0a945f9..c7edb1072 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,8 @@ project(OpenMW) # Sound source selection option(USE_AUDIERE "use Audiere for sound" OFF) -option(USE_FFMPEG "use ffmpeg for sound" ON) +option(USE_FFMPEG "use ffmpeg for sound" OFF) +option(USE_MPG123 "use mpg123 for sound" ON) # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) @@ -106,7 +107,7 @@ if (USE_AUDIERE) find_package(Audiere REQUIRED) set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY}) - add_definitions(-DOPENMW_USE_AUDIERE) + set(SOUND_DEFINE -DOPENMW_USE_AUDIERE) endif (USE_AUDIERE) if (USE_FFMPEG) @@ -115,9 +116,18 @@ if (USE_FFMPEG) find_package(FFMPEG REQUIRED) set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) - add_definitions(-DOPENMW_USE_FFMPEG) + set(SOUND_DEFINE -DOPENMW_USE_FFMPEG) endif (USE_FFMPEG) +if (USE_MPG123) + set(MANGLE_SOUND_OUTPUT + ${LIBDIR}/mangle/sound/sources/mpg123_source.cpp) + find_package(MPG123 REQUIRED) + set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR}) + set(SOUND_INPUT_LIBRARY ${MPG123_LIBRARY}) + set(SOUND_DEFINE -DOPENMW_USE_MPG123) +endif (USE_MPG123) + set(OENGINE_SOUND # Mangle and OEngine sound files are sort of intertwined, so put # them together here @@ -150,7 +160,6 @@ include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${ICONV_INCLUDE_DIR} - ${SOUND_INPUT_INCLUDES} ${PLATFORM_INCLUDE_DIR} ${CMAKE_HOME_DIRECTORY}/extern/caelum/include ${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a4a6f6c27..87cc31954 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -179,6 +179,11 @@ add_executable(openmw ${APPLE_BUNDLE_RESOURCES} ) +# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING +# when we change the backend. +include_directories(${SOUND_INPUT_INCLUDES}) +add_definitions(${SOUND_DEFINE}) + target_link_libraries(openmw ${OGRE_LIBRARIES} ${OIS_LIBRARIES} diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 1754fdf28..28b4ef6ca 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -18,6 +18,11 @@ #define SOUND_FACTORY OpenAL_FFMpeg_Factory #endif +#ifdef OPENMW_USE_MPG123 +#include +#define SOUND_FACTORY OpenAL_Mpg123_Factory +#endif + using namespace Mangle::Sound; typedef OEngine::Sound::SoundManager OEManager; typedef OEngine::Sound::SoundManagerPtr OEManagerPtr; diff --git a/apps/soundtest/CMakeLists.txt b/apps/soundtest/CMakeLists.txt index 71c870e04..b7ff04039 100644 --- a/apps/soundtest/CMakeLists.txt +++ b/apps/soundtest/CMakeLists.txt @@ -5,6 +5,9 @@ project(SoundTest) # Main executable add_executable(sound_test main.cpp ${OENGINE_SOUND}) +include_directories(${SOUND_INPUT_INCLUDES}) +add_definitions(${SOUND_DEFINE}) + target_link_libraries(sound_test ${OPENAL_LIBRARY} ${SOUND_INPUT_LIBRARY} diff --git a/apps/soundtest/main.cpp b/apps/soundtest/main.cpp index 1e88020e1..dde76d9bd 100644 --- a/apps/soundtest/main.cpp +++ b/apps/soundtest/main.cpp @@ -18,6 +18,11 @@ AudiereLoader loader; FFMpegLoader loader; #endif +#ifdef OPENMW_USE_MPG123 +#include +Mpg123Loader loader; +#endif + OpenAL_Factory openal; void play(const char* name) diff --git a/cmake/FindMPG123.cmake b/cmake/FindMPG123.cmake new file mode 100644 index 000000000..51e562c91 --- /dev/null +++ b/cmake/FindMPG123.cmake @@ -0,0 +1,47 @@ +# Locate MPG123 +# This module defines +# MPG123_LIBRARY +# MPG123_FOUND, if false, do not try to link to Mpg123 +# MPG123_INCLUDE_DIR, where to find the headers +# +# Created by Nicolay Korslund for OpenMW (http://openmw.com) +# +# Ripped off from other sources. In fact, this file is so generic (I +# just did a search and replace on another file) that I wonder why the +# CMake guys haven't wrapped this entire thing in a single +# function. Do we really need to repeat this stuff for every single +# library when they all work the same? + +FIND_PATH(MPG123_INCLUDE_DIR mpg123.h + HINTS + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +FIND_LIBRARY(MPG123_LIBRARY + NAMES mpg123 + HINTS + PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt +) + +SET(MPG123_FOUND "NO") +IF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) + SET(MPG123_FOUND "YES") +ENDIF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) + diff --git a/libs/mangle b/libs/mangle index dc0c026ce..5b8e8d6b4 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit dc0c026ce054a96cdd4093237031ca63048a7393 +Subproject commit 5b8e8d6b48847cd99d14064e8c7a1115efdd4fed From 979ea4e607b74b7dee8f2610f74e6f2ddbf35464 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 23:01:23 +0200 Subject: [PATCH 13/25] Mangle update for const error --- libs/mangle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/mangle b/libs/mangle index 5b8e8d6b4..85fa6d392 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit 5b8e8d6b48847cd99d14064e8c7a1115efdd4fed +Subproject commit 85fa6d392319e72cbe359c55c7651faafcebdd2b From 05b3140740a3643c47031073c3db4f90a91a096a Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 13 Aug 2010 23:41:58 +0200 Subject: [PATCH 14/25] Enabled crosshairs --- apps/openmw/mwgui/mw_layouts.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/mw_layouts.hpp b/apps/openmw/mwgui/mw_layouts.hpp index 8f1d7affc..22e7b58fa 100644 --- a/apps/openmw/mwgui/mw_layouts.hpp +++ b/apps/openmw/mwgui/mw_layouts.hpp @@ -47,8 +47,8 @@ namespace MWGui getWidget(crosshair, "Crosshair"); - compass->setImageTexture("compass.dds"); - crosshair->setImageTexture("target.dds"); + compass->setImageTexture("textures\\compass.dds"); + crosshair->setImageTexture("textures\\target.dds"); // These are just demo values, you should replace these with // real calls from outside the class later. From 1d91ac9d9e29a20794625cae1271a3bf45cf2d42 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 07:54:51 +0200 Subject: [PATCH 15/25] sound manager interface enhancement --- apps/openmw/mwsound/soundmanager.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 88cf63e1b..2cefbd24f 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -20,31 +20,32 @@ namespace MWSound // enough as it is. struct SoundImpl; SoundImpl *mData; - + public: SoundManager(Ogre::Root*, Ogre::Camera*); ~SoundManager(); - + 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. - + bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? void streamMusic (const std::string& filename); ///< Play a soundifle /// \param filename name of a sound file in "Music/" in the data directory. - + void playSound (const std::string& soundId, float volume, float pitch); ///< Play a sound, independently of 3D-position - + void playSound3D (MWWorld::Ptr reference, const std::string& soundId, float volume, float pitch, bool loop); ///< Play a sound from an object - void stopSound3D (MWWorld::Ptr reference, const std::string& soundId); - ///< Stop the given object from playing the given sound. + void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = ""); + ///< Stop the given object from playing the given sound, If no soundId is given, + /// all sounds for this reference will stop. bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const; ///< Is the given sound currently playing on the given object? @@ -52,5 +53,3 @@ namespace MWSound } #endif - - From de2eeb4cde6c5e1e49202f07c6b3460228393781 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 09:20:47 +0200 Subject: [PATCH 16/25] integrated insertObject function into class hierarchy --- apps/openmw/mwrender/cellimp.cpp | 63 ++++++++++++++++++------------- apps/openmw/mwrender/cellimp.hpp | 12 +++--- apps/openmw/mwrender/interior.cpp | 9 +---- apps/openmw/mwrender/interior.hpp | 13 +++++-- apps/openmw/mwworld/class.cpp | 6 +++ apps/openmw/mwworld/class.hpp | 10 +++++ apps/openmw/mwworld/world.cpp | 3 +- 7 files changed, 71 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 121f17383..1f1034379 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -2,6 +2,9 @@ #include +#include "../mwworld/class.hpp" +#include "../mwworld/ptr.hpp" + using namespace MWRender; template @@ -59,37 +62,45 @@ void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef -void insertCellRefList (CellRenderImp& cellRender, const ESMS::ESMStore& store, T& cellRefList) +void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment, + T& cellRefList, ESMS::CellStore &cell) { - for(typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) + if (!cellRefList.list.empty()) { - if (it->mData.getCount()) - insertObj (cellRender, *it, store); + const MWWorld::Class& class_ = + MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); + + for (typename T::List::iterator it = cellRefList.list.begin(); + it != cellRefList.list.end(); it++) + { + if (it->mData.getCount()) + class_.insertObj (MWWorld::Ptr (&*it, &cell), cellRender, environment); + } } } -void CellRenderImp::insertCell(ESMS::CellStore &cell, const ESMS::ESMStore& store) +void CellRenderImp::insertCell(ESMS::CellStore &cell, + MWWorld::Environment& environment) { // Loop through all references in the cell - insertCellRefList (*this, store, cell.activators); - insertCellRefList (*this, store, cell.potions); - insertCellRefList (*this, store, cell.appas); - insertCellRefList (*this, store, cell.armors); - insertCellRefList (*this, store, cell.books); - insertCellRefList (*this, store, cell.clothes); - insertCellRefList (*this, store, cell.containers); - insertCellRefList (*this, store, cell.creatures); - insertCellRefList (*this, store, cell.doors); - insertCellRefList (*this, store, cell.ingreds); - // insertCellRefList (*this, store, cell.creatureLists); - // insertCellRefList (*this, store, cell.itemLists); - insertCellRefList (*this, store, cell.lights); - insertCellRefList (*this, store, cell.lockpicks); - insertCellRefList (*this, store, cell.miscItems); - insertCellRefList (*this, store, cell.npcs); - insertCellRefList (*this, store, cell.probes); - insertCellRefList (*this, store, cell.repairs); - insertCellRefList (*this, store, cell.statics); - insertCellRefList (*this, store, cell.weapons); + insertCellRefList (*this, environment, cell.activators, cell); + insertCellRefList (*this, environment, cell.potions, cell); + insertCellRefList (*this, environment, cell.appas, cell); + insertCellRefList (*this, environment, cell.armors, cell); + insertCellRefList (*this, environment, cell.books, cell); + insertCellRefList (*this, environment, cell.clothes, cell); + insertCellRefList (*this, environment, cell.containers, cell); + insertCellRefList (*this, environment, cell.creatures, cell); + insertCellRefList (*this, environment, cell.doors, cell); + insertCellRefList (*this, environment, cell.ingreds, cell); + // insertCellRefList (*this, environment, cell.creatureLists, cell); + // insertCellRefList (*this, environment, cell.itemLists, cell); + insertCellRefList (*this, environment, cell.lights, cell); + insertCellRefList (*this, environment, cell.lockpicks, cell); + insertCellRefList (*this, environment, cell.miscItems, cell); + insertCellRefList (*this, environment, cell.npcs, cell); + insertCellRefList (*this, environment, cell.probes, cell); + insertCellRefList (*this, environment, cell.repairs, cell); + insertCellRefList (*this, environment, cell.statics, cell); + insertCellRefList (*this, environment, cell.weapons, cell); } diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp index a4bb6868c..fadba79a5 100644 --- a/apps/openmw/mwrender/cellimp.hpp +++ b/apps/openmw/mwrender/cellimp.hpp @@ -12,9 +12,9 @@ namespace ESM class CellRef; } -namespace ESMS +namespace MWWorld { - class ESMStore; + class Environment; } namespace MWRender @@ -33,14 +33,14 @@ namespace MWRender /// insert a mesh related to the most recent insertBegin call. virtual void insertMesh(const std::string &mesh) = 0; - + /// insert a light related to the most recent insertBegin call. virtual void insertLight(float r, float g, float b, float radius) = 0; - + /// finish inserting a new reference and return a handle to it. virtual std::string insertEnd (bool Enable) = 0; - - void insertCell(ESMS::CellStore &cell, const ESMS::ESMStore& store); + + void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); }; } diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index d559a1216..1e88ecab4 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -174,19 +174,12 @@ void InteriorCellRender::setAmbientMode() void InteriorCellRender::show() { - // If already loaded, just make the cell visible. - if(base) - { - base->setVisible(true); - return; - } - base = scene.getRoot()->createChildSceneNode(); configureAmbient(); configureFog(); - insertCell(cell, store); + insertCell(cell, mEnvironment); } void InteriorCellRender::hide() diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 3d375f7f2..8d69ca061 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -3,7 +3,6 @@ #include "cell.hpp" #include "cellimp.hpp" -#include "components/esm_store/cell_store.hpp" #include "OgreColourValue.h" @@ -12,6 +11,11 @@ namespace Ogre class SceneNode; } +namespace MWWorld +{ + class Environment; +} + namespace MWRender { class MWScene; @@ -43,7 +47,7 @@ namespace MWRender static bool lightOutQuadInLin; ESMS::CellStore &cell; - const ESMS::ESMStore &store; + MWWorld::Environment &mEnvironment; MWScene &scene; /// The scene node that contains all objects belonging to this @@ -79,8 +83,9 @@ namespace MWRender public: - InteriorCellRender(ESMS::CellStore &_cell, const ESMS::ESMStore& _store, MWScene &_scene) - : cell(_cell), store(_store), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {} + InteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, + MWScene &_scene) + : cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {} virtual ~InteriorCellRender() { destroy(); } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 85e5140ea..b7498dcdd 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -14,6 +14,12 @@ namespace MWWorld Class::~Class() {} + void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + + } + MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 28d96d69f..83269957a 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -10,6 +10,11 @@ #include "containerstore.hpp" #include "refdata.hpp" +namespace MWRender +{ + class CellRenderImp; +} + namespace MWMechanics { struct CreatureStats; @@ -18,6 +23,7 @@ namespace MWMechanics namespace MWWorld { class Ptr; + class Environment; /// \brief Base class for referenceable esm records class Class @@ -36,6 +42,10 @@ namespace MWWorld virtual ~Class(); + virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering (default implementation: don't render anything). + virtual std::string getName (const Ptr& ptr) const = 0; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c8230f5a8..823cb2528 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -537,6 +537,7 @@ namespace MWWorld active->second->destroy(); delete active->second; mActiveCells.erase (active); + // TODO remove sounds } // register local scripts @@ -551,7 +552,7 @@ namespace MWWorld // This connects the cell data with the rendering scene. std::pair result = mActiveCells.insert (std::make_pair (cell, - new MWRender::InteriorCellRender (*cell, mStore, mScene))); + new MWRender::InteriorCellRender (*cell, mEnvironment, mScene))); if (result.second) { From 0a8d0fed402aa6c7e6c9421bc3c291f7a864e1d2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 09:26:00 +0200 Subject: [PATCH 17/25] added cell-wide stopSound function --- apps/openmw/mwsound/soundmanager.cpp | 9 +++++++-- apps/openmw/mwsound/soundmanager.hpp | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 28b4ef6ca..b6f88daa1 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -104,7 +104,7 @@ namespace MWSound // Play the sound and tell it to stream, if possible. mData->mgr->play(filename)->setStreaming(true); } - + void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { } @@ -120,9 +120,14 @@ namespace MWSound { } + void stopSound (MWWorld::Ptr::CellStore *cell) + { + // Note to Nico: You can get the cell of a Ptr via the getCell function. Just iterate over all + // sounds and remove those with matching cell. + } + bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const { return false; } } - diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 2cefbd24f..9ea86fea8 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -47,6 +47,9 @@ namespace MWSound ///< Stop the given object from playing the given sound, If no soundId is given, /// all sounds for this reference will stop. + void stopSound (MWWorld::Ptr::CellStore *cell); + ///< Stop all sounds for the given cell. + bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const; ///< Is the given sound currently playing on the given object? }; From 4649d7fa4174958f5907d61520d490b0c3428f21 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 09:29:38 +0200 Subject: [PATCH 18/25] stop sounds on cell change --- apps/openmw/mwsound/soundmanager.cpp | 2 +- apps/openmw/mwworld/world.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b6f88daa1..20b365b37 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -120,7 +120,7 @@ namespace MWSound { } - void stopSound (MWWorld::Ptr::CellStore *cell) + void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) { // Note to Nico: You can get the cell of a Ptr via the getCell function. Just iterate over all // sounds and remove those with matching cell. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 823cb2528..620751f61 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -11,6 +11,8 @@ #include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwsound/soundmanager.hpp" + #include "ptr.hpp" #include "environment.hpp" @@ -535,9 +537,9 @@ namespace MWWorld { mEnvironment.mMechanicsManager->dropActors (active->first); active->second->destroy(); + mEnvironment.mSoundManager->stopSound (active->first); delete active->second; mActiveCells.erase (active); - // TODO remove sounds } // register local scripts From ab1510fd5ec53ec3f50b376fafc576da78e36d13 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 09:30:43 +0200 Subject: [PATCH 19/25] fixed previous commit --- apps/openmw/mwsound/soundmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b6f88daa1..20b365b37 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -120,7 +120,7 @@ namespace MWSound { } - void stopSound (MWWorld::Ptr::CellStore *cell) + void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) { // Note to Nico: You can get the cell of a Ptr via the getCell function. Just iterate over all // sounds and remove those with matching cell. From 967f85875d772fb215d27e121f4bb73979cef9bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 10:02:54 +0200 Subject: [PATCH 20/25] reimplemented class-dependend rendering code in MWClass --- apps/openmw/mwclass/activator.cpp | 18 ++++++++++ apps/openmw/mwclass/activator.hpp | 4 +++ apps/openmw/mwclass/apparatus.cpp | 18 ++++++++++ apps/openmw/mwclass/apparatus.hpp | 4 +++ apps/openmw/mwclass/armor.cpp | 18 ++++++++++ apps/openmw/mwclass/armor.hpp | 4 +++ apps/openmw/mwclass/book.cpp | 18 ++++++++++ apps/openmw/mwclass/book.hpp | 4 +++ apps/openmw/mwclass/clothing.cpp | 18 ++++++++++ apps/openmw/mwclass/clothing.hpp | 4 +++ apps/openmw/mwclass/container.cpp | 18 ++++++++++ apps/openmw/mwclass/container.hpp | 4 +++ apps/openmw/mwclass/creature.cpp | 18 ++++++++++ apps/openmw/mwclass/creature.hpp | 4 +++ apps/openmw/mwclass/door.cpp | 18 ++++++++++ apps/openmw/mwclass/door.hpp | 4 +++ apps/openmw/mwclass/ingredient.cpp | 18 ++++++++++ apps/openmw/mwclass/ingredient.hpp | 4 +++ apps/openmw/mwclass/light.cpp | 28 +++++++++++++++ apps/openmw/mwclass/light.hpp | 4 +++ apps/openmw/mwclass/lockpick.cpp | 18 ++++++++++ apps/openmw/mwclass/lockpick.hpp | 4 +++ apps/openmw/mwclass/misc.cpp | 18 ++++++++++ apps/openmw/mwclass/misc.hpp | 4 +++ apps/openmw/mwclass/npc.cpp | 35 +++++++++++++++++- apps/openmw/mwclass/npc.hpp | 4 +++ apps/openmw/mwclass/potion.cpp | 18 ++++++++++ apps/openmw/mwclass/potion.hpp | 4 +++ apps/openmw/mwclass/probe.cpp | 18 ++++++++++ apps/openmw/mwclass/probe.hpp | 4 +++ apps/openmw/mwclass/repair.cpp | 18 ++++++++++ apps/openmw/mwclass/repair.hpp | 4 +++ apps/openmw/mwclass/static.cpp | 20 +++++++++++ apps/openmw/mwclass/static.hpp | 4 +++ apps/openmw/mwclass/weapon.cpp | 18 ++++++++++ apps/openmw/mwclass/weapon.hpp | 4 +++ apps/openmw/mwrender/cellimp.cpp | 58 ++---------------------------- 37 files changed, 426 insertions(+), 57 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 3cdc1f850..69a510803 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -7,8 +7,26 @@ #include "../mwworld/ptr.hpp" +#include "../mwrender/cellimp.hpp" + namespace MWClass { + void Activator::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Activator::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 66821a7c5..3b48796ac 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 4b94d78d1..007b2ca77 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Apparatus::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Apparatus::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 4a514c94d..c2e6e25e1 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index f4236b5f6..5c06077b2 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Armor::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Armor::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 217a74a76..040342a69 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 3bea7d5b9..179a060c6 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Book::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Book::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 3f15e2278..70d1bca3b 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index c0e43bc3e..c3bbfa9f0 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Clothing::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Clothing::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index ea358be68..fb88e25df 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 0cc516308..9c1ed7a89 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -7,8 +7,26 @@ #include "../mwworld/ptr.hpp" +#include "../mwrender/cellimp.hpp" + namespace MWClass { + void Container::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Container::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index baeac23c7..de54a9e68 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8525e9142..86adfb71a 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -8,8 +8,26 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwrender/cellimp.hpp" + namespace MWClass { + void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Creature::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index e964a7708..18771491e 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 2c4bd3562..6fd8f996c 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -13,8 +13,26 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwrender/cellimp.hpp" + namespace MWClass { + void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Door::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index fa3b6d657..b6bf8808e 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 9162384af..29d66d012 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Ingredient::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Ingredient::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index d742fae8b..8b781ba2f 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 7cb363bf8..73ef69dc5 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -9,10 +9,38 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Light::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + + cellRender.insertMesh ("meshes\\" + model); + + // Extract the color and convert to floating point + const int color = ref->base->data.color; + const float r = ((color >> 0) & 0xFF) / 255.0f; + const float g = ((color >> 8) & 0xFF) / 255.0f; + const float b = ((color >> 16) & 0xFF) / 255.0f; + const float radius = float (ref->base->data.radius); + cellRender.insertLight (r, g, b, radius); + + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Light::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 6d08d557c..9ac5c586b 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index ab1969480..c87d1e128 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Lockpick::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Lockpick::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index e15d9daee..bb9866b8c 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index f29a0be1f..57dca3148 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Misc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Misc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 01542baed..0da1f0d3a 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 829b17e7e..09b589c67 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -7,9 +7,42 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwrender/cellimp.hpp" namespace MWClass { + void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + + std::string headID = ref->base->head; + + //get the part of the bodypart id which describes the race and the gender + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + std::string headModel = "meshes\\" + + environment.mWorld->getStore().bodyParts.find(headID)->model; + + cellRender.insertBegin (ref->ref); + cellRender.insertMesh (headModel); + + //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the + // right place + const ESM::BodyPart *bodyPart = + environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); + + if (bodyPart) + cellRender.insertMesh("meshes\\" + bodyPart->model); + + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + std::string Npc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -49,7 +82,7 @@ namespace MWClass const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); - } + } MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index a2dd6f470..af00ff198 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 0799b2031..3fe38542b 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Potion::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Potion::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 208c26c56..9bf3b34a8 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 08ec391a8..bc6c4ba19 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Probe::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Probe::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index c17d53dab..11399d2f6 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 9ed7f0e77..253569afe 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Repair::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Repair::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 52d045ebe..3da591e01 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index f2bc4f635..211d239c6 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -3,8 +3,28 @@ #include +#include "../mwworld/ptr.hpp" + +#include "../mwrender/cellimp.hpp" + namespace MWClass { + void Static::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Static::getName (const MWWorld::Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index fb8080182..abbf6cd5f 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index c292c32dd..5a941360a 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -8,10 +8,28 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwrender/cellimp.hpp" + #include "containerutil.hpp" namespace MWClass { + void Weapon::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + const std::string &model = ref->base->model; + if (!model.empty()) + { + cellRender.insertBegin (ref->ref); + cellRender.insertMesh ("meshes\\" + model); + ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + } + } + std::string Weapon::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 6bc96381c..d9c7653dd 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -9,6 +9,10 @@ namespace MWClass { public: + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const; + ///< Add reference into a cell for rendering + 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. diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 1f1034379..0b5e7c951 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -7,60 +7,6 @@ using namespace MWRender; -template -void insertObj(CellRenderImp& cellRender, T& liveRef, const ESMS::ESMStore& store) -{ - assert (liveRef.base != NULL); - const std::string &model = liveRef.base->model; - if(!model.empty()) - { - cellRender.insertBegin (liveRef.ref); - cellRender.insertMesh ("meshes\\" + model); - liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); - } -} - -template<> -void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef& liveRef, const ESMS::ESMStore& store) -{ - assert (liveRef.base != NULL); - const std::string &model = liveRef.base->model; - if(!model.empty()) - { - cellRender.insertBegin (liveRef.ref); - - cellRender.insertMesh ("meshes\\" + model); - - // Extract the color and convert to floating point - const int color = liveRef.base->data.color; - const float r = ((color >> 0) & 0xFF) / 255.0f; - const float g = ((color >> 8) & 0xFF) / 255.0f; - const float b = ((color >> 16) & 0xFF) / 255.0f; - const float radius = float(liveRef.base->data.radius); - cellRender.insertLight(r, g, b, radius); - - liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); - } -} - -template<> -void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef& liveRef, const ESMS::ESMStore& store) -{ - std::string headID = liveRef.base->head; - - //get the part of the bodypart id which describes the race and the gender - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - std::string headModel = "meshes\\" + store.bodyParts.find(headID)->model; - - cellRender.insertBegin(liveRef.ref); - cellRender.insertMesh(headModel); - - //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the right place - cellRender.insertMesh("meshes\\" + store.bodyParts.find(bodyRaceID + "chest")->model); - - liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); -} - template void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment, T& cellRefList, ESMS::CellStore &cell) @@ -93,8 +39,8 @@ void CellRenderImp::insertCell(ESMS::CellStore &cell, insertCellRefList (*this, environment, cell.creatures, cell); insertCellRefList (*this, environment, cell.doors, cell); insertCellRefList (*this, environment, cell.ingreds, cell); - // insertCellRefList (*this, environment, cell.creatureLists, cell); - // insertCellRefList (*this, environment, cell.itemLists, cell); + insertCellRefList (*this, environment, cell.creatureLists, cell); + insertCellRefList (*this, environment, cell.itemLists, cell); insertCellRefList (*this, environment, cell.lights, cell); insertCellRefList (*this, environment, cell.lockpicks, cell); insertCellRefList (*this, environment, cell.miscItems, cell); From d57c984517ecfcd745dc5eb5321e7485bfbd84f8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 11:27:13 +0200 Subject: [PATCH 21/25] added enable and disable functions to class hierarchy; fixed a bug regarding actors in cellings being actived --- apps/openmw/mwclass/creature.cpp | 13 +++++++++++++ apps/openmw/mwclass/creature.hpp | 6 ++++++ apps/openmw/mwclass/npc.cpp | 12 ++++++++++++ apps/openmw/mwclass/npc.hpp | 6 ++++++ apps/openmw/mwrender/cellimp.cpp | 6 +++++- apps/openmw/mwworld/class.cpp | 10 ++++++++++ apps/openmw/mwworld/class.hpp | 10 ++++++++++ apps/openmw/mwworld/world.cpp | 25 +++++++------------------ 8 files changed, 69 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 86adfb71a..8757c93fd 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -7,9 +7,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/cellimp.hpp" +#include "../mwmechanics/mechanicsmanager.hpp" + namespace MWClass { void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, @@ -28,6 +31,16 @@ namespace MWClass } } + void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + { + environment.mMechanicsManager->addActor (ptr); + } + + void Creature::disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + { + environment.mMechanicsManager->removeActor (ptr); + } + std::string Creature::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 18771491e..ec354a015 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -13,6 +13,12 @@ namespace MWClass MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + ///< Enable reference; only does the non-rendering part + + virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) 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. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 09b589c67..1aae8928d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -12,6 +12,8 @@ #include "../mwrender/cellimp.hpp" +#include "../mwmechanics/mechanicsmanager.hpp" + namespace MWClass { void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, @@ -43,6 +45,16 @@ namespace MWClass ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); } + void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + { + environment.mMechanicsManager->addActor (ptr); + } + + void Npc::disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + { + environment.mMechanicsManager->removeActor (ptr); + } + std::string Npc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index af00ff198..1bbf427de 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -13,6 +13,12 @@ namespace MWClass MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; + ///< Enable reference; only does the non-rendering part + + virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) 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. diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 0b5e7c951..d1e1ec8f9 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -20,7 +20,11 @@ void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environ it != cellRefList.list.end(); it++) { if (it->mData.getCount()) - class_.insertObj (MWWorld::Ptr (&*it, &cell), cellRender, environment); + { + MWWorld::Ptr ptr (&*it, &cell); + class_.insertObj (ptr, cellRender, environment); + class_.enable (ptr, environment); + } } } } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index b7498dcdd..386ba650e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -20,6 +20,16 @@ namespace MWWorld } + void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const + { + + } + + void Class::disable (const Ptr& ptr, MWWorld::Environment& environment) const + { + + } + MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 83269957a..d230605da 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -46,6 +46,16 @@ namespace MWWorld MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). + virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) 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; + ///< 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 std::string getName (const Ptr& ptr) const = 0; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 620751f61..5744779da 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -15,6 +15,7 @@ #include "ptr.hpp" #include "environment.hpp" +#include "class.hpp" namespace { @@ -374,12 +375,8 @@ namespace MWWorld { render->enable (reference.getRefData().getHandle()); - if (mActiveCells.find (reference.getCell())!=mActiveCells.end() && - (reference.getType()==typeid (ESMS::LiveCellRef) || - reference.getType()==typeid (ESMS::LiveCellRef))) - { - mEnvironment.mMechanicsManager->addActor (reference); - } + if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) + Class::get (reference).enable (reference, mEnvironment); } } } @@ -394,12 +391,8 @@ namespace MWWorld { render->disable (reference.getRefData().getHandle()); - if (mActiveCells.find (reference.getCell())!=mActiveCells.end() && - (reference.getType()==typeid (ESMS::LiveCellRef) || - reference.getType()==typeid (ESMS::LiveCellRef))) - { - mEnvironment.mMechanicsManager->removeActor (reference); - } + if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) + Class::get (reference).disable (reference, mEnvironment); } } } @@ -626,12 +619,8 @@ namespace MWWorld render->deleteObject (ptr.getRefData().getHandle()); ptr.getRefData().setHandle (""); - if (mActiveCells.find (ptr.getCell())!=mActiveCells.end() && - (ptr.getType()==typeid (ESMS::LiveCellRef) || - ptr.getType()==typeid (ESMS::LiveCellRef))) - { - mEnvironment.mMechanicsManager->removeActor (ptr); - } + if (mActiveCells.find (ptr.getCell())!=mActiveCells.end()) + Class::get (ptr).disable (ptr, mEnvironment); } } } From 6f28bd9adff73cfdd91729adf7ff3be8528e700c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 14 Aug 2010 11:39:32 +0200 Subject: [PATCH 22/25] handle sounds when enabling/disabling --- apps/openmw/mwclass/light.cpp | 14 ++++++++++++++ apps/openmw/mwclass/light.hpp | 5 +++++ apps/openmw/mwworld/world.cpp | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 73ef69dc5..e57511452 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -8,9 +8,12 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/environment.hpp" #include "../mwrender/cellimp.hpp" +#include "../mwsound/soundmanager.hpp" + #include "containerutil.hpp" namespace MWClass @@ -41,6 +44,17 @@ namespace MWClass } } + void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (!ref->base->sound.empty()) + { + environment.mSoundManager->playSound3D (ptr, ref->base->sound, 1.0, 1.0, true); + } + } + std::string Light::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 9ac5c586b..5a1a15b1d 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -13,6 +13,11 @@ namespace MWClass MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) 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. + 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. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 5744779da..de69d7144 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -392,7 +392,10 @@ namespace MWWorld render->disable (reference.getRefData().getHandle()); if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) + { Class::get (reference).disable (reference, mEnvironment); + mEnvironment.mSoundManager->stopSound3D (reference); + } } } } @@ -620,7 +623,10 @@ namespace MWWorld ptr.getRefData().setHandle (""); if (mActiveCells.find (ptr.getCell())!=mActiveCells.end()) + { Class::get (ptr).disable (ptr, mEnvironment); + mEnvironment.mSoundManager->stopSound3D (ptr); + } } } } From 9875d74abf1aa264b1c8aafee9332b7f4de4f61e Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 14 Aug 2010 14:28:17 +0200 Subject: [PATCH 23/25] Implemented 3D sound placement. Sound management / lookup system not done yet. --- CMakeLists.txt | 4 +- apps/openmw/engine.cpp | 4 +- apps/openmw/mwsound/soundmanager.cpp | 149 ++++++++++++++++++++++----- apps/openmw/mwsound/soundmanager.hpp | 11 +- libs/mangle | 2 +- old_d_version/scene/gamesettings.d | 47 --------- old_d_version/scene/soundlist.d | 96 ----------------- 7 files changed, 139 insertions(+), 174 deletions(-) delete mode 100644 old_d_version/scene/gamesettings.d delete mode 100644 old_d_version/scene/soundlist.d diff --git a/CMakeLists.txt b/CMakeLists.txt index c7edb1072..d4b021916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ project(OpenMW) # Sound source selection -option(USE_AUDIERE "use Audiere for sound" OFF) +option(USE_AUDIERE "use Audiere for sound" ON) option(USE_FFMPEG "use ffmpeg for sound" OFF) -option(USE_MPG123 "use mpg123 for sound" ON) +option(USE_MPG123 "use mpg123 for sound" OFF) # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b90c1d0a5..a77ee925e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -234,7 +234,9 @@ void OMW::Engine::go() // Create sound system mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), - mOgre.getCamera()); + mOgre.getCamera(), + mEnvironment.mWorld->getStore(), + (mDataDir / "Sound").file_string()); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 20b365b37..b5a7a84fe 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -1,12 +1,20 @@ #include "soundmanager.hpp" +#include +using namespace std; + #include #include #include -/* Set up the sound manager to use Audiere of FFMPEG for input. The - OPENMW_USE_x macros are set in CMakeLists.txt. +#include +#include + +#include + +/* Set up the sound manager to use Audiere, FFMPEG or MPG123 for + input. The OPENMW_USE_x macros are set in CMakeLists.txt. */ #ifdef OPENMW_USE_AUDIERE #include @@ -36,13 +44,14 @@ typedef OEngine::Sound::SoundManagerPtr OEManagerPtr; frame is expensive, so there should be a special flag for sounds that need to track their attached object. */ -static void setPos(SoundPtr snd, const MWWorld::Ptr ref) +static void setPos(SoundPtr &snd, const MWWorld::Ptr ref) { // Get sound position from the reference const float *pos = ref.getCellRef().pos.pos; - // Move the sound. Might need to convert coordinates, test. - snd->setPos(pos[0], pos[1], pos[2]); + // Move the sound, converting from MW coordinates to Ogre + // coordinates. + snd->setPos(pos[0], pos[2], -pos[1]); } namespace MWSound @@ -64,19 +73,89 @@ namespace MWSound */ Mangle::Sound::OgreListenerMover cameraTracker; - SoundImpl() + const ESMS::ESMStore &store; + std::string dir; + + SoundImpl(Ogre::Root *root, Ogre::Camera *camera, + const ESMS::ESMStore &str, + const std::string &soundDir) : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) , updater(mgr) , cameraTracker(mgr) - {} + , store(str) + { + // Attach the camera to the camera tracker + cameraTracker.followCamera(camera); + + // Tell Ogre to update the sound system each frame + root->addFrameListener(&updater); + + dir = soundDir + "/"; + } + + // Convert a soundId to file name, and modify the volume + // according to the sounds local volume setting, minRange and + // maxRange. + std::string lookup(const std::string &soundId, + float &volume, float &min, float &max) + { + const ESM::Sound *snd = store.sounds.search(soundId); + if(snd == NULL) return ""; + + volume *= snd->data.volume / 255.0; + // These factors are not very fine tuned. + min = snd->data.minRange * 4; + max = snd->data.maxRange * 1000; + std::string file = dir + snd->sound; + std::replace(file.begin(), file.end(), '\\', '/'); + return file; + } + + // Add a sound to the list and play it + void add(const std::string &file, + MWWorld::Ptr reference, + const std::string &id, + float volume, float pitch, + float min, float max, + bool loop) + { + SoundPtr snd = mgr->load(file); + snd->setRepeat(loop); + snd->setVolume(volume); + snd->setPitch(pitch); + snd->setRange(min,max); + setPos(snd, reference); + snd->play(); + } + + // Stop a sound and remove it from the list. If id="" then + // remove the entire object and stop all its sounds. + void remove(MWWorld::Ptr reference, const std::string &id = "") + { + } + + bool isPlaying(MWWorld::Ptr reference, const std::string &id) const + { + return true; + } + + void removeCell(const MWWorld::Ptr::CellStore *cell) + { + // Note to Nico: You can get the cell of a Ptr via the getCell + // function. Just iterate over all sounds and remove those + // with matching cell. + } + + void updatePositions(MWWorld::Ptr reference) + { + } }; - SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera) + SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, + const ESMS::ESMStore &store, + const std::string &soundDir) { - mData = new SoundImpl; - - // Attach the camera to the camera tracker - mData->cameraTracker.followCamera(camera); + mData = new SoundImpl(root, camera, store, soundDir); } SoundManager::~SoundManager() @@ -86,48 +165,66 @@ namespace MWSound void SoundManager::say (MWWorld::Ptr reference, const std::string& filename) { - // Play the sound at the correct position - SoundPtr snd = mData->mgr->play(filename); - setPos(snd, reference); - // TODO: We need to attach it to the reference somehow. A weak - // pointer is probably the best bet + // The range values are not tested + mData->add(filename, reference, "_say_sound", 1, 1, 100, 10000, false); } bool SoundManager::sayDone (MWWorld::Ptr reference) const { - return true; - // TODO: Ask the reference to check its attached 'say' sound. + return !mData->isPlaying(reference, "_say_sound"); } void SoundManager::streamMusic (const std::string& filename) { - // Play the sound and tell it to stream, if possible. - mData->mgr->play(filename)->setStreaming(true); + // Play the sound and tell it to stream, if possible. TODO: + // Store the reference, the jukebox will need to check status, + // control volume etc. + SoundPtr music = mData->mgr->play(filename); + music->setStreaming(true); + music->setVolume(0.6); } void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { + // Play and forget + float min, max; + const std::string &file = mData->lookup(soundId, volume, min, max); + if(file != "") + { + SoundPtr snd = mData->mgr->play(file); + snd->setVolume(volume); + snd->setRange(min,max); + snd->setPitch(pitch); + } } void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId, float volume, float pitch, bool loop) { - // Not implemented - need both a way to find sounds by id and - // a way to attach them to the reference + // Look up the sound in the ESM data + float min, max; + const std::string &file = mData->lookup(soundId, volume, min, max); + if(file != "") + mData->add(file, reference, soundId, volume, pitch, min, max, loop); } void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId) { + mData->remove(reference, soundId); } void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) { - // Note to Nico: You can get the cell of a Ptr via the getCell function. Just iterate over all - // sounds and remove those with matching cell. + mData->removeCell(cell); } bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const { - return false; + return mData->isPlaying(reference, soundId); + } + + void SoundManager::updateObject(MWWorld::Ptr reference) + { + mData->updatePositions(reference); } } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 9ea86fea8..9b4745203 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -12,6 +12,11 @@ namespace Ogre class Camera; } +namespace ESMS +{ + struct ESMStore; +} + namespace MWSound { class SoundManager @@ -22,7 +27,8 @@ namespace MWSound SoundImpl *mData; public: - SoundManager(Ogre::Root*, Ogre::Camera*); + SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, + const std::string &soundDir); ~SoundManager(); void say (MWWorld::Ptr reference, const std::string& filename); @@ -52,6 +58,9 @@ namespace MWSound bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const; ///< Is the given sound currently playing on the given object? + + void updateObject(MWWorld::Ptr reference); + ///< Update the position of all sounds connected to the given object. }; } diff --git a/libs/mangle b/libs/mangle index 85fa6d392..3db61c8bd 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit 85fa6d392319e72cbe359c55c7651faafcebdd2b +Subproject commit 3db61c8bdde65910e43a3a06b34738296960e9e8 diff --git a/old_d_version/scene/gamesettings.d b/old_d_version/scene/gamesettings.d deleted file mode 100644 index a07133fe3..000000000 --- a/old_d_version/scene/gamesettings.d +++ /dev/null @@ -1,47 +0,0 @@ -module scene.gamesettings; - -import monster.monster; -import esm.records : gameSettings; -import esm.defs : VarType; -import std.stdio; -import std.string; - -MonsterObject *gmstObj; - -void loadGameSettings() -{ - // Load the GameSettings Monster class, and get the singleton - // instance - MonsterClass mc = vm.load("GMST"); - gmstObj = mc.getSing(); - - foreach(a, b; gameSettings.names) - { - assert(a == b.id); - assert(a[0] == 'i' || a[0] == 'f' || a[0] == 's'); - - // There's three cases of variable names containing - // spaces. Since these are so seldom, it makes more sense to - // make special workarounds for them instead of searching every - // string. - char[] name = a; - if(name.length > 13 && (name[6] == ' ' || name[5] == ' ')) - { - name = name.replace(" ", "_"); - // Make sure we don't change the original string! - assert(name != a); - } - - if(!mc.sc.lookupName(name).isVar) - { - writefln("WARNING: GMST %s not supported!", name); - continue; - } - - if(b.type == VarType.Int) gmstObj.setInt(name, b.i); - else if(b.type == VarType.Float) gmstObj.setFloat(name, b.f); - // TODO: At some point we will probably translate strings into - // UTF32 at load time, so string8 will not be needed here. - else if(b.type == VarType.String) gmstObj.setString8(name, b.str); - } -} diff --git a/old_d_version/scene/soundlist.d b/old_d_version/scene/soundlist.d deleted file mode 100644 index bad47f2df..000000000 --- a/old_d_version/scene/soundlist.d +++ /dev/null @@ -1,96 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (soundlist.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module scene.soundlist; - -import esm.loadsoun; -import sound.audio; -import sound.sfx; - -SoundList soundScene; - -// Has a list over all sounds currently playing in the -// scene. Currently only holds static, looping sounds, mainly -// torches. Later I will have to decide what to do with play-once -// sounds. Do I bother to update their position, or do I assume that -// once it starts playing, it is short enough that it doesn't matter? -// The last option is probably not viable, since some sounds can be -// very long. -struct SoundList -{ - SoundInstance[] list; - - // Get a sound instance from a Sound struct - static SoundInstance getInstance(Sound *s, bool loop=false) - { - const distFactor = 40.0; // Just guessing, really. - - assert(!s.sound.isEmpty()); - - SoundInstance inst = s.sound.getInstance(); - inst.setParams(s.data.volume/255.0, - s.data.minRange*distFactor, - s.data.maxRange*distFactor, - loop); - return inst; - } - - SoundInstance *insert(Sound *snd, bool loop=false) - { - // For some reason, we get called with empty sound instances here - // if some files are missing, but not for others. Check into it - // later. - if(snd.sound.isEmpty) return null; - - // Reuse a dead instance if one exists - foreach(ref s; list) - { - if(s.owner == null) - { - s = getInstance(snd, loop); - return &s; - } - } - // Otherwise append a new one - list ~= getInstance(snd, loop); - return &list[$-1]; - } - - void update(float x, float y, float z, - float frontx, float fronty, float frontz, - float upx, float upy, float upz) - { - SoundInstance.setPlayerPos(x,y,z,frontx,fronty,frontz,upx,upy,upz); - foreach(ref s; list) - if(s.owner) s.updateSound(); - } - - void kill() - { - foreach(ref s; list) - { - if(s.owner) s.kill(); - } - list = null; - } -} From dbd42386da316a7dcbd9495c7233d4b175e6135f Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Sat, 14 Aug 2010 21:43:25 +0200 Subject: [PATCH 24/25] temporary try/catch around sound loading --- apps/openmw/mwsound/soundmanager.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b5a7a84fe..95b013568 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -119,13 +119,20 @@ namespace MWSound float min, float max, bool loop) { - SoundPtr snd = mgr->load(file); - snd->setRepeat(loop); - snd->setVolume(volume); - snd->setPitch(pitch); - snd->setRange(min,max); - setPos(snd, reference); - snd->play(); + try + { + SoundPtr snd = mgr->load(file); + snd->setRepeat(loop); + snd->setVolume(volume); + snd->setPitch(pitch); + snd->setRange(min,max); + setPos(snd, reference); + snd->play(); + } + catch(...) + { + cout << "Error loading " << file << ", skipping.\n"; + } } // Stop a sound and remove it from the list. If id="" then From 08289158d7ce0328ee23f8b2fb09020da8ac4e9e Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 16 Aug 2010 17:14:37 +0200 Subject: [PATCH 25/25] Added support for WAV files with libsndfile --- CMakeLists.txt | 16 ++++--- apps/openmw/mwsound/soundmanager.cpp | 15 ++++--- apps/soundtest/CMakeLists.txt | 14 ------ apps/soundtest/main.cpp | 65 ---------------------------- cmake/FindSNDFILE.cmake | 41 ++++++++++++++++++ libs/mangle | 2 +- 6 files changed, 59 insertions(+), 94 deletions(-) delete mode 100644 apps/soundtest/CMakeLists.txt delete mode 100644 apps/soundtest/main.cpp create mode 100644 cmake/FindSNDFILE.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d4b021916..32f4e483a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ project(OpenMW) # Sound source selection -option(USE_AUDIERE "use Audiere for sound" ON) +option(USE_AUDIERE "use Audiere for sound" OFF) option(USE_FFMPEG "use ffmpeg for sound" OFF) -option(USE_MPG123 "use mpg123 for sound" OFF) +option(USE_MPG123 "use mpg123 + libsndfile for sound" ON) # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) @@ -103,6 +103,7 @@ set(OENGINE_GUI if (USE_AUDIERE) set(MANGLE_SOUND_OUTPUT ${LIBDIR}/mangle/sound/sources/audiere_source.cpp + ${LIBDIR}/mangle/sound/sources/sample_reader.cpp ${LIBDIR}/mangle/stream/clients/audiere_file.cpp) find_package(Audiere REQUIRED) set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR}) @@ -121,10 +122,13 @@ endif (USE_FFMPEG) if (USE_MPG123) set(MANGLE_SOUND_OUTPUT - ${LIBDIR}/mangle/sound/sources/mpg123_source.cpp) + ${LIBDIR}/mangle/sound/sources/mpg123_source.cpp + ${LIBDIR}/mangle/sound/sources/libsndfile.cpp + ${LIBDIR}/mangle/sound/sources/sample_reader.cpp) find_package(MPG123 REQUIRED) - set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR}) - set(SOUND_INPUT_LIBRARY ${MPG123_LIBRARY}) + find_package(SNDFILE REQUIRED) + set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) + set(SOUND_INPUT_LIBRARY ${MPG123_LIBRARY} ${SNDFILE_LIBRARY}) set(SOUND_DEFINE -DOPENMW_USE_MPG123) endif (USE_MPG123) @@ -236,5 +240,3 @@ option(BUILD_ESMTOOL "build ESM inspector" ON) if (BUILD_ESMTOOL) add_subdirectory( apps/esmtool ) endif() - -add_subdirectory( apps/soundtest ) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 95b013568..03a118eda 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -13,8 +13,9 @@ using namespace std; #include -/* Set up the sound manager to use Audiere, FFMPEG or MPG123 for - input. The OPENMW_USE_x macros are set in CMakeLists.txt. +/* Set up the sound manager to use Audiere, FFMPEG or + MPG123/libsndfile for input. The OPENMW_USE_x macros are set in + CMakeLists.txt. */ #ifdef OPENMW_USE_AUDIERE #include @@ -27,8 +28,8 @@ using namespace std; #endif #ifdef OPENMW_USE_MPG123 -#include -#define SOUND_FACTORY OpenAL_Mpg123_Factory +#include +#define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory #endif using namespace Mangle::Sound; @@ -104,8 +105,8 @@ namespace MWSound volume *= snd->data.volume / 255.0; // These factors are not very fine tuned. - min = snd->data.minRange * 4; - max = snd->data.maxRange * 1000; + min = snd->data.minRange * 7; + max = snd->data.maxRange * 2000; std::string file = dir + snd->sound; std::replace(file.begin(), file.end(), '\\', '/'); return file; @@ -188,7 +189,7 @@ namespace MWSound // control volume etc. SoundPtr music = mData->mgr->play(filename); music->setStreaming(true); - music->setVolume(0.6); + music->setVolume(0.4); } void SoundManager::playSound (const std::string& soundId, float volume, float pitch) diff --git a/apps/soundtest/CMakeLists.txt b/apps/soundtest/CMakeLists.txt deleted file mode 100644 index b7ff04039..000000000 --- a/apps/soundtest/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -project(SoundTest) - -# local files - -# Main executable -add_executable(sound_test main.cpp ${OENGINE_SOUND}) - -include_directories(${SOUND_INPUT_INCLUDES}) -add_definitions(${SOUND_DEFINE}) - -target_link_libraries(sound_test - ${OPENAL_LIBRARY} - ${SOUND_INPUT_LIBRARY} -) diff --git a/apps/soundtest/main.cpp b/apps/soundtest/main.cpp deleted file mode 100644 index dde76d9bd..000000000 --- a/apps/soundtest/main.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include - -#include -#include -#include - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -#ifdef OPENMW_USE_AUDIERE -#include -AudiereLoader loader; -#endif - -#ifdef OPENMW_USE_FFMPEG -#include -FFMpegLoader loader; -#endif - -#ifdef OPENMW_USE_MPG123 -#include -Mpg123Loader loader; -#endif - -OpenAL_Factory openal; - -void play(const char* name) -{ - try - { - cout << "Opening " << name << "\n"; - SampleSourcePtr samples = loader.load(name); - cout << "Loading entire file into memory\n"; - StreamPtr buf(new BufferStream(samples)); - - // Recreate the stream as a sample source (we're only doing it - // this complicated to test each step individually) - int a,b,c; - samples->getInfo(&a,&b,&c); - samples.reset(new Stream2Samples(buf, a,b,c)); - - cout << "Creating OpenAL sound from data\n"; - SoundPtr snd = openal.loadRaw(samples); - cout << "Playing (abort with Ctrl-C)\n"; - snd->play(); - - while(snd->isPlaying()) - usleep(10000); - cout << "Done playing\n"; - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main(int argc, char** argv) -{ - if(argc==1) - cout << "Specify sound file (wav, mp3, ogg) on command line.\n"; - for(int i=1; i