Merge branch 'master' into dialogue
Conflicts: apps/openmw/mwscript/docs/vmformat.txtactorid
commit
4bdfbb6d4f
@ -1,10 +0,0 @@
|
|||||||
package "esmtool"
|
|
||||||
version "1.0"
|
|
||||||
purpose "Inspect and extract from Morrowind ES files (ESM, ESP, ESS)"
|
|
||||||
args "--unamed-opts=ES-FILE -F esmtool_cmd -G"
|
|
||||||
|
|
||||||
option "raw" r "Show an unformattet list of all records and subrecords" optional
|
|
||||||
option "quiet" q "Supress all record information. Useful for speed tests." optional
|
|
||||||
option "loadcells" C "Browse through contents of all cells." optional
|
|
||||||
|
|
||||||
text "\nIf no option is given, the default action is to parse all records in the archive and display diagnostic information."
|
|
File diff suppressed because it is too large
Load Diff
@ -1,179 +0,0 @@
|
|||||||
/** @file esmtool_cmd.h
|
|
||||||
* @brief The header file for the command line option parser
|
|
||||||
* generated by GNU Gengetopt version 2.22.2
|
|
||||||
* http://www.gnu.org/software/gengetopt.
|
|
||||||
* DO NOT modify this file, since it can be overwritten
|
|
||||||
* @author GNU Gengetopt by Lorenzo Bettini */
|
|
||||||
|
|
||||||
#ifndef ESMTOOL_CMD_H
|
|
||||||
#define ESMTOOL_CMD_H
|
|
||||||
|
|
||||||
/* If we use autoconf. */
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h> /* for FILE */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#ifndef CMDLINE_PARSER_PACKAGE
|
|
||||||
/** @brief the program name (used for printing errors) */
|
|
||||||
#define CMDLINE_PARSER_PACKAGE "esmtool"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CMDLINE_PARSER_PACKAGE_NAME
|
|
||||||
/** @brief the complete program name (used for help and version) */
|
|
||||||
#define CMDLINE_PARSER_PACKAGE_NAME "esmtool"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CMDLINE_PARSER_VERSION
|
|
||||||
/** @brief the program version */
|
|
||||||
#define CMDLINE_PARSER_VERSION "1.0"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @brief Where the command line options are stored */
|
|
||||||
struct gengetopt_args_info
|
|
||||||
{
|
|
||||||
const char *help_help; /**< @brief Print help and exit help description. */
|
|
||||||
const char *version_help; /**< @brief Print version and exit help description. */
|
|
||||||
const char *raw_help; /**< @brief Show an unformattet list of all records and subrecords help description. */
|
|
||||||
const char *quiet_help; /**< @brief Supress all record information. Useful for speed tests. help description. */
|
|
||||||
const char *loadcells_help; /**< @brief Browse through contents of all cells. help description. */
|
|
||||||
|
|
||||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
|
||||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
|
||||||
unsigned int raw_given ; /**< @brief Whether raw was given. */
|
|
||||||
unsigned int quiet_given ; /**< @brief Whether quiet was given. */
|
|
||||||
unsigned int loadcells_given ; /**< @brief Whether loadcells was given. */
|
|
||||||
|
|
||||||
char **inputs ; /**< @brief unamed options (options without names) */
|
|
||||||
unsigned inputs_num ; /**< @brief unamed options number */
|
|
||||||
} ;
|
|
||||||
|
|
||||||
/** @brief The additional parameters to pass to parser functions */
|
|
||||||
struct cmdline_parser_params
|
|
||||||
{
|
|
||||||
int override; /**< @brief whether to override possibly already present options (default 0) */
|
|
||||||
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
|
|
||||||
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
|
|
||||||
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
|
|
||||||
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
|
|
||||||
} ;
|
|
||||||
|
|
||||||
/** @brief the purpose string of the program */
|
|
||||||
extern const char *gengetopt_args_info_purpose;
|
|
||||||
/** @brief the usage string of the program */
|
|
||||||
extern const char *gengetopt_args_info_usage;
|
|
||||||
/** @brief all the lines making the help output */
|
|
||||||
extern const char *gengetopt_args_info_help[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The command line parser
|
|
||||||
* @param argc the number of command line options
|
|
||||||
* @param argv the command line options
|
|
||||||
* @param args_info the structure where option information will be stored
|
|
||||||
* @return 0 if everything went fine, NON 0 if an error took place
|
|
||||||
*/
|
|
||||||
int cmdline_parser (int argc, char * const *argv,
|
|
||||||
struct gengetopt_args_info *args_info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The command line parser (version with additional parameters - deprecated)
|
|
||||||
* @param argc the number of command line options
|
|
||||||
* @param argv the command line options
|
|
||||||
* @param args_info the structure where option information will be stored
|
|
||||||
* @param override whether to override possibly already present options
|
|
||||||
* @param initialize whether to initialize the option structure my_args_info
|
|
||||||
* @param check_required whether to check that all required options were provided
|
|
||||||
* @return 0 if everything went fine, NON 0 if an error took place
|
|
||||||
* @deprecated use cmdline_parser_ext() instead
|
|
||||||
*/
|
|
||||||
int cmdline_parser2 (int argc, char * const *argv,
|
|
||||||
struct gengetopt_args_info *args_info,
|
|
||||||
int override, int initialize, int check_required);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The command line parser (version with additional parameters)
|
|
||||||
* @param argc the number of command line options
|
|
||||||
* @param argv the command line options
|
|
||||||
* @param args_info the structure where option information will be stored
|
|
||||||
* @param params additional parameters for the parser
|
|
||||||
* @return 0 if everything went fine, NON 0 if an error took place
|
|
||||||
*/
|
|
||||||
int cmdline_parser_ext (int argc, char * const *argv,
|
|
||||||
struct gengetopt_args_info *args_info,
|
|
||||||
struct cmdline_parser_params *params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the contents of the option struct into an already open FILE stream.
|
|
||||||
* @param outfile the stream where to dump options
|
|
||||||
* @param args_info the option struct to dump
|
|
||||||
* @return 0 if everything went fine, NON 0 if an error took place
|
|
||||||
*/
|
|
||||||
int cmdline_parser_dump(FILE *outfile,
|
|
||||||
struct gengetopt_args_info *args_info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the contents of the option struct into a (text) file.
|
|
||||||
* This file can be read by the config file parser (if generated by gengetopt)
|
|
||||||
* @param filename the file where to save
|
|
||||||
* @param args_info the option struct to save
|
|
||||||
* @return 0 if everything went fine, NON 0 if an error took place
|
|
||||||
*/
|
|
||||||
int cmdline_parser_file_save(const char *filename,
|
|
||||||
struct gengetopt_args_info *args_info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the help
|
|
||||||
*/
|
|
||||||
void cmdline_parser_print_help(void);
|
|
||||||
/**
|
|
||||||
* Print the version
|
|
||||||
*/
|
|
||||||
void cmdline_parser_print_version(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes all the fields a cmdline_parser_params structure
|
|
||||||
* to their default values
|
|
||||||
* @param params the structure to initialize
|
|
||||||
*/
|
|
||||||
void cmdline_parser_params_init(struct cmdline_parser_params *params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates dynamically a cmdline_parser_params structure and initializes
|
|
||||||
* all its fields to their default values
|
|
||||||
* @return the created and initialized cmdline_parser_params structure
|
|
||||||
*/
|
|
||||||
struct cmdline_parser_params *cmdline_parser_params_create(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the passed gengetopt_args_info structure's fields
|
|
||||||
* (also set default values for options that have a default)
|
|
||||||
* @param args_info the structure to initialize
|
|
||||||
*/
|
|
||||||
void cmdline_parser_init (struct gengetopt_args_info *args_info);
|
|
||||||
/**
|
|
||||||
* Deallocates the string fields of the gengetopt_args_info structure
|
|
||||||
* (but does not deallocate the structure itself)
|
|
||||||
* @param args_info the structure to deallocate
|
|
||||||
*/
|
|
||||||
void cmdline_parser_free (struct gengetopt_args_info *args_info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that all the required options were specified
|
|
||||||
* @param args_info the structure to check
|
|
||||||
* @param prog_name the name of the program that will be used to print
|
|
||||||
* possible errors
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int cmdline_parser_required (struct gengetopt_args_info *args_info,
|
|
||||||
const char *prog_name);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
#endif /* ESMTOOL_CMD_H */
|
|
@ -1,28 +0,0 @@
|
|||||||
#ifndef GAME_MWCLASS_CONTAINERUTIL_H
|
|
||||||
#define GAME_MWCLASS_CONTAINERUTIL_H
|
|
||||||
|
|
||||||
#include <components/esm_store/cell_store.hpp>
|
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
|
||||||
|
|
||||||
namespace MWClass
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
void insertIntoContainerStore (const MWWorld::Ptr& ptr,
|
|
||||||
ESMS::CellRefList<T, MWWorld::RefData>& containerStore)
|
|
||||||
{
|
|
||||||
if (!ptr.isEmpty())
|
|
||||||
{
|
|
||||||
// TODO check stacking
|
|
||||||
|
|
||||||
ESMS::LiveCellRef<T, MWWorld::RefData> cellRef(ptr.getCellRef(), ptr.get<T>()->base);
|
|
||||||
cellRef.mData = ptr.getRefData();
|
|
||||||
|
|
||||||
containerStore.list.push_back (cellRef);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,116 +1,764 @@
|
|||||||
#include "sky.hpp"
|
#include "sky.hpp"
|
||||||
#include "Caelum.h"
|
|
||||||
|
|
||||||
namespace MWRender
|
#include <OgreCamera.h>
|
||||||
|
#include <OgreRenderWindow.h>
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
#include <OgreMesh.h>
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
#include <OgreHardwareVertexBuffer.h>
|
||||||
|
#include <OgreHighLevelGpuProgramManager.h>
|
||||||
|
|
||||||
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
|
||||||
|
using namespace MWRender;
|
||||||
|
using namespace Ogre;
|
||||||
|
|
||||||
|
// the speed at which the clouds are animated
|
||||||
|
#define CLOUD_SPEED 0.001
|
||||||
|
|
||||||
|
// this distance has to be set accordingly so that the
|
||||||
|
// celestial bodies are behind the clouds, but in front of the atmosphere
|
||||||
|
#define CELESTIAL_BODY_DISTANCE 1000.f
|
||||||
|
|
||||||
|
BillboardObject::BillboardObject( const String& textureName,
|
||||||
|
const float initialSize,
|
||||||
|
const Vector3& position,
|
||||||
|
SceneNode* rootNode)
|
||||||
{
|
{
|
||||||
//
|
init(textureName, initialSize, position, rootNode);
|
||||||
// Implements a Caelum sky with default settings.
|
}
|
||||||
//
|
|
||||||
// Note: this is intended as a temporary solution to provide some form of
|
BillboardObject::BillboardObject()
|
||||||
// sky rendering. This code will obviously need significant tailoring to
|
{
|
||||||
// support fidelity with Morrowind's rendering. Before doing major work
|
}
|
||||||
// on this class, more research should be done to determine whether
|
|
||||||
// Caelum or another plug-in such as SkyX would be best for the long-term.
|
void BillboardObject::setVisible(const bool visible)
|
||||||
//
|
|
||||||
class CaelumManager : public SkyManager
|
|
||||||
{
|
{
|
||||||
protected:
|
mNode->setVisible(visible);
|
||||||
Caelum::CaelumSystem* mpCaelumSystem;
|
}
|
||||||
|
|
||||||
public:
|
void BillboardObject::setSize(const float size)
|
||||||
CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
{
|
||||||
Ogre::Camera* pCamera,
|
mNode->setScale(size, size, size);
|
||||||
const boost::filesystem::path& resDir);
|
}
|
||||||
virtual ~CaelumManager ();
|
|
||||||
|
|
||||||
virtual void enable() {}
|
void BillboardObject::setVisibility(const float visibility)
|
||||||
|
{
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void disable() {}
|
void BillboardObject::setPosition(const Vector3& pPosition)
|
||||||
|
{
|
||||||
|
Vector3 normalised = pPosition.normalisedCopy();
|
||||||
|
Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE;
|
||||||
|
|
||||||
virtual void setHour (double hour) {}
|
mBBSet->setCommonDirection( -normalised );
|
||||||
///< will be called even when sky is disabled.
|
|
||||||
|
|
||||||
virtual void setDate (int day, int month) {}
|
mNode->setPosition(finalPosition);
|
||||||
///< will be called even when sky is disabled.
|
}
|
||||||
|
|
||||||
virtual int getMasserPhase() const { return 0; }
|
Vector3 BillboardObject::getPosition() const
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
{
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
return mNode->getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
virtual int getSecundaPhase() const { return 0; }
|
void BillboardObject::setColour(const ColourValue& pColour)
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
{
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void setMoonColour (bool red) {}
|
void BillboardObject::setRenderQueue(unsigned int id)
|
||||||
};
|
{
|
||||||
|
mBBSet->setRenderQueueGroup(id);
|
||||||
|
}
|
||||||
|
|
||||||
CaelumManager::CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
SceneNode* BillboardObject::getNode()
|
||||||
Ogre::Camera* pCamera,
|
|
||||||
const boost::filesystem::path& resDir)
|
|
||||||
: mpCaelumSystem (NULL)
|
|
||||||
{
|
{
|
||||||
using namespace Ogre;
|
return mNode;
|
||||||
using namespace Caelum;
|
}
|
||||||
|
|
||||||
|
void BillboardObject::init(const String& textureName,
|
||||||
|
const float initialSize,
|
||||||
|
const Vector3& position,
|
||||||
|
SceneNode* rootNode)
|
||||||
|
{
|
||||||
|
SceneManager* sceneMgr = rootNode->getCreator();
|
||||||
|
|
||||||
|
Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
||||||
|
|
||||||
|
static unsigned int bodyCount=0;
|
||||||
|
|
||||||
|
/// \todo These billboards are not 100% correct, might want to revisit them later
|
||||||
|
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
||||||
|
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
||||||
|
mBBSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2);
|
||||||
|
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
||||||
|
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
||||||
|
mNode = rootNode->createChildSceneNode();
|
||||||
|
mNode->setPosition(finalPosition);
|
||||||
|
mNode->attachObject(mBBSet);
|
||||||
|
mBBSet->createBillboard(0,0,0);
|
||||||
|
|
||||||
|
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
|
mMaterial->removeAllTechniques();
|
||||||
|
Pass* p = mMaterial->createTechnique()->createPass();
|
||||||
|
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
p->setDepthCheckEnabled(false);
|
||||||
|
p->setDepthWriteEnabled(false);
|
||||||
|
p->setSelfIllumination(1.0,1.0,1.0);
|
||||||
|
p->setDiffuse(0.0,0.0,0.0,1.0);
|
||||||
|
p->setAmbient(0.0,0.0,0.0);
|
||||||
|
p->createTextureUnitState(textureName);
|
||||||
|
mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
|
||||||
|
|
||||||
|
bodyCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Moon::Moon( const String& textureName,
|
||||||
|
const float initialSize,
|
||||||
|
const Vector3& position,
|
||||||
|
SceneNode* rootNode)
|
||||||
|
{
|
||||||
|
init(textureName, initialSize, position, rootNode);
|
||||||
|
|
||||||
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
HighLevelGpuProgramPtr vshader;
|
||||||
|
if (mgr.resourceExists("Moon_VP"))
|
||||||
|
vshader = mgr.getByName("Moon_VP");
|
||||||
|
else
|
||||||
|
vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM);
|
||||||
|
vshader->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
|
vshader->setParameter("entry_point", "main_vp");
|
||||||
|
StringUtil::StrStreamType outStream;
|
||||||
|
outStream <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float2 oUV : TEXCOORD0, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oUV = uv; \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
"}";
|
||||||
|
vshader->setSource(outStream.str());
|
||||||
|
vshader->load();
|
||||||
|
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||||
|
|
||||||
|
HighLevelGpuProgramPtr fshader;
|
||||||
|
if (mgr.resourceExists("Moon_FP"))
|
||||||
|
fshader = mgr.getByName("Moon_FP");
|
||||||
|
else
|
||||||
|
fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM);
|
||||||
|
|
||||||
|
fshader->setParameter("profiles", "ps_2_x arbfp1");
|
||||||
|
fshader->setParameter("entry_point", "main_fp");
|
||||||
|
StringUtil::StrStreamType outStream2;
|
||||||
|
outStream2 <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform float4 diffuse, \n"
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
|
" oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n"
|
||||||
|
" float bump = pow((1-diffuse.a),4); \n"
|
||||||
|
" oColor.rgb += float3(bump, bump, bump)*0.5; \n"
|
||||||
|
"}";
|
||||||
|
fshader->setSource(outStream2.str());
|
||||||
|
fshader->load();
|
||||||
|
fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||||
|
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
|
||||||
|
|
||||||
|
setVisibility(1.0);
|
||||||
|
|
||||||
|
mPhase = Moon::Phase_Full;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Moon::setType(const Moon::Type& type)
|
||||||
|
{
|
||||||
|
mType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
|
||||||
|
void Moon::setPhase(const Moon::Phase& phase)
|
||||||
|
{
|
||||||
|
Ogre::String textureName = "textures\\tx_";
|
||||||
|
|
||||||
|
if (mType == Moon::Type_Secunda) textureName += "secunda_";
|
||||||
|
else textureName += "masser_";
|
||||||
|
|
||||||
|
if (phase == Moon::Phase_New) textureName += "new";
|
||||||
|
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
|
||||||
|
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
|
||||||
|
else if (phase == Moon::Phase_WaxingGibbous) textureName += "three_wax";
|
||||||
|
else if (phase == Moon::Phase_WaningCrescent) textureName += "one_wan";
|
||||||
|
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
|
||||||
|
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
|
||||||
|
else if (phase == Moon::Phase_Full) textureName += "full";
|
||||||
|
|
||||||
|
textureName += ".dds";
|
||||||
|
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);
|
||||||
|
|
||||||
|
mPhase = phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
Moon::Phase Moon::getPhase() const
|
||||||
|
{
|
||||||
|
return mPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Moon::getPhaseInt() const
|
||||||
|
{
|
||||||
|
if (mPhase == Moon::Phase_New) return 0;
|
||||||
|
else if (mPhase == Moon::Phase_WaxingCrescent) return 1;
|
||||||
|
else if (mPhase == Moon::Phase_WaningCrescent) return 1;
|
||||||
|
else if (mPhase == Moon::Phase_WaxingHalf) return 2;
|
||||||
|
else if (mPhase == Moon::Phase_WaningHalf) return 2;
|
||||||
|
else if (mPhase == Moon::Phase_WaxingGibbous) return 3;
|
||||||
|
else if (mPhase == Moon::Phase_WaningGibbous) return 3;
|
||||||
|
else if (mPhase == Moon::Phase_Full) return 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||||
|
{
|
||||||
|
// Get the vertex colour buffer of this mesh
|
||||||
|
const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE );
|
||||||
|
HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource());
|
||||||
|
|
||||||
|
// Lock
|
||||||
|
void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL);
|
||||||
|
|
||||||
|
// Iterate over all vertices
|
||||||
|
int vertex_size = colourBuffer->getVertexSize();
|
||||||
|
float * currentVertex = NULL;
|
||||||
|
for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i)
|
||||||
|
{
|
||||||
|
// Get a pointer to the vertex colour
|
||||||
|
ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex );
|
||||||
|
|
||||||
|
unsigned char alpha;
|
||||||
|
if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
||||||
|
else if (meshType == 1)
|
||||||
|
{
|
||||||
|
if (i>= 49 && i <= 64) alpha = 0; // bottom-most row
|
||||||
|
else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
|
||||||
|
else alpha = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 tmpR = static_cast<uint8>(255);
|
||||||
|
uint8 tmpG = static_cast<uint8>(255);
|
||||||
|
uint8 tmpB = static_cast<uint8>(255);
|
||||||
|
uint8 tmpA = static_cast<uint8>(alpha);
|
||||||
|
|
||||||
|
// This does not matter since R and B are always 1.
|
||||||
|
/*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case VET_COLOUR_ARGB:
|
||||||
|
std::swap(tmpR, tmpB);
|
||||||
|
break;
|
||||||
|
case VET_COLOUR_ABGR:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Modify
|
||||||
|
*((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);
|
||||||
|
|
||||||
|
// Move to the next vertex
|
||||||
|
pData = static_cast<unsigned char *> (pData) + vertex_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock
|
||||||
|
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
|
mGlareFade(0), mGlareEnabled(false)
|
||||||
|
{
|
||||||
|
mViewport = pCamera->getViewport();
|
||||||
|
mSceneMgr = pMwRoot->getCreator();
|
||||||
|
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
||||||
|
mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates
|
||||||
|
mRootNode->setInheritOrientation(false);
|
||||||
|
|
||||||
|
/// \todo preload all the textures and meshes that are used for sky rendering
|
||||||
|
|
||||||
|
// Create overlay used for thunderstorm
|
||||||
|
MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
|
||||||
|
Pass* pass = material->getTechnique(0)->getPass(0);
|
||||||
|
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
mThunderTextureUnit = pass->createTextureUnitState();
|
||||||
|
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour
|
||||||
|
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
||||||
|
OverlayManager& ovm = OverlayManager::getSingleton();
|
||||||
|
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
||||||
|
OverlayContainer* overlay_panel;
|
||||||
|
overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel");
|
||||||
|
overlay_panel->_setPosition(0, 0);
|
||||||
|
overlay_panel->_setDimensions(1, 1);
|
||||||
|
overlay_panel->setMaterialName( "ThunderMaterial" );
|
||||||
|
overlay_panel->show();
|
||||||
|
mThunderOverlay->add2D(overlay_panel);
|
||||||
|
mThunderOverlay->hide();
|
||||||
|
|
||||||
|
mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||||
|
mSecunda->setType(Moon::Type_Secunda);
|
||||||
|
mSecunda->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+4);
|
||||||
|
|
||||||
|
mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||||
|
mMasser->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+3);
|
||||||
|
mMasser->setType(Moon::Type_Masser);
|
||||||
|
|
||||||
|
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode);
|
||||||
|
mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode);
|
||||||
|
mSunGlare->setRenderQueue(RENDER_QUEUE_SKIES_LATE);
|
||||||
|
|
||||||
|
|
||||||
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
|
||||||
|
// Stars
|
||||||
|
/// \todo sky_night_02.nif (available in Bloodmoon)
|
||||||
|
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
|
||||||
|
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||||
|
night1_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1);
|
||||||
|
|
||||||
|
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||||
|
mAtmosphereNight->attachObject(night1_ent);
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
|
||||||
|
{
|
||||||
|
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
|
||||||
|
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
|
mStarsMaterials[i] = mp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stars vertex shader
|
||||||
|
HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_VERTEX_PROGRAM);
|
||||||
|
vshader3->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
|
vshader3->setParameter("entry_point", "main_vp");
|
||||||
|
StringUtil::StrStreamType outStream4;
|
||||||
|
outStream4 <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float2 oUV : TEXCOORD0, \n"
|
||||||
|
" out float oFade : TEXCOORD1, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oUV = uv; \n"
|
||||||
|
" oFade = (position.z > 50) ? 1.f : 0.f; \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
"}";
|
||||||
|
vshader3->setSource(outStream4.str());
|
||||||
|
vshader3->load();
|
||||||
|
vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName());
|
||||||
|
|
||||||
|
// Stars fragment shader
|
||||||
|
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_FRAGMENT_PROGRAM);
|
||||||
|
stars_fp->setParameter("profiles", "ps_2_x arbfp1");
|
||||||
|
stars_fp->setParameter("entry_point", "main_fp");
|
||||||
|
StringUtil::StrStreamType outStream5;
|
||||||
|
outStream5 <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" in float fade : TEXCOORD1, \n"
|
||||||
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform float opacity, \n"
|
||||||
|
" uniform float4 diffuse, \n"
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n"
|
||||||
|
"}";
|
||||||
|
stars_fp->setSource(outStream5.str());
|
||||||
|
stars_fp->load();
|
||||||
|
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||||
|
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
|
||||||
|
|
||||||
|
// Atmosphere (day)
|
||||||
|
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||||
|
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||||
|
|
||||||
|
ModVertexAlpha(atmosphere_ent, 0);
|
||||||
|
|
||||||
|
atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);
|
||||||
|
mAtmosphereDay = mRootNode->createChildSceneNode();
|
||||||
|
mAtmosphereDay->attachObject(atmosphere_ent);
|
||||||
|
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
|
||||||
|
|
||||||
|
// Atmosphere shader
|
||||||
|
HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_VERTEX_PROGRAM);
|
||||||
|
|
||||||
|
vshader->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
|
vshader->setParameter("entry_point", "main_vp");
|
||||||
|
|
||||||
|
StringUtil::StrStreamType outStream;
|
||||||
|
outStream <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" in float4 color : COLOR, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" uniform float4 emissive, \n"
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
" oColor = color * emissive; \n"
|
||||||
|
"}";
|
||||||
|
vshader->setSource(outStream.str());
|
||||||
|
vshader->load();
|
||||||
|
|
||||||
|
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||||
|
|
||||||
assert(pCamera);
|
// Clouds
|
||||||
assert(pRenderWindow);
|
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||||
|
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
||||||
|
clouds_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+5);
|
||||||
|
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||||
|
clouds_node->attachObject(clouds_ent);
|
||||||
|
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||||
|
|
||||||
// Load the Caelum resources
|
// Clouds vertex shader
|
||||||
//
|
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
ResourceGroupManager::getSingleton().addResourceLocation((resDir / "caelum").string(), "FileSystem", "Caelum");
|
"cg", GPT_VERTEX_PROGRAM);
|
||||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
vshader2->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
|
vshader2->setParameter("entry_point", "main_vp");
|
||||||
|
StringUtil::StrStreamType outStream3;
|
||||||
|
outStream3 <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" in float4 color : COLOR, \n"
|
||||||
|
" out float4 oColor : TEXCOORD1, \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float2 oUV : TEXCOORD0, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oUV = uv; \n"
|
||||||
|
" oColor = color; \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
"}";
|
||||||
|
vshader2->setSource(outStream3.str());
|
||||||
|
vshader2->load();
|
||||||
|
vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName());
|
||||||
|
|
||||||
// Load the Caelum resources
|
// Clouds fragment shader
|
||||||
//
|
mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
Ogre::SceneManager* pScene = pCamera->getSceneManager();
|
"cg", GPT_FRAGMENT_PROGRAM);
|
||||||
Caelum::CaelumSystem::CaelumComponent componentMask = CaelumSystem::CAELUM_COMPONENTS_DEFAULT;
|
mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1");
|
||||||
mpCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), pScene, componentMask);
|
mCloudFragmentShader->setParameter("entry_point", "main_fp");
|
||||||
|
StringUtil::StrStreamType outStream2;
|
||||||
|
outStream2 <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" in float4 color : TEXCOORD1, \n"
|
||||||
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
||||||
|
" uniform float transitionFactor, \n"
|
||||||
|
" uniform float time, \n"
|
||||||
|
" uniform float speed, \n"
|
||||||
|
" uniform float opacity, \n"
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" uv += float2(1,1) * time * speed * "<<CLOUD_SPEED<<"; \n" // Scroll in x,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"
|
||||||
|
"}";
|
||||||
|
mCloudFragmentShader->setSource(outStream2.str());
|
||||||
|
mCloudFragmentShader->load();
|
||||||
|
mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName());
|
||||||
|
setCloudsOpacity(0.75);
|
||||||
|
|
||||||
// Set time acceleration.
|
ModVertexAlpha(clouds_ent, 1);
|
||||||
mpCaelumSystem->getUniversalClock()->setTimeScale(128);
|
|
||||||
|
|
||||||
// Disable fog since OpenMW is handling OGRE fog elsewhere
|
// I'm not sure if the materials are being used by any other objects
|
||||||
mpCaelumSystem->setManageSceneFog(false);
|
// Make a unique "modifiable" copy of the materials to be sure
|
||||||
|
mCloudMaterial = mCloudMaterial->clone("Clouds");
|
||||||
|
clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial);
|
||||||
|
mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere");
|
||||||
|
atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial);
|
||||||
|
|
||||||
// Change the camera far distance to make sure the sky is not clipped
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||||
pCamera->setFarClipDistance(50000);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0);
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
// Register Caelum as an OGRE listener
|
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||||
pRenderWindow->addListener(mpCaelumSystem);
|
|
||||||
Root::getSingletonPtr()->addFrameListener(mpCaelumSystem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CaelumManager::~CaelumManager()
|
SkyManager::~SkyManager()
|
||||||
{
|
{
|
||||||
if (mpCaelumSystem)
|
delete mSun;
|
||||||
mpCaelumSystem->shutdown (false);
|
delete mSunGlare;
|
||||||
|
delete mMasser;
|
||||||
|
delete mSecunda;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and connects the sky rendering component to OGRE.
|
int SkyManager::getMasserPhase() const
|
||||||
///
|
|
||||||
/// \return NULL on failure.
|
|
||||||
///
|
|
||||||
SkyManager* SkyManager::create (Ogre::RenderWindow* pRenderWindow,
|
|
||||||
Ogre::Camera* pCamera,
|
|
||||||
const boost::filesystem::path& resDir)
|
|
||||||
{
|
{
|
||||||
SkyManager* pSkyManager = NULL;
|
return mMasser->getPhaseInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkyManager::getSecundaPhase() const
|
||||||
|
{
|
||||||
|
return mSecunda->getPhaseInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::update(float duration)
|
||||||
|
{
|
||||||
|
if (!mEnabled) return;
|
||||||
|
|
||||||
|
// UV Scroll the clouds
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1);
|
||||||
|
|
||||||
|
/// \todo improve this
|
||||||
|
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
|
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
|
|
||||||
|
// increase the strength of the sun glare effect depending
|
||||||
|
// on how directly the player is looking at the sun
|
||||||
|
if (mSunEnabled)
|
||||||
|
{
|
||||||
|
Vector3 sun = mSunGlare->getPosition();
|
||||||
|
sun = Vector3(sun.x, sun.z, -sun.y);
|
||||||
|
Vector3 cam = mViewport->getCamera()->getRealDirection();
|
||||||
|
const Degree angle = sun.angleBetween( cam );
|
||||||
|
float val = 1- (angle.valueDegrees() / 180.f);
|
||||||
|
val = (val*val*val*val)*2;
|
||||||
|
|
||||||
|
if (mGlareEnabled)
|
||||||
|
{
|
||||||
|
mGlareFade += duration*3;
|
||||||
|
if (mGlareFade > 1) mGlareFade = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mGlareFade -= duration*3;
|
||||||
|
if (mGlareFade < 0.3) mGlareFade = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSunGlare->setSize(val * (mGlareFade));
|
||||||
|
}
|
||||||
|
|
||||||
try
|
mSunGlare->setVisible(mGlareFade>0 && mSunEnabled);
|
||||||
|
mSun->setVisible(mSunEnabled);
|
||||||
|
mMasser->setVisible(mMasserEnabled);
|
||||||
|
mSecunda->setVisible(mSecundaEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::enable()
|
||||||
{
|
{
|
||||||
pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir);
|
mRootNode->setVisible(true);
|
||||||
|
mEnabled = true;
|
||||||
}
|
}
|
||||||
catch (Ogre::Exception& e)
|
|
||||||
|
void SkyManager::disable()
|
||||||
{
|
{
|
||||||
std::cout << "\nOGRE Exception when attempting to add sky: "
|
mRootNode->setVisible(false);
|
||||||
<< e.getFullDescription().c_str() << std::endl;
|
mEnabled = false;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
|
||||||
|
void SkyManager::setMoonColour (bool red)
|
||||||
|
{
|
||||||
|
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
||||||
|
: ColourValue(1.0, 1.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setCloudsOpacity(float opacity)
|
||||||
{
|
{
|
||||||
std::cout << "\nException when attempting to add sky: "
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||||
<< e.what() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pSkyManager;
|
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
|
{
|
||||||
|
if (mClouds != weather.mCloudTexture)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture);
|
||||||
|
mClouds = weather.mCloudTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mNextClouds != weather.mNextCloudTexture)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("textures\\"+weather.mNextCloudTexture);
|
||||||
|
mNextClouds = weather.mNextCloudTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudBlendFactor != weather.mCloudBlendFactor)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor));
|
||||||
|
mCloudBlendFactor = weather.mCloudBlendFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudOpacity != weather.mCloudOpacity)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity));
|
||||||
|
mCloudOpacity = weather.mCloudOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudColour != weather.mSunColor)
|
||||||
|
{
|
||||||
|
ColourValue clr( weather.mSunColor.r*0.7 + weather.mAmbientColor.r*0.7,
|
||||||
|
weather.mSunColor.g*0.7 + weather.mAmbientColor.g*0.7,
|
||||||
|
weather.mSunColor.b*0.7 + weather.mAmbientColor.b*0.7);
|
||||||
|
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(clr);
|
||||||
|
mCloudColour = weather.mSunColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSkyColour != weather.mSkyColor)
|
||||||
|
{
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
|
||||||
|
mSkyColour = weather.mSkyColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudSpeed != weather.mCloudSpeed)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("speed", Real(weather.mCloudSpeed));
|
||||||
|
mCloudSpeed = weather.mCloudSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weather.mNight && mStarsOpacity != weather.mNightFade)
|
||||||
|
{
|
||||||
|
for (int i=0; i<7; ++i)
|
||||||
|
mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade);
|
||||||
|
mStarsOpacity = weather.mNightFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
float strength;
|
||||||
|
float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length());
|
||||||
|
if (timeofday_angle <= 0.44)
|
||||||
|
strength = timeofday_angle/0.44f;
|
||||||
|
else
|
||||||
|
strength = 1.f;
|
||||||
|
|
||||||
|
mSunGlare->setVisibility(weather.mGlareView * strength);
|
||||||
|
|
||||||
|
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setGlare(bool glare)
|
||||||
|
{
|
||||||
|
mGlareEnabled = glare;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 SkyManager::getRealSunPos()
|
||||||
|
{
|
||||||
|
return mSun->getNode()->_getDerivedPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::sunEnable()
|
||||||
|
{
|
||||||
|
mSunEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::sunDisable()
|
||||||
|
{
|
||||||
|
mSunEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setSunDirection(const Vector3& direction)
|
||||||
|
{
|
||||||
|
mSun->setPosition(direction);
|
||||||
|
mSunGlare->setPosition(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setMasserDirection(const Vector3& direction)
|
||||||
|
{
|
||||||
|
mMasser->setPosition(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setSecundaDirection(const Vector3& direction)
|
||||||
|
{
|
||||||
|
mSecunda->setPosition(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::masserEnable()
|
||||||
|
{
|
||||||
|
mMasserEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::secundaEnable()
|
||||||
|
{
|
||||||
|
mSecundaEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::masserDisable()
|
||||||
|
{
|
||||||
|
mMasserEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::secundaDisable()
|
||||||
|
{
|
||||||
|
mSecundaEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setThunder(const float factor)
|
||||||
|
{
|
||||||
|
if (factor > 0.f)
|
||||||
|
{
|
||||||
|
mThunderOverlay->show();
|
||||||
|
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, factor*0.6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mThunderOverlay->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setMasserFade(const float fade)
|
||||||
|
{
|
||||||
|
mMasser->setVisibility(fade);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setSecundaFade(const float fade)
|
||||||
|
{
|
||||||
|
mSecunda->setVisibility(fade);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setHour(double hour)
|
||||||
|
{
|
||||||
|
mHour = hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setDate(int day, int month)
|
||||||
|
{
|
||||||
|
mDay = day;
|
||||||
|
mMonth = month;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,342 @@
|
|||||||
|
|
||||||
|
#include "containerstore.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::begin (int mask)
|
||||||
|
{
|
||||||
|
return ContainerStoreIterator (mask, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
|
||||||
|
{
|
||||||
|
return ContainerStoreIterator (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWWorld::ContainerStore::add (const Ptr& ptr)
|
||||||
|
{
|
||||||
|
/// \todo implement item stocking
|
||||||
|
|
||||||
|
switch (getType (ptr))
|
||||||
|
{
|
||||||
|
case Type_Potion: potions.list.push_back (*ptr.get<ESM::Potion>()); break;
|
||||||
|
case Type_Apparatus: appas.list.push_back (*ptr.get<ESM::Apparatus>()); break;
|
||||||
|
case Type_Armor: armors.list.push_back (*ptr.get<ESM::Armor>()); break;
|
||||||
|
case Type_Book: books.list.push_back (*ptr.get<ESM::Book>()); break;
|
||||||
|
case Type_Clothing: clothes.list.push_back (*ptr.get<ESM::Clothing>()); break;
|
||||||
|
case Type_Ingredient: ingreds.list.push_back (*ptr.get<ESM::Ingredient>()); break;
|
||||||
|
case Type_Light: lights.list.push_back (*ptr.get<ESM::Light>()); break;
|
||||||
|
case Type_Lockpick: lockpicks.list.push_back (*ptr.get<ESM::Tool>()); break;
|
||||||
|
case Type_Miscellaneous: miscItems.list.push_back (*ptr.get<ESM::Miscellaneous>()); break;
|
||||||
|
case Type_Probe: probes.list.push_back (*ptr.get<ESM::Probe>()); break;
|
||||||
|
case Type_Repair: repairs.list.push_back (*ptr.get<ESM::Repair>()); break;
|
||||||
|
case Type_Weapon: weapons.list.push_back (*ptr.get<ESM::Weapon>()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MWWorld::ContainerStore::getType (const Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.isEmpty())
|
||||||
|
throw std::runtime_error ("can't put a non-existent object into a container");
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Potion).name())
|
||||||
|
return Type_Potion;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Apparatus).name())
|
||||||
|
return Type_Apparatus;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Armor).name())
|
||||||
|
return Type_Armor;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Book).name())
|
||||||
|
return Type_Book;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Clothing).name())
|
||||||
|
return Type_Clothing;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Ingredient).name())
|
||||||
|
return Type_Ingredient;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Light).name())
|
||||||
|
return Type_Light;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Tool).name())
|
||||||
|
return Type_Lockpick;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Miscellaneous).name())
|
||||||
|
return Type_Miscellaneous;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Probe).name())
|
||||||
|
return Type_Probe;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Repair).name())
|
||||||
|
return Type_Repair;
|
||||||
|
|
||||||
|
if (ptr.getTypeName()==typeid (ESM::Weapon).name())
|
||||||
|
return Type_Weapon;
|
||||||
|
|
||||||
|
throw std::runtime_error (
|
||||||
|
"Object of type " + ptr.getTypeName() + " can not be placed into a container");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container)
|
||||||
|
: mType (-1), mMask (0), mContainer (container)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStore *container)
|
||||||
|
: mType (0), mMask (mask), mContainer (container)
|
||||||
|
{
|
||||||
|
nextType();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWWorld::ContainerStoreIterator::incType()
|
||||||
|
{
|
||||||
|
if (mType==0)
|
||||||
|
mType = 1;
|
||||||
|
else if (mType!=-1)
|
||||||
|
{
|
||||||
|
mType <<= 1;
|
||||||
|
|
||||||
|
if (mType>ContainerStore::Type_Last)
|
||||||
|
mType = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWWorld::ContainerStoreIterator::nextType()
|
||||||
|
{
|
||||||
|
while (mType!=-1)
|
||||||
|
{
|
||||||
|
incType();
|
||||||
|
|
||||||
|
if (mType & mMask)
|
||||||
|
if (resetIterator())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::ContainerStoreIterator::resetIterator()
|
||||||
|
{
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case ContainerStore::Type_Potion:
|
||||||
|
|
||||||
|
mPotion = mContainer->potions.list.begin();
|
||||||
|
return mPotion!=mContainer->potions.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Apparatus:
|
||||||
|
|
||||||
|
mApparatus = mContainer->appas.list.begin();
|
||||||
|
return mApparatus!=mContainer->appas.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Armor:
|
||||||
|
|
||||||
|
mArmor = mContainer->armors.list.begin();
|
||||||
|
return mArmor!=mContainer->armors.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Book:
|
||||||
|
|
||||||
|
mBook = mContainer->books.list.begin();
|
||||||
|
return mBook!=mContainer->books.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Clothing:
|
||||||
|
|
||||||
|
mClothing = mContainer->clothes.list.begin();
|
||||||
|
return mClothing!=mContainer->clothes.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Ingredient:
|
||||||
|
|
||||||
|
mIngredient = mContainer->ingreds.list.begin();
|
||||||
|
return mIngredient!=mContainer->ingreds.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Light:
|
||||||
|
|
||||||
|
mLight = mContainer->lights.list.begin();
|
||||||
|
return mLight!=mContainer->lights.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Lockpick:
|
||||||
|
|
||||||
|
mLockpick = mContainer->lockpicks.list.begin();
|
||||||
|
return mLockpick!=mContainer->lockpicks.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Miscellaneous:
|
||||||
|
|
||||||
|
mMiscellaneous = mContainer->miscItems.list.begin();
|
||||||
|
return mMiscellaneous!=mContainer->miscItems.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Probe:
|
||||||
|
|
||||||
|
mProbe = mContainer->probes.list.begin();
|
||||||
|
return mProbe!=mContainer->probes.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Repair:
|
||||||
|
|
||||||
|
mRepair = mContainer->repairs.list.begin();
|
||||||
|
return mRepair!=mContainer->repairs.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Weapon:
|
||||||
|
|
||||||
|
mWeapon = mContainer->weapons.list.begin();
|
||||||
|
return mWeapon!=mContainer->weapons.list.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::ContainerStoreIterator::incIterator()
|
||||||
|
{
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case ContainerStore::Type_Potion:
|
||||||
|
|
||||||
|
++mPotion;
|
||||||
|
return mPotion==mContainer->potions.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Apparatus:
|
||||||
|
|
||||||
|
++mApparatus;
|
||||||
|
return mApparatus==mContainer->appas.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Armor:
|
||||||
|
|
||||||
|
++mArmor;
|
||||||
|
return mArmor==mContainer->armors.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Book:
|
||||||
|
|
||||||
|
++mBook;
|
||||||
|
return mBook==mContainer->books.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Clothing:
|
||||||
|
|
||||||
|
++mClothing;
|
||||||
|
return mClothing==mContainer->clothes.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Ingredient:
|
||||||
|
|
||||||
|
++mIngredient;
|
||||||
|
return mIngredient==mContainer->ingreds.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Light:
|
||||||
|
|
||||||
|
++mLight;
|
||||||
|
return mLight==mContainer->lights.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Lockpick:
|
||||||
|
|
||||||
|
++mLockpick;
|
||||||
|
return mLockpick==mContainer->lockpicks.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Miscellaneous:
|
||||||
|
|
||||||
|
++mMiscellaneous;
|
||||||
|
return mMiscellaneous==mContainer->miscItems.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Probe:
|
||||||
|
|
||||||
|
++mProbe;
|
||||||
|
return mProbe==mContainer->probes.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Repair:
|
||||||
|
|
||||||
|
++mRepair;
|
||||||
|
return mRepair==mContainer->repairs.list.end();
|
||||||
|
|
||||||
|
case ContainerStore::Type_Weapon:
|
||||||
|
|
||||||
|
++mWeapon;
|
||||||
|
return mWeapon==mContainer->weapons.list.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr *MWWorld::ContainerStoreIterator::operator->() const
|
||||||
|
{
|
||||||
|
mPtr = **this;
|
||||||
|
return &mPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr MWWorld::ContainerStoreIterator::operator*() const
|
||||||
|
{
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case ContainerStore::Type_Potion: return MWWorld::Ptr (&*mPotion, 0);
|
||||||
|
case ContainerStore::Type_Apparatus: return MWWorld::Ptr (&*mApparatus, 0);
|
||||||
|
case ContainerStore::Type_Armor: return MWWorld::Ptr (&*mArmor, 0);
|
||||||
|
case ContainerStore::Type_Book: return MWWorld::Ptr (&*mBook, 0);
|
||||||
|
case ContainerStore::Type_Clothing: return MWWorld::Ptr (&*mClothing, 0);
|
||||||
|
case ContainerStore::Type_Ingredient: return MWWorld::Ptr (&*mIngredient, 0);
|
||||||
|
case ContainerStore::Type_Light: return MWWorld::Ptr (&*mLight, 0);
|
||||||
|
case ContainerStore::Type_Lockpick: return MWWorld::Ptr (&*mLockpick, 0);
|
||||||
|
case ContainerStore::Type_Miscellaneous: return MWWorld::Ptr (&*mMiscellaneous, 0);
|
||||||
|
case ContainerStore::Type_Probe: return MWWorld::Ptr (&*mProbe, 0);
|
||||||
|
case ContainerStore::Type_Repair: return MWWorld::Ptr (&*mRepair, 0);
|
||||||
|
case ContainerStore::Type_Weapon: return MWWorld::Ptr (&*mWeapon, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error ("invalid pointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator& MWWorld::ContainerStoreIterator::operator++()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (incIterator())
|
||||||
|
nextType();
|
||||||
|
}
|
||||||
|
while (mType!=-1 && !(**this).getRefData().getCount());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStoreIterator::operator++ (int)
|
||||||
|
{
|
||||||
|
ContainerStoreIterator iter (*this);
|
||||||
|
++*this;
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::ContainerStoreIterator::isEqual (const ContainerStoreIterator& iter) const
|
||||||
|
{
|
||||||
|
assert (mContainer==iter.mContainer);
|
||||||
|
|
||||||
|
if (mType!=iter.mType)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case ContainerStore::Type_Potion: return mPotion==iter.mPotion;
|
||||||
|
case ContainerStore::Type_Apparatus: return mApparatus==iter.mApparatus;
|
||||||
|
case ContainerStore::Type_Armor: return mArmor==iter.mArmor;
|
||||||
|
case ContainerStore::Type_Book: return mBook==iter.mBook;
|
||||||
|
case ContainerStore::Type_Clothing: return mClothing==iter.mClothing;
|
||||||
|
case ContainerStore::Type_Ingredient: return mIngredient==iter.mIngredient;
|
||||||
|
case ContainerStore::Type_Light: return mLight==iter.mLight;
|
||||||
|
case ContainerStore::Type_Lockpick: return mLockpick==iter.mLockpick;
|
||||||
|
case ContainerStore::Type_Miscellaneous: return mMiscellaneous==iter.mMiscellaneous;
|
||||||
|
case ContainerStore::Type_Probe: return mProbe==iter.mProbe;
|
||||||
|
case ContainerStore::Type_Repair: return mRepair==iter.mRepair;
|
||||||
|
case ContainerStore::Type_Weapon: return mWeapon==iter.mWeapon;
|
||||||
|
case -1: return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MWWorld::ContainerStoreIterator::getType() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right)
|
||||||
|
{
|
||||||
|
return left.isEqual (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right)
|
||||||
|
{
|
||||||
|
return !(left==right);
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
|
|
||||||
#include "containerutil.hpp"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
void listItemsInContainerImp (const std::string& id,
|
|
||||||
ESMS::CellRefList<T, MWWorld::RefData>& containerStore,
|
|
||||||
const ESMS::RecListT<T>& store, std::vector<MWWorld::Ptr>& list)
|
|
||||||
{
|
|
||||||
if (const T *record = store.search (id))
|
|
||||||
{
|
|
||||||
for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter
|
|
||||||
(containerStore.list.begin());
|
|
||||||
iter!=containerStore.list.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (iter->base==record)
|
|
||||||
list.push_back (MWWorld::Ptr (&*iter, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace MWWorld
|
|
||||||
{
|
|
||||||
void listItemsInContainer (const std::string& id,
|
|
||||||
ContainerStore<MWWorld::RefData>& containerStore,
|
|
||||||
const ESMS::ESMStore& store, std::vector<Ptr>& list)
|
|
||||||
{
|
|
||||||
listItemsInContainerImp (id, containerStore.potions, store.potions, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.appas, store.appas, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.armors, store.armors, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.books, store.books, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.clothes, store.clothes, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.ingreds, store.ingreds, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.lights, store.lights, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.lockpicks, store.lockpicks, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.miscItems, store.miscItems, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.probes, store.probes, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.repairs, store.repairs, list);
|
|
||||||
listItemsInContainerImp (id, containerStore.weapons, store.weapons, list);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef GAME_MWWORLD_CONTAINERUTIL_H
|
|
||||||
#define GAME_MWWORLD_CONTAINERUTIL_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <components/esm_store/store.hpp>
|
|
||||||
|
|
||||||
#include "containerstore.hpp"
|
|
||||||
#include "ptr.hpp"
|
|
||||||
#include "refdata.hpp"
|
|
||||||
|
|
||||||
namespace MWWorld
|
|
||||||
{
|
|
||||||
void listItemsInContainer (const std::string& id, ContainerStore<MWWorld::RefData>& containerStore,
|
|
||||||
const ESMS::ESMStore& store, std::vector<Ptr>& list);
|
|
||||||
///< append all references with the given id to list.
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -0,0 +1,803 @@
|
|||||||
|
#include "weather.hpp"
|
||||||
|
#include "world.hpp"
|
||||||
|
#include "player.hpp"
|
||||||
|
|
||||||
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace MWWorld;
|
||||||
|
using namespace MWSound;
|
||||||
|
|
||||||
|
#define lerp(x, y) (x * (1-factor) + y * factor)
|
||||||
|
|
||||||
|
const std::string WeatherGlobals::mThunderSoundID0 = "Thunder0";
|
||||||
|
const std::string WeatherGlobals::mThunderSoundID1 = "Thunder1";
|
||||||
|
const std::string WeatherGlobals::mThunderSoundID2 = "Thunder2";
|
||||||
|
const std::string WeatherGlobals::mThunderSoundID3 = "Thunder3";
|
||||||
|
|
||||||
|
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environment* env) :
|
||||||
|
mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0),
|
||||||
|
mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0)
|
||||||
|
{
|
||||||
|
mRendering = rendering;
|
||||||
|
mEnvironment = env;
|
||||||
|
|
||||||
|
#define clr(r,g,b) ColourValue(r/255.f, g/255.f, b/255.f)
|
||||||
|
|
||||||
|
/// \todo read these from Morrowind.ini
|
||||||
|
Weather clear;
|
||||||
|
clear.mCloudTexture = "tx_sky_clear.dds";
|
||||||
|
clear.mCloudsMaximumPercent = 1.0;
|
||||||
|
clear.mTransitionDelta = 0.015;
|
||||||
|
clear.mSkySunriseColor = clr(118, 141, 164);
|
||||||
|
clear.mSkyDayColor = clr(95, 135, 203);
|
||||||
|
clear.mSkySunsetColor = clr(56, 89, 129);
|
||||||
|
clear.mSkyNightColor = clr(9, 10, 11);
|
||||||
|
clear.mFogSunriseColor = clr(255, 189, 157);
|
||||||
|
clear.mFogDayColor = clr(206, 227, 255);
|
||||||
|
clear.mFogSunsetColor = clr(255, 189, 157);
|
||||||
|
clear.mFogNightColor = clr(9, 10, 11);
|
||||||
|
clear.mAmbientSunriseColor = clr(47, 66, 96);
|
||||||
|
clear.mAmbientDayColor = clr(137, 140, 160);
|
||||||
|
clear.mAmbientSunsetColor = clr(68, 75, 96);
|
||||||
|
clear.mAmbientNightColor = clr(32, 35, 42);
|
||||||
|
clear.mSunSunriseColor = clr(242, 159, 99);
|
||||||
|
clear.mSunDayColor = clr(255, 252, 238);
|
||||||
|
clear.mSunSunsetColor = clr(255, 115, 79);
|
||||||
|
clear.mSunNightColor = clr(59, 97, 176);
|
||||||
|
clear.mSunDiscSunsetColor = clr(255, 189, 157);
|
||||||
|
clear.mLandFogDayDepth = 0.69;
|
||||||
|
clear.mLandFogNightDepth = 0.69;
|
||||||
|
clear.mWindSpeed = 0.1;
|
||||||
|
clear.mCloudSpeed = 1.25;
|
||||||
|
clear.mGlareView = 1.0;
|
||||||
|
mWeatherSettings["clear"] = clear;
|
||||||
|
|
||||||
|
Weather cloudy;
|
||||||
|
cloudy.mCloudTexture = "tx_sky_cloudy.dds";
|
||||||
|
cloudy.mCloudsMaximumPercent = 1.0;
|
||||||
|
cloudy.mTransitionDelta = 0.015;
|
||||||
|
cloudy.mSkySunriseColor = clr(126, 158, 173);
|
||||||
|
cloudy.mSkyDayColor = clr(117, 160, 215);
|
||||||
|
cloudy.mSkySunsetColor = clr(111, 114, 159);
|
||||||
|
cloudy.mSkyNightColor = clr(9, 10, 11);
|
||||||
|
cloudy.mFogSunriseColor = clr(255, 207, 149);
|
||||||
|
cloudy.mFogDayColor = clr(245, 235, 224);
|
||||||
|
cloudy.mFogSunsetColor = clr(255, 155, 106);
|
||||||
|
cloudy.mFogNightColor = clr(9, 10, 11);
|
||||||
|
cloudy.mAmbientSunriseColor = clr(66, 74, 87);
|
||||||
|
cloudy.mAmbientDayColor = clr(137, 145, 160);
|
||||||
|
cloudy.mAmbientSunsetColor = clr(71, 80, 92);
|
||||||
|
cloudy.mAmbientNightColor = clr(32, 39, 54);
|
||||||
|
cloudy.mSunSunriseColor = clr(241, 177, 99);
|
||||||
|
cloudy.mSunDayColor = clr(255, 236, 221);
|
||||||
|
cloudy.mSunSunsetColor = clr(255, 89, 00);
|
||||||
|
cloudy.mSunNightColor = clr(77, 91, 124);
|
||||||
|
cloudy.mSunDiscSunsetColor = clr(255, 202, 179);
|
||||||
|
cloudy.mLandFogDayDepth = 0.72;
|
||||||
|
cloudy.mLandFogNightDepth = 0.72;
|
||||||
|
cloudy.mWindSpeed = 0.2;
|
||||||
|
cloudy.mCloudSpeed = 2;
|
||||||
|
cloudy.mGlareView = 1.0;
|
||||||
|
mWeatherSettings["cloudy"] = cloudy;
|
||||||
|
|
||||||
|
Weather foggy;
|
||||||
|
foggy.mCloudTexture = "tx_sky_foggy.dds";
|
||||||
|
foggy.mCloudsMaximumPercent = 1.0;
|
||||||
|
foggy.mTransitionDelta = 0.015;
|
||||||
|
foggy.mSkySunriseColor = clr(197, 190, 180);
|
||||||
|
foggy.mSkyDayColor = clr(184, 211, 228);
|
||||||
|
foggy.mSkySunsetColor = clr(142, 159, 176);
|
||||||
|
foggy.mSkyNightColor = clr(18, 23, 28);
|
||||||
|
foggy.mFogSunriseColor = clr(173, 164, 148);
|
||||||
|
foggy.mFogDayColor = clr(150, 187, 209);
|
||||||
|
foggy.mFogSunsetColor = clr(113, 135, 157);
|
||||||
|
foggy.mFogNightColor = clr(19, 24, 29);
|
||||||
|
foggy.mAmbientSunriseColor = clr(48, 43, 37);
|
||||||
|
foggy.mAmbientDayColor = clr(92, 109, 120);
|
||||||
|
foggy.mAmbientSunsetColor = clr(28, 33, 39);
|
||||||
|
foggy.mAmbientNightColor = clr(28, 33, 39);
|
||||||
|
foggy.mSunSunriseColor = clr(177, 162, 137);
|
||||||
|
foggy.mSunDayColor = clr(111, 131, 151);
|
||||||
|
foggy.mSunSunsetColor = clr(125, 157, 189);
|
||||||
|
foggy.mSunNightColor = clr(81, 100, 119);
|
||||||
|
foggy.mSunDiscSunsetColor = clr(223, 223, 223);
|
||||||
|
foggy.mLandFogDayDepth = 1.0;
|
||||||
|
foggy.mLandFogNightDepth = 1.9;
|
||||||
|
foggy.mWindSpeed = 0;
|
||||||
|
foggy.mCloudSpeed = 1.25;
|
||||||
|
foggy.mGlareView = 0.25;
|
||||||
|
mWeatherSettings["foggy"] = foggy;
|
||||||
|
|
||||||
|
Weather thunderstorm;
|
||||||
|
thunderstorm.mCloudTexture = "tx_sky_thunder.dds";
|
||||||
|
thunderstorm.mCloudsMaximumPercent = 0.66;
|
||||||
|
thunderstorm.mTransitionDelta = 0.03;
|
||||||
|
thunderstorm.mSkySunriseColor = clr(35, 36, 39);
|
||||||
|
thunderstorm.mSkyDayColor = clr(97, 104, 115);
|
||||||
|
thunderstorm.mSkySunsetColor = clr(35, 36, 39);
|
||||||
|
thunderstorm.mSkyNightColor = clr(19, 20, 22);
|
||||||
|
thunderstorm.mFogSunriseColor = clr(70, 74, 85);
|
||||||
|
thunderstorm.mFogDayColor = clr(97, 104, 115);
|
||||||
|
thunderstorm.mFogSunsetColor = clr(70, 74, 85);
|
||||||
|
thunderstorm.mFogNightColor = clr(19, 20, 22);
|
||||||
|
thunderstorm.mAmbientSunriseColor = clr(54, 54, 54);
|
||||||
|
thunderstorm.mAmbientDayColor = clr(90, 90, 90);
|
||||||
|
thunderstorm.mAmbientSunsetColor = clr(54, 54, 54);
|
||||||
|
thunderstorm.mAmbientNightColor = clr(49, 51, 54);
|
||||||
|
thunderstorm.mSunSunriseColor = clr(91, 99, 122);
|
||||||
|
thunderstorm.mSunDayColor = clr(138, 144, 155);
|
||||||
|
thunderstorm.mSunSunsetColor = clr(96, 101, 117);
|
||||||
|
thunderstorm.mSunNightColor = clr(55, 76, 110);
|
||||||
|
thunderstorm.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
thunderstorm.mLandFogDayDepth = 1;
|
||||||
|
thunderstorm.mLandFogNightDepth = 1.15;
|
||||||
|
thunderstorm.mWindSpeed = 0.5;
|
||||||
|
thunderstorm.mCloudSpeed = 3;
|
||||||
|
thunderstorm.mGlareView = 0;
|
||||||
|
thunderstorm.mRainLoopSoundID = "rain heavy";
|
||||||
|
mWeatherSettings["thunderstorm"] = thunderstorm;
|
||||||
|
|
||||||
|
Weather rain;
|
||||||
|
rain.mCloudTexture = "tx_sky_rainy.dds";
|
||||||
|
rain.mCloudsMaximumPercent = 0.66;
|
||||||
|
rain.mTransitionDelta = 0.015;
|
||||||
|
rain.mSkySunriseColor = clr(71, 74, 75);
|
||||||
|
rain.mSkyDayColor = clr(116, 120, 122);
|
||||||
|
rain.mSkySunsetColor = clr(73, 73, 73);
|
||||||
|
rain.mSkyNightColor = clr(24, 25, 26);
|
||||||
|
rain.mFogSunriseColor = clr(71, 74, 75);
|
||||||
|
rain.mFogDayColor = clr(116, 120, 122);
|
||||||
|
rain.mFogSunsetColor = clr(73, 73, 73);
|
||||||
|
rain.mFogNightColor = clr(24, 25, 26);
|
||||||
|
rain.mAmbientSunriseColor = clr(97, 90, 88);
|
||||||
|
rain.mAmbientDayColor = clr(105, 110, 113);
|
||||||
|
rain.mAmbientSunsetColor = clr(88, 97, 97);
|
||||||
|
rain.mAmbientNightColor = clr(50, 55, 67);
|
||||||
|
rain.mSunSunriseColor = clr(131, 122, 120);
|
||||||
|
rain.mSunDayColor = clr(149, 157, 170);
|
||||||
|
rain.mSunSunsetColor = clr(120, 126, 131);
|
||||||
|
rain.mSunNightColor = clr(50, 62, 101);
|
||||||
|
rain.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
rain.mLandFogDayDepth = 0.8;
|
||||||
|
rain.mLandFogNightDepth = 0.8;
|
||||||
|
rain.mWindSpeed = 0.3;
|
||||||
|
rain.mCloudSpeed = 2;
|
||||||
|
rain.mGlareView = 0;
|
||||||
|
rain.mRainLoopSoundID = "rain";
|
||||||
|
mWeatherSettings["rain"] = rain;
|
||||||
|
|
||||||
|
Weather overcast;
|
||||||
|
overcast.mCloudTexture = "tx_sky_overcast.dds";
|
||||||
|
overcast.mCloudsMaximumPercent = 1.0;
|
||||||
|
overcast.mTransitionDelta = 0.015;
|
||||||
|
overcast.mSkySunriseColor = clr(91, 99, 106);
|
||||||
|
overcast.mSkyDayColor = clr(143, 146, 149);
|
||||||
|
overcast.mSkySunsetColor = clr(108, 115, 121);
|
||||||
|
overcast.mSkyNightColor = clr(19, 22, 25);
|
||||||
|
overcast.mFogSunriseColor = clr(91, 99, 106);
|
||||||
|
overcast.mFogDayColor = clr(143, 146, 149);
|
||||||
|
overcast.mFogSunsetColor = clr(108, 115, 121);
|
||||||
|
overcast.mFogNightColor = clr(19, 22, 25);
|
||||||
|
overcast.mAmbientSunriseColor = clr(84, 88, 92);
|
||||||
|
overcast.mAmbientDayColor = clr(93, 96, 105);
|
||||||
|
overcast.mAmbientSunsetColor = clr(83, 77, 75);
|
||||||
|
overcast.mAmbientNightColor = clr(57, 60, 66);
|
||||||
|
overcast.mSunSunriseColor = clr(87, 125, 163);
|
||||||
|
overcast.mSunDayColor = clr(163, 169, 183);
|
||||||
|
overcast.mSunSunsetColor = clr(85, 103, 157);
|
||||||
|
overcast.mSunNightColor = clr(32, 54, 100);
|
||||||
|
overcast.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
overcast.mLandFogDayDepth = 0.7;
|
||||||
|
overcast.mLandFogNightDepth = 0.7;
|
||||||
|
overcast.mWindSpeed = 0.2;
|
||||||
|
overcast.mCloudSpeed = 1.5;
|
||||||
|
overcast.mGlareView = 0;
|
||||||
|
mWeatherSettings["overcast"] = overcast;
|
||||||
|
|
||||||
|
Weather ashstorm;
|
||||||
|
ashstorm.mCloudTexture = "tx_sky_ashstorm.dds";
|
||||||
|
ashstorm.mCloudsMaximumPercent = 1.0;
|
||||||
|
ashstorm.mTransitionDelta = 0.035;
|
||||||
|
ashstorm.mSkySunriseColor = clr(91, 56, 51);
|
||||||
|
ashstorm.mSkyDayColor = clr(124, 73, 58);
|
||||||
|
ashstorm.mSkySunsetColor = clr(106, 55, 40);
|
||||||
|
ashstorm.mSkyNightColor = clr(20, 21, 22);
|
||||||
|
ashstorm.mFogSunriseColor = clr(91, 56, 51);
|
||||||
|
ashstorm.mFogDayColor = clr(124, 73, 58);
|
||||||
|
ashstorm.mFogSunsetColor = clr(106, 55, 40);
|
||||||
|
ashstorm.mFogNightColor = clr(20, 21, 22);
|
||||||
|
ashstorm.mAmbientSunriseColor = clr(52, 42, 37);
|
||||||
|
ashstorm.mAmbientDayColor = clr(75, 49, 41);
|
||||||
|
ashstorm.mAmbientSunsetColor = clr(48, 39, 35);
|
||||||
|
ashstorm.mAmbientNightColor = clr(36, 42, 49);
|
||||||
|
ashstorm.mSunSunriseColor = clr(184, 91, 71);
|
||||||
|
ashstorm.mSunDayColor = clr(228, 139, 114);
|
||||||
|
ashstorm.mSunSunsetColor = clr(185, 86, 57);
|
||||||
|
ashstorm.mSunNightColor = clr(54, 66, 74);
|
||||||
|
ashstorm.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
ashstorm.mLandFogDayDepth = 1.1;
|
||||||
|
ashstorm.mLandFogNightDepth = 1.2;
|
||||||
|
ashstorm.mWindSpeed = 0.8;
|
||||||
|
ashstorm.mCloudSpeed = 7;
|
||||||
|
ashstorm.mGlareView = 0;
|
||||||
|
ashstorm.mAmbientLoopSoundID = "ashstorm";
|
||||||
|
mWeatherSettings["ashstorm"] = ashstorm;
|
||||||
|
|
||||||
|
Weather blight;
|
||||||
|
blight.mCloudTexture = "tx_sky_blight.dds";
|
||||||
|
blight.mCloudsMaximumPercent = 1.0;
|
||||||
|
blight.mTransitionDelta = 0.04;
|
||||||
|
blight.mSkySunriseColor = clr(90, 35, 35);
|
||||||
|
blight.mSkyDayColor = clr(90, 35, 35);
|
||||||
|
blight.mSkySunsetColor = clr(92, 33, 33);
|
||||||
|
blight.mSkyNightColor = clr(44, 14, 14);
|
||||||
|
blight.mFogSunriseColor = clr(90, 35, 35);
|
||||||
|
blight.mFogDayColor = clr(128, 19, 19);
|
||||||
|
blight.mFogSunsetColor = clr(92, 33, 33);
|
||||||
|
blight.mFogNightColor = clr(44, 14, 14);
|
||||||
|
blight.mAmbientSunriseColor = clr(61, 40, 40);
|
||||||
|
blight.mAmbientDayColor = clr(79, 54, 54);
|
||||||
|
blight.mAmbientSunsetColor = clr(61, 40, 40);
|
||||||
|
blight.mAmbientNightColor = clr(56, 58, 62);
|
||||||
|
blight.mSunSunriseColor = clr(180, 78, 78);
|
||||||
|
blight.mSunDayColor = clr(224, 84, 84);
|
||||||
|
blight.mSunSunsetColor = clr(180, 78, 78);
|
||||||
|
blight.mSunNightColor = clr(61, 91, 143);
|
||||||
|
blight.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
blight.mLandFogDayDepth = 1.1;
|
||||||
|
blight.mLandFogNightDepth = 1.2;
|
||||||
|
blight.mWindSpeed = 0.9;
|
||||||
|
blight.mCloudSpeed = 9;
|
||||||
|
blight.mGlareView = 0;
|
||||||
|
blight.mAmbientLoopSoundID = "blight";
|
||||||
|
mWeatherSettings["blight"] = blight;
|
||||||
|
|
||||||
|
Weather snow;
|
||||||
|
snow.mCloudTexture = "tx_bm_sky_snow.dds";
|
||||||
|
snow.mCloudsMaximumPercent = 1.0;
|
||||||
|
snow.mTransitionDelta = 0.014;
|
||||||
|
snow.mSkySunriseColor = clr(196, 91, 91);
|
||||||
|
snow.mSkyDayColor = clr(153, 158, 166);
|
||||||
|
snow.mSkySunsetColor = clr(96, 115, 134);
|
||||||
|
snow.mSkyNightColor = clr(31, 35, 39);
|
||||||
|
snow.mFogSunriseColor = clr(106, 91, 91);
|
||||||
|
snow.mFogDayColor = clr(153, 158, 166);
|
||||||
|
snow.mFogSunsetColor = clr(96, 115, 134);
|
||||||
|
snow.mFogNightColor = clr(31, 35, 39);
|
||||||
|
snow.mAmbientSunriseColor = clr(92, 84, 84);
|
||||||
|
snow.mAmbientDayColor = clr(93, 96, 105);
|
||||||
|
snow.mAmbientSunsetColor = clr(70, 79, 87);
|
||||||
|
snow.mAmbientNightColor = clr(49, 58, 68);
|
||||||
|
snow.mSunSunriseColor = clr(141, 109, 109);
|
||||||
|
snow.mSunDayColor = clr(163, 169, 183);
|
||||||
|
snow.mSunSunsetColor = clr(101, 121, 141);
|
||||||
|
snow.mSunNightColor = clr(55, 66, 77);
|
||||||
|
snow.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
snow.mLandFogDayDepth = 1.0;
|
||||||
|
snow.mLandFogNightDepth = 1.2;
|
||||||
|
snow.mWindSpeed = 0;
|
||||||
|
snow.mCloudSpeed = 1.5;
|
||||||
|
snow.mGlareView = 0;
|
||||||
|
mWeatherSettings["snow"] = snow;
|
||||||
|
|
||||||
|
Weather blizzard;
|
||||||
|
blizzard.mCloudTexture = "tx_bm_sky_blizzard.dds";
|
||||||
|
blizzard.mCloudsMaximumPercent = 1.0;
|
||||||
|
blizzard.mTransitionDelta = 0.030;
|
||||||
|
blizzard.mSkySunriseColor = clr(91, 99, 106);
|
||||||
|
blizzard.mSkyDayColor = clr(121, 133, 145);
|
||||||
|
blizzard.mSkySunsetColor = clr(108, 115, 121);
|
||||||
|
blizzard.mSkyNightColor = clr(27, 29, 31);
|
||||||
|
blizzard.mFogSunriseColor = clr(91, 99, 106);
|
||||||
|
blizzard.mFogDayColor = clr(121, 133, 145);
|
||||||
|
blizzard.mFogSunsetColor = clr(108, 115, 121);
|
||||||
|
blizzard.mFogNightColor = clr(21, 24, 28);
|
||||||
|
blizzard.mAmbientSunriseColor = clr(84, 88, 92);
|
||||||
|
blizzard.mAmbientDayColor = clr(93, 96, 105);
|
||||||
|
blizzard.mAmbientSunsetColor = clr(83, 77, 75);
|
||||||
|
blizzard.mAmbientNightColor = clr(53, 62, 70);
|
||||||
|
blizzard.mSunSunriseColor = clr(114, 128, 146);
|
||||||
|
blizzard.mSunDayColor = clr(163, 169, 183);
|
||||||
|
blizzard.mSunSunsetColor = clr(106, 114, 136);
|
||||||
|
blizzard.mSunNightColor = clr(57, 66, 74);
|
||||||
|
blizzard.mSunDiscSunsetColor = clr(128, 128, 128);
|
||||||
|
blizzard.mLandFogDayDepth = 2.8;
|
||||||
|
blizzard.mLandFogNightDepth = 3.0;
|
||||||
|
blizzard.mWindSpeed = 0.9;
|
||||||
|
blizzard.mCloudSpeed = 7.5;
|
||||||
|
blizzard.mGlareView = 0;
|
||||||
|
blizzard.mAmbientLoopSoundID = "BM Blizzard";
|
||||||
|
mWeatherSettings["blizzard"] = blizzard;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
|
{
|
||||||
|
if (instant || mFirstUpdate)
|
||||||
|
{
|
||||||
|
mNextWeather = "";
|
||||||
|
mCurrentWeather = weather;
|
||||||
|
mFirstUpdate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mNextWeather != "")
|
||||||
|
{
|
||||||
|
// transition more than 50% finished?
|
||||||
|
if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60) <= 0.5)
|
||||||
|
mCurrentWeather = mNextWeather;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNextWeather = weather;
|
||||||
|
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherResult WeatherManager::getResult(const String& weather)
|
||||||
|
{
|
||||||
|
const Weather& current = mWeatherSettings[weather];
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
|
result.mCloudBlendFactor = 0;
|
||||||
|
result.mCloudOpacity = current.mCloudsMaximumPercent;
|
||||||
|
result.mWindSpeed = current.mWindSpeed;
|
||||||
|
result.mCloudSpeed = current.mCloudSpeed;
|
||||||
|
result.mGlareView = current.mGlareView;
|
||||||
|
result.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
|
||||||
|
result.mSunColor = current.mSunDiscSunsetColor;
|
||||||
|
|
||||||
|
const float fade_duration = current.mTransitionDelta * 24.f;
|
||||||
|
|
||||||
|
result.mNight = (mHour < 6.f+fade_duration || mHour > 20.f-fade_duration);
|
||||||
|
|
||||||
|
result.mFogDepth = result.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
|
||||||
|
|
||||||
|
// night
|
||||||
|
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration)
|
||||||
|
|| mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration))
|
||||||
|
{
|
||||||
|
result.mFogColor = current.mFogNightColor;
|
||||||
|
result.mAmbientColor = current.mAmbientNightColor;
|
||||||
|
result.mSunColor = current.mSunNightColor;
|
||||||
|
result.mSkyColor = current.mSkyNightColor;
|
||||||
|
result.mNightFade = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sunrise
|
||||||
|
else if (mHour >= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration) && mHour <= WeatherGlobals::mSunriseTime)
|
||||||
|
{
|
||||||
|
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration))
|
||||||
|
{
|
||||||
|
// fade in
|
||||||
|
float advance = (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration)-mHour;
|
||||||
|
float factor = (advance / fade_duration);
|
||||||
|
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor);
|
||||||
|
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor);
|
||||||
|
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor);
|
||||||
|
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor);
|
||||||
|
result.mNightFade = factor;
|
||||||
|
}
|
||||||
|
else if (mHour >= (WeatherGlobals::mSunriseTime-fade_duration))
|
||||||
|
{
|
||||||
|
// fade out
|
||||||
|
float advance = mHour-(WeatherGlobals::mSunriseTime-fade_duration);
|
||||||
|
float factor = advance / fade_duration;
|
||||||
|
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor);
|
||||||
|
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor);
|
||||||
|
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor);
|
||||||
|
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.mFogColor = current.mFogSunriseColor;
|
||||||
|
result.mAmbientColor = current.mAmbientSunriseColor;
|
||||||
|
result.mSunColor = current.mSunSunriseColor;
|
||||||
|
result.mSkyColor = current.mSkySunriseColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// day
|
||||||
|
else if (mHour >= (WeatherGlobals::mSunriseTime) && mHour <= (WeatherGlobals::mSunsetTime))
|
||||||
|
{
|
||||||
|
result.mFogColor = current.mFogDayColor;
|
||||||
|
result.mAmbientColor = current.mAmbientDayColor;
|
||||||
|
result.mSunColor = current.mSunDayColor;
|
||||||
|
result.mSkyColor = current.mSkyDayColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sunset
|
||||||
|
else if (mHour >= (WeatherGlobals::mSunsetTime) && mHour <= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration))
|
||||||
|
{
|
||||||
|
if (mHour <= (WeatherGlobals::mSunsetTime+fade_duration))
|
||||||
|
{
|
||||||
|
// fade in
|
||||||
|
float advance = (WeatherGlobals::mSunsetTime+fade_duration)-mHour;
|
||||||
|
float factor = (advance / fade_duration);
|
||||||
|
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor);
|
||||||
|
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor);
|
||||||
|
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor);
|
||||||
|
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor);
|
||||||
|
}
|
||||||
|
else if (mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration))
|
||||||
|
{
|
||||||
|
// fade out
|
||||||
|
float advance = mHour-(WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration);
|
||||||
|
float factor = advance / fade_duration;
|
||||||
|
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor);
|
||||||
|
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor);
|
||||||
|
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor);
|
||||||
|
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor);
|
||||||
|
result.mNightFade = factor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.mFogColor = current.mFogSunsetColor;
|
||||||
|
result.mAmbientColor = current.mAmbientSunsetColor;
|
||||||
|
result.mSunColor = current.mSunSunsetColor;
|
||||||
|
result.mSkyColor = current.mSkySunsetColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherResult WeatherManager::transition(float factor)
|
||||||
|
{
|
||||||
|
const WeatherResult& current = getResult(mCurrentWeather);
|
||||||
|
const WeatherResult& other = getResult(mNextWeather);
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
|
result.mNextCloudTexture = other.mCloudTexture;
|
||||||
|
result.mCloudBlendFactor = factor;
|
||||||
|
|
||||||
|
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
||||||
|
result.mFogColor = lerp(current.mFogColor, other.mFogColor);
|
||||||
|
result.mSunColor = lerp(current.mSunColor, other.mSunColor);
|
||||||
|
result.mSkyColor = lerp(current.mSkyColor, other.mSkyColor);
|
||||||
|
|
||||||
|
result.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor);
|
||||||
|
result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor);
|
||||||
|
result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth);
|
||||||
|
result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed);
|
||||||
|
result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed);
|
||||||
|
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
||||||
|
result.mGlareView = lerp(current.mGlareView, other.mGlareView);
|
||||||
|
|
||||||
|
result.mNight = current.mNight;
|
||||||
|
|
||||||
|
// sound change behaviour:
|
||||||
|
// if 'other' has a new sound, switch to it after 1/2 of the transition length
|
||||||
|
if (other.mAmbientLoopSoundID != "")
|
||||||
|
result.mAmbientLoopSoundID = factor>0.5 ? other.mAmbientLoopSoundID : current.mAmbientLoopSoundID;
|
||||||
|
// if 'current' has a sound and 'other' does not have a sound, turn off the sound immediately
|
||||||
|
else if (current.mAmbientLoopSoundID != "")
|
||||||
|
result.mAmbientLoopSoundID = "";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::update(float duration)
|
||||||
|
{
|
||||||
|
mWeatherUpdateTime -= duration;
|
||||||
|
if (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior())
|
||||||
|
{
|
||||||
|
std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region;
|
||||||
|
boost::algorithm::to_lower(regionstr);
|
||||||
|
|
||||||
|
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
||||||
|
{
|
||||||
|
mCurrentRegion = regionstr;
|
||||||
|
mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*60.f;
|
||||||
|
|
||||||
|
std::string weather;
|
||||||
|
|
||||||
|
if (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
|
||||||
|
weather = mRegionOverrides[regionstr];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get weather probabilities for the current region
|
||||||
|
const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr);
|
||||||
|
|
||||||
|
float clear = region->data.clear/255.f;
|
||||||
|
float cloudy = region->data.cloudy/255.f;
|
||||||
|
float foggy = region->data.foggy/255.f;
|
||||||
|
float overcast = region->data.overcast/255.f;
|
||||||
|
float rain = region->data.rain/255.f;
|
||||||
|
float thunder = region->data.thunder/255.f;
|
||||||
|
float ash = region->data.ash/255.f;
|
||||||
|
float blight = region->data.blight/255.f;
|
||||||
|
float snow = region->data.a/255.f;
|
||||||
|
float blizzard = region->data.b/255.f;
|
||||||
|
|
||||||
|
// re-scale to 100 percent
|
||||||
|
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight+snow+blizzard;
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
float random = ((rand()%100)/100.f) * total;
|
||||||
|
|
||||||
|
if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
|
weather = "blizzard";
|
||||||
|
else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
|
weather = "snow";
|
||||||
|
else if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
|
weather = "blight";
|
||||||
|
else if (random >= thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
|
weather = "ashstorm";
|
||||||
|
else if (random >= rain+overcast+foggy+cloudy+clear)
|
||||||
|
weather = "thunderstorm";
|
||||||
|
else if (random >= overcast+foggy+cloudy+clear)
|
||||||
|
weather = "rain";
|
||||||
|
else if (random >= foggy+cloudy+clear)
|
||||||
|
weather = "overcast";
|
||||||
|
else if (random >= cloudy+clear)
|
||||||
|
weather = "foggy";
|
||||||
|
else if (random >= clear)
|
||||||
|
weather = "cloudy";
|
||||||
|
else
|
||||||
|
weather = "clear";
|
||||||
|
}
|
||||||
|
|
||||||
|
setWeather(weather, false);
|
||||||
|
/*
|
||||||
|
std::cout << "roll result: " << random << std::endl;
|
||||||
|
|
||||||
|
std::cout << regionstr << " weather probabilities: " << clear << " " << cloudy << " " << foggy << " "
|
||||||
|
<< overcast << " " << rain << " " << thunder << " " << ash << " " << blight << " " << snow << " "
|
||||||
|
<< blizzard << std::endl;
|
||||||
|
|
||||||
|
std::cout << "New weather : " << weather << std::endl;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
if (mNextWeather != "")
|
||||||
|
{
|
||||||
|
mRemainingTransitionTime -= duration;
|
||||||
|
if (mRemainingTransitionTime < 0)
|
||||||
|
{
|
||||||
|
mCurrentWeather = mNextWeather;
|
||||||
|
mNextWeather = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNextWeather != "")
|
||||||
|
result = transition(1-(mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60)));
|
||||||
|
else
|
||||||
|
result = getResult(mCurrentWeather);
|
||||||
|
|
||||||
|
mRendering->configureFog(result.mFogDepth, result.mFogColor);
|
||||||
|
|
||||||
|
// disable sun during night
|
||||||
|
if (mHour >= WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration
|
||||||
|
|| mHour <= WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration)
|
||||||
|
mRendering->getSkyManager()->sunDisable();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// during day, calculate sun angle
|
||||||
|
float height = 1-std::abs(((mHour-13)/7.f));
|
||||||
|
int facing = mHour > 13.f ? 1 : -1;
|
||||||
|
Vector3 final(
|
||||||
|
(1-height)*facing,
|
||||||
|
(1-height)*facing,
|
||||||
|
height);
|
||||||
|
mRendering->setSunDirection(final);
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->sunEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// moon calculations
|
||||||
|
float night;
|
||||||
|
if (mHour >= 14)
|
||||||
|
night = mHour-14;
|
||||||
|
else if (mHour <= 10)
|
||||||
|
night = mHour+10;
|
||||||
|
else
|
||||||
|
night = 0;
|
||||||
|
|
||||||
|
night /= 20.f;
|
||||||
|
|
||||||
|
if (night != 0)
|
||||||
|
{
|
||||||
|
float moonHeight = 1-std::abs((night-0.5)*2);
|
||||||
|
int facing = (mHour > 0.f && mHour<12.f) ? 1 : -1;
|
||||||
|
Vector3 masser(
|
||||||
|
(1-moonHeight)*facing,
|
||||||
|
(1-moonHeight)*facing,
|
||||||
|
moonHeight);
|
||||||
|
|
||||||
|
Vector3 secunda(
|
||||||
|
(1-moonHeight)*facing*0.8,
|
||||||
|
(1-moonHeight)*facing*1.25,
|
||||||
|
moonHeight);
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->setMasserDirection(masser);
|
||||||
|
mRendering->getSkyManager()->setSecundaDirection(secunda);
|
||||||
|
mRendering->getSkyManager()->masserEnable();
|
||||||
|
mRendering->getSkyManager()->secundaEnable();
|
||||||
|
|
||||||
|
float hour_fade;
|
||||||
|
if (mHour >= 7.f && mHour <= 14.f)
|
||||||
|
hour_fade = 1-(mHour-7)/3.f;
|
||||||
|
else if (mHour >= 14 && mHour <= 15.f)
|
||||||
|
hour_fade = mHour-14;
|
||||||
|
else
|
||||||
|
hour_fade = 1;
|
||||||
|
|
||||||
|
float secunda_angle_fade;
|
||||||
|
float masser_angle_fade;
|
||||||
|
float angle = moonHeight*90.f;
|
||||||
|
|
||||||
|
if (angle >= 30 && angle <= 50)
|
||||||
|
secunda_angle_fade = (angle-30)/20.f;
|
||||||
|
else if (angle <30)
|
||||||
|
secunda_angle_fade = 0.f;
|
||||||
|
else
|
||||||
|
secunda_angle_fade = 1.f;
|
||||||
|
|
||||||
|
if (angle >= 40 && angle <= 50)
|
||||||
|
masser_angle_fade = (angle-40)/10.f;
|
||||||
|
else if (angle <40)
|
||||||
|
masser_angle_fade = 0.f;
|
||||||
|
else
|
||||||
|
masser_angle_fade = 1.f;
|
||||||
|
|
||||||
|
masser_angle_fade *= hour_fade;
|
||||||
|
secunda_angle_fade *= hour_fade;
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->setMasserFade(masser_angle_fade);
|
||||||
|
mRendering->getSkyManager()->setSecundaFade(secunda_angle_fade);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mRendering->getSkyManager()->masserDisable();
|
||||||
|
mRendering->getSkyManager()->secundaDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentWeather == "thunderstorm" && mNextWeather == "")
|
||||||
|
{
|
||||||
|
if (mThunderFlash > 0)
|
||||||
|
{
|
||||||
|
// play the sound after a delay
|
||||||
|
mThunderSoundDelay -= duration;
|
||||||
|
if (mThunderSoundDelay <= 0)
|
||||||
|
{
|
||||||
|
// pick a random sound
|
||||||
|
int sound = rand() % 4;
|
||||||
|
std::string soundname;
|
||||||
|
if (sound == 0) soundname = WeatherGlobals::mThunderSoundID0;
|
||||||
|
else if (sound == 1) soundname = WeatherGlobals::mThunderSoundID1;
|
||||||
|
else if (sound == 2) soundname = WeatherGlobals::mThunderSoundID2;
|
||||||
|
else if (sound == 3) soundname = WeatherGlobals::mThunderSoundID3;
|
||||||
|
mEnvironment->mSoundManager->playSound(soundname, 1.0, 1.0);
|
||||||
|
mThunderSoundDelay = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
mThunderFlash -= duration;
|
||||||
|
if (mThunderFlash > 0)
|
||||||
|
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srand(time(NULL));
|
||||||
|
mThunderChanceNeeded = rand() % 100;
|
||||||
|
mThunderChance = 0;
|
||||||
|
mRendering->getSkyManager()->setThunder( 0.f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no thunder active
|
||||||
|
mThunderChance += duration*4; // chance increases by 4 percent every second
|
||||||
|
if (mThunderChance >= mThunderChanceNeeded)
|
||||||
|
{
|
||||||
|
mThunderFlash = WeatherGlobals::mThunderThreshold;
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
||||||
|
|
||||||
|
mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mRendering->getSkyManager()->setThunder(0.f);
|
||||||
|
|
||||||
|
mRendering->setAmbientColour(result.mAmbientColor);
|
||||||
|
mRendering->sunEnable();
|
||||||
|
mRendering->setSunColour(result.mSunColor);
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->setWeather(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mRendering->sunDisable();
|
||||||
|
mRendering->skyDisable();
|
||||||
|
mRendering->getSkyManager()->setThunder(0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::setHour(const float hour)
|
||||||
|
{
|
||||||
|
// accelerate a bit for testing
|
||||||
|
/*
|
||||||
|
mHour += 0.005;
|
||||||
|
|
||||||
|
if (mHour >= 24.f) mHour = 0.f;
|
||||||
|
|
||||||
|
std::cout << "hour " << mHour << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
mHour = hour;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::setDate(const int day, const int month)
|
||||||
|
{
|
||||||
|
mDay = day;
|
||||||
|
mMonth = month;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int WeatherManager::getWeatherID() const
|
||||||
|
{
|
||||||
|
// Source: http://www.uesp.net/wiki/Tes3Mod:GetCurrentWeather
|
||||||
|
|
||||||
|
if (mCurrentWeather == "clear")
|
||||||
|
return 0;
|
||||||
|
else if (mCurrentWeather == "cloudy")
|
||||||
|
return 1;
|
||||||
|
else if (mCurrentWeather == "foggy")
|
||||||
|
return 2;
|
||||||
|
else if (mCurrentWeather == "overcast")
|
||||||
|
return 3;
|
||||||
|
else if (mCurrentWeather == "rain")
|
||||||
|
return 4;
|
||||||
|
else if (mCurrentWeather == "thunder")
|
||||||
|
return 5;
|
||||||
|
else if (mCurrentWeather == "ashstorm")
|
||||||
|
return 6;
|
||||||
|
else if (mCurrentWeather == "blight")
|
||||||
|
return 7;
|
||||||
|
else if (mCurrentWeather == "snow")
|
||||||
|
return 8;
|
||||||
|
else if (mCurrentWeather == "blizzard")
|
||||||
|
return 9;
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::changeWeather(const std::string& region, const unsigned int id)
|
||||||
|
{
|
||||||
|
std::string weather;
|
||||||
|
if (id==0)
|
||||||
|
weather = "clear";
|
||||||
|
else if (id==1)
|
||||||
|
weather = "cloudy";
|
||||||
|
else if (id==2)
|
||||||
|
weather = "foggy";
|
||||||
|
else if (id==3)
|
||||||
|
weather = "overcast";
|
||||||
|
else if (id==4)
|
||||||
|
weather = "rain";
|
||||||
|
else if (id==5)
|
||||||
|
weather = "thunder";
|
||||||
|
else if (id==6)
|
||||||
|
weather = "ashstorm";
|
||||||
|
else if (id==7)
|
||||||
|
weather = "blight";
|
||||||
|
else if (id==8)
|
||||||
|
weather = "snow";
|
||||||
|
else if (id==9)
|
||||||
|
weather = "blizzard";
|
||||||
|
else
|
||||||
|
weather = "clear";
|
||||||
|
|
||||||
|
mRegionOverrides[region] = weather;
|
||||||
|
}
|
@ -0,0 +1,272 @@
|
|||||||
|
#ifndef GAME_MWWORLD_WEATHER_H
|
||||||
|
#define GAME_MWWORLD_WEATHER_H
|
||||||
|
|
||||||
|
#include <OgreString.h>
|
||||||
|
#include <OgreColourValue.h>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
class RenderingManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Environment;
|
||||||
|
|
||||||
|
/// Global weather manager properties (according to INI)
|
||||||
|
struct WeatherGlobals
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
[Weather]
|
||||||
|
EnvReduceColor=255,255,255,255
|
||||||
|
LerpCloseColor=037,046,048,255
|
||||||
|
BumpFadeColor=230,239,255,255
|
||||||
|
AlphaReduce=0.35
|
||||||
|
Minimum Time Between Environmental Sounds=1.0
|
||||||
|
Maximum Time Between Environmental Sounds=5.0
|
||||||
|
Sun Glare Fader Max=0.5
|
||||||
|
Sun Glare Fader Angle Max=30.0
|
||||||
|
Sun Glare Fader Color=222,095,039
|
||||||
|
Timescale Clouds=0
|
||||||
|
Precip Gravity=575
|
||||||
|
Hours Between Weather Changes=20
|
||||||
|
Rain Ripples=1
|
||||||
|
Rain Ripple Radius=1024
|
||||||
|
Rain Ripples Per Drop=1
|
||||||
|
Rain Ripple Scale=0.3
|
||||||
|
Rain Ripple Speed=1.0
|
||||||
|
Fog Depth Change Speed=3
|
||||||
|
Sunrise Time=6
|
||||||
|
Sunset Time=18
|
||||||
|
Sunrise Duration=2
|
||||||
|
Sunset Duration=2
|
||||||
|
Sky Pre-Sunrise Time=.5
|
||||||
|
Sky Post-Sunrise Time=1
|
||||||
|
Sky Pre-Sunset Time=1.5
|
||||||
|
Sky Post-Sunset Time=.5
|
||||||
|
Ambient Pre-Sunrise Time=.5
|
||||||
|
Ambient Post-Sunrise Time=2
|
||||||
|
Ambient Pre-Sunset Time=1
|
||||||
|
Ambient Post-Sunset Time=1.25
|
||||||
|
Fog Pre-Sunrise Time=.5
|
||||||
|
Fog Post-Sunrise Time=1
|
||||||
|
Fog Pre-Sunset Time=2
|
||||||
|
Fog Post-Sunset Time=1
|
||||||
|
Sun Pre-Sunrise Time=0
|
||||||
|
Sun Post-Sunrise Time=0
|
||||||
|
Sun Pre-Sunset Time=1
|
||||||
|
Sun Post-Sunset Time=1.25
|
||||||
|
Stars Post-Sunset Start=1
|
||||||
|
Stars Pre-Sunrise Finish=2
|
||||||
|
Stars Fading Duration=2
|
||||||
|
Snow Ripples=0
|
||||||
|
Snow Ripple Radius=1024
|
||||||
|
Snow Ripples Per Flake=1
|
||||||
|
Snow Ripple Scale=0.3
|
||||||
|
Snow Ripple Speed=1.0
|
||||||
|
Snow Gravity Scale=0.1
|
||||||
|
Snow High Kill=700
|
||||||
|
Snow Low Kill=150
|
||||||
|
|
||||||
|
|
||||||
|
[Moons]
|
||||||
|
Masser Size=94
|
||||||
|
Masser Fade In Start=14
|
||||||
|
Masser Fade In Finish=15
|
||||||
|
Masser Fade Out Start=7
|
||||||
|
Masser Fade Out Finish=10
|
||||||
|
Masser Axis Offset=35
|
||||||
|
Masser Speed=.5
|
||||||
|
Masser Daily Increment=1
|
||||||
|
Masser Fade Start Angle=50
|
||||||
|
Masser Fade End Angle=40
|
||||||
|
Masser Moon Shadow Early Fade Angle=0.5
|
||||||
|
Secunda Size=40
|
||||||
|
Secunda Fade In Start=14
|
||||||
|
Secunda Fade In Finish=15
|
||||||
|
Secunda Fade Out Start=7
|
||||||
|
Secunda Fade Out Finish=10
|
||||||
|
Secunda Axis Offset=50
|
||||||
|
Secunda Speed=.6
|
||||||
|
Secunda Daily Increment=1.2
|
||||||
|
Secunda Fade Start Angle=50
|
||||||
|
Secunda Fade End Angle=30
|
||||||
|
Secunda Moon Shadow Early Fade Angle=0.5
|
||||||
|
Script Color=255,20,20
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const float mSunriseTime = 8;
|
||||||
|
static const float mSunsetTime = 18;
|
||||||
|
static const float mSunriseDuration = 2;
|
||||||
|
static const float mSunsetDuration = 2;
|
||||||
|
|
||||||
|
static const float mWeatherUpdateTime = 20.f;
|
||||||
|
|
||||||
|
// morrowind sets these per-weather, but since they are only used by 'thunderstorm'
|
||||||
|
// weather setting anyway, we can just as well set them globally
|
||||||
|
static const float mThunderFrequency = .4;
|
||||||
|
static const float mThunderThreshold = 0.6;
|
||||||
|
static const float mThunderSoundDelay = 0.25;
|
||||||
|
static const std::string mThunderSoundID0;
|
||||||
|
static const std::string mThunderSoundID1;
|
||||||
|
static const std::string mThunderSoundID2;
|
||||||
|
static const std::string mThunderSoundID3;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Defines the actual weather that results from weather setting (see below), time of day and weather transition
|
||||||
|
struct WeatherResult
|
||||||
|
{
|
||||||
|
Ogre::String mCloudTexture;
|
||||||
|
Ogre::String mNextCloudTexture;
|
||||||
|
float mCloudBlendFactor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mFogColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mAmbientColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mSkyColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mSunColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mSunDiscColor;
|
||||||
|
|
||||||
|
float mFogDepth;
|
||||||
|
|
||||||
|
float mWindSpeed;
|
||||||
|
|
||||||
|
float mCloudSpeed;
|
||||||
|
|
||||||
|
float mCloudOpacity;
|
||||||
|
|
||||||
|
float mGlareView;
|
||||||
|
|
||||||
|
bool mNight; // use night skybox
|
||||||
|
float mNightFade; // fading factor for night skybox
|
||||||
|
|
||||||
|
Ogre::String mAmbientLoopSoundID;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Defines a single weather setting (according to INI)
|
||||||
|
struct Weather
|
||||||
|
{
|
||||||
|
Ogre::String mCloudTexture;
|
||||||
|
|
||||||
|
// Sky (atmosphere) colors
|
||||||
|
Ogre::ColourValue mSkySunriseColor,
|
||||||
|
mSkyDayColor,
|
||||||
|
mSkySunsetColor,
|
||||||
|
mSkyNightColor;
|
||||||
|
|
||||||
|
// Fog colors
|
||||||
|
Ogre::ColourValue mFogSunriseColor,
|
||||||
|
mFogDayColor,
|
||||||
|
mFogSunsetColor,
|
||||||
|
mFogNightColor;
|
||||||
|
|
||||||
|
// Ambient lighting colors
|
||||||
|
Ogre::ColourValue mAmbientSunriseColor,
|
||||||
|
mAmbientDayColor,
|
||||||
|
mAmbientSunsetColor,
|
||||||
|
mAmbientNightColor;
|
||||||
|
|
||||||
|
// Sun (directional) lighting colors
|
||||||
|
Ogre::ColourValue mSunSunriseColor,
|
||||||
|
mSunDayColor,
|
||||||
|
mSunSunsetColor,
|
||||||
|
mSunNightColor;
|
||||||
|
|
||||||
|
// Fog depth/density
|
||||||
|
float mLandFogDayDepth,
|
||||||
|
mLandFogNightDepth;
|
||||||
|
|
||||||
|
// Color modulation for the sun itself during sunset (not completely sure)
|
||||||
|
Ogre::ColourValue mSunDiscSunsetColor;
|
||||||
|
|
||||||
|
// Duration of weather transition (in days)
|
||||||
|
float mTransitionDelta;
|
||||||
|
|
||||||
|
// No idea what this one is used for?
|
||||||
|
float mWindSpeed;
|
||||||
|
|
||||||
|
// Cloud animation speed multiplier
|
||||||
|
float mCloudSpeed;
|
||||||
|
|
||||||
|
// Multiplier for clouds transparency
|
||||||
|
float mCloudsMaximumPercent;
|
||||||
|
|
||||||
|
// Value between 0 and 1, defines the strength of the sun glare effect
|
||||||
|
float mGlareView;
|
||||||
|
|
||||||
|
// Sound effect
|
||||||
|
// This is used for Blight, Ashstorm and Blizzard (Bloodmoon)
|
||||||
|
Ogre::String mAmbientLoopSoundID;
|
||||||
|
|
||||||
|
// Rain sound effect
|
||||||
|
Ogre::String mRainLoopSoundID;
|
||||||
|
|
||||||
|
/// \todo disease chance
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Interface for weather settings
|
||||||
|
///
|
||||||
|
class WeatherManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WeatherManager(MWRender::RenderingManager*, MWWorld::Environment*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the weather in the specified region
|
||||||
|
* @param region that should be changed
|
||||||
|
* @param ID of the weather setting to shift to
|
||||||
|
*/
|
||||||
|
void changeWeather(const std::string& region, const unsigned int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per-frame update
|
||||||
|
* @param duration
|
||||||
|
*/
|
||||||
|
void update(float duration);
|
||||||
|
|
||||||
|
void setHour(const float hour);
|
||||||
|
|
||||||
|
void setDate(const int day, const int month);
|
||||||
|
|
||||||
|
unsigned int getWeatherID() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float mHour;
|
||||||
|
int mDay, mMonth;
|
||||||
|
|
||||||
|
MWRender::RenderingManager* mRendering;
|
||||||
|
MWWorld::Environment* mEnvironment;
|
||||||
|
|
||||||
|
std::map<Ogre::String, Weather> mWeatherSettings;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> mRegionOverrides;
|
||||||
|
|
||||||
|
Ogre::String mCurrentWeather;
|
||||||
|
Ogre::String mNextWeather;
|
||||||
|
|
||||||
|
std::string mCurrentRegion;
|
||||||
|
|
||||||
|
bool mFirstUpdate;
|
||||||
|
|
||||||
|
float mWeatherUpdateTime;
|
||||||
|
|
||||||
|
float mRemainingTransitionTime;
|
||||||
|
|
||||||
|
float mThunderFlash;
|
||||||
|
float mThunderChance;
|
||||||
|
float mThunderChanceNeeded;
|
||||||
|
float mThunderSoundDelay;
|
||||||
|
|
||||||
|
WeatherResult transition(const float factor);
|
||||||
|
WeatherResult getResult(const Ogre::String& weather);
|
||||||
|
|
||||||
|
void setWeather(const Ogre::String& weather, bool instant=false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GAME_MWWORLD_WEATHER_H
|
@ -1,157 +0,0 @@
|
|||||||
#include "configurationmanager.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Cfg
|
|
||||||
{
|
|
||||||
|
|
||||||
static const char* const openmwCfgFile = "openmw.cfg";
|
|
||||||
static const char* const ogreCfgFile = "ogre.cfg";
|
|
||||||
static const char* const pluginsCfgFile = "plugins.cfg";
|
|
||||||
|
|
||||||
|
|
||||||
ConfigurationManager::ConfigurationManager()
|
|
||||||
: mPath("openmw")
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* According to task #168 plugins.cfg file shall be located in global
|
|
||||||
* configuration path or in runtime configuration path.
|
|
||||||
*/
|
|
||||||
mPluginsCfgPath = mPath.getGlobalConfigPath() / pluginsCfgFile;
|
|
||||||
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
|
|
||||||
{
|
|
||||||
mPluginsCfgPath = mPath.getRuntimeConfigPath() / pluginsCfgFile;
|
|
||||||
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl;
|
|
||||||
mPluginsCfgPath.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* According to task #168 ogre.cfg file shall be located only
|
|
||||||
* in user configuration path.
|
|
||||||
*/
|
|
||||||
mOgreCfgPath = mPath.getLocalConfigPath() / ogreCfgFile;
|
|
||||||
|
|
||||||
mLogPath = mPath.getLocalConfigPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigurationManager::~ConfigurationManager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables,
|
|
||||||
boost::program_options::options_description& description)
|
|
||||||
{
|
|
||||||
loadConfig(mPath.getLocalConfigPath(), variables, description);
|
|
||||||
boost::program_options::notify(variables);
|
|
||||||
loadConfig(mPath.getRuntimeConfigPath(), variables, description);
|
|
||||||
boost::program_options::notify(variables);
|
|
||||||
loadConfig(mPath.getGlobalConfigPath(), variables, description);
|
|
||||||
boost::program_options::notify(variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::loadConfig(const boost::filesystem::path& path,
|
|
||||||
boost::program_options::variables_map& variables,
|
|
||||||
boost::program_options::options_description& description)
|
|
||||||
{
|
|
||||||
boost::filesystem::path cfgFile(path);
|
|
||||||
cfgFile /= std::string(openmwCfgFile);
|
|
||||||
if (boost::filesystem::is_regular_file(cfgFile))
|
|
||||||
{
|
|
||||||
std::cout << "Loading config file: " << cfgFile.string() << "... ";
|
|
||||||
|
|
||||||
std::ifstream configFileStream(cfgFile.string().c_str());
|
|
||||||
if (configFileStream.is_open())
|
|
||||||
{
|
|
||||||
boost::program_options::store(boost::program_options::parse_config_file(
|
|
||||||
configFileStream, description), variables);
|
|
||||||
|
|
||||||
std::cout << "done." << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "failed." << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getGlobalConfigPath() const
|
|
||||||
{
|
|
||||||
return mPath.getGlobalConfigPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setGlobalConfigPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setGlobalConfigPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getLocalConfigPath() const
|
|
||||||
{
|
|
||||||
return mPath.getLocalConfigPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setLocalConfigPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setLocalConfigPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getRuntimeConfigPath() const
|
|
||||||
{
|
|
||||||
return mPath.getRuntimeConfigPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setRuntimeConfigPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setRuntimeConfigPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getGlobalDataPath() const
|
|
||||||
{
|
|
||||||
return mPath.getGlobalDataPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setGlobalDataPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setGlobalDataPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getLocalDataPath() const
|
|
||||||
{
|
|
||||||
return mPath.getLocalDataPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setLocalDataPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setLocalDataPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getRuntimeDataPath() const
|
|
||||||
{
|
|
||||||
return mPath.getRuntimeDataPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurationManager::setRuntimeDataPath(const boost::filesystem::path& newPath)
|
|
||||||
{
|
|
||||||
mPath.setRuntimeDataPath(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const
|
|
||||||
{
|
|
||||||
return mOgreCfgPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const
|
|
||||||
{
|
|
||||||
return mPluginsCfgPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boost::filesystem::path& ConfigurationManager::getLogPath() const
|
|
||||||
{
|
|
||||||
return mLogPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace Cfg */
|
|
@ -1,62 +0,0 @@
|
|||||||
#ifndef COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP
|
|
||||||
#define COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP
|
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <components/files/path.hpp>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \namespace Cfg
|
|
||||||
*/
|
|
||||||
namespace Cfg
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \struct ConfigurationManager
|
|
||||||
*/
|
|
||||||
struct ConfigurationManager
|
|
||||||
{
|
|
||||||
ConfigurationManager();
|
|
||||||
virtual ~ConfigurationManager();
|
|
||||||
|
|
||||||
void readConfiguration(boost::program_options::variables_map& variables,
|
|
||||||
boost::program_options::options_description& description);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getGlobalConfigPath() const;
|
|
||||||
void setGlobalConfigPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getLocalConfigPath() const;
|
|
||||||
void setLocalConfigPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getRuntimeConfigPath() const;
|
|
||||||
void setRuntimeConfigPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getGlobalDataPath() const;
|
|
||||||
void setGlobalDataPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getLocalDataPath() const;
|
|
||||||
void setLocalDataPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getRuntimeDataPath() const;
|
|
||||||
void setRuntimeDataPath(const boost::filesystem::path& newPath);
|
|
||||||
|
|
||||||
const boost::filesystem::path& getOgreConfigPath() const;
|
|
||||||
const boost::filesystem::path& getPluginsConfigPath() const;
|
|
||||||
const boost::filesystem::path& getLogPath() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadConfig(const boost::filesystem::path& path,
|
|
||||||
boost::program_options::variables_map& variables,
|
|
||||||
boost::program_options::options_description& description);
|
|
||||||
|
|
||||||
Files::Path<> mPath;
|
|
||||||
|
|
||||||
boost::filesystem::path mOgreCfgPath;
|
|
||||||
boost::filesystem::path mPluginsCfgPath;
|
|
||||||
boost::filesystem::path mLogPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Cfg */
|
|
||||||
|
|
||||||
#endif /* COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP */
|
|
@ -0,0 +1,182 @@
|
|||||||
|
#include "configurationmanager.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/algorithm/string/erase.hpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \namespace Files
|
||||||
|
*/
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
|
||||||
|
static const char* const openmwCfgFile = "openmw.cfg";
|
||||||
|
static const char* const ogreCfgFile = "ogre.cfg";
|
||||||
|
static const char* const pluginsCfgFile = "plugins.cfg";
|
||||||
|
|
||||||
|
const char* const mwToken = "?mw?";
|
||||||
|
const char* const localToken = "?local?";
|
||||||
|
const char* const userToken = "?user?";
|
||||||
|
const char* const globalToken = "?global?";
|
||||||
|
|
||||||
|
ConfigurationManager::ConfigurationManager()
|
||||||
|
: mFixedPath("openmw")
|
||||||
|
{
|
||||||
|
setupTokensMapping();
|
||||||
|
|
||||||
|
mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile;
|
||||||
|
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
|
||||||
|
{
|
||||||
|
mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile;
|
||||||
|
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl;
|
||||||
|
mPluginsCfgPath.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mOgreCfgPath = mFixedPath.getUserPath() / ogreCfgFile;
|
||||||
|
mLogPath = mFixedPath.getUserPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationManager::~ConfigurationManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigurationManager::setupTokensMapping()
|
||||||
|
{
|
||||||
|
mTokensMapping.insert(std::make_pair(mwToken, &FixedPath<>::getInstallPath));
|
||||||
|
mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath));
|
||||||
|
mTokensMapping.insert(std::make_pair(userToken, &FixedPath<>::getUserPath));
|
||||||
|
mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables,
|
||||||
|
boost::program_options::options_description& description)
|
||||||
|
{
|
||||||
|
loadConfig(mFixedPath.getUserPath(), variables, description);
|
||||||
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
|
loadConfig(mFixedPath.getLocalPath(), variables, description);
|
||||||
|
boost::program_options::notify(variables);
|
||||||
|
loadConfig(mFixedPath.getGlobalPath(), variables, description);
|
||||||
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigurationManager::processPaths(Files::PathContainer& dataDirs)
|
||||||
|
{
|
||||||
|
std::string path;
|
||||||
|
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
|
||||||
|
{
|
||||||
|
path = it->string();
|
||||||
|
boost::erase_all(path, "\"");
|
||||||
|
*it = boost::filesystem::path(path);
|
||||||
|
|
||||||
|
// Check if path contains a token
|
||||||
|
if (!path.empty() && *path.begin() == '?')
|
||||||
|
{
|
||||||
|
std::string::size_type pos = path.find('?', 1);
|
||||||
|
if (pos != std::string::npos && pos != 0)
|
||||||
|
{
|
||||||
|
TokensMappingContainer::iterator tokenIt = mTokensMapping.find(path.substr(0, pos + 1));
|
||||||
|
if (tokenIt != mTokensMapping.end())
|
||||||
|
{
|
||||||
|
boost::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))());
|
||||||
|
if (pos < path.length() - 1)
|
||||||
|
{
|
||||||
|
// There is something after the token, so we should
|
||||||
|
// append it to the path
|
||||||
|
tempPath /= path.substr(pos + 1, path.length() - pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
*it = tempPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clean invalid / unknown token, it will be removed outside the loop
|
||||||
|
(*it).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_directory(*it))
|
||||||
|
{
|
||||||
|
(*it).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataDirs.erase(std::remove_if(dataDirs.begin(), dataDirs.end(),
|
||||||
|
boost::bind(&boost::filesystem::path::empty, _1)), dataDirs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigurationManager::loadConfig(const boost::filesystem::path& path,
|
||||||
|
boost::program_options::variables_map& variables,
|
||||||
|
boost::program_options::options_description& description)
|
||||||
|
{
|
||||||
|
boost::filesystem::path cfgFile(path);
|
||||||
|
cfgFile /= std::string(openmwCfgFile);
|
||||||
|
if (boost::filesystem::is_regular_file(cfgFile))
|
||||||
|
{
|
||||||
|
std::cout << "Loading config file: " << cfgFile.string() << "... ";
|
||||||
|
|
||||||
|
std::ifstream configFileStream(cfgFile.string().c_str());
|
||||||
|
if (configFileStream.is_open())
|
||||||
|
{
|
||||||
|
boost::program_options::store(boost::program_options::parse_config_file(
|
||||||
|
configFileStream, description, true), variables);
|
||||||
|
|
||||||
|
std::cout << "done." << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "failed." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getGlobalPath() const
|
||||||
|
{
|
||||||
|
return mFixedPath.getGlobalPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getUserPath() const
|
||||||
|
{
|
||||||
|
return mFixedPath.getUserPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getLocalPath() const
|
||||||
|
{
|
||||||
|
return mFixedPath.getLocalPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getGlobalDataPath() const
|
||||||
|
{
|
||||||
|
return mFixedPath.getGlobalDataPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getInstallPath() const
|
||||||
|
{
|
||||||
|
return mFixedPath.getInstallPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const
|
||||||
|
{
|
||||||
|
return mOgreCfgPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const
|
||||||
|
{
|
||||||
|
return mPluginsCfgPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& ConfigurationManager::getLogPath() const
|
||||||
|
{
|
||||||
|
return mLogPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace Cfg */
|
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
|
||||||
|
#define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <boost/tr1/tr1/unordered_map>
|
||||||
|
#else
|
||||||
|
#include <tr1/unordered_map>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <components/files/fixedpath.hpp>
|
||||||
|
#include <components/files/collections.hpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \namespace Files
|
||||||
|
*/
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct ConfigurationManager
|
||||||
|
*/
|
||||||
|
struct ConfigurationManager
|
||||||
|
{
|
||||||
|
ConfigurationManager();
|
||||||
|
virtual ~ConfigurationManager();
|
||||||
|
|
||||||
|
void readConfiguration(boost::program_options::variables_map& variables,
|
||||||
|
boost::program_options::options_description& description);
|
||||||
|
void processPaths(Files::PathContainer& dataDirs);
|
||||||
|
|
||||||
|
/**< Fixed paths */
|
||||||
|
const boost::filesystem::path& getGlobalPath() const;
|
||||||
|
const boost::filesystem::path& getUserPath() const;
|
||||||
|
const boost::filesystem::path& getLocalPath() const;
|
||||||
|
|
||||||
|
const boost::filesystem::path& getGlobalDataPath() const;
|
||||||
|
const boost::filesystem::path& getUserDataPath() const;
|
||||||
|
const boost::filesystem::path& getLocalDataPath() const;
|
||||||
|
const boost::filesystem::path& getInstallPath() const;
|
||||||
|
|
||||||
|
const boost::filesystem::path& getOgreConfigPath() const;
|
||||||
|
const boost::filesystem::path& getPluginsConfigPath() const;
|
||||||
|
const boost::filesystem::path& getLogPath() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef Files::FixedPath<> FixedPathType;
|
||||||
|
|
||||||
|
typedef const boost::filesystem::path& (FixedPathType::*path_type_f)() const;
|
||||||
|
typedef std::tr1::unordered_map<std::string, path_type_f> TokensMappingContainer;
|
||||||
|
|
||||||
|
void loadConfig(const boost::filesystem::path& path,
|
||||||
|
boost::program_options::variables_map& variables,
|
||||||
|
boost::program_options::options_description& description);
|
||||||
|
|
||||||
|
void setupTokensMapping();
|
||||||
|
|
||||||
|
FixedPathType mFixedPath;
|
||||||
|
|
||||||
|
boost::filesystem::path mOgreCfgPath;
|
||||||
|
boost::filesystem::path mPluginsCfgPath;
|
||||||
|
boost::filesystem::path mLogPath;
|
||||||
|
|
||||||
|
TokensMappingContainer mTokensMapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace Cfg */
|
||||||
|
|
||||||
|
#endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */
|
@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
* Open Morrowind - an opensource Elder Scrolls III: Morrowind
|
||||||
|
* engine implementation.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Open Morrowind Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file components/files/fixedpath.hpp */
|
||||||
|
|
||||||
|
#ifndef COMPONENTS_FILES_FIXEDPATH_HPP
|
||||||
|
#define COMPONENTS_FILES_FIXEDPATH_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
|
#include <components/files/linuxpath.hpp>
|
||||||
|
namespace Files { typedef LinuxPath TargetPathType; }
|
||||||
|
|
||||||
|
#elif defined(__WIN32) || defined(__WINDOWS__) || defined(_WIN32)
|
||||||
|
#include <components/files/windowspath.hpp>
|
||||||
|
namespace Files { typedef WindowsPath TargetPathType; }
|
||||||
|
|
||||||
|
#elif defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__)
|
||||||
|
#include <components/files/macospath.hpp>
|
||||||
|
namespace Files { typedef MacOsPath TargetPathType; }
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Unknown platform!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \namespace Files
|
||||||
|
*/
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct Path
|
||||||
|
*
|
||||||
|
* \tparam P - Path strategy class type (depends on target system)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template
|
||||||
|
<
|
||||||
|
class P = TargetPathType
|
||||||
|
>
|
||||||
|
struct FixedPath
|
||||||
|
{
|
||||||
|
typedef P PathType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Path constructor.
|
||||||
|
*
|
||||||
|
* \param [in] application_name - Name of the application
|
||||||
|
*/
|
||||||
|
FixedPath(const std::string& application_name)
|
||||||
|
: mPath()
|
||||||
|
, mUserPath(mPath.getUserPath())
|
||||||
|
, mGlobalPath(mPath.getGlobalPath())
|
||||||
|
, mLocalPath(mPath.getLocalPath())
|
||||||
|
, mGlobalDataPath(mPath.getGlobalDataPath())
|
||||||
|
, mInstallPath(mPath.getInstallPath())
|
||||||
|
{
|
||||||
|
if (!application_name.empty())
|
||||||
|
{
|
||||||
|
boost::filesystem::path suffix(application_name + std::string("/"));
|
||||||
|
|
||||||
|
mUserPath /= suffix;
|
||||||
|
mGlobalPath /= suffix;
|
||||||
|
mGlobalDataPath /= suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return path pointing to the user local configuration directory.
|
||||||
|
*
|
||||||
|
* \return boost::filesystem::path
|
||||||
|
*/
|
||||||
|
const boost::filesystem::path& getUserPath() const
|
||||||
|
{
|
||||||
|
return mUserPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return path pointing to the global (system) configuration directory.
|
||||||
|
*
|
||||||
|
* \return boost::filesystem::path
|
||||||
|
*/
|
||||||
|
const boost::filesystem::path& getGlobalPath() const
|
||||||
|
{
|
||||||
|
return mGlobalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return path pointing to the directory where application was started.
|
||||||
|
*
|
||||||
|
* \return boost::filesystem::path
|
||||||
|
*/
|
||||||
|
const boost::filesystem::path& getLocalPath() const
|
||||||
|
{
|
||||||
|
return mLocalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& getInstallPath() const
|
||||||
|
{
|
||||||
|
return mInstallPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& getGlobalDataPath() const
|
||||||
|
{
|
||||||
|
return mGlobalDataPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PathType mPath;
|
||||||
|
|
||||||
|
boost::filesystem::path mUserPath; /**< User path */
|
||||||
|
boost::filesystem::path mGlobalPath; /**< Global path */
|
||||||
|
boost::filesystem::path mLocalPath; /**< It is the same directory where application was run */
|
||||||
|
|
||||||
|
boost::filesystem::path mGlobalDataPath; /**< Global application data path */
|
||||||
|
|
||||||
|
boost::filesystem::path mInstallPath;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace Files */
|
||||||
|
|
||||||
|
#endif /* COMPONENTS_FILES_FIXEDPATH_HPP */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue