diff --git a/CMakeLists.txt b/CMakeLists.txt index cd058c570..32f4e483a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ project(OpenMW) +# Sound source selection +option(USE_AUDIERE "use Audiere for sound" OFF) +option(USE_FFMPEG "use ffmpeg 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) @@ -9,17 +14,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 @@ -31,44 +36,47 @@ 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) 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 +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}) + ${COMPILER} ${INTERPRETER} ${ESM}) set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER} ${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${INTERPRETER_HEADER}) @@ -90,12 +98,53 @@ set(OENGINE_GUI ${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/manager.cpp ) -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI}) + +# Sound setup +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}) + set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY}) + set(SOUND_DEFINE -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_INCLUDES ${FFMPEG_INCLUDE_DIR}) + set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) + set(SOUND_DEFINE -DOPENMW_USE_FFMPEG) +endif (USE_FFMPEG) + +if (USE_MPG123) + set(MANGLE_SOUND_OUTPUT + ${LIBDIR}/mangle/sound/sources/mpg123_source.cpp + ${LIBDIR}/mangle/sound/sources/libsndfile.cpp + ${LIBDIR}/mangle/sound/sources/sample_reader.cpp) + find_package(MPG123 REQUIRED) + 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) + +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/outputs/openal_out.cpp + ${MANGLE_SOUND_OUTPUT} +) +set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND}) 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") @@ -110,6 +159,7 @@ 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) include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} @@ -158,13 +208,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") 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/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a43119c61..87cc31954 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -179,10 +179,17 @@ 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} ${Boost_LIBRARIES} + ${OPENAL_LIBRARY} + ${SOUND_INPUT_LIBRARY} ${ICONV_LIBRARIES} caelum MyGUIEngine diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b67bcd0ac..a77ee925e 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)); @@ -233,7 +233,10 @@ void OMW::Engine::go() mExtensions, mNewGame); // Create sound system - mEnvironment.mSoundManager = new MWSound::SoundManager; + mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), + mOgre.getCamera(), + mEnvironment.mWorld->getStore(), + (mDataDir / "Sound").file_string()); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, @@ -266,6 +269,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/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..8757c93fd 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -7,9 +7,40 @@ #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, + 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())); + } + } + + 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 e964a7708..ec354a015 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -9,6 +9,16 @@ 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 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/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..e57511452 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -8,11 +8,53 @@ #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 { + 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())); + } + } + + 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 6d08d557c..5a1a15b1d 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -9,6 +9,15 @@ 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 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/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..1aae8928d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -7,9 +7,54 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" + +#include "../mwrender/cellimp.hpp" + +#include "../mwmechanics/mechanicsmanager.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())); + } + + 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 = @@ -49,7 +94,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..1bbf427de 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -9,6 +9,16 @@ 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 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/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/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. diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 802d49385..d1e1ec8f9 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -2,91 +2,55 @@ #include -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); +#include "../mwworld/class.hpp" +#include "../mwworld/ptr.hpp" - 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); - - liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); -} +using namespace MWRender; template -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()) + { + MWWorld::Ptr ptr (&*it, &cell); + class_.insertObj (ptr, cellRender, environment); + class_.enable (ptr, 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/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..58554ef16 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); + 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); } }; @@ -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 bfe51686b..03a118eda 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -1,71 +1,238 @@ #include "soundmanager.hpp" -#include // TODO remove this line, once the real code is in place. +#include +using namespace std; -#include +#include +#include +#include + +#include +#include + +#include + +/* 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 +#define SOUND_FACTORY OpenAL_Audiere_Factory +#endif + +#ifdef OPENMW_USE_FFMPEG +#include +#define SOUND_FACTORY OpenAL_FFMpeg_Factory +#endif + +#ifdef OPENMW_USE_MPG123 +#include +#define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory +#endif + +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 + 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, const MWWorld::Ptr ref) +{ + // Get sound position from the reference + const float *pos = ref.getCellRef().pos.pos; + + // Move the sound, converting from MW coordinates to Ogre + // coordinates. + snd->setPos(pos[0], pos[2], -pos[1]); +} namespace MWSound { - void SoundManager::say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text, Interpreter::Context& context) + struct SoundManager::SoundImpl + { + /* 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; + + 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 * 7; + max = snd->data.maxRange * 2000; + 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) + { + 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 + // 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, + const ESMS::ESMStore &store, + const std::string &soundDir) + { + mData = new SoundImpl(root, camera, store, soundDir); + } + + SoundManager::~SoundManager() + { + delete mData; + } + + void SoundManager::say (MWWorld::Ptr reference, const std::string& filename) { - std::cout << "sound effect: " << reference.getRefData().getHandle() << " is speaking" << std::endl; - - context.messageBox (text); + // The range values are not tested + mData->add(filename, reference, "_say_sound", 1, 1, 100, 10000, false); } - bool SoundManager::sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const + bool SoundManager::sayDone (MWWorld::Ptr reference) const { - return false; + return !mData->isPlaying(reference, "_say_sound"); } - 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; + // 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.4); } - - 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 - << " at volume " << volume << ", at pitch " << pitch - << std::endl; + // 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, Interpreter::Context& context) + 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; - - mSounds[reference.getRefData().getHandle()] = soundId; + // 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, - Interpreter::Context& context) + void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId) { - std::cout - << "sound effect : stop playing sound " << soundId - << " from " << reference.getRefData().getHandle() << std::endl; - - mSounds[reference.getRefData().getHandle()] = ""; + mData->remove(reference, soundId); } - bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId, - Interpreter::Context& context) const + void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) { - std::map::const_iterator iter = - mSounds.find (reference.getRefData().getHandle()); - - if (iter==mSounds.end()) - return false; - - return iter->second==soundId; + mData->removeCell(cell); + } + + bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const + { + 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 5a79c0c27..9b4745203 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -6,63 +6,62 @@ #include "../mwworld/ptr.hpp" -namespace Interpreter +namespace Ogre { - class Context; + class Root; + class Camera; +} + +namespace ESMS +{ + struct ESMStore; } 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) - 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: - - void say (MWWorld::Ptr reference, const std::string& filename, - const std::string& text, Interpreter::Context& context); + SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, + const std::string &soundDir); + ~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. - /// \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); - ///< 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. + + void stopSound (MWWorld::Ptr::CellStore *cell); + ///< Stop all sounds for the given cell. - 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? + + void updateObject(MWWorld::Ptr reference); + ///< Update the position of all sounds connected to the given object. }; } #endif - - diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 85e5140ea..386ba650e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -14,6 +14,22 @@ namespace MWWorld Class::~Class() {} + void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, + MWWorld::Environment& environment) const + { + + } + + 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 28d96d69f..d230605da 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,20 @@ 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 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/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/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c8230f5a8..de69d7144 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -11,8 +11,11 @@ #include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwsound/soundmanager.hpp" + #include "ptr.hpp" #include "environment.hpp" +#include "class.hpp" namespace { @@ -372,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); } } } @@ -392,11 +391,10 @@ namespace MWWorld { render->disable (reference.getRefData().getHandle()); - if (mActiveCells.find (reference.getCell())!=mActiveCells.end() && - (reference.getType()==typeid (ESMS::LiveCellRef) || - reference.getType()==typeid (ESMS::LiveCellRef))) + if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) { - mEnvironment.mMechanicsManager->removeActor (reference); + Class::get (reference).disable (reference, mEnvironment); + mEnvironment.mSoundManager->stopSound3D (reference); } } } @@ -535,6 +533,7 @@ namespace MWWorld { mEnvironment.mMechanicsManager->dropActors (active->first); active->second->destroy(); + mEnvironment.mSoundManager->stopSound (active->first); delete active->second; mActiveCells.erase (active); } @@ -551,7 +550,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) { @@ -623,11 +622,10 @@ 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))) + if (mActiveCells.find (ptr.getCell())!=mActiveCells.end()) { - mEnvironment.mMechanicsManager->removeActor (ptr); + Class::get (ptr).disable (ptr, mEnvironment); + mEnvironment.mSoundManager->stopSound3D (ptr); } } } 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/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/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/cmake/FindSNDFILE.cmake b/cmake/FindSNDFILE.cmake new file mode 100644 index 000000000..5c7664b50 --- /dev/null +++ b/cmake/FindSNDFILE.cmake @@ -0,0 +1,41 @@ +# Locate SNDFILE +# This module defines +# SNDFILE_LIBRARY +# SNDFILE_FOUND, if false, do not try to link to Sndfile +# SNDFILE_INCLUDE_DIR, where to find the headers +# +# Created by Nicolay Korslund for OpenMW (http://openmw.com) + +FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h + HINTS + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +FIND_LIBRARY(SNDFILE_LIBRARY + NAMES sndfile + 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(SNDFILE_FOUND "NO") +IF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) + SET(SNDFILE_FOUND "YES") +ENDIF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) + 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; + } } - 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/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..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 @@ -97,41 +97,10 @@ struct NPC std::string name, model, race, cls, faction, script, hair, head; // body parts - void load(ESMReader &esm) - { - 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; + std::string mId; - esm.skipRecord(); - } + // Implementation moved to load_impl.cpp + void load(ESMReader &esm, const std::string& id); }; } #endif 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; diff --git a/libs/mangle b/libs/mangle index c7b179d65..c982f701c 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit c7b179d6546688208528c8eef681d42b7c1ec7be +Subproject commit c982f701cacdd2932bfdc22b168f54221a549b62 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 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; - } -}