Merge remote branch 'upstream/master'

actorid
Armin Preiml 15 years ago
commit 6a936100a7

@ -1,5 +1,10 @@
project(OpenMW)
# Sound source selection
option(USE_AUDIERE "use Audiere for sound" OFF)
option(USE_FFMPEG "use ffmpeg for sound" OFF)
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
# We probably support older versions than this.
cmake_minimum_required(VERSION 2.6)
@ -48,7 +53,10 @@ set(ESM_STORE_HEADER
source_group(components\\esm_store FILES ${ESM_STORE} ${ESM_STORE_HEADER})
file(GLOB ESM_HEADER ${COMP_DIR}/esm/*.hpp)
source_group(components\\esm FILES ${ESM_HEADER})
set(ESM
${COMP_DIR}/esm/load_impl.cpp
)
source_group(components\\esm FILES ${ESM_HEADER} ${ESM})
set(MISC
${COMP_DIR}/misc/stringops.cpp
@ -68,7 +76,7 @@ file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp)
source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER})
set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC}
${COMPILER} ${INTERPRETER})
${COMPILER} ${INTERPRETER} ${ESM})
set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER}
${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER}
${INTERPRETER_HEADER})
@ -90,7 +98,48 @@ set(OENGINE_GUI
${LIBDIR}/openengine/gui/events.cpp
${LIBDIR}/openengine/gui/manager.cpp
)
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI})
# Sound setup
if (USE_AUDIERE)
set(MANGLE_SOUND_OUTPUT
${LIBDIR}/mangle/sound/sources/audiere_source.cpp
${LIBDIR}/mangle/sound/sources/sample_reader.cpp
${LIBDIR}/mangle/stream/clients/audiere_file.cpp)
find_package(Audiere REQUIRED)
set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY})
set(SOUND_DEFINE -DOPENMW_USE_AUDIERE)
endif (USE_AUDIERE)
if (USE_FFMPEG)
set(MANGLE_SOUND_OUTPUT
${LIBDIR}/mangle/sound/sources/ffmpeg_source.cpp)
find_package(FFMPEG REQUIRED)
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
set(SOUND_DEFINE -DOPENMW_USE_FFMPEG)
endif (USE_FFMPEG)
if (USE_MPG123)
set(MANGLE_SOUND_OUTPUT
${LIBDIR}/mangle/sound/sources/mpg123_source.cpp
${LIBDIR}/mangle/sound/sources/libsndfile.cpp
${LIBDIR}/mangle/sound/sources/sample_reader.cpp)
find_package(MPG123 REQUIRED)
find_package(SNDFILE REQUIRED)
set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
set(SOUND_DEFINE -DOPENMW_USE_MPG123)
endif (USE_MPG123)
set(OENGINE_SOUND
# Mangle and OEngine sound files are sort of intertwined, so put
# them together here
${LIBDIR}/openengine/sound/sndmanager.cpp
${LIBDIR}/mangle/sound/outputs/openal_out.cpp
${MANGLE_SOUND_OUTPUT}
)
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND})
source_group(libs\\openengine FILES ${OENGINE_ALL})
set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL})
@ -110,6 +159,7 @@ find_package(OGRE REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
find_package(OIS REQUIRED)
find_package(Iconv REQUIRED)
find_package(OpenAL REQUIRED)
include_directories("."
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre
${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR}

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

@ -179,10 +179,17 @@ add_executable(openmw
${APPLE_BUNDLE_RESOURCES}
)
# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
# when we change the backend.
include_directories(${SOUND_INPUT_INCLUDES})
add_definitions(${SOUND_DEFINE})
target_link_libraries(openmw
${OGRE_LIBRARIES}
${OIS_LIBRARIES}
${Boost_LIBRARIES}
${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY}
${ICONV_LIBRARIES}
caelum
MyGUIEngine

@ -38,7 +38,7 @@ void OMW::Engine::executeLocalScripts()
mEnvironment.mWorld->getLocalScripts().begin());
iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter)
{
if (!mIgnoreLocalPtr.isEmpty() && mIgnoreLocalPtr!=iter->second)
if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second)
{
MWScript::InterpreterContext interpreterContext (mEnvironment,
&iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second));
@ -233,7 +233,10 @@ void OMW::Engine::go()
mExtensions, mNewGame);
// Create sound system
mEnvironment.mSoundManager = new MWSound::SoundManager;
mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(),
mOgre.getCamera(),
mEnvironment.mWorld->getStore(),
(mDataDir / "Sound").file_string());
// Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
@ -266,6 +269,18 @@ void OMW::Engine::go()
mOgre.getRoot()->addFrameListener (this);
// Play some good 'ol tunes
std::string music = (mDataDir / "Music/Explore/mx_explore_5.mp3").file_string();
try
{
std::cout << "Playing " << music << "\n";
mEnvironment.mSoundManager->streamMusic(music);
}
catch(std::exception &e)
{
std::cout << " Music Error: " << e.what() << "\n";
}
// Start the main rendering loop
mOgre.start();

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,16 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,15 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
/// \attention This is not the same as the script instruction with the same name. References
/// should only be enabled while in an active cell.
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,16 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
virtual void disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -9,6 +9,10 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

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

@ -2,91 +2,55 @@
#include <cassert>
#include "../mwworld/class.hpp"
#include "../mwworld/ptr.hpp"
using namespace MWRender;
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)
void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment,
T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
{
assert (liveRef.base != NULL);
const std::string &model = liveRef.base->model;
if(!model.empty())
{
cellRender.insertBegin (liveRef.ref);
cellRender.insertMesh ("meshes\\" + model);
// Extract the color and convert to floating point
const int color = liveRef.base->data.color;
const float r = ((color >> 0) & 0xFF) / 255.0f;
const float g = ((color >> 8) & 0xFF) / 255.0f;
const float b = ((color >> 16) & 0xFF) / 255.0f;
const float radius = float(liveRef.base->data.radius);
cellRender.insertLight(r, g, b, radius);
liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled()));
}
}
template<>
void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>& liveRef, const ESMS::ESMStore& store)
if (!cellRefList.list.empty())
{
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()));
}
const MWWorld::Class& class_ =
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell));
template<typename T>
void insertCellRefList (CellRenderImp& cellRender, const ESMS::ESMStore& store, T& cellRefList)
{
for (typename T::List::iterator it = cellRefList.list.begin();
it != cellRefList.list.end(); it++)
{
if (it->mData.getCount())
insertObj (cellRender, *it, store);
{
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
insertCellRefList (*this, store, cell.activators);
insertCellRefList (*this, store, cell.potions);
insertCellRefList (*this, store, cell.appas);
insertCellRefList (*this, store, cell.armors);
insertCellRefList (*this, store, cell.books);
insertCellRefList (*this, store, cell.clothes);
insertCellRefList (*this, store, cell.containers);
insertCellRefList (*this, store, cell.creatures);
insertCellRefList (*this, store, cell.doors);
insertCellRefList (*this, store, cell.ingreds);
// insertCellRefList (*this, store, cell.creatureLists);
// insertCellRefList (*this, store, cell.itemLists);
insertCellRefList (*this, store, cell.lights);
insertCellRefList (*this, store, cell.lockpicks);
insertCellRefList (*this, store, cell.miscItems);
insertCellRefList (*this, store, cell.npcs);
insertCellRefList (*this, store, cell.probes);
insertCellRefList (*this, store, cell.repairs);
insertCellRefList (*this, store, cell.statics);
insertCellRefList (*this, store, cell.weapons);
insertCellRefList (*this, environment, cell.activators, cell);
insertCellRefList (*this, environment, cell.potions, cell);
insertCellRefList (*this, environment, cell.appas, cell);
insertCellRefList (*this, environment, cell.armors, cell);
insertCellRefList (*this, environment, cell.books, cell);
insertCellRefList (*this, environment, cell.clothes, cell);
insertCellRefList (*this, environment, cell.containers, cell);
insertCellRefList (*this, environment, cell.creatures, cell);
insertCellRefList (*this, environment, cell.doors, cell);
insertCellRefList (*this, environment, cell.ingreds, cell);
insertCellRefList (*this, environment, cell.creatureLists, cell);
insertCellRefList (*this, environment, cell.itemLists, cell);
insertCellRefList (*this, environment, cell.lights, cell);
insertCellRefList (*this, environment, cell.lockpicks, cell);
insertCellRefList (*this, environment, cell.miscItems, cell);
insertCellRefList (*this, environment, cell.npcs, cell);
insertCellRefList (*this, environment, cell.probes, cell);
insertCellRefList (*this, environment, cell.repairs, cell);
insertCellRefList (*this, environment, cell.statics, cell);
insertCellRefList (*this, environment, cell.weapons, cell);
}

@ -12,9 +12,9 @@ namespace ESM
class CellRef;
}
namespace ESMS
namespace MWWorld
{
class ESMStore;
class Environment;
}
namespace MWRender
@ -40,7 +40,7 @@ namespace MWRender
/// finish inserting a new reference and return a handle to it.
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()
{
// If already loaded, just make the cell visible.
if(base)
{
base->setVisible(true);
return;
}
base = scene.getRoot()->createChildSceneNode();
configureAmbient();
configureFog();
insertCell(cell, store);
insertCell(cell, mEnvironment);
}
void InteriorCellRender::hide()

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

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

@ -32,8 +32,8 @@ namespace MWScript
std::string text = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
context.getSoundManager().say (context.getReference(), file, text,
context);
context.getSoundManager().say (context.getReference(), file);
context.messageBox (text);
}
};
@ -46,8 +46,7 @@ namespace MWScript
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
runtime.push (context.getSoundManager().sayDone (context.getReference(),
context));
runtime.push (context.getSoundManager().sayDone (context.getReference()));
}
};
@ -63,7 +62,7 @@ namespace MWScript
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
context.getSoundManager().streamMusic (sound, context);
context.getSoundManager().streamMusic (sound);
}
};
@ -79,7 +78,7 @@ namespace MWScript
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
context.getSoundManager().playSound (sound, 1.0, 1.0, context);
context.getSoundManager().playSound (sound, 1.0, 1.0);
}
};
@ -101,7 +100,7 @@ namespace MWScript
Interpreter::Type_Float pitch = runtime[0].mFloat;
runtime.pop();
context.getSoundManager().playSound (sound, volume, pitch, context);
context.getSoundManager().playSound (sound, volume, pitch);
}
};
@ -122,7 +121,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound,
1.0, 1.0, mLoop, context);
1.0, 1.0, mLoop);
}
};
@ -149,7 +148,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound, volume,
pitch, mLoop, context);
pitch, mLoop);
}
};
@ -166,7 +165,7 @@ namespace MWScript
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
context.getSoundManager().stopSound3D (context.getReference(), sound, context);
context.getSoundManager().stopSound3D (context.getReference(), sound);
}
};
@ -183,7 +182,7 @@ namespace MWScript
runtime.pop();
runtime.push (context.getSoundManager().getSoundPlaying (
context.getReference(), runtime.getStringLiteral (index), context));
context.getReference(), runtime.getStringLiteral (index)));
}
};
@ -206,7 +205,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().say (context.getWorld().getPtr (id, true),
file, text, context);
file);
}
};
@ -223,7 +222,7 @@ namespace MWScript
runtime.pop();
runtime.push (context.getSoundManager().sayDone (
context.getWorld().getPtr (id, true), context));
context.getWorld().getPtr (id, true)));
}
};
@ -247,7 +246,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().playSound3D (
context.getWorld().getPtr (id, true), sound, 1.0, 1.0, mLoop, context);
context.getWorld().getPtr (id, true), sound, 1.0, 1.0, mLoop);
}
};
@ -277,7 +276,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().playSound3D (
context.getWorld().getPtr (id, true), sound, volume, pitch, mLoop, context);
context.getWorld().getPtr (id, true), sound, volume, pitch, mLoop);
}
};
@ -298,7 +297,7 @@ namespace MWScript
runtime.pop();
context.getSoundManager().stopSound3D (
context.getWorld().getPtr (id, true), sound, context);
context.getWorld().getPtr (id, true), sound);
}
};
@ -319,7 +318,7 @@ namespace MWScript
runtime.push (context.getSoundManager().getSoundPlaying (
context.getWorld().getPtr (id, true),
runtime.getStringLiteral (index), context));
runtime.getStringLiteral (index)));
}
};

@ -1,71 +1,238 @@
#include "soundmanager.hpp"
#include <iostream> // TODO remove this line, once the real code is in place.
#include <iostream>
using namespace std;
#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;
#include <components/interpreter/context.hpp>
// Move the sound, converting from MW coordinates to Ogre
// coordinates.
snd->setPos(pos[0], pos[2], -pos[1]);
}
namespace MWSound
{
void SoundManager::say (MWWorld::Ptr reference, const std::string& filename,
const std::string& text, Interpreter::Context& context)
struct SoundManager::SoundImpl
{
/* This is the sound manager. It loades, stores and deletes
sounds based on the sound factory it is given.
*/
OEManagerPtr mgr;
/* This class calls update() on the sound manager each frame
using and Ogre::FrameListener
*/
Mangle::Sound::OgreOutputUpdater updater;
/* This class tracks the movement of an Ogre::Camera and moves
a sound listener automatically to follow it.
*/
Mangle::Sound::OgreListenerMover cameraTracker;
const ESMS::ESMStore &store;
std::string dir;
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
const ESMS::ESMStore &str,
const std::string &soundDir)
: mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
, updater(mgr)
, cameraTracker(mgr)
, store(str)
{
std::cout << "sound effect: " << reference.getRefData().getHandle() << " is speaking" << std::endl;
// Attach the camera to the camera tracker
cameraTracker.followCamera(camera);
context.messageBox (text);
// Tell Ogre to update the sound system each frame
root->addFrameListener(&updater);
dir = soundDir + "/";
}
bool SoundManager::sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const
// 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)
{
return false;
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;
}
void SoundManager::streamMusic (const std::string& filename, Interpreter::Context& context)
// 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
{
std::cout << "sound effect: playing music" << filename << std::endl;
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";
}
}
void SoundManager::playSound (const std::string& soundId, float volume, float pitch,
Interpreter::Context& context)
// 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 = "")
{
std::cout
<< "sound effect: playing sound " << soundId
<< " at volume " << volume << ", at pitch " << pitch
<< std::endl;
}
void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, bool loop, Interpreter::Context& context)
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()
{
std::cout
<< "sound effect: playing sound " << soundId
<< " from " << reference.getRefData().getHandle()
<< " at volume " << volume << ", at pitch " << pitch
<< std::endl;
delete mData;
}
void SoundManager::say (MWWorld::Ptr reference, const std::string& filename)
{
// The range values are not tested
mData->add(filename, reference, "_say_sound", 1, 1, 100, 10000, false);
}
mSounds[reference.getRefData().getHandle()] = soundId;
bool SoundManager::sayDone (MWWorld::Ptr reference) const
{
return !mData->isPlaying(reference, "_say_sound");
}
void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId,
Interpreter::Context& context)
void SoundManager::streamMusic (const std::string& filename)
{
std::cout
<< "sound effect : stop playing sound " << soundId
<< " from " << reference.getRefData().getHandle() << 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);
}
mSounds[reference.getRefData().getHandle()] = "";
void SoundManager::playSound (const std::string& soundId, float volume, float pitch)
{
// Play and forget
float min, max;
const std::string &file = mData->lookup(soundId, volume, min, max);
if(file != "")
{
SoundPtr snd = mData->mgr->play(file);
snd->setVolume(volume);
snd->setRange(min,max);
snd->setPitch(pitch);
}
}
bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId,
Interpreter::Context& context) const
void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, bool loop)
{
std::map<std::string, std::string>::const_iterator iter =
mSounds.find (reference.getRefData().getHandle());
// Look up the sound in the ESM data
float min, max;
const std::string &file = mData->lookup(soundId, volume, min, max);
if(file != "")
mData->add(file, reference, soundId, volume, pitch, min, max, loop);
}
if (iter==mSounds.end())
return false;
void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId)
{
mData->remove(reference, soundId);
}
return iter->second==soundId;
void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell)
{
mData->removeCell(cell);
}
bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const
{
return mData->isPlaying(reference, soundId);
}
void SoundManager::updateObject(MWWorld::Ptr reference)
{
mData->updatePositions(reference);
}
}

