Merged pull request #1421

pull/456/head
Marc Zinnschlag 7 years ago
commit 5a9e382efe

@ -30,6 +30,7 @@
Bug #4451: Script fails to compile when using "Begin, [ScriptName]" syntax
Bug #4453: Quick keys behaviour is invalid for equipment
Bug #4454: AI opens doors too slow
Feature #4256: Implement ToggleBorders (TB) console command
Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results
Feature #4222: 360° screenshots
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts

@ -120,6 +120,7 @@ namespace MWBase
virtual bool toggleWater() = 0;
virtual bool toggleWorld() = 0;
virtual bool toggleBorders() = 0;
virtual void adjustSky() = 0;

@ -203,8 +203,8 @@ namespace MWRender
, mNightEyeFactor(0.f)
, mDistantFog(false)
, mDistantTerrain(false)
, mFieldOfViewOverridden(false)
, mFieldOfViewOverride(0.f)
, mBorders(false)
{
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
@ -254,9 +254,10 @@ namespace MWRender
Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
if (mDistantTerrain)
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile, Mask_Debug));
else
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile, Mask_Debug));
mTerrain->setDefaultViewer(mViewer->getCamera());
mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
@ -477,6 +478,13 @@ namespace MWRender
{
mSky->setEnabled(enabled);
}
bool RenderingManager::toggleBorders()
{
mBorders = !mBorders;
mTerrain->setBordersVisible(mBorders);
return mBorders;
}
bool RenderingManager::toggleRenderMode(RenderMode mode)
{

@ -207,6 +207,8 @@ namespace MWRender
LandManager* getLandManager() const;
bool toggleBorders();
private:
void updateProjectionMatrix();
void updateTextureFiltering();
@ -265,6 +267,7 @@ namespace MWRender
float mFieldOfViewOverride;
float mFieldOfView;
float mFirstPersonFieldOfView;
bool mBorders;
void operator = (const RenderingManager&);
RenderingManager(const RenderingManager&);

@ -454,5 +454,6 @@ op 0x2000303: Fixme, explicit
op 0x2000304: Show
op 0x2000305: Show, explicit
op 0x2000306: OnActivate, explicit
op 0x2000307: ToggleBorders, tb
opcodes 0x2000307-0x3ffffff unused
opcodes 0x2000308-0x3ffffff unused

@ -254,6 +254,20 @@ namespace MWScript
}
};
class OpToggleBorders : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
bool enabled =
MWBase::Environment::get().getWorld()->toggleBorders();
runtime.getContext().report (enabled ?
"Border Rendering -> On" : "Border Rendering -> Off");
}
};
class OpTogglePathgrid : public Interpreter::Opcode0
{
public:
@ -1380,6 +1394,7 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevItem, new OpRemoveFromLevItem);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraph, new OpShowSceneGraph<ImplicitRef>);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph<ExplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleBorders, new OpToggleBorders);
}
}
}

@ -1937,6 +1937,11 @@ namespace MWWorld
return mRendering->toggleRenderMode(MWRender::Render_Scene);
}
bool World::toggleBorders()
{
return mRendering->toggleBorders();
}
void World::PCDropped (const Ptr& item)
{
std::string script = item.getClass().getScript(item);

@ -218,6 +218,7 @@ namespace MWWorld
bool toggleWater() override;
bool toggleWorld() override;
bool toggleBorders() override;
void adjustSky() override;

@ -114,7 +114,7 @@ add_component_dir (translation
)
add_component_dir (terrain
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata cellborder
)
add_component_dir (loadinglistener

@ -318,6 +318,8 @@ namespace Compiler
extensions.registerInstruction ("removefromlevcreature", "ccl", opcodeRemoveFromLevCreature);
extensions.registerInstruction ("addtolevitem", "ccl", opcodeAddToLevItem);
extensions.registerInstruction ("removefromlevitem", "ccl", opcodeRemoveFromLevItem);
extensions.registerInstruction ("tb", "", opcodeToggleBorders);
extensions.registerInstruction ("toggleborders", "", opcodeToggleBorders);
}
}

@ -295,6 +295,7 @@ namespace Compiler
const int opcodeRemoveFromLevItem = 0x20002fe;
const int opcodeShowSceneGraph = 0x2002f;
const int opcodeShowSceneGraphExplicit = 0x20030;
const int opcodeToggleBorders = 0x2000307;
}
namespace Sky

