Merge remote-tracking branch 'upstream/master' into windowsPinning

Conflicts:
	apps/openmw/mwgui/window_manager.cpp (keep both changes)
actorid
Roman Melnik 13 years ago
commit bdbb8a8d84

@ -24,10 +24,12 @@ set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VE
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
# Sound source selection
option(USE_FFMPEG "use ffmpeg for sound" OFF)
option(USE_AUDIERE "use audiere for sound" OFF)
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
@ -133,6 +135,13 @@ if (USE_FFMPEG)
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
endif (USE_FFMPEG)
if (USE_AUDIERE)
find_package(Audiere REQUIRED)
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
endif (USE_AUDIERE)
if (USE_MPG123)
find_package(MPG123 REQUIRED)
find_package(SNDFILE REQUIRED)
@ -215,6 +224,9 @@ endif (APPLE)
# Other files
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}/settings-default.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
"${OpenMW_BINARY_DIR}/openmw.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
@ -241,8 +253,14 @@ if (APPLE)
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
# prepare plugins
if (${CMAKE_BUILD_TYPE} MATCHES "Release" OR
${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo")
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
set(OPENMW_RELEASE_BUILD 1)
endif()
if (${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo")
set(OPENMW_RELEASE_BUILD 1)
endif()
if (${OPENMW_RELEASE_BUILD})
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
else()
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
@ -289,6 +307,7 @@ if(DPKG_PROGRAM)
INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
#Install global configuration files
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")

@ -12,12 +12,22 @@ MwIniImporter::MwIniImporter() {
const char *map[][2] =
{
{ "fps", "General:Show FPS" },
{ "nosound", "General:Disable Audio" },
{ 0, 0 }
};
const char *fallback[] = {
"Weather:Sunrise Time",
"Weather:Sunset Time",
0
};
for(int i=0; map[i][0]; i++) {
mMergeMap.insert(std::make_pair<std::string, std::string>(map[i][0], map[i][1]));
}
for(int i=0; fallback[i]; i++) {
mMergeFallback.push_back(fallback[i]);
}
}
void MwIniImporter::setVerbose(bool verbose) {
@ -116,16 +126,38 @@ void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) {
multistrmap::iterator iniIt;
for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) {
if((iniIt = ini.find(it->second)) != ini.end()) {
cfg.erase(it->first);
if(!this->specialMerge(it->first, it->second, cfg, ini)) {
cfg.insert(std::make_pair<std::string, std::vector<std::string> >(it->first, iniIt->second));
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) {
cfg.erase(it->first);
insertMultistrmap(cfg, it->first, *vc);
}
}
}
}
bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini) {
return false;
void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) {
cfg.erase("fallback");
multistrmap::iterator cfgIt;
multistrmap::iterator iniIt;
for(std::vector<std::string>::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); it++) {
if((iniIt = ini.find(*it)) != ini.end()) {
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) {
std::string value(*it);
std::replace( value.begin(), value.end(), ' ', '_' );
std::replace( value.begin(), value.end(), ':', '_' );
value.append(",").append(vc->substr(0,vc->length()-1));
insertMultistrmap(cfg, "fallback", value);
}
}
}
};
void MwIniImporter::insertMultistrmap(multistrmap &cfg, std::string key, std::string value) {
multistrmap::iterator it = cfg.find(key);
if(it == cfg.end()) {
cfg.insert(std::make_pair<std::string, std::vector<std::string> >(key, std::vector<std::string>() ));
}
cfg[key].push_back(value);
}
void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {

@ -18,14 +18,16 @@ class MwIniImporter {
multistrmap loadIniFile(std::string filename);
multistrmap loadCfgFile(std::string filename);
void merge(multistrmap &cfg, multistrmap &ini);
void mergeFallback(multistrmap &cfg, multistrmap &ini);
void importGameFiles(multistrmap &cfg, multistrmap &ini);
void writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg);
private:
bool specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini);
void insertMultistrmap(multistrmap &cfg, std::string key, std::string value);
std::string numberToString(int n);
bool mVerbose;
strmap mMergeMap;
std::vector<std::string> mMergeFallback;
};

@ -9,7 +9,8 @@ namespace bpo = boost::program_options;
int main(int argc, char *argv[]) {
bpo::options_description desc("Syntax: mwiniimporter <options>\nAllowed options");
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
bpo::positional_options_description p_desc;
desc.add_options()
("help,h", "produce help message")
("verbose,v", "verbose output")
@ -18,28 +19,22 @@ int main(int argc, char *argv[]) {
("output,o", bpo::value<std::string>()->default_value(""), "openmw.cfg file")
("game-files,g", "import esm and esp files")
;
p_desc.add("ini", 1).add("cfg", 1);
bpo::variables_map vm;
try {
bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
// parse help before calling notify because we dont want it to throw an error if help is set
if(vm.count("help")) {
std::cout << desc;
return 0;
}
bpo::notify(vm);
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
.options(desc)
.positional(p_desc)
.run();
bpo::store(parsed, vm);
if(vm.count("help") || !vm.count("ini") || !vm.count("cfg")) {
std::cout << desc;
return 0;
}
catch(std::exception& e) {
std::cerr << "Error:" << e.what() << std::endl;
return -1;
}
catch(...) {
std::cerr << "Error" << std::endl;
return -2;
}
bpo::notify(vm);
std::string iniFile = vm["ini"].as<std::string>();
std::string cfgFile = vm["cfg"].as<std::string>();
@ -58,21 +53,22 @@ int main(int argc, char *argv[]) {
std::cerr << "cfg file does not exist" << std::endl;
return -4;
}
MwIniImporter importer;
importer.setVerbose(vm.count("verbose"));
boost::iostreams::stream<boost::iostreams::file_sink> file(outputFile);
MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile);
MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile);
importer.merge(cfg, ini);
importer.mergeFallback(cfg, ini);
if(vm.count("game-files")) {
importer.importGameFiles(cfg, ini);
}
std::cout << "write to: " << outputFile << std::endl;
boost::iostreams::stream<boost::iostreams::file_sink> file(outputFile);
importer.writeToFile(file, cfg);
return 0;

@ -40,7 +40,7 @@ add_openmw_dir (mwscript
)
add_openmw_dir (mwsound
soundmanager openal_output mpgsnd_decoder ffmpeg_decoder
soundmanager openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder
)
add_openmw_dir (mwworld

@ -20,6 +20,7 @@
#include <components/esm/esm_reader.hpp>
#include <components/files/fixedpath.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
#include <components/nifbullet/bullet_nif_loader.hpp>
#include <components/nifogre/ogre_nif_loader.hpp>
@ -82,12 +83,20 @@ void OMW::Engine::updateFocusReport (float duration)
if (!handle.empty())
{
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
// the faced handle is not updated immediately, so on a cell change it might
// point to an object that doesn't exist anymore
// therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case
try
{
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
if (!ptr.isEmpty()){
name = MWWorld::Class::get (ptr).getName (ptr);
if (!ptr.isEmpty()){
name = MWWorld::Class::get (ptr).getName (ptr);
}
}
catch (std::runtime_error& e)
{}
}
if (name!=mFocusName)
@ -115,6 +124,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
mEnvironment.mFrameDuration = evt.timeSinceLastFrame;
// update input
mEnvironment.mInputManager->update();
// sound
if (mUseSound)
mEnvironment.mSoundManager->update (evt.timeSinceLastFrame);
@ -313,6 +325,29 @@ void OMW::Engine::go()
{
boost::filesystem::create_directories(configPath);
}
// Create the settings manager and load default settings file
Settings::Manager settings;
const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg";
const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg";
// prefer local
if (boost::filesystem::exists(localdefault))
settings.loadDefault(localdefault);
else if (boost::filesystem::exists(globaldefault))
settings.loadDefault(globaldefault);
// load user settings if they exist, otherwise just load the default settings as user settings
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
if (boost::filesystem::exists(settingspath))
settings.loadUser(settingspath);
else if (boost::filesystem::exists(localdefault))
settings.loadUser(localdefault);
else if (boost::filesystem::exists(globaldefault))
settings.loadUser(globaldefault);
mFpsLevel = settings.getInt("fps", "HUD");
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
mCfgMgr.getOgreConfigPath().string(),
mCfgMgr.getLogPath().string(),
@ -333,7 +368,7 @@ void OMW::Engine::go()
// Create the world
mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
mResDir, mNewGame, mEnvironment, mEncoding);
mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap);
// Create window manager - this manages all the MW-specific GUI windows
MWScript::registerExtensions (mExtensions);
@ -407,6 +442,9 @@ void OMW::Engine::go()
// Start the main rendering loop
mOgre->start();
// Save user settings
settings.saveUser(settingspath);
std::cout << "Quitting peacefully.\n";
}
@ -420,10 +458,21 @@ void OMW::Engine::activate()
if (handle.empty())
return;
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
// the faced handle is not updated immediately, so on a cell change it might
// point to an object that doesn't exist anymore
// therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case
MWWorld::Ptr ptr;
try
{
ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
if (ptr.isEmpty())
if (ptr.isEmpty())
return;
}
catch (std::runtime_error&)
{
return;
}
MWScript::InterpreterContext interpreterContext (mEnvironment,
&ptr.getRefData().getLocals(), ptr);
@ -489,3 +538,8 @@ void OMW::Engine::setEncoding(const std::string& encoding)
{
mEncoding = encoding;
}
void OMW::Engine::setFallbackValues(std::map<std::string,std::string> fallbackMap)
{
mFallbackMap = fallbackMap;
}

@ -76,6 +76,7 @@ namespace OMW
bool mReportFocus;
float mFocusTDiff;
std::string mFocusName;
std::map<std::string,std::string> mFallbackMap;
MWWorld::Environment mEnvironment;
Compiler::Extensions mExtensions;
@ -163,6 +164,8 @@ namespace OMW
void setAnimationVerbose(bool animverbose);
void setFallbackValues(std::map<std::string,std::string> map);
private:
Files::ConfigurationManager& mCfgMgr;
};

@ -54,6 +54,41 @@ inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string
using namespace std;
struct FallbackMap {
std::map<std::string,std::string> mMap;
};
void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap*, int)
{
if(v.empty())
{
v = boost::any(FallbackMap());
}
FallbackMap *map = boost::any_cast<FallbackMap>(&v);
std::map<std::string,std::string>::iterator mapIt;
for(std::vector<std::string>::const_iterator it=tokens.begin(); it != tokens.end(); it++)
{
int sep = it->find(",");
if(sep < 1 || sep == (int)it->length()-1)
#if (BOOST_VERSION < 104200)
throw boost::program_options::validation_error("invalid value");
#else
throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
#endif
std::string key(it->substr(0,sep));
std::string value(it->substr(sep+1));
if((mapIt = map->mMap.find(key)) == map->mMap.end())
{
map->mMap.insert(std::make_pair<std::string,std::string>(key,value));
}
}
}
/**
* \brief Parses application command line and calls \ref Cfg::ConfigurationManager
* to parse configuration files.
@ -92,39 +127,40 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("plugin", bpo::value<StringsVector>()->default_value(StringsVector(), "")
->multitoken(), "plugin file(s)")
("fps", boost::program_options::value<int>()->implicit_value(1)
->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)")
("anim-verbose", boost::program_options::value<bool>()->implicit_value(true)
("anim-verbose", bpo::value<bool>()->implicit_value(true)
->default_value(false), "output animation indices files")
("debug", boost::program_options::value<bool>()->implicit_value(true)
("debug", bpo::value<bool>()->implicit_value(true)
->default_value(false), "debug mode")
("nosound", boost::program_options::value<bool>()->implicit_value(true)
("nosound", bpo::value<bool>()->implicit_value(true)
->default_value(false), "disable all sounds")
("script-verbose", boost::program_options::value<bool>()->implicit_value(true)
("script-verbose", bpo::value<bool>()->implicit_value(true)
->default_value(false), "verbose script output")
("new-game", boost::program_options::value<bool>()->implicit_value(true)
("new-game", bpo::value<bool>()->implicit_value(true)
->default_value(false), "activate char gen/new game mechanics")
("script-all", boost::program_options::value<bool>()->implicit_value(true)
("script-all", bpo::value<bool>()->implicit_value(true)
->default_value(false), "compile all scripts (excluding dialogue scripts) at startup")
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)
("fs-strict", bpo::value<bool>()->implicit_value(true)
->default_value(false), "strict file system handling (no case folding)")
( "encoding", boost::program_options::value<std::string>()->
( "encoding", bpo::value<std::string>()->
default_value("win1252"),
"Character encoding used in OpenMW game messages:\n"
"\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
"\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
"\n\twin1252 - Western European (Latin) alphabet, used by default")
("report-focus", boost::program_options::value<bool>()->implicit_value(true)
("report-focus", bpo::value<bool>()->implicit_value(true)
->default_value(false), "write name of focussed object to cout")
("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")
->multitoken()->composing(), "fallback values")
;
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
@ -225,13 +261,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setNewGame(variables["new-game"].as<bool>());
// other settings
engine.showFPS(variables["fps"].as<int>());
engine.setDebugMode(variables["debug"].as<bool>());
engine.setSoundUsage(!variables["nosound"].as<bool>());
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
engine.setCompileAll(variables["script-all"].as<bool>());
engine.setReportFocus(variables["report-focus"].as<bool>());
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
return true;
}

@ -528,6 +528,13 @@ namespace MWDialogue
mChoice = -1;
mIsInChoice = false;
mCompilerContext.setExtensions (&extensions);
mDialogueMap.clear();
actorKnownTopics.clear();
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
mDialogueMap[it->first] = it->second;
}
}
void DialogueManager::addTopic(std::string topic)
@ -563,13 +570,7 @@ namespace MWDialogue
mActor = actor;
mDialogueMap.clear();
actorKnownTopics.clear();
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
mDialogueMap[it->first] = it->second;
}
//initialise the GUI
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
@ -582,6 +583,7 @@ namespace MWDialogue
//greeting
bool greetingFound = false;
//ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
ESM::Dialogue ndialogue = it->second;

@ -238,6 +238,7 @@ LocalMapBase::LocalMapBase()
: mCurX(0)
, mCurY(0)
, mInterior(false)
, mFogOfWar(true)
, mLocalMap(NULL)
, mPrefix()
, mChanged(true)
@ -261,6 +262,32 @@ void LocalMapBase::setCellPrefix(const std::string& prefix)
mChanged = true;
}
void LocalMapBase::toggleFogOfWar()
{
mFogOfWar = !mFogOfWar;
applyFogOfWar();
}
void LocalMapBase::applyFogOfWar()
{
for (int mx=0; mx<3; ++mx)
{
for (int my=0; my<3; ++my)
{
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
+ boost::lexical_cast<std::string>(my);
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(mCurX + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* fog;
mLayout->getWidget(fog, name+"_fog");
fog->setImageTexture(mFogOfWar ?
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
: "black.png" )
: "");
}
}
}
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
@ -276,23 +303,17 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
MyGUI::ImageBox* box;
mLayout->getWidget(box, name);
MyGUI::ImageBox* fog;
mLayout->getWidget(fog, name+"_fog");
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
box->setImageTexture(image);
else
box->setImageTexture("black.png");
if (MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0)
fog->setImageTexture(image+"_fog");
else
fog->setImageTexture("black.png");
}
}
mInterior = interior;
mCurX = x;
mCurY = y;
mChanged = false;
applyFogOfWar();
}

@ -40,12 +40,17 @@ namespace MWGui
void setCellPrefix(const std::string& prefix);
void setActiveCell(const int x, const int y, bool interior=false);
void toggleFogOfWar();
protected:
int mCurX, mCurY;
bool mInterior;
MyGUI::ScrollView* mLocalMap;
std::string mPrefix;
bool mChanged;
bool mFogOfWar;
void applyFogOfWar();
OEngine::GUI::Layout* mLayout;

@ -466,3 +466,9 @@ void WindowManager::setMinimapVisibility(bool visible)
{
hud->setBottomRightVisibility(hud->effectBox->getVisible(), visible);
}
void WindowManager::toggleFogOfWar()
{
map->toggleFogOfWar();
hud->toggleFogOfWar();
}

@ -156,6 +156,8 @@ namespace MWGui
void changeCell(MWWorld::Ptr::CellStore* cell); ///< change the active cell
void setPlayerPos(const float x, const float y); ///< set player position in map space
void setPlayerDir(const float x, const float y); ///< set player view direction in map space
void toggleFogOfWar();
void setInteriorMapTexture(const int x, const int y);
///< set the index of the map texture that should be used (for interiors)

@ -70,7 +70,7 @@ namespace MWInput
};
// Class that handles all input and key bindings for OpenMW
class InputImpl : public Ogre::FrameListener
class InputImpl
{
OEngine::Input::DispatcherPtr disp;
OEngine::Render::OgreRenderer &ogre;
@ -200,8 +200,6 @@ namespace MWInput
// Add the exit listener
ogre.getRoot()->addFrameListener(&exit);
// Add ourselves as a frame listener to catch movement keys
ogre.getRoot()->addFrameListener(this);
// Set up the mouse handler and tell it about the player camera
mouse = MouseLookEventPtr(new MouseLookEvent(player.getRenderer()->getCamera()));
@ -262,7 +260,7 @@ namespace MWInput
}
//NOTE: Used to check for movement keys
bool frameRenderingQueued (const Ogre::FrameEvent &evt)
void update ()
{
// Tell OIS to handle all input events
input.capture();
@ -276,7 +274,7 @@ namespace MWInput
windows.update();
// Disable movement in Gui mode
if (windows.isGuiMode()) return true;
if (windows.isGuiMode()) return;
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
@ -305,8 +303,6 @@ namespace MWInput
}
else
player.setForwardBackward (0);
return true;
}
// Switch between gui modes. Besides controlling the Gui windows
@ -358,4 +354,9 @@ namespace MWInput
{
impl->setGuiMode(mode);
}
void MWInputManager::update()
{
impl->update();
}
}

@ -48,6 +48,8 @@ namespace MWInput
OMW::Engine& engine);
~MWInputManager();
void update();
void setGuiMode(MWGui::GuiMode mode);
};
}

@ -2,33 +2,283 @@
#include <assert.h>
#include "OgreRoot.h"
#include "OgreRenderWindow.h"
#include "OgreSceneManager.h"
#include "OgreViewport.h"
#include "OgreCamera.h"
#include "OgreTextureManager.h"
#include <OgreNode.h>
#include <OgreSceneManager.h>
#include <OgreMaterial.h>
#include <OgreMaterialManager.h>
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
#include "../mwworld/environment.hpp"
#include "../mwworld/ptr.hpp"
#include <components/esm/loadstat.hpp>
#include <components/esm/loadpgrd.hpp>
#include "player.hpp"
using namespace MWRender;
using namespace Ogre;
Debugging::Debugging(OEngine::Physic::PhysicEngine* engine){
eng = engine;
namespace MWRender
{
static const std::string PATHGRID_POINT_MATERIAL = "pathgridPointMaterial";
static const std::string PATHGRID_LINE_MATERIAL = "pathgridLineMaterial";
static const std::string DEBUGGING_GROUP = "debugging";
static const int POINT_MESH_BASE = 35;
void Debugging::createGridMaterials()
{
if (mGridMatsCreated) return;
if (MaterialManager::getSingleton().getByName(PATHGRID_LINE_MATERIAL, DEBUGGING_GROUP).isNull())
{
MaterialPtr lineMatPtr = MaterialManager::getSingleton().create(PATHGRID_LINE_MATERIAL, DEBUGGING_GROUP);
lineMatPtr->setReceiveShadows(false);
lineMatPtr->getTechnique(0)->setLightingEnabled(true);
lineMatPtr->getTechnique(0)->getPass(0)->setDiffuse(1,1,0,0);
lineMatPtr->getTechnique(0)->getPass(0)->setAmbient(1,1,0);
lineMatPtr->getTechnique(0)->getPass(0)->setSelfIllumination(1,1,0);
}
if (MaterialManager::getSingleton().getByName(PATHGRID_POINT_MATERIAL, DEBUGGING_GROUP).isNull())
{
MaterialPtr pointMatPtr = MaterialManager::getSingleton().create(PATHGRID_POINT_MATERIAL, DEBUGGING_GROUP);
pointMatPtr->setReceiveShadows(false);
pointMatPtr->getTechnique(0)->setLightingEnabled(true);
pointMatPtr->getTechnique(0)->getPass(0)->setDiffuse(1,0,0,0);
pointMatPtr->getTechnique(0)->getPass(0)->setAmbient(1,0,0);
pointMatPtr->getTechnique(0)->getPass(0)->setSelfIllumination(1,0,0);
}
mGridMatsCreated = true;
}
void Debugging::destroyGridMaterials()
{
if (mGridMatsCreated)
{
MaterialManager::getSingleton().remove(PATHGRID_POINT_MATERIAL);
MaterialManager::getSingleton().remove(PATHGRID_LINE_MATERIAL);
mGridMatsCreated = false;
}
}
ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid)
{
ManualObject *result = mSceneMgr->createManualObject();
result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST);
for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->edges.begin();
it != pathgrid->edges.end();
it++)
{
const ESM::Pathgrid::Edge &edge = *it;
const ESM::Pathgrid::Point &p1 = pathgrid->points[edge.v0], &p2 = pathgrid->points[edge.v1];
Vector3 direction = (Vector3(p2.x, p2.y, p2.z) - Vector3(p1.x, p1.y, p1.z));
Vector3 lineDisplacement = direction.crossProduct(Vector3::UNIT_Z).normalisedCopy();
lineDisplacement = lineDisplacement * POINT_MESH_BASE +
Vector3(0, 0, 10); // move lines up a little, so they will be less covered by meshes/landscape
result->position(Vector3(p1.x, p1.y, p1.z) + lineDisplacement);
result->position(Vector3(p2.x, p2.y, p2.z) + lineDisplacement);
}
result->end();
return result;
}
ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid)
{
ManualObject *result = mSceneMgr->createManualObject();
const float height = POINT_MESH_BASE * sqrtf(2);
result->begin(PATHGRID_POINT_MATERIAL, RenderOperation::OT_TRIANGLE_STRIP);
bool first = true;
uint32 startIndex = 0;
for(ESM::Pathgrid::PointList::const_iterator it = pathgrid->points.begin();
it != pathgrid->points.end();
it++, startIndex += 6)
{
Vector3 pointPos(it->x, it->y, it->z);
if (!first)
{
// degenerate triangle from previous octahedron
result->index(startIndex - 4); // 2nd point of previous octahedron
result->index(startIndex); // start point of current octahedron
}
result->position(pointPos + Vector3(0, 0, height)); // 0
result->position(pointPos + Vector3(-POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 1
result->position(pointPos + Vector3(POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 2
result->position(pointPos + Vector3(POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 3
result->position(pointPos + Vector3(-POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 4
result->position(pointPos + Vector3(0, 0, -height)); // 5
result->index(startIndex + 0);
result->index(startIndex + 1);
result->index(startIndex + 2);
result->index(startIndex + 5);
result->index(startIndex + 3);
result->index(startIndex + 4);
// degenerates
result->index(startIndex + 4);
result->index(startIndex + 5);
result->index(startIndex + 5);
// end degenerates
result->index(startIndex + 1);
result->index(startIndex + 4);
result->index(startIndex + 0);
result->index(startIndex + 3);
result->index(startIndex + 2);
first = false;
}
result->end();
return result;
}
Debugging::Debugging(SceneNode *mwRoot, MWWorld::Environment &env, OEngine::Physic::PhysicEngine *engine) :
mMwRoot(mwRoot), mEnvironment(env), mEngine(engine),
mSceneMgr(mwRoot->getCreator()),
mPathgridEnabled(false),
mInteriorPathgridNode(NULL), mPathGridRoot(NULL),
mGridMatsCreated(false)
{
ResourceGroupManager::getSingleton().createResourceGroup(DEBUGGING_GROUP);
}
Debugging::~Debugging()
{
if (mPathgridEnabled)
{
togglePathgrid();
}
ResourceGroupManager::getSingleton().destroyResourceGroup(DEBUGGING_GROUP);
}
bool Debugging::toggleRenderMode (int mode){
switch (mode)
switch (mode)
{
case MWWorld::World::Render_CollisionDebug:
return eng->toggleDebugRendering();
return mEngine->toggleDebugRendering();
case MWWorld::World::Render_Pathgrid:
togglePathgrid();
return mPathgridEnabled;
}
return false;
}
void Debugging::cellAdded(MWWorld::Ptr::CellStore *store)
{
mActiveCells.push_back(store);
if (mPathgridEnabled)
enableCellPathgrid(store);
}
void Debugging::cellRemoved(MWWorld::Ptr::CellStore *store)
{
mActiveCells.erase(std::remove(mActiveCells.begin(), mActiveCells.end(), store), mActiveCells.end());
if (mPathgridEnabled)
disableCellPathgrid(store);
}
void Debugging::togglePathgrid()
{
mPathgridEnabled = !mPathgridEnabled;
if (mPathgridEnabled)
{
createGridMaterials();
// add path grid meshes to already loaded cells
mPathGridRoot = mMwRoot->createChildSceneNode();
for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++)
{
enableCellPathgrid(*it);
}
}
else
{
// remove path grid meshes from already loaded cells
for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++)
{
disableCellPathgrid(*it);
}
mPathGridRoot->removeAndDestroyAllChildren();
mSceneMgr->destroySceneNode(mPathGridRoot);
mPathGridRoot = NULL;
destroyGridMaterials();
}
}
void Debugging::enableCellPathgrid(MWWorld::Ptr::CellStore *store)
{
ESM::Pathgrid *pathgrid = mEnvironment.mWorld->getStore().pathgrids.search(*store->cell);
if (!pathgrid) return;
Vector3 cellPathGridPos(0, 0, 0);
if (store->cell->isExterior())
{
cellPathGridPos.x = store->cell->data.gridX * ESM::Land::REAL_SIZE;
cellPathGridPos.y = store->cell->data.gridY * ESM::Land::REAL_SIZE;
}
SceneNode *cellPathGrid = mPathGridRoot->createChildSceneNode(cellPathGridPos);
cellPathGrid->attachObject(createPathgridLines(pathgrid));
cellPathGrid->attachObject(createPathgridPoints(pathgrid));
if (store->cell->isExterior())
{
mExteriorPathgridNodes[std::make_pair(store->cell->data.gridX, store->cell->data.gridY)] = cellPathGrid;
}
else
{
assert(mInteriorPathgridNode == NULL);
mInteriorPathgridNode = cellPathGrid;
}
}
void Debugging::disableCellPathgrid(MWWorld::Ptr::CellStore *store)
{
if (store->cell->isExterior())
{
ExteriorPathgridNodes::iterator it =
mExteriorPathgridNodes.find(std::make_pair(store->cell->data.gridX, store->cell->data.gridY));
if (it != mExteriorPathgridNodes.end())
{
destroyCellPathgridNode(it->second);
mExteriorPathgridNodes.erase(it);
}
}
else
{
if (mInteriorPathgridNode)
{
destroyCellPathgridNode(mInteriorPathgridNode);
mInteriorPathgridNode = NULL;
}
}
}
void Debugging::destroyCellPathgridNode(SceneNode *node)
{
mPathGridRoot->removeChild(node);
destroyAttachedObjects(node);
mSceneMgr->destroySceneNode(node);
}
void Debugging::destroyAttachedObjects(SceneNode *node)
{
SceneNode::ObjectIterator objIt = node->getAttachedObjectIterator();
while (objIt.hasMoreElements())
{
MovableObject *mesh = static_cast<MovableObject *>(objIt.getNext());
mSceneMgr->destroyMovableObject(mesh);
}
}
}

@ -4,6 +4,7 @@
#include <utility>
#include <openengine/ogre/renderer.hpp>
#include <openengine/bullet/physic.hpp>
#include "../mwworld/ptr.hpp"
#include <vector>
#include <string>
@ -22,20 +23,58 @@ namespace Ogre
namespace MWWorld
{
class World;
class Environment;
}
namespace MWRender
{
class Player;
class Debugging{
OEngine::Physic::PhysicEngine* eng;
class Debugging
{
OEngine::Physic::PhysicEngine* mEngine;
Ogre::SceneManager *mSceneMgr;
MWWorld::Environment& mEnvironment;
// Path grid stuff
bool mPathgridEnabled;
public:
Debugging(OEngine::Physic::PhysicEngine* engine);
bool toggleRenderMode (int mode);
};
void togglePathgrid();
typedef std::vector<MWWorld::Ptr::CellStore *> CellList;
CellList mActiveCells;
Ogre::SceneNode *mMwRoot;
Ogre::SceneNode *mPathGridRoot;
typedef std::map<std::pair<int,int>, Ogre::SceneNode *> ExteriorPathgridNodes;
ExteriorPathgridNodes mExteriorPathgridNodes;
Ogre::SceneNode *mInteriorPathgridNode;
void enableCellPathgrid(MWWorld::Ptr::CellStore *store);
void disableCellPathgrid(MWWorld::Ptr::CellStore *store);
// utility
void destroyCellPathgridNode(Ogre::SceneNode *node);
void destroyAttachedObjects(Ogre::SceneNode *node);
// materials
bool mGridMatsCreated;
void createGridMaterials();
void destroyGridMaterials();
// path grid meshes
Ogre::ManualObject *createPathgridLines(const ESM::Pathgrid *pathgrid);
Ogre::ManualObject *createPathgridPoints(const ESM::Pathgrid *pathgrid);
public:
Debugging(Ogre::SceneNode* mwRoot, MWWorld::Environment &env, OEngine::Physic::PhysicEngine *engine);
~Debugging();
bool toggleRenderMode (int mode);
void cellAdded(MWWorld::Ptr::CellStore* store);
void cellRemoved(MWWorld::Ptr::CellStore* store);
};
}

@ -2,6 +2,7 @@
#include "renderingmanager.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwgui/window_manager.hpp"
#include <OgreOverlayManager.h>
@ -10,16 +11,24 @@
using namespace MWRender;
using namespace Ogre;
LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWWorld::Environment* env)
LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering, MWWorld::Environment* env) :
mInterior(false), mCellX(0), mCellY(0)
{
mRendering = rend;
mRenderingManager = rendering;
mEnvironment = env;
mCameraPosNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
mCameraRotNode = mCameraPosNode->createChildSceneNode();
mCameraNode = mCameraRotNode->createChildSceneNode();
mCellCamera = mRendering->getScene()->createCamera("CellCamera");
mCellCamera->setProjectionType(PT_ORTHOGRAPHIC);
// look down -y
const float sqrt0pt5 = 0.707106781;
mCellCamera->setOrientation(Quaternion(sqrt0pt5, -sqrt0pt5, 0, 0));
mCameraNode->attachObject(mCellCamera);
}
LocalMap::~LocalMap()
@ -27,6 +36,12 @@ LocalMap::~LocalMap()
deleteBuffers();
}
const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle)
{
return Vector2( Math::Cos(angle) * (p.x - c.x) - Math::Sin(angle) * (p.y - c.y) + c.x,
Math::Sin(angle) * (p.x - c.x) + Math::Cos(angle) * (p.y - c.y) + c.y);
}
void LocalMap::deleteBuffers()
{
mBuffers.clear();
@ -65,9 +80,6 @@ void LocalMap::saveFogOfWar(MWWorld::Ptr::CellStore* cell)
{
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
/// \todo why is this workaround needed?
min *= 1.3;
max *= 1.3;
Vector2 length = max-min;
// divide into segments
@ -90,11 +102,15 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell)
{
mInterior = false;
mCameraRotNode->setOrientation(Quaternion::IDENTITY);
std::string name = "Cell_"+coordStr(cell->cell->data.gridX, cell->cell->data.gridY);
int x = cell->cell->data.gridX;
int y = cell->cell->data.gridY;
mCameraPosNode->setPosition(Vector3(0,0,0));
render((x+0.5)*sSize, (-y-0.5)*sSize, -10000, 10000, sSize, sSize, name);
}
@ -103,17 +119,41 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
{
mInterior = true;
mBounds = bounds;
Vector2 z(bounds.getMaximum().y, bounds.getMinimum().y);
Vector2 min(bounds.getMinimum().x, bounds.getMinimum().z);
Vector2 max(bounds.getMaximum().x, bounds.getMaximum().z);
/// \todo why is this workaround needed?
min *= 1.3;
max *= 1.3;
Vector2 z(mBounds.getMaximum().y, mBounds.getMinimum().y);
const Vector2& north = mEnvironment->mWorld->getNorthVector(cell);
Radian angle(std::atan2(-north.x, -north.y));
mAngle = angle.valueRadians();
mCameraRotNode->setOrientation(Quaternion(Math::Cos(angle/2.f), 0, Math::Sin(angle/2.f), 0));
// rotate the cell and merge the rotated corners to the bounding box
Vector2 _center(bounds.getCenter().x, bounds.getCenter().z);
Vector3 _c1 = bounds.getCorner(AxisAlignedBox::NEAR_LEFT_BOTTOM);
Vector3 _c2 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM);
Vector3 _c3 = bounds.getCorner(AxisAlignedBox::NEAR_RIGHT_BOTTOM);
Vector3 _c4 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM);
Vector2 c1(_c1.x, _c1.z);
Vector2 c2(_c2.x, _c2.z);
Vector2 c3(_c3.x, _c3.z);
Vector2 c4(_c4.x, _c4.z);
c1 = rotatePoint(c1, _center, mAngle);
c2 = rotatePoint(c2, _center, mAngle);
c3 = rotatePoint(c3, _center, mAngle);
c4 = rotatePoint(c4, _center, mAngle);
mBounds.merge(Vector3(c1.x, 0, c1.y));
mBounds.merge(Vector3(c2.x, 0, c2.y));
mBounds.merge(Vector3(c3.x, 0, c3.y));
mBounds.merge(Vector3(c4.x, 0, c4.y));
Vector2 center(mBounds.getCenter().x, mBounds.getCenter().z);
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
Vector2 length = max-min;
Vector2 center(bounds.getCenter().x, bounds.getCenter().z);
mCameraPosNode->setPosition(Vector3(center.x, 0, center.y));
// divide into segments
const int segsX = std::ceil( length.x / sSize );
@ -128,7 +168,7 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
Vector2 start = min + Vector2(sSize*x,sSize*y);
Vector2 newcenter = start + 4096;
render(newcenter.x, newcenter.y, z.y, z.x, sSize, sSize,
render(newcenter.x - center.x, newcenter.y - center.y, z.y, z.x, sSize, sSize,
cell->cell->name + "_" + coordStr(x,y));
}
}
@ -147,8 +187,9 @@ void LocalMap::render(const float x, const float y,
// make everything visible
mRendering->getScene()->setAmbientLight(ColourValue(1,1,1));
mRenderingManager->disableLights();
mCellCamera->setPosition(Vector3(x, zhigh+100000, y));
mCameraNode->setPosition(Vector3(x, zhigh+100000, y));
//mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 );
mCellCamera->setFarClipDistance(0); // infinite
@ -215,13 +256,14 @@ void LocalMap::render(const float x, const float y,
//rtt->writeContentsToFile("./" + texture + ".jpg");
}
}
mRenderingManager->enableLights();
// re-enable fog
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd);
}
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction)
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
{
if (sFogOfWarSkip != 0)
{
@ -232,7 +274,19 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3&
// retrieve the x,y grid coordinates the player is in
int x,y;
Vector2 pos(position.x, position.z);
Vector3 _pos(position.x, 0, position.z);
Vector2 pos(_pos.x, _pos.z);
if (mInterior)
{
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle);
}
Vector3 playerdirection = -mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis();
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
if (!mInterior)
{
x = std::ceil(pos.x / sSize)-1;
@ -242,9 +296,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3&
}
else
{
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
min *= 1.3;
x = std::ceil((pos.x - min.x)/sSize)-1;
y = std::ceil((pos.y - min.y)/sSize)-1;
@ -259,20 +310,17 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3&
u = std::abs((pos.x - (sSize*x))/sSize);
v = 1-std::abs((pos.y + (sSize*y))/sSize);
texName = "Cell_"+coordStr(x,y);
}
else
{
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
min *= 1.3;
u = (pos.x - min.x - sSize*x)/sSize;
v = (pos.y - min.y - sSize*y)/sSize;
texName = mInteriorName + "_" + coordStr(x,y);
}
mEnvironment->mWindowManager->setPlayerPos(u, v);
mEnvironment->mWindowManager->setPlayerDir(direction.x, -direction.z);
mEnvironment->mWindowManager->setPlayerDir(playerdirection.x, -playerdirection.z);
// explore radius (squared)
const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution;

@ -12,13 +12,15 @@ namespace MWWorld
namespace MWRender
{
class RenderingManager;
///
/// \brief Local map rendering
///
class LocalMap
{
public:
LocalMap(OEngine::Render::OgreRenderer*, MWWorld::Environment* env);
LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering, MWWorld::Environment* env);
~LocalMap();
/**
@ -44,9 +46,9 @@ namespace MWRender
* @remarks This is used to draw a "fog of war" effect
* to hide areas on the map the player has not discovered yet.
* @param position (OGRE coordinates)
* @param view direction (OGRE coordinates)
* @param camera orientation (OGRE coordinates)
*/
void updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction);
void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation);
/**
* Save the fog of war for the current cell to disk.
@ -58,6 +60,7 @@ namespace MWRender
private:
OEngine::Render::OgreRenderer* mRendering;
MWRender::RenderingManager* mRenderingManager;
MWWorld::Environment* mEnvironment;
// 1024*1024 pixels for a cell
@ -73,6 +76,12 @@ namespace MWRender
static const int sSize = 8192;
Ogre::Camera* mCellCamera;
Ogre::SceneNode* mCameraNode;
Ogre::SceneNode* mCameraPosNode;
Ogre::SceneNode* mCameraRotNode;
float mAngle;
const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle);
void render(const float x, const float y,
const float zlow, const float zhigh,

@ -3,6 +3,7 @@
#include <OgreSceneNode.h>
#include <components/nifogre/ogre_nif_loader.hpp>
#include <components/settings/settings.hpp>
using namespace MWRender;
@ -88,18 +89,16 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
NifOgre::NIFLoader::load(mesh);
Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh);
/*
Ogre::Vector3 extents = ent->getBoundingBox().getSize();
extents *= insert->getScale();
// float size = std::max(std::max(extents.x, extents.y), extents.z);
float size = std::max(std::max(extents.x, extents.y), extents.z);
bool small = (size < 250); /// \todo config value
bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Objects");
// do not fade out doors. that will cause holes and look stupid
if (ptr.getTypeName().find("Door") != std::string::npos)
small = false;
*/
const bool small = false;
if (mBounds.find(ptr.getCell()) == mBounds.end())
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
@ -113,11 +112,11 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
bounds.scale(insert->getScale());
mBounds[ptr.getCell()].merge(bounds);
if(!mIsStatic)
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects"))
{
insert->attachObject(ent);
ent->setRenderingDistance(small ? 2500 : 0); /// \todo config value
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); /// \todo config value
}
else
{
@ -131,7 +130,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
mStaticGeometrySmall[ptr.getCell()] = sg;
sg->setRenderingDistance(2500); /// \todo config value
sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); /// \todo config value
}
else
sg = mStaticGeometrySmall[ptr.getCell()];
@ -169,6 +168,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
assert(insert);
Ogre::Light *light = mRenderer.getScene()->createLight();
light->setDiffuseColour (r, g, b);
mLights.push_back(light->getName());
float cval=0.0f, lval=0.0f, qval=0.0f;
@ -274,3 +274,34 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
{
return mBounds[cell];
}
void Objects::enableLights()
{
std::vector<std::string>::iterator it = mLights.begin();
while (it != mLights.end())
{
if (mMwRoot->getCreator()->hasLight(*it))
{
mMwRoot->getCreator()->getLight(*it)->setVisible(true);
++it;
}
else
it = mLights.erase(it);
}
}
void Objects::disableLights()
{
std::vector<std::string>::iterator it = mLights.begin();
while (it != mLights.end())
{
if (mMwRoot->getCreator()->hasLight(*it))
{
mMwRoot->getCreator()->getLight(*it)->setVisible(false);
++it;
}
else
it = mLights.erase(it);
}
}

