forked from teamnwah/openmw-tes3coop
Merge pull request #145 from OpenMW/master while resolving conflicts
# Conflicts: # CMakeLists.txt
This commit is contained in:
commit
ae23c6d6a5
30 changed files with 329 additions and 126 deletions
|
@ -252,10 +252,15 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(REQUIRED_BULLET_VERSION 286) # Bullet 286 required due to runtime bugfixes for btCapsuleShape
|
||||||
|
if (DEFINED ENV{TRAVIS_BRANCH} OR DEFINED ENV{APPVEYOR})
|
||||||
|
set(REQUIRED_BULLET_VERSION 283) # but for build testing, 283 is fine
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(MyGUI 3.2.1 REQUIRED)
|
find_package(MyGUI 3.2.1 REQUIRED)
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
find_package(Bullet 283 REQUIRED COMPONENTS BulletCollision LinearMath)
|
find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath)
|
||||||
|
|
||||||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||||
|
|
||||||
|
|
|
@ -675,8 +675,6 @@ void OMW::Engine::go()
|
||||||
}
|
}
|
||||||
else if (!mSkipMenu)
|
else if (!mSkipMenu)
|
||||||
{
|
{
|
||||||
mEnvironment.getWorld()->preloadCommonAssets();
|
|
||||||
|
|
||||||
// start in main menu
|
// start in main menu
|
||||||
mEnvironment.getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
mEnvironment.getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||||
try
|
try
|
||||||
|
|
|
@ -95,8 +95,6 @@ namespace MWBase
|
||||||
|
|
||||||
virtual ~World() {}
|
virtual ~World() {}
|
||||||
|
|
||||||
virtual void preloadCommonAssets() = 0;
|
|
||||||
|
|
||||||
virtual void startNewGame (bool bypass) = 0;
|
virtual void startNewGame (bool bypass) = 0;
|
||||||
///< \param bypass Bypass regular game start.
|
///< \param bypass Bypass regular game start.
|
||||||
|
|
||||||
|
|
|
@ -268,12 +268,12 @@ namespace MWPhysics
|
||||||
( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length2() > 35*35
|
( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length2() > 35*35
|
||||||
|| !isWalkableSlope(tracer.mPlaneNormal)))
|
|| !isWalkableSlope(tracer.mPlaneNormal)))
|
||||||
{
|
{
|
||||||
actor->setOnSlope(isWalkableSlope(resultCallback1.m_hitNormalWorld));
|
actor->setOnSlope(!isWalkableSlope(resultCallback1.m_hitNormalWorld));
|
||||||
return toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, 1.f);
|
return toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, 1.f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
actor->setOnSlope(isWalkableSlope(tracer.mPlaneNormal));
|
actor->setOnSlope(!isWalkableSlope(tracer.mPlaneNormal));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tracer.mEndPos;
|
return tracer.mEndPos;
|
||||||
|
|
|
@ -543,7 +543,7 @@ namespace MWRender
|
||||||
size_t blendMask = detectBlendMask(node);
|
size_t blendMask = detectBlendMask(node);
|
||||||
|
|
||||||
// clone the controller, because each Animation needs its own ControllerSource
|
// clone the controller, because each Animation needs its own ControllerSource
|
||||||
osg::ref_ptr<NifOsg::KeyframeController> cloned = osg::clone(it->second.get(), osg::CopyOp::DEEP_COPY_ALL);
|
osg::ref_ptr<NifOsg::KeyframeController> cloned = new NifOsg::KeyframeController(*it->second, osg::CopyOp::SHALLOW_COPY);
|
||||||
cloned->setSource(mAnimationTimePtr[blendMask]);
|
cloned->setSource(mAnimationTimePtr[blendMask]);
|
||||||
|
|
||||||
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
|
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
|
||||||
|
@ -1272,7 +1272,7 @@ namespace MWRender
|
||||||
writableStateSet = node->getOrCreateStateSet();
|
writableStateSet = node->getOrCreateStateSet();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writableStateSet = osg::clone(node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
writableStateSet = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
||||||
node->setStateSet(writableStateSet);
|
node->setStateSet(writableStateSet);
|
||||||
}
|
}
|
||||||
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
||||||
|
|
|
@ -231,13 +231,51 @@ void LocalMap::setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int
|
||||||
segment.mMapTexture = texture;
|
segment.mMapTexture = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needUpdate(std::set<std::pair<int, int> >& renderedGrid, std::set<std::pair<int, int> >& currentGrid, int cellX, int cellY)
|
||||||
|
{
|
||||||
|
// if all the cells of the current grid are contained in the rendered grid then we can keep the old render
|
||||||
|
for (int dx=-1;dx<2;dx+=1)
|
||||||
|
{
|
||||||
|
for (int dy=-1;dy<2;dy+=1)
|
||||||
|
{
|
||||||
|
bool haveInRenderedGrid = renderedGrid.find(std::make_pair(cellX+dx,cellY+dy)) != renderedGrid.end();
|
||||||
|
bool haveInCurrentGrid = currentGrid.find(std::make_pair(cellX+dx,cellY+dy)) != currentGrid.end();
|
||||||
|
if (haveInCurrentGrid && !haveInRenderedGrid)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells)
|
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells)
|
||||||
{
|
{
|
||||||
|
std::set<std::pair<int, int> > grid;
|
||||||
for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
|
for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
|
||||||
{
|
{
|
||||||
const MWWorld::CellStore* cell = *it;
|
const MWWorld::CellStore* cell = *it;
|
||||||
if (cell->isExterior())
|
if (cell->isExterior())
|
||||||
|
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
|
||||||
|
{
|
||||||
|
const MWWorld::CellStore* cell = *it;
|
||||||
|
if (cell->isExterior())
|
||||||
|
{
|
||||||
|
int cellX = cell->getCell()->getGridX();
|
||||||
|
int cellY = cell->getCell()->getGridY();
|
||||||
|
|
||||||
|
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
|
||||||
|
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segment.mGrid = grid;
|
||||||
requestExteriorMap(cell);
|
requestExteriorMap(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
requestInteriorMap(cell);
|
requestInteriorMap(cell);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,8 @@ namespace MWRender
|
||||||
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
|
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
|
||||||
osg::ref_ptr<osg::Image> mFogOfWarImage;
|
osg::ref_ptr<osg::Image> mFogOfWarImage;
|
||||||
|
|
||||||
|
std::set<std::pair<int, int> > mGrid; // the grid that was active at the time of rendering this segment
|
||||||
|
|
||||||
bool mHasFogState;
|
bool mHasFogState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/resource/keyframemanager.hpp>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
@ -139,15 +140,25 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void doWork()
|
virtual void doWork()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
for (std::vector<std::string>::const_iterator it = mModels.begin(); it != mModels.end(); ++it)
|
for (std::vector<std::string>::const_iterator it = mModels.begin(); it != mModels.end(); ++it)
|
||||||
mResourceSystem->getSceneManager()->getTemplate(*it);
|
mResourceSystem->getSceneManager()->cacheInstance(*it);
|
||||||
for (std::vector<std::string>::const_iterator it = mTextures.begin(); it != mTextures.end(); ++it)
|
for (std::vector<std::string>::const_iterator it = mTextures.begin(); it != mTextures.end(); ++it)
|
||||||
mResourceSystem->getImageManager()->getImage(*it);
|
mResourceSystem->getImageManager()->getImage(*it);
|
||||||
|
for (std::vector<std::string>::const_iterator it = mKeyframes.begin(); it != mKeyframes.end(); ++it)
|
||||||
|
mResourceSystem->getKeyframeManager()->get(*it);
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
// ignore error (will be shown when these are needed proper)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> mModels;
|
std::vector<std::string> mModels;
|
||||||
std::vector<std::string> mTextures;
|
std::vector<std::string> mTextures;
|
||||||
|
std::vector<std::string> mKeyframes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
@ -308,6 +319,13 @@ namespace MWRender
|
||||||
mSky->listAssetsToPreload(workItem->mModels, workItem->mTextures);
|
mSky->listAssetsToPreload(workItem->mModels, workItem->mTextures);
|
||||||
mWater->listAssetsToPreload(workItem->mTextures);
|
mWater->listAssetsToPreload(workItem->mTextures);
|
||||||
|
|
||||||
|
const char* basemodels[] = {"xbase_anim", "xbase_anim.1st", "xbase_anim_female", "xbase_animkna"};
|
||||||
|
for (size_t i=0; i<sizeof(basemodels)/sizeof(basemodels[0]); ++i)
|
||||||
|
{
|
||||||
|
workItem->mModels.push_back(std::string("meshes/") + basemodels[i] + ".nif");
|
||||||
|
workItem->mKeyframes.push_back(std::string("meshes/") + basemodels[i] + ".kf");
|
||||||
|
}
|
||||||
|
|
||||||
workItem->mTextures.push_back("textures/_land_default.dds");
|
workItem->mTextures.push_back("textures/_land_default.dds");
|
||||||
|
|
||||||
mWorkQueue->addWorkItem(workItem);
|
mWorkQueue->addWorkItem(workItem);
|
||||||
|
@ -435,14 +453,6 @@ namespace MWRender
|
||||||
mViewer->getCamera()->setCullMask(mask);
|
mViewer->getCamera()->setCullMask(mask);
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
else //if (mode == Render_BoundingBoxes)
|
|
||||||
{
|
|
||||||
bool show = !mRendering.getScene()->getShowBoundingBoxes();
|
|
||||||
mRendering.getScene()->showBoundingBoxes(show);
|
|
||||||
return show;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ namespace MWRender
|
||||||
Render_CollisionDebug,
|
Render_CollisionDebug,
|
||||||
Render_Wireframe,
|
Render_Wireframe,
|
||||||
Render_Pathgrid,
|
Render_Pathgrid,
|
||||||
Render_BoundingBoxes,
|
|
||||||
Render_Water,
|
Render_Water,
|
||||||
Render_Scene
|
Render_Scene
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> stateset;
|
osg::ref_ptr<osg::StateSet> stateset;
|
||||||
if (node->getStateSet())
|
if (node->getStateSet())
|
||||||
stateset = osg::clone(node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
stateset = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
||||||
else
|
else
|
||||||
stateset = new osg::StateSet;
|
stateset = new osg::StateSet;
|
||||||
|
|
||||||
|
|
|
@ -278,10 +278,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
bool enabled =
|
bool enabled =
|
||||||
MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_BoundingBoxes);
|
MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_CollisionDebug);
|
||||||
|
|
||||||
runtime.getContext().report (enabled ?
|
runtime.getContext().report (enabled ?
|
||||||
"Bounding Box Rendering -> On" : "Bounding Box Rendering -> Off");
|
"Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,10 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(std::exception&)
|
||||||
{
|
{
|
||||||
|
if(mStream)
|
||||||
|
avcodec_close((*mStream)->codec);
|
||||||
|
mStream = NULL;
|
||||||
|
|
||||||
if (mFormatCtx->pb->buffer != NULL)
|
if (mFormatCtx->pb->buffer != NULL)
|
||||||
{
|
{
|
||||||
av_free(mFormatCtx->pb->buffer);
|
av_free(mFormatCtx->pb->buffer);
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace MWWorld
|
||||||
, mKeyframeManager(keyframeManager)
|
, mKeyframeManager(keyframeManager)
|
||||||
, mTerrain(terrain)
|
, mTerrain(terrain)
|
||||||
, mPreloadInstances(preloadInstances)
|
, mPreloadInstances(preloadInstances)
|
||||||
|
, mAbort(false)
|
||||||
{
|
{
|
||||||
ListModelsVisitor visitor (mMeshes);
|
ListModelsVisitor visitor (mMeshes);
|
||||||
if (cell->getState() == MWWorld::CellStore::State_Loaded)
|
if (cell->getState() == MWWorld::CellStore::State_Loaded)
|
||||||
|
@ -76,11 +77,30 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void abort()
|
||||||
|
{
|
||||||
|
mAbort = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Preload work to be called from the worker thread.
|
/// Preload work to be called from the worker thread.
|
||||||
virtual void doWork()
|
virtual void doWork()
|
||||||
{
|
{
|
||||||
|
if (mIsExterior)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mPreloadedObjects.push_back(mTerrain->cacheCell(mX, mY));
|
||||||
|
}
|
||||||
|
catch(std::exception& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (MeshList::const_iterator it = mMeshes.begin(); it != mMeshes.end(); ++it)
|
for (MeshList::const_iterator it = mMeshes.begin(); it != mMeshes.end(); ++it)
|
||||||
{
|
{
|
||||||
|
if (mAbort)
|
||||||
|
break;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::string mesh = *it;
|
std::string mesh = *it;
|
||||||
|
@ -119,17 +139,6 @@ namespace MWWorld
|
||||||
// error will be shown when visiting the cell
|
// error will be shown when visiting the cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsExterior)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mPreloadedObjects.push_back(mTerrain->cacheCell(mX, mY));
|
|
||||||
}
|
|
||||||
catch(std::exception& e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -144,6 +153,8 @@ namespace MWWorld
|
||||||
Terrain::World* mTerrain;
|
Terrain::World* mTerrain;
|
||||||
bool mPreloadInstances;
|
bool mPreloadInstances;
|
||||||
|
|
||||||
|
volatile bool mAbort;
|
||||||
|
|
||||||
// keep a ref to the loaded objects to make sure it stays loaded as long as this cell is in the preloaded state
|
// keep a ref to the loaded objects to make sure it stays loaded as long as this cell is in the preloaded state
|
||||||
std::vector<osg::ref_ptr<const osg::Object> > mPreloadedObjects;
|
std::vector<osg::ref_ptr<const osg::Object> > mPreloadedObjects;
|
||||||
};
|
};
|
||||||
|
@ -187,7 +198,10 @@ namespace MWWorld
|
||||||
CellPreloader::~CellPreloader()
|
CellPreloader::~CellPreloader()
|
||||||
{
|
{
|
||||||
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();++it)
|
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();++it)
|
||||||
|
{
|
||||||
|
it->second.mWorkItem->abort();
|
||||||
it->second.mWorkItem->waitTillDone();
|
it->second.mWorkItem->waitTillDone();
|
||||||
|
}
|
||||||
mPreloadCells.clear();
|
mPreloadCells.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +242,10 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldestTimestamp + threshold < timestamp)
|
if (oldestTimestamp + threshold < timestamp)
|
||||||
|
{
|
||||||
|
oldestCell->second.mWorkItem->abort();
|
||||||
mPreloadCells.erase(oldestCell);
|
mPreloadCells.erase(oldestCell);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -246,18 +263,42 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
// do the deletion in the background thread
|
// do the deletion in the background thread
|
||||||
if (found->second.mWorkItem)
|
if (found->second.mWorkItem)
|
||||||
|
{
|
||||||
|
found->second.mWorkItem->abort();
|
||||||
mUnrefQueue->push(mPreloadCells[cell].mWorkItem);
|
mUnrefQueue->push(mPreloadCells[cell].mWorkItem);
|
||||||
|
}
|
||||||
|
|
||||||
mPreloadCells.erase(found);
|
mPreloadCells.erase(found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellPreloader::clear()
|
||||||
|
{
|
||||||
|
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();)
|
||||||
|
{
|
||||||
|
if (it->second.mWorkItem)
|
||||||
|
{
|
||||||
|
it->second.mWorkItem->abort();
|
||||||
|
mUnrefQueue->push(it->second.mWorkItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreloadCells.erase(it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CellPreloader::updateCache(double timestamp)
|
void CellPreloader::updateCache(double timestamp)
|
||||||
{
|
{
|
||||||
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();)
|
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();)
|
||||||
{
|
{
|
||||||
if (mPreloadCells.size() >= mMinCacheSize && it->second.mTimeStamp < timestamp - mExpiryDelay)
|
if (mPreloadCells.size() >= mMinCacheSize && it->second.mTimeStamp < timestamp - mExpiryDelay)
|
||||||
|
{
|
||||||
|
if (it->second.mWorkItem)
|
||||||
|
{
|
||||||
|
it->second.mWorkItem->abort();
|
||||||
|
mUnrefQueue->push(it->second.mWorkItem);
|
||||||
|
}
|
||||||
mPreloadCells.erase(it++);
|
mPreloadCells.erase(it++);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void notifyLoaded(MWWorld::CellStore* cell);
|
void notifyLoaded(MWWorld::CellStore* cell);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
/// Removes preloaded cells that have not had a preload request for a while.
|
/// Removes preloaded cells that have not had a preload request for a while.
|
||||||
void updateCache(double timestamp);
|
void updateCache(double timestamp);
|
||||||
|
|
||||||
|
|
|
@ -205,9 +205,9 @@ namespace MWWorld
|
||||||
if (mPreloadEnabled)
|
if (mPreloadEnabled)
|
||||||
{
|
{
|
||||||
mPreloadTimer += duration;
|
mPreloadTimer += duration;
|
||||||
if (mPreloadTimer > 0.25f)
|
if (mPreloadTimer > 0.1f)
|
||||||
{
|
{
|
||||||
preloadCells();
|
preloadCells(0.1f);
|
||||||
mPreloadTimer = 0.f;
|
mPreloadTimer = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,13 +328,15 @@ namespace MWWorld
|
||||||
mPreloader->notifyLoaded(cell);
|
mPreloader->notifyLoaded(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeToVoid()
|
void Scene::clear()
|
||||||
{
|
{
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||||
while (active!=mActiveCells.end())
|
while (active!=mActiveCells.end())
|
||||||
unloadCell (active++);
|
unloadCell (active++);
|
||||||
assert(mActiveCells.empty());
|
assert(mActiveCells.empty());
|
||||||
mCurrentCell = NULL;
|
mCurrentCell = NULL;
|
||||||
|
|
||||||
|
mPreloader->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::playerMoved(const osg::Vec3f &pos)
|
void Scene::playerMoved(const osg::Vec3f &pos)
|
||||||
|
@ -481,6 +483,8 @@ namespace MWWorld
|
||||||
mechMgr->watchActor(player);
|
mechMgr->watchActor(player);
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->adjustSky();
|
MWBase::Environment::get().getWorld()->adjustSky();
|
||||||
|
|
||||||
|
mLastPlayerPos = pos.asVec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics)
|
Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics)
|
||||||
|
@ -675,17 +679,24 @@ namespace MWWorld
|
||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::preloadCells()
|
void Scene::preloadCells(float dt)
|
||||||
{
|
{
|
||||||
|
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||||
|
osg::Vec3f moved = playerPos - mLastPlayerPos;
|
||||||
|
osg::Vec3f predictedPos = playerPos + moved / dt;
|
||||||
|
|
||||||
|
mLastPlayerPos = playerPos;
|
||||||
|
|
||||||
if (mPreloadDoors)
|
if (mPreloadDoors)
|
||||||
preloadTeleportDoorDestinations();
|
preloadTeleportDoorDestinations(playerPos, predictedPos);
|
||||||
if (mPreloadExteriorGrid)
|
if (mPreloadExteriorGrid)
|
||||||
preloadExteriorGrid();
|
preloadExteriorGrid(playerPos, predictedPos);
|
||||||
if (mPreloadFastTravel)
|
if (mPreloadFastTravel)
|
||||||
preloadFastTravelDestinations();
|
preloadFastTravelDestinations(playerPos, predictedPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::preloadTeleportDoorDestinations()
|
void Scene::preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos)
|
||||||
{
|
{
|
||||||
std::vector<MWWorld::ConstPtr> teleportDoors;
|
std::vector<MWWorld::ConstPtr> teleportDoors;
|
||||||
for (CellStoreCollection::const_iterator iter (mActiveCells.begin());
|
for (CellStoreCollection::const_iterator iter (mActiveCells.begin());
|
||||||
|
@ -703,11 +714,11 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
for (std::vector<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it)
|
for (std::vector<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it)
|
||||||
{
|
{
|
||||||
const MWWorld::ConstPtr& door = *it;
|
const MWWorld::ConstPtr& door = *it;
|
||||||
float sqrDistToPlayer = (player.getRefData().getPosition().asVec3() - door.getRefData().getPosition().asVec3()).length2();
|
float sqrDistToPlayer = (playerPos - door.getRefData().getPosition().asVec3()).length2();
|
||||||
|
sqrDistToPlayer = std::min(sqrDistToPlayer, (predictedPos - door.getRefData().getPosition().asVec3()).length2());
|
||||||
|
|
||||||
if (sqrDistToPlayer < mPreloadDistance*mPreloadDistance)
|
if (sqrDistToPlayer < mPreloadDistance*mPreloadDistance)
|
||||||
{
|
{
|
||||||
|
@ -730,15 +741,13 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::preloadExteriorGrid()
|
void Scene::preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos)
|
||||||
{
|
{
|
||||||
if (!MWBase::Environment::get().getWorld()->isCellExterior())
|
if (!MWBase::Environment::get().getWorld()->isCellExterior())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int halfGridSizePlusOne = mHalfGridSize + 1;
|
int halfGridSizePlusOne = mHalfGridSize + 1;
|
||||||
|
|
||||||
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
|
||||||
|
|
||||||
int cellX,cellY;
|
int cellX,cellY;
|
||||||
getGridCenter(cellX,cellY);
|
getGridCenter(cellX,cellY);
|
||||||
|
@ -757,6 +766,7 @@ namespace MWWorld
|
||||||
MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true);
|
MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true);
|
||||||
|
|
||||||
float dist = std::max(std::abs(thisCellCenterX - playerPos.x()), std::abs(thisCellCenterY - playerPos.y()));
|
float dist = std::max(std::abs(thisCellCenterX - playerPos.x()), std::abs(thisCellCenterY - playerPos.y()));
|
||||||
|
dist = std::min(dist,std::max(std::abs(thisCellCenterX - predictedPos.x()), std::abs(thisCellCenterY - predictedPos.y())));
|
||||||
float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance;
|
float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance;
|
||||||
|
|
||||||
if (dist < loadDist)
|
if (dist < loadDist)
|
||||||
|
@ -816,7 +826,7 @@ namespace MWWorld
|
||||||
std::vector<ESM::Transport::Dest> mList;
|
std::vector<ESM::Transport::Dest> mList;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Scene::preloadFastTravelDestinations()
|
void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/) // ignore predictedPos here since opening dialogue with travel service takes extra time
|
||||||
{
|
{
|
||||||
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3());
|
ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3());
|
||||||
|
|
|
@ -68,6 +68,8 @@ namespace MWWorld
|
||||||
bool mPreloadDoors;
|
bool mPreloadDoors;
|
||||||
bool mPreloadFastTravel;
|
bool mPreloadFastTravel;
|
||||||
|
|
||||||
|
osg::Vec3f mLastPlayerPos;
|
||||||
|
|
||||||
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener);
|
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener);
|
||||||
|
|
||||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||||
|
@ -75,12 +77,10 @@ namespace MWWorld
|
||||||
|
|
||||||
void getGridCenter(int& cellX, int& cellY);
|
void getGridCenter(int& cellX, int& cellY);
|
||||||
|
|
||||||
void preloadCells();
|
void preloadCells(float dt);
|
||||||
void preloadTeleportDoorDestinations();
|
void preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
|
||||||
void preloadExteriorGrid();
|
void preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
|
||||||
void preloadFastTravelDestinations();
|
void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
|
||||||
|
|
||||||
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -88,6 +88,8 @@ namespace MWWorld
|
||||||
|
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
|
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
|
||||||
|
|
||||||
void unloadCell (CellStoreCollection::iterator iter);
|
void unloadCell (CellStoreCollection::iterator iter);
|
||||||
|
|
||||||
void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn);
|
void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn);
|
||||||
|
@ -111,7 +113,7 @@ namespace MWWorld
|
||||||
///< Move to exterior cell.
|
///< Move to exterior cell.
|
||||||
/// @param changeEvent Set cellChanged flag?
|
/// @param changeEvent Set cellChanged flag?
|
||||||
|
|
||||||
void changeToVoid();
|
void clear();
|
||||||
///< Change into a void
|
///< Change into a void
|
||||||
|
|
||||||
void markCellAsUnchanged();
|
void markCellAsUnchanged();
|
||||||
|
|
|
@ -164,6 +164,8 @@ namespace MWWorld
|
||||||
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath);
|
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath);
|
||||||
mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics));
|
mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics));
|
||||||
|
|
||||||
|
mRendering->preloadCommonAssets();
|
||||||
|
|
||||||
mEsm.resize(contentFiles.size());
|
mEsm.resize(contentFiles.size());
|
||||||
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
listener->loadingOn();
|
listener->loadingOn();
|
||||||
|
@ -303,7 +305,7 @@ namespace MWWorld
|
||||||
mProjectileManager->clear();
|
mProjectileManager->clear();
|
||||||
mLocalScripts.clear();
|
mLocalScripts.clear();
|
||||||
|
|
||||||
mWorldScene->changeToVoid();
|
mWorldScene->clear();
|
||||||
|
|
||||||
mStore.clearDynamic();
|
mStore.clearDynamic();
|
||||||
mStore.setUp();
|
mStore.setUp();
|
||||||
|
@ -359,9 +361,9 @@ namespace MWWorld
|
||||||
|
|
||||||
mStore.write (writer, progress); // dynamic Store must be written (and read) before Cells, so that
|
mStore.write (writer, progress); // dynamic Store must be written (and read) before Cells, so that
|
||||||
// references to custom made records will be recognized
|
// references to custom made records will be recognized
|
||||||
|
mPlayer->write (writer, progress);
|
||||||
mCells.write (writer, progress);
|
mCells.write (writer, progress);
|
||||||
mGlobalVariables.write (writer, progress);
|
mGlobalVariables.write (writer, progress);
|
||||||
mPlayer->write (writer, progress);
|
|
||||||
mWeatherManager->write (writer, progress);
|
mWeatherManager->write (writer, progress);
|
||||||
mProjectileManager->write (writer, progress);
|
mProjectileManager->write (writer, progress);
|
||||||
|
|
||||||
|
@ -387,10 +389,13 @@ namespace MWWorld
|
||||||
reader.getHNT(mTeleportEnabled, "TELE");
|
reader.getHNT(mTeleportEnabled, "TELE");
|
||||||
reader.getHNT(mLevitationEnabled, "LEVT");
|
reader.getHNT(mLevitationEnabled, "LEVT");
|
||||||
return;
|
return;
|
||||||
|
case ESM::REC_PLAY:
|
||||||
|
mPlayer->readRecord(reader, type);
|
||||||
|
mWorldScene->preloadCell(getPlayerPtr().getCell(), true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!mStore.readRecord (reader, type) &&
|
if (!mStore.readRecord (reader, type) &&
|
||||||
!mGlobalVariables.readRecord (reader, type) &&
|
!mGlobalVariables.readRecord (reader, type) &&
|
||||||
!mPlayer->readRecord (reader, type) &&
|
|
||||||
!mWeatherManager->readRecord (reader, type) &&
|
!mWeatherManager->readRecord (reader, type) &&
|
||||||
!mCells.readRecord (reader, type, contentFileMap)
|
!mCells.readRecord (reader, type, contentFileMap)
|
||||||
&& !mProjectileManager->readRecord (reader, type)
|
&& !mProjectileManager->readRecord (reader, type)
|
||||||
|
@ -1468,8 +1473,6 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
if(player != results.end())
|
if(player != results.end())
|
||||||
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
|
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
|
||||||
|
|
||||||
mPhysics->debugDraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
|
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
|
||||||
|
@ -1643,6 +1646,8 @@ namespace MWWorld
|
||||||
if (!paused)
|
if (!paused)
|
||||||
doPhysics (duration);
|
doPhysics (duration);
|
||||||
|
|
||||||
|
mPhysics->debugDraw();
|
||||||
|
|
||||||
mWorldScene->update (duration, paused);
|
mWorldScene->update (duration, paused);
|
||||||
|
|
||||||
updateWindowManager ();
|
updateWindowManager ();
|
||||||
|
@ -2200,6 +2205,8 @@ namespace MWWorld
|
||||||
|
|
||||||
scaleObject(getPlayerPtr(), 1.f); // apply race height
|
scaleObject(getPlayerPtr(), 1.f); // apply race height
|
||||||
|
|
||||||
|
rotateObject(getPlayerPtr(), 0.f, 0.f, 0.f, true);
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr());
|
MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr());
|
||||||
MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr());
|
MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr());
|
||||||
|
|
||||||
|
@ -3429,9 +3436,4 @@ namespace MWWorld
|
||||||
return mPhysics->getHitDistance(weaponPos, target) - halfExtents.y();
|
return mPhysics->getHitDistance(weaponPos, target) - halfExtents.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::preloadCommonAssets()
|
|
||||||
{
|
|
||||||
mRendering->preloadCommonAssets();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,8 +191,6 @@ namespace MWWorld
|
||||||
virtual void startNewGame (bool bypass);
|
virtual void startNewGame (bool bypass);
|
||||||
///< \param bypass Bypass regular game start.
|
///< \param bypass Bypass regular game start.
|
||||||
|
|
||||||
virtual void preloadCommonAssets();
|
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const;
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace ESM
|
||||||
esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS);
|
esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS);
|
||||||
}
|
}
|
||||||
if (mDataTypes & Land::DATA_VTEX) {
|
if (mDataTypes & Land::DATA_VTEX) {
|
||||||
static uint16_t vtex[LAND_NUM_TEXTURES];
|
uint16_t vtex[LAND_NUM_TEXTURES];
|
||||||
transposeTextureData(mTextures, vtex);
|
transposeTextureData(mTextures, vtex);
|
||||||
esm.writeHNT("VTEX", vtex, sizeof(vtex));
|
esm.writeHNT("VTEX", vtex, sizeof(vtex));
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ namespace ESM
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.isNextSub("VHGT")) {
|
if (reader.isNextSub("VHGT")) {
|
||||||
static VHGT vhgt;
|
VHGT vhgt;
|
||||||
if (condLoad(reader, flags, DATA_VHGT, &vhgt, sizeof(vhgt))) {
|
if (condLoad(reader, flags, DATA_VHGT, &vhgt, sizeof(vhgt))) {
|
||||||
float rowOffset = vhgt.mHeightOffset;
|
float rowOffset = vhgt.mHeightOffset;
|
||||||
for (int y = 0; y < LAND_SIZE; y++) {
|
for (int y = 0; y < LAND_SIZE; y++) {
|
||||||
|
@ -227,7 +227,7 @@ namespace ESM
|
||||||
if (reader.isNextSub("VCLR"))
|
if (reader.isNextSub("VCLR"))
|
||||||
condLoad(reader, flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS);
|
condLoad(reader, flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS);
|
||||||
if (reader.isNextSub("VTEX")) {
|
if (reader.isNextSub("VTEX")) {
|
||||||
static uint16_t vtex[LAND_NUM_TEXTURES];
|
uint16_t vtex[LAND_NUM_TEXTURES];
|
||||||
if (condLoad(reader, flags, DATA_VTEX, vtex, sizeof(vtex))) {
|
if (condLoad(reader, flags, DATA_VTEX, vtex, sizeof(vtex))) {
|
||||||
LandData::transposeTextureData(vtex, mLandData->mTextures);
|
LandData::transposeTextureData(vtex, mLandData->mTextures);
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,11 +356,23 @@ namespace NifOsg
|
||||||
|
|
||||||
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
|
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, imageManager, std::vector<int>(), 0, 0, false, &textkeys->mTextKeys);
|
osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, imageManager, std::vector<int>(), 0, false, &textkeys->mTextKeys);
|
||||||
|
|
||||||
if (nif->getUseSkinning())
|
if (nif->getUseSkinning())
|
||||||
{
|
{
|
||||||
osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton;
|
osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton;
|
||||||
|
|
||||||
|
osg::Group* root = created->asGroup();
|
||||||
|
if (root && root->getDataVariance() == osg::Object::STATIC)
|
||||||
|
{
|
||||||
|
skel->setStateSet(root->getStateSet());
|
||||||
|
skel->setName(root->getName());
|
||||||
|
for (unsigned int i=0; i<root->getNumChildren(); ++i)
|
||||||
|
skel->addChild(root->getChild(i));
|
||||||
|
root->removeChildren(0, root->getNumChildren());
|
||||||
|
created = skel;
|
||||||
|
}
|
||||||
|
else
|
||||||
skel->addChild(created);
|
skel->addChild(created);
|
||||||
created = skel;
|
created = skel;
|
||||||
}
|
}
|
||||||
|
@ -404,15 +416,6 @@ namespace NifOsg
|
||||||
toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl)));
|
toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupParticleController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int particleflags)
|
|
||||||
{
|
|
||||||
bool autoPlay = particleflags & Nif::NiNode::ParticleFlag_AutoPlay;
|
|
||||||
if (autoPlay)
|
|
||||||
toSetup->setSource(boost::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
|
|
||||||
|
|
||||||
toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void optimize (const Nif::Node* nifNode, osg::Group* node, bool skipMeshes)
|
void optimize (const Nif::Node* nifNode, osg::Group* node, bool skipMeshes)
|
||||||
{
|
{
|
||||||
// For nodes with an identity transform, remove the redundant Transform node
|
// For nodes with an identity transform, remove the redundant Transform node
|
||||||
|
@ -547,7 +550,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
||||||
std::vector<int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
|
std::vector<int> boundTextures, int animflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
|
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
|
||||||
|
|
||||||
|
@ -617,10 +620,8 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nifNode->recType == Nif::RC_NiBSAnimationNode)
|
if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode)
|
||||||
animflags |= nifNode->flags;
|
animflags = nifNode->flags;
|
||||||
if (nifNode->recType == Nif::RC_NiBSParticleNode)
|
|
||||||
particleflags |= nifNode->flags;
|
|
||||||
|
|
||||||
// Hide collision shapes, but don't skip the subgraph
|
// Hide collision shapes, but don't skip the subgraph
|
||||||
// We still need to animate the hidden bones so the physics system can access them
|
// We still need to animate the hidden bones so the physics system can access them
|
||||||
|
@ -663,7 +664,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
handleParticleSystem(nifNode, node, composite, animflags, particleflags, rootNode);
|
handleParticleSystem(nifNode, node, composite, animflags, rootNode);
|
||||||
|
|
||||||
if (composite->getNumControllers() > 0)
|
if (composite->getNumControllers() > 0)
|
||||||
node->addUpdateCallback(composite);
|
node->addUpdateCallback(composite);
|
||||||
|
@ -700,7 +701,7 @@ namespace NifOsg
|
||||||
for(size_t i = 0;i < children.length();++i)
|
for(size_t i = 0;i < children.length();++i)
|
||||||
{
|
{
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode);
|
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, textKeys, rootNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,7 +966,7 @@ namespace NifOsg
|
||||||
return emitter;
|
return emitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags, int particleflags, osg::Node* rootNode)
|
void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags, osg::Node* rootNode)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
|
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
|
||||||
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
||||||
|
@ -986,7 +987,7 @@ namespace NifOsg
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgParticle::ParticleProcessor::ReferenceFrame rf = (particleflags & Nif::NiNode::ParticleFlag_LocalSpace)
|
osgParticle::ParticleProcessor::ReferenceFrame rf = (animflags & Nif::NiNode::ParticleFlag_LocalSpace)
|
||||||
? osgParticle::ParticleProcessor::RELATIVE_RF
|
? osgParticle::ParticleProcessor::RELATIVE_RF
|
||||||
: osgParticle::ParticleProcessor::ABSOLUTE_RF;
|
: osgParticle::ParticleProcessor::ABSOLUTE_RF;
|
||||||
|
|
||||||
|
@ -1032,10 +1033,10 @@ namespace NifOsg
|
||||||
emitterNode->addChild(emitter);
|
emitterNode->addChild(emitter);
|
||||||
|
|
||||||
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
|
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
|
||||||
setupParticleController(partctrl, callback, particleflags);
|
setupController(partctrl, callback, animflags);
|
||||||
emitter->setUpdateCallback(callback);
|
emitter->setUpdateCallback(callback);
|
||||||
|
|
||||||
if (!(particleflags & Nif::NiNode::ParticleFlag_AutoPlay))
|
if (!(animflags & Nif::NiNode::ParticleFlag_AutoPlay))
|
||||||
{
|
{
|
||||||
partsys->setFrozen(true);
|
partsys->setFrozen(true);
|
||||||
// HACK: particle system will not render in Frozen state if there was no update
|
// HACK: particle system will not render in Frozen state if there was no update
|
||||||
|
@ -1438,20 +1439,27 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i];
|
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i];
|
||||||
if(tex.texture.empty())
|
if(tex.texture.empty() && texprop->controller.empty())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl;
|
std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a new texture, will later attempt to share using the SharedStateManager
|
||||||
|
osg::ref_ptr<osg::Texture2D> texture2d;
|
||||||
|
if (!tex.texture.empty())
|
||||||
|
{
|
||||||
const Nif::NiSourceTexture *st = tex.texture.getPtr();
|
const Nif::NiSourceTexture *st = tex.texture.getPtr();
|
||||||
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
|
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
|
||||||
|
texture2d = new osg::Texture2D(image);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
texture2d = new osg::Texture2D;
|
||||||
|
|
||||||
unsigned int clamp = static_cast<unsigned int>(tex.clamp);
|
unsigned int clamp = static_cast<unsigned int>(tex.clamp);
|
||||||
int wrapT = (clamp) & 0x1;
|
int wrapT = (clamp) & 0x1;
|
||||||
int wrapS = (clamp >> 1) & 0x1;
|
int wrapS = (clamp >> 1) & 0x1;
|
||||||
|
|
||||||
// create a new texture, will later attempt to share using the SharedStateManager
|
|
||||||
osg::ref_ptr<osg::Texture2D> texture2d (new osg::Texture2D(image));
|
|
||||||
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
||||||
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "keyframemanager.hpp"
|
#include "keyframemanager.hpp"
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/nifosg/nifloader.hpp>
|
|
||||||
|
|
||||||
#include "objectcache.hpp"
|
#include "objectcache.hpp"
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,9 @@
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "resourcemanager.hpp"
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
|
||||||
namespace NifOsg
|
#include "resourcemanager.hpp"
|
||||||
{
|
|
||||||
class KeyframeHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,20 @@
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class LightStateCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
osg::Light* lastAppliedLight[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
LightStateCache* getLightStateCache(unsigned int contextid)
|
||||||
|
{
|
||||||
|
static std::vector<LightStateCache> cacheVector;
|
||||||
|
if (cacheVector.size() < contextid+1)
|
||||||
|
cacheVector.resize(contextid+1);
|
||||||
|
return &cacheVector[contextid];
|
||||||
|
}
|
||||||
|
|
||||||
// Resets the modelview matrix to just the view matrix before applying lights.
|
// Resets the modelview matrix to just the view matrix before applying lights.
|
||||||
class LightStateAttribute : public osg::StateAttribute
|
class LightStateAttribute : public osg::StateAttribute
|
||||||
{
|
{
|
||||||
|
@ -50,8 +64,17 @@ namespace SceneUtil
|
||||||
|
|
||||||
state.applyModelViewMatrix(state.getInitialViewMatrix());
|
state.applyModelViewMatrix(state.getInitialViewMatrix());
|
||||||
|
|
||||||
|
LightStateCache* cache = getLightStateCache(state.getContextID());
|
||||||
|
|
||||||
for (unsigned int i=0; i<mLights.size(); ++i)
|
for (unsigned int i=0; i<mLights.size(); ++i)
|
||||||
|
{
|
||||||
|
osg::Light* current = cache->lastAppliedLight[i+mIndex];
|
||||||
|
if (current != mLights[i].get())
|
||||||
|
{
|
||||||
applyLight((GLenum)((int)GL_LIGHT0 + i + mIndex), mLights[i].get());
|
applyLight((GLenum)((int)GL_LIGHT0 + i + mIndex), mLights[i].get());
|
||||||
|
cache->lastAppliedLight[i+mIndex] = mLights[i].get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state.applyModelViewMatrix(modelViewMatrix);
|
state.applyModelViewMatrix(modelViewMatrix);
|
||||||
}
|
}
|
||||||
|
@ -262,18 +285,64 @@ namespace SceneUtil
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DisableLight : public osg::StateAttribute
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DisableLight() : mIndex(0) {}
|
||||||
|
DisableLight(int index) : mIndex(index) {}
|
||||||
|
|
||||||
|
DisableLight(const DisableLight& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
|
||||||
|
: osg::StateAttribute(copy,copyop), mIndex(copy.mIndex) {}
|
||||||
|
|
||||||
|
virtual osg::Object* cloneType() const { return new DisableLight(mIndex); }
|
||||||
|
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new DisableLight(*this,copyop); }
|
||||||
|
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const DisableLight *>(obj)!=NULL; }
|
||||||
|
virtual const char* libraryName() const { return "SceneUtil"; }
|
||||||
|
virtual const char* className() const { return "DisableLight"; }
|
||||||
|
virtual Type getType() const { return LIGHT; }
|
||||||
|
|
||||||
|
unsigned int getMember() const
|
||||||
|
{
|
||||||
|
return mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool getModeUsage(ModeUsage & usage) const
|
||||||
|
{
|
||||||
|
usage.usesMode(GL_LIGHT0 + mIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int compare(const StateAttribute &sa) const
|
||||||
|
{
|
||||||
|
throw std::runtime_error("DisableLight::compare: unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::State& state) const
|
||||||
|
{
|
||||||
|
int lightNum = GL_LIGHT0 + mIndex;
|
||||||
|
glLightfv( lightNum, GL_AMBIENT, mNull.ptr() );
|
||||||
|
glLightfv( lightNum, GL_DIFFUSE, mNull.ptr() );
|
||||||
|
glLightfv( lightNum, GL_SPECULAR, mNull.ptr() );
|
||||||
|
|
||||||
|
LightStateCache* cache = getLightStateCache(state.getContextID());
|
||||||
|
cache->lastAppliedLight[mIndex] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int mIndex;
|
||||||
|
osg::Vec4f mNull;
|
||||||
|
};
|
||||||
|
|
||||||
void LightManager::setStartLight(int start)
|
void LightManager::setStartLight(int start)
|
||||||
{
|
{
|
||||||
mStartLight = start;
|
mStartLight = start;
|
||||||
|
|
||||||
// Set default light state to zero
|
// Set default light state to zero
|
||||||
|
// This is necessary because shaders don't respect glDisable(GL_LIGHTX) so in addition to disabling
|
||||||
|
// we'll have to set a light state that has no visible effect
|
||||||
for (int i=start; i<8; ++i)
|
for (int i=start; i<8; ++i)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Light> defaultLight (new osg::Light(i));
|
osg::ref_ptr<DisableLight> defaultLight (new DisableLight(i));
|
||||||
defaultLight->setAmbient(osg::Vec4());
|
|
||||||
defaultLight->setDiffuse(osg::Vec4());
|
|
||||||
defaultLight->setSpecular(osg::Vec4());
|
|
||||||
defaultLight->setConstantAttenuation(0.f);
|
|
||||||
getOrCreateStateSet()->setAttributeAndModes(defaultLight, osg::StateAttribute::OFF);
|
getOrCreateStateSet()->setAttributeAndModes(defaultLight, osg::StateAttribute::OFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +368,7 @@ namespace SceneUtil
|
||||||
mId = sLightId++;
|
mId = sLightId++;
|
||||||
|
|
||||||
for (int i=0; i<2; ++i)
|
for (int i=0; i<2; ++i)
|
||||||
mLight[i] = osg::clone(copy.mLight[i].get(), copyop);
|
mLight[i] = new osg::Light(*copy.mLight[i].get(), copyop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace SceneUtil
|
||||||
void setLight(osg::Light* light)
|
void setLight(osg::Light* light)
|
||||||
{
|
{
|
||||||
mLight[0] = light;
|
mLight[0] = light;
|
||||||
mLight[1] = osg::clone(light);
|
mLight[1] = new osg::Light(*light);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the unique ID for this light source.
|
/// Get the unique ID for this light source.
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace SceneUtil
|
||||||
for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first
|
for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first
|
||||||
// This can be done conveniently in user implementations of the setDefaults() method
|
// This can be done conveniently in user implementations of the setDefaults() method
|
||||||
{
|
{
|
||||||
mStateSets[i] = osg::clone(src, osg::CopyOp::SHALLOW_COPY);
|
mStateSets[i] = new osg::StateSet(*src, osg::CopyOp::SHALLOW_COPY);
|
||||||
setDefaults(mStateSets[i]);
|
setDefaults(mStateSets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace SceneUtil
|
||||||
/// Internal use by the WorkQueue.
|
/// Internal use by the WorkQueue.
|
||||||
void signalDone();
|
void signalDone();
|
||||||
|
|
||||||
|
/// Set abort flag in order to return from doWork() as soon as possible. May not be respected by all WorkItems.
|
||||||
|
virtual void abort() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OpenThreads::Atomic mDone;
|
OpenThreads::Atomic mDone;
|
||||||
OpenThreads::Mutex mMutex;
|
OpenThreads::Mutex mMutex;
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace Shader
|
||||||
if (!node.getStateSet())
|
if (!node.getStateSet())
|
||||||
return node.getOrCreateStateSet();
|
return node.getOrCreateStateSet();
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> newStateSet = osg::clone(node.getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
osg::ref_ptr<osg::StateSet> newStateSet = new osg::StateSet(*node.getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
||||||
node.setStateSet(newStateSet);
|
node.setStateSet(newStateSet);
|
||||||
return newStateSet.get();
|
return newStateSet.get();
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ namespace Shader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAutoUseNormalMaps && diffuseMap != NULL && normalMap == NULL)
|
if (mAutoUseNormalMaps && diffuseMap != NULL && normalMap == NULL && diffuseMap->getImage(0))
|
||||||
{
|
{
|
||||||
std::string normalMapFileName = diffuseMap->getImage(0)->getFileName();
|
std::string normalMapFileName = diffuseMap->getImage(0)->getFileName();
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ namespace Shader
|
||||||
mRequirements.back().mNormalHeight = normalHeight;
|
mRequirements.back().mNormalHeight = normalHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mAutoUseSpecularMaps && diffuseMap != NULL && specularMap == NULL)
|
if (mAutoUseSpecularMaps && diffuseMap != NULL && specularMap == NULL && diffuseMap->getImage(0))
|
||||||
{
|
{
|
||||||
std::string specularMapFileName = diffuseMap->getImage(0)->getFileName();
|
std::string specularMapFileName = diffuseMap->getImage(0)->getFileName();
|
||||||
boost::replace_last(specularMapFileName, ".", mSpecularMapPattern + ".");
|
boost::replace_last(specularMapFileName, ".", mSpecularMapPattern + ".");
|
||||||
|
@ -272,6 +272,9 @@ namespace Shader
|
||||||
{
|
{
|
||||||
switch (reqs.mVertexColorMode)
|
switch (reqs.mVertexColorMode)
|
||||||
{
|
{
|
||||||
|
case GL_AMBIENT:
|
||||||
|
defineMap["colorMode"] = "3";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
case GL_AMBIENT_AND_DIFFUSE:
|
case GL_AMBIENT_AND_DIFFUSE:
|
||||||
defineMap["colorMode"] = "2";
|
defineMap["colorMode"] = "2";
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox">
|
<Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox">
|
||||||
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
||||||
<Property key="NeedMouse" value="false"/>
|
<Property key="NeedMouse" value="false"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="WeapImage">
|
<Widget type="ItemWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="WeapImage">
|
||||||
<Property key="NeedMouse" value="false"/>
|
<Property key="NeedMouse" value="false"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
<!-- Selected spell box -->
|
<!-- Selected spell box -->
|
||||||
<Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox">
|
<Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox">
|
||||||
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="SpellImage"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="SpellImage"/>
|
||||||
<Property key="NeedMouse" value="false"/>
|
<Property key="NeedMouse" value="false"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Magic" position="0 36 36 6" align="Left Bottom" name="SpellStatus">
|
<Widget type="ProgressBar" skin="MW_EnergyBar_Magic" position="0 36 36 6" align="Left Bottom" name="SpellStatus">
|
||||||
|
|
|
@ -128,6 +128,18 @@
|
||||||
</Widget>
|
</Widget>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
|
||||||
|
<Resource type="ResourceLayout" name="MW_ItemIconNoShadow" version="3.2.0">
|
||||||
|
<Widget type="Widget" skin="" position="0 0 42 42" name="Root">
|
||||||
|
<Widget type="ImageBox" skin="ImageBox" position="0 0 42 42" align="Stretch" name="Frame">
|
||||||
|
<Widget type="TextBox" skin="CountText" position="5 19 32 18" align="Right Bottom" name="Text">
|
||||||
|
<Property key="TextAlign" value="Right"/>
|
||||||
|
<Property key="TextShadow" value="true"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Stretch" name="Item"/>
|
||||||
|
</Widget>
|
||||||
|
</Widget>
|
||||||
|
</Resource>
|
||||||
|
|
||||||
<Resource type="ResourceLayout" name="MW_ItemIconSmall" version="3.2.0">
|
<Resource type="ResourceLayout" name="MW_ItemIconSmall" version="3.2.0">
|
||||||
<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">
|
||||||
|
|
|
@ -5,7 +5,10 @@ vec4 doLighting(vec3 viewPos, vec3 viewNormal, vec4 vertexColor)
|
||||||
vec3 lightDir;
|
vec3 lightDir;
|
||||||
float d;
|
float d;
|
||||||
|
|
||||||
#if @colorMode == 2
|
#if @colorMode == 3
|
||||||
|
vec4 diffuse = gl_FrontMaterial.diffuse;
|
||||||
|
vec3 ambient = vertexColor.xyz;
|
||||||
|
#elif @colorMode == 2
|
||||||
vec4 diffuse = vertexColor;
|
vec4 diffuse = vertexColor;
|
||||||
vec3 ambient = vertexColor.xyz;
|
vec3 ambient = vertexColor.xyz;
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in a new issue