@ -0,0 +1,98 @@
#include "cellborder.hpp"
#include <osg/PolygonMode>
#include <osg/Geometry>
#include <osg/Geode>
#include "world.hpp"
#include "../esm/loadland.hpp"
namespace MWRender
{
CellBorder::CellBorder(Terrain::World *world, osg::Group *root, int borderMask):
mWorld(world),
mRoot(root),
mBorderMask(borderMask)
{
}
void CellBorder::createCellBorderGeometry(int x, int y)
{
const int cellSize = ESM::Land::REAL_SIZE;
const int borderSegments = 40;
const float offset = 10.0;
osg::Vec3 cellCorner = osg::Vec3(x * cellSize,y * cellSize,0);
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,-1.0f, 0.0f));
float borderStep = cellSize / ((float) borderSegments);
for (int i = 0; i <= 2 * borderSegments; ++i)
{
osg::Vec3f pos = i < borderSegments ?
osg::Vec3(i * borderStep,0.0f,0.0f) :
osg::Vec3(cellSize,(i - borderSegments) * borderStep,0.0f);
pos += cellCorner;
pos += osg::Vec3f(0,0,mWorld->getHeightAt(pos) + offset);
vertices->push_back(pos);
osg::Vec4f col = i % 2 == 0 ?
osg::Vec4f(0,0,0,1) :
osg::Vec4f(1,1,0,1);
colors->push_back(col);
}
osg::ref_ptr<osg::Geometry> border = new osg::Geometry;
border->setVertexArray(vertices.get());
border->setNormalArray(normals.get());
border->setNormalBinding(osg::Geometry::BIND_OVERALL);
border->setColorArray(colors.get());
border->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
border->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP,0,vertices->size()));
osg::ref_ptr<osg::Geode> borderGeode = new osg::Geode;
borderGeode->addDrawable(border.get());
osg::StateSet *stateSet = borderGeode->getOrCreateStateSet();
osg::PolygonMode* polygonmode = new osg::PolygonMode;
polygonmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
stateSet->setAttributeAndModes(polygonmode,osg::StateAttribute::ON);
borderGeode->setNodeMask(mBorderMask);
mRoot->addChild(borderGeode);
mCellBorderNodes[std::make_pair(x,y)] = borderGeode;
}
void CellBorder::destroyCellBorderGeometry(int x, int y)
{
CellGrid::iterator it = mCellBorderNodes.find(std::make_pair(x,y));
if (it == mCellBorderNodes.end())
return;
osg::ref_ptr<osg::Node> borderNode = it->second;
mRoot->removeChild(borderNode);
mCellBorderNodes.erase(it);
}
void CellBorder::destroyCellBorderGeometry()
{
for (CellGrid::iterator it = mCellBorderNodes.begin(); it != mCellBorderNodes.end(); ++it)
destroyCellBorderGeometry(it->first.first,it->first.second);
}
}

@ -0,0 +1,41 @@
#ifndef GAME_RENDER_CELLBORDER
#define GAME_RENDER_CELLBORDER
#include <map>
#include <osg/Group>
namespace Terrain
{
class World;
}
namespace MWRender
{
/**
* @Brief Handles the debug cell borders.
*/
class CellBorder
{
public:
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > CellGrid;
CellBorder(Terrain::World *world, osg::Group *root, int borderMask);
void createCellBorderGeometry(int x, int y);
void destroyCellBorderGeometry(int x, int y);
/**
Destroys the geometry for all borders.
*/
void destroyCellBorderGeometry();
protected:
Terrain::World *mWorld;
osg::Group *mRoot;
CellGrid mCellBorderNodes;
int mBorderMask;
};
}
#endif

