forked from mirror/openmw-tes3mp
Resolve conflicts in pull request #75
# Conflicts: # CMakeLists.txt # apps/openmw/CMakeLists.txt
This commit is contained in:
commit
3136a12051
49 changed files with 692 additions and 360 deletions
|
@ -217,27 +217,28 @@ if(NOT HAVE_STDINT_H)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options thread)
|
|
||||||
if(WIN32)
|
|
||||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
|
||||||
endif(WIN32)
|
|
||||||
|
|
||||||
IF(BOOST_STATIC)
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||||
|
|
||||||
find_package(OpenSceneGraph 3.3.4 REQUIRED osgDB osgViewer osgText osgGA osgAnimation osgParticle osgUtil osgFX)
|
find_package(OpenSceneGraph 3.3.4 REQUIRED osgDB osgViewer osgText osgGA osgAnimation osgParticle osgUtil osgFX)
|
||||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
|
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
set(USED_OSG_PLUGINS
|
||||||
|
osgdb_bmp
|
||||||
|
osgdb_dds
|
||||||
|
osgdb_jpeg
|
||||||
|
osgdb_osg
|
||||||
|
osgdb_png
|
||||||
|
osgdb_serializers_osg
|
||||||
|
osgdb_tga
|
||||||
|
)
|
||||||
|
|
||||||
get_filename_component(OSG_LIB_DIR ${OSGDB_LIBRARY} DIRECTORY)
|
get_filename_component(OSG_LIB_DIR ${OSGDB_LIBRARY} DIRECTORY)
|
||||||
set(OSGPlugins_LIB_DIR "${OSG_LIB_DIR}/osgPlugins-${OPENSCENEGRAPH_VERSION}")
|
set(OSGPlugins_LIB_DIR "${OSG_LIB_DIR}/osgPlugins-${OPENSCENEGRAPH_VERSION}")
|
||||||
|
|
||||||
if(OSG_STATIC)
|
if(OSG_STATIC)
|
||||||
add_definitions(-DOSG_LIBRARY_STATIC)
|
add_definitions(-DOSG_LIBRARY_STATIC)
|
||||||
|
|
||||||
find_package(OSGPlugins REQUIRED COMPONENTS osgdb_png osgdb_tga osgdb_dds osgdb_jpeg)
|
find_package(OSGPlugins REQUIRED COMPONENTS ${USED_OSG_PLUGINS})
|
||||||
list(APPEND OPENSCENEGRAPH_LIBRARIES ${OSGPlugins_LIBRARIES})
|
list(APPEND OPENSCENEGRAPH_LIBRARIES ${OSGPlugins_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -258,6 +259,16 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||||
|
|
||||||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||||
|
|
||||||
|
|
||||||
|
set(BOOST_COMPONENTS system filesystem program_options)
|
||||||
|
if(WIN32)
|
||||||
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
IF(BOOST_STATIC)
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||||
|
|
||||||
include_directories("."
|
include_directories("."
|
||||||
|
@ -769,12 +780,6 @@ if (APPLE)
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
|
|
||||||
set(ABSOLUTE_PLUGINS "")
|
set(ABSOLUTE_PLUGINS "")
|
||||||
set(USED_OSG_PLUGINS
|
|
||||||
osgdb_dds
|
|
||||||
osgdb_jpeg
|
|
||||||
osgdb_png
|
|
||||||
osgdb_tga
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach (PLUGIN_NAME ${USED_OSG_PLUGINS})
|
foreach (PLUGIN_NAME ${USED_OSG_PLUGINS})
|
||||||
set(PLUGIN_ABS "${OSGPlugins_LIB_DIR}/${PLUGIN_NAME}.so")
|
set(PLUGIN_ABS "${OSGPlugins_LIB_DIR}/${PLUGIN_NAME}.so")
|
||||||
|
|
|
@ -108,7 +108,7 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
|
||||||
verifyCell(topicInfo.mCell, id, messages);
|
verifyCell(topicInfo.mCell, id, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!topicInfo.mFaction.empty())
|
if (!topicInfo.mFaction.empty() && !topicInfo.mFactionLess)
|
||||||
{
|
{
|
||||||
if (verifyId(topicInfo.mFaction, mFactions, id, messages))
|
if (verifyId(topicInfo.mFaction, mFactions, id, messages))
|
||||||
{
|
{
|
||||||
|
|
|
@ -371,7 +371,6 @@ void CSMWorld::ConstInfoSelectWrapper::updateComparisonType()
|
||||||
case Function_NotClass:
|
case Function_NotClass:
|
||||||
case Function_NotRace:
|
case Function_NotRace:
|
||||||
case Function_NotCell:
|
case Function_NotCell:
|
||||||
case Function_NotLocal:
|
|
||||||
case Function_PcExpelled:
|
case Function_PcExpelled:
|
||||||
case Function_PcCommonDisease:
|
case Function_PcCommonDisease:
|
||||||
case Function_PcBlightDisease:
|
case Function_PcBlightDisease:
|
||||||
|
@ -454,6 +453,7 @@ void CSMWorld::ConstInfoSelectWrapper::updateComparisonType()
|
||||||
// Numeric
|
// Numeric
|
||||||
case Function_Global:
|
case Function_Global:
|
||||||
case Function_Local:
|
case Function_Local:
|
||||||
|
case Function_NotLocal:
|
||||||
|
|
||||||
case Function_Health_Percent:
|
case Function_Health_Percent:
|
||||||
case Function_PcHealthPercent:
|
case Function_PcHealthPercent:
|
||||||
|
@ -560,7 +560,6 @@ std::pair<int, int> CSMWorld::ConstInfoSelectWrapper::getValidIntRange() const
|
||||||
case Function_NotClass:
|
case Function_NotClass:
|
||||||
case Function_NotRace:
|
case Function_NotRace:
|
||||||
case Function_NotCell:
|
case Function_NotCell:
|
||||||
case Function_NotLocal:
|
|
||||||
case Function_PcExpelled:
|
case Function_PcExpelled:
|
||||||
case Function_PcCommonDisease:
|
case Function_PcCommonDisease:
|
||||||
case Function_PcBlightDisease:
|
case Function_PcBlightDisease:
|
||||||
|
@ -657,6 +656,7 @@ std::pair<int, int> CSMWorld::ConstInfoSelectWrapper::getValidIntRange() const
|
||||||
// Numeric
|
// Numeric
|
||||||
case Function_Global:
|
case Function_Global:
|
||||||
case Function_Local:
|
case Function_Local:
|
||||||
|
case Function_NotLocal:
|
||||||
return std::pair<int, int>(IntMin, IntMax);
|
return std::pair<int, int>(IntMin, IntMax);
|
||||||
|
|
||||||
case Function_PcMagicka:
|
case Function_PcMagicka:
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <osgViewer/CompositeViewer>
|
#include <osgViewer/CompositeViewer>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
#include <osg/LightModel>
|
#include <osg/LightModel>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
@ -130,6 +131,10 @@ CompositeViewer::CompositeViewer()
|
||||||
|
|
||||||
setThreadingModel(threadingModel);
|
setThreadingModel(threadingModel);
|
||||||
|
|
||||||
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,5)
|
||||||
|
setUseConfigureAffinity(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
// disable the default setting of viewer.done() by pressing Escape.
|
// disable the default setting of viewer.done() by pressing Escape.
|
||||||
setKeyEventSetsDone(0);
|
setKeyEventSetsDone(0);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
renderbin
|
renderbin actoranimation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -145,14 +145,15 @@ target_link_libraries(tes3mp
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set (OSG_PLUGINS
|
set (OSG_PLUGINS
|
||||||
-Wl,--whole-archive
|
-Wl,--whole-archive
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_dds.a
|
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_bmp.a
|
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_tga.a
|
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_gif.a
|
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_jpeg.a
|
|
||||||
${OSG_PLUGINS_DIR}/libosgdb_png.a
|
|
||||||
-Wl,--no-whole-archive
|
|
||||||
)
|
)
|
||||||
|
foreach(PLUGIN_NAME ${USED_OSG_PLUGINS})
|
||||||
|
set(OSG_PLUGINS ${OSG_PLUGINS} ${OSG_PLUGINS_DIR}/lib${PLUGIN_NAME}.a)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set (OSG_PLUGINS
|
||||||
|
${OSG_PLUGINS} -Wl,--no-whole-archive
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(tes3mp
|
target_link_libraries(tes3mp
|
||||||
EGL
|
EGL
|
||||||
android
|
android
|
||||||
|
|
|
@ -448,6 +448,11 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
|
||||||
|
// Clamp permanent disposition change so that final disposition doesn't go below 0 (could happen with intimidate)
|
||||||
|
float curDisp = static_cast<float>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor, false));
|
||||||
|
if (curDisp + mPermanentDispositionChange < 0)
|
||||||
|
mPermanentDispositionChange = -curDisp;
|
||||||
|
|
||||||
// Apply disposition change to NPC's base disposition
|
// Apply disposition change to NPC's base disposition
|
||||||
if (mActor.getClass().isNpc())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
|
|
|
@ -159,6 +159,39 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
|
||||||
: (actorDisposition >= info.mData.mDisposition);
|
: (actorDisposition >= info.mData.mDisposition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MWDialogue::Filter::testFunctionLocal(const MWDialogue::SelectWrapper& select) const
|
||||||
|
{
|
||||||
|
std::string scriptName = mActor.getClass().getScript (mActor);
|
||||||
|
|
||||||
|
if (scriptName.empty())
|
||||||
|
return false; // no script
|
||||||
|
|
||||||
|
std::string name = Misc::StringUtils::lowerCase (select.getName());
|
||||||
|
|
||||||
|
const Compiler::Locals& localDefs =
|
||||||
|
MWBase::Environment::get().getScriptManager()->getLocals (scriptName);
|
||||||
|
|
||||||
|
char type = localDefs.getType (name);
|
||||||
|
|
||||||
|
if (type==' ')
|
||||||
|
return false; // script does not have a variable of this name.
|
||||||
|
|
||||||
|
int index = localDefs.getIndex (name);
|
||||||
|
if (index < 0)
|
||||||
|
return false; // shouldn't happen, we checked that variable has a type above, so must exist
|
||||||
|
|
||||||
|
const MWScript::Locals& locals = mActor.getRefData().getLocals();
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
|
||||||
|
case 'l': return select.selectCompare (locals.mLongs[index]);
|
||||||
|
case 'f': return select.selectCompare (locals.mFloats[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::logic_error ("unknown local variable type in dialogue filter");
|
||||||
|
}
|
||||||
|
|
||||||
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
|
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
|
||||||
{
|
{
|
||||||
if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name()))
|
if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name()))
|
||||||
|
@ -200,35 +233,12 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
|
||||||
|
|
||||||
case SelectWrapper::Function_Local:
|
case SelectWrapper::Function_Local:
|
||||||
{
|
{
|
||||||
std::string scriptName = mActor.getClass().getScript (mActor);
|
return testFunctionLocal(select);
|
||||||
|
|
||||||
if (scriptName.empty())
|
|
||||||
return false; // no script
|
|
||||||
|
|
||||||
std::string name = Misc::StringUtils::lowerCase (select.getName());
|
|
||||||
|
|
||||||
const Compiler::Locals& localDefs =
|
|
||||||
MWBase::Environment::get().getScriptManager()->getLocals (scriptName);
|
|
||||||
|
|
||||||
char type = localDefs.getType (name);
|
|
||||||
|
|
||||||
if (type==' ')
|
|
||||||
return false; // script does not have a variable of this name.
|
|
||||||
|
|
||||||
int index = localDefs.getIndex (name);
|
|
||||||
if (index < 0)
|
|
||||||
return false; // shouldn't happen, we checked that variable has a type above, so must exist
|
|
||||||
|
|
||||||
const MWScript::Locals& locals = mActor.getRefData().getLocals();
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
|
|
||||||
case 'l': return select.selectCompare (locals.mLongs[index]);
|
|
||||||
case 'f': return select.selectCompare (locals.mFloats[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::logic_error ("unknown local variable type in dialogue filter");
|
case SelectWrapper::Function_NotLocal:
|
||||||
|
{
|
||||||
|
return !testFunctionLocal(select);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcHealthPercent:
|
case SelectWrapper::Function_PcHealthPercent:
|
||||||
|
@ -472,20 +482,6 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||||
return !Misc::StringUtils::ciEqual(MWBase::Environment::get().getWorld()->getCellName(mActor.getCell())
|
return !Misc::StringUtils::ciEqual(MWBase::Environment::get().getWorld()->getCellName(mActor.getCell())
|
||||||
, select.getName());
|
, select.getName());
|
||||||
|
|
||||||
case SelectWrapper::Function_NotLocal:
|
|
||||||
{
|
|
||||||
std::string scriptName = mActor.getClass().getScript (mActor);
|
|
||||||
|
|
||||||
if (scriptName.empty())
|
|
||||||
// This actor has no attached script, so there is no local variable
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const Compiler::Locals& localDefs =
|
|
||||||
MWBase::Environment::get().getScriptManager()->getLocals (scriptName);
|
|
||||||
|
|
||||||
return localDefs.getIndex (Misc::StringUtils::lowerCase (select.getName()))==-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SelectWrapper::Function_SameGender:
|
case SelectWrapper::Function_SameGender:
|
||||||
|
|
||||||
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
|
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace MWDialogue
|
||||||
bool testDisposition (const ESM::DialInfo& info, bool invert=false) const;
|
bool testDisposition (const ESM::DialInfo& info, bool invert=false) const;
|
||||||
///< Is the actor disposition toward the player high enough (or low enough, if \a invert is true)?
|
///< Is the actor disposition toward the player high enough (or low enough, if \a invert is true)?
|
||||||
|
|
||||||
|
bool testFunctionLocal(const SelectWrapper& select) const;
|
||||||
|
|
||||||
bool testSelectStruct (const SelectWrapper& select) const;
|
bool testSelectStruct (const SelectWrapper& select) const;
|
||||||
|
|
||||||
bool testSelectStructNumeric (const SelectWrapper& select) const;
|
bool testSelectStructNumeric (const SelectWrapper& select) const;
|
||||||
|
|
|
@ -39,9 +39,9 @@ void test(const MWWorld::Ptr& actor, int &compiled, int &total, const Compiler::
|
||||||
{
|
{
|
||||||
std::vector<const ESM::DialInfo*> infos = filter.listAll(*it);
|
std::vector<const ESM::DialInfo*> infos = filter.listAll(*it);
|
||||||
|
|
||||||
for (std::vector<const ESM::DialInfo*>::iterator it = infos.begin(); it != infos.end(); ++it)
|
for (std::vector<const ESM::DialInfo*>::iterator iter = infos.begin(); iter != infos.end(); ++iter)
|
||||||
{
|
{
|
||||||
const ESM::DialInfo* info = *it;
|
const ESM::DialInfo* info = *iter;
|
||||||
if (!info->mResultScript.empty())
|
if (!info->mResultScript.empty())
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
|
@ -210,7 +210,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
|
||||||
|
|
||||||
static const Function numericFunctions[] =
|
static const Function numericFunctions[] =
|
||||||
{
|
{
|
||||||
Function_Global, Function_Local,
|
Function_Global, Function_Local, Function_NotLocal,
|
||||||
Function_PcDynamicStat, Function_PcHealthPercent,
|
Function_PcDynamicStat, Function_PcHealthPercent,
|
||||||
Function_HealthPercent,
|
Function_HealthPercent,
|
||||||
Function_None // end marker
|
Function_None // end marker
|
||||||
|
@ -232,7 +232,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
|
||||||
static const Function invertedBooleanFunctions[] =
|
static const Function invertedBooleanFunctions[] =
|
||||||
{
|
{
|
||||||
Function_NotId, Function_NotFaction, Function_NotClass,
|
Function_NotId, Function_NotFaction, Function_NotClass,
|
||||||
Function_NotRace, Function_NotCell, Function_NotLocal,
|
Function_NotRace, Function_NotCell,
|
||||||
Function_None // end marker
|
Function_None // end marker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ namespace MWGui
|
||||||
mSpellItems.push_back(label);
|
mSpellItems.push_back(label);
|
||||||
coord.top += lineHeight;
|
coord.top += lineHeight;
|
||||||
|
|
||||||
std::vector<std::string>::const_iterator end = categories[category].spells.end();
|
end = categories[category].spells.end();
|
||||||
for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != end; ++it)
|
for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != end; ++it)
|
||||||
{
|
{
|
||||||
const std::string &spellId = *it;
|
const std::string &spellId = *it;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace MWGui
|
||||||
|
|
||||||
ItemWidget::ItemWidget()
|
ItemWidget::ItemWidget()
|
||||||
: mItem(NULL)
|
: mItem(NULL)
|
||||||
|
, mItemShadow(NULL)
|
||||||
, mFrame(NULL)
|
, mFrame(NULL)
|
||||||
, mText(NULL)
|
, mText(NULL)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +45,9 @@ namespace MWGui
|
||||||
assignWidget(mItem, "Item");
|
assignWidget(mItem, "Item");
|
||||||
if (mItem)
|
if (mItem)
|
||||||
mItem->setNeedMouseFocus(false);
|
mItem->setNeedMouseFocus(false);
|
||||||
|
assignWidget(mItemShadow, "ItemShadow");
|
||||||
|
if (mItemShadow)
|
||||||
|
mItemShadow->setNeedMouseFocus(false);
|
||||||
assignWidget(mFrame, "Frame");
|
assignWidget(mFrame, "Frame");
|
||||||
if (mFrame)
|
if (mFrame)
|
||||||
mFrame->setNeedMouseFocus(false);
|
mFrame->setNeedMouseFocus(false);
|
||||||
|
@ -63,6 +67,8 @@ namespace MWGui
|
||||||
|
|
||||||
void ItemWidget::setIcon(const std::string &icon)
|
void ItemWidget::setIcon(const std::string &icon)
|
||||||
{
|
{
|
||||||
|
if (mItemShadow)
|
||||||
|
mItemShadow->setImageTexture(icon);
|
||||||
if (mItem)
|
if (mItem)
|
||||||
mItem->setImageTexture(icon);
|
mItem->setImageTexture(icon);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +85,10 @@ namespace MWGui
|
||||||
|
|
||||||
void ItemWidget::setIcon(const MWWorld::Ptr &ptr)
|
void ItemWidget::setIcon(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
setIcon(MWBase::Environment::get().getWindowManager()->correctIconPath(ptr.getClass().getInventoryIcon(ptr)));
|
std::string invIcon = ptr.getClass().getInventoryIcon(ptr);
|
||||||
|
if (invIcon.empty())
|
||||||
|
invIcon = "default icon.tga";
|
||||||
|
setIcon(MWBase::Environment::get().getWindowManager()->correctIconPath(invIcon));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace MWGui
|
||||||
virtual void initialiseOverride();
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
MyGUI::ImageBox* mItem;
|
MyGUI::ImageBox* mItem;
|
||||||
|
MyGUI::ImageBox* mItemShadow;
|
||||||
MyGUI::ImageBox* mFrame;
|
MyGUI::ImageBox* mFrame;
|
||||||
MyGUI::TextBox* mText;
|
MyGUI::TextBox* mText;
|
||||||
};
|
};
|
||||||
|
|
|
@ -559,8 +559,8 @@ namespace MWGui
|
||||||
|
|
||||||
std::vector<std::string> destNotes;
|
std::vector<std::string> destNotes;
|
||||||
CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest);
|
CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest);
|
||||||
for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it)
|
for (CustomMarkerCollection::ContainerType::const_iterator iter = markers.first; iter != markers.second; ++iter)
|
||||||
destNotes.push_back(it->second.mNote);
|
destNotes.push_back(iter->second.mNote);
|
||||||
|
|
||||||
MarkerUserData data (mLocalMapRender);
|
MarkerUserData data (mLocalMapRender);
|
||||||
data.notes = destNotes;
|
data.notes = destNotes;
|
||||||
|
|
|
@ -476,16 +476,16 @@ namespace MWGui
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
MWWorld::Ptr item;
|
MWWorld::Ptr item;
|
||||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
for (MWWorld::ContainerStoreIterator iter = store.begin(); iter != store.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id))
|
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id))
|
||||||
{
|
{
|
||||||
if (item.isEmpty() ||
|
if (item.isEmpty() ||
|
||||||
// Prefer the stack with the lowest remaining uses
|
// Prefer the stack with the lowest remaining uses
|
||||||
!item.getClass().hasItemHealth(*it) ||
|
!item.getClass().hasItemHealth(*iter) ||
|
||||||
it->getClass().getItemHealth(*it) < item.getClass().getItemHealth(item))
|
iter->getClass().getItemHealth(*iter) < item.getClass().getItemHealth(item))
|
||||||
{
|
{
|
||||||
item = *it;
|
item = *iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,10 +362,10 @@ namespace MWGui
|
||||||
std::sort(items.begin(), items.end(), sortRaces);
|
std::sort(items.begin(), items.end(), sortRaces);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (std::vector<std::pair<std::string, std::string> >::const_iterator it = items.begin(); it != items.end(); ++it)
|
for (std::vector<std::pair<std::string, std::string> >::const_iterator iter = items.begin(); iter != items.end(); ++iter)
|
||||||
{
|
{
|
||||||
mRaceList->addItem(it->second, it->first);
|
mRaceList->addItem(iter->second, iter->first);
|
||||||
if (Misc::StringUtils::ciEqual(it->first, mCurrentRaceId))
|
if (Misc::StringUtils::ciEqual(iter->first, mCurrentRaceId))
|
||||||
mRaceList->setIndexSelected(index);
|
mRaceList->setIndexSelected(index);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1046,8 +1046,9 @@ namespace MWMechanics
|
||||||
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
|
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||||
{
|
{
|
||||||
MWWorld::Ptr actor = iter->first; // make a copy of the map key to avoid it being invalidated when the player teleports
|
MWWorld::Ptr actor = iter->first; // make a copy of the map key to avoid it being invalidated when the player teleports
|
||||||
|
bool cellChanged = MWBase::Environment::get().getWorld()->hasCellChanged();
|
||||||
updateActor(actor, duration);
|
updateActor(actor, duration);
|
||||||
if (MWBase::Environment::get().getWorld()->hasCellChanged())
|
if (!cellChanged && MWBase::Environment::get().getWorld()->hasCellChanged())
|
||||||
{
|
{
|
||||||
return; // for now abort update of the old cell when cell changes by teleportation magic effect
|
return; // for now abort update of the old cell when cell changes by teleportation magic effect
|
||||||
// a better solution might be to apply cell changes at the end of the frame
|
// a better solution might be to apply cell changes at the end of the frame
|
||||||
|
|
|
@ -91,8 +91,8 @@ std::list<AiPackage*>::const_iterator AiSequence::erase(std::list<AiPackage*>::c
|
||||||
{
|
{
|
||||||
if (package == it)
|
if (package == it)
|
||||||
{
|
{
|
||||||
AiPackage* package = *it;
|
AiPackage* packagePtr = *it;
|
||||||
delete package;
|
delete packagePtr;
|
||||||
return mPackages.erase(it);
|
return mPackages.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ void MWMechanics::Alchemy::applyTools (int flags, float& value) const
|
||||||
bool duration = !(flags & ESM::MagicEffect::NoDuration);
|
bool duration = !(flags & ESM::MagicEffect::NoDuration);
|
||||||
bool negative = (flags & ESM::MagicEffect::Harmful) != 0;
|
bool negative = (flags & ESM::MagicEffect::Harmful) != 0;
|
||||||
|
|
||||||
int tool = negative ? ESM::Apparatus::Retort : ESM::Apparatus::Albemic;
|
int tool = negative ? ESM::Apparatus::Alembic : ESM::Apparatus::Retort;
|
||||||
|
|
||||||
int setup = 0;
|
int setup = 0;
|
||||||
|
|
||||||
|
|
|
@ -478,28 +478,28 @@ void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterStat
|
||||||
mIdleState = idle;
|
mIdleState = idle;
|
||||||
size_t numLoops = ~0ul;
|
size_t numLoops = ~0ul;
|
||||||
|
|
||||||
std::string idle;
|
std::string idleGroup;
|
||||||
MWRender::Animation::AnimPriority idlePriority (Priority_Default);
|
MWRender::Animation::AnimPriority idlePriority (Priority_Default);
|
||||||
// Only play "idleswim" or "idlesneak" if they exist. Otherwise, fallback to
|
// Only play "idleswim" or "idlesneak" if they exist. Otherwise, fallback to
|
||||||
// "idle"+weapon or "idle".
|
// "idle"+weapon or "idle".
|
||||||
if(mIdleState == CharState_IdleSwim && mAnimation->hasAnimation("idleswim"))
|
if(mIdleState == CharState_IdleSwim && mAnimation->hasAnimation("idleswim"))
|
||||||
{
|
{
|
||||||
idle = "idleswim";
|
idleGroup = "idleswim";
|
||||||
idlePriority = Priority_SwimIdle;
|
idlePriority = Priority_SwimIdle;
|
||||||
}
|
}
|
||||||
else if(mIdleState == CharState_IdleSneak && mAnimation->hasAnimation("idlesneak"))
|
else if(mIdleState == CharState_IdleSneak && mAnimation->hasAnimation("idlesneak"))
|
||||||
{
|
{
|
||||||
idle = "idlesneak";
|
idleGroup = "idlesneak";
|
||||||
idlePriority[MWRender::Animation::BoneGroup_LowerBody] = Priority_SneakIdleLowerBody;
|
idlePriority[MWRender::Animation::BoneGroup_LowerBody] = Priority_SneakIdleLowerBody;
|
||||||
}
|
}
|
||||||
else if(mIdleState != CharState_None)
|
else if(mIdleState != CharState_None)
|
||||||
{
|
{
|
||||||
idle = "idle";
|
idleGroup = "idle";
|
||||||
if(weap != sWeaponTypeListEnd)
|
if(weap != sWeaponTypeListEnd)
|
||||||
{
|
{
|
||||||
idle += weap->shortgroup;
|
idleGroup += weap->shortgroup;
|
||||||
if(!mAnimation->hasAnimation(idle))
|
if(!mAnimation->hasAnimation(idleGroup))
|
||||||
idle = "idle";
|
idleGroup = "idle";
|
||||||
|
|
||||||
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
||||||
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
||||||
|
@ -508,7 +508,7 @@ void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterStat
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimation->disable(mCurrentIdle);
|
mAnimation->disable(mCurrentIdle);
|
||||||
mCurrentIdle = idle;
|
mCurrentIdle = idleGroup;
|
||||||
if(!mCurrentIdle.empty())
|
if(!mCurrentIdle.empty())
|
||||||
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
||||||
1.0f, "start", "stop", 0.0f, numLoops, true);
|
1.0f, "start", "stop", 0.0f, numLoops, true);
|
||||||
|
@ -571,8 +571,8 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I
|
||||||
else if(type == typeid(ESM::Weapon).name())
|
else if(type == typeid(ESM::Weapon).name())
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Weapon> *ref = weapon->get<ESM::Weapon>();
|
MWWorld::LiveCellRef<ESM::Weapon> *ref = weapon->get<ESM::Weapon>();
|
||||||
ESM::Weapon::Type type = (ESM::Weapon::Type)ref->mBase->mData.mType;
|
ESM::Weapon::Type weaponType = (ESM::Weapon::Type)ref->mBase->mData.mType;
|
||||||
switch(type)
|
switch(weaponType)
|
||||||
{
|
{
|
||||||
case ESM::Weapon::ShortBladeOneHand:
|
case ESM::Weapon::ShortBladeOneHand:
|
||||||
case ESM::Weapon::LongBladeOneHand:
|
case ESM::Weapon::LongBladeOneHand:
|
||||||
|
@ -1745,14 +1745,12 @@ void CharacterController::update(float duration)
|
||||||
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
|
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
|
||||||
|
|
||||||
// decrease fatigue
|
// decrease fatigue
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
|
||||||
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
|
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
|
||||||
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
|
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
|
||||||
float normalizedEncumbrance = mPtr.getClass().getNormalizedEncumbrance(mPtr);
|
float normalizedEncumbrance = mPtr.getClass().getNormalizedEncumbrance(mPtr);
|
||||||
if (normalizedEncumbrance > 1)
|
if (normalizedEncumbrance > 1)
|
||||||
normalizedEncumbrance = 1;
|
normalizedEncumbrance = 1;
|
||||||
const float fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
|
const float fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
|
||||||
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
|
|
||||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
|
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
|
||||||
cls.getCreatureStats(mPtr).setFatigue(fatigue);
|
cls.getCreatureStats(mPtr).setFatigue(fatigue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,8 @@ void MWMechanics::NpcStats::raiseRank(const std::string &faction)
|
||||||
if (it != mFactionRank.end())
|
if (it != mFactionRank.end())
|
||||||
{
|
{
|
||||||
// Does the next rank exist?
|
// Does the next rank exist?
|
||||||
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(lower);
|
const ESM::Faction* factionPtr = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(lower);
|
||||||
if (it->second+1 < 10 && !faction->mRanks[it->second+1].empty())
|
if (it->second+1 < 10 && !factionPtr->mRanks[it->second+1].empty())
|
||||||
it->second += 1;
|
it->second += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,6 +482,9 @@ namespace MWMechanics
|
||||||
ActiveSpells::ActiveEffect effect;
|
ActiveSpells::ActiveEffect effect;
|
||||||
effect.mEffectId = effectIt->mEffectID;
|
effect.mEffectId = effectIt->mEffectID;
|
||||||
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
||||||
|
if (!hasDuration)
|
||||||
|
effect.mDuration = 1.0f;
|
||||||
|
else
|
||||||
effect.mDuration = static_cast<float>(effectIt->mDuration);
|
effect.mDuration = static_cast<float>(effectIt->mDuration);
|
||||||
effect.mMagnitude = magnitude;
|
effect.mMagnitude = magnitude;
|
||||||
|
|
||||||
|
@ -497,13 +500,13 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i)
|
if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i)
|
||||||
{
|
{
|
||||||
std::vector<ActiveSpells::ActiveEffect> effects;
|
std::vector<ActiveSpells::ActiveEffect> absorbEffects;
|
||||||
ActiveSpells::ActiveEffect effect_ = effect;
|
ActiveSpells::ActiveEffect effect_ = effect;
|
||||||
effect_.mMagnitude *= -1;
|
effect_.mMagnitude *= -1;
|
||||||
effects.push_back(effect_);
|
absorbEffects.push_back(effect_);
|
||||||
// Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies
|
// Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies
|
||||||
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
||||||
effects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
|
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,11 +517,11 @@ namespace MWMechanics
|
||||||
if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor())
|
if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor())
|
||||||
{
|
{
|
||||||
CreatureStats& targetStats = target.getClass().getCreatureStats(target);
|
CreatureStats& targetStats = target.getClass().getCreatureStats(target);
|
||||||
std::map<CreatureStats::SummonKey, int>::iterator found = targetStats.getSummonedCreatureMap().find(std::make_pair(effectIt->mEffectID, mId));
|
std::map<CreatureStats::SummonKey, int>::iterator findCreature = targetStats.getSummonedCreatureMap().find(std::make_pair(effectIt->mEffectID, mId));
|
||||||
if (found != targetStats.getSummonedCreatureMap().end())
|
if (findCreature != targetStats.getSummonedCreatureMap().end())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, found->second);
|
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, findCreature->second);
|
||||||
targetStats.getSummonedCreatureMap().erase(found);
|
targetStats.getSummonedCreatureMap().erase(findCreature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,36 +615,8 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target.getClass().isActor())
|
else if (target.getClass().isActor() && target == getPlayer())
|
||||||
{
|
{
|
||||||
switch (effectId)
|
|
||||||
{
|
|
||||||
case ESM::MagicEffect::CurePoison:
|
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::CureParalyzation:
|
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze);
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::CureCommonDisease:
|
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease();
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::CureBlightDisease:
|
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease();
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::CureCorprusDisease:
|
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::Dispel:
|
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
|
|
||||||
return true;
|
|
||||||
case ESM::MagicEffect::RemoveCurse:
|
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target != getPlayer())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
||||||
|
|
||||||
if (effectId == ESM::MagicEffect::DivineIntervention)
|
if (effectId == ESM::MagicEffect::DivineIntervention)
|
||||||
|
@ -664,7 +639,6 @@ namespace MWMechanics
|
||||||
anim->addEffect("meshes\\" + fx->mModel, -1);
|
anim->addEffect("meshes\\" + fx->mModel, -1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (effectId == ESM::MagicEffect::Mark)
|
else if (effectId == ESM::MagicEffect::Mark)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||||
|
@ -1176,6 +1150,27 @@ namespace MWMechanics
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ESM::MagicEffect::CurePoison:
|
||||||
|
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::CureParalyzation:
|
||||||
|
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze);
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::CureCommonDisease:
|
||||||
|
actor.getClass().getCreatureStats(actor).getSpells().purgeCommonDisease();
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::CureBlightDisease:
|
||||||
|
actor.getClass().getCreatureStats(actor).getSpells().purgeBlightDisease();
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::CureCorprusDisease:
|
||||||
|
actor.getClass().getCreatureStats(actor).getSpells().purgeCorprusDisease();
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::Dispel:
|
||||||
|
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeAll(magnitude);
|
||||||
|
break;
|
||||||
|
case ESM::MagicEffect::RemoveCurse:
|
||||||
|
actor.getClass().getCreatureStats(actor).getSpells().purgeCurses();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (receivedMagicDamage && actor == getPlayer())
|
if (receivedMagicDamage && actor == getPlayer())
|
||||||
|
|
131
apps/openmw/mwrender/actoranimation.cpp
Normal file
131
apps/openmw/mwrender/actoranimation.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include "actoranimation.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/Group>
|
||||||
|
#include <osg/Vec4f>
|
||||||
|
|
||||||
|
#include <components/esm/loadligh.hpp>
|
||||||
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
#include <components/sceneutil/lightutil.hpp>
|
||||||
|
|
||||||
|
#include <components/fallback/fallback.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
#include "vismask.hpp"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
ActorAnimation::ActorAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
|
||||||
|
bool disableListener)
|
||||||
|
: Animation(ptr, parentNode, resourceSystem),
|
||||||
|
mListenerDisabled(disableListener)
|
||||||
|
{
|
||||||
|
MWWorld::ContainerStore& store = mPtr.getClass().getContainerStore(mPtr);
|
||||||
|
|
||||||
|
for (MWWorld::ContainerStoreIterator iter = store.begin(MWWorld::ContainerStore::Type_Light); iter != store.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::Light* light = iter->get<ESM::Light>()->mBase;
|
||||||
|
if (!(light->mData.mFlags & ESM::Light::Carry))
|
||||||
|
{
|
||||||
|
addHiddenItemLight(*iter, light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mListenerDisabled)
|
||||||
|
store.setContListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorAnimation::~ActorAnimation()
|
||||||
|
{
|
||||||
|
if (!mListenerDisabled && mPtr.getRefData().getCustomData() && mPtr.getClass().getContainerStore(mPtr).getContListener() == this)
|
||||||
|
mPtr.getClass().getContainerStore(mPtr).setContListener(NULL);
|
||||||
|
|
||||||
|
for (ItemLightMap::iterator iter = mItemLights.begin(); iter != mItemLights.end(); ++iter)
|
||||||
|
{
|
||||||
|
mInsert->removeChild(iter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorAnimation::itemAdded(const MWWorld::ConstPtr& item, int /*count*/)
|
||||||
|
{
|
||||||
|
if (item.getTypeName() == typeid(ESM::Light).name())
|
||||||
|
{
|
||||||
|
const ESM::Light* light = item.get<ESM::Light>()->mBase;
|
||||||
|
if (!(light->mData.mFlags & ESM::Light::Carry))
|
||||||
|
{
|
||||||
|
addHiddenItemLight(item, light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorAnimation::itemRemoved(const MWWorld::ConstPtr& item, int /*count*/)
|
||||||
|
{
|
||||||
|
if (item.getTypeName() == typeid(ESM::Light).name())
|
||||||
|
{
|
||||||
|
ItemLightMap::iterator iter = mItemLights.find(item);
|
||||||
|
if (iter != mItemLights.end())
|
||||||
|
{
|
||||||
|
if (!item.getRefData().getCount())
|
||||||
|
{
|
||||||
|
removeHiddenItemLight(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorAnimation::addHiddenItemLight(const MWWorld::ConstPtr& item, const ESM::Light* esmLight)
|
||||||
|
{
|
||||||
|
if (mItemLights.find(item) != mItemLights.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||||
|
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
||||||
|
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||||
|
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
||||||
|
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||||
|
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
||||||
|
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||||
|
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
||||||
|
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
||||||
|
|
||||||
|
osg::Vec4f ambient(1,1,1,1);
|
||||||
|
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin,
|
||||||
|
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient);
|
||||||
|
|
||||||
|
mInsert->addChild(lightSource);
|
||||||
|
|
||||||
|
if (mLightListCallback && mPtr == MWMechanics::getPlayer())
|
||||||
|
mLightListCallback->getIgnoredLightSources().insert(lightSource.get());
|
||||||
|
|
||||||
|
mItemLights.insert(std::make_pair(item, lightSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorAnimation::removeHiddenItemLight(const MWWorld::ConstPtr& item)
|
||||||
|
{
|
||||||
|
ItemLightMap::iterator iter = mItemLights.find(item);
|
||||||
|
if (iter == mItemLights.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mLightListCallback && mPtr == MWMechanics::getPlayer())
|
||||||
|
{
|
||||||
|
std::set<SceneUtil::LightSource*>::iterator ignoredIter = mLightListCallback->getIgnoredLightSources().find(iter->second.get());
|
||||||
|
if (ignoredIter != mLightListCallback->getIgnoredLightSources().end())
|
||||||
|
mLightListCallback->getIgnoredLightSources().erase(ignoredIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
mInsert->removeChild(iter->second);
|
||||||
|
mItemLights.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
apps/openmw/mwrender/actoranimation.hpp
Normal file
53
apps/openmw/mwrender/actoranimation.hpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef GAME_RENDER_ACTORANIMATION_H
|
||||||
|
#define GAME_RENDER_ACTORANIMATION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
|
#include "animation.hpp"
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class ConstPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
class LightSource;
|
||||||
|
class LightListCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
class ActorAnimation : public Animation, public MWWorld::ContainerStoreListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActorAnimation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
|
||||||
|
bool disableListener=false);
|
||||||
|
virtual ~ActorAnimation();
|
||||||
|
|
||||||
|
virtual void itemAdded(const MWWorld::ConstPtr& item, int count);
|
||||||
|
virtual void itemRemoved(const MWWorld::ConstPtr& item, int count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addHiddenItemLight(const MWWorld::ConstPtr& item, const ESM::Light* esmLight);
|
||||||
|
void removeHiddenItemLight(const MWWorld::ConstPtr& item);
|
||||||
|
|
||||||
|
typedef std::map<MWWorld::ConstPtr, osg::ref_ptr<SceneUtil::LightSource> > ItemLightMap;
|
||||||
|
ItemLightMap mItemLights;
|
||||||
|
|
||||||
|
bool mListenerDisabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -429,6 +429,8 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < sNumBlendMasks;i++)
|
for(size_t i = 0;i < sNumBlendMasks;i++)
|
||||||
mAnimationTimePtr[i].reset(new AnimationTime);
|
mAnimationTimePtr[i].reset(new AnimationTime);
|
||||||
|
|
||||||
|
mLightListCallback = new SceneUtil::LightListCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::~Animation()
|
Animation::~Animation()
|
||||||
|
@ -1095,6 +1097,8 @@ namespace MWRender
|
||||||
osg::ref_ptr<osg::StateSet> previousStateset;
|
osg::ref_ptr<osg::StateSet> previousStateset;
|
||||||
if (mObjectRoot)
|
if (mObjectRoot)
|
||||||
{
|
{
|
||||||
|
if (mLightListCallback)
|
||||||
|
mObjectRoot->removeCullCallback(mLightListCallback);
|
||||||
previousStateset = mObjectRoot->getStateSet();
|
previousStateset = mObjectRoot->getStateSet();
|
||||||
mObjectRoot->getParent(0)->removeChild(mObjectRoot);
|
mObjectRoot->getParent(0)->removeChild(mObjectRoot);
|
||||||
}
|
}
|
||||||
|
@ -1150,7 +1154,9 @@ namespace MWRender
|
||||||
removeTriBipVisitor.remove();
|
removeTriBipVisitor.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
mObjectRoot->addCullCallback(new SceneUtil::LightListCallback);
|
if (!mLightListCallback)
|
||||||
|
mLightListCallback = new SceneUtil::LightListCallback;
|
||||||
|
mObjectRoot->addCullCallback(mLightListCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Group* Animation::getObjectRoot()
|
osg::Group* Animation::getObjectRoot()
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace NifOsg
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class LightSource;
|
class LightSource;
|
||||||
|
class LightListCallback;
|
||||||
class Skeleton;
|
class Skeleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +274,8 @@ protected:
|
||||||
|
|
||||||
float mAlpha;
|
float mAlpha;
|
||||||
|
|
||||||
|
osg::ref_ptr<SceneUtil::LightListCallback> mLightListCallback;
|
||||||
|
|
||||||
const NodeMap& getNodeMap() const;
|
const NodeMap& getNodeMap() const;
|
||||||
|
|
||||||
/* Sets the appropriate animations on the bone groups based on priority.
|
/* Sets the appropriate animations on the bone groups based on priority.
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MWRender
|
||||||
|
|
||||||
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
||||||
const std::string& model, Resource::ResourceSystem* resourceSystem)
|
const std::string& model, Resource::ResourceSystem* resourceSystem)
|
||||||
: Animation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
: ActorAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
||||||
|
|
||||||
|
|
||||||
CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem)
|
CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem)
|
||||||
: Animation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
: ActorAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
||||||
, mShowWeapons(false)
|
, mShowWeapons(false)
|
||||||
, mShowCarriedLeft(false)
|
, mShowCarriedLeft(false)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const
|
||||||
addAnimSource("meshes\\xbase_anim.nif");
|
addAnimSource("meshes\\xbase_anim.nif");
|
||||||
addAnimSource(model);
|
addAnimSource(model);
|
||||||
|
|
||||||
mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr);
|
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
||||||
|
|
||||||
updateParts();
|
updateParts();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_RENDER_CREATUREANIMATION_H
|
#ifndef GAME_RENDER_CREATUREANIMATION_H
|
||||||
#define GAME_RENDER_CREATUREANIMATION_H
|
#define GAME_RENDER_CREATUREANIMATION_H
|
||||||
|
|
||||||
#include "animation.hpp"
|
#include "actoranimation.hpp"
|
||||||
#include "weaponanimation.hpp"
|
#include "weaponanimation.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace MWWorld
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
class CreatureAnimation : public Animation
|
class CreatureAnimation : public ActorAnimation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreatureAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem);
|
CreatureAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem);
|
||||||
|
@ -22,7 +22,7 @@ namespace MWRender
|
||||||
// For creatures with weapons and shields
|
// For creatures with weapons and shields
|
||||||
// Animation is already virtual anyway, so might as well make a separate class.
|
// Animation is already virtual anyway, so might as well make a separate class.
|
||||||
// Most creatures don't need weapons/shields, so this will save some memory.
|
// Most creatures don't need weapons/shields, so this will save some memory.
|
||||||
class CreatureWeaponAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener
|
class CreatureWeaponAnimation : public ActorAnimation, public WeaponAnimation, public MWWorld::InventoryStoreListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem);
|
CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <components/sceneutil/attach.hpp>
|
#include <components/sceneutil/attach.hpp>
|
||||||
#include <components/sceneutil/visitor.hpp>
|
#include <components/sceneutil/visitor.hpp>
|
||||||
#include <components/sceneutil/skeleton.hpp>
|
#include <components/sceneutil/skeleton.hpp>
|
||||||
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp> // TextKeyMapHolder
|
#include <components/nifosg/nifloader.hpp> // TextKeyMapHolder
|
||||||
|
|
||||||
|
@ -272,8 +273,8 @@ NpcAnimation::~NpcAnimation()
|
||||||
// No need to getInventoryStore() to reset, if none exists
|
// No need to getInventoryStore() to reset, if none exists
|
||||||
// This is to avoid triggering the listener via ensureCustomData()->autoEquip()->fireEquipmentChanged()
|
// This is to avoid triggering the listener via ensureCustomData()->autoEquip()->fireEquipmentChanged()
|
||||||
// all from within this destructor. ouch!
|
// all from within this destructor. ouch!
|
||||||
&& mPtr.getRefData().getCustomData() && mPtr.getClass().getInventoryStore(mPtr).getListener() == this)
|
&& mPtr.getRefData().getCustomData() && mPtr.getClass().getInventoryStore(mPtr).getInvListener() == this)
|
||||||
mPtr.getClass().getInventoryStore(mPtr).setListener(NULL, mPtr);
|
mPtr.getClass().getInventoryStore(mPtr).setInvListener(NULL, mPtr);
|
||||||
|
|
||||||
// do not detach (delete) parts yet, this is done so the background thread can handle the deletion
|
// do not detach (delete) parts yet, this is done so the background thread can handle the deletion
|
||||||
for(size_t i = 0;i < ESM::PRT_Count;i++)
|
for(size_t i = 0;i < ESM::PRT_Count;i++)
|
||||||
|
@ -285,7 +286,7 @@ NpcAnimation::~NpcAnimation()
|
||||||
|
|
||||||
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
|
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
|
||||||
bool disableListener, bool disableSounds, ViewMode viewMode, float firstPersonFieldOfView)
|
bool disableListener, bool disableSounds, ViewMode viewMode, float firstPersonFieldOfView)
|
||||||
: Animation(ptr, parentNode, resourceSystem),
|
: ActorAnimation(ptr, parentNode, resourceSystem, disableListener),
|
||||||
mListenerDisabled(disableListener),
|
mListenerDisabled(disableListener),
|
||||||
mViewMode(viewMode),
|
mViewMode(viewMode),
|
||||||
mShowWeapons(false),
|
mShowWeapons(false),
|
||||||
|
@ -310,7 +311,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> par
|
||||||
updateNpcBase();
|
updateNpcBase();
|
||||||
|
|
||||||
if (!disableListener)
|
if (!disableListener)
|
||||||
mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr);
|
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
|
#include "actoranimation.hpp"
|
||||||
#include "weaponanimation.hpp"
|
#include "weaponanimation.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -19,7 +20,7 @@ namespace MWRender
|
||||||
class NeckController;
|
class NeckController;
|
||||||
class HeadAnimationTime;
|
class HeadAnimationTime;
|
||||||
|
|
||||||
class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener
|
class NpcAnimation : public ActorAnimation, public WeaponAnimation, public MWWorld::InventoryStoreListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void equipmentChanged();
|
virtual void equipmentChanged();
|
||||||
|
|
|
@ -112,12 +112,12 @@ bool Objects::removeObject (const MWWorld::Ptr& ptr)
|
||||||
PtrAnimationMap::iterator iter = mObjects.find(ptr);
|
PtrAnimationMap::iterator iter = mObjects.find(ptr);
|
||||||
if(iter != mObjects.end())
|
if(iter != mObjects.end())
|
||||||
{
|
{
|
||||||
|
if (mUnrefQueue.get())
|
||||||
|
mUnrefQueue->push(iter->second->getObjectRoot());
|
||||||
|
|
||||||
delete iter->second;
|
delete iter->second;
|
||||||
mObjects.erase(iter);
|
mObjects.erase(iter);
|
||||||
|
|
||||||
if (mUnrefQueue.get())
|
|
||||||
mUnrefQueue->push(ptr.getRefData().getBaseNode());
|
|
||||||
|
|
||||||
ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
|
ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
|
||||||
|
|
||||||
ptr.getRefData().setBaseNode(NULL);
|
ptr.getRefData().setBaseNode(NULL);
|
||||||
|
|
|
@ -3,12 +3,16 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
|
||||||
#include "openal_output.hpp"
|
#include "openal_output.hpp"
|
||||||
#include "sound_decoder.hpp"
|
#include "sound_decoder.hpp"
|
||||||
|
@ -243,31 +247,31 @@ const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f;
|
||||||
//
|
//
|
||||||
// A background streaming thread (keeps active streams processed)
|
// A background streaming thread (keeps active streams processed)
|
||||||
//
|
//
|
||||||
struct OpenAL_Output::StreamThread {
|
struct OpenAL_Output::StreamThread : public OpenThreads::Thread {
|
||||||
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
||||||
StreamVec mStreams;
|
StreamVec mStreams;
|
||||||
|
|
||||||
volatile bool mQuitNow;
|
volatile bool mQuitNow;
|
||||||
boost::mutex mMutex;
|
OpenThreads::Mutex mMutex;
|
||||||
boost::condition_variable mCondVar;
|
OpenThreads::Condition mCondVar;
|
||||||
boost::thread mThread;
|
|
||||||
|
|
||||||
StreamThread()
|
StreamThread()
|
||||||
: mQuitNow(false), mThread(boost::ref(*this))
|
: mQuitNow(false)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
}
|
}
|
||||||
~StreamThread()
|
~StreamThread()
|
||||||
{
|
{
|
||||||
mQuitNow = true;
|
mQuitNow = true;
|
||||||
mMutex.lock(); mMutex.unlock();
|
mMutex.lock(); mMutex.unlock();
|
||||||
mCondVar.notify_all();
|
mCondVar.broadcast();
|
||||||
mThread.join();
|
join();
|
||||||
}
|
}
|
||||||
|
|
||||||
// boost::thread entry point
|
// thread entry point
|
||||||
void operator()()
|
virtual void run()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
while(!mQuitNow)
|
while(!mQuitNow)
|
||||||
{
|
{
|
||||||
StreamVec::iterator iter = mStreams.begin();
|
StreamVec::iterator iter = mStreams.begin();
|
||||||
|
@ -279,31 +283,30 @@ struct OpenAL_Output::StreamThread {
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCondVar.timed_wait(lock, boost::posix_time::milliseconds(50));
|
mCondVar.wait(&mMutex, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(OpenAL_SoundStream *stream)
|
void add(OpenAL_SoundStream *stream)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
if(std::find(mStreams.begin(), mStreams.end(), stream) == mStreams.end())
|
if(std::find(mStreams.begin(), mStreams.end(), stream) == mStreams.end())
|
||||||
{
|
{
|
||||||
mStreams.push_back(stream);
|
mStreams.push_back(stream);
|
||||||
lock.unlock();
|
mCondVar.broadcast();
|
||||||
mCondVar.notify_all();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(OpenAL_SoundStream *stream)
|
void remove(OpenAL_SoundStream *stream)
|
||||||
{
|
{
|
||||||
boost::lock_guard<boost::mutex> lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
StreamVec::iterator iter = std::find(mStreams.begin(), mStreams.end(), stream);
|
StreamVec::iterator iter = std::find(mStreams.begin(), mStreams.end(), stream);
|
||||||
if(iter != mStreams.end()) mStreams.erase(iter);
|
if(iter != mStreams.end()) mStreams.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAll()
|
void removeAll()
|
||||||
{
|
{
|
||||||
boost::lock_guard<boost::mutex> lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
mStreams.clear();
|
mStreams.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +471,7 @@ ALint OpenAL_SoundStream::refillQueue()
|
||||||
if(got < data.size())
|
if(got < data.size())
|
||||||
{
|
{
|
||||||
mIsFinished = true;
|
mIsFinished = true;
|
||||||
memset(&data[got], mSilence, data.size()-got);
|
std::memset(&data[got], mSilence, data.size()-got);
|
||||||
}
|
}
|
||||||
if(got > 0)
|
if(got > 0)
|
||||||
{
|
{
|
||||||
|
@ -1023,7 +1026,7 @@ double OpenAL_Output::getStreamOffset(MWBase::SoundStreamPtr sound)
|
||||||
{
|
{
|
||||||
if(!sound->mHandle) return 0.0;
|
if(!sound->mHandle) return 0.0;
|
||||||
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
||||||
boost::lock_guard<boost::mutex> lock(mStreamThread->mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mStreamThread->mMutex);
|
||||||
return stream->getStreamOffset();
|
return stream->getStreamOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,7 +1034,7 @@ float OpenAL_Output::getStreamLoudness(MWBase::SoundStreamPtr sound)
|
||||||
{
|
{
|
||||||
if(!sound->mHandle) return 0.0;
|
if(!sound->mHandle) return 0.0;
|
||||||
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
||||||
boost::lock_guard<boost::mutex> lock(mStreamThread->mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mStreamThread->mMutex);
|
||||||
return stream->getCurrentLoudness();
|
return stream->getCurrentLoudness();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,7 +1042,7 @@ bool OpenAL_Output::isStreamPlaying(MWBase::SoundStreamPtr sound)
|
||||||
{
|
{
|
||||||
if(!sound->mHandle) return false;
|
if(!sound->mHandle) return false;
|
||||||
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
OpenAL_SoundStream *stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
||||||
boost::lock_guard<boost::mutex> lock(mStreamThread->mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mStreamThread->mMutex);
|
||||||
return stream->isPlaying();
|
return stream->isPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ void MWWorld::ContainerStore::storeStates (const CellRefList<T>& collection,
|
||||||
|
|
||||||
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
|
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
|
||||||
|
|
||||||
MWWorld::ContainerStore::ContainerStore() : mCachedWeight (0), mWeightUpToDate (false) {}
|
MWWorld::ContainerStore::ContainerStore() : mListener(NULL), mCachedWeight (0), mWeightUpToDate (false) {}
|
||||||
|
|
||||||
MWWorld::ContainerStore::~ContainerStore() {}
|
MWWorld::ContainerStore::~ContainerStore() {}
|
||||||
|
|
||||||
|
@ -136,6 +136,17 @@ int MWWorld::ContainerStore::count(const std::string &id)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreListener* MWWorld::ContainerStore::getContListener() const
|
||||||
|
{
|
||||||
|
return mListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MWWorld::ContainerStore::setContListener(MWWorld::ContainerStoreListener* listener)
|
||||||
|
{
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container, int count)
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container, int count)
|
||||||
{
|
{
|
||||||
if (ptr.getRefData().getCount() <= count)
|
if (ptr.getRefData().getCount() <= count)
|
||||||
|
@ -292,6 +303,9 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
||||||
item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
|
item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mListener)
|
||||||
|
mListener->itemAdded(item, count);
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +412,9 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
|
||||||
|
|
||||||
flagAsModified();
|
flagAsModified();
|
||||||
|
|
||||||
|
if (mListener)
|
||||||
|
mListener->itemRemoved(item, count - toRemove);
|
||||||
|
|
||||||
// number of removed items
|
// number of removed items
|
||||||
return count - toRemove;
|
return count - toRemove;
|
||||||
}
|
}
|
||||||
|
@ -423,12 +440,12 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||||
|
|
||||||
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
||||||
{
|
{
|
||||||
const ESM::ItemLevList* levItem = ref.getPtr().get<ESM::ItemLevList>()->mBase;
|
const ESM::ItemLevList* levItemList = ref.getPtr().get<ESM::ItemLevList>()->mBase;
|
||||||
|
|
||||||
if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each)
|
if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
|
||||||
{
|
{
|
||||||
for (int i=0; i<std::abs(count); ++i)
|
for (int i=0; i<std::abs(count); ++i)
|
||||||
addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItem->mId);
|
addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItemList->mId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -436,7 +453,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||||
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
||||||
if (id.empty())
|
if (id.empty())
|
||||||
return;
|
return;
|
||||||
addInitialItem(id, owner, count, false, levItem->mId);
|
addInitialItem(id, owner, count, false, levItemList->mId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -31,6 +31,13 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
class ContainerStoreIterator;
|
class ContainerStoreIterator;
|
||||||
|
|
||||||
|
class ContainerStoreListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void itemAdded(const ConstPtr& item, int count) {}
|
||||||
|
virtual void itemRemoved(const ConstPtr& item, int count) {}
|
||||||
|
};
|
||||||
|
|
||||||
class ContainerStore
|
class ContainerStore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -73,6 +80,8 @@ namespace MWWorld
|
||||||
///< Stores result of levelled item spawns. <(refId, spawningGroup), count>
|
///< Stores result of levelled item spawns. <(refId, spawningGroup), count>
|
||||||
/// This is used to restock levelled items(s) if the old item was sold.
|
/// This is used to restock levelled items(s) if the old item was sold.
|
||||||
|
|
||||||
|
ContainerStoreListener* mListener;
|
||||||
|
|
||||||
mutable float mCachedWeight;
|
mutable float mCachedWeight;
|
||||||
mutable bool mWeightUpToDate;
|
mutable bool mWeightUpToDate;
|
||||||
ContainerStoreIterator addImp (const Ptr& ptr, int count);
|
ContainerStoreIterator addImp (const Ptr& ptr, int count);
|
||||||
|
@ -143,6 +152,9 @@ namespace MWWorld
|
||||||
/// @return How many items with refID \a id are in this container?
|
/// @return How many items with refID \a id are in this container?
|
||||||
int count (const std::string& id);
|
int count (const std::string& id);
|
||||||
|
|
||||||
|
ContainerStoreListener* getContListener() const;
|
||||||
|
void setContListener(ContainerStoreListener* listener);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ContainerStoreIterator addNewStack (const ConstPtr& ptr, int count);
|
ContainerStoreIterator addNewStack (const ConstPtr& ptr, int count);
|
||||||
///< Add the item to this container (do not try to stack it onto existing items)
|
///< Add the item to this container (do not try to stack it onto existing items)
|
||||||
|
|
|
@ -606,12 +606,12 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(con
|
||||||
return unstack(item, actor, item.getRefData().getCount() - count);
|
return unstack(item, actor, item.getRefData().getCount() - count);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::InventoryStoreListener* MWWorld::InventoryStore::getListener()
|
MWWorld::InventoryStoreListener* MWWorld::InventoryStore::getInvListener()
|
||||||
{
|
{
|
||||||
return mListener;
|
return mListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::InventoryStore::setListener(InventoryStoreListener *listener, const Ptr& actor)
|
void MWWorld::InventoryStore::setInvListener(InventoryStoreListener *listener, const Ptr& actor)
|
||||||
{
|
{
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
updateMagicEffects(actor);
|
updateMagicEffects(actor);
|
||||||
|
|
|
@ -197,10 +197,10 @@ namespace MWWorld
|
||||||
/// in the slot (they can be re-stacked so its count may be different
|
/// in the slot (they can be re-stacked so its count may be different
|
||||||
/// than the requested count).
|
/// than the requested count).
|
||||||
|
|
||||||
void setListener (InventoryStoreListener* listener, const Ptr& actor);
|
void setInvListener (InventoryStoreListener* listener, const Ptr& actor);
|
||||||
///< Set a listener for various events, see \a InventoryStoreListener
|
///< Set a listener for various events, see \a InventoryStoreListener
|
||||||
|
|
||||||
InventoryStoreListener* getListener();
|
InventoryStoreListener* getInvListener();
|
||||||
|
|
||||||
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor);
|
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor);
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Ptr player = getPlayer();
|
MWWorld::Ptr player = getPlayer();
|
||||||
const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player);
|
const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player);
|
||||||
if (playerStats.isParalyzed() || playerStats.getKnockedDown())
|
if (playerStats.isParalyzed() || playerStats.getKnockedDown() || playerStats.isDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MWWorld::Ptr toActivate = MWBase::Environment::get().getWorld()->getFacedObject();
|
MWWorld::Ptr toActivate = MWBase::Environment::get().getWorld()->getFacedObject();
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace Compiler
|
||||||
extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone,
|
extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone,
|
||||||
opcodeGetAiPackageDoneExplicit);
|
opcodeGetAiPackageDoneExplicit);
|
||||||
extensions.registerFunction ("getcurrentaipackage", 'l', "", opcodeGetCurrentAiPackage,
|
extensions.registerFunction ("getcurrentaipackage", 'l', "", opcodeGetCurrentAiPackage,
|
||||||
opcodeGetAiPackageDoneExplicit);
|
opcodeGetCurrentAiPackageExplicit);
|
||||||
extensions.registerFunction ("getdetected", 'l', "c", opcodeGetDetected,
|
extensions.registerFunction ("getdetected", 'l', "c", opcodeGetDetected,
|
||||||
opcodeGetDetectedExplicit);
|
opcodeGetDetectedExplicit);
|
||||||
extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit);
|
extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit);
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct Apparatus
|
||||||
enum AppaType
|
enum AppaType
|
||||||
{
|
{
|
||||||
MortarPestle = 0,
|
MortarPestle = 0,
|
||||||
Albemic = 1,
|
Alembic = 1,
|
||||||
Calcinator = 2,
|
Calcinator = 2,
|
||||||
Retort = 3
|
Retort = 3
|
||||||
};
|
};
|
||||||
|
|
|
@ -356,8 +356,7 @@ short MagicEffect::getWeaknessEffect(short effect)
|
||||||
effects[Corprus] = WeaknessToCorprusDisease;
|
effects[Corprus] = WeaknessToCorprusDisease;
|
||||||
effects[Poison] = WeaknessToPoison;
|
effects[Poison] = WeaknessToPoison;
|
||||||
|
|
||||||
// Weakness to magicka or -1 ?
|
effects[Paralyze] = -1;
|
||||||
effects[Paralyze] = WeaknessToMagicka;
|
|
||||||
|
|
||||||
if (effects.find(effect) != effects.end())
|
if (effects.find(effect) != effects.end())
|
||||||
return effects[effect];
|
return effects[effect];
|
||||||
|
|
|
@ -13,6 +13,9 @@ USE_OSGPLUGIN(png)
|
||||||
USE_OSGPLUGIN(tga)
|
USE_OSGPLUGIN(tga)
|
||||||
USE_OSGPLUGIN(dds)
|
USE_OSGPLUGIN(dds)
|
||||||
USE_OSGPLUGIN(jpeg)
|
USE_OSGPLUGIN(jpeg)
|
||||||
|
USE_OSGPLUGIN(bmp)
|
||||||
|
USE_OSGPLUGIN(osg)
|
||||||
|
USE_SERIALIZER_WRAPPER_LIBRARY(osg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|
|
@ -359,6 +359,10 @@ namespace SceneUtil
|
||||||
for (unsigned int i=0; i<lights.size(); ++i)
|
for (unsigned int i=0; i<lights.size(); ++i)
|
||||||
{
|
{
|
||||||
const LightManager::LightSourceViewBound& l = lights[i];
|
const LightManager::LightSourceViewBound& l = lights[i];
|
||||||
|
|
||||||
|
if (mIgnoredLightSources.count(l.mLightSource))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (l.mViewBound.intersects(nodeBound))
|
if (l.mViewBound.intersects(nodeBound))
|
||||||
mLightList.push_back(&l);
|
mLightList.push_back(&l);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef OPENMW_COMPONENTS_SCENEUTIL_LIGHTMANAGER_H
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_LIGHTMANAGER_H
|
||||||
#define OPENMW_COMPONENTS_SCENEUTIL_LIGHTMANAGER_H
|
#define OPENMW_COMPONENTS_SCENEUTIL_LIGHTMANAGER_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <osg/Light>
|
#include <osg/Light>
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
@ -157,16 +159,20 @@ namespace SceneUtil
|
||||||
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
|
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
|
||||||
, mLightManager(copy.mLightManager)
|
, mLightManager(copy.mLightManager)
|
||||||
, mLastFrameNumber(0)
|
, mLastFrameNumber(0)
|
||||||
|
, mIgnoredLightSources(copy.mIgnoredLightSources)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
META_Object(SceneUtil, LightListCallback)
|
META_Object(SceneUtil, LightListCallback)
|
||||||
|
|
||||||
void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
std::set<SceneUtil::LightSource*>& getIgnoredLightSources() { return mIgnoredLightSources; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LightManager* mLightManager;
|
LightManager* mLightManager;
|
||||||
unsigned int mLastFrameNumber;
|
unsigned int mLastFrameNumber;
|
||||||
LightManager::LightList mLightList;
|
LightManager::LightList mLightList;
|
||||||
|
std::set<SceneUtil::LightSource*> mIgnoredLightSources;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace SceneUtil
|
||||||
light->setLinearAttenuation(linearAttenuation);
|
light->setLinearAttenuation(linearAttenuation);
|
||||||
light->setQuadraticAttenuation(quadraticAttenuation);
|
light->setQuadraticAttenuation(quadraticAttenuation);
|
||||||
light->setConstantAttenuation(0.f);
|
light->setConstantAttenuation(0.f);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
|
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
|
||||||
|
@ -68,6 +67,14 @@ namespace SceneUtil
|
||||||
attachTo = trans;
|
attachTo = trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<LightSource> lightSource = createLightSource(esmLight, lightMask, isExterior, outQuadInLin, useQuadratic, quadraticValue,
|
||||||
|
quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
|
||||||
|
attachTo->addChild(lightSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<LightSource> createLightSource(const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic, float quadraticValue,
|
||||||
|
float quadraticRadiusMult, bool useLinear, float linearRadiusMult, float linearValue, const osg::Vec4f& ambient)
|
||||||
|
{
|
||||||
osg::ref_ptr<SceneUtil::LightSource> lightSource (new SceneUtil::LightSource);
|
osg::ref_ptr<SceneUtil::LightSource> lightSource (new SceneUtil::LightSource);
|
||||||
osg::ref_ptr<osg::Light> light (new osg::Light);
|
osg::ref_ptr<osg::Light> light (new osg::Light);
|
||||||
lightSource->setNodeMask(lightMask);
|
lightSource->setNodeMask(lightMask);
|
||||||
|
@ -85,7 +92,7 @@ namespace SceneUtil
|
||||||
diffuse.a() = 1;
|
diffuse.a() = 1;
|
||||||
}
|
}
|
||||||
light->setDiffuse(diffuse);
|
light->setDiffuse(diffuse);
|
||||||
light->setAmbient(osg::Vec4f(0,0,0,1));
|
light->setAmbient(ambient);
|
||||||
light->setSpecular(osg::Vec4f(0,0,0,0));
|
light->setSpecular(osg::Vec4f(0,0,0,0));
|
||||||
|
|
||||||
lightSource->setLight(light);
|
lightSource->setLight(light);
|
||||||
|
@ -103,7 +110,6 @@ namespace SceneUtil
|
||||||
|
|
||||||
lightSource->addUpdateCallback(ctrl);
|
lightSource->addUpdateCallback(ctrl);
|
||||||
|
|
||||||
attachTo->addChild(lightSource);
|
return lightSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef OPENMW_COMPONENTS_LIGHTUTIL_H
|
#ifndef OPENMW_COMPONENTS_LIGHTUTIL_H
|
||||||
#define OPENMW_COMPONENTS_LIGHTUTIL_H
|
#define OPENMW_COMPONENTS_LIGHTUTIL_H
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/Vec4f>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Group;
|
class Group;
|
||||||
|
@ -13,6 +16,7 @@ namespace ESM
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
class LightSource;
|
||||||
|
|
||||||
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and add it to a sub graph.
|
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and add it to a sub graph.
|
||||||
/// @note If the sub graph contains a node named "AttachLight" (case insensitive), then the light is added to that.
|
/// @note If the sub graph contains a node named "AttachLight" (case insensitive), then the light is added to that.
|
||||||
|
@ -27,6 +31,15 @@ namespace SceneUtil
|
||||||
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult,
|
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult,
|
||||||
float linearValue);
|
float linearValue);
|
||||||
|
|
||||||
|
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and return it.
|
||||||
|
/// @param esmLight The light definition coming from the game files containing radius, color, flicker, etc.
|
||||||
|
/// @param lightMask Mask to assign to the newly created LightSource.
|
||||||
|
/// @param isExterior Is the light outside? May be used for deciding which attenuation settings to use.
|
||||||
|
/// @param ambient Ambient component of the light.
|
||||||
|
/// @par Attenuation parameters come from the game INI file.
|
||||||
|
osg::ref_ptr<LightSource> createLightSource (const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
|
||||||
|
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult, float linearValue, const osg::Vec4f& ambient=osg::Vec4f(0,0,0,1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "audiodecoder.hpp"
|
#include "audiodecoder.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
79
extern/osg-ffmpeg-videoplayer/videostate.cpp
vendored
79
extern/osg-ffmpeg-videoplayer/videostate.cpp
vendored
|
@ -1,6 +1,7 @@
|
||||||
#include "videostate.hpp"
|
#include "videostate.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
@ -102,14 +103,14 @@ void PacketQueue::put(AVPacket *pkt)
|
||||||
this->last_pkt = pkt1;
|
this->last_pkt = pkt1;
|
||||||
this->nb_packets++;
|
this->nb_packets++;
|
||||||
this->size += pkt1->pkt.size;
|
this->size += pkt1->pkt.size;
|
||||||
this->cond.notify_one();
|
this->cond.signal();
|
||||||
|
|
||||||
this->mutex.unlock();
|
this->mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(this->mutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(this->mutex);
|
||||||
while(!is->mQuit)
|
while(!is->mQuit)
|
||||||
{
|
{
|
||||||
AVPacketList *pkt1 = this->first_pkt;
|
AVPacketList *pkt1 = this->first_pkt;
|
||||||
|
@ -129,7 +130,7 @@ int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
||||||
|
|
||||||
if(this->flushing)
|
if(this->flushing)
|
||||||
break;
|
break;
|
||||||
this->cond.wait(lock);
|
this->cond.wait(&this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -138,7 +139,7 @@ int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
||||||
void PacketQueue::flush()
|
void PacketQueue::flush()
|
||||||
{
|
{
|
||||||
this->flushing = true;
|
this->flushing = true;
|
||||||
this->cond.notify_one();
|
this->cond.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketQueue::clear()
|
void PacketQueue::clear()
|
||||||
|
@ -233,7 +234,7 @@ void VideoState::video_display(VideoPicture *vp)
|
||||||
|
|
||||||
void VideoState::video_refresh()
|
void VideoState::video_refresh()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(this->pictq_mutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(this->pictq_mutex);
|
||||||
if(this->pictq_size == 0)
|
if(this->pictq_size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -245,7 +246,7 @@ void VideoState::video_refresh()
|
||||||
this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE;
|
this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE;
|
||||||
this->frame_last_pts = vp->pts;
|
this->frame_last_pts = vp->pts;
|
||||||
this->pictq_size--;
|
this->pictq_size--;
|
||||||
this->pictq_cond.notify_one();
|
this->pictq_cond.signal();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -275,7 +276,7 @@ void VideoState::video_refresh()
|
||||||
// update queue for next picture
|
// update queue for next picture
|
||||||
this->pictq_size--;
|
this->pictq_size--;
|
||||||
this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE;
|
this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE;
|
||||||
this->pictq_cond.notify_one();
|
this->pictq_cond.signal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,9 +287,9 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts)
|
||||||
|
|
||||||
/* wait until we have a new pic */
|
/* wait until we have a new pic */
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(this->pictq_mutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(this->pictq_mutex);
|
||||||
while(this->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !this->mQuit)
|
while(this->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !this->mQuit)
|
||||||
this->pictq_cond.timed_wait(lock, boost::posix_time::milliseconds(1));
|
this->pictq_cond.wait(&this->pictq_mutex, 1);
|
||||||
}
|
}
|
||||||
if(this->mQuit)
|
if(this->mQuit)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -371,9 +372,18 @@ static void our_free_buffer(void *opaque, uint8_t *data)
|
||||||
av_free(data);
|
av_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VideoThread : public OpenThreads::Thread
|
||||||
void VideoState::video_thread_loop(VideoState *self)
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
VideoThread(VideoState* self)
|
||||||
|
: mVideoState(self)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void run()
|
||||||
|
{
|
||||||
|
VideoState* self = mVideoState;
|
||||||
AVPacket pkt1, *packet = &pkt1;
|
AVPacket pkt1, *packet = &pkt1;
|
||||||
int frameFinished;
|
int frameFinished;
|
||||||
AVFrame *pFrame;
|
AVFrame *pFrame;
|
||||||
|
@ -430,8 +440,23 @@ void VideoState::video_thread_loop(VideoState *self)
|
||||||
av_free(self->rgbaFrame);
|
av_free(self->rgbaFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoState::decode_thread_loop(VideoState *self)
|
private:
|
||||||
|
VideoState* mVideoState;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParseThread : public OpenThreads::Thread
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
ParseThread(VideoState* self)
|
||||||
|
: mVideoState(self)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void run()
|
||||||
|
{
|
||||||
|
VideoState* self = mVideoState;
|
||||||
|
|
||||||
AVFormatContext *pFormatCtx = self->format_ctx;
|
AVFormatContext *pFormatCtx = self->format_ctx;
|
||||||
AVPacket pkt1, *packet = &pkt1;
|
AVPacket pkt1, *packet = &pkt1;
|
||||||
|
|
||||||
|
@ -505,7 +530,7 @@ void VideoState::decode_thread_loop(VideoState *self)
|
||||||
if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) ||
|
if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) ||
|
||||||
(self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
|
(self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
|
||||||
{
|
{
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
OpenThreads::Thread::microSleep(10 * 1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,6 +559,10 @@ void VideoState::decode_thread_loop(VideoState *self)
|
||||||
self->mQuit = true;
|
self->mQuit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VideoState* mVideoState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool VideoState::update()
|
bool VideoState::update()
|
||||||
{
|
{
|
||||||
|
@ -587,7 +616,7 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx)
|
||||||
this->video_st = pFormatCtx->streams + stream_index;
|
this->video_st = pFormatCtx->streams + stream_index;
|
||||||
|
|
||||||
codecCtx->get_buffer2 = our_get_buffer;
|
codecCtx->get_buffer2 = our_get_buffer;
|
||||||
this->video_thread = boost::thread(video_thread_loop, this);
|
this->video_thread.reset(new VideoThread(this));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -669,7 +698,7 @@ void VideoState::init(boost::shared_ptr<std::istream> inputstream, const std::st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this->parse_thread = boost::thread(decode_thread_loop, this);
|
this->parse_thread.reset(new ParseThread(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoState::deinit()
|
void VideoState::deinit()
|
||||||
|
@ -681,10 +710,16 @@ void VideoState::deinit()
|
||||||
|
|
||||||
mAudioDecoder.reset();
|
mAudioDecoder.reset();
|
||||||
|
|
||||||
if (this->parse_thread.joinable())
|
if (this->parse_thread.get())
|
||||||
this->parse_thread.join();
|
{
|
||||||
if (this->video_thread.joinable())
|
this->parse_thread->join();
|
||||||
this->video_thread.join();
|
this->parse_thread.reset();
|
||||||
|
}
|
||||||
|
if (this->video_thread.get())
|
||||||
|
{
|
||||||
|
this->video_thread->join();
|
||||||
|
this->video_thread.reset();
|
||||||
|
}
|
||||||
|
|
||||||
if(this->audio_st)
|
if(this->audio_st)
|
||||||
avcodec_close((*this->audio_st)->codec);
|
avcodec_close((*this->audio_st)->codec);
|
||||||
|
@ -779,7 +814,7 @@ ExternalClock::ExternalClock()
|
||||||
|
|
||||||
void ExternalClock::setPaused(bool paused)
|
void ExternalClock::setPaused(bool paused)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
if (mPaused == paused)
|
if (mPaused == paused)
|
||||||
return;
|
return;
|
||||||
if (paused)
|
if (paused)
|
||||||
|
@ -793,7 +828,7 @@ void ExternalClock::setPaused(bool paused)
|
||||||
|
|
||||||
uint64_t ExternalClock::get()
|
uint64_t ExternalClock::get()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
if (mPaused)
|
if (mPaused)
|
||||||
return mPausedAt;
|
return mPausedAt;
|
||||||
else
|
else
|
||||||
|
@ -802,7 +837,7 @@ uint64_t ExternalClock::get()
|
||||||
|
|
||||||
void ExternalClock::set(uint64_t time)
|
void ExternalClock::set(uint64_t time)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(mMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
mTimeBase = av_gettime() - time;
|
mTimeBase = av_gettime() - time;
|
||||||
mPausedAt = time;
|
mPausedAt = time;
|
||||||
}
|
}
|
||||||
|
|
24
extern/osg-ffmpeg-videoplayer/videostate.hpp
vendored
24
extern/osg-ffmpeg-videoplayer/videostate.hpp
vendored
|
@ -2,8 +2,14 @@
|
||||||
#define VIDEOPLAYER_VIDEOSTATE_H
|
#define VIDEOPLAYER_VIDEOSTATE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
namespace osg
|
namespace osg
|
||||||
|
@ -34,6 +40,8 @@ struct VideoState;
|
||||||
|
|
||||||
class MovieAudioFactory;
|
class MovieAudioFactory;
|
||||||
class MovieAudioDecoder;
|
class MovieAudioDecoder;
|
||||||
|
class VideoThread;
|
||||||
|
class ParseThread;
|
||||||
|
|
||||||
struct ExternalClock
|
struct ExternalClock
|
||||||
{
|
{
|
||||||
|
@ -43,7 +51,7 @@ struct ExternalClock
|
||||||
uint64_t mPausedAt;
|
uint64_t mPausedAt;
|
||||||
bool mPaused;
|
bool mPaused;
|
||||||
|
|
||||||
boost::mutex mMutex;
|
OpenThreads::Mutex mMutex;
|
||||||
|
|
||||||
void setPaused(bool paused);
|
void setPaused(bool paused);
|
||||||
uint64_t get();
|
uint64_t get();
|
||||||
|
@ -62,8 +70,8 @@ struct PacketQueue {
|
||||||
int nb_packets;
|
int nb_packets;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
boost::mutex mutex;
|
OpenThreads::Mutex mutex;
|
||||||
boost::condition_variable cond;
|
OpenThreads::Condition cond;
|
||||||
|
|
||||||
void put(AVPacket *pkt);
|
void put(AVPacket *pkt);
|
||||||
int get(AVPacket *pkt, VideoState *is);
|
int get(AVPacket *pkt, VideoState *is);
|
||||||
|
@ -141,11 +149,11 @@ struct VideoState {
|
||||||
VideoPicture pictq[VIDEO_PICTURE_ARRAY_SIZE];
|
VideoPicture pictq[VIDEO_PICTURE_ARRAY_SIZE];
|
||||||
AVFrame* rgbaFrame; // used as buffer for the frame converted from its native format to RGBA
|
AVFrame* rgbaFrame; // used as buffer for the frame converted from its native format to RGBA
|
||||||
int pictq_size, pictq_rindex, pictq_windex;
|
int pictq_size, pictq_rindex, pictq_windex;
|
||||||
boost::mutex pictq_mutex;
|
OpenThreads::Mutex pictq_mutex;
|
||||||
boost::condition_variable pictq_cond;
|
OpenThreads::Condition pictq_cond;
|
||||||
|
|
||||||
boost::thread parse_thread;
|
std::auto_ptr<ParseThread> parse_thread;
|
||||||
boost::thread video_thread;
|
std::auto_ptr<VideoThread> video_thread;
|
||||||
|
|
||||||
volatile bool mSeekRequested;
|
volatile bool mSeekRequested;
|
||||||
uint64_t mSeekPos;
|
uint64_t mSeekPos;
|
||||||
|
|
|
@ -120,6 +120,10 @@
|
||||||
<Property key="TextShadow" value="true"/>
|
<Property key="TextShadow" value="true"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Stretch" name="Item"/>
|
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Stretch" name="Item"/>
|
||||||
|
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" align="Stretch" name="ItemShadow">
|
||||||
|
<Property key="Colour" value="0 0 0"/>
|
||||||
|
<Property key="Alpha" value="0.5"/>
|
||||||
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
@ -128,6 +132,10 @@
|
||||||
<Widget type="Widget" skin="" position="0 0 32 32" name="Root">
|
<Widget type="Widget" skin="" position="0 0 32 32" name="Root">
|
||||||
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Frame">
|
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Frame">
|
||||||
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Item"/>
|
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Item"/>
|
||||||
|
<Widget type="ImageBox" skin="ImageBox" position="4 4 32 32" align="Stretch" name="ItemShadow">
|
||||||
|
<Property key="Colour" value="0 0 0"/>
|
||||||
|
<Property key="Alpha" value="0.5"/>
|
||||||
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
@ -140,6 +148,10 @@
|
||||||
<Property key="TextShadow" value="true"/>
|
<Property key="TextShadow" value="true"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Center" name="Item"/>
|
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Center" name="Item"/>
|
||||||
|
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" align="Stretch" name="ItemShadow">
|
||||||
|
<Property key="Colour" value="0 0 0"/>
|
||||||
|
<Property key="Alpha" value="0.5"/>
|
||||||
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="Widget" skin="MW_Box_Overlay" position="0 0 50 50" align="Stretch"/>
|
<Widget type="Widget" skin="MW_Box_Overlay" position="0 0 50 50" align="Stretch"/>
|
||||||
|
|
Loading…
Reference in a new issue