@ -6,63 +6,62 @@
#include "../mwworld/ptr.hpp"
namespace Interpreter
namespace Ogre
{
class Context;
class Root;
class Camera;
}
namespace MWSound
namespace ESMS
{
// 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)
struct ESMStore;
}
namespace MWSound
{
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:
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
const std::string &soundDir);
~SoundManager();
void say (MWWorld::Ptr reference, const std::string& filename,
const std::string& text, Interpreter::Context& context);
void say (MWWorld::Ptr reference, const std::string& filename);
///< Make an actor say some text.
/// \param filename name of a sound file in "Sound/Vo/" in the data directory.
/// \param text Subtitle
bool sayDone (MWWorld::Ptr reference, Interpreter::Context& context) const;
bool sayDone (MWWorld::Ptr reference) const;
///< Is actor not speaking?
void streamMusic (const std::string& filename, Interpreter::Context& context);
void streamMusic (const std::string& filename);
///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory.
void playSound (const std::string& soundId, float volume, float pitch,
Interpreter::Context& context);
void playSound (const std::string& soundId, float volume, float pitch);
///< Play a sound, independently of 3D-position
void playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, bool loop, Interpreter::Context& context);
float volume, float pitch, bool loop);
///< Play a sound from an object
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId,
Interpreter::Context& context);
///< Stop the given object from playing the given sound.
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = "");
///< Stop the given object from playing the given sound, If no soundId is given,
/// all sounds for this reference will stop.
bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId,
Interpreter::Context& context) const;
void stopSound (MWWorld::Ptr::CellStore *cell);
///< Stop all sounds for the given cell.
bool getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const;
///< Is the given sound currently playing on the given object?
void updateObject(MWWorld::Ptr reference);
///< Update the position of all sounds connected to the given object.
};
}
#endif