@ -16,6 +16,7 @@ class Objects{
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometrySmall;
std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
std::vector<std::string> mLights;
Ogre::SceneNode* mMwRoot;
bool mIsStatic;
static int uniqueID;
@ -44,6 +45,9 @@ public:
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius);
void enableLights();
void disableLights();
Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
///< get a bounding box that encloses all objects in the specified cell

@ -5,14 +5,17 @@
#include <OgreBillboardSet.h>
#include <OgreHardwareOcclusionQuery.h>
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreMaterialManager.h>
using namespace MWRender;
using namespace Ogre;
OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) :
mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0),
mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false),
mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false)
mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false),
mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false),
mBBNode(0)
{
mRendering = renderer;
mSunNode = sunNode;
@ -52,7 +55,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
matQueryVisible->setCullingMode(CULL_NONE);
matQueryVisible->setManualCullingMode(MANUAL_CULL_NONE);
mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode();
if (sunNode)
mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode();
mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
@ -82,7 +86,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
mRendering->getScene()->addRenderObjectListener(this);
mRendering->getScene()->addRenderQueueListener(this);
mDoQuery = true;
mDoQuery2 = true;
}
OcclusionQuery::~OcclusionQuery()
@ -98,7 +101,7 @@ bool OcclusionQuery::supported()
return mSupported;
}
void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source,
void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source,
const LightList* pLightList, bool suppressRenderStateChanges)
{
// The following code activates and deactivates the occlusion queries
@ -132,7 +135,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass
mActiveQuery = mSingleObjectQuery;
mObjectWasVisible = true;
}
if (mActiveQuery != NULL)
mActiveQuery->beginOcclusionQuery();
}
@ -182,15 +185,17 @@ void OcclusionQuery::update(float duration)
if (dist==0) dist = 10000000;
dist -= 1000; // bias
dist /= 1000.f;
mBBNode->setPosition(mSunNode->getPosition() * dist);
mBBNode->setScale(dist, dist, dist);
mBBNodeReal->setPosition(mBBNode->_getDerivedPosition());
mBBNodeReal->setScale(mBBNode->getScale());
if (mBBNode)
{
mBBNode->setPosition(mSunNode->getPosition() * dist);
mBBNode->setScale(dist, dist, dist);
mBBNodeReal->setPosition(mBBNode->_getDerivedPosition());
mBBNodeReal->setScale(mBBNode->getScale());
}
// Stop occlusion queries until we get their information
// (may not happen on the same frame they are requested in)
mDoQuery = false;
mDoQuery2 = false;
if (!mSunTotalAreaQuery->isStillOutstanding()
&& !mSunVisibleAreaQuery->isStillOutstanding()
@ -245,6 +250,13 @@ bool OcclusionQuery::occlusionTestPending()
return (mQuerySingleObjectRequested || mQuerySingleObjectStarted);
}
void OcclusionQuery::setSunNode(Ogre::SceneNode* node)
{
mSunNode = node;
if (!mBBNode)
mBBNode = node->getParentSceneNode()->createChildSceneNode();
}
bool OcclusionQuery::getTestResult()
{
assert( !occlusionTestPending()
@ -252,3 +264,40 @@ bool OcclusionQuery::getTestResult()
return mTestResult;
}
bool OcclusionQuery::isPotentialOccluder(Ogre::SceneNode* node)
{
bool result = false;
for (unsigned int i=0; i < node->numAttachedObjects(); ++i)
{
MovableObject* ob = node->getAttachedObject(i);
std::string type = ob->getMovableType();
if (type == "Entity")
{
Entity* ent = static_cast<Entity*>(ob);
for (unsigned int j=0; j < ent->getNumSubEntities(); ++j)
{
// if any sub entity has a material with depth write off,
// consider the object as not an occluder
MaterialPtr mat = ent->getSubEntity(j)->getMaterial();
Material::TechniqueIterator techIt = mat->getTechniqueIterator();
while (techIt.hasMoreElements())
{
Technique* tech = techIt.getNext();
Technique::PassIterator passIt = tech->getPassIterator();
while (passIt.hasMoreElements())
{
Pass* pass = passIt.getNext();
if (pass->getDepthWriteEnabled() == false)
return false;
else
result = true;
}
}
}
}
}
return result;
}

@ -46,6 +46,14 @@ namespace MWRender
*/
bool occlusionTestPending();
/**
* Checks if the objects held by this scenenode
* can be considered as potential occluders
* (which might not be the case when transparency is involved)
* @param Scene node
*/
bool isPotentialOccluder(Ogre::SceneNode* node);
/**
* @return true if the object tested in the last request was occluded
*/
@ -53,6 +61,8 @@ namespace MWRender
float getSunVisibility() const {return mSunVisibility;};
void setSunNode(Ogre::SceneNode* node);
private:
Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery;
Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery;

@ -12,6 +12,7 @@
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
#include "../mwworld/ptr.hpp"
#include <components/esm/loadstat.hpp>
#include <components/settings/settings.hpp>
using namespace MWRender;
@ -20,9 +21,9 @@ using namespace Ogre;
namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0)
{
mRendering.createScene("PlayerCam", 55, 5);
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
mTerrainManager = new TerrainManager(mRendering.getScene(),
environment);
@ -31,7 +32,17 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
configureFog(1, ColourValue(1,1,1));
// Set default mipmap level (NB some APIs ignore this)
TextureManager::getSingleton().setDefaultNumMipmaps(5);
TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
// Set default texture filtering options
TextureFilterOptions tfo;
std::string filter = Settings::Manager::getString("texture filtering", "General");
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
else if (filter == "trilinear") tfo = TFO_TRILINEAR;
else /* if (filter == "bilinear") */ tfo = TFO_BILINEAR;
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy(Settings::Manager::getInt("anisotropy", "General"));
// Load resources
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
@ -52,7 +63,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode();
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
cameraPitchNode->attachObject(mRendering.getCamera());
//mSkyManager = 0;
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
@ -63,7 +74,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0;
mLocalMap = new MWRender::LocalMap(&mRendering, &environment);
mDebugging = new Debugging(mMwRoot, environment, engine);
mLocalMap = new MWRender::LocalMap(&mRendering, this, &environment);
}
RenderingManager::~RenderingManager ()
@ -71,6 +83,7 @@ RenderingManager::~RenderingManager ()
//TODO: destroy mSun?
delete mPlayer;
delete mSkyManager;
delete mDebugging;
delete mTerrainManager;
delete mLocalMap;
delete mOcclusionQuery;
@ -101,6 +114,7 @@ void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
{
mObjects.removeCell(store);
mActors.removeCell(store);
mDebugging->cellRemoved(store);
if (store->cell->isExterior())
mTerrainManager->cellRemoved(store);
}
@ -122,6 +136,7 @@ void RenderingManager::toggleWater()
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
{
mObjects.buildStaticGeometry (*store);
mDebugging->cellAdded(store);
if (store->cell->isExterior())
mTerrainManager->cellAdded(store);
}
@ -173,7 +188,7 @@ void RenderingManager::update (float duration){
mRendering.update(duration);
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
checkUnderwater();
}
@ -188,7 +203,7 @@ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
}
else
removeWater();
}
void RenderingManager::setWaterHeight(const float height)
@ -201,6 +216,8 @@ void RenderingManager::skyEnable ()
{
if(mSkyManager)
mSkyManager->enable();
mOcclusionQuery->setSunNode(mSkyManager->getSunNode());
}
void RenderingManager::skyDisable ()
@ -224,7 +241,7 @@ void RenderingManager::skySetDate (int day, int month)
int RenderingManager::skyGetMasserPhase() const
{
return mSkyManager->getMasserPhase();
}
@ -240,8 +257,8 @@ void RenderingManager::skySetMoonColour (bool red){
bool RenderingManager::toggleRenderMode(int mode)
{
if (mode == MWWorld::World::Render_CollisionDebug)
return mDebugging.toggleRenderMode(mode);
if (mode != MWWorld::World::Render_Wireframe)
return mDebugging->toggleRenderMode(mode);
else // if (mode == MWWorld::World::Render_Wireframe)
{
if (mRendering.getCamera()->getPolygonMode() == PM_SOLID)
@ -266,19 +283,15 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
}
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
{
/// \todo make the viewing distance and fog start/end configurable
{
float max = Settings::Manager::getFloat("max viewing distance", "Viewing distance");
// right now we load 3x3 cells, so the maximum viewing distance we
// can allow (to prevent objects suddenly popping up) equals:
// 8192 * 0.69
// ^ cell size ^ minimum density value used (clear weather)
float low = 5652.48 / density / 2.f;
float high = 5652.48 / density;
float low = max / (density) * Settings::Manager::getFloat("fog start factor", "Viewing distance");
float high = max / (density) * Settings::Manager::getFloat("fog end factor", "Viewing distance");
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);
mRendering.getCamera()->setFarClipDistance ( high );
mRendering.getCamera()->setFarClipDistance ( max / density );
mRendering.getViewport()->setBackgroundColour (colour);
}
@ -380,10 +393,10 @@ void RenderingManager::sunDisable()
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
{
// direction * -1 (because 'direction' is camera to sun vector and not sun to camera),
// direction * -1 (because 'direction' is camera to sun vector and not sun to camera),
// then convert from MW to ogre coordinates (swap y,z and make y negative)
if (mSun) mSun->setDirection(Vector3(-direction.x, -direction.z, direction.y));
mSkyManager->setSunDirection(direction);
}
@ -405,4 +418,14 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
mLocalMap->saveFogOfWar(cell);
}
void RenderingManager::disableLights()
{
mObjects.disableLights();
}
void RenderingManager::enableLights()
{
mObjects.enableLights();
}
} // namespace

