From 95cf13e3f2995e573c8c275256106dc1d4449d81 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 15:23:37 +0100 Subject: [PATCH 01/29] Terrain: make the blendmapSize and layerTileSize in FixedFunctionTechnique configurable --- components/terrain/material.cpp | 14 ++++++++------ components/terrain/material.hpp | 6 ++++-- components/terrain/terraingrid.cpp | 4 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index df45b6ec2a..d467a9e167 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -11,7 +11,7 @@ namespace Terrain { FixedFunctionTechnique::FixedFunctionTechnique(const std::vector >& layers, - const std::vector >& blendmaps) + const std::vector >& blendmaps, int blendmapSize, float layerTileSize) { bool firstLayer = true; int i=0; @@ -36,7 +36,7 @@ namespace Terrain // This is to map corner vertices directly to the center of a blendmap texel. osg::Matrixf texMat; - float scale = (16/(16.f+1.f)); + float scale = (blendmapSize/(static_cast(blendmapSize)+1.f)); texMat.preMultTranslate(osg::Vec3f(0.5f, 0.5f, 0.f)); texMat.preMultScale(osg::Vec3f(scale, scale, 1.f)); texMat.preMultTranslate(osg::Vec3f(-0.5f, -0.5f, 0.f)); @@ -57,8 +57,7 @@ namespace Terrain stateset->setTextureAttributeAndModes(texunit, tex.get()); osg::ref_ptr texMat (new osg::TexMat); - float scale = 16.f; - texMat->setMatrix(osg::Matrix::scale(osg::Vec3f(scale,scale,1.f))); + texMat->setMatrix(osg::Matrix::scale(osg::Vec3f(layerTileSize,layerTileSize,1.f))); stateset->setTextureAttributeAndModes(texunit, texMat, osg::StateAttribute::ON); firstLayer = false; @@ -67,9 +66,12 @@ namespace Terrain } } - Effect::Effect(const std::vector > &layers, const std::vector > &blendmaps) + Effect::Effect(const std::vector > &layers, const std::vector > &blendmaps, + int blendmapSize, float layerTileSize) : mLayers(layers) , mBlendmaps(blendmaps) + , mBlendmapSize(blendmapSize) + , mLayerTileSize(layerTileSize) { osg::ref_ptr material (new osg::Material); material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); @@ -80,7 +82,7 @@ namespace Terrain bool Effect::define_techniques() { - addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps)); + addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps, mBlendmapSize, mLayerTileSize)); return true; } diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index b423aa8b0c..1be227b0d7 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -19,7 +19,7 @@ namespace Terrain public: FixedFunctionTechnique( const std::vector >& layers, - const std::vector >& blendmaps); + const std::vector >& blendmaps, int blendmapSize, float layerTileSize); protected: virtual void define_passes() {} @@ -30,7 +30,7 @@ namespace Terrain public: Effect( const std::vector >& layers, - const std::vector >& blendmaps); + const std::vector >& blendmaps, int blendmapSize, float layerTileSize); virtual bool define_techniques(); @@ -50,6 +50,8 @@ namespace Terrain private: std::vector > mLayers; std::vector > mBlendmaps; + int mBlendmapSize; + float mLayerTileSize; }; } diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 5afb991768..7c23955662 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -150,7 +152,7 @@ void TerrainGrid::loadCell(int x, int y) for (unsigned int i=0; i<2; ++i) geometry->setTexCoordArray(i, mCache.getUVBuffer()); - osg::ref_ptr effect (new Terrain::Effect(layerTextures, blendmapTextures)); + osg::ref_ptr effect (new Terrain::Effect(layerTextures, blendmapTextures, ESM::Land::LAND_TEXTURE_SIZE, ESM::Land::LAND_TEXTURE_SIZE)); effect->addCullCallback(new SceneUtil::LightListCallback); From ef18f4217f1aca7830f39f241d355b353a4602ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 20:14:57 +0100 Subject: [PATCH 02/29] Terrain: create 4x4 terrain chunks per ESM::Cell to improve performance Improves performance because the number of splatting layers per chunk is reduced, and finer grained frustum culling can be done. --- components/esmterrain/storage.cpp | 80 ++++++++---- components/terrain/buffercache.cpp | 3 + components/terrain/material.cpp | 10 +- components/terrain/material.hpp | 6 +- components/terrain/terraingrid.cpp | 203 ++++++++++++++++++----------- components/terrain/terraingrid.hpp | 7 + 6 files changed, 199 insertions(+), 110 deletions(-) diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index ccfe6d9ee5..e954bfec8a 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -1,6 +1,7 @@ #include "storage.hpp" #include +#include #include #include @@ -34,19 +35,22 @@ namespace ESMTerrain osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f); - assert(origin.x() == (int) origin.x()); - assert(origin.y() == (int) origin.y()); + int cellX = static_cast(std::floor(origin.x())); + int cellY = static_cast(std::floor(origin.y())); - int cellX = static_cast(origin.x()); - int cellY = static_cast(origin.y()); + int startRow = (origin.x() - cellX) * ESM::Land::LAND_SIZE; + int startColumn = (origin.y() - cellY) * ESM::Land::LAND_SIZE; + + int endRow = startRow + size * (ESM::Land::LAND_SIZE-1) + 1; + int endColumn = startColumn + size * (ESM::Land::LAND_SIZE-1) + 1; if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VHGT)) { min = std::numeric_limits::max(); max = -std::numeric_limits::max(); - for (int row=0; rowmHeights[col*ESM::Land::LAND_SIZE+row]; if (h > max) @@ -143,11 +147,9 @@ namespace ESMTerrain size_t increment = 1 << lodLevel; osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f); - assert(origin.x() == (int) origin.x()); - assert(origin.y() == (int) origin.y()); - int startX = static_cast(origin.x()); - int startY = static_cast(origin.y()); + int startCellX = static_cast(std::floor(origin.x())); + int startCellY = static_cast(std::floor(origin.y())); size_t numVerts = static_cast(size*(ESM::Land::LAND_SIZE - 1) / increment + 1); @@ -162,10 +164,10 @@ namespace ESMTerrain float vertX = 0; float vertY_ = 0; // of current cell corner - for (int cellY = startY; cellY < startY + std::ceil(size); ++cellY) + for (int cellY = startCellY; cellY < startCellY + std::ceil(size); ++cellY) { float vertX_ = 0; // of current cell corner - for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX) + for (int cellX = startCellX; cellX < startCellX + std::ceil(size); ++cellX) { const ESM::Land::LandData *heightData = getLandData (cellX, cellY, ESM::Land::DATA_VHGT); const ESM::Land::LandData *normalData = getLandData (cellX, cellY, ESM::Land::DATA_VNML); @@ -175,18 +177,31 @@ namespace ESMTerrain int colStart = 0; // Skip the first row / column unless we're at a chunk edge, // since this row / column is already contained in a previous cell + // This is only relevant if we're creating a chunk spanning multiple cells if (colStart == 0 && vertY_ != 0) colStart += increment; if (rowStart == 0 && vertX_ != 0) rowStart += increment; + // Only relevant for chunks smaller than (contained in) one cell + rowStart += (origin.x() - startCellX) * ESM::Land::LAND_SIZE; + colStart += (origin.y() - startCellY) * ESM::Land::LAND_SIZE; + int rowEnd = rowStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE-1) + 1; + int colEnd = colStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE-1) + 1; + vertY = vertY_; - for (int col=colStart; col= 0 && row < ESM::Land::LAND_SIZE); + assert(col >= 0 && col < ESM::Land::LAND_SIZE); + + assert (vertX < numVerts); + assert (vertY < numVerts); float height = -2048; if (heightData) @@ -200,7 +215,7 @@ namespace ESMTerrain if (normalData) { for (int i=0; i<3; ++i) - normal[i] = normalData->mNormals[arrayIndex+i]; + normal[i] = normalData->mNormals[srcArrayIndex+i]; normal.normalize(); } @@ -222,7 +237,7 @@ namespace ESMTerrain if (colourData) { for (int i=0; i<3; ++i) - color[i] = colourData->mColours[arrayIndex+i] / 255.f; + color[i] = colourData->mColours[srcArrayIndex+i] / 255.f; } else { @@ -305,8 +320,19 @@ namespace ESMTerrain // and interpolate the rest of the cell by hand? :/ osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize/2.f, chunkSize/2.f); - int cellX = static_cast(origin.x()); - int cellY = static_cast(origin.y()); + int cellX = static_cast(std::floor(origin.x())); + int cellY = static_cast(std::floor(origin.y())); + + int realTextureSize = ESM::Land::LAND_TEXTURE_SIZE+1; // add 1 to wrap around next cell + + int rowStart = (origin.x() - cellX) * realTextureSize; + int colStart = (origin.y() - cellY) * realTextureSize; + int rowEnd = rowStart + chunkSize * (realTextureSize-1) + 1; + int colEnd = colStart + chunkSize * (realTextureSize-1) + 1; + + assert (rowStart >= 0 && colStart >= 0); + assert (rowEnd <= realTextureSize); + assert (colEnd <= realTextureSize); // Save the used texture indices so we know the total number of textures // and number of required blend maps @@ -317,8 +343,15 @@ namespace ESMTerrain // So we're always adding _land_default.dds as the base layer here, even if it's not referenced in this cell. textureIndices.insert(std::make_pair(0,0)); - for (int y=0; ysecond; int blendIndex = (pack ? static_cast(std::floor((layerIndex - 1) / 4.f)) : layerIndex - 1); int channel = pack ? std::max(0, (layerIndex-1) % 4) : 0; diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp index a64f8ffd1d..c6cf0fe33c 100644 --- a/components/terrain/buffercache.cpp +++ b/components/terrain/buffercache.cpp @@ -1,6 +1,7 @@ #include "buffercache.hpp" #include +#include #include @@ -208,6 +209,8 @@ namespace Terrain { unsigned int verts = mNumVerts; + std::cout << "getting index buffer for " << verts << std::endl; + if (mIndexBufferMap.find(flags) != mIndexBufferMap.end()) { return mIndexBufferMap[flags]; diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index d467a9e167..59d06f2542 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -11,7 +11,7 @@ namespace Terrain { FixedFunctionTechnique::FixedFunctionTechnique(const std::vector >& layers, - const std::vector >& blendmaps, int blendmapSize, float layerTileSize) + const std::vector >& blendmaps, int blendmapScale, float layerTileSize) { bool firstLayer = true; int i=0; @@ -36,7 +36,7 @@ namespace Terrain // This is to map corner vertices directly to the center of a blendmap texel. osg::Matrixf texMat; - float scale = (blendmapSize/(static_cast(blendmapSize)+1.f)); + float scale = (blendmapScale/(static_cast(blendmapScale)+1.f)); texMat.preMultTranslate(osg::Vec3f(0.5f, 0.5f, 0.f)); texMat.preMultScale(osg::Vec3f(scale, scale, 1.f)); texMat.preMultTranslate(osg::Vec3f(-0.5f, -0.5f, 0.f)); @@ -67,10 +67,10 @@ namespace Terrain } Effect::Effect(const std::vector > &layers, const std::vector > &blendmaps, - int blendmapSize, float layerTileSize) + int blendmapScale, float layerTileSize) : mLayers(layers) , mBlendmaps(blendmaps) - , mBlendmapSize(blendmapSize) + , mBlendmapScale(blendmapScale) , mLayerTileSize(layerTileSize) { osg::ref_ptr material (new osg::Material); @@ -82,7 +82,7 @@ namespace Terrain bool Effect::define_techniques() { - addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps, mBlendmapSize, mLayerTileSize)); + addTechnique(new FixedFunctionTechnique(mLayers, mBlendmaps, mBlendmapScale, mLayerTileSize)); return true; } diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index 1be227b0d7..dd00e41ed4 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -19,7 +19,7 @@ namespace Terrain public: FixedFunctionTechnique( const std::vector >& layers, - const std::vector >& blendmaps, int blendmapSize, float layerTileSize); + const std::vector >& blendmaps, int blendmapScale, float layerTileSize); protected: virtual void define_passes() {} @@ -30,7 +30,7 @@ namespace Terrain public: Effect( const std::vector >& layers, - const std::vector >& blendmaps, int blendmapSize, float layerTileSize); + const std::vector >& blendmaps, int blendmapScale, float layerTileSize); virtual bool define_techniques(); @@ -50,7 +50,7 @@ namespace Terrain private: std::vector > mLayers; std::vector > mBlendmaps; - int mBlendmapSize; + int mBlendmapScale; float mLayerTileSize; }; diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 7c23955662..6414fa9517 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -1,6 +1,8 @@ #include "terraingrid.hpp" #include +#include +#include #include #include @@ -47,8 +49,10 @@ namespace Terrain TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, Storage* storage, int nodeMask) : Terrain::World(parent, resourceSystem, ico, storage, nodeMask) + , mNumSplits(4) , mKdTreeBuilder(new osg::KdTreeBuilder) { + mCache = BufferCache((storage->getCellVertices()-1)/static_cast(mNumSplits) + 1); } TerrainGrid::~TerrainGrid() @@ -62,108 +66,149 @@ TerrainGrid::~TerrainGrid() class GridElement { public: - osg::ref_ptr mNode; + osg::ref_ptr mNode; }; +osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter) +{ + if (chunkSize * mNumSplits > 1.f) + { + // keep splitting + osg::ref_ptr group (new osg::Group); + if (parent) + parent->addChild(group); + std::cout << "splitting " << chunkSize << " " << std::endl; + float newChunkSize = chunkSize/2.f; + buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, newChunkSize/2.f)); + buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, -newChunkSize/2.f)); + buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, newChunkSize/2.f)); + buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, -newChunkSize/2.f)); + return group; + } + else + { + float minH, maxH; + if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH)) + return NULL; // no terrain defined + + std::cout << "creating " << chunkSize << " " << chunkCenter << std::endl; + + osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); + osg::ref_ptr transform (new osg::PositionAttitudeTransform); + transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); + + if (parent) + parent->addChild(transform); + + osg::ref_ptr positions (new osg::Vec3Array); + osg::ref_ptr normals (new osg::Vec3Array); + osg::ref_ptr colors (new osg::Vec4Array); + + osg::ref_ptr vbo (new osg::VertexBufferObject); + positions->setVertexBufferObject(vbo); + normals->setVertexBufferObject(vbo); + colors->setVertexBufferObject(vbo); + + mStorage->fillVertexBuffers(0, chunkSize, chunkCenter, positions, normals, colors); + + osg::ref_ptr geometry (new osg::Geometry); + geometry->setVertexArray(positions); + geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); + geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); + geometry->setUseDisplayList(false); + geometry->setUseVertexBufferObjects(true); + + geometry->addPrimitiveSet(mCache.getIndexBuffer(0)); + + // we already know the bounding box, so no need to let OSG compute it. + osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize, + -0.5f*mStorage->getCellWorldSize()*chunkSize, + minH); + osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize, + 0.5f*mStorage->getCellWorldSize()*chunkSize, + maxH); + osg::BoundingBox bounds(min, max); + geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds)); + + osg::ref_ptr geode (new osg::Geode); + geode->addDrawable(geometry); + + + std::vector layerList; + std::vector > blendmaps; + mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList); + + // For compiling textures, I don't think the osgFX::Effect does it correctly + osg::ref_ptr textureCompileDummy (new osg::Node); + + std::vector > layerTextures; + for (std::vector::const_iterator it = layerList.begin(); it != layerList.end(); ++it) + { + layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT)); + textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); + } + + std::vector > blendmapTextures; + for (std::vector >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it) + { + osg::ref_ptr texture (new osg::Texture2D); + texture->setImage(*it); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + texture->setResizeNonPowerOfTwoHint(false); + blendmapTextures.push_back(texture); + + textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); + } + + // use texture coordinates for both texture units, the layer texture and blend texture + for (unsigned int i=0; i<2; ++i) + geometry->setTexCoordArray(i, mCache.getUVBuffer()); + + float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize; + osg::ref_ptr effect (new Terrain::Effect(layerTextures, blendmapTextures, blendmapScale, blendmapScale)); + + effect->addCullCallback(new SceneUtil::LightListCallback); + + transform->addChild(effect); + effect->addChild(geode); + + return transform; + } +} + void TerrainGrid::loadCell(int x, int y) { if (mGrid.find(std::make_pair(x, y)) != mGrid.end()) return; // already loaded osg::Vec2f center(x+0.5f, y+0.5f); - float minH, maxH; - if (!mStorage->getMinMaxHeights(1, center, minH, maxH)) + + osg::ref_ptr terrainNode = buildTerrain(NULL, 1.f, center); + if (!terrainNode) return; // no terrain defined std::auto_ptr element (new GridElement); - - osg::Vec2f worldCenter = center*mStorage->getCellWorldSize(); - element->mNode = new osg::PositionAttitudeTransform; - element->mNode->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); + element->mNode = terrainNode; mTerrainRoot->addChild(element->mNode); - osg::ref_ptr positions (new osg::Vec3Array); - osg::ref_ptr normals (new osg::Vec3Array); - osg::ref_ptr colors (new osg::Vec4Array); - - osg::ref_ptr vbo (new osg::VertexBufferObject); - positions->setVertexBufferObject(vbo); - normals->setVertexBufferObject(vbo); - colors->setVertexBufferObject(vbo); - - mStorage->fillVertexBuffers(0, 1, center, positions, normals, colors); - - osg::ref_ptr geometry (new osg::Geometry); - geometry->setVertexArray(positions); - geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); - geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); - geometry->setUseDisplayList(false); - geometry->setUseVertexBufferObjects(true); - - geometry->addPrimitiveSet(mCache.getIndexBuffer(0)); - - // we already know the bounding box, so no need to let OSG compute it. - osg::Vec3f min(-0.5f*mStorage->getCellWorldSize(), - -0.5f*mStorage->getCellWorldSize(), - minH); - osg::Vec3f max (0.5f*mStorage->getCellWorldSize(), - 0.5f*mStorage->getCellWorldSize(), - maxH); - osg::BoundingBox bounds(min, max); - geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds)); - - osg::ref_ptr geode (new osg::Geode); - geode->addDrawable(geometry); - + /* // build a kdtree to speed up intersection tests with the terrain // Note, the build could be optimized using a custom kdtree builder, since we know that the terrain can be represented by a quadtree geode->accept(*mKdTreeBuilder); + */ - std::vector layerList; - std::vector > blendmaps; - mStorage->getBlendmaps(1.f, center, false, blendmaps, layerList); - - // For compiling textures, I don't think the osgFX::Effect does it correctly - osg::ref_ptr textureCompileDummy (new osg::Node); - - std::vector > layerTextures; - for (std::vector::const_iterator it = layerList.begin(); it != layerList.end(); ++it) - { - layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT)); - textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); - } - - std::vector > blendmapTextures; - for (std::vector >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it) - { - osg::ref_ptr texture (new osg::Texture2D); - texture->setImage(*it); - texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - texture->setResizeNonPowerOfTwoHint(false); - blendmapTextures.push_back(texture); - - textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); - } - - // use texture coordinates for both texture units, the layer texture and blend texture - for (unsigned int i=0; i<2; ++i) - geometry->setTexCoordArray(i, mCache.getUVBuffer()); - - osg::ref_ptr effect (new Terrain::Effect(layerTextures, blendmapTextures, ESM::Land::LAND_TEXTURE_SIZE, ESM::Land::LAND_TEXTURE_SIZE)); - - effect->addCullCallback(new SceneUtil::LightListCallback); - - effect->addChild(geode); - element->mNode->addChild(effect); + /* if (mIncrementalCompileOperation) { mIncrementalCompileOperation->add(geode); mIncrementalCompileOperation->add(textureCompileDummy); } + */ + mGrid[std::make_pair(x,y)] = element.release(); } diff --git a/components/terrain/terraingrid.hpp b/components/terrain/terraingrid.hpp index 832b952e89..169a9a6228 100644 --- a/components/terrain/terraingrid.hpp +++ b/components/terrain/terraingrid.hpp @@ -1,6 +1,8 @@ #ifndef COMPONENTS_TERRAIN_TERRAINGRID_H #define COMPONENTS_TERRAIN_TERRAINGRID_H +#include + #include "world.hpp" #include "material.hpp" @@ -26,6 +28,11 @@ namespace Terrain virtual void unloadCell(int x, int y); private: + osg::ref_ptr buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter); + + // split each ESM::Cell into mNumSplits*mNumSplits terrain chunks + unsigned int mNumSplits; + typedef std::map, GridElement*> Grid; Grid mGrid; From 7ca8e45d5ddbb2cfbf28716aa297e928cde08889 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 20:21:39 +0100 Subject: [PATCH 03/29] Terrain: remove debug code --- components/esmterrain/storage.cpp | 8 -------- components/terrain/buffercache.cpp | 3 --- components/terrain/terraingrid.cpp | 7 ++----- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index e954bfec8a..c36e3efe0c 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -1,7 +1,6 @@ #include "storage.hpp" #include -#include #include #include @@ -343,13 +342,6 @@ namespace ESMTerrain // So we're always adding _land_default.dds as the base layer here, even if it's not referenced in this cell. textureIndices.insert(std::make_pair(0,0)); - /* - _________ - | | | | - | | | | - - | | | | - | | | | - - - */ - for (int y=colStart; y -#include #include @@ -209,8 +208,6 @@ namespace Terrain { unsigned int verts = mNumVerts; - std::cout << "getting index buffer for " << verts << std::endl; - if (mIndexBufferMap.find(flags) != mIndexBufferMap.end()) { return mIndexBufferMap[flags]; diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 6414fa9517..99525d0f48 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -1,8 +1,6 @@ #include "terraingrid.hpp" #include -#include -#include #include #include @@ -77,7 +75,7 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu osg::ref_ptr group (new osg::Group); if (parent) parent->addChild(group); - std::cout << "splitting " << chunkSize << " " << std::endl; + float newChunkSize = chunkSize/2.f; buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, -newChunkSize/2.f)); @@ -91,8 +89,6 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH)) return NULL; // no terrain defined - std::cout << "creating " << chunkSize << " " << chunkCenter << std::endl; - osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); osg::ref_ptr transform (new osg::PositionAttitudeTransform); transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); @@ -194,6 +190,7 @@ void TerrainGrid::loadCell(int x, int y) element->mNode = terrainNode; mTerrainRoot->addChild(element->mNode); + // kdtree probably not needed with mNumSplits=4 /* // build a kdtree to speed up intersection tests with the terrain // Note, the build could be optimized using a custom kdtree builder, since we know that the terrain can be represented by a quadtree From 72252d4f32e200f21c076688322854b477ca9bb8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 20:22:07 +0100 Subject: [PATCH 04/29] Terrain: restore IncrementalCompileOperation --- components/terrain/terraingrid.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 99525d0f48..732936aa99 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -171,6 +171,12 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu transform->addChild(effect); effect->addChild(geode); + if (mIncrementalCompileOperation) + { + mIncrementalCompileOperation->add(geode); + mIncrementalCompileOperation->add(textureCompileDummy); + } + return transform; } } @@ -197,16 +203,6 @@ void TerrainGrid::loadCell(int x, int y) geode->accept(*mKdTreeBuilder); */ - - /* - if (mIncrementalCompileOperation) - { - mIncrementalCompileOperation->add(geode); - mIncrementalCompileOperation->add(textureCompileDummy); - } - */ - - mGrid[std::make_pair(x,y)] = element.release(); } From 0210b87ffc0fc33bddaf2449ad1d1c042cc51553 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 22:35:12 +0100 Subject: [PATCH 05/29] Revert "Fix LightSource crash" This reverts commit f336c6db87be04903c0a92ab0c749bfe290bb5f0. Root cause should be fixed in next commit. --- components/sceneutil/lightmanager.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index b652562aa8..e62dc00e58 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -76,7 +76,7 @@ namespace SceneUtil struct LightSourceTransform { - osg::ref_ptr mLightSource; + LightSource* mLightSource; osg::Matrix mWorldMatrix; }; @@ -84,7 +84,7 @@ namespace SceneUtil struct LightSourceViewBound { - osg::ref_ptr mLightSource; + LightSource* mLightSource; osg::BoundingSphere mViewBound; }; From 6e698081294377acab61a29be0056d8ac491e2c3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 22:41:32 +0100 Subject: [PATCH 06/29] Fix the frameNumber not being incremented in certain frames --- apps/openmw/mwgui/loadingscreen.cpp | 8 +++++++- apps/openmw/mwgui/windowmanagerimp.cpp | 16 ++++++++++++++-- apps/openmw/mwrender/renderingmanager.cpp | 10 +++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 9afce68735..321d5e6645 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -282,7 +282,13 @@ namespace MWGui MWBase::Environment::get().getInputManager()->update(0, true, true); //osg::Timer timer; - mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); + // at the time this function is called we are in the middle of a frame, + // so out of order calls are necessary to get a correct frameNumber for the next frame. + // refer to the advance() and frame() order in Engine::go() + mViewer->eventTraversal(); + mViewer->updateTraversal(); + mViewer->renderingTraversals(); + mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); //std::cout << "frame took " << timer.time_m() << std::endl; //if (mViewer->getIncrementalCompileOperation()) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 90a5f74817..e1e838cdf9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -859,7 +859,13 @@ namespace MWGui mMessageBoxManager->onFrame(0.f); MWBase::Environment::get().getInputManager()->update(0, true, false); - mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); + // at the time this function is called we are in the middle of a frame, + // so out of order calls are necessary to get a correct frameNumber for the next frame. + // refer to the advance() and frame() order in Engine::go() + mViewer->eventTraversal(); + mViewer->updateTraversal(); + mViewer->renderingTraversals(); + mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); } } } @@ -1756,7 +1762,13 @@ namespace MWGui { MWBase::Environment::get().getInputManager()->update(0, true, false); - mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); + // at the time this function is called we are in the middle of a frame, + // so out of order calls are necessary to get a correct frameNumber for the next frame. + // refer to the advance() and frame() order in Engine::go() + mViewer->eventTraversal(); + mViewer->updateTraversal(); + mViewer->renderingTraversals(); + mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); } mVideoWidget->stop(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7b11c9d859..7848cdd3cb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -521,10 +521,18 @@ namespace MWRender osg::ref_ptr callback (new NotifyDrawCompletedCallback); rttCamera->setFinalDrawCallback(callback); - mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); + // at the time this function is called we are in the middle of a frame, + // so out of order calls are necessary to get a correct frameNumber for the next frame. + // refer to the advance() and frame() order in Engine::go() + mViewer->eventTraversal(); + mViewer->updateTraversal(); + mViewer->renderingTraversals(); callback->waitTillDone(); + // now that we've "used up" the current frame, get a fresh framenumber for the next frame() following after the screenshot is completed + mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); + rttCamera->removeChildren(0, rttCamera->getNumChildren()); rttCamera->setGraphicsContext(NULL); mRootNode->removeChild(rttCamera); From 2407f393cee9a3a7634337777c8ce902a9186923 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 23:13:57 +0100 Subject: [PATCH 07/29] Fix double update traversal in screenshot function --- apps/openmw/mwrender/renderingmanager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7848cdd3cb..45c04ceecd 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -489,6 +489,15 @@ namespace MWRender mutable bool mDone; }; + + class NoTraverseCallback : public osg::NodeCallback + { + public: + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + } + }; + void RenderingManager::screenshot(osg::Image *image, int w, int h) { osg::ref_ptr rttCamera (new osg::Camera); @@ -512,6 +521,7 @@ namespace MWRender image->setDataType(GL_UNSIGNED_BYTE); image->setPixelFormat(texture->getInternalFormat()); + rttCamera->setUpdateCallback(new NoTraverseCallback); rttCamera->addChild(mLightRoot); rttCamera->setCullMask(mViewer->getCamera()->getCullMask() & (~Mask_GUI)); From 4cc200680c071541f484d36897eab61171d57182 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Nov 2015 23:59:06 +0100 Subject: [PATCH 08/29] Comment out shadows tab in settings menu --- files/mygui/openmw_settings_window.layout | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index e76c3a7dbc..5f2a6e5a06 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -392,7 +392,11 @@ + + + From a41ebd6695096f71b2c5a54983e222d2aec8eb16 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 00:02:15 +0100 Subject: [PATCH 09/29] Comment out object shaders in the settings menu --- files/mygui/openmw_settings_window.layout | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 5f2a6e5a06..cb74636560 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -262,6 +262,8 @@ + + From 47664e13707c5ed2a4f0b3282dc4cb67dfc7392a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 00:10:49 +0100 Subject: [PATCH 10/29] Hide the defunct FPS checkbox in settings menu, added hint text for f3 binding --- files/mygui/openmw_settings_window.layout | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index cb74636560..1d02ea19ae 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -256,6 +256,8 @@ + + @@ -273,6 +275,12 @@ + + + + + + From 13c7235b6b49b8ec76a1034e2876992adbccdffc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 00:13:13 +0100 Subject: [PATCH 11/29] Remove old FPS setting code --- apps/mwiniimporter/importer.cpp | 1 - apps/openmw/engine.cpp | 3 --- apps/openmw/mwbase/windowmanager.hpp | 2 -- apps/openmw/mwgui/hud.cpp | 28 +---------------------- apps/openmw/mwgui/hud.hpp | 8 +------ apps/openmw/mwgui/settingswindow.cpp | 12 ---------- apps/openmw/mwgui/settingswindow.hpp | 2 -- apps/openmw/mwgui/windowmanagerimp.cpp | 11 +-------- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ---- files/mygui/openmw_hud.layout | 6 ----- files/mygui/openmw_settings_window.layout | 8 ------- files/mygui/openmw_text.skin.xml | 9 -------- files/settings-default.cfg | 5 ---- 13 files changed, 3 insertions(+), 96 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 479f8cba28..251889e281 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -20,7 +20,6 @@ MwIniImporter::MwIniImporter() { const char *map[][2] = { - { "fps", "General:Show FPS" }, { "no-sound", "General:Disable Audio" }, { 0, 0 } }; diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 089880fb26..5d2d588ed3 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -168,9 +168,6 @@ void OMW::Engine::frame(float frametime) if (mEnvironment.getStateManager()->getState()!= MWBase::StateManager::State_NoGame) { -#if 0 - mEnvironment.getWindowManager()->wmUpdateFps(fps); -#endif mEnvironment.getWindowManager()->update(); } diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index fb7eca4a35..f364ada7ac 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -155,8 +155,6 @@ namespace MWBase virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0; - virtual void wmUpdateFps(float fps) = 0; - /// Set value for the given ID. virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0; virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a93bb47e9d..3922b1997c 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -67,7 +67,7 @@ namespace MWGui }; - HUD::HUD(CustomMarkerCollection &customMarkers, bool showFps, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender) + HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender) : Layout("openmw_hud.layout") , LocalMapBase(customMarkers, localMapRender) , mHealth(NULL) @@ -85,8 +85,6 @@ namespace MWGui , mCellNameBox(NULL) , mDrowningFrame(NULL) , mDrowningFlash(NULL) - , mFpsBox(NULL) - , mFpsCounter(NULL) , mHealthManaStaminaBaseLeft(0) , mWeapBoxBaseLeft(0) , mSpellBoxBaseLeft(0) @@ -161,8 +159,6 @@ namespace MWGui getWidget(mCrosshair, "Crosshair"); - setFpsVisible(showFps); - LocalMapBase::init(mMinimap, mCompass, Settings::Manager::getInt("local map hud widget size", "Map")); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); @@ -181,28 +177,6 @@ namespace MWGui delete mSpellIcons; } - void HUD::setFpsVisible(const bool visible) - { - mFpsCounter = 0; - - MyGUI::Widget* fps; - getWidget(fps, "FPSBox"); - fps->setVisible(false); - - if (visible) - { - getWidget(mFpsBox, "FPSBox"); - //mFpsBox->setVisible(true); - getWidget(mFpsCounter, "FPSCounter"); - } - } - - void HUD::setFPS(float fps) - { - if (mFpsCounter) - mFpsCounter->setCaption(MyGUI::utility::toString((int)fps)); - } - void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& value) { int current = std::max(0, static_cast(value.getCurrent())); diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 629613c982..c5ae457891 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -19,10 +19,9 @@ namespace MWGui class HUD : public Layout, public LocalMapBase { public: - HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender); + HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender); virtual ~HUD(); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setFPS(float fps); /// Set time left for the player to start drowning /// @param time time left to start drowning @@ -38,8 +37,6 @@ namespace MWGui void setEffectVisible(bool visible); void setMinimapVisible(bool visible); - void setFpsVisible(const bool visible); - void setSelectedSpell(const std::string& spellId, int successChancePercent); void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); @@ -77,9 +74,6 @@ namespace MWGui MyGUI::TextBox* mWeaponSpellBox; MyGUI::Widget *mDrowningFrame, *mDrowningFlash; - MyGUI::Widget* mFpsBox; - MyGUI::TextBox* mFpsCounter; - // bottom left elements int mHealthManaStaminaBaseLeft, mWeapBoxBaseLeft, mSpellBoxBaseLeft, mSneakBoxBaseLeft; // bottom right elements diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 667dc0c285..eb2f235299 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -166,7 +166,6 @@ namespace MWGui getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); getWidget(mWindowBorderButton, "WindowBorderButton"); - getWidget(mFPSButton, "FPSButton"); getWidget(mFOVSlider, "FOVSlider"); getWidget(mAnisotropySlider, "AnisotropySlider"); getWidget(mTextureFilteringButton, "TextureFilteringButton"); @@ -201,7 +200,6 @@ namespace MWGui mSettingsTab->eventTabChangeSelect += MyGUI::newDelegate(this, &SettingsWindow::onTabChanged); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); - mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged); @@ -256,8 +254,6 @@ namespace MWGui mShadowsEnabledButton->setEnabled(false); } - mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); - MyGUI::TextBox* fovText; getWidget(fovText, "FovText"); fovText->setCaption("Field of View (" + MyGUI::utility::toString(int(Settings::Manager::getInt("field of view", "General"))) + ")"); @@ -427,14 +423,6 @@ namespace MWGui } } - void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) - { - int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 2; - Settings::Manager::setInt("fps", "HUD", newLevel); - mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel)); - apply(); - } - void SettingsWindow::onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos) { Settings::Manager::setString("texture filtering", "General", Misc::StringUtils::lowerCase(_sender->getItemNameAt(pos))); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 0369eb40ec..99553808b4 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -30,7 +30,6 @@ namespace MWGui MyGUI::Button* mFullscreenButton; MyGUI::Button* mVSyncButton; MyGUI::Button* mWindowBorderButton; - MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mFOVSlider; MyGUI::ScrollBar* mDifficultySlider; MyGUI::ScrollBar* mAnisotropySlider; @@ -53,7 +52,6 @@ namespace MWGui void onTabChanged(MyGUI::TabControl* _sender, size_t index); void onOkButtonClicked(MyGUI::Widget* _sender); - void onFpsToggled(MyGUI::Widget* _sender); void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e1e838cdf9..e2404c58a1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -185,7 +185,6 @@ namespace MWGui , mForceHidden(GW_None) , mAllowed(GW_ALL) , mRestAllowed(true) - , mFPS(0.0f) , mFallbackMap(fallbackMap) , mShowOwned(0) , mVersionDescription(versionDescription) @@ -296,7 +295,7 @@ namespace MWGui trackWindow(mDialogueWindow, "dialogue"); mContainerWindow = new ContainerWindow(mDragAndDrop); trackWindow(mContainerWindow, "container"); - mHud = new HUD(mCustomMarkers, Settings::Manager::getInt("fps", "HUD"), mDragAndDrop, mLocalMapRender); + mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender); mToolTips = new ToolTips(); mScrollWindow = new ScrollWindow(); mBookWindow = new BookWindow(); @@ -464,8 +463,6 @@ namespace MWGui { cleanupGarbage(); - mHud->setFPS(mFPS); - mHud->update(); } @@ -1138,7 +1135,6 @@ namespace MWGui void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { - mHud->setFpsVisible(static_cast(Settings::Manager::getInt("fps", "HUD"))); mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); for (Settings::CategorySettingVector::const_iterator it = changed.begin(); @@ -1322,11 +1318,6 @@ namespace MWGui mConsole->executeFile (path); } - void WindowManager::wmUpdateFps(float fps) - { - mFPS = fps; - } - MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; } MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a1f76683e5..7df5508a16 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -180,8 +180,6 @@ namespace MWGui virtual void setConsoleSelectedObject(const MWWorld::Ptr& object); - virtual void wmUpdateFps(float fps); - ///< Set value for the given ID. virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value); virtual void setValue (int parSkill, const MWMechanics::SkillValue& value); @@ -486,8 +484,6 @@ namespace MWGui void updateMap(); - float mFPS; - std::map mFallbackMap; int mShowOwned; diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index 97b0184696..03c05260f3 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -125,11 +125,5 @@ - - - - - - diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 1d02ea19ae..22d36de2b6 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -255,14 +255,6 @@ - - - - - - - - diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index e459f22fab..b7a893580f 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -18,15 +18,6 @@ color_misc=0,205,205 # ???? - - - - - - - - - diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 7c809b9266..d68bc2fef7 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -84,11 +84,6 @@ fade start = 0.8 debug = false [HUD] -# FPS counter -# 0: not visible -# 1: FPS display -fps = 0 - crosshair = true [Objects] From 7ff168b787f33169456db82c3127b2c6f832cdbe Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 17:21:03 +0100 Subject: [PATCH 12/29] osgMyGUI: add support for layers to insert custom rendering state --- .../myguiplatform/myguirendermanager.cpp | 46 ++++++++++++++++--- .../myguiplatform/myguirendermanager.hpp | 6 +++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index 160d659bd6..5bd56dc8f4 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -45,6 +45,9 @@ namespace osgMyGUI class Drawable : public osg::Drawable { osgMyGUI::RenderManager *mParent; + osg::ref_ptr mStateSet; + +public: // Stage 0: update widget animations and controllers. Run during the Update traversal. class FrameUpdate : public osg::Drawable::UpdateCallback @@ -101,6 +104,10 @@ class Drawable : public osg::Drawable { virtual void drawImplementation(osg::RenderInfo &renderInfo) const { osg::State *state = renderInfo.getState(); + + state->pushStateSet(mStateSet); + state->apply(); + state->disableAllVertexArrays(); state->setClientActiveTextureUnit(0); glEnableClientState(GL_VERTEX_ARRAY); @@ -113,6 +120,13 @@ class Drawable : public osg::Drawable { { const Batch& batch = *it; osg::VertexBufferObject *vbo = batch.mVertexBuffer; + + if (batch.mStateSet) + { + state->pushStateSet(batch.mStateSet); + state->apply(); + } + osg::Texture2D* texture = batch.mTexture; if(texture) state->applyTextureAttribute(0, texture); @@ -135,12 +149,20 @@ class Drawable : public osg::Drawable { } glDrawArrays(GL_TRIANGLES, 0, batch.mVertexCount); + + if (batch.mStateSet) + { + state->popStateSet(); + state->apply(); + } } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + state->popStateSet(); + state->unbindVertexBufferObject(); state->dirtyAllVertexArrays(); state->disableAllVertexArrays(); @@ -161,10 +183,17 @@ public: osg::ref_ptr frameUpdate = new FrameUpdate; frameUpdate->setRenderManager(mParent); setUpdateCallback(frameUpdate); + + mStateSet = new osg::StateSet; + mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + mStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + mStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON); } Drawable(const Drawable ©, const osg::CopyOp ©op=osg::CopyOp::SHALLOW_COPY) : osg::Drawable(copy, copyop) , mParent(copy.mParent) + , mStateSet(copy.mStateSet) , mWriteTo(0) , mReadFrom(0) { @@ -180,6 +209,9 @@ public: // need to hold on to this too as the mVertexBuffer does not hold a ref to its own array osg::ref_ptr mArray; + // optional + osg::ref_ptr mStateSet; + size_t mVertexCount; }; @@ -321,6 +353,7 @@ RenderManager::RenderManager(osgViewer::Viewer *viewer, osg::Group *sceneroot, R , mUpdate(false) , mIsInitialise(false) , mInvScalingFactor(1.f) + , mInjectState(NULL) { if (scalingFactor != 0.f) mInvScalingFactor = 1.f / scalingFactor; @@ -364,12 +397,6 @@ void RenderManager::initialise() camera->setViewMatrix(osg::Matrix::identity()); camera->setRenderOrder(osg::Camera::POST_RENDER); camera->setClearMask(GL_NONE); - osg::StateSet *state = new osg::StateSet; - state->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); - state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); - state->setMode(GL_BLEND, osg::StateAttribute::ON); - state->setAttribute(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - geode->setStateSet(state); geode->setCullingActive(false); camera->addChild(geode.get()); @@ -418,10 +445,17 @@ void RenderManager::doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *text if (batch.mTexture->getDataVariance() == osg::Object::DYNAMIC) mDrawable->setDataVariance(osg::Object::DYNAMIC); // only for this frame, reset in begin() } + if (mInjectState) + batch.mStateSet = mInjectState; mDrawable->addBatch(batch); } +void RenderManager::setInjectState(osg::StateSet* stateSet) +{ + mInjectState = stateSet; +} + void RenderManager::end() { } diff --git a/components/myguiplatform/myguirendermanager.hpp b/components/myguiplatform/myguirendermanager.hpp index d9fdc1834a..f2251cdb04 100644 --- a/components/myguiplatform/myguirendermanager.hpp +++ b/components/myguiplatform/myguirendermanager.hpp @@ -20,6 +20,7 @@ namespace osg class Group; class Camera; class RenderInfo; + class StateSet; } namespace osgMyGUI @@ -48,6 +49,8 @@ class RenderManager : public MyGUI::RenderManager, public MyGUI::IRenderTarget float mInvScalingFactor; + osg::StateSet* mInjectState; + void destroyAllResources(); public: @@ -95,6 +98,9 @@ public: /** @see IRenderTarget::doRender */ virtual void doRender(MyGUI::IVertexBuffer *buffer, MyGUI::ITexture *texture, size_t count); + /** specify a StateSet to inject for rendering. The StateSet will be used by future doRender calls until you reset it to NULL again. */ + void setInjectState(osg::StateSet* stateSet); + /** @see IRenderTarget::getInfo */ virtual const MyGUI::RenderTargetInfo& getInfo() { return mInfo; } From 51f3a8fec66ce990d6cef41ed5b8490355a9791c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 17:39:31 +0100 Subject: [PATCH 13/29] osgMyGUI: move Platform methods to the .cpp file --- apps/openmw/mwgui/windowmanagerimp.cpp | 1 + components/CMakeLists.txt | 2 +- components/myguiplatform/myguiplatform.cpp | 62 +++++++++++++++++ components/myguiplatform/myguiplatform.hpp | 79 ++++++++-------------- 4 files changed, 91 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e2404c58a1..6f2e7755d6 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -33,6 +33,7 @@ #include #include +#include #include diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 00eac6ca52..1460dee7b5 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -115,7 +115,7 @@ add_component_dir (loadinglistener ) add_component_dir (myguiplatform - myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener + myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer ) add_component_dir (widgets diff --git a/components/myguiplatform/myguiplatform.cpp b/components/myguiplatform/myguiplatform.cpp index 01d6ca567f..22b88438f6 100644 --- a/components/myguiplatform/myguiplatform.cpp +++ b/components/myguiplatform/myguiplatform.cpp @@ -1,2 +1,64 @@ #include "myguiplatform.hpp" +#include "myguirendermanager.hpp" +#include "myguidatamanager.hpp" +#include "myguiloglistener.hpp" + +namespace osgMyGUI +{ + +Platform::Platform(osgViewer::Viewer *viewer, osg::Group *guiRoot, Resource::TextureManager *textureManager, float uiScalingFactor) + : mRenderManager(nullptr) + , mDataManager(nullptr) + , mLogManager(nullptr) + , mLogFacility(nullptr) +{ + mLogManager = new MyGUI::LogManager(); + mRenderManager = new RenderManager(viewer, guiRoot, textureManager, uiScalingFactor); + mDataManager = new DataManager(); +} + +Platform::~Platform() +{ + delete mRenderManager; + mRenderManager = nullptr; + delete mDataManager; + mDataManager = nullptr; + delete mLogManager; + mLogManager = nullptr; + delete mLogFacility; + mLogFacility = nullptr; +} + +void Platform::initialise(const std::string &resourcePath, const std::string &_logName) +{ + if (!_logName.empty() && !mLogFacility) + { + mLogFacility = new LogFacility(_logName, false); + mLogManager->addLogSource(mLogFacility->getSource()); + } + + mDataManager->setResourcePath(resourcePath); + + mRenderManager->initialise(); + mDataManager->initialise(); +} + +void Platform::shutdown() +{ + mRenderManager->shutdown(); + mDataManager->shutdown(); +} + +RenderManager *Platform::getRenderManagerPtr() +{ + return mRenderManager; +} + +DataManager *Platform::getDataManagerPtr() +{ + return mDataManager; +} + + +} diff --git a/components/myguiplatform/myguiplatform.hpp b/components/myguiplatform/myguiplatform.hpp index 513267c991..56562e12a6 100644 --- a/components/myguiplatform/myguiplatform.hpp +++ b/components/myguiplatform/myguiplatform.hpp @@ -1,71 +1,46 @@ #ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_MYGUIPLATFORM_H #define OPENMW_COMPONENTS_MYGUIPLATFORM_MYGUIPLATFORM_H -#include "MyGUI_Prerequest.h" -#include "MyGUI_LogManager.h" +#include -#include "myguirendermanager.hpp" -#include "myguidatamanager.hpp" -#include "myguiloglistener.hpp" +namespace osgViewer +{ + class Viewer; +} +namespace osg +{ + class Group; +} +namespace Resource +{ + class TextureManager; +} +namespace MyGUI +{ + class LogManager; +} namespace osgMyGUI { + class RenderManager; + class DataManager; + class LogFacility; + class Platform { public: - Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::TextureManager* textureManager, float uiScalingFactor) - : mRenderManager(nullptr) - , mDataManager(nullptr) - , mLogManager(nullptr) - , mLogFacility(nullptr) - { - mLogManager = new MyGUI::LogManager(); - mRenderManager = new RenderManager(viewer, guiRoot, textureManager, uiScalingFactor); - mDataManager = new DataManager(); - } + Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::TextureManager* textureManager, float uiScalingFactor); - ~Platform() - { - delete mRenderManager; - mRenderManager = nullptr; - delete mDataManager; - mDataManager = nullptr; - delete mLogManager; - mLogManager = nullptr; - delete mLogFacility; - mLogFacility = nullptr; - } + ~Platform(); - void initialise(const std::string& resourcePath, const std::string& _logName = "MyGUI.log") - { - if (!_logName.empty() && !mLogFacility) - { - mLogFacility = new LogFacility(_logName, false); - mLogManager->addLogSource(mLogFacility->getSource()); - } + void initialise(const std::string& resourcePath, const std::string& _logName = "MyGUI.log"); - mDataManager->setResourcePath(resourcePath); + void shutdown(); - mRenderManager->initialise(); - mDataManager->initialise(); - } + RenderManager* getRenderManagerPtr(); - void shutdown() - { - mRenderManager->shutdown(); - mDataManager->shutdown(); - } - - RenderManager* getRenderManagerPtr() - { - return mRenderManager; - } - - DataManager* getDataManagerPtr() - { - return mDataManager; - } + DataManager* getDataManagerPtr(); private: RenderManager* mRenderManager; From 57b9eafa0fd2d4d073a3fee9176f24b4cd98de52 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 17:45:22 +0100 Subject: [PATCH 14/29] osgMyGUI: implement AdditiveLayer --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 ++ components/myguiplatform/additivelayer.cpp | 33 ++++++++++++++++++++++ components/myguiplatform/additivelayer.hpp | 33 ++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 components/myguiplatform/additivelayer.cpp create mode 100644 components/myguiplatform/additivelayer.hpp diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 6f2e7755d6..fdf26d9499 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -34,6 +34,7 @@ #include #include +#include #include @@ -216,6 +217,7 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Layer"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); ItemWidget::registerComponents(); diff --git a/components/myguiplatform/additivelayer.cpp b/components/myguiplatform/additivelayer.cpp new file mode 100644 index 0000000000..aa2ef08b3b --- /dev/null +++ b/components/myguiplatform/additivelayer.cpp @@ -0,0 +1,33 @@ +#include "additivelayer.hpp" + +#include +#include + +#include "myguirendermanager.hpp" + +namespace osgMyGUI +{ + + AdditiveLayer::AdditiveLayer() + { + mStateSet = new osg::StateSet; + mStateSet->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE)); + } + + AdditiveLayer::~AdditiveLayer() + { + // defined in .cpp file since we can't delete incomplete types + } + + void AdditiveLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update) + { + RenderManager& renderManager = static_cast(MyGUI::RenderManager::getInstance()); + + renderManager.setInjectState(mStateSet.get()); + + MyGUI::OverlappedLayer::renderToTarget(_target, _update); + + renderManager.setInjectState(NULL); + } + +} diff --git a/components/myguiplatform/additivelayer.hpp b/components/myguiplatform/additivelayer.hpp new file mode 100644 index 0000000000..f3d47bc826 --- /dev/null +++ b/components/myguiplatform/additivelayer.hpp @@ -0,0 +1,33 @@ +#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_ADDITIVELAYER +#define OPENMW_COMPONENTS_MYGUIPLATFORM_ADDITIVELAYER + +#include + +#include + +namespace osg +{ + class StateSet; +} + +namespace osgMyGUI +{ + + /// @brief A Layer rendering with additive blend mode. + class AdditiveLayer : public MyGUI::OverlappedLayer + { + public: + MYGUI_RTTI_DERIVED( AdditiveLayer ) + + AdditiveLayer(); + ~AdditiveLayer(); + + virtual void renderToTarget(MyGUI::IRenderTarget* _target, bool _update); + + private: + osg::ref_ptr mStateSet; + }; + +} + +#endif From a90ef8afd0aacf576467513cc9ec4e64732e2b40 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 17:48:36 +0100 Subject: [PATCH 15/29] layer renaming --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- files/mygui/openmw_layers.xml | 4 ++-- files/mygui/openmw_screen_fader.layout | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index fdf26d9499..3fe786ab22 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -334,7 +334,7 @@ namespace MWGui mDebugWindow = new DebugWindow(); - mInputBlocker = MyGUI::Gui::getInstance().createWidget("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); + mInputBlocker = MyGUI::Gui::getInstance().createWidget("",0,0,w,h,MyGUI::Align::Stretch,"InputBlocker"); mHud->setVisible(mHudEnabled); diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index cf577aec52..7b2955bbd4 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -1,7 +1,7 @@ - + @@ -12,6 +12,6 @@ - + diff --git a/files/mygui/openmw_screen_fader.layout b/files/mygui/openmw_screen_fader.layout index 13234792f7..e9009d32a6 100644 --- a/files/mygui/openmw_screen_fader.layout +++ b/files/mygui/openmw_screen_fader.layout @@ -1,7 +1,7 @@ - + From d85d74e615818ba2abf71dd668b0581c077a1575 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 18:04:03 +0100 Subject: [PATCH 16/29] Use AdditiveLayer for the hit fader --- apps/openmw/mwgui/screenfader.cpp | 4 ++-- apps/openmw/mwgui/screenfader.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_layers.xml | 1 + files/mygui/openmw_screen_fader_hit.layout | 7 +++++++ 6 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 files/mygui/openmw_screen_fader_hit.layout diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index 473776a82a..c44bcc3f1f 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -66,8 +66,8 @@ namespace MWGui mFader->notifyOperationFinished(); } - ScreenFader::ScreenFader(const std::string & texturePath) - : WindowBase("openmw_screen_fader.layout") + ScreenFader::ScreenFader(const std::string & texturePath, const std::string& layout) + : WindowBase(layout) , mCurrentAlpha(0.f) , mFactor(1.f) , mRepeat(false) diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index 402554555e..d25f5fdc4e 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -36,7 +36,7 @@ namespace MWGui class ScreenFader : public WindowBase { public: - ScreenFader(const std::string & texturePath); + ScreenFader(const std::string & texturePath, const std::string& layout = "openmw_screen_fader.layout"); void setTexture(const std::string & texturePath); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 3fe786ab22..bf65377f6d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -329,7 +329,7 @@ namespace MWGui // TODO: check if non-BM versions actually use player_hit_01.dds if(!mResourceSystem->getVFS()->exists(hitFaderTexture)) hitFaderTexture = "textures\\player_hit_01.dds"; - mHitFader = new ScreenFader(hitFaderTexture); + mHitFader = new ScreenFader(hitFaderTexture, "openmw_screen_fader_hit.layout"); mScreenFader = new ScreenFader("black"); mDebugWindow = new DebugWindow(); diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index dc9e8ea848..7494d3ba2d 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -80,6 +80,7 @@ set(MYGUI_FILES openmw_savegame_dialog.layout openmw_recharge_dialog.layout openmw_screen_fader.layout + openmw_screen_fader_hit.layout openmw_edit_note.layout openmw_debug_window.layout openmw_debug_window.skin.xml diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 7b2955bbd4..c8684c858f 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -2,6 +2,7 @@ + diff --git a/files/mygui/openmw_screen_fader_hit.layout b/files/mygui/openmw_screen_fader_hit.layout new file mode 100644 index 0000000000..7e60f0ff5a --- /dev/null +++ b/files/mygui/openmw_screen_fader_hit.layout @@ -0,0 +1,7 @@ + + + + + + + From 6c12c9a467cfeb0b4e640e9f48b95bfaec1bf3b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Nov 2015 19:45:30 +0100 Subject: [PATCH 17/29] Layer renaming fix --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index bf65377f6d..58e33623d0 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -248,7 +248,7 @@ namespace MWGui MyGUI::PointerManager::getInstance().setVisible(false); mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, - MyGUI::Align::Default, "Overlay"); + MyGUI::Align::Default, "InputBlocker"); mVideoBackground->setImageTexture("black"); mVideoBackground->setVisible(false); mVideoBackground->setNeedMouseFocus(true); From 231570f0916386c56fe7134106e56baf25d7cd9a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 01:21:59 +0100 Subject: [PATCH 18/29] travis.yml fix --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22f6164c2f..0910ac5462 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,8 @@ script: - cd ./build - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi - - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi + - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi + - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi notifications: recipients: - corrmage+travis-ci@gmail.com From 08a55febc874abb44216303110ea4dcc1db6525c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 17:52:39 +0100 Subject: [PATCH 19/29] Adjust Scroll window layout to better match MW --- files/mygui/openmw_scroll.layout | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_scroll.layout b/files/mygui/openmw_scroll.layout index 194700f36e..e4ad23bba6 100644 --- a/files/mygui/openmw_scroll.layout +++ b/files/mygui/openmw_scroll.layout @@ -2,24 +2,24 @@ - + - + - + - + From 59aee04ddb33b50e4a02a6f4a296126a7bdf1d4f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:21:25 +0100 Subject: [PATCH 20/29] Implement ScalingLayer, for layouting of widgets in screen-relative coordinates --- components/CMakeLists.txt | 2 +- components/myguiplatform/scalinglayer.cpp | 138 ++++++++++++++++++++++ components/myguiplatform/scalinglayer.hpp | 31 +++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 components/myguiplatform/scalinglayer.cpp create mode 100644 components/myguiplatform/scalinglayer.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 1460dee7b5..f8f4c64ab0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -115,7 +115,7 @@ add_component_dir (loadinglistener ) add_component_dir (myguiplatform - myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer + myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer ) add_component_dir (widgets diff --git a/components/myguiplatform/scalinglayer.cpp b/components/myguiplatform/scalinglayer.cpp new file mode 100644 index 0000000000..7f7cac69b9 --- /dev/null +++ b/components/myguiplatform/scalinglayer.cpp @@ -0,0 +1,138 @@ +#include "scalinglayer.hpp" + +#include + +namespace osgMyGUI +{ + + /// @brief the ProxyRenderTarget allows to adjust the pixel scale and offset for a "source" render target. + class ProxyRenderTarget : public MyGUI::IRenderTarget + { + public: + /// @param target The target to render to. + /// @param viewSize The size of the underlying layer node to render. + /// @param hoffset The horizontal rendering offset, specified as an offset from the left screen edge in range 0-1. + /// @param voffset The vertical rendering offset, specified as an offset from the top screen edge in range 0-1. + ProxyRenderTarget(MyGUI::IRenderTarget* target, MyGUI::IntSize viewSize, float hoffset, float voffset) + : mTarget(target) + , mViewSize(viewSize) + , mHOffset(hoffset) + , mVOffset(voffset) + { + } + + virtual void begin() + { + mTarget->begin(); + } + + virtual void end() + { + mTarget->end(); + } + + virtual void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count) + { + mTarget->doRender(_buffer, _texture, _count); + } + + virtual const MyGUI::RenderTargetInfo& getInfo() + { + mInfo = mTarget->getInfo(); + mInfo.hOffset = mHOffset; + mInfo.vOffset = mVOffset; + mInfo.pixScaleX = 1.f / mViewSize.width; + mInfo.pixScaleY = 1.f / mViewSize.height; + return mInfo; + } + + private: + MyGUI::IRenderTarget* mTarget; + MyGUI::IntSize mViewSize; + float mHOffset, mVOffset; + MyGUI::RenderTargetInfo mInfo; + }; + + MyGUI::ILayerItem *ScalingLayer::getLayerItemByPoint(int _left, int _top) const + { + screenToLayerCoords(_left, _top); + + return OverlappedLayer::getLayerItemByPoint(_left, _top); + } + + void ScalingLayer::screenToLayerCoords(int& _left, int& _top) const + { + float scale = getScaleFactor(); + if (scale <= 0.f) + return; + + MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize(); + + _left -= globalViewSize.width/2; + _top -= globalViewSize.height/2; + + _left /= scale; + _top /= scale; + + _left += mViewSize.width/2; + _top += mViewSize.height/2; + } + + float ScalingLayer::getScaleFactor() const + { + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + float w = viewSize.width; + float h = viewSize.height; + + float heightScale = (h / mViewSize.height); + float widthScale = (w / mViewSize.width); + return std::min(widthScale, heightScale); + } + + MyGUI::IntPoint ScalingLayer::getPosition(int _left, int _top) const + { + screenToLayerCoords(_left, _top); + return MyGUI::IntPoint(_left, _top); + } + + void ScalingLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update) + { + MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntSize viewSize = globalViewSize; + viewSize.width /= getScaleFactor(); + viewSize.height /= getScaleFactor(); + + float hoffset = (globalViewSize.width - mViewSize.width*getScaleFactor())/2.f / static_cast(globalViewSize.width); + float voffset = (globalViewSize.height - mViewSize.height*getScaleFactor())/2.f / static_cast(globalViewSize.height); + + ProxyRenderTarget proxy(_target, viewSize, hoffset, voffset); + + MyGUI::OverlappedLayer::renderToTarget(&proxy, _update); + } + + void ScalingLayer::resizeView(const MyGUI::IntSize &_viewSize) + { + // do nothing + } + + void ScalingLayer::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) + { + MyGUI::OverlappedLayer::deserialization(_node, _version); + + MyGUI::xml::ElementEnumerator info = _node->getElementEnumerator(); + while (info.next()) + { + if (info->getName() == "Property") + { + const std::string& key = info->findAttribute("key"); + const std::string& value = info->findAttribute("value"); + + if (key == "Size") + { + mViewSize = MyGUI::IntSize::parse(value); + } + } + } + } + +} diff --git a/components/myguiplatform/scalinglayer.hpp b/components/myguiplatform/scalinglayer.hpp new file mode 100644 index 0000000000..3ee1489f19 --- /dev/null +++ b/components/myguiplatform/scalinglayer.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER +#define OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER + +#include + +namespace osgMyGUI +{ + + ///@brief A Layer that lays out and renders widgets in screen-relative coordinates. The "Size" property determines the size of the virtual screen, + /// which is then upscaled to the real screen size during rendering. The aspect ratio is kept intact, adding blanks to the sides when necessary. + class ScalingLayer : public MyGUI::OverlappedLayer + { + public: + MYGUI_RTTI_DERIVED(ScalingLayer) + + virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version); + + virtual MyGUI::ILayerItem* getLayerItemByPoint(int _left, int _top) const; + virtual MyGUI::IntPoint getPosition(int _left, int _top) const; + virtual void renderToTarget(MyGUI::IRenderTarget* _target, bool _update); + + virtual void resizeView(const MyGUI::IntSize& _viewSize); + + private: + void screenToLayerCoords(int& _left, int& _top) const; + float getScaleFactor() const; + }; + +} + +#endif From f9932130dabc201067d32cca69b8b5b4e49b2c95 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:23:02 +0100 Subject: [PATCH 21/29] Work around MyGUI bug with mouse event coordinates (fixed in git) --- apps/openmw/mwgui/bookpage.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index cfb49ebffb..9878051f7a 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -949,12 +949,18 @@ public: if (!mBook) return; - left -= mCroppedParent->getAbsoluteLeft (); - top -= mCroppedParent->getAbsoluteTop (); + // work around inconsistency in MyGUI where the mouse press coordinates aren't + // transformed by the current Layer (even though mouse *move* events are). + MyGUI::IntPoint pos (left, top); +#if MYGUI_VERSION < MYGUI_DEFINE_VERSION(3,2,3) + pos = mNode->getLayer()->getPosition(left, top); +#endif + pos.left -= mCroppedParent->getAbsoluteLeft (); + pos.top -= mCroppedParent->getAbsoluteTop (); if (mLastDown == MyGUI::MouseButton::None) { - mFocusItem = mBook->hitTest (left, mViewTop + top); + mFocusItem = mBook->hitTest (pos.left, mViewTop + pos.top); mItemActive = true; dirtyFocusItem (); @@ -968,12 +974,19 @@ public: if (!mBook) return; - left -= mCroppedParent->getAbsoluteLeft (); - top -= mCroppedParent->getAbsoluteTop (); + // work around inconsistency in MyGUI where the mouse release coordinates aren't + // transformed by the current Layer (even though mouse *move* events are). + MyGUI::IntPoint pos (left, top); +#if MYGUI_VERSION < MYGUI_DEFINE_VERSION(3,2,3) + pos = mNode->getLayer()->getPosition(left, top); +#endif + + pos.left -= mCroppedParent->getAbsoluteLeft (); + pos.top -= mCroppedParent->getAbsoluteTop (); if (mLastDown == id) { - Style * mItem = mBook->hitTest (left, mViewTop + top); + Style * mItem = mBook->hitTest (pos.left, mViewTop + pos.top); bool clicked = mFocusItem == mItem; From a7ad45e73e32131716bbdf871231fe43aa8abe0b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:23:47 +0100 Subject: [PATCH 22/29] WindowBase::center use the layer size instead of render window size --- apps/openmw/mwgui/windowbase.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index 191e8223d8..c9d1b06175 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -49,11 +49,13 @@ void WindowBase::center() { // Centre dialog - MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntSize layerSize = MyGUI::RenderManager::getInstance().getViewSize(); + if (mMainWidget->getLayer()) + layerSize = mMainWidget->getLayer()->getSize(); MyGUI::IntCoord coord = mMainWidget->getCoord(); - coord.left = (gameWindowSize.width - coord.width)/2; - coord.top = (gameWindowSize.height - coord.height)/2; + coord.left = (layerSize.width - coord.width)/2; + coord.top = (layerSize.height - coord.height)/2; mMainWidget->setCoord(coord); } From 516f2765a15c7c80fcc8784f953c1d5e2842bbd6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:24:28 +0100 Subject: [PATCH 23/29] Use the ScalingLayer for journal, books and scrolls --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 ++ files/mygui/openmw_book.layout | 2 +- files/mygui/openmw_journal.layout | 2 +- files/mygui/openmw_layers.xml | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 58e33623d0..a7c3a19576 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -218,6 +219,7 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Layer"); + MyGUI::FactoryManager::getInstance().registerFactory("Layer"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); ItemWidget::registerComponents(); diff --git a/files/mygui/openmw_book.layout b/files/mygui/openmw_book.layout index 2336d5b2ca..7c158af8dc 100644 --- a/files/mygui/openmw_book.layout +++ b/files/mygui/openmw_book.layout @@ -2,7 +2,7 @@ - + diff --git a/files/mygui/openmw_journal.layout b/files/mygui/openmw_journal.layout index 5524f55202..9c40bd5623 100644 --- a/files/mygui/openmw_journal.layout +++ b/files/mygui/openmw_journal.layout @@ -2,7 +2,7 @@ - + diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index c8684c858f..c6d3df5210 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -6,6 +6,9 @@ + + + From 79b3f1e6a823ff5fbf9784adb4db9f991d477ec5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:27:01 +0100 Subject: [PATCH 24/29] Small cleanup --- components/myguiplatform/scalinglayer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/myguiplatform/scalinglayer.cpp b/components/myguiplatform/scalinglayer.cpp index 7f7cac69b9..19ae108410 100644 --- a/components/myguiplatform/scalinglayer.cpp +++ b/components/myguiplatform/scalinglayer.cpp @@ -99,8 +99,9 @@ namespace osgMyGUI { MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize viewSize = globalViewSize; - viewSize.width /= getScaleFactor(); - viewSize.height /= getScaleFactor(); + float scale = getScaleFactor(); + viewSize.width /= scale; + viewSize.height /= scale; float hoffset = (globalViewSize.width - mViewSize.width*getScaleFactor())/2.f / static_cast(globalViewSize.width); float voffset = (globalViewSize.height - mViewSize.height*getScaleFactor())/2.f / static_cast(globalViewSize.height); From 75f11f781c85acc3d6efa077403e1fb12db710d3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 18:32:41 +0100 Subject: [PATCH 25/29] Use the ScalingLayer for Scroll window --- files/mygui/openmw_scroll.layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/mygui/openmw_scroll.layout b/files/mygui/openmw_scroll.layout index e4ad23bba6..b2e62f28d8 100644 --- a/files/mygui/openmw_scroll.layout +++ b/files/mygui/openmw_scroll.layout @@ -2,7 +2,7 @@ - + From 66925be44073dbd45d1c107823eb6c2c1633edea Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 19:59:33 +0100 Subject: [PATCH 26/29] Partially revert 682f30ef9c7e8edad3e825be6920670ffac3bdce This change made dead netch fall through the floor, because the animation moves the creature *below* its external collision box. --- apps/openmw/mwphysics/physicssystem.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 92994d5574..739b0013b8 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -240,8 +240,6 @@ namespace MWPhysics const ESM::Position& refpos = ptr.getRefData().getPosition(); osg::Vec3f position(refpos.asVec3()); - float collisionShapeOffset = physicActor->getPosition().z() - position.z(); - // Early-out for totally static creatures // (Not sure if gravity should still apply?) if (!ptr.getClass().isMobile(ptr)) @@ -258,11 +256,17 @@ namespace MWPhysics } btCollisionObject *colobj = physicActor->getCollisionObject(); - position.z() += collisionShapeOffset; + osg::Vec3f halfExtents = physicActor->getHalfExtents(); + + // NOTE: here we don't account for the collision box translation (i.e. physicActor->getPosition() - refpos.pos). + // That means the collision shape used for moving this actor is in a different spot than the collision shape + // other actors are using to collide against this actor. + // While this is strictly speaking wrong, it's needed for MW compatibility. + position.z() += halfExtents.z(); static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get() .find("fSwimHeightScale")->getFloat(); - float swimlevel = waterlevel + collisionShapeOffset - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale); + float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale); ActorTracer tracer; osg::Vec3f inertia = physicActor->getInertialForce(); @@ -370,7 +374,7 @@ namespace MWPhysics { // don't let pure water creatures move out of water after stepMove if (ptr.getClass().isPureWaterCreature(ptr) - && newPosition.z() + physicActor->getHalfExtents().z() > waterlevel) + && newPosition.z() + halfExtents.z() > waterlevel) newPosition = oldPosition; } else @@ -451,7 +455,7 @@ namespace MWPhysics } physicActor->setOnGround(isOnGround); - newPosition.z() -= collisionShapeOffset; // remove what was added at the beginning + newPosition.z() -= halfExtents.z(); // remove what was added at the beginning return newPosition; } }; From f0a1434578506727f86c935f72c0be2d3f986044 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Nov 2015 20:58:00 +0100 Subject: [PATCH 27/29] Dead actors underwater will float to the surface --- apps/openmw/mwphysics/physicssystem.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 739b0013b8..55144afe75 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -288,6 +288,11 @@ namespace MWPhysics velocity = velocity + physicActor->getInertialForce(); } } + + // dead actors underwater will float to the surface + if (ptr.getClass().getCreatureStats(ptr).isDead() && position.z() < swimlevel) + velocity = osg::Vec3f(0,0,1) * 25; + ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0; // Now that we have the effective movement vector, apply wind forces to it From 055841e721734b043f1f80be6f3653547332239a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 9 Nov 2015 02:22:40 +0100 Subject: [PATCH 28/29] Improve cloud lighting --- apps/openmw/mwrender/sky.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 12708ba481..5c38d79d4d 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1563,17 +1563,15 @@ void SkyManager::setWeather(const WeatherResult& weather) mCloudMesh2->setNodeMask(mCloudBlendFactor > 0.f ? ~0 : 0); } - if (mCloudColour != weather.mSunColor) + if (mCloudColour != weather.mFogColor) { - // FIXME: this doesn't look correct - osg::Vec4f clr( weather.mSunColor.r()*0.7f + weather.mAmbientColor.r()*0.7f, - weather.mSunColor.g()*0.7f + weather.mAmbientColor.g()*0.7f, - weather.mSunColor.b()*0.7f + weather.mAmbientColor.b()*0.7f, 1.f); + osg::Vec4f clr (weather.mFogColor); + clr += osg::Vec4f(0.13f, 0.13f, 0.13f, 0.f); mCloudUpdater->setEmissionColor(clr); mCloudUpdater2->setEmissionColor(clr); - mCloudColour = weather.mSunColor; + mCloudColour = weather.mFogColor; } if (mSkyColour != weather.mSkyColor) From b89945804c829443beac2de8c80730c2a2dbb7a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 9 Nov 2015 02:57:49 +0100 Subject: [PATCH 29/29] BookPage: implement hit test with margin for error --- apps/openmw/mwgui/bookpage.cpp | 46 +++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 9878051f7a..b728b748f7 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -153,6 +153,34 @@ struct TypesetBookImpl : TypesetBook visitRuns (top, bottom, NULL, visitor); } + /// hit test with a margin for error. only hits on interactive text fragments are reported. + StyleImpl * hitTestWithMargin (int left, int top) + { + StyleImpl * hit = hitTest(left, top); + if (hit && hit->mInteractiveId > 0) + return hit; + + const int maxMargin = 10; + for (int margin=1; margin < maxMargin; ++margin) + { + for (int i=0; i<4; ++i) + { + if (i==0) + hit = hitTest(left, top-margin); + else if (i==1) + hit = hitTest(left, top+margin); + else if (i==2) + hit = hitTest(left-margin, top); + else + hit = hitTest(left+margin, top); + + if (hit && hit->mInteractiveId > 0) + return hit; + } + } + return NULL; + } + StyleImpl * hitTest (int left, int top) const { for (Sections::const_iterator i = mSections.begin (); i != mSections.end (); ++i) @@ -916,15 +944,15 @@ public: left -= mCroppedParent->getAbsoluteLeft (); top -= mCroppedParent->getAbsoluteTop (); - Style * Hit = mBook->hitTest (left, mViewTop + top); + Style * hit = mBook->hitTestWithMargin (left, mViewTop + top); if (mLastDown == MyGUI::MouseButton::None) { - if (Hit != mFocusItem) + if (hit != mFocusItem) { dirtyFocusItem (); - mFocusItem = Hit; + mFocusItem = hit; mItemActive = false; dirtyFocusItem (); @@ -933,7 +961,7 @@ public: else if (mFocusItem != 0) { - bool newItemActive = Hit == mFocusItem; + bool newItemActive = hit == mFocusItem; if (newItemActive != mItemActive) { @@ -960,7 +988,7 @@ public: if (mLastDown == MyGUI::MouseButton::None) { - mFocusItem = mBook->hitTest (pos.left, mViewTop + pos.top); + mFocusItem = mBook->hitTestWithMargin (pos.left, mViewTop + pos.top); mItemActive = true; dirtyFocusItem (); @@ -986,9 +1014,9 @@ public: if (mLastDown == id) { - Style * mItem = mBook->hitTest (pos.left, mViewTop + pos.top); + Style * item = mBook->hitTestWithMargin (pos.left, mViewTop + pos.top); - bool clicked = mFocusItem == mItem; + bool clicked = mFocusItem == item; mItemActive = false; @@ -996,8 +1024,8 @@ public: mLastDown = MyGUI::MouseButton::None; - if (clicked && mLinkClicked && mItem && mItem->mInteractiveId != 0) - mLinkClicked (mItem->mInteractiveId); + if (clicked && mLinkClicked && item && item->mInteractiveId != 0) + mLinkClicked (item->mInteractiveId); } }