mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-29 09:32:45 +00:00
Merged pull request #1421
This commit is contained in:
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
|
||||
|
98
components/terrain/cellborder.cpp
Normal file
98
components/terrain/cellborder.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
41
components/terrain/cellborder.hpp
Normal file
41
components/terrain/cellborder.hpp
Normal file
@ -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…
x
Reference in New Issue
Block a user