@ -109,6 +109,9 @@ class RenderingManager: private RenderingInterface {
void sunEnable();
void sunDisable();
void disableLights();
void enableLights();
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
@ -174,7 +177,8 @@ class RenderingManager: private RenderingInterface {
OEngine::Physic::PhysicEngine* mPhysicsEngine;
MWRender::Player *mPlayer;
MWRender::Debugging mDebugging;
MWRender::Debugging *mDebugging;
MWRender::LocalMap* mLocalMap;
};

@ -325,14 +325,17 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environmen
, mSunEnabled(true)
, mMasserEnabled(true)
, mSecundaEnabled(true)
, mCreated(false)
{
mViewport = pCamera->getViewport();
mSceneMgr = pMwRoot->getCreator();
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates
mRootNode->setInheritOrientation(false);
}
void SkyManager::create()
{
/// \todo preload all the textures and meshes that are used for sky rendering
// Create overlay used for thunderstorm
@ -533,7 +536,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environmen
" uniform float4 emissive \n"
") \n"
"{ \n"
" uv += float2(1,0) * time * speed * 0.003; \n" // Scroll in x direction
" uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
"}";
@ -562,6 +565,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environmen
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
mCreated = true;
}
SkyManager::~SkyManager()
@ -574,11 +579,13 @@ SkyManager::~SkyManager()
int SkyManager::getMasserPhase() const
{
if (!mCreated) return 0;
return mMasser->getPhaseInt();
}
int SkyManager::getSecundaPhase() const
{
if (!mCreated) return 0;
return mSecunda->getPhaseInt();
}
@ -631,6 +638,9 @@ void SkyManager::update(float duration)
void SkyManager::enable()
{
if (!mCreated)
create();
mRootNode->setVisible(true);
mEnabled = true;
}
@ -654,6 +664,7 @@ void SkyManager::setCloudsOpacity(float opacity)
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
{
if (!mCreated) return;
if (mClouds != weather.mCloudTexture)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture);
@ -735,6 +746,7 @@ void SkyManager::setGlare(const float glare)
Vector3 SkyManager::getRealSunPos()
{
if (!mCreated) return Vector3(0,0,0);
return mSun->getNode()->_getDerivedPosition();
}
@ -750,17 +762,20 @@ void SkyManager::sunDisable()
void SkyManager::setSunDirection(const Vector3& direction)
{
if (!mCreated) return;
mSun->setPosition(direction);
mSunGlare->setPosition(direction);
}
void SkyManager::setMasserDirection(const Vector3& direction)
{
if (!mCreated) return;
mMasser->setPosition(direction);
}
void SkyManager::setSecundaDirection(const Vector3& direction)
{
if (!mCreated) return;
mSecunda->setPosition(direction);
}
@ -786,6 +801,7 @@ void SkyManager::secundaDisable()
void SkyManager::setThunder(const float factor)
{
if (!mCreated) return;
if (factor > 0.f)
{
mThunderOverlay->show();
@ -818,5 +834,6 @@ void SkyManager::setDate(int day, int month)
Ogre::SceneNode* SkyManager::getSunNode()
{
if (!mCreated) return 0;
return mSun->getNode();
}

@ -112,6 +112,9 @@ namespace MWRender
void update(float duration);
void create();
///< no need to call this, automatically done on first enable()
void enable();
void disable();
@ -164,8 +167,10 @@ namespace MWRender
void setGlare(const float glare);
Ogre::Vector3 getRealSunPos();
private:
bool mCreated;
MWWorld::Environment* mEnvironment;
float mHour;
int mDay;

@ -98,7 +98,10 @@ namespace MWRender
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
if ( land != NULL )
{
land->loadData();
if (!land->dataLoaded)
{
land->loadData();
}
}
//split the cell terrain into four segments
@ -420,7 +423,11 @@ namespace MWRender
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
if ( land != NULL )
{
land->loadData();
if (!land->dataLoaded)
{
land->loadData();
}
return land->landData
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
}

@ -36,7 +36,7 @@ THE SOFTWARE.
#include "OgreHardwarePixelBuffer.h"
#include "OgreShadowCameraSetupPSSM.h"
#define POINTLIGHTS
#include <components/settings/settings.hpp>
namespace Ogre
{
@ -220,22 +220,10 @@ namespace Ogre
}
int TerrainMaterialGeneratorB::SM2Profile::getNumberOfLightsSupported() const
{
#ifndef POINTLIGHTS
return 1;
#else
// number of supported lights depends on the number of available constant registers,
// which in turn depends on the shader profile used
if (GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0")
|| GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0")
|| GpuProgramManager::getSingleton().isSyntaxSupported("fp40")
)
return 32;
else
return 8;
#endif
}
int TerrainMaterialGeneratorB::SM2Profile::getNumberOfLightsSupported() const
{
return Settings::Manager::getInt("num lights", "Terrain");
}
//---------------------------------------------------------------------
MaterialPtr TerrainMaterialGeneratorB::SM2Profile::generate(const Terrain* terrain)
{
@ -565,7 +553,8 @@ namespace Ogre
{
params->setNamedAutoConstant("lightPosObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
params->setNamedAutoConstant("lightDiffuseColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
params->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
if (prof->getNumberOfLightsSupported() > 1)
params->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
//params->setNamedAutoConstant("lightSpecularColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, i);
}
@ -980,10 +969,9 @@ namespace Ogre
//"uniform float3 lightSpecularColour"<<i<<",\n"
;
#ifdef POINTLIGHTS
outStream <<
"uniform float4 lightAttenuation"<<i<<",\n";
#endif
if (prof->getNumberOfLightsSupported() > 1)
outStream <<
"uniform float4 lightAttenuation"<<i<<",\n";
}
@ -1130,10 +1118,9 @@ namespace Ogre
}
else
{
#ifdef POINTLIGHTS
outStream << "float d; \n"
if (prof->getNumberOfLightsSupported() > 1)
outStream << "float d; \n"
"float attn; \n";
#endif
outStream <<
" eyeDir = normalize(eyeDir); \n";
@ -1144,13 +1131,12 @@ namespace Ogre
outStream << " float3 halfAngle"<<i<<" = normalize(lightDir"<<i<<" + eyeDir);\n"
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normal), dot(halfAngle"<<i<<", normal), scaleBiasSpecular.z);\n";
#ifdef POINTLIGHTS
if (prof->getNumberOfLightsSupported() > 1)
outStream <<
// pre-multiply light color with attenuation factor
"d = length( lightDir"<<i<<" ); \n"
"attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
"lightDiffuseColour"<<i<<" *= attn; \n";
#endif
}
}
}