@ -14,6 +14,22 @@ namespace MWWorld
Class::~Class() {}
void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
{
}
void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const
{
}
void Class::disable (const Ptr& ptr, MWWorld::Environment& environment) const
{
}
MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const
{
throw std::runtime_error ("class does not have creature stats");

@ -10,6 +10,11 @@
#include "containerstore.hpp"
#include "refdata.hpp"
namespace MWRender
{
class CellRenderImp;
}
namespace MWMechanics
{
struct CreatureStats;
@ -18,6 +23,7 @@ namespace MWMechanics
namespace MWWorld
{
class Ptr;
class Environment;
/// \brief Base class for referenceable esm records
class Class
@ -36,6 +42,20 @@ namespace MWWorld
virtual ~Class();
virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering (default implementation: don't render anything).
virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part (default implementation: ignore)
/// \attention This is not the same as the script instruction with the same name. References
/// should only be enabled while in an active cell.
virtual void disable (const Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part (default implementation: ignore)
/// \attention This is not the same as the script instruction with the same name. References
/// should only be enabled while in an active cell.
virtual std::string getName (const Ptr& ptr) const = 0;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -36,6 +36,23 @@ namespace MWWorld
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:
ManualRef (const ESMS::ESMStore& store, const std::string& name)

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

@ -316,14 +316,15 @@ namespace Compiler
name += c;
break;
}
else if (c=='\\')
{
if (!get (c))
{
mErrorHandler.error ("incomplete escape sequence", mLoc);
break;
}
}
// ignoring escape sequences for now, because they are messing up stupid Windows path names.
// else if (c=='\\')
// {
// if (!get (c))
// {
// mErrorHandler.error ("incomplete escape sequence", mLoc);
// break;
// }
// }
else if (c=='\n')
{
mErrorHandler.error ("incomplete string or name", mLoc);
@ -513,4 +514,3 @@ namespace Compiler
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
InventoryList inventory;
void load(ESMReader &esm)
std::string mId;
void load(ESMReader &esm, const std::string& id)
{
mId = id;
model = esm.getHNString("MODL");
original = esm.getHNOString("CNAM");
name = esm.getHNOString("FNAM");

@ -57,10 +57,10 @@ struct NPC
char strength, intelligence, willpower, agility,
speed, endurance, personality, luck;
char skills[27];
char reputation;
short health, mana, fatigue;
char disposition;
char reputation; // Was "factionID", but that makes no sense.
char rank, unknown, u2;
char disposition, factionID, rank;
char unknown;
int gold;
}; // 52 bytes
@ -97,41 +97,10 @@ struct NPC
std::string name, model, race, cls, faction, script,
hair, head; // body parts
void load(ESMReader &esm)
{
npdt52.gold = -10;
model = esm.getHNOString("MODL");
name = esm.getHNOString("FNAM");
race = esm.getHNString("RNAM");
cls = esm.getHNString("CNAM");
faction = esm.getHNString("ANAM");
head = esm.getHNString("BNAM");
hair = esm.getHNString("KNAM");
script = esm.getHNOString("SCRI");
esm.getSubNameIs("NPDT");
esm.getSubHeader();
if(esm.getSubSize() == 52) esm.getExact(&npdt52, 52);
else if(esm.getSubSize() == 12) esm.getExact(&npdt12, 12);
else esm.fail("NPC_NPDT must be 12 or 52 bytes long");
esm.getHNT(flags, "FLAG");
std::string mId;
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

@ -68,6 +68,44 @@ namespace ESMS
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)
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(); }
};
// The only difference to the above is a slight change to the load()
// function. We might merge these together later, and store the id
// in all the structs.

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