Merge remote branch 'upstream/master'

actorid
Armin Preiml 15 years ago
commit 6a936100a7

@ -1,5 +1,10 @@
project(OpenMW) 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. # We probably support older versions than this.
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
@ -9,17 +14,17 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
# source directory: components # source directory: components
set(COMP_DIR ${CMAKE_SOURCE_DIR}/components) set(COMP_DIR ${CMAKE_SOURCE_DIR}/components)
set(BSA set(BSA
${COMP_DIR}/bsa/bsa_archive.cpp ${COMP_DIR}/bsa/bsa_archive.cpp
${COMP_DIR}/bsa/bsa_file.cpp) ${COMP_DIR}/bsa/bsa_file.cpp)
set(BSA_HEADER set(BSA_HEADER
${COMP_DIR}/bsa/bsa_archive.hpp ${COMP_DIR}/bsa/bsa_archive.hpp
${COMP_DIR}/bsa/bsa_file.hpp) ${COMP_DIR}/bsa/bsa_file.hpp)
source_group(components\\bsa FILES ${BSA} ${BSA_HEADER}) source_group(components\\bsa FILES ${BSA} ${BSA_HEADER})
set(NIF set(NIF
${COMP_DIR}/nif/nif_file.cpp) ${COMP_DIR}/nif/nif_file.cpp)
set(NIF_HEADER set(NIF_HEADER
${COMP_DIR}/nif/controlled.hpp ${COMP_DIR}/nif/controlled.hpp
${COMP_DIR}/nif/effect.hpp ${COMP_DIR}/nif/effect.hpp
${COMP_DIR}/nif/nif_types.hpp ${COMP_DIR}/nif/nif_types.hpp
@ -31,44 +36,47 @@ set(NIF_HEADER
${COMP_DIR}/nif/data.hpp ${COMP_DIR}/nif/data.hpp
${COMP_DIR}/nif/nif_file.hpp ${COMP_DIR}/nif/nif_file.hpp
${COMP_DIR}/nif/property.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) ${COMP_DIR}/nifogre/ogre_nif_loader.cpp)
set(NIFOGRE_HEADER set(NIFOGRE_HEADER
${COMP_DIR}/nifogre/ogre_nif_loader.hpp) ${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) ${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/cell_store.hpp
${COMP_DIR}/esm_store/reclists.hpp ${COMP_DIR}/esm_store/reclists.hpp
${COMP_DIR}/esm_store/store.hpp) ${COMP_DIR}/esm_store/store.hpp)
source_group(components\\esm_store FILES ${ESM_STORE} ${ESM_STORE_HEADER}) source_group(components\\esm_store FILES ${ESM_STORE} ${ESM_STORE_HEADER})
file(GLOB ESM_HEADER ${COMP_DIR}/esm/*.hpp) 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/stringops.cpp
${COMP_DIR}/misc/fileops.cpp) ${COMP_DIR}/misc/fileops.cpp)
set(MISC_HEADER set(MISC_HEADER
${COMP_DIR}/misc/fileops.hpp ${COMP_DIR}/misc/fileops.hpp
${COMP_DIR}/misc/slice_array.hpp ${COMP_DIR}/misc/slice_array.hpp
${COMP_DIR}/misc/stringops.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 ${COMP_DIR}/compiler/*.cpp)
file(GLOB COMPILER_HEADER ${COMP_DIR}/compiler/*.hpp) 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 ${COMP_DIR}/interpreter/*.cpp)
file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp) 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} 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} set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER}
${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER}
${INTERPRETER_HEADER}) ${INTERPRETER_HEADER})
@ -90,12 +98,53 @@ set(OENGINE_GUI
${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/events.cpp
${LIBDIR}/openengine/gui/manager.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}) source_group(libs\\openengine FILES ${OENGINE_ALL})
set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL})
set(OPENMW_LIBS_HEADER) set(OPENMW_LIBS_HEADER)
# Platform specific # Platform specific
if (WIN32) if (WIN32)
set(PLATFORM_INCLUDE_DIR "platform") 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(Boost REQUIRED COMPONENTS system filesystem program_options thread)
find_package(OIS REQUIRED) find_package(OIS REQUIRED)
find_package(Iconv REQUIRED) find_package(Iconv REQUIRED)
find_package(OpenAL REQUIRED)
include_directories("." include_directories("."
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre
${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
@ -158,13 +208,13 @@ endif (CMAKE_COMPILER_IS_GNUCC)
# Apple bundling # Apple bundling
if (APPLE) if (APPLE)
set(MISC_FILES set(MISC_FILES
${CMAKE_SOURCE_DIR}/files/openmw.cfg ${CMAKE_SOURCE_DIR}/files/openmw.cfg
${CMAKE_SOURCE_DIR}/files/mac/plugins.cfg ${CMAKE_SOURCE_DIR}/files/mac/plugins.cfg
${CMAKE_SOURCE_DIR}/files/mac/ogre.cfg) ${CMAKE_SOURCE_DIR}/files/mac/ogre.cfg)
install(TARGETS openmw install(TARGETS openmw
BUNDLE DESTINATION . BUNDLE DESTINATION .
RUNTIME DESTINATION ../MacOS RUNTIME DESTINATION ../MacOS
COMPONENT Runtime) COMPONENT Runtime)
install(FILES ${MISC_FILES} DESTINATION ../MacOS) install(FILES ${MISC_FILES} DESTINATION ../MacOS)
set(CPACK_GENERATOR "Bundle") set(CPACK_GENERATOR "Bundle")

@ -180,7 +180,7 @@ int main(int argc, char**argv)
case REC_CREA: case REC_CREA:
{ {
Creature b; Creature b;
b.load(esm); b.load(esm, id);
if(quiet) break; if(quiet) break;
cout << " Name: " << b.name << endl; cout << " Name: " << b.name << endl;
break; break;

@ -179,10 +179,17 @@ add_executable(openmw
${APPLE_BUNDLE_RESOURCES} ${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 target_link_libraries(openmw
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OIS_LIBRARIES} ${OIS_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY}
${ICONV_LIBRARIES} ${ICONV_LIBRARIES}
caelum caelum
MyGUIEngine MyGUIEngine

@ -38,7 +38,7 @@ void OMW::Engine::executeLocalScripts()
mEnvironment.mWorld->getLocalScripts().begin()); mEnvironment.mWorld->getLocalScripts().begin());
iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter) iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter)
{ {
if (!mIgnoreLocalPtr.isEmpty() && mIgnoreLocalPtr!=iter->second) if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second)
{ {
MWScript::InterpreterContext interpreterContext (mEnvironment, MWScript::InterpreterContext interpreterContext (mEnvironment,
&iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second)); &iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second));
@ -233,7 +233,10 @@ void OMW::Engine::go()
mExtensions, mNewGame); mExtensions, mNewGame);
// Create sound system // 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 // Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
@ -266,6 +269,18 @@ void OMW::Engine::go()
mOgre.getRoot()->addFrameListener (this); 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 // Start the main rendering loop
mOgre.start(); mOgre.start();

@ -7,8 +7,26 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass namespace MWClass
{ {
void Activator::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
ptr.get<ESM::Activator>();
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 std::string Activator::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Apparatus::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
ptr.get<ESM::Apparatus>();
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 std::string Apparatus::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Armor::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
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 std::string Armor::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Book::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
ptr.get<ESM::Book>();
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 std::string Book::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Clothing::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
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 std::string Clothing::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -7,8 +7,26 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass namespace MWClass
{ {
void Container::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
ptr.get<ESM::Container>();
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 std::string Container::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -7,9 +7,40 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp" #include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
ptr.get<ESM::Creature>();
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 std::string Creature::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =

@ -9,6 +9,16 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -13,8 +13,26 @@
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass namespace MWClass
{ {
void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
ptr.get<ESM::Door>();
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 std::string Door::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Ingredient::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
ptr.get<ESM::Ingredient>();
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 std::string Ingredient::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,11 +8,53 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwsound/soundmanager.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Light::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
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<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
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 std::string Light::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =

@ -9,6 +9,15 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Lockpick::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
ptr.get<ESM::Tool>();
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 std::string Lockpick::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Misc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Misc, MWWorld::RefData> *ref =
ptr.get<ESM::Misc>();
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 std::string Misc::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Misc, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Misc, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -7,9 +7,54 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp" #include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>();
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 std::string Npc::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
@ -49,7 +94,7 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr)); return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
} }
MWWorld::ContainerStore<MWWorld::RefData>& Npc::getContainerStore (const MWWorld::Ptr& ptr) MWWorld::ContainerStore<MWWorld::RefData>& Npc::getContainerStore (const MWWorld::Ptr& ptr)
const const

@ -9,6 +9,16 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Potion::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
ptr.get<ESM::Potion>();
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 std::string Potion::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Probe::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
ptr.get<ESM::Probe>();
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 std::string Probe::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Repair::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
ptr.get<ESM::Repair>();
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 std::string Repair::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -3,8 +3,28 @@
#include <components/esm/loadstat.hpp> #include <components/esm/loadstat.hpp>
#include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass namespace MWClass
{ {
void Static::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
ptr.get<ESM::Static>();
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 std::string Static::getName (const MWWorld::Ptr& ptr) const
{ {
return ""; return "";

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -8,10 +8,28 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp" #include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
void Weapon::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
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 std::string Weapon::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =

@ -9,6 +9,10 @@ namespace MWClass
{ {
public: 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -47,8 +47,8 @@ namespace MWGui
getWidget(crosshair, "Crosshair"); getWidget(crosshair, "Crosshair");
compass->setImageTexture("compass.dds"); compass->setImageTexture("textures\\compass.dds");
crosshair->setImageTexture("target.dds"); crosshair->setImageTexture("textures\\target.dds");
// These are just demo values, you should replace these with // These are just demo values, you should replace these with
// real calls from outside the class later. // real calls from outside the class later.

@ -2,91 +2,55 @@
#include <cassert> #include <cassert>
using namespace MWRender; #include "../mwworld/class.hpp"
#include "../mwworld/ptr.hpp"
template<typename T>
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<ESM::Light, MWWorld::RefData>& 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())); using namespace MWRender;
}
}
template<>
void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>& 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()));
}
template<typename T> template<typename T>
void insertCellRefList (CellRenderImp& cellRender, const ESMS::ESMStore& store, T& cellRefList) void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment,
T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
{ {
for(typename T::List::iterator it = cellRefList.list.begin(); if (!cellRefList.list.empty())
it != cellRefList.list.end(); it++)
{ {
if (it->mData.getCount()) const MWWorld::Class& class_ =
insertObj (cellRender, *it, store); 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<MWWorld::RefData> &cell, const ESMS::ESMStore& store) void CellRenderImp::insertCell(ESMS::CellStore<MWWorld::RefData> &cell,
MWWorld::Environment& environment)
{ {
// Loop through all references in the cell // Loop through all references in the cell
insertCellRefList (*this, store, cell.activators); insertCellRefList (*this, environment, cell.activators, cell);
insertCellRefList (*this, store, cell.potions); insertCellRefList (*this, environment, cell.potions, cell);
insertCellRefList (*this, store, cell.appas); insertCellRefList (*this, environment, cell.appas, cell);
insertCellRefList (*this, store, cell.armors); insertCellRefList (*this, environment, cell.armors, cell);
insertCellRefList (*this, store, cell.books); insertCellRefList (*this, environment, cell.books, cell);
insertCellRefList (*this, store, cell.clothes); insertCellRefList (*this, environment, cell.clothes, cell);
insertCellRefList (*this, store, cell.containers); insertCellRefList (*this, environment, cell.containers, cell);
insertCellRefList (*this, store, cell.creatures); insertCellRefList (*this, environment, cell.creatures, cell);
insertCellRefList (*this, store, cell.doors); insertCellRefList (*this, environment, cell.doors, cell);
insertCellRefList (*this, store, cell.ingreds); insertCellRefList (*this, environment, cell.ingreds, cell);
// insertCellRefList (*this, store, cell.creatureLists); insertCellRefList (*this, environment, cell.creatureLists, cell);
// insertCellRefList (*this, store, cell.itemLists); insertCellRefList (*this, environment, cell.itemLists, cell);
insertCellRefList (*this, store, cell.lights); insertCellRefList (*this, environment, cell.lights, cell);
insertCellRefList (*this, store, cell.lockpicks); insertCellRefList (*this, environment, cell.lockpicks, cell);
insertCellRefList (*this, store, cell.miscItems); insertCellRefList (*this, environment, cell.miscItems, cell);
insertCellRefList (*this, store, cell.npcs); insertCellRefList (*this, environment, cell.npcs, cell);
insertCellRefList (*this, store, cell.probes); insertCellRefList (*this, environment, cell.probes, cell);
insertCellRefList (*this, store, cell.repairs); insertCellRefList (*this, environment, cell.repairs, cell);
insertCellRefList (*this, store, cell.statics); insertCellRefList (*this, environment, cell.statics, cell);
insertCellRefList (*this, store, cell.weapons); insertCellRefList (*this, environment, cell.weapons, cell);
} }

@ -12,9 +12,9 @@ namespace ESM
class CellRef; class CellRef;
} }
namespace ESMS namespace MWWorld
{ {
class ESMStore; class Environment;
} }
namespace MWRender namespace MWRender
@ -33,14 +33,14 @@ namespace MWRender
/// insert a mesh related to the most recent insertBegin call. /// insert a mesh related to the most recent insertBegin call.
virtual void insertMesh(const std::string &mesh) = 0; virtual void insertMesh(const std::string &mesh) = 0;
/// insert a light related to the most recent insertBegin call. /// insert a light related to the most recent insertBegin call.
virtual void insertLight(float r, float g, float b, float radius) = 0; virtual void insertLight(float r, float g, float b, float radius) = 0;
/// finish inserting a new reference and return a handle to it. /// finish inserting a new reference and return a handle to it.
virtual std::string insertEnd (bool Enable) = 0; virtual std::string insertEnd (bool Enable) = 0;
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, const ESMS::ESMStore& store); void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
}; };
} }

@ -174,19 +174,12 @@ void InteriorCellRender::setAmbientMode()
void InteriorCellRender::show() void InteriorCellRender::show()
{ {
// If already loaded, just make the cell visible.
if(base)
{
base->setVisible(true);
return;
}
base = scene.getRoot()->createChildSceneNode(); base = scene.getRoot()->createChildSceneNode();
configureAmbient(); configureAmbient();
configureFog(); configureFog();
insertCell(cell, store); insertCell(cell, mEnvironment);
} }
void InteriorCellRender::hide() void InteriorCellRender::hide()

@ -3,7 +3,6 @@
#include "cell.hpp" #include "cell.hpp"
#include "cellimp.hpp" #include "cellimp.hpp"
#include "components/esm_store/cell_store.hpp"
#include "OgreColourValue.h" #include "OgreColourValue.h"
@ -12,6 +11,11 @@ namespace Ogre
class SceneNode; class SceneNode;
} }
namespace MWWorld
{
class Environment;
}
namespace MWRender namespace MWRender
{ {
class MWScene; class MWScene;
@ -43,7 +47,7 @@ namespace MWRender
static bool lightOutQuadInLin; static bool lightOutQuadInLin;
ESMS::CellStore<MWWorld::RefData> &cell; ESMS::CellStore<MWWorld::RefData> &cell;
const ESMS::ESMStore &store; MWWorld::Environment &mEnvironment;
MWScene &scene; MWScene &scene;
/// The scene node that contains all objects belonging to this /// The scene node that contains all objects belonging to this
@ -79,8 +83,9 @@ namespace MWRender
public: public:
InteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, const ESMS::ESMStore& _store, MWScene &_scene) InteriorCellRender(ESMS::CellStore<MWWorld::RefData> &_cell, MWWorld::Environment& environment,
: cell(_cell), store(_store), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {} MWScene &_scene)
: cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {}
virtual ~InteriorCellRender() { destroy(); } virtual ~InteriorCellRender() { destroy(); }

@ -51,6 +51,7 @@ namespace MWScript
virtual void setLocalFloat (int index, float value); virtual void setLocalFloat (int index, float value);
using Interpreter::Context::messageBox;
virtual void messageBox (const std::string& message, virtual void messageBox (const std::string& message,
const std::vector<std::string>& buttons); const std::vector<std::string>& buttons);

@ -25,15 +25,15 @@ namespace MWScript
{ {
MWScript::InterpreterContext& context MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext()); = static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string file = runtime.getStringLiteral (runtime[0].mInteger); std::string file = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
std::string text = runtime.getStringLiteral (runtime[0].mInteger); std::string text = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
context.getSoundManager().say (context.getReference(), file, text, context.getSoundManager().say (context.getReference(), file);
context); context.messageBox (text);
} }
}; };
@ -46,8 +46,7 @@ namespace MWScript
MWScript::InterpreterContext& context MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext()); = static_cast<MWScript::InterpreterContext&> (runtime.getContext());
runtime.push (context.getSoundManager().sayDone (context.getReference(), runtime.push (context.getSoundManager().sayDone (context.getReference()));
context));
} }
}; };
@ -63,7 +62,7 @@ namespace MWScript
std::string sound = runtime.getStringLiteral (runtime[0].mInteger); std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); 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); std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); 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; Interpreter::Type_Float pitch = runtime[0].mFloat;
runtime.pop(); runtime.pop();
context.getSoundManager().playSound (sound, volume, pitch, context); context.getSoundManager().playSound (sound, volume, pitch);
} }
}; };
@ -122,7 +121,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound, 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(); runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound, volume, 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); std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
context.getSoundManager().stopSound3D (context.getReference(), sound, context); context.getSoundManager().stopSound3D (context.getReference(), sound);
} }
}; };
@ -183,7 +182,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
runtime.push (context.getSoundManager().getSoundPlaying ( runtime.push (context.getSoundManager().getSoundPlaying (
context.getReference(), runtime.getStringLiteral (index), context)); context.getReference(), runtime.getStringLiteral (index)));
} }
}; };
@ -206,7 +205,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
context.getSoundManager().say (context.getWorld().getPtr (id, true), context.getSoundManager().say (context.getWorld().getPtr (id, true),
file, text, context); file);
} }
}; };
@ -223,7 +222,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
runtime.push (context.getSoundManager().sayDone ( runtime.push (context.getSoundManager().sayDone (
context.getWorld().getPtr (id, true), context)); context.getWorld().getPtr (id, true)));
} }
}; };
@ -247,7 +246,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
context.getSoundManager().playSound3D ( 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(); runtime.pop();
context.getSoundManager().playSound3D ( 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(); runtime.pop();
context.getSoundManager().stopSound3D ( 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 ( runtime.push (context.getSoundManager().getSoundPlaying (
context.getWorld().getPtr (id, true), context.getWorld().getPtr (id, true),
runtime.getStringLiteral (index), context)); runtime.getStringLiteral (index)));
} }
}; };

@ -1,71 +1,238 @@
#include "soundmanager.hpp" #include "soundmanager.hpp"
#include <iostream> // TODO remove this line, once the real code is in place. #include <iostream>
using namespace std;
#include <components/interpreter/context.hpp> #include <openengine/sound/sndmanager.hpp>
#include <mangle/sound/clients/ogre_listener_mover.hpp>
#include <mangle/sound/clients/ogre_output_updater.hpp>
#include <components/esm_store/store.hpp>
#include <algorithm>
#include <OgreRoot.h>
/* 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 <mangle/sound/filters/openal_audiere.hpp>
#define SOUND_FACTORY OpenAL_Audiere_Factory
#endif
#ifdef OPENMW_USE_FFMPEG
#include <mangle/sound/filters/openal_ffmpeg.hpp>
#define SOUND_FACTORY OpenAL_FFMpeg_Factory
#endif
#ifdef OPENMW_USE_MPG123
#include <mangle/sound/filters/openal_sndfile_mpg123.hpp>
#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 namespace MWSound
{ {
void SoundManager::say (MWWorld::Ptr reference, const std::string& filename, struct SoundManager::SoundImpl
const std::string& text, Interpreter::Context& context) {
/* 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; // The range values are not tested
mData->add(filename, reference, "_say_sound", 1, 1, 100, 10000, false);
context.messageBox (text);
} }
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, void SoundManager::playSound (const std::string& soundId, float volume, float pitch)
Interpreter::Context& context)
{ {
std::cout // Play and forget
<< "sound effect: playing sound " << soundId float min, max;
<< " at volume " << volume << ", at pitch " << pitch const std::string &file = mData->lookup(soundId, volume, min, max);
<< std::endl; 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, 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 // Look up the sound in the ESM data
<< "sound effect: playing sound " << soundId float min, max;
<< " from " << reference.getRefData().getHandle() const std::string &file = mData->lookup(soundId, volume, min, max);
<< " at volume " << volume << ", at pitch " << pitch if(file != "")
<< std::endl; mData->add(file, reference, soundId, volume, pitch, min, max, loop);
mSounds[reference.getRefData().getHandle()] = soundId;
} }
void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId, void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId)
Interpreter::Context& context)
{ {
std::cout mData->remove(reference, soundId);
<< "sound effect : stop playing sound " << soundId
<< " from " << reference.getRefData().getHandle() << std::endl;
mSounds[reference.getRefData().getHandle()] = "";
} }
bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId, void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell)
Interpreter::Context& context) const
{ {
std::map<std::string, std::string>::const_iterator iter = mData->removeCell(cell);
mSounds.find (reference.getRefData().getHandle()); }
if (iter==mSounds.end()) bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const
return false; {
return mData->isPlaying(reference, soundId);
return iter->second==soundId;
} }
}
void SoundManager::updateObject(MWWorld::Ptr reference)
{
mData->updatePositions(reference);
}
}

@ -6,63 +6,62 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
namespace Interpreter namespace Ogre
{ {
class Context; class Root;
class Camera;
}
namespace ESMS
{
struct ESMStore;
} }
namespace MWSound 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 class SoundManager
{ {
std::map<std::string, std::string> mSounds; // object, sound (for testing only) // Hide implementation details - engine.cpp is compiling
// enough as it is.
struct SoundImpl;
SoundImpl *mData;
public: public:
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
void say (MWWorld::Ptr reference, const std::string& filename, const std::string &soundDir);
const std::string& text, Interpreter::Context& context); ~SoundManager();
void say (MWWorld::Ptr reference, const std::string& filename);
///< Make an actor say some text. ///< Make an actor say some text.
/// \param filename name of a sound file in "Sound/Vo/" in the data directory. /// \param filename name of a sound file in "Sound/Vo/" in the data directory.
/// \param text Subtitle
bool sayDone (MWWorld::Ptr reference) const;
bool sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const;
///< Is actor not speaking? ///< Is actor not speaking?
void streamMusic (const std::string& filename, Interpreter::Context& context); void streamMusic (const std::string& filename);
///< Play a soundifle ///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory. /// \param filename name of a sound file in "Music/" in the data directory.
void playSound (const std::string& soundId, float volume, float pitch, void playSound (const std::string& soundId, float volume, float pitch);
Interpreter::Context& context);
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
void playSound3D (MWWorld::Ptr reference, const std::string& soundId, 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 ///< Play a sound from an object
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId, void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = "");
Interpreter::Context& context); ///< Stop the given object from playing the given sound, If no soundId is given,
///< Stop the given object from playing the given sound. /// 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, bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const;
Interpreter::Context& context) const;
///< Is the given sound currently playing on the given object? ///< 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 #endif

@ -14,6 +14,22 @@ namespace MWWorld
Class::~Class() {} 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 MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const
{ {
throw std::runtime_error ("class does not have creature stats"); throw std::runtime_error ("class does not have creature stats");

@ -10,6 +10,11 @@
#include "containerstore.hpp" #include "containerstore.hpp"
#include "refdata.hpp" #include "refdata.hpp"
namespace MWRender
{
class CellRenderImp;
}
namespace MWMechanics namespace MWMechanics
{ {
struct CreatureStats; struct CreatureStats;
@ -18,6 +23,7 @@ namespace MWMechanics
namespace MWWorld namespace MWWorld
{ {
class Ptr; class Ptr;
class Environment;
/// \brief Base class for referenceable esm records /// \brief Base class for referenceable esm records
class Class class Class
@ -36,6 +42,20 @@ namespace MWWorld
virtual ~Class(); 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; 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); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -36,6 +36,23 @@ namespace MWWorld
return false; return false;
} }
template<typename T>
bool create (const ESMS::RecListWithIDT<T>& list, const std::string& name)
{
if (const T *instance = list.search (name))
{
ESMS::LiveCellRef<T, RefData> ref;
ref.base = instance;
mRef = ref;
mPtr = Ptr (&boost::any_cast<ESMS::LiveCellRef<T, RefData>&> (mRef), 0);
return true;
}
return false;
}
public: public:
ManualRef (const ESMS::ESMStore& store, const std::string& name) ManualRef (const ESMS::ESMStore& store, const std::string& name)

@ -11,8 +11,11 @@
#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwsound/soundmanager.hpp"
#include "ptr.hpp" #include "ptr.hpp"
#include "environment.hpp" #include "environment.hpp"
#include "class.hpp"
namespace namespace
{ {
@ -372,12 +375,8 @@ namespace MWWorld
{ {
render->enable (reference.getRefData().getHandle()); render->enable (reference.getRefData().getHandle());
if (mActiveCells.find (reference.getCell())!=mActiveCells.end() && if (mActiveCells.find (reference.getCell())!=mActiveCells.end())
(reference.getType()==typeid (ESMS::LiveCellRef<ESM::NPC, RefData>) || Class::get (reference).enable (reference, mEnvironment);
reference.getType()==typeid (ESMS::LiveCellRef<ESM::Creature, RefData>)))
{
mEnvironment.mMechanicsManager->addActor (reference);
}
} }
} }
} }
@ -392,11 +391,10 @@ namespace MWWorld
{ {
render->disable (reference.getRefData().getHandle()); render->disable (reference.getRefData().getHandle());
if (mActiveCells.find (reference.getCell())!=mActiveCells.end() && if (mActiveCells.find (reference.getCell())!=mActiveCells.end())
(reference.getType()==typeid (ESMS::LiveCellRef<ESM::NPC, RefData>) ||
reference.getType()==typeid (ESMS::LiveCellRef<ESM::Creature, RefData>)))
{ {
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); mEnvironment.mMechanicsManager->dropActors (active->first);
active->second->destroy(); active->second->destroy();
mEnvironment.mSoundManager->stopSound (active->first);
delete active->second; delete active->second;
mActiveCells.erase (active); mActiveCells.erase (active);
} }
@ -551,7 +550,7 @@ namespace MWWorld
// This connects the cell data with the rendering scene. // This connects the cell data with the rendering scene.
std::pair<CellRenderCollection::iterator, bool> result = std::pair<CellRenderCollection::iterator, bool> result =
mActiveCells.insert (std::make_pair (cell, mActiveCells.insert (std::make_pair (cell,
new MWRender::InteriorCellRender (*cell, mStore, mScene))); new MWRender::InteriorCellRender (*cell, mEnvironment, mScene)));
if (result.second) if (result.second)
{ {
@ -623,11 +622,10 @@ namespace MWWorld
render->deleteObject (ptr.getRefData().getHandle()); render->deleteObject (ptr.getRefData().getHandle());
ptr.getRefData().setHandle (""); ptr.getRefData().setHandle ("");
if (mActiveCells.find (ptr.getCell())!=mActiveCells.end() && if (mActiveCells.find (ptr.getCell())!=mActiveCells.end())
(ptr.getType()==typeid (ESMS::LiveCellRef<ESM::NPC, RefData>) ||
ptr.getType()==typeid (ESMS::LiveCellRef<ESM::Creature, RefData>)))
{ {
mEnvironment.mMechanicsManager->removeActor (ptr); Class::get (ptr).disable (ptr, mEnvironment);
mEnvironment.mSoundManager->stopSound3D (ptr);
} }
} }
} }

@ -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)

@ -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 )

@ -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? </today's rant>
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)

@ -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)

@ -48,35 +48,35 @@ namespace Compiler
switch (mPutback) switch (mPutback)
{ {
case Putback_Special: case Putback_Special:
mPutback = Putback_None; mPutback = Putback_None;
return parser.parseSpecial (mPutbackCode, mPutbackLoc, *this); return parser.parseSpecial (mPutbackCode, mPutbackLoc, *this);
case Putback_Integer: case Putback_Integer:
mPutback = Putback_None; mPutback = Putback_None;
return parser.parseInt (mPutbackInteger, mPutbackLoc, *this); return parser.parseInt (mPutbackInteger, mPutbackLoc, *this);
case Putback_Float: case Putback_Float:
mPutback = Putback_None; mPutback = Putback_None;
return parser.parseFloat (mPutbackFloat, mPutbackLoc, *this); return parser.parseFloat (mPutbackFloat, mPutbackLoc, *this);
case Putback_Name: case Putback_Name:
mPutback = Putback_None; mPutback = Putback_None;
return parser.parseName (mPutbackName, mPutbackLoc, *this); return parser.parseName (mPutbackName, mPutbackLoc, *this);
case Putback_Keyword: case Putback_Keyword:
mPutback = Putback_None; mPutback = Putback_None;
return parser.parseKeyword (mPutbackCode, mPutbackLoc, *this); return parser.parseKeyword (mPutbackCode, mPutbackLoc, *this);
case Putback_None: case Putback_None:
break; break;
} }
char c; char c;
if (!get (c)) if (!get (c))
@ -265,12 +265,12 @@ namespace Compiler
cont = parser.parseName (name, loc, *this); cont = parser.parseName (name, loc, *this);
return true; return true;
} }
int i = 0; int i = 0;
std::string lowerCase; std::string lowerCase;
lowerCase.reserve (name.size()); lowerCase.reserve (name.size());
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower); (int(*)(int)) std::tolower);
@ -283,13 +283,13 @@ namespace Compiler
cont = parser.parseKeyword (i, loc, *this); cont = parser.parseKeyword (i, loc, *this);
return true; return true;
} }
if (mExtensions) if (mExtensions)
{ {
if (int keyword = mExtensions->searchKeyword (lowerCase)) if (int keyword = mExtensions->searchKeyword (lowerCase))
{ {
cont = parser.parseKeyword (keyword, loc, *this); cont = parser.parseKeyword (keyword, loc, *this);
return true; return true;
} }
} }
@ -316,19 +316,20 @@ namespace Compiler
name += c; name += c;
break; break;
} }
else if (c=='\\') // ignoring escape sequences for now, because they are messing up stupid Windows path names.
{ // else if (c=='\\')
if (!get (c)) // {
{ // if (!get (c))
mErrorHandler.error ("incomplete escape sequence", mLoc); // {
break; // mErrorHandler.error ("incomplete escape sequence", mLoc);
} // break;
} // }
// }
else if (c=='\n') else if (c=='\n')
{ {
mErrorHandler.error ("incomplete string or name", mLoc); mErrorHandler.error ("incomplete string or name", mLoc);
break; break;
} }
} }
else if (!(c=='"' && name.empty())) else if (!(c=='"' && name.empty()))
{ {
@ -341,7 +342,7 @@ namespace Compiler
if (first && std::isdigit (c)) if (first && std::isdigit (c))
error = true; error = true;
} }
name += c; name += c;
first = false; first = false;
} }
@ -374,7 +375,7 @@ namespace Compiler
else else
{ {
putback (c); putback (c);
return false; return false;
} }
} }
else if (c=='!') else if (c=='!')
@ -449,8 +450,8 @@ namespace Compiler
return false; return false;
if (special==S_newline) if (special==S_newline)
mLoc.mLiteral = "<newline>"; mLoc.mLiteral = "<newline>";
TokenLoc loc (mLoc); TokenLoc loc (mLoc);
mLoc.mLiteral.clear(); mLoc.mLiteral.clear();
@ -477,40 +478,39 @@ namespace Compiler
{ {
while (scanToken (parser)); while (scanToken (parser));
} }
void Scanner::putbackSpecial (int code, const TokenLoc& loc) void Scanner::putbackSpecial (int code, const TokenLoc& loc)
{ {
mPutback = Putback_Special; mPutback = Putback_Special;
mPutbackCode = code; mPutbackCode = code;
mPutbackLoc = loc; mPutbackLoc = loc;
} }
void Scanner::putbackInt (int value, const TokenLoc& loc) void Scanner::putbackInt (int value, const TokenLoc& loc)
{ {
mPutback = Putback_Integer; mPutback = Putback_Integer;
mPutbackInteger = value; mPutbackInteger = value;
mPutbackLoc = loc; mPutbackLoc = loc;
} }
void Scanner::putbackFloat (float value, const TokenLoc& loc) void Scanner::putbackFloat (float value, const TokenLoc& loc)
{ {
mPutback = Putback_Float; mPutback = Putback_Float;
mPutbackFloat = value; mPutbackFloat = value;
mPutbackLoc = loc; mPutbackLoc = loc;
} }
void Scanner::putbackName (const std::string& name, const TokenLoc& loc) void Scanner::putbackName (const std::string& name, const TokenLoc& loc)
{ {
mPutback = Putback_Name; mPutback = Putback_Name;
mPutbackName = name; mPutbackName = name;
mPutbackLoc = loc; mPutbackLoc = loc;
} }
void Scanner::putbackKeyword (int keyword, const TokenLoc& loc) void Scanner::putbackKeyword (int keyword, const TokenLoc& loc)
{ {
mPutback = Putback_Keyword; mPutback = Putback_Keyword;
mPutbackCode = keyword; mPutbackCode = keyword;
mPutbackLoc = loc; mPutbackLoc = loc;
} }
} }

@ -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();
}
}

@ -62,8 +62,12 @@ struct Creature
// Defined in loadcont.hpp // Defined in loadcont.hpp
InventoryList inventory; InventoryList inventory;
void load(ESMReader &esm) std::string mId;
void load(ESMReader &esm, const std::string& id)
{ {
mId = id;
model = esm.getHNString("MODL"); model = esm.getHNString("MODL");
original = esm.getHNOString("CNAM"); original = esm.getHNOString("CNAM");
name = esm.getHNOString("FNAM"); name = esm.getHNOString("FNAM");
@ -93,7 +97,7 @@ struct Creature
// AI_A - activate? // AI_A - activate?
esm.skipRecord(); esm.skipRecord();
} }
}; };
} }
#endif #endif

@ -57,10 +57,10 @@ struct NPC
char strength, intelligence, willpower, agility, char strength, intelligence, willpower, agility,
speed, endurance, personality, luck; speed, endurance, personality, luck;
char skills[27]; char skills[27];
char reputation;
short health, mana, fatigue; short health, mana, fatigue;
char disposition; char disposition, factionID, rank;
char reputation; // Was "factionID", but that makes no sense. char unknown;
char rank, unknown, u2;
int gold; int gold;
}; // 52 bytes }; // 52 bytes
@ -97,41 +97,10 @@ struct NPC
std::string name, model, race, cls, faction, script, std::string name, model, race, cls, faction, script,
hair, head; // body parts hair, head; // body parts
void load(ESMReader &esm) std::string mId;
{
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 #endif

@ -17,16 +17,16 @@ namespace ESMS
{ {
virtual void load(ESMReader &esm, const std::string &id) = 0; virtual void load(ESMReader &esm, const std::string &id) = 0;
virtual int getSize() = 0; virtual int getSize() = 0;
static std::string toLower (const std::string& name) static std::string toLower (const std::string& name)
{ {
std::string lowerCase; std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower); (int(*)(int)) std::tolower);
return lowerCase; return lowerCase;
} }
}; };
typedef std::map<int,RecList*> RecListList; typedef std::map<int,RecList*> RecListList;
@ -53,15 +53,53 @@ namespace ESMS
return NULL; return NULL;
return &list.find(id2)->second; 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 <typename X>
struct RecListWithIDT : RecList
{
typedef std::map<std::string,X> 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) // Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const const X* find(const std::string &id) const
{ {
const X *object = search (id); const X *object = search (id);
if (!object) if (!object)
throw std::runtime_error ("object " + id + " not found"); throw std::runtime_error ("object " + id + " not found");
return object; return object;
} }
@ -80,7 +118,7 @@ namespace ESMS
void load(ESMReader &esm, const std::string &id) void load(ESMReader &esm, const std::string &id)
{ {
std::string id2 = toLower (id); std::string id2 = toLower (id);
X& ref = list[id2]; X& ref = list[id2];
ref.id = id; ref.id = id;
@ -95,18 +133,18 @@ namespace ESMS
return NULL; return NULL;
return &list.find(id2)->second; return &list.find(id2)->second;
} }
// Find the given object ID (throws an exception if not found) // Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const const X* find(const std::string &id) const
{ {
const X *object = search (id); const X *object = search (id);
if (!object) if (!object)
throw std::runtime_error ("object " + id + " not found"); throw std::runtime_error ("object " + id + " not found");
return object; return object;
} }
int getSize() { return list.size(); } int getSize() { return list.size(); }
}; };
@ -180,7 +218,7 @@ namespace ESMS
} }
} }
}; };
template <typename X> template <typename X>
struct ScriptListT : RecList struct ScriptListT : RecList
{ {
@ -193,16 +231,16 @@ namespace ESMS
{ {
X ref; X ref;
ref.load (esm); ref.load (esm);
std::string realId = toLower (ref.data.name.toString()); std::string realId = toLower (ref.data.name.toString());
std::swap (list[realId], ref); std::swap (list[realId], ref);
} }
// Find the given object ID, or return NULL if not found. // Find the given object ID, or return NULL if not found.
const X* search(const std::string &id) const const X* search(const std::string &id) const
{ {
std::string id2 = toLower (id); std::string id2 = toLower (id);
if(list.find(id2) == list.end()) if(list.find(id2) == list.end())
return NULL; return NULL;
return &list.find(id2)->second; return &list.find(id2)->second;
@ -212,15 +250,15 @@ namespace ESMS
const X* find(const std::string &id) const const X* find(const std::string &id) const
{ {
const X *object = search (id); const X *object = search (id);
if (!object) if (!object)
throw std::runtime_error ("object " + id + " not found"); throw std::runtime_error ("object " + id + " not found");
return object; return object;
} }
int getSize() { return list.size(); } int getSize() { return list.size(); }
}; };
/* We need special lists for: /* We need special lists for:

@ -40,7 +40,7 @@ namespace ESMS
RecListT<Clothing> clothes; RecListT<Clothing> clothes;
RecListT<LoadCNTC> contChange; RecListT<LoadCNTC> contChange;
RecListT<Container> containers; RecListT<Container> containers;
RecListT<Creature> creatures; RecListWithIDT<Creature> creatures;
RecListT<LoadCREC> creaChange; RecListT<LoadCREC> creaChange;
RecListT<Dialogue> dialogs; RecListT<Dialogue> dialogs;
RecListT<Door> doors; RecListT<Door> doors;
@ -53,7 +53,7 @@ namespace ESMS
RecListT<Light> lights; RecListT<Light> lights;
RecListT<Tool> lockpicks; RecListT<Tool> lockpicks;
RecListT<Misc> miscItems; RecListT<Misc> miscItems;
RecListT<NPC> npcs; RecListWithIDT<NPC> npcs;
RecListT<LoadNPCC> npcChange; RecListT<LoadNPCC> npcChange;
RecListT<Probe> probes; RecListT<Probe> probes;
RecListT<Race> races; RecListT<Race> races;

@ -1 +1 @@
Subproject commit c7b179d6546688208528c8eef681d42b7c1ec7be Subproject commit c982f701cacdd2932bfdc22b168f54221a549b62

@ -1 +1 @@
Subproject commit c04d72cbe380217c2d1d60f8a2c6e4810fe4c050 Subproject commit b9d4dc448bc3be908653f9dea3c3450fb85ed107

@ -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);
}
}

@ -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;
}
}
Loading…
Cancel
Save