@ -127,4 +127,6 @@ op 0x2000141: GetWaterLevel
op 0x2000142: SetWaterLevel
op 0x2000143: ModWaterLevel
op 0x2000144: ToggleWater, twa
opcodes 0x2000145-0x3ffffff unused
op 0x2000145: ToggleFogOfWar (tfow)
op 0x2000146: TogglePathgrid
opcodes 0x2000147-0x3ffffff unused

@ -67,6 +67,19 @@ namespace MWScript
}
};
class OpToggleFogOfWar : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
context.getEnvironment().mWindowManager->toggleFogOfWar();
}
};
const int opcodeEnableBirthMenu = 0x200000e;
const int opcodeEnableClassMenu = 0x200000f;
const int opcodeEnableNameMenu = 0x2000010;
@ -79,6 +92,7 @@ namespace MWScript
const int opcodeEnableRest = 0x2000017;
const int opcodeShowRestMenu = 0x2000018;
const int opcodeGetButtonPressed = 0x2000137;
const int opcodeToggleFogOfWar = 0x2000145;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -100,6 +114,9 @@ namespace MWScript
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu);
extensions.registerFunction ("getbuttonpressed", 'l', "", opcodeGetButtonPressed);
extensions.registerInstruction ("togglefogofwar", "", opcodeToggleFogOfWar);
extensions.registerInstruction ("tfow", "", opcodeToggleFogOfWar);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -135,6 +152,8 @@ namespace MWScript
new OpShowDialogue (MWGui::GM_Rest));
interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed);
interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar);
}
}
}

