mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 05:39:42 +00:00
Merge remote-tracking branch 'upstream/master' into osgshadow-test-vdsm
This commit is contained in:
commit
2a90dff388
51 changed files with 530 additions and 302 deletions
|
@ -41,8 +41,8 @@ addons:
|
|||
project:
|
||||
name: "OpenMW/openmw"
|
||||
description: "<Your project description here>"
|
||||
notification_email: scrawl@baseoftrash.de
|
||||
build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE"
|
||||
notification_email: 720642+scrawl@users.noreply.github.com
|
||||
build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE"
|
||||
build_command: "make -j3"
|
||||
branch_pattern: coverity_scan
|
||||
matrix:
|
||||
|
|
|
@ -329,8 +329,9 @@ endif ()
|
|||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg
|
||||
"${OpenMW_BINARY_DIR}" "openmw-cs.cfg")
|
||||
|
||||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
||||
"${OpenMW_BINARY_DIR}" "resources/defaultfilters" COPYONLY)
|
||||
# Needs the copy version because the configure version assumes the end of the file has been reached when a null character is reached and there are no CMake expressions to evaluate.
|
||||
copy_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
||||
"${OpenMW_BINARY_DIR}" "resources/defaultfilters")
|
||||
|
||||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
|
||||
"${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt")
|
||||
|
|
|
@ -90,16 +90,16 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
||||
|
||||
desc.add_options()
|
||||
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()->composing())
|
||||
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
||||
("data", boost::program_options::value<Files::EscapePathContainer>()->default_value(Files::EscapePathContainer(), "data")->multitoken()->composing())
|
||||
("data-local", boost::program_options::value<Files::EscapeHashString>()->default_value(""))
|
||||
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
||||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
|
||||
("resources", boost::program_options::value<std::string>()->default_value("resources"))
|
||||
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
|
||||
default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
|
||||
("encoding", boost::program_options::value<Files::EscapeHashString>()->default_value("win1252"))
|
||||
("resources", boost::program_options::value<Files::EscapeHashString>()->default_value("resources"))
|
||||
("fallback-archive", boost::program_options::value<Files::EscapeStringVector>()->
|
||||
default_value(Files::EscapeStringVector(), "fallback-archive")->multitoken())
|
||||
("fallback", boost::program_options::value<FallbackMap>()->default_value(FallbackMap(), "")
|
||||
->multitoken()->composing(), "fallback values")
|
||||
("script-blacklist", boost::program_options::value<std::vector<std::string> >()->default_value(std::vector<std::string>(), "")
|
||||
("script-blacklist", boost::program_options::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "")
|
||||
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)")
|
||||
("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
|
||||
->default_value(true), "enable script blacklisting");
|
||||
|
@ -109,25 +109,29 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
mCfgMgr.readConfiguration(variables, desc, quiet);
|
||||
|
||||
mDocumentManager.setEncoding (
|
||||
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
||||
ToUTF8::calculateEncoding (variables["encoding"].as<Files::EscapeHashString>().toStdString()));
|
||||
|
||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
|
||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<Files::EscapeHashString>().toStdString());
|
||||
|
||||
mDocumentManager.setFallbackMap (variables["fallback"].as<FallbackMap>().mMap);
|
||||
|
||||
if (variables["script-blacklist-use"].as<bool>())
|
||||
mDocumentManager.setBlacklistedScripts (
|
||||
variables["script-blacklist"].as<std::vector<std::string> >());
|
||||
variables["script-blacklist"].as<Files::EscapeStringVector>().toStdStringVector());
|
||||
|
||||
mFsStrict = variables["fs-strict"].as<bool>();
|
||||
|
||||
Files::PathContainer dataDirs, dataLocal;
|
||||
if (!variables["data"].empty()) {
|
||||
dataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
|
||||
dataDirs = Files::PathContainer(Files::EscapePath::toPathContainer(variables["data"].as<Files::EscapePathContainer>()));
|
||||
}
|
||||
|
||||
std::string local = variables["data-local"].as<std::string>();
|
||||
if (!local.empty()) {
|
||||
std::string local = variables["data-local"].as<Files::EscapeHashString>().toStdString();
|
||||
if (!local.empty())
|
||||
{
|
||||
if (local.front() == '\"')
|
||||
local = local.substr(1, local.length() - 2);
|
||||
|
||||
dataLocal.push_back(Files::PathContainer::value_type(local));
|
||||
}
|
||||
|
||||
|
@ -157,7 +161,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
mFileDialog.addFiles(path);
|
||||
}
|
||||
|
||||
return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
|
||||
return std::make_pair (dataDirs, variables["fallback-archive"].as<Files::EscapeStringVector>().toStdStringVector());
|
||||
}
|
||||
|
||||
void CS::Editor::createGame()
|
||||
|
|
|
@ -288,7 +288,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
if (mContentFiles.empty())
|
||||
throw std::runtime_error ("Empty content file sequence");
|
||||
|
||||
if (!boost::filesystem::exists (mProjectPath))
|
||||
if (mNew || !boost::filesystem::exists (mProjectPath))
|
||||
{
|
||||
boost::filesystem::path customFiltersPath (configuration.getUserDataPath());
|
||||
customFiltersPath /= "defaultfilters";
|
||||
|
|
|
@ -38,9 +38,10 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr
|
|||
appendStage (new MergeRefIdsStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new ListLandTexturesMergeStage (mState));
|
||||
appendStage (new MergeLandTexturesStage (mState));
|
||||
appendStage (new PopulateLandTexturesMergeStage (mState));
|
||||
appendStage (new MergeLandStage (mState));
|
||||
appendStage (new FixLandsAndLandTexturesMergeStage (mState));
|
||||
appendStage (new CleanupLandTexturesMergeStage (mState));
|
||||
|
||||
appendStage (new FinishMergedDocumentStage (mState, encoding));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#include "mergestate.hpp"
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
#include "../world/commands.hpp"
|
||||
#include "../world/data.hpp"
|
||||
#include "../world/idtable.hpp"
|
||||
|
||||
|
||||
CSMTools::StartMergeStage::StartMergeStage (MergeState& state)
|
||||
|
@ -109,102 +111,32 @@ void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messa
|
|||
}
|
||||
|
||||
|
||||
CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::ListLandTexturesMergeStage::setup()
|
||||
CSMTools::PopulateLandTexturesMergeStage::PopulateLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
int CSMTools::PopulateLandTexturesMergeStage::setup()
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||
mState.mSource.getData().getLand().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
// make sure record is loaded
|
||||
land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX);
|
||||
|
||||
if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX))
|
||||
{
|
||||
// list texture indices
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
|
||||
mState.mTextureIndices[key] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state)
|
||||
: mState (state), mNext (mState.mTextureIndices.end())
|
||||
{}
|
||||
|
||||
int CSMTools::MergeLandTexturesStage::setup()
|
||||
{
|
||||
// Should use the size of mState.mTextureIndices instead, but that is not available at this
|
||||
// point. Unless there are any errors in the land and land texture records this will not
|
||||
// make a difference.
|
||||
return mState.mSource.getData().getLandTextures().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
void CSMTools::PopulateLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
if (stage==0)
|
||||
mNext = mState.mTextureIndices.begin();
|
||||
const CSMWorld::Record<CSMWorld::LandTexture>& record =
|
||||
mState.mSource.getData().getLandTextures().getRecord (stage);
|
||||
|
||||
bool found = false;
|
||||
|
||||
do
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
if (mNext==mState.mTextureIndices.end())
|
||||
return;
|
||||
|
||||
mNext->second = stage+1;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext->first.first-1 << "_" << mNext->first.second;
|
||||
|
||||
int index = mState.mSource.getData().getLandTextures().searchId (stream.str());
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
CSMWorld::LandTexture texture =
|
||||
mState.mSource.getData().getLandTextures().getRecord (index).get();
|
||||
|
||||
stream.clear();
|
||||
stream << mNext->second-1 << "_0";
|
||||
|
||||
texture.mIndex = mNext->second-1;
|
||||
texture.mId = stream.str();
|
||||
|
||||
CSMWorld::Record<CSMWorld::LandTexture> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture);
|
||||
|
||||
mState.mTarget->getData().getLandTextures().appendRecord (newRecord);
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
++mNext;
|
||||
mState.mTarget->getData().getLandTextures().appendRecord(record);
|
||||
}
|
||||
while (!found);
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {}
|
||||
CSMTools::MergeLandStage::MergeLandStage (MergeState& state)
|
||||
: mState (state)
|
||||
{
|
||||
}
|
||||
|
||||
int CSMTools::MergeLandStage::setup()
|
||||
{
|
||||
|
@ -218,40 +150,66 @@ void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VTEX);
|
||||
|
||||
CSMWorld::Land newLand (land);
|
||||
|
||||
newLand.mPlugin = 0;
|
||||
|
||||
if (land.mDataTypes & ESM::Land::DATA_VTEX)
|
||||
{
|
||||
// adjust land texture references
|
||||
if (ESM::Land::LandData *data = newLand.getLandData())
|
||||
{
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
std::map<std::pair<uint16_t, int>, int>::const_iterator iter =
|
||||
mState.mTextureIndices.find (key);
|
||||
|
||||
if (iter!=mState.mTextureIndices.end())
|
||||
data->mTextures[i] = iter->second;
|
||||
else
|
||||
data->mTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSMWorld::Record<CSMWorld::Land> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand);
|
||||
|
||||
mState.mTarget->getData().getLand().appendRecord (newRecord);
|
||||
mState.mTarget->getData().getLand().appendRecord (record);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::FixLandsAndLandTexturesMergeStage::FixLandsAndLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{
|
||||
}
|
||||
|
||||
int CSMTools::FixLandsAndLandTexturesMergeStage::setup()
|
||||
{
|
||||
// We will have no more than the source
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::FixLandsAndLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
if (stage < mState.mTarget->getData().getLand().getSize())
|
||||
{
|
||||
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&>(
|
||||
*mState.mTarget->getData().getTableModel(CSMWorld::UniversalId::Type_Lands));
|
||||
|
||||
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&>(
|
||||
*mState.mTarget->getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
||||
|
||||
std::string id = mState.mTarget->getData().getLand().getId(stage);
|
||||
|
||||
CSMWorld::TouchLandCommand cmd(landTable, ltexTable, id);
|
||||
cmd.redo();
|
||||
|
||||
// Get rid of base data
|
||||
const CSMWorld::Record<CSMWorld::Land>& oldRecord =
|
||||
mState.mTarget->getData().getLand().getRecord (stage);
|
||||
|
||||
CSMWorld::Record<CSMWorld::Land> newRecord(CSMWorld::RecordBase::State_ModifiedOnly,
|
||||
nullptr, &oldRecord.get());
|
||||
|
||||
mState.mTarget->getData().getLand().setRecord(stage, newRecord);
|
||||
}
|
||||
}
|
||||
|
||||
CSMTools::CleanupLandTexturesMergeStage::CleanupLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{
|
||||
}
|
||||
|
||||
int CSMTools::CleanupLandTexturesMergeStage::setup()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSMTools::CleanupLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
auto& landTextures = mState.mTarget->getData().getLandTextures();
|
||||
for (int i = 0; i < landTextures.getSize(); )
|
||||
{
|
||||
if (!landTextures.getRecord(i).isModified())
|
||||
landTextures.removeRows(i, 1);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,29 +116,14 @@ namespace CSMTools
|
|||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class ListLandTexturesMergeStage : public CSMDoc::Stage
|
||||
/// Adds all land texture records that could potentially be referenced when merging
|
||||
class PopulateLandTexturesMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
ListLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeLandTexturesStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
std::map<std::pair<uint16_t, int>, int>::iterator mNext;
|
||||
|
||||
public:
|
||||
|
||||
MergeLandTexturesStage (MergeState& state);
|
||||
PopulateLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
@ -161,6 +146,40 @@ namespace CSMTools
|
|||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
/// During this stage, the complex process of combining LandTextures from
|
||||
/// potentially multiple plugins is undertaken.
|
||||
class FixLandsAndLandTexturesMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
FixLandsAndLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
/// Removes base LandTexture records. This gets rid of the base records previously
|
||||
/// needed in FixLandsAndLandTexturesMergeStage.
|
||||
class CleanupLandTexturesMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
CleanupLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace CSMWorld
|
|||
throw std::runtime_error("invalid land map LOD data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.setDataLoaded(Land::DATA_WNAM);
|
||||
copy.add(Land::DATA_WNAM);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
|
@ -155,7 +155,7 @@ namespace CSMWorld
|
|||
throw std::runtime_error("invalid land normals data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.setDataLoaded(Land::DATA_VNML);
|
||||
copy.add(Land::DATA_VNML);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
|
@ -202,7 +202,7 @@ namespace CSMWorld
|
|||
throw std::runtime_error("invalid land heights data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.setDataLoaded(Land::DATA_VHGT);
|
||||
copy.add(Land::DATA_VHGT);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ namespace CSMWorld
|
|||
throw std::runtime_error("invalid land colours data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.setDataLoaded(Land::DATA_VCLR);
|
||||
copy.add(Land::DATA_VCLR);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
|
@ -296,7 +296,7 @@ namespace CSMWorld
|
|||
throw std::runtime_error("invalid land textures data");
|
||||
|
||||
Land copy = record.get();
|
||||
copy.setDataLoaded(Land::DATA_VTEX);
|
||||
copy.add(Land::DATA_VTEX);
|
||||
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,15 @@ namespace CSMWorld
|
|||
bool mChanged;
|
||||
};
|
||||
|
||||
/// \brief Adds LandTexture records and modifies texture indices as needed.
|
||||
///
|
||||
/// LandTexture records are different from other types of records, because
|
||||
/// they only effect the current plugin. Thus, when modifying or copying
|
||||
/// a Land record, all of the LandTexture records referenced need to be
|
||||
/// added to the current plugin. Since these newly added LandTextures could
|
||||
/// have indices that conflict with pre-existing LandTextures in the current
|
||||
/// plugin, the indices might have to be changed, both for the newly added
|
||||
/// LandRecord and within the Land record.
|
||||
class ImportLandTexturesCommand : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
|
@ -71,6 +80,9 @@ namespace CSMWorld
|
|||
std::vector<std::string> mCreatedTextures;
|
||||
};
|
||||
|
||||
/// \brief This command is used to fix LandTexture records and texture
|
||||
/// indices after cloning a Land. See ImportLandTexturesCommand for
|
||||
/// details.
|
||||
class CopyLandTexturesCommand : public ImportLandTexturesCommand
|
||||
{
|
||||
public:
|
||||
|
@ -90,6 +102,9 @@ namespace CSMWorld
|
|||
std::string mDestId;
|
||||
};
|
||||
|
||||
/// \brief This command brings a land record into the current plugin, adding
|
||||
/// LandTexture records and modifying texture indices as needed.
|
||||
/// \note See ImportLandTextures for more details.
|
||||
class TouchLandCommand : public ImportLandTexturesCommand
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -336,7 +336,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
|
|||
int oldRow = idCollection()->searchId(id);
|
||||
|
||||
// If it does not exist or it is in the current plugin, it can be skipped.
|
||||
if (oldRow <= 0 || plugin == 0)
|
||||
if (oldRow < 0 || plugin == 0)
|
||||
{
|
||||
results.recordMapping.push_back(std::make_pair(id, id));
|
||||
continue;
|
||||
|
|
|
@ -194,6 +194,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
std::string local(variables["data-local"].as<Files::EscapeHashString>().toStdString());
|
||||
if (!local.empty())
|
||||
{
|
||||
if (local.front() == '\"')
|
||||
local = local.substr(1, local.length() - 2);
|
||||
|
||||
dataDirs.push_back(Files::PathContainer::value_type(local));
|
||||
}
|
||||
|
||||
|
|
|
@ -155,8 +155,6 @@ namespace MWGui
|
|||
void restock();
|
||||
void deleteLater();
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
bool mIsCompanion;
|
||||
std::list<std::string> mKeywords;
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ namespace MWGui
|
|||
, mSpellStatus(NULL)
|
||||
, mEffectBox(NULL)
|
||||
, mMinimap(NULL)
|
||||
, mCompass(NULL)
|
||||
, mCrosshair(NULL)
|
||||
, mCellNameBox(NULL)
|
||||
, mDrowningFrame(NULL)
|
||||
|
|
|
@ -69,7 +69,6 @@ namespace MWGui
|
|||
MyGUI::Widget *mEffectBox, *mMinimapBox;
|
||||
MyGUI::Button* mMinimapButton;
|
||||
MyGUI::ScrollView* mMinimap;
|
||||
MyGUI::ImageBox* mCompass;
|
||||
MyGUI::ImageBox* mCrosshair;
|
||||
MyGUI::TextBox* mCellNameBox;
|
||||
MyGUI::TextBox* mWeaponSpellBox;
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace MWGui
|
|||
{
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(player, "prisonmarker");
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.f); // override fade-in caused by cell transition
|
||||
|
||||
setVisible(true);
|
||||
mTimeAdvancer.run(100);
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace MWGui
|
|||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed);
|
||||
dialog->eventCancelClicked.clear();
|
||||
dialog->eventCancelClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotCancel);
|
||||
}
|
||||
|
||||
void SaveGameDialog::onDeleteSlotConfirmed()
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace MWGui
|
|||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void addSpell(const ESM::Spell& spell);
|
||||
void clearSpells();
|
||||
int mLastPos,mCurrentY;
|
||||
int mCurrentY;
|
||||
|
||||
static const int sLineHeight;
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace MWGui
|
|||
|
||||
std::stringstream out;
|
||||
out << val << "/" << max;
|
||||
setText(tname, out.str().c_str());
|
||||
setText(tname, out.str());
|
||||
|
||||
pt->setProgressRange(std::max(0, max));
|
||||
pt->setProgressPosition(std::max(0, val));
|
||||
|
|
|
@ -451,11 +451,10 @@ namespace MWMechanics
|
|||
// Check if an idle actor is too close to a door - if so start walking
|
||||
storage.mDoorCheckDuration += duration;
|
||||
|
||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||
|
||||
if (storage.mDoorCheckDuration >= DOOR_CHECK_INTERVAL)
|
||||
{
|
||||
storage.mDoorCheckDuration = 0; // restart timer
|
||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||
if (mDistance && // actor is not intended to be stationary
|
||||
proximityToDoor(actor, distance*1.6f))
|
||||
{
|
||||
|
@ -531,11 +530,10 @@ namespace MWMechanics
|
|||
|
||||
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos)
|
||||
{
|
||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||
|
||||
if (mObstacleCheck.isEvading())
|
||||
{
|
||||
// first check if we're walking into a door
|
||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||
if (proximityToDoor(actor, distance))
|
||||
{
|
||||
// remove allowed points then select another random destination
|
||||
|
|
|
@ -1874,7 +1874,7 @@ void CharacterController::update(float duration)
|
|||
: (sneak ? CharState_SneakBack
|
||||
: (isrunning ? CharState_RunBack : CharState_WalkBack)));
|
||||
}
|
||||
else if(rot.z() != 0.0f && !inwater && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
|
||||
else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
|
||||
{
|
||||
if(rot.z() > 0.0f)
|
||||
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
|
||||
|
|
|
@ -424,26 +424,6 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim)
|
||||
{
|
||||
const MWWorld::Class& attackerClass = attacker.getClass();
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// If attacker is fish, victim must be in water
|
||||
if (attackerClass.isPureWaterCreature(attacker))
|
||||
{
|
||||
return world->isWading(victim);
|
||||
}
|
||||
|
||||
// If attacker can't swim, victim must not be in water
|
||||
if (!attackerClass.canSwim(attacker))
|
||||
{
|
||||
return !world->isSwimming(victim);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2)
|
||||
{
|
||||
osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3());
|
||||
|
|
|
@ -39,10 +39,6 @@ void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& vict
|
|||
/// Apply the fatigue loss incurred by attacking with the given weapon (weapon may be empty = hand-to-hand)
|
||||
void applyFatigueLoss(const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float attackStrength);
|
||||
|
||||
/// Can attacker operate in victim's environment?
|
||||
/// e.g. If attacker is a fish, is victim in water? Or, if attacker can't swim, is victim on land?
|
||||
bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim);
|
||||
|
||||
float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2);
|
||||
}
|
||||
|
||||
|
|
|
@ -1123,6 +1123,10 @@ namespace MWMechanics
|
|||
if (playerFollowers.find(*it) != playerFollowers.end())
|
||||
continue;
|
||||
|
||||
// NPC will complain about theft even if he will do nothing about it
|
||||
if (type == OT_Theft || type == OT_Pickpocket)
|
||||
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
|
||||
|
||||
crimeSeen = true;
|
||||
}
|
||||
}
|
||||
|
@ -1243,9 +1247,7 @@ namespace MWMechanics
|
|||
{
|
||||
reported = true;
|
||||
|
||||
if (type == OT_Theft || type == OT_Pickpocket)
|
||||
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
|
||||
else if (type == OT_Trespassing)
|
||||
if (type == OT_Trespassing)
|
||||
MWBase::Environment::get().getDialogueManager()->say(*it, "intruder");
|
||||
}
|
||||
|
||||
|
|
|
@ -536,6 +536,13 @@ namespace MWMechanics
|
|||
|
||||
appliedLastingEffects.push_back(effect);
|
||||
|
||||
// Unequip all items, if a spell with the ExtraSpell effect was casted
|
||||
if (effectIt->mEffectID == ESM::MagicEffect::ExtraSpell && target.getClass().hasInventoryStore(target))
|
||||
{
|
||||
MWWorld::InventoryStore& store = target.getClass().getInventoryStore(target);
|
||||
store.unequipAll(target);
|
||||
}
|
||||
|
||||
// Command spells should have their effect, including taking the target out of combat, each time the spell successfully affects the target
|
||||
if (((effectIt->mEffectID == ESM::MagicEffect::CommandHumanoid && target.getClass().isNpc())
|
||||
|| (effectIt->mEffectID == ESM::MagicEffect::CommandCreature && target.getTypeName() == typeid(ESM::Creature).name()))
|
||||
|
|
|
@ -702,8 +702,6 @@ namespace MWPhysics
|
|||
const char* env = getenv("OPENMW_PHYSICS_FPS");
|
||||
if (env)
|
||||
{
|
||||
std::string str(env);
|
||||
|
||||
float physFramerate = std::atof(env);
|
||||
if (physFramerate > 0)
|
||||
{
|
||||
|
@ -1046,7 +1044,7 @@ namespace MWPhysics
|
|||
bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor)
|
||||
{
|
||||
Actor* physactor = getActor(actor);
|
||||
return physactor->getOnGround();
|
||||
return physactor && physactor->getOnGround();
|
||||
}
|
||||
|
||||
bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel)
|
||||
|
|
|
@ -290,11 +290,9 @@ namespace MWRender
|
|||
sceneRoot->setNodeMask(Mask_Scene);
|
||||
sceneRoot->setName("Scene Root");
|
||||
|
||||
mUniformRainIntensity = new osg::Uniform("rainIntensity",(float) 0.0);
|
||||
|
||||
mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity);
|
||||
|
||||
mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager()));
|
||||
mSky->setCamera(mViewer->getCamera());
|
||||
mSky->setRainIntensityUniform(mWater->getRainIntensityUniform());
|
||||
|
||||
source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON);
|
||||
|
||||
|
@ -544,9 +542,6 @@ namespace MWRender
|
|||
mWater->update(dt);
|
||||
}
|
||||
|
||||
if (!mSky->isEnabled() || !mSky->hasRain())
|
||||
clearRainRipples();
|
||||
|
||||
mCamera->update(dt, paused);
|
||||
|
||||
osg::Vec3f focal, cameraPos;
|
||||
|
@ -845,12 +840,6 @@ namespace MWRender
|
|||
void RenderingManager::notifyWorldSpaceChanged()
|
||||
{
|
||||
mEffectManager->clear();
|
||||
mWater->clearRipples();
|
||||
}
|
||||
|
||||
void RenderingManager::clearRainRipples()
|
||||
{
|
||||
mUniformRainIntensity->set((float) 0.0);
|
||||
}
|
||||
|
||||
void RenderingManager::clear()
|
||||
|
|
|
@ -85,7 +85,6 @@ namespace MWRender
|
|||
|
||||
osg::Uniform* mUniformNear;
|
||||
osg::Uniform* mUniformFar;
|
||||
osg::Uniform* mUniformRainIntensity;
|
||||
|
||||
void preloadCommonAssets();
|
||||
|
||||
|
@ -160,8 +159,6 @@ namespace MWRender
|
|||
/// Clear all worldspace-specific data
|
||||
void notifyWorldSpaceChanged();
|
||||
|
||||
void clearRainRipples();
|
||||
|
||||
void update(float dt, bool paused);
|
||||
|
||||
Animation* getAnimation(const MWWorld::Ptr& ptr);
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <osgParticle/ConstantRateCounter>
|
||||
#include <osgParticle/RadialShooter>
|
||||
|
||||
#include <osgParticle/Operator>
|
||||
#include <osgParticle/ModularProgram>
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
@ -48,7 +51,6 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
|
||||
osg::ref_ptr<osg::Material> createAlphaTrackingUnlitMaterial()
|
||||
{
|
||||
osg::ref_ptr<osg::Material> mat = new osg::Material;
|
||||
|
@ -1093,6 +1095,8 @@ private:
|
|||
|
||||
SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager)
|
||||
: mSceneManager(sceneManager)
|
||||
, mCamera(NULL)
|
||||
, mRainIntensityUniform(NULL)
|
||||
, mAtmosphereNightRoll(0.f)
|
||||
, mCreated(false)
|
||||
, mIsStorm(false)
|
||||
|
@ -1135,6 +1139,11 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
|
|||
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
|
||||
}
|
||||
|
||||
void SkyManager::setRainIntensityUniform(osg::Uniform *uniform)
|
||||
{
|
||||
mRainIntensityUniform = uniform;
|
||||
}
|
||||
|
||||
void SkyManager::create()
|
||||
{
|
||||
assert(!mCreated);
|
||||
|
@ -1236,9 +1245,11 @@ private:
|
|||
class AlphaFader : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
AlphaFader()
|
||||
/// @param alphaUpdate variable which to update with alpha value
|
||||
AlphaFader(float *alphaUpdate)
|
||||
: mAlpha(1.f)
|
||||
{
|
||||
mAlphaUpdate = alphaUpdate;
|
||||
}
|
||||
|
||||
void setAlpha(float alpha)
|
||||
|
@ -1257,15 +1268,19 @@ public:
|
|||
{
|
||||
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha));
|
||||
|
||||
if (mAlphaUpdate)
|
||||
*mAlphaUpdate = mAlpha;
|
||||
}
|
||||
|
||||
// Helper for adding AlphaFaders to a subgraph
|
||||
class SetupVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
SetupVisitor()
|
||||
SetupVisitor(float *alphaUpdate)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
mAlphaUpdate = alphaUpdate;
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node &node)
|
||||
|
@ -1276,14 +1291,16 @@ public:
|
|||
{
|
||||
SceneUtil::CompositeStateSetUpdater* composite = NULL;
|
||||
osg::Callback* callback = node.getUpdateCallback();
|
||||
|
||||
while (callback)
|
||||
{
|
||||
if ((composite = dynamic_cast<SceneUtil::CompositeStateSetUpdater*>(callback)))
|
||||
break;
|
||||
|
||||
callback = callback->getNestedCallback();
|
||||
}
|
||||
|
||||
osg::ref_ptr<AlphaFader> alphaFader (new AlphaFader);
|
||||
osg::ref_ptr<AlphaFader> alphaFader (new AlphaFader(mAlphaUpdate));
|
||||
|
||||
if (composite)
|
||||
composite->addController(alphaFader);
|
||||
|
@ -1293,6 +1310,7 @@ public:
|
|||
mAlphaFaders.push_back(alphaFader);
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
|
@ -1303,19 +1321,19 @@ public:
|
|||
|
||||
private:
|
||||
std::vector<osg::ref_ptr<AlphaFader> > mAlphaFaders;
|
||||
float *mAlphaUpdate;
|
||||
};
|
||||
|
||||
protected:
|
||||
float mAlpha;
|
||||
float *mAlphaUpdate;
|
||||
};
|
||||
|
||||
class RainFader : public AlphaFader
|
||||
{
|
||||
public:
|
||||
|
||||
RainFader(osg::Uniform *rainIntensityUniform): AlphaFader()
|
||||
RainFader(float *alphaUpdate): AlphaFader(alphaUpdate)
|
||||
{
|
||||
mRainIntensityUniform = rainIntensityUniform;
|
||||
}
|
||||
|
||||
virtual void setDefaults(osg::StateSet* stateset)
|
||||
|
@ -1330,11 +1348,89 @@ public:
|
|||
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||
{
|
||||
AlphaFader::apply(stateset,nv);
|
||||
mRainIntensityUniform->set((float) (mAlpha * 2.0)); // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity
|
||||
*mAlphaUpdate = mAlpha * 2.0; // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity
|
||||
}
|
||||
};
|
||||
|
||||
void SkyManager::setCamera(osg::Camera *camera)
|
||||
{
|
||||
mCamera = camera;
|
||||
}
|
||||
|
||||
class WrapAroundOperator : public osgParticle::Operator
|
||||
{
|
||||
public:
|
||||
WrapAroundOperator(osg::Camera *camera, const osg::Vec3 &wrapRange): osgParticle::Operator()
|
||||
{
|
||||
mCamera = camera;
|
||||
mWrapRange = wrapRange;
|
||||
mHalfWrapRange = mWrapRange / 2.0;
|
||||
mPreviousCameraPosition = getCameraPosition();
|
||||
}
|
||||
|
||||
virtual osg::Object *cloneType() const override
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual osg::Object *clone(const osg::CopyOp &op) const override
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void operate(osgParticle::Particle *P, double dt) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operateParticles(osgParticle::ParticleSystem *ps, double dt) override
|
||||
{
|
||||
osg::Vec3 position = getCameraPosition();
|
||||
osg::Vec3 positionDifference = position - mPreviousCameraPosition;
|
||||
|
||||
osg::Matrix toWorld, toLocal;
|
||||
|
||||
std::vector<osg::Matrix> worldMatrices = ps->getWorldMatrices();
|
||||
|
||||
if (!worldMatrices.empty())
|
||||
{
|
||||
toWorld = worldMatrices[0];
|
||||
toLocal.invert(toWorld);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ps->numParticles(); ++i)
|
||||
{
|
||||
osgParticle::Particle *p = ps->getParticle(i);
|
||||
p->setPosition(toWorld.preMult(p->getPosition()));
|
||||
p->setPosition(p->getPosition() - positionDifference);
|
||||
|
||||
for (int j = 0; j < 3; ++j) // wrap-around in all 3 dimensions
|
||||
{
|
||||
osg::Vec3 pos = p->getPosition();
|
||||
|
||||
if (pos[j] < -mHalfWrapRange[j])
|
||||
pos[j] = mHalfWrapRange[j] + fmod(pos[j] - mHalfWrapRange[j],mWrapRange[j]);
|
||||
else if (pos[j] > mHalfWrapRange[j])
|
||||
pos[j] = fmod(pos[j] + mHalfWrapRange[j],mWrapRange[j]) - mHalfWrapRange[j];
|
||||
|
||||
p->setPosition(pos);
|
||||
}
|
||||
|
||||
p->setPosition(toLocal.preMult(p->getPosition()));
|
||||
}
|
||||
|
||||
mPreviousCameraPosition = position;
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::Uniform* mRainIntensityUniform;
|
||||
osg::Camera *mCamera;
|
||||
osg::Vec3 mPreviousCameraPosition;
|
||||
osg::Vec3 mWrapRange;
|
||||
osg::Vec3 mHalfWrapRange;
|
||||
|
||||
osg::Vec3 getCameraPosition()
|
||||
{
|
||||
return mCamera->getInverseViewMatrix().getTrans();
|
||||
}
|
||||
};
|
||||
|
||||
void SkyManager::createRain()
|
||||
|
@ -1345,6 +1441,8 @@ void SkyManager::createRain()
|
|||
mRainNode = new osg::Group;
|
||||
|
||||
mRainParticleSystem = new osgParticle::ParticleSystem;
|
||||
osg::Vec3 rainRange = osg::Vec3(600,600,600);
|
||||
|
||||
mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED);
|
||||
mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0));
|
||||
mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1));
|
||||
|
@ -1370,8 +1468,8 @@ void SkyManager::createRain()
|
|||
emitter->setParticleSystem(mRainParticleSystem);
|
||||
|
||||
osg::ref_ptr<osgParticle::BoxPlacer> placer (new osgParticle::BoxPlacer);
|
||||
placer->setXRange(-300, 300); // Rain_Diameter
|
||||
placer->setYRange(-300, 300);
|
||||
placer->setXRange(-rainRange.x() / 2, rainRange.x() / 2); // Rain_Diameter
|
||||
placer->setYRange(-rainRange.y() / 2, rainRange.y() / 2);
|
||||
placer->setZRange(300, 300);
|
||||
emitter->setPlacer(placer);
|
||||
|
||||
|
@ -1386,11 +1484,16 @@ void SkyManager::createRain()
|
|||
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater);
|
||||
updater->addParticleSystem(mRainParticleSystem);
|
||||
|
||||
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
|
||||
program->addOperator(new WrapAroundOperator(mCamera,rainRange));
|
||||
program->setParticleSystem(mRainParticleSystem);
|
||||
mRainNode->addChild(program);
|
||||
|
||||
mRainNode->addChild(emitter);
|
||||
mRainNode->addChild(mRainParticleSystem);
|
||||
mRainNode->addChild(updater);
|
||||
|
||||
mRainFader = new RainFader(mRootNode->getParent(0)->getParent(0)->getStateSet()->getUniform("rainIntensity"));
|
||||
mRainFader = new RainFader(&mWeatherAlpha);
|
||||
mRainNode->addUpdateCallback(mRainFader);
|
||||
mRainNode->addCullCallback(mUnderwaterSwitch);
|
||||
mRainNode->setNodeMask(Mask_WeatherParticles);
|
||||
|
@ -1443,7 +1546,21 @@ bool SkyManager::hasRain()
|
|||
|
||||
void SkyManager::update(float duration)
|
||||
{
|
||||
if (!mEnabled) return;
|
||||
if (!mEnabled)
|
||||
{
|
||||
if (mRainIntensityUniform)
|
||||
mRainIntensityUniform->set((float) 0.0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRainIntensityUniform)
|
||||
{
|
||||
if (mIsStorm || (!hasRain() && !mParticleNode))
|
||||
mRainIntensityUniform->set((float) 0.0);
|
||||
else
|
||||
mRainIntensityUniform->set((float) mWeatherAlpha);
|
||||
}
|
||||
|
||||
if (mIsStorm)
|
||||
{
|
||||
|
@ -1452,6 +1569,7 @@ void SkyManager::update(float duration)
|
|||
|
||||
if (mParticleNode)
|
||||
mParticleNode->setAttitude(quat);
|
||||
|
||||
mCloudNode->setAttitude(quat);
|
||||
}
|
||||
else
|
||||
|
@ -1548,17 +1666,35 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||
mParticleNode->setNodeMask(Mask_WeatherParticles);
|
||||
mRootNode->addChild(mParticleNode);
|
||||
}
|
||||
|
||||
mParticleEffect = mSceneManager->getInstance(mCurrentParticleEffect, mParticleNode);
|
||||
|
||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
|
||||
mParticleEffect->accept(assignVisitor);
|
||||
|
||||
AlphaFader::SetupVisitor alphaFaderSetupVisitor;
|
||||
AlphaFader::SetupVisitor alphaFaderSetupVisitor(&mWeatherAlpha);
|
||||
|
||||
mParticleEffect->accept(alphaFaderSetupVisitor);
|
||||
mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders();
|
||||
|
||||
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
||||
mParticleEffect->accept(disableFreezeOnCullVisitor);
|
||||
|
||||
if (!weather.mIsStorm)
|
||||
{
|
||||
SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem"));
|
||||
mParticleEffect->accept(findPSVisitor);
|
||||
|
||||
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
|
||||
{
|
||||
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(findPSVisitor.mFoundNodes[i]);
|
||||
|
||||
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
|
||||
program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800)));
|
||||
program->setParticleSystem(ps);
|
||||
mParticleNode->addChild(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1634,7 +1770,8 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||
mSun->adjustTransparency(weather.mGlareView * weather.mSunDiscColor.a());
|
||||
|
||||
float nextStarsOpacity = weather.mNightFade * weather.mGlareView;
|
||||
if(weather.mNight && mStarsOpacity != nextStarsOpacity)
|
||||
|
||||
if (weather.mNight && mStarsOpacity != nextStarsOpacity)
|
||||
{
|
||||
mStarsOpacity = nextStarsOpacity;
|
||||
|
||||
|
@ -1645,6 +1782,7 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||
|
||||
if (mRainFader)
|
||||
mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold?
|
||||
|
||||
for (std::vector<osg::ref_ptr<AlphaFader> >::const_iterator it = mParticleFaders.begin(); it != mParticleFaders.end(); ++it)
|
||||
(*it)->setAlpha(weather.mEffectFade);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Vec4f>
|
||||
#include <osg/Uniform>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Camera;
|
||||
}
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
@ -161,6 +167,10 @@ namespace MWRender
|
|||
|
||||
void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures);
|
||||
|
||||
void setCamera(osg::Camera *camera);
|
||||
|
||||
void setRainIntensityUniform(osg::Uniform *uniform);
|
||||
|
||||
private:
|
||||
void create();
|
||||
///< no need to call this, automatically done on first enable()
|
||||
|
@ -171,6 +181,9 @@ namespace MWRender
|
|||
|
||||
Resource::SceneManager* mSceneManager;
|
||||
|
||||
osg::Camera *mCamera;
|
||||
osg::Uniform *mRainIntensityUniform;
|
||||
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
osg::ref_ptr<osg::Group> mEarlyRenderBinRoot;
|
||||
|
||||
|
@ -239,6 +252,8 @@ namespace MWRender
|
|||
bool mEnabled;
|
||||
bool mSunEnabled;
|
||||
|
||||
float mWeatherAlpha;
|
||||
|
||||
osg::Vec4f mMoonScriptColor;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -411,12 +411,19 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
|||
createSimpleWaterStateSet(geom2, mFallback->getFallbackFloat("Water_Map_Alpha"));
|
||||
geom2->setNodeMask(Mask_SimpleWater);
|
||||
mWaterNode->addChild(geom2);
|
||||
|
||||
|
||||
mSceneRoot->addChild(mWaterNode);
|
||||
|
||||
setHeight(mTop);
|
||||
|
||||
updateWaterMaterial();
|
||||
|
||||
mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0);
|
||||
}
|
||||
|
||||
osg::Uniform *Water::getRainIntensityUniform()
|
||||
{
|
||||
return mRainIntensityUniform.get();
|
||||
}
|
||||
|
||||
void Water::updateWaterMaterial()
|
||||
|
@ -550,6 +557,8 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R
|
|||
program->addShader(fragmentShader);
|
||||
shaderStateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||
|
||||
shaderStateset->addUniform(mRainIntensityUniform);
|
||||
|
||||
node->setStateSet(shaderStateset);
|
||||
node->setUpdateCallback(NULL);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Uniform>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
|
@ -50,6 +51,8 @@ namespace MWRender
|
|||
{
|
||||
static const int CELL_SIZE = 8192;
|
||||
|
||||
osg::ref_ptr<osg::Uniform> mRainIntensityUniform;
|
||||
|
||||
osg::ref_ptr<osg::Group> mParent;
|
||||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> mWaterNode;
|
||||
|
@ -110,6 +113,8 @@ namespace MWRender
|
|||
void update(float dt);
|
||||
|
||||
void processChangedSettings(const Settings::CategorySettingVector& settings);
|
||||
|
||||
osg::Uniform *getRainIntensityUniform();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ void Config::GameSettings::validatePaths()
|
|||
|
||||
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
|
||||
QString path = QString::fromUtf8(it->string().c_str());
|
||||
path.remove(QChar('\"'));
|
||||
|
||||
QDir dir(path);
|
||||
if (dir.exists())
|
||||
|
@ -64,6 +63,11 @@ void Config::GameSettings::validatePaths()
|
|||
|
||||
// Do the same for data-local
|
||||
QString local = mSettings.value(QString("data-local"));
|
||||
if (local.at(0) == QChar('\"'))
|
||||
{
|
||||
local.remove(0, 1);
|
||||
local.chop(1);
|
||||
}
|
||||
|
||||
if (local.isEmpty())
|
||||
return;
|
||||
|
@ -76,7 +80,6 @@ void Config::GameSettings::validatePaths()
|
|||
|
||||
if (!dataDirs.empty()) {
|
||||
QString path = QString::fromUtf8(dataDirs.front().string().c_str());
|
||||
path.remove(QChar('\"'));
|
||||
|
||||
QDir dir(path);
|
||||
if (dir.exists())
|
||||
|
@ -120,6 +123,28 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMap<QString, QString>
|
|||
// Don't remove existing data entries
|
||||
if (key != QLatin1String("data"))
|
||||
settings.remove(key);
|
||||
else
|
||||
{
|
||||
// 'data=...' line, so needs processing to deal with ampersands and quotes
|
||||
// The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved
|
||||
QChar delim = '\"';
|
||||
QChar escape = '&';
|
||||
|
||||
if (value.at(0) == delim)
|
||||
{
|
||||
QString valueOriginal = value;
|
||||
value = "";
|
||||
|
||||
for (QString::const_iterator it = valueOriginal.begin() + 1; it != valueOriginal.end(); ++it)
|
||||
{
|
||||
if (*it == escape)
|
||||
++it;
|
||||
else if (*it == delim)
|
||||
break;
|
||||
value += *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList values = cache.values(key);
|
||||
values.append(settings.values(key));
|
||||
|
@ -152,9 +177,31 @@ bool Config::GameSettings::writeFile(QTextStream &stream)
|
|||
while (i.hasPrevious()) {
|
||||
i.previous();
|
||||
|
||||
// 'data=...' lines need quotes and ampersands escaping to match how boost::filesystem::path uses boost::io::quoted
|
||||
if (i.key() == QLatin1String("data"))
|
||||
{
|
||||
stream << i.key() << "=";
|
||||
|
||||
// The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved
|
||||
QChar delim = '\"';
|
||||
QChar escape = '&';
|
||||
QString string = i.value();
|
||||
|
||||
stream << delim;
|
||||
for (QString::const_iterator it = string.begin(); it != string.end(); ++it)
|
||||
{
|
||||
if (*it == delim || *it == escape)
|
||||
stream << escape;
|
||||
stream << *it;
|
||||
}
|
||||
stream << delim;
|
||||
|
||||
stream << '\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Quote paths with spaces
|
||||
if (i.key() == QLatin1String("data")
|
||||
|| i.key() == QLatin1String("data-local")
|
||||
if (i.key() == QLatin1String("data-local")
|
||||
|| i.key() == QLatin1String("resources"))
|
||||
{
|
||||
if (i.value().contains(QChar(' ')))
|
||||
|
@ -358,9 +405,26 @@ bool Config::GameSettings::writeFileWithComments(QFile &file)
|
|||
{
|
||||
it.previous();
|
||||
|
||||
if (it.key() == QLatin1String("data"))
|
||||
{
|
||||
settingLine = it.key() + "=";
|
||||
|
||||
// The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved
|
||||
QChar delim = '\"';
|
||||
QChar escape = '&';
|
||||
QString string = it.value();
|
||||
|
||||
settingLine += delim;
|
||||
for (QString::const_iterator iter = string.begin(); iter != string.end(); ++iter)
|
||||
{
|
||||
if (*iter == delim || *iter == escape)
|
||||
settingLine += escape;
|
||||
settingLine += *iter;
|
||||
}
|
||||
settingLine += delim;
|
||||
}
|
||||
// Quote paths with spaces
|
||||
if ((it.key() == QLatin1String("data")
|
||||
|| it.key() == QLatin1String("data-local")
|
||||
else if ((it.key() == QLatin1String("data-local")
|
||||
|| it.key() == QLatin1String("resources")) && it.value().contains(QChar(' ')))
|
||||
{
|
||||
QString stripped = it.value();
|
||||
|
|
|
@ -315,16 +315,7 @@ namespace ESM
|
|||
|
||||
bool Land::isDataLoaded(int flags) const
|
||||
{
|
||||
return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes);
|
||||
}
|
||||
|
||||
void Land::setDataLoaded(int flags)
|
||||
{
|
||||
if (!mLandData)
|
||||
mLandData = new LandData;
|
||||
|
||||
mDataTypes |= flags;
|
||||
mLandData->mDataLoaded |= flags;
|
||||
return mLandData && (mLandData->mDataLoaded & flags) == flags;
|
||||
}
|
||||
|
||||
Land::Land (const Land& land)
|
||||
|
|
|
@ -132,7 +132,6 @@ struct Land
|
|||
void unloadData() const;
|
||||
|
||||
/// Check if given data type is loaded
|
||||
/// @note We only check data types that *can* be loaded (present in mDataTypes)
|
||||
bool isDataLoaded(int flags) const;
|
||||
|
||||
/// Sets the flags and creates a LandData if needed
|
||||
|
|
|
@ -380,6 +380,7 @@ static std::map<short,std::string> genNameMap()
|
|||
names[131] ="sEffectBoundGloves";
|
||||
names[128] ="sEffectBoundHelm";
|
||||
names[125] ="sEffectBoundLongbow";
|
||||
names[126] ="sEffectExtraSpell";
|
||||
names[121] ="sEffectBoundLongsword";
|
||||
names[122] ="sEffectBoundMace";
|
||||
names[130] ="sEffectBoundShield";
|
||||
|
|
|
@ -75,8 +75,6 @@ void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool cre
|
|||
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
|
||||
{
|
||||
path = it->string();
|
||||
boost::erase_all(path, "\"");
|
||||
*it = boost::filesystem::path(path);
|
||||
|
||||
// Check if path contains a token
|
||||
if (!path.empty() && *path.begin() == '?')
|
||||
|
|
|
@ -49,7 +49,7 @@ BulletNifLoader::~BulletNifLoader()
|
|||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif)
|
||||
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr& nif)
|
||||
{
|
||||
mShape = new Resource::BulletShape;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
abort();
|
||||
}
|
||||
|
||||
osg::ref_ptr<Resource::BulletShape> load(const Nif::NIFFilePtr file);
|
||||
osg::ref_ptr<Resource::BulletShape> load(const Nif::NIFFilePtr& file);
|
||||
|
||||
private:
|
||||
bool findBoundingBox(const Nif::Node* node, int flags = 0);
|
||||
|
|
|
@ -1191,8 +1191,8 @@ namespace NifOsg
|
|||
if (pixelData->mipmaps.empty())
|
||||
return NULL;
|
||||
|
||||
unsigned int width = 0;
|
||||
unsigned int height = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
std::vector<unsigned int> mipmapVector;
|
||||
for (unsigned int i=0; i<pixelData->mipmaps.size()-3; ++i)
|
||||
|
|
|
@ -63,7 +63,7 @@ class NodeToShapeVisitor : public osg::NodeVisitor
|
|||
public:
|
||||
NodeToShapeVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mTriangleMesh(NULL)
|
||||
, mTriangleMesh(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -71,11 +71,11 @@ public:
|
|||
virtual void apply(osg::Drawable &drawable)
|
||||
{
|
||||
if (!mTriangleMesh)
|
||||
mTriangleMesh = new btTriangleMesh;
|
||||
mTriangleMesh.reset(new btTriangleMesh);
|
||||
|
||||
osg::Matrixf worldMat = osg::computeLocalToWorld(getNodePath());
|
||||
osg::TriangleFunctor<GetTriangleFunctor> functor;
|
||||
functor.setTriMesh(mTriangleMesh);
|
||||
functor.setTriMesh(mTriangleMesh.get());
|
||||
functor.setMatrix(worldMat);
|
||||
drawable.accept(functor);
|
||||
}
|
||||
|
@ -86,14 +86,12 @@ public:
|
|||
return osg::ref_ptr<BulletShape>();
|
||||
|
||||
osg::ref_ptr<BulletShape> shape (new BulletShape);
|
||||
TriangleMeshShape* meshShape = new TriangleMeshShape(mTriangleMesh, true);
|
||||
shape->mCollisionShape = meshShape;
|
||||
mTriangleMesh = NULL;
|
||||
shape->mCollisionShape = new TriangleMeshShape(mTriangleMesh.release(), true);
|
||||
return shape;
|
||||
}
|
||||
|
||||
private:
|
||||
btTriangleMesh* mTriangleMesh;
|
||||
std::unique_ptr<btTriangleMesh> mTriangleMesh;
|
||||
};
|
||||
|
||||
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager)
|
||||
|
@ -141,10 +139,7 @@ osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &
|
|||
node->accept(visitor);
|
||||
shape = visitor.getShape();
|
||||
if (!shape)
|
||||
{
|
||||
mCache->addEntryToObjectCache(normalized, NULL);
|
||||
return osg::ref_ptr<BulletShape>();
|
||||
}
|
||||
}
|
||||
|
||||
mCache->addEntryToObjectCache(normalized, shape);
|
||||
|
@ -158,7 +153,8 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(const std::s
|
|||
mVFS->normalizeFilename(normalized);
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> instance = createInstance(normalized);
|
||||
mInstanceCache->addEntryToObjectCache(normalized, instance.get());
|
||||
if (instance)
|
||||
mInstanceCache->addEntryToObjectCache(normalized, instance.get());
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ namespace Resource
|
|||
// This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG.
|
||||
&& !osg::isGLExtensionSupported(0, "GL_S3_s3tc"))
|
||||
{
|
||||
std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -123,12 +122,31 @@ namespace Resource
|
|||
return mWarningImage;
|
||||
}
|
||||
|
||||
osg::Image* image = result.getImage();
|
||||
osg::ref_ptr<osg::Image> image = result.getImage();
|
||||
|
||||
image->setFileName(normalized);
|
||||
if (!checkSupported(image, filename))
|
||||
{
|
||||
mCache->addEntryToObjectCache(normalized, mWarningImage);
|
||||
return mWarningImage;
|
||||
static bool uncompress = (getenv("OPENMW_DECOMPRESS_TEXTURES") != 0);
|
||||
if (!uncompress)
|
||||
{
|
||||
std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl;
|
||||
mCache->addEntryToObjectCache(normalized, mWarningImage);
|
||||
return mWarningImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
// decompress texture in software if not supported by GPU
|
||||
// requires update to getColor() to be released with OSG 3.6
|
||||
osg::ref_ptr<osg::Image> newImage = new osg::Image;
|
||||
newImage->setFileName(image->getFileName());
|
||||
newImage->allocateImage(image->s(), image->t(), image->r(), image->isImageTranslucent() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);
|
||||
for (int s=0; s<image->s(); ++s)
|
||||
for (int t=0; t<image->t(); ++t)
|
||||
for (int r=0; r<image->r(); ++r)
|
||||
newImage->setColor(image->getColor(s,t,r), s,t,r);
|
||||
image = newImage;
|
||||
}
|
||||
}
|
||||
|
||||
mCache->addEntryToObjectCache(normalized, image);
|
||||
|
|
|
@ -51,6 +51,11 @@ namespace Resource
|
|||
|
||||
void MultiObjectCache::addEntryToObjectCache(const std::string &filename, osg::Object *object)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl;
|
||||
return;
|
||||
}
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
_objectCache.insert(std::make_pair(filename, object));
|
||||
}
|
||||
|
|
|
@ -34,6 +34,11 @@ ObjectCache::~ObjectCache()
|
|||
|
||||
void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl;
|
||||
return;
|
||||
}
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
_objectCache[filename]=ObjectTimeStampPair(object,timestamp);
|
||||
}
|
||||
|
|
|
@ -244,12 +244,9 @@ namespace Resource
|
|||
|
||||
void SceneManager::recreateShaders(osg::ref_ptr<osg::Node> node)
|
||||
{
|
||||
Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl");
|
||||
shaderVisitor.setForceShaders(mForceShaders);
|
||||
shaderVisitor.setClampLighting(mClampLighting);
|
||||
shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting);
|
||||
shaderVisitor.setAllowedToModifyStateSets(false);
|
||||
node->accept(shaderVisitor);
|
||||
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(createShaderVisitor());
|
||||
shaderVisitor->setAllowedToModifyStateSets(false);
|
||||
node->accept(*shaderVisitor);
|
||||
}
|
||||
|
||||
void SceneManager::setClampLighting(bool clamp)
|
||||
|
@ -516,16 +513,8 @@ namespace Resource
|
|||
SetFilterSettingsControllerVisitor setFilterSettingsControllerVisitor(mMinFilter, mMagFilter, mMaxAnisotropy);
|
||||
loaded->accept(setFilterSettingsControllerVisitor);
|
||||
|
||||
Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl");
|
||||
shaderVisitor.setForceShaders(mForceShaders);
|
||||
shaderVisitor.setClampLighting(mClampLighting);
|
||||
shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting);
|
||||
shaderVisitor.setAutoUseNormalMaps(mAutoUseNormalMaps);
|
||||
shaderVisitor.setNormalMapPattern(mNormalMapPattern);
|
||||
shaderVisitor.setNormalHeightMapPattern(mNormalHeightMapPattern);
|
||||
shaderVisitor.setAutoUseSpecularMaps(mAutoUseSpecularMaps);
|
||||
shaderVisitor.setSpecularMapPattern(mSpecularMapPattern);
|
||||
loaded->accept(shaderVisitor);
|
||||
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor (createShaderVisitor());
|
||||
loaded->accept(*shaderVisitor);
|
||||
|
||||
// share state
|
||||
// do this before optimizing so the optimizer will be able to combine nodes more aggressively
|
||||
|
@ -748,4 +737,18 @@ namespace Resource
|
|||
stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize());
|
||||
}
|
||||
|
||||
Shader::ShaderVisitor *SceneManager::createShaderVisitor()
|
||||
{
|
||||
Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl");
|
||||
shaderVisitor->setForceShaders(mForceShaders);
|
||||
shaderVisitor->setClampLighting(mClampLighting);
|
||||
shaderVisitor->setForcePerPixelLighting(mForcePerPixelLighting);
|
||||
shaderVisitor->setAutoUseNormalMaps(mAutoUseNormalMaps);
|
||||
shaderVisitor->setNormalMapPattern(mNormalMapPattern);
|
||||
shaderVisitor->setNormalHeightMapPattern(mNormalHeightMapPattern);
|
||||
shaderVisitor->setAutoUseSpecularMaps(mAutoUseSpecularMaps);
|
||||
shaderVisitor->setSpecularMapPattern(mSpecularMapPattern);
|
||||
return shaderVisitor;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace osgDB
|
|||
namespace Shader
|
||||
{
|
||||
class ShaderManager;
|
||||
class ShaderVisitor;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
|
@ -149,6 +150,8 @@ namespace Resource
|
|||
|
||||
private:
|
||||
|
||||
Shader::ShaderVisitor* createShaderVisitor();
|
||||
|
||||
std::unique_ptr<Shader::ShaderManager> mShaderManager;
|
||||
bool mForceShaders;
|
||||
bool mClampLighting;
|
||||
|
|
|
@ -42,13 +42,4 @@ osg::Vec4f colourFromRGB(unsigned int clr)
|
|||
return colour;
|
||||
}
|
||||
|
||||
osg::Vec4f colourFromRGBA(unsigned int clr)
|
||||
{
|
||||
osg::Vec4f colour(((clr >> 0) & 0xFF) / 255.0f,
|
||||
((clr >> 8) & 0xFF) / 255.0f,
|
||||
((clr >> 16) & 0xFF) / 255.0f,
|
||||
((clr >> 24) & 0xFF) / 255.0f);
|
||||
return colour;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ namespace SceneUtil
|
|||
|
||||
osg::Vec4f colourFromRGB (unsigned int clr);
|
||||
|
||||
osg::Vec4f colourFromRGBA (unsigned int clr);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,14 @@ namespace SceneUtil
|
|||
return false;
|
||||
}
|
||||
|
||||
void FindByClassVisitor::apply(osg::Node &node)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(node.className(), mNameToFind))
|
||||
mFoundNodes.push_back(&node);
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void FindByNameVisitor::apply(osg::Group &group)
|
||||
{
|
||||
if (!checkGroup(group))
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace SceneUtil
|
|||
}
|
||||
|
||||
virtual void apply(osg::Group& group);
|
||||
|
||||
virtual void apply(osg::MatrixTransform& node);
|
||||
virtual void apply(osg::Geometry& node);
|
||||
|
||||
|
@ -30,6 +29,21 @@ namespace SceneUtil
|
|||
osg::Group* mFoundNode;
|
||||
};
|
||||
|
||||
class FindByClassVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
FindByClassVisitor(const std::string& nameToFind)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mNameToFind(nameToFind)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node &node);
|
||||
|
||||
std::string mNameToFind;
|
||||
std::vector<osg::Node *> mFoundNodes;
|
||||
};
|
||||
|
||||
// Disable freezeOnCull for all visited particlesystems
|
||||
class DisableFreezeOnCullVisitor : public osg::NodeVisitor
|
||||
{
|
||||
|
|
|
@ -119,6 +119,7 @@ unsigned int WorkQueue::getNumActiveThreads() const
|
|||
|
||||
WorkThread::WorkThread(WorkQueue *workQueue)
|
||||
: mWorkQueue(workQueue)
|
||||
, mActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
2
extern/osg-ffmpeg-videoplayer/License.txt
vendored
2
extern/osg-ffmpeg-videoplayer/License.txt
vendored
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2014 Jannik Heller <scrawl@baseoftrash.de>, Chris Robinson
|
||||
Copyright (c) 2014 scrawl, Chris Robinson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
Loading…
Reference in a new issue