@ -222,8 +222,8 @@ private:
osg::ref_ptr<RootNode> mRootNode;
};
QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resource::ResourceSystem *resourceSystem, Storage *storage, int nodeMask, int preCompileMask)
: World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask)
QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resource::ResourceSystem *resourceSystem, Storage *storage, int nodeMask, int preCompileMask, int borderMask)
: World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask, borderMask)
, mViewDataMap(new ViewDataMap)
, mQuadTreeBuilt(false)
{

@ -19,7 +19,7 @@ namespace Terrain
class QuadTreeWorld : public Terrain::World
{
public:
QuadTreeWorld(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0);
QuadTreeWorld(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0, int borderMask=0);
~QuadTreeWorld();
void accept(osg::NodeVisitor& nv);

@ -17,8 +17,8 @@ public:
virtual void reset(unsigned int frame) {}
};
TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask)
: Terrain::World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask)
TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask)
: Terrain::World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask, borderMask)
, mNumSplits(4)
{
}
@ -75,6 +75,8 @@ void TerrainGrid::loadCell(int x, int y)
if (!terrainNode)
return; // no terrain defined
TerrainGrid::World::loadCell(x,y);
mTerrainRoot->addChild(terrainNode);
mGrid[std::make_pair(x,y)] = terrainNode;
@ -82,10 +84,12 @@ void TerrainGrid::loadCell(int x, int y)
void TerrainGrid::unloadCell(int x, int y)
{
Grid::iterator it = mGrid.find(std::make_pair(x,y));
MWRender::CellBorder::CellGrid::iterator it = mGrid.find(std::make_pair(x,y));
if (it == mGrid.end())
return;
Terrain::World::unloadCell(x,y);
osg::ref_ptr<osg::Node> terrainNode = it->second;
mTerrainRoot->removeChild(terrainNode);

@ -14,7 +14,7 @@ namespace Terrain
class TerrainGrid : public Terrain::World
{
public:
TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0);
TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0, int borderMask=0);
~TerrainGrid();
virtual void cacheCell(View* view, int x, int y);
@ -33,10 +33,8 @@ namespace Terrain
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
unsigned int mNumSplits;
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > Grid;
Grid mGrid;
MWRender::CellBorder::CellGrid mGrid;
};
}
#endif

@ -14,10 +14,11 @@
namespace Terrain
{
World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask)
World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask)
: mStorage(storage)
, mParent(parent)
, mResourceSystem(resourceSystem)
, mBorderVisible(false)
{
mTerrainRoot = new osg::Group;
mTerrainRoot->setNodeMask(nodeMask);
@ -39,7 +40,6 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
compileRoot->addChild(compositeCam);
mCompositeMapRenderer = new CompositeMapRenderer;
compositeCam->addChild(mCompositeMapRenderer);
@ -47,6 +47,7 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get(), mCompositeMapRenderer));
mCellBorder.reset(new MWRender::CellBorder(this,mTerrainRoot.get(),borderMask));
mResourceSystem->addResourceManager(mChunkManager.get());
mResourceSystem->addResourceManager(mTextureManager.get());
@ -65,6 +66,35 @@ World::~World()
delete mStorage;
}
void World::setBordersVisible(bool visible)
{
mBorderVisible = visible;
if (visible)
{
for (std::set<std::pair<int,int>>::iterator it = mLoadedCells.begin(); it != mLoadedCells.end(); ++it)
mCellBorder->createCellBorderGeometry(it->first,it->second);
}
else
mCellBorder->destroyCellBorderGeometry();
}
void World::loadCell(int x, int y)
{
if (mBorderVisible)
mCellBorder->createCellBorderGeometry(x,y);
mLoadedCells.insert(std::pair<int,int>(x,y));
}
void World::unloadCell(int x, int y)
{
if (mBorderVisible)
mCellBorder->destroyCellBorderGeometry(x,y);
mLoadedCells.erase(std::pair<int,int>(x,y));
}
void World::setTargetFrameRate(float rate)
{
mCompositeMapRenderer->setTargetFrameRate(rate);

@ -6,8 +6,10 @@
#include <osg/Vec3f>
#include <memory>
#include <set>
#include "defs.hpp"
#include "cellborder.hpp"
namespace osg
{
@ -54,7 +56,7 @@ namespace Terrain
/// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..)
/// @param nodeMask mask for the terrain root
/// @param preCompileMask mask for pre compiling textures
World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask);
World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask);
virtual ~World();
/// See CompositeMapRenderer::setTargetFrameRate
@ -76,16 +78,16 @@ namespace Terrain
/// Load the cell into the scene graph.
/// @note Not thread safe.
/// @note May be ignored by derived implementations that don't organize the terrain into cells.
virtual void loadCell(int x, int y) {}
virtual void loadCell(int x, int y);
/// Remove the cell from the scene graph.
/// @note Not thread safe.
/// @note May be ignored by derived implementations that don't organize the terrain into cells.
virtual void unloadCell(int x, int y) {}
virtual void unloadCell(int x, int y);
virtual void enable(bool enabled) {}
virtual void setBordersVisible(bool visible);
/// Create a View to use with preload feature. The caller is responsible for deleting the view.
/// @note Thread safe.
virtual View* createView() { return NULL; }
@ -113,8 +115,13 @@ namespace Terrain
std::unique_ptr<TextureManager> mTextureManager;
std::unique_ptr<ChunkManager> mChunkManager;
};
std::unique_ptr<MWRender::CellBorder> mCellBorder;
bool mBorderVisible;
std::set<std::pair<int,int>> mLoadedCells;
};
}
#endif

Loading…
Cancel
Save