@ -106,7 +106,7 @@ namespace MWScript
"Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
}
};
class OpToggleWireframe : public Interpreter::Opcode0
{
public:
@ -123,7 +123,23 @@ namespace MWScript
"Wireframe Rendering -> On" : "Wireframe Rendering -> Off");
}
};
class OpTogglePathgrid : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
bool enabled =
context.getWorld().toggleRenderMode (MWWorld::World::Render_Pathgrid);
context.report (enabled ?
"Path Grid rendering -> On" : "Path Grid Rendering -> Off");
}
};
class OpFadeIn : public Interpreter::Opcode0
{
public:
@ -135,11 +151,11 @@ namespace MWScript
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeIn(time);
}
};
class OpFadeOut : public Interpreter::Opcode0
{
public:
@ -151,11 +167,11 @@ namespace MWScript
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeOut(time);
}
};
class OpFadeTo : public Interpreter::Opcode0
{
public:
@ -167,10 +183,10 @@ namespace MWScript
Interpreter::Type_Float alpha = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeTo(alpha, time);
}
};
@ -201,6 +217,7 @@ namespace MWScript
const int opcodeFadeOut = 0x200013d;
const int opcodeFadeTo = 0x200013e;
const int opcodeToggleWater = 0x2000144;
const int opcodeTogglePathgrid = 0x2000146;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -220,6 +237,8 @@ namespace MWScript
extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
extensions.registerInstruction ("togglewater", "", opcodeToggleWater);
extensions.registerInstruction ("twa", "", opcodeToggleWater);
extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -236,6 +255,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn);
interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut);
interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid);
interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
}
}

@ -0,0 +1,122 @@
#ifdef OPENMW_USE_AUDIERE
#include <stdexcept>
#include <iostream>
#include "audiere_decoder.hpp"
static void fail(const std::string &msg)
{ throw std::runtime_error("Audiere exception: "+msg); }
namespace MWSound
{
class OgreFile : public audiere::File
{
Ogre::DataStreamPtr mStream;
ADR_METHOD(int) read(void* buffer, int size)
{
return mStream->read(buffer, size);
}
ADR_METHOD(bool) seek(int position, SeekMode mode)
{
if(mode == CURRENT)
mStream->seek(mStream->tell()+position);
else if(mode == BEGIN)
mStream->seek(position);
else if(mode == END)
mStream->seek(mStream->size()+position);
else
return false;
return true;
}
ADR_METHOD(int) tell()
{
return mStream->tell();
}
size_t refs;
virtual void ref() { ++refs; }
virtual void unref()
{
if(--refs == 0)
delete this;
}
public:
OgreFile(const Ogre::DataStreamPtr &stream)
: mStream(stream), refs(1)
{ }
virtual ~OgreFile() { }
};
void Audiere_Decoder::open(const std::string &fname)
{
close();
audiere::FilePtr file(new OgreFile(mResourceMgr.openResource(fname)));
mSoundSource = audiere::OpenSampleSource(file);
int channels, srate;
audiere::SampleFormat format;
mSoundSource->getFormat(channels, srate, format);
if(format == audiere::SF_S16)
mSampleType = SampleType_Int16;
else if(format == audiere::SF_U8)
mSampleType = SampleType_UInt8;
else
fail("Unsupported sample type");
if(channels == 1)
mChannelConfig = ChannelConfig_Mono;
else if(channels == 2)
mChannelConfig = ChannelConfig_Stereo;
else
fail("Unsupported channel count");
mSampleRate = srate;
}
void Audiere_Decoder::close()
{
mSoundSource = NULL;
}
void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
{
*samplerate = mSampleRate;
*chans = mChannelConfig;
*type = mSampleType;
}
size_t Audiere_Decoder::read(char *buffer, size_t bytes)
{
int size = bytesToFrames(bytes, mChannelConfig, mSampleType);
size = mSoundSource->read(size, buffer);
return framesToBytes(size, mChannelConfig, mSampleType);
}
void Audiere_Decoder::rewind()
{
mSoundSource->reset();
}
Audiere_Decoder::Audiere_Decoder()
{
}
Audiere_Decoder::~Audiere_Decoder()
{
close();
}
}
#endif

@ -0,0 +1,42 @@
#ifndef GAME_SOUND_AUDIERE_DECODER_H
#define GAME_SOUND_AUDIERE_DECODER_H
#include <OgreDataStream.h>
#include "audiere.h"
#include "sound_decoder.hpp"
namespace MWSound
{
class Audiere_Decoder : public Sound_Decoder
{
audiere::SampleSourcePtr mSoundSource;
int mSampleRate;
SampleType mSampleType;
ChannelConfig mChannelConfig;
virtual void open(const std::string &fname);
virtual void close();
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes);
virtual void rewind();
Audiere_Decoder& operator=(const Audiere_Decoder &rhs);
Audiere_Decoder(const Audiere_Decoder &rhs);
Audiere_Decoder();
public:
virtual ~Audiere_Decoder();
friend class SoundManager;
};
#ifndef DEFAULT_DECODER
#define DEFAULT_DECODER (::MWSound::Audiere_Decoder)
#endif
};
#endif

@ -508,6 +508,8 @@ void OpenAL_Output::init(const std::string &devname)
}
if(mFreeSources.empty())
fail("Could not allocate any sources");
mInitialized = true;
}
void OpenAL_Output::deinit()
@ -535,6 +537,8 @@ void OpenAL_Output::deinit()
if(mDevice)
alcCloseDevice(mDevice);
mDevice = 0;
mInitialized = false;
}

@ -35,15 +35,19 @@ namespace MWSound
Sound_Output(const Sound_Output &rhs);
protected:
bool mInitialized;
Ogre::Vector3 mPos;
Sound_Output(SoundManager &mgr)
: mManager(mgr)
, mInitialized(false)
, mPos(0.0f, 0.0f, 0.0f)
{ }
public:
virtual ~Sound_Output() { }
bool isInitialized() { return mInitialized; }
friend class OpenAL_Output;
friend class SoundManager;
};

@ -18,8 +18,8 @@
#include "openal_output.hpp"
#define SOUND_OUT "OpenAL"
/* Set up the sound manager to use FFMPEG or MPG123+libsndfile for input. The
* OPENMW_USE_x macros are set in CMakeLists.txt.
/* Set up the sound manager to use FFMPEG, MPG123+libsndfile, or Audiere for
* input. The OPENMW_USE_x macros are set in CMakeLists.txt.
*/
#ifdef OPENMW_USE_FFMPEG
#include "ffmpeg_decoder.hpp"
@ -28,6 +28,13 @@
#endif
#endif
#ifdef OPENMW_USE_AUDIERE
#include "audiere_decoder.hpp"
#ifndef SOUND_IN
#define SOUND_IN "Audiere"
#endif
#endif
#ifdef OPENMW_USE_MPG123
#include "mpgsnd_decoder.hpp"
#ifndef SOUND_IN
@ -129,6 +136,8 @@ namespace MWSound
void SoundManager::streamMusicFull(const std::string& filename)
{
if(!mOutput->isInitialized())
return;
std::cout <<"Playing "<<filename<< std::endl;
try
{
@ -173,6 +182,8 @@ namespace MWSound
void SoundManager::say(MWWorld::Ptr ptr, const std::string& filename)
{
if(!mOutput->isInitialized())
return;
try
{
// The range values are not tested
@ -203,6 +214,8 @@ namespace MWSound
SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode)
{
SoundPtr sound;
if(!mOutput->isInitialized())
return sound;
try
{
float basevol = 1.0f; /* TODO: volume settings */
@ -230,6 +243,8 @@ namespace MWSound
float volume, float pitch, int mode)
{
SoundPtr sound;
if(!mOutput->isInitialized())
return sound;
try
{
// Look up the sound in the ESM data
@ -407,7 +422,7 @@ namespace MWSound
if(!isMusicPlaying())
startRandomTitle();
MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell();
const ESM::Cell *cell = mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell;
Ogre::Camera *cam = mEnvironment.mWorld->getPlayer().getRenderer()->getCamera();
Ogre::Vector3 nPos, nDir, nUp;
nPos = cam->getRealPosition();
@ -415,7 +430,7 @@ namespace MWSound
nUp = cam->getRealUp();
Environment env = Env_Normal;
if(nPos.y < current->cell->water)
if((cell->data.flags&cell->HasWater) && nPos.y < cell->water)
env = Env_Underwater;
// The output handler is expecting vectors oriented like the game
@ -443,6 +458,8 @@ namespace MWSound
void SoundManager::update(float duration)
{
if(!mOutput->isInitialized())
return;
updateSounds(duration);
updateRegionSound(duration);
}

@ -34,7 +34,7 @@ const float WeatherGlobals::mThunderFrequency = .4;
const float WeatherGlobals::mThunderThreshold = 0.6;
const float WeatherGlobals::mThunderSoundDelay = 0.25;
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environment* env) :
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::Environment* env) :
mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0),
mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0)
{

@ -146,16 +146,36 @@ namespace MWWorld
mRendering->skySetDate (mGlobalVariables->getInt ("day"),
mGlobalVariables->getInt ("month"));
mRendering->getSkyManager()->enable();
mRendering->skyEnable();
}
else
mRendering->getSkyManager()->disable();
mRendering->skyDisable();
}
void World::setFallbackValues(std::map<std::string,std::string> fallbackMap)
{
mFallback = fallbackMap;
}
std::string World::getFallback(std::string key)
{
return getFallback(key, "");
}
std::string World::getFallback(std::string key, std::string def)
{
std::map<std::string,std::string>::iterator it;
if((it = mFallback.find(key)) == mFallback.end())
{
return def;
}
return it->second;
}
World::World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment, const std::string& encoding)
bool newGame, Environment& environment, const std::string& encoding, std::map<std::string,std::string> fallbackMap)
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this),
mNumFacing(0)
@ -191,6 +211,8 @@ namespace MWWorld
mWorldScene = new Scene(environment, this, *mRendering, mPhysics);
setFallbackValues(fallbackMap);
}
@ -543,7 +565,7 @@ namespace MWWorld
if (ptr==mPlayer->getPlayer())
{
//std::cout << "X:" << ptr.getRefData().getPosition().pos[0] << " Z: " << ptr.getRefData().getPosition().pos[1] << "\n";
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
if (currentCell)
{
@ -750,15 +772,16 @@ namespace MWWorld
// figure out which object we want to test against
std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects();
// ignore the player
for (std::vector < std::pair < float, std::string > >::iterator it = results.begin();
it != results.end(); ++it)
// ignore the player and other things we're not interested in
std::vector < std::pair < float, std::string > >::iterator it = results.begin();
while (it != results.end())
{
if ( (*it).second == mPlayer->getPlayer().getRefData().getHandle() )
if ( getPtrViaHandle((*it).second) == mPlayer->getPlayer() )
{
results.erase(it);
break;
it = results.erase(it);
}
else
++it;
}
if (results.size() == 0)
@ -774,6 +797,10 @@ namespace MWWorld
btVector3 p = mPhysics->getRayPoint(results.front().first);
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode();
//std::cout << "Num facing 1 : " << mFaced1Name << std::endl;
//std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl;
query->occlusionTest(pos, node);
}
else
@ -786,8 +813,33 @@ namespace MWWorld
btVector3 p = mPhysics->getRayPoint(results[1].first);
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
Ogre::SceneNode* node = mFaced2.getRefData().getBaseNode();
query->occlusionTest(pos, node);
Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode();
Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode();
// no need to test if the first node is not occluder
if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos))
{
mFacedHandle = mFaced1Name;
//std::cout << "node1 Not an occluder" << std::endl;
return;
}
// no need to test if the second object is static (thus cannot be activated)
if (mFaced2.getTypeName().find("Static") != std::string::npos)
{
mFacedHandle = mFaced1Name;
return;
}
// work around door problems
if (mFaced1.getTypeName().find("Static") != std::string::npos
&& mFaced2.getTypeName().find("Door") != std::string::npos)
{
mFacedHandle = mFaced2Name;
return;
}
query->occlusionTest(pos, node2);
}
}
}
@ -834,6 +886,18 @@ namespace MWWorld
return mRendering->getFader();
}
Ogre::Vector2 World::getNorthVector(Ptr::CellStore* cell)
{
ESMS::CellRefList<ESM::Static, MWWorld::RefData> statics = cell->statics;
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData>* ref = statics.find("northmarker");
if (!ref)
return Vector2(0, 1);
Ogre::SceneNode* node = ref->mData.getBaseNode();
Vector3 dir = node->_getDerivedOrientation().yAxis();
Vector2 d = Vector2(dir.x, dir.z);
return d;
}
void World::setWaterHeight(const float height)
{
mRendering->setWaterHeight(height);

@ -63,13 +63,14 @@ namespace MWWorld
enum RenderMode
{
Render_CollisionDebug,
Render_Wireframe
Render_Wireframe,
Render_Pathgrid
};
private:
MWRender::RenderingManager* mRendering;
MWWorld::WeatherManager* mWeatherManager;
MWWorld::Scene *mWorldScene;
@ -99,6 +100,7 @@ namespace MWWorld
std::string mFaced1Name;
std::string mFaced2Name;
int mNumFacing;
std::map<std::string,std::string> mFallback;
int getDaysPerMonth (int month) const;
@ -109,10 +111,10 @@ namespace MWWorld
World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment, const std::string& encoding);
Environment& environment, const std::string& encoding, std::map<std::string,std::string> fallbackMap);
~World();
OEngine::Render::Fader* getFader();
Ptr::CellStore *getExterior (int x, int y);
@ -121,9 +123,15 @@ namespace MWWorld
void setWaterHeight(const float height);
void toggleWater();
void adjustSky();
void setFallbackValues(std::map<std::string,std::string> fallbackMap);
std::string getFallback(std::string key);
std::string getFallback(std::string key, std::string def);
MWWorld::Player& getPlayer();
const ESMS::ESMStore& getStore() const;
@ -134,10 +142,13 @@ namespace MWWorld
bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame?
bool isCellExterior() const;
bool isCellQuasiExterior() const;
Ogre::Vector2 getNorthVector(Ptr::CellStore* cell);
///< get north vector (OGRE coordinates) for given interior cell
Globals::Data& getGlobalVariable (const std::string& name);
Globals::Data getGlobalVariable (const std::string& name) const;
@ -172,9 +183,9 @@ namespace MWWorld
bool toggleSky();
///< \return Resulting mode
void changeWeather(const std::string& region, const unsigned int id);
int getCurrentWeather() const;
int getMasserPhase() const;

@ -82,20 +82,37 @@ findpkg_finish ( "MYGUI" )
ELSE (WIN32) #Unix
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR)
FIND_PACKAGE(PkgConfig)
PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI)
IF (MYGUI_INCLUDE_DIRS)
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
ELSE (MYGUI_INCLUDE_DIRS)
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib)
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
ENDIF (MYGUI_INCLUDE_DIRS)
IF(MYGUI_STATIC)
PKG_SEARCH_MODULE(MYGUI MYGUIStatic MyGUIStatic)
IF (MYGUI_INCLUDE_DIRS)
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
ELSE (MYGUI_INCLUDE_DIRS)
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
FIND_LIBRARY(MYGUI_LIBRARIES myguistatic PATHS /usr/lib /usr/local/lib)
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
ENDIF (MYGUI_INCLUDE_DIRS)
ELSE(MYGUI_STATIC)
PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI)
IF (MYGUI_INCLUDE_DIRS)
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
ELSE (MYGUI_INCLUDE_DIRS)
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib)
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
ENDIF (MYGUI_INCLUDE_DIRS)
ENDIF(MYGUI_STATIC)
ENDIF (WIN32)
#Do some preparation

@ -2,6 +2,10 @@ project (Components)
# source files
add_component_dir (settings
settings
)
add_component_dir (bsa
bsa_archive bsa_file
)

@ -41,21 +41,21 @@ struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
bool operator() (const std::string & s1, const std::string & s2) const {
//case insensitive version of is_less
return lexicographical_compare(s1, s2, boost::algorithm::is_iless());
return boost::ilexicographical_compare(s1, s2);
}
};
struct pathComparer
{
private:
int m_start, m_size;
std::string find;
public:
pathComparer(int start, int size) : m_start(start), m_size(size) { }
pathComparer(const std::string& toFind) : find(toFind) { }
bool operator() (const std::string& first, const std::string& other)
bool operator() (const std::string& other)
{
return lexicographical_compare(first.substr(m_start,m_size), other.substr(m_start,m_size), boost::algorithm::is_iless());
return boost::iequals(find, other);
}
};
@ -71,9 +71,6 @@ class DirArchive: public Ogre::FileSystemArchive
bool findFile(const String& filename, std::string& copy) const
{
if (filename.find(".tga") != std::string::npos)
return false;
{
String passed = filename;
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
@ -116,10 +113,13 @@ class DirArchive: public Ogre::FileSystemArchive
current = found->second;
}
pathComparer comp(delimiter, copy.size() - delimiter-1);
std::vector<std::string>::iterator find = std::lower_bound(current.begin(), current.end(), copy, comp);
if (find != current.end() && !comp(copy, current.front()))
std::vector<std::string>::iterator find = std::lower_bound(current.begin(), current.end(), copy, ciLessBoost());
if (find != current.end() && !ciLessBoost()(copy, current.front()))
{
if (!boost::iequals(copy, *find))
if ((find = std::find_if(current.begin(), current.end(), pathComparer(copy))) == current.end()) //\todo Check if this line is actually needed
return false;
copy = *find;
return true;
}

@ -7,6 +7,7 @@
#include "errorhandler.hpp"
#include "exception.hpp"
#include "scanner.hpp"
namespace Compiler
{
@ -81,6 +82,8 @@ namespace Compiler
{
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected numeric value", loc);
else
scanner.putbackInt (value, loc);
return false;
}
@ -94,6 +97,8 @@ namespace Compiler
{
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected floating point value", loc);
else
scanner.putbackFloat (value, loc);
return false;
}
@ -108,6 +113,8 @@ namespace Compiler
{
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected name", loc);
else
scanner.putbackName (name, loc);
return false;
}
@ -121,6 +128,8 @@ namespace Compiler
{
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected keyword", loc);
else
scanner.putbackKeyword (keyword, loc);
return false;
}
@ -134,6 +143,8 @@ namespace Compiler
{
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected special token", loc);
else
scanner.putbackSpecial (code, loc);
return false;
}

@ -39,11 +39,6 @@ namespace Compiler
mState = CommaState;
return true;
}
else if (code==Scanner::S_newline && mState==StartState)
{
scanner.putbackSpecial (code, loc);
return false;
}
return Parser::parseSpecial (code, loc, scanner);
}

@ -2,6 +2,24 @@
namespace ESM
{
Land::Land()
: flags(0)
, X(0)
, Y(0)
, mEsm(NULL)
, hasData(false)
, dataLoaded(false)
, landData(NULL)
{
}
Land::~Land()
{
delete landData;
}
void Land::load(ESMReader &esm)
{
mEsm = &esm;

@ -11,6 +11,9 @@ namespace ESM
struct Land
{
Land();
~Land();
int flags; // Only first four bits seem to be used, don't know what
// they mean.
int X, Y; // Map coordinates.
@ -77,6 +80,11 @@ struct Land
* Frees memory allocated for land data
*/
void unloadData();
private:
Land(const Land& land);
Land& operator=(const Land& land);
};
}
#endif

@ -457,7 +457,7 @@ namespace ESMS
}
}
Pathgrid *find(int cellX, int cellY, std::string cellName) const
Pathgrid *find(int cellX, int cellY, const std::string &cellName) const
{
Pathgrid *result = search(cellX, cellY, cellName);
if (!result)
@ -467,7 +467,7 @@ namespace ESMS
return result;
}
Pathgrid *search(int cellX, int cellY, std::string cellName) const
Pathgrid *search(int cellX, int cellY, const std::string &cellName) const
{
Pathgrid *result = NULL;
if (cellX == 0 && cellY == 0) // possibly interior

@ -25,6 +25,7 @@
#include "ogre_nif_loader.hpp"
#include <components/settings/settings.hpp>
typedef unsigned char ubyte;
@ -299,138 +300,136 @@ void NIFLoader::createMaterial(const String &name,
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
material->setShininess(glossiness);
// Create shader for the material
// vertex
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
HighLevelGpuProgramPtr vertex;
if (mgr.getByName("main_vp").isNull())
if (Settings::Manager::getBool("shaders", "Objects"))
{
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
vertex->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" float4 normal : NORMAL, \n"
" float4 colour : COLOR, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" out float4 oPositionObjSpace : TEXCOORD1, \n"
" out float4 oNormal : TEXCOORD2, \n"
" out float oFogValue : TEXCOORD3, \n"
" out float4 oVertexColour : TEXCOORD4, \n"
" uniform float4 fogParams, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oVertexColour = colour; \n"
" oUV = uv; \n"
" oNormal = normal; \n"
" oPosition = mul( worldViewProj, position ); \n"
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
" oPositionObjSpace = position; \n"
"}";
vertex->setSource(outStream.str());
vertex->load();
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
}
else
vertex = mgr.getByName("main_vp");
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
// the number of lights to support.
// when rendering an object, OGRE automatically picks the lights that are
// closest to the object being rendered. unfortunately this mechanism does
// not work perfectly for objects batched together (they will all use the same
// lights). to work around this, we are simply pushing the maximum number
// of lights here in order to minimize disappearing lights.
float num_lights;
if (GpuProgramManager::getSingleton().isSyntaxSupported("fp40") ||
GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"))
num_lights = 8 /* 32 */;
else
num_lights = 8;
// Create shader for the material
// vertex
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
// fragment
HighLevelGpuProgramPtr fragment;
if (mgr.getByName("main_fp").isNull())
{
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
fragment->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n"
" uniform sampler2D texture : TEXUNIT0, \n"
" float4 positionObjSpace : TEXCOORD1, \n"
" float4 normal : TEXCOORD2, \n"
" float fogValue : TEXCOORD3, \n"
" float4 vertexColour : TEXCOORD4, \n"
" uniform float4 fogColour, \n";
for (int i=0; i<num_lights; ++i)
HighLevelGpuProgramPtr vertex;
if (mgr.getByName("main_vp").isNull())
{
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
vertex->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
" uniform float4 lightDiffuse"<<i<<", \n"
" uniform float4 lightPositionObjSpace"<<i<<", \n"
" uniform float4 lightAttenuation"<<i<<", \n";
"void main_vp( \n"
" float4 position : POSITION, \n"
" float4 normal : NORMAL, \n"
" float4 colour : COLOR, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" out float4 oPositionObjSpace : TEXCOORD1, \n"
" out float4 oNormal : TEXCOORD2, \n"
" out float oFogValue : TEXCOORD3, \n"
" out float4 oVertexColour : TEXCOORD4, \n"
" uniform float4 fogParams, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oVertexColour = colour; \n"
" oUV = uv; \n"
" oNormal = normal; \n"
" oPosition = mul( worldViewProj, position ); \n"
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
" oPositionObjSpace = position; \n"
"}";
vertex->setSource(outStream.str());
vertex->load();
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
}
outStream <<
" uniform float4 lightAmbient, \n"
" uniform float4 ambient, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" float4 tex = tex2D(texture, uv); \n"
" float d; \n"
" float attn; \n"
" float3 lightColour = float3(0, 0, 0); \n";
for (int i=0; i<num_lights; ++i)
else
vertex = mgr.getByName("main_vp");
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
// the number of lights to support.
// when rendering an object, OGRE automatically picks the lights that are
// closest to the object being rendered. unfortunately this mechanism does
// not work perfectly for objects batched together (they will all use the same
// lights). to work around this, we are simply pushing the maximum number
// of lights here in order to minimize disappearing lights.
int num_lights = Settings::Manager::getInt("num lights", "Objects");
// fragment
HighLevelGpuProgramPtr fragment;
if (mgr.getByName("main_fp").isNull())
{
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
fragment->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n"
" uniform sampler2D texture : TEXUNIT0, \n"
" float4 positionObjSpace : TEXCOORD1, \n"
" float4 normal : TEXCOORD2, \n"
" float fogValue : TEXCOORD3, \n"
" float4 vertexColour : TEXCOORD4, \n"
" uniform float4 fogColour, \n";
for (int i=0; i<num_lights; ++i)
{
outStream <<
" uniform float4 lightDiffuse"<<i<<", \n"
" uniform float4 lightPositionObjSpace"<<i<<", \n"
" uniform float4 lightAttenuation"<<i<<", \n";
}
outStream <<
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
" uniform float4 lightAmbient, \n"
" uniform float4 ambient, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" float4 tex = tex2D(texture, uv); \n"
" float d; \n"
" float attn; \n"
" float3 lightColour = float3(0, 0, 0); \n";
for (int i=0; i<num_lights; ++i)
{
outStream <<
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
// pre-multiply light color with attenuation factor
" d = length( lightDir"<<i<<" ); \n"
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
" lightDiffuse"<<i<<" *= attn; \n"
// pre-multiply light color with attenuation factor
" d = length( lightDir"<<i<<" ); \n"
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
" lightDiffuse"<<i<<" *= attn; \n"
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
}
outStream <<
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
"}";
fragment->setSource(outStream.str());
fragment->load();
for (int i=0; i<num_lights; ++i)
{
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
}
outStream <<
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
"}";
fragment->setSource(outStream.str());
fragment->load();
for (int i=0; i<num_lights; ++i)
{
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
}
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
}
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
else
fragment = mgr.getByName("main_fp");
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
}
else
fragment = mgr.getByName("main_fp");
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
}
// Takes a name and adds a unique part to it. This is just used to

@ -0,0 +1,158 @@
#include "settings.hpp"
#include <fstream>
#include <OgreResourceGroupManager.h>
#include <OgreStringConverter.h>
using namespace Settings;
Ogre::ConfigFile Manager::mFile = Ogre::ConfigFile();
Ogre::ConfigFile Manager::mDefaultFile = Ogre::ConfigFile();
CategorySettingVector Manager::mChangedSettings = CategorySettingVector();
CategorySettingValueMap Manager::mNewSettings = CategorySettingValueMap();
void Manager::loadUser (const std::string& file)
{
mFile.load(file);
}
void Manager::loadDefault (const std::string& file)
{
mDefaultFile.load(file);
}
void Manager::saveUser(const std::string& file)
{
std::fstream fout(file.c_str(), std::ios::out);
Ogre::ConfigFile::SectionIterator seci = mFile.getSectionIterator();
while (seci.hasMoreElements())
{
Ogre::String sectionName = seci.peekNextKey();
if (sectionName.length() > 0)
fout << '\n' << '[' << seci.peekNextKey() << ']' << '\n';
Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
fout << i->first.c_str() << " = " << i->second.c_str() << '\n';
}
CategorySettingValueMap::iterator it = mNewSettings.begin();
while (it != mNewSettings.end())
{
if (it->first.first == sectionName)
{
fout << it->first.second << " = " << it->second << '\n';
mNewSettings.erase(it++);
}
else
++it;
}
}
std::string category = "";
for (CategorySettingValueMap::iterator it = mNewSettings.begin();
it != mNewSettings.end(); ++it)
{
if (category != it->first.first)
{
category = it->first.first;
fout << '\n' << '[' << category << ']' << '\n';
}
fout << it->first.second << " = " << it->second << '\n';
}
}
const std::string Manager::getString (const std::string& setting, const std::string& category)
{
if (mNewSettings.find(std::make_pair(category, setting)) != mNewSettings.end())
return mNewSettings[std::make_pair(category, setting)];
std::string defaultval = mDefaultFile.getSetting(setting, category);
return mFile.getSetting(setting, category, defaultval);
}
const float Manager::getFloat (const std::string& setting, const std::string& category)
{
return Ogre::StringConverter::parseReal( getString(setting, category) );
}
const int Manager::getInt (const std::string& setting, const std::string& category)
{
return Ogre::StringConverter::parseInt( getString(setting, category) );
}
const bool Manager::getBool (const std::string& setting, const std::string& category)
{
return Ogre::StringConverter::parseBool( getString(setting, category) );
}
void Manager::setString (const std::string& setting, const std::string& category, const std::string& value)
{
CategorySetting s = std::make_pair(category, setting);
bool found=false;
try
{
Ogre::ConfigFile::SettingsIterator it = mFile.getSettingsIterator(category);
while (it.hasMoreElements())
{
Ogre::ConfigFile::SettingsMultiMap::iterator i = it.current();
if ((*i).first == setting)
{
if ((*i).second != value)
{
mChangedSettings.push_back(std::make_pair(category, setting));
(*i).second = value;
}
found = true;
}
it.getNext();
}
}
catch (Ogre::Exception&)
{}
if (!found)
{
if (mNewSettings.find(s) != mNewSettings.end())
{
if (mNewSettings[s] != value)
{
mChangedSettings.push_back(std::make_pair(category, setting));
mNewSettings[s] = value;
}
}
else
mNewSettings[s] = value;
}
}
void Manager::setInt (const std::string& setting, const std::string& category, const int value)
{
setString(setting, category, Ogre::StringConverter::toString(value));
}
void Manager::setFloat (const std::string& setting, const std::string& category, const float value)
{
setString(setting, category, Ogre::StringConverter::toString(value));
}
void Manager::setBool (const std::string& setting, const std::string& category, const bool value)
{
setString(setting, category, Ogre::StringConverter::toString(value));
}
const CategorySettingVector Manager::apply()
{
CategorySettingVector vec = mChangedSettings;
mChangedSettings.clear();
return vec;
}

@ -0,0 +1,52 @@
#ifndef _COMPONENTS_SETTINGS_H
#define _COMPONENTS_SETTINGS_H
#include <OgreConfigFile.h>
namespace Settings
{
typedef std::pair < std::string, std::string > CategorySetting;
typedef std::vector< std::pair<std::string, std::string> > CategorySettingVector;
typedef std::map < CategorySetting, std::string > CategorySettingValueMap;
///
/// \brief Settings management (can change during runtime)
///
class Manager
{
public:
static Ogre::ConfigFile mFile;
static Ogre::ConfigFile mDefaultFile;
static CategorySettingVector mChangedSettings;
///< tracks all the settings that were changed since the last apply() call
static CategorySettingValueMap mNewSettings;
///< tracks all the settings that are in the default file, but not in user file yet
void loadDefault (const std::string& file);
///< load file as the default settings (can be overridden by user settings)
void loadUser (const std::string& file);
///< load file as user settings
void saveUser (const std::string& file);
///< save user settings to file
static const CategorySettingVector apply();
///< returns the list of changed settings and then clears it
static const int getInt (const std::string& setting, const std::string& category);
static const float getFloat (const std::string& setting, const std::string& category);
static const std::string getString (const std::string& setting, const std::string& category);
static const bool getBool (const std::string& setting, const std::string& category);
static void setInt (const std::string& setting, const std::string& category, const int value);
static void setFloat (const std::string& setting, const std::string& category, const float value);
static void setString (const std::string& setting, const std::string& category, const std::string& value);
static void setBool (const std::string& setting, const std::string& category, const bool value);
};
}
#endif // _COMPONENTS_SETTINGS_H

@ -12,7 +12,7 @@ void tab() { cout << " "; }
// write one number with a space in front of it and a comma after it
void num(unsigned char i, bool last)
{
cout << " 0x" << (unsigned)i;
cout << " (char)0x" << (unsigned)i;
if(!last) cout << ",";
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,55 @@
[General]
# Camera field of view
field of view = 55
# Texture filtering mode. valid values:
# anisotropic
# bilinear
# trilinear
texture filtering = anisotropic
# Has no effect when texture filtering is not anisotropic
anisotropy = 4
# Number of texture mipmaps to generate
num mipmaps = 5
[HUD]
# FPS counter
# 0: not visible
# 1: basic FPS display
# 2: advanced FPS display (batches, triangles)
fps = 0
[Objects]
shaders = true
# Max. number of lights that affect objects. Setting to 1 will only reflect sunlight
# Note: has no effect when shaders are turned off
num lights = 8
# Use static geometry for static objects. Improves rendering speed.
use static geometry = true
[Viewing distance]
# Limit the rendering distance of small objects
limit small object distance = false
# Size below which an object is considered as small
small object size = 250
# Rendering distance for small objects
small object distance = 3500
# Max viewing distance at clear weather conditions
max viewing distance = 5600
# Distance at which fog starts (proportional to viewing distance)
fog start factor = 0.5
# Distance at which fog ends (proportional to viewing distance)
fog end factor = 1.0
[Terrain]
# Max. number of lights that affect the terrain. Setting to 1 will only reflect sunlight
num lights = 8
Loading…
Cancel
Save