Merge branch 'next'

Conflicts:
	.gitignore
	cmake/FindOGRE.cmake
actorid
Marc Zinnschlag 13 years ago
commit be70d197e5

4
.gitignore vendored

@ -10,4 +10,6 @@ CMakeCache.txt
moc_*.cxx moc_*.cxx
cmake_install.cmake cmake_install.cmake
*.[ao] *.[ao]
Makefile
makefile
data

@ -96,6 +96,7 @@ source_group(libs\\mangle FILES ${MANGLE_ALL})
set(OENGINE_OGRE set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp ${LIBDIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/mouselook.cpp ${LIBDIR}/openengine/ogre/mouselook.cpp
${LIBDIR}/openengine/ogre/fader.cpp
) )
set(OENGINE_GUI set(OENGINE_GUI
${LIBDIR}/openengine/gui/events.cpp ${LIBDIR}/openengine/gui/events.cpp
@ -192,7 +193,6 @@ include_directories("."
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE
${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}
${PLATFORM_INCLUDE_DIR} ${PLATFORM_INCLUDE_DIR}
${CMAKE_HOME_DIRECTORY}/extern/caelum/include
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include ${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/OgrePlatform/include ${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/OgrePlatform/include
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
@ -206,10 +206,10 @@ if(APPLE)
# List used Ogre plugins # List used Ogre plugins
SET(USED_OGRE_PLUGINS "RenderSystem_GL" SET(USED_OGRE_PLUGINS "RenderSystem_GL"
"Plugin_OctreeSceneManager" "Plugin_OctreeSceneManager"
"Plugin_CgProgramManager"
"Plugin_ParticleFX") "Plugin_ParticleFX")
endif(APPLE) endif(APPLE)
add_subdirectory( extern/caelum )
add_subdirectory( extern/mygui_3.0.1 ) add_subdirectory( extern/mygui_3.0.1 )
# Make sure that certain libraries are used as static libraries # Make sure that certain libraries are used as static libraries
@ -219,9 +219,6 @@ add_subdirectory( extern/mygui_3.0.1 )
# MyGUI: extern/mygui_3.0.0/ # MyGUI: extern/mygui_3.0.0/
add_definitions(-DMYGUI_STATIC) add_definitions(-DMYGUI_STATIC)
# Caelum: extern/caelum/
add_definitions(-DCAELUM_STATIC)
# Specify build paths # Specify build paths
if (APPLE) if (APPLE)

@ -1,6 +1,4 @@
set(ESMTOOL set(ESMTOOL
esmtool_cmd.c
esmtool_cmd.h
esmtool.cpp esmtool.cpp
) )
source_group(apps\\esmtool FILES ${ESMTOOL}) source_group(apps\\esmtool FILES ${ESMTOOL})

@ -1,5 +0,0 @@
esmtool_cmd.c: esmtool.ggo
gengetopt < esmtool.ggo
clean:
rm esmtool_cmd.c esmtool_cmd.h

@ -1,35 +1,138 @@
#include <iostream>
#include <boost/program_options.hpp>
#include <components/esm/esm_reader.hpp> #include <components/esm/esm_reader.hpp>
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include "esmtool_cmd.h" #define ESMTOOL_VERSION 1.1
#include <iostream>
using namespace std; using namespace std;
using namespace ESM; using namespace ESM;
// Create a local alias for brevity
namespace bpo = boost::program_options;
void printRaw(ESMReader &esm); void printRaw(ESMReader &esm);
void loadCell(Cell &cell, ESMReader &esm, bool quiet); void loadCell(Cell &cell, ESMReader &esm, bool quiet);
int main(int argc, char**argv) // Based on the legacy struct
struct Arguments
{ {
gengetopt_args_info info; unsigned int raw_given;
unsigned int quiet_given;
unsigned int loadcells_given;
std::string encoding;
std::string filename;
};
if(cmdline_parser(argc, argv, &info) != 0) bool parseOptions (int argc, char** argv, Arguments &info)
return 1; {
bpo::options_description desc("Inspect and extract from Morrowind ES files (ESM, ESP, ESS)\nSyntax: esmtool [options] file \nAllowed options");
desc.add_options()
("help,h", "print help message.")
("version,v", "print version information and quit.")
("raw,r", "Show an unformattet list of all records and subrecords.")
("quiet,q", "Supress all record information. Useful for speed tests.")
("loadcells,C", "Browse through contents of all cells.")
( "encoding,e", bpo::value<std::string>(&(info.encoding))->
default_value("win1252"),
"Character encoding used in ESMTool:\n"
"\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
"\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
"\n\twin1252 - Western European (Latin) alphabet, used by default")
;
std::string finalText = "\nIf no option is given, the default action is to parse all records in the archive\nand display diagnostic information.";
if(info.inputs_num != 1) // input-file is hidden and used as a positional argument
bpo::options_description hidden("Hidden Options");
hidden.add_options()
( "input-file,i", bpo::value< vector<std::string> >(), "input file")
;
bpo::positional_options_description p;
p.add("input-file", -1);
// there might be a better way to do this
bpo::options_description all;
all.add(desc).add(hidden);
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
.options(all).positional(p).run();
bpo::variables_map variables;
bpo::store(valid_opts, variables);
bpo::notify(variables);
if (variables.count ("help"))
{ {
if(info.inputs_num == 0) std::cout << desc << finalText << std::endl;
cout << "ERROR: missing ES file\n\n"; return false;
else }
cout << "ERROR: more than one ES file specified\n\n"; if (variables.count ("version"))
cmdline_parser_print_help(); {
return 1; std::cout << "ESMTool version " << ESMTOOL_VERSION << std::endl;
return false;
}
if ( !variables.count("input-file") )
{
std::cout << "\nERROR: missing ES file\n\n";
std::cout << desc << finalText << std::endl;
return false;
} }
// handling gracefully the user adding multiple files
if (variables["input-file"].as< vector<std::string> >().size() > 1)
{
std::cout << "\nERROR: more than one ES file specified\n\n";
std::cout << desc << finalText << std::endl;
return false;
}
info.filename = variables["input-file"].as< vector<std::string> >()[0];
info.raw_given = variables.count ("raw");
info.quiet_given = variables.count ("quiet");
info.loadcells_given = variables.count ("loadcells");
// Font encoding settings
info.encoding = variables["encoding"].as<std::string>();
if (info.encoding == "win1250")
{
std::cout << "Using Central and Eastern European font encoding." << std::endl;
}
else if (info.encoding == "win1251")
{
std::cout << "Using Cyrillic font encoding." << std::endl;
}
else
{
if(info.encoding != "win1252")
{
std::cout << info.encoding << " is not a valid encoding option." << std::endl;
info.encoding = "win1252";
}
std::cout << "Using default (English) font encoding." << std::endl;
}
return true;
}
int main(int argc, char**argv)
{
Arguments info;
if(!parseOptions (argc, argv, info))
return 1;
ESMReader esm; ESMReader esm;
const char* filename = info.inputs[0]; esm.setEncoding(info.encoding);
string filename = info.filename;
cout << "\nFile: " << filename << endl; cout << "\nFile: " << filename << endl;
try { try {

@ -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 */

@ -23,7 +23,7 @@ add_openmw_dir (mwinput
add_openmw_dir (mwgui add_openmw_dir (mwgui
layouts text_input widgets race class birth review window_manager console dialogue layouts text_input widgets race class birth review window_manager console dialogue
dialogue_history window_base stats_window messagebox journalwindow dialogue_history window_base stats_window messagebox journalwindow charactercreation
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue
@ -43,8 +43,8 @@ add_openmw_dir (mwsound
add_openmw_dir (mwworld add_openmw_dir (mwworld
refdata world physicssystem scene environment globals class action nullaction actionteleport refdata world physicssystem scene environment globals class action nullaction actionteleport
containerstore actiontalk actiontake containerstore manualref containerutil player cellfunctors containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts cells localscripts customdata weather
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
@ -77,7 +77,6 @@ target_link_libraries(openmw
${OPENAL_LIBRARY} ${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY} ${SOUND_INPUT_LIBRARY}
${BULLET_LIBRARIES} ${BULLET_LIBRARIES}
caelum
components components
MyGUIEngine MyGUIEngine
MyGUIOgrePlatform MyGUIOgrePlatform

@ -37,8 +37,6 @@
#include "mwsound/soundmanager.hpp" #include "mwsound/soundmanager.hpp"
#include "mwworld/world.hpp" #include "mwworld/world.hpp"
#include "mwworld/ptr.hpp"
#include "mwworld/environment.hpp"
#include "mwworld/class.hpp" #include "mwworld/class.hpp"
#include "mwworld/player.hpp" #include "mwworld/player.hpp"
@ -177,7 +175,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
: mOgre (0) : mOgre (0)
, mPhysicEngine (0)
, mFpsLevel(0) , mFpsLevel(0)
, mDebug (false) , mDebug (false)
, mVerboseScripts (false) , mVerboseScripts (false)
@ -188,7 +185,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mFocusTDiff (0) , mFocusTDiff (0)
, mScriptManager (0) , mScriptManager (0)
, mScriptContext (0) , mScriptContext (0)
, mGuiManager (0)
, mFSStrict (false) , mFSStrict (false)
, mCfgMgr(configurationManager) , mCfgMgr(configurationManager)
{ {
@ -198,7 +194,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
OMW::Engine::~Engine() OMW::Engine::~Engine()
{ {
delete mGuiManager;
delete mEnvironment.mWorld; delete mEnvironment.mWorld;
delete mEnvironment.mSoundManager; delete mEnvironment.mSoundManager;
delete mEnvironment.mGlobalScripts; delete mEnvironment.mGlobalScripts;
@ -207,7 +202,6 @@ OMW::Engine::~Engine()
delete mEnvironment.mJournal; delete mEnvironment.mJournal;
delete mScriptManager; delete mScriptManager;
delete mScriptContext; delete mScriptContext;
delete mPhysicEngine;
delete mOgre; delete mOgre;
} }
@ -334,26 +328,15 @@ void OMW::Engine::go()
loadBSA(); loadBSA();
/// \todo move this into the physics manager
// Create physics. shapeLoader is deleted by the physic engine
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
// Create the world // Create the world
mEnvironment.mWorld = new MWWorld::World (*mOgre, mPhysicEngine, mFileCollections, mMaster, mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
mResDir, mNewGame, mEnvironment, mEncoding); mResDir, mNewGame, mEnvironment, mEncoding);
/// \todo move this into the GUI manager (a.k.a WindowManager)
// Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false,
mCfgMgr.getLogPath().string() + std::string("/"));
// Create window manager - this manages all the MW-specific GUI windows // Create window manager - this manages all the MW-specific GUI windows
MWScript::registerExtensions (mExtensions); MWScript::registerExtensions (mExtensions);
mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui(), mEnvironment, mEnvironment.mWindowManager = new MWGui::WindowManager(mEnvironment,
mExtensions, mFpsLevel, mNewGame); mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"));
// Create sound system // Create sound system
mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(), mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(),

@ -7,8 +7,6 @@
#include <OgreFrameListener.h> #include <OgreFrameListener.h>
#include <openengine/bullet/physic.hpp>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
#include <components/files/collections.hpp> #include <components/files/collections.hpp>
@ -67,7 +65,6 @@ namespace OMW
Files::PathContainer mDataDirs; Files::PathContainer mDataDirs;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer *mOgre; OEngine::Render::OgreRenderer *mOgre;
OEngine::Physic::PhysicEngine* mPhysicEngine;
std::string mCellName; std::string mCellName;
std::string mMaster; std::string mMaster;
int mFpsLevel; int mFpsLevel;
@ -84,7 +81,7 @@ namespace OMW
MWScript::ScriptManager *mScriptManager; MWScript::ScriptManager *mScriptManager;
Compiler::Extensions mExtensions; Compiler::Extensions mExtensions;
Compiler::Context *mScriptContext; Compiler::Context *mScriptContext;
OEngine::GUI::MyGUIManager *mGuiManager;
Files::Collections mFileCollections; Files::Collections mFileCollections;
bool mFSStrict; bool mFSStrict;

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -58,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Apparatus::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.appas);
}
std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_APPARATUS_H #define GAME_MWCLASS_APPARATUS_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -70,12 +69,6 @@ namespace MWClass
return ref->base->data.health; return ref->base->data.health;
} }
void Armor::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.armors);
}
std::string Armor::getScript (const MWWorld::Ptr& ptr) const std::string Armor::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_ARMOR_H #define GAME_MWCLASS_ARMOR_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -29,10 +28,6 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health ///< Return item max health or throw an exception, if class does not have item health
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -60,12 +59,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Book::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.books);
}
std::string Book::getScript (const MWWorld::Ptr& ptr) const std::string Book::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_BOOK_H #define GAME_MWCLASS_BOOK_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -58,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Clothing::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.clothes);
}
std::string Clothing::getScript (const MWWorld::Ptr& ptr) const std::string Clothing::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_CLOTHING_H #define GAME_MWCLASS_CLOTHING_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -6,9 +6,45 @@
#include <components/esm_store/cell_store.hpp> #include <components/esm_store/cell_store.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace
{
struct CustomData : public MWWorld::CustomData
{
MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
{
return new CustomData (*this);
}
}
namespace MWClass namespace MWClass
{ {
void Container::ensureCustomData (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
// \todo add initial container content
// store
ptr.getRefData().setCustomData (data.release());
}
}
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{ {
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
@ -39,6 +75,38 @@ namespace MWClass
} }
boost::shared_ptr<MWWorld::Action> Container::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{
const std::string lockedSound = "LockedChest";
const std::string trapActivationSound = "Disarm Trap Fail";
if (ptr.getCellRef().lockLevel>0)
{
// TODO check for key
std::cout << "Locked container" << std::endl;
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
}
else
{
std::cout << "Unlocked container" << std::endl;
if(ptr.getCellRef().trap.empty())
{
// Not trapped, Inventory GUI goes here
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
}
else
{
// Trap activation goes here
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
}
}
}
std::string Container::getName (const MWWorld::Ptr& ptr) const std::string Container::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
@ -47,20 +115,12 @@ namespace MWClass
return ref->base->name; return ref->base->name;
} }
MWWorld::ContainerStore<MWWorld::RefData>& Container::getContainerStore (const MWWorld::Ptr& ptr) MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr)
const const
{ {
if (!ptr.getRefData().getContainerStore().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
new MWWorld::ContainerStore<MWWorld::RefData>);
// TODO add initial content
ptr.getRefData().getContainerStore() = store;
}
return *ptr.getRefData().getContainerStore(); return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
} }
std::string Container::getScript (const MWWorld::Ptr& ptr) const std::string Container::getScript (const MWWorld::Ptr& ptr) const

@ -2,12 +2,13 @@
#define GAME_MWCLASS_CONTAINER_H #define GAME_MWCLASS_CONTAINER_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
class Container : public MWWorld::Class class Container : public MWWorld::Class
{ {
void ensureCustomData (const MWWorld::Ptr& ptr) const;
public: public:
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
@ -19,8 +20,11 @@ namespace MWClass
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& ptr) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation
virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
///< Return container store ///< Return container store
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;

@ -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

@ -4,16 +4,62 @@
#include <components/esm/loadcrea.hpp> #include <components/esm/loadcrea.hpp>
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp" #include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwworld/containerstore.hpp"
namespace
{
struct CustomData : public MWWorld::CustomData
{
MWMechanics::CreatureStats mCreatureStats;
MWWorld::ContainerStore mContainerStore;
#include "../mwmechanics/mechanicsmanager.hpp" virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
{
return new CustomData (*this);
}
}
namespace MWClass namespace MWClass
{ {
void Creature::ensureCustomData (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ptr.get<ESM::Creature>();
// creature stats
data->mCreatureStats.mAttributes[0].set (ref->base->data.strength);
data->mCreatureStats.mAttributes[1].set (ref->base->data.intelligence);
data->mCreatureStats.mAttributes[2].set (ref->base->data.willpower);
data->mCreatureStats.mAttributes[3].set (ref->base->data.agility);
data->mCreatureStats.mAttributes[4].set (ref->base->data.speed);
data->mCreatureStats.mAttributes[5].set (ref->base->data.endurance);
data->mCreatureStats.mAttributes[6].set (ref->base->data.personality);
data->mCreatureStats.mAttributes[7].set (ref->base->data.luck);
data->mCreatureStats.mDynamic[0].set (ref->base->data.health);
data->mCreatureStats.mDynamic[1].set (ref->base->data.mana);
data->mCreatureStats.mDynamic[2].set (ref->base->data.fatigue);
data->mCreatureStats.mLevel = ref->base->data.level;
// \todo add initial container content
// store
ptr.getRefData().setCustomData (data.release());
}
}
std::string Creature::getId (const MWWorld::Ptr& ptr) const std::string Creature::getId (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
@ -24,18 +70,8 @@ namespace MWClass
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{ {
MWRender::Actors& actors = renderingInterface.getActors();
/*ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = actors.insertCreature(ptr);
ptr.get<ESM::Creature>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{*/
MWRender::Actors& actors = renderingInterface.getActors();
actors.insertCreature(ptr);
} }
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
@ -49,7 +85,6 @@ namespace MWClass
if(!model.empty()){ if(!model.empty()){
physics.insertActorPhysics(ptr, "meshes\\" + model); physics.insertActorPhysics(ptr, "meshes\\" + model);
} }
} }
void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
@ -72,31 +107,9 @@ namespace MWClass
MWMechanics::CreatureStats& Creature::getCreatureStats (const MWWorld::Ptr& ptr) const MWMechanics::CreatureStats& Creature::getCreatureStats (const MWWorld::Ptr& ptr) const
{ {
if (!ptr.getRefData().getCreatureStats().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWMechanics::CreatureStats> stats (
new MWMechanics::CreatureStats);
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ptr.get<ESM::Creature>(); return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
stats->mAttributes[0].set (ref->base->data.strength);
stats->mAttributes[1].set (ref->base->data.intelligence);
stats->mAttributes[2].set (ref->base->data.willpower);
stats->mAttributes[3].set (ref->base->data.agility);
stats->mAttributes[4].set (ref->base->data.speed);
stats->mAttributes[5].set (ref->base->data.endurance);
stats->mAttributes[6].set (ref->base->data.personality);
stats->mAttributes[7].set (ref->base->data.luck);
stats->mDynamic[0].set (ref->base->data.health);
stats->mDynamic[1].set (ref->base->data.mana);
stats->mDynamic[2].set (ref->base->data.fatigue);
stats->mLevel = ref->base->data.level;
ptr.getRefData().getCreatureStats() = stats;
}
return *ptr.getRefData().getCreatureStats();
} }
boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr,
@ -105,20 +118,12 @@ namespace MWClass
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr)); return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
} }
MWWorld::ContainerStore<MWWorld::RefData>& Creature::getContainerStore (const MWWorld::Ptr& ptr) MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr)
const const
{ {
if (!ptr.getRefData().getContainerStore().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
new MWWorld::ContainerStore<MWWorld::RefData>);
// TODO add initial content
ptr.getRefData().getContainerStore() = store;
}
return *ptr.getRefData().getContainerStore(); return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
} }
std::string Creature::getScript (const MWWorld::Ptr& ptr) const std::string Creature::getScript (const MWWorld::Ptr& ptr) const

@ -10,6 +10,8 @@ namespace MWClass
{ {
class Creature : public MWWorld::Class class Creature : public MWWorld::Class
{ {
void ensureCustomData (const MWWorld::Ptr& ptr) const;
public: public:
virtual std::string getId (const MWWorld::Ptr& ptr) const; virtual std::string getId (const MWWorld::Ptr& ptr) const;
@ -37,7 +39,7 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( virtual MWWorld::ContainerStore& getContainerStore (
const MWWorld::Ptr& ptr) const; const MWWorld::Ptr& ptr) const;
///< Return container store ///< Return container store

@ -14,7 +14,7 @@
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include <iostream> #include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
@ -39,13 +39,11 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
ptr.get<ESM::Door>(); ptr.get<ESM::Door>();
const std::string &model = ref->base->model; const std::string &model = ref->base->model;
assert (ref->base != NULL); assert (ref->base != NULL);
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
} }
std::string Door::getName (const MWWorld::Ptr& ptr) const std::string Door::getName (const MWWorld::Ptr& ptr) const
@ -65,15 +63,28 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
ptr.get<ESM::Door>(); ptr.get<ESM::Door>();
const std::string &openSound = ref->base->openSound;
//const std::string &closeSound = ref->base->closeSound;
const std::string lockedSound = "LockedDoor";
const std::string trapActivationSound = "Disarm Trap Fail";
if (ptr.getCellRef().lockLevel>0) if (ptr.getCellRef().lockLevel>0)
{ {
// TODO check for key // TODO check for key
// TODO report failure to player (message, sound?). Look up behaviour of original MW. // TODO report failure to player (message, sound?). Look up behaviour of original MW.
std::cout << "Locked!" << std::endl; std::cout << "Locked!" << std::endl;
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
// TODO check trap if(!ptr.getCellRef().trap.empty())
{
// Trap activation
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
}
if (ref->ref.teleport) if (ref->ref.teleport)
{ {
@ -81,12 +92,13 @@ namespace MWClass
if (environment.mWorld->getPlayer().getPlayer()==actor) if (environment.mWorld->getPlayer().getPlayer()==actor)
{ {
// the player is using the door // the player is using the door
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest));
} }
else else
{ {
// another NPC or a create is using the door // another NPC or a creature is using the door
// TODO return action for teleporting other NPC/creature // TODO return action for teleporting other NPC/creature
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
@ -95,6 +107,9 @@ namespace MWClass
{ {
// animated door // animated door
// TODO return action for rotating the door // TODO return action for rotating the door
// This is a little pointless, but helps with testing
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
} }

@ -2,7 +2,6 @@
#define GAME_MWCLASS_DOOR_H #define GAME_MWCLASS_DOOR_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -34,14 +33,11 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
ptr.get<ESM::Ingredient>(); ptr.get<ESM::Ingredient>();
const std::string &model = ref->base->model; const std::string &model = ref->base->model;
assert (ref->base != NULL); assert (ref->base != NULL);
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
} }
std::string Ingredient::getName (const MWWorld::Ptr& ptr) const std::string Ingredient::getName (const MWWorld::Ptr& ptr) const
@ -59,12 +55,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Ingredient::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.ingreds);
}
std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_INGREDIENT_H #define GAME_MWCLASS_INGREDIENT_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -12,7 +12,7 @@
#include "../mwsound/soundmanager.hpp" #include "../mwsound/soundmanager.hpp"
#include "containerutil.hpp" #include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -86,12 +86,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Light::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.lights);
}
std::string Light::getScript (const MWWorld::Ptr& ptr) const std::string Light::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_LIGHT_H #define GAME_MWCLASS_LIGHT_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -28,10 +27,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,7 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "containerutil.hpp" #include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -58,12 +58,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Lockpick::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.lockpicks);
}
std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_LOCKPICK_H #define GAME_MWCLASS_LOCKPICK_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,7 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "containerutil.hpp" #include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -57,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Miscellaneous::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.miscItems);
}
std::string Miscellaneous::getScript (const MWWorld::Ptr& ptr) const std::string Miscellaneous::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_MISC_H #define GAME_MWCLASS_MISC_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -1,27 +1,88 @@
#include "npc.hpp" #include "npc.hpp"
#include <memory>
#include <OgreSceneNode.h>
#include <components/esm/loadnpc.hpp> #include <components/esm/loadnpc.hpp>
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp" #include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwworld/customdata.hpp"
#include <OgreSceneNode.h>
namespace namespace
{ {
const Ogre::Radian kOgrePi (Ogre::Math::PI); const Ogre::Radian kOgrePi (Ogre::Math::PI);
const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0)); const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0));
struct CustomData : public MWWorld::CustomData
{
MWMechanics::NpcStats mNpcStats;
MWMechanics::CreatureStats mCreatureStats;
MWMechanics::Movement mMovement;
MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
{
return new CustomData (*this);
}
} }
namespace MWClass namespace MWClass
{ {
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
// NPC stats
if (!ref->base->faction.empty())
{
// TODO research how initial rank is stored. The information in loadnpc.hpp are at
// best very unclear.
data->mNpcStats.mFactionRank[ref->base->faction] = 0;
}
for (int i=0; i<27; ++i)
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
// creature stats
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower);
data->mCreatureStats.mAttributes[3].set (ref->base->npdt52.agility);
data->mCreatureStats.mAttributes[4].set (ref->base->npdt52.speed);
data->mCreatureStats.mAttributes[5].set (ref->base->npdt52.endurance);
data->mCreatureStats.mAttributes[6].set (ref->base->npdt52.personality);
data->mCreatureStats.mAttributes[7].set (ref->base->npdt52.luck);
data->mCreatureStats.mDynamic[0].set (ref->base->npdt52.health);
data->mCreatureStats.mDynamic[1].set (ref->base->npdt52.mana);
data->mCreatureStats.mDynamic[2].set (ref->base->npdt52.fatigue);
data->mCreatureStats.mLevel = ref->base->npdt52.level;
// \todo add initial container content
// store
ptr.getRefData().setCustomData (data.release());
}
}
std::string Npc::getId (const MWWorld::Ptr& ptr) const std::string Npc::getId (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
@ -77,56 +138,16 @@ namespace MWClass
MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const
{ {
if (!ptr.getRefData().getCreatureStats().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWMechanics::CreatureStats> stats (
new MWMechanics::CreatureStats);
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
stats->mAttributes[0].set (ref->base->npdt52.strength); return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
stats->mAttributes[1].set (ref->base->npdt52.intelligence);
stats->mAttributes[2].set (ref->base->npdt52.willpower);
stats->mAttributes[3].set (ref->base->npdt52.agility);
stats->mAttributes[4].set (ref->base->npdt52.speed);
stats->mAttributes[5].set (ref->base->npdt52.endurance);
stats->mAttributes[6].set (ref->base->npdt52.personality);
stats->mAttributes[7].set (ref->base->npdt52.luck);
stats->mDynamic[0].set (ref->base->npdt52.health);
stats->mDynamic[1].set (ref->base->npdt52.mana);
stats->mDynamic[2].set (ref->base->npdt52.fatigue);
stats->mLevel = ref->base->npdt52.level;
ptr.getRefData().getCreatureStats() = stats;
}
return *ptr.getRefData().getCreatureStats();
} }
MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
{ {
if (!ptr.getRefData().getNpcStats().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWMechanics::NpcStats> stats (
new MWMechanics::NpcStats);
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
if (!ref->base->faction.empty())
{
// TODO research how initial rank is stored. The information in loadnpc.hpp are at
// best very unclear.
stats->mFactionRank[ref->base->faction] = 0;
}
for (int i=0; i<27; ++i) return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
stats->mSkill[i].setBase (ref->base->npdt52.skills[i]);
ptr.getRefData().getNpcStats() = stats;
}
return *ptr.getRefData().getNpcStats();
} }
boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr,
@ -135,20 +156,12 @@ namespace MWClass
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr)); return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
} }
MWWorld::ContainerStore<MWWorld::RefData>& Npc::getContainerStore (const MWWorld::Ptr& ptr) MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr)
const const
{ {
if (!ptr.getRefData().getContainerStore().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
new MWWorld::ContainerStore<MWWorld::RefData>);
// TODO add initial content
ptr.getRefData().getContainerStore() = store; return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
}
return *ptr.getRefData().getContainerStore();
} }
std::string Npc::getScript (const MWWorld::Ptr& ptr) const std::string Npc::getScript (const MWWorld::Ptr& ptr) const
@ -239,29 +252,20 @@ namespace MWClass
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
{ {
if (!ptr.getRefData().getMovement().get()) ensureCustomData (ptr);
{
boost::shared_ptr<MWMechanics::Movement> movement (
new MWMechanics::Movement);
ptr.getRefData().getMovement() = movement;
}
return *ptr.getRefData().getMovement(); return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mMovement;
} }
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
{ {
Ogre::Vector3 vector (0, 0, 0); Ogre::Vector3 vector (0, 0, 0);
if (ptr.getRefData().getMovement().get()) vector.x = - getMovementSettings (ptr).mLeftRight * 200;
{ vector.y = getMovementSettings (ptr).mForwardBackward * 200;
vector.x = - ptr.getRefData().getMovement()->mLeftRight * 200;
vector.y = ptr.getRefData().getMovement()->mForwardBackward * 200;
if (getStance (ptr, Run, false)) if (getStance (ptr, Run, false))
vector *= 2; vector *= 2;
}
return vector; return vector;
} }

@ -3,11 +3,12 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
namespace MWClass namespace MWClass
{ {
class Npc : public MWWorld::Class class Npc : public MWWorld::Class
{ {
void ensureCustomData (const MWWorld::Ptr& ptr) const;
public: public:
virtual std::string getId (const MWWorld::Ptr& ptr) const; virtual std::string getId (const MWWorld::Ptr& ptr) const;
@ -34,8 +35,7 @@ namespace MWClass
virtual MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const; virtual MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const;
///< Return NPC stats ///< Return NPC stats
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
const MWWorld::Ptr& ptr) const;
///< Return container store ///< Return container store
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -58,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Potion::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.potions);
}
std::string Potion::getScript (const MWWorld::Ptr& ptr) const std::string Potion::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_POTION_H #define GAME_MWCLASS_POTION_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,7 +8,6 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "containerutil.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
@ -58,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Probe::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.probes);
}
std::string Probe::getScript (const MWWorld::Ptr& ptr) const std::string Probe::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =

@ -3,7 +3,6 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
namespace MWClass namespace MWClass
{ {
class Probe : public MWWorld::Class class Probe : public MWWorld::Class
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -8,7 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "containerutil.hpp" #include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -57,12 +57,6 @@ namespace MWClass
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
void Repair::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.repairs);
}
std::string Repair::getScript (const MWWorld::Ptr& ptr) const std::string Repair::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_REPAIR_H #define GAME_MWCLASS_REPAIR_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -23,10 +22,6 @@ namespace MWClass
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -5,6 +5,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {

@ -2,7 +2,6 @@
#define GAME_MWCLASS_STATIC_H #define GAME_MWCLASS_STATIC_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {

@ -8,8 +8,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwrender/objects.hpp"
#include "containerutil.hpp"
namespace MWClass namespace MWClass
{ {
@ -71,12 +70,6 @@ namespace MWClass
return ref->base->data.health; return ref->base->data.health;
} }
void Weapon::insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
{
insertIntoContainerStore (ptr, containerStore.weapons);
}
std::string Weapon::getScript (const MWWorld::Ptr& ptr) const std::string Weapon::getScript (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =

@ -2,7 +2,6 @@
#define GAME_MWCLASS_WEAPON_H #define GAME_MWCLASS_WEAPON_H
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass namespace MWClass
{ {
@ -29,10 +28,6 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health ///< Return item max health or throw an exception, if class does not have item health
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
///< Insert into a containe
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -0,0 +1,629 @@
#include "charactercreation.hpp"
#include "text_input.hpp"
#include "race.hpp"
#include "class.hpp"
#include "birth.hpp"
#include "review.hpp"
#include "dialogue.hpp"
#include "mode.hpp"
namespace
{
struct Step
{
const char* mText;
const char* mButtons[3];
ESM::Class::Specialization mSpecializations[3]; // The specialization for each answer
};
static boost::array<Step, 10> sGenerateClassSteps = { {
// Question 1
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
{"Draw your dagger, mercifully endings its life with a single thrust.",
"Use herbs from your pack to put it to sleep.",
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 2
{"One Summer afternoon your father gives you a choice of chores.",
{"Work in the forge with him casting iron for a new plow.",
"Gather herbs for your mother who is preparing dinner.",
"Go catch fish at the stream using a net and line."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 3
{"Your cousin has given you a very embarrassing nickname and, even worse, likes to call you it in front of your friends. You asked him to stop, but he finds it very amusing to watch you blush.",
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 4
{"There is a lot of heated discussion at the local tavern over a grouped of people called 'Telepaths'. They have been hired by certain City-State kings. Rumor has it these Telepaths read a person's mind and tell their lord whether a follower is telling the truth or not.",
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 5
{"Your mother sends you to the market with a list of goods to buy. After you finish you find that by mistake a shopkeeper has given you too much money back in exchange for one of the items.",
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
"Decide to put the extra money to good use and purchase items that would help your family?",
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 6
{"While in the market place you witness a thief cut a purse from a noble. Even as he does so, the noble notices and calls for the city guards. In his haste to get away, the thief drops the purse near you. Surprisingly no one seems to notice the bag of coins at your feet.",
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
"Leave the bag there, knowing that it is better not to get involved.",
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 7
{"Your father sends you on a task which you loathe, cleaning the stables. On the way there, pitchfork in hand, you run into your friend from the homestead near your own. He offers to do it for you, in return for a future favor of his choosing.",
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 8
{"Your mother asks you to help fix the stove. While you are working, a very hot pipe slips its mooring and falls towards her.",
{"Position yourself between the pipe and your mother.",
"Grab the hot pipe and try to push it away.",
"Push your mother out of the way."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 9
{"While in town the baker gives you a sweetroll. Delighted, you take it into an alley to enjoy only to be intercepted by a gang of three other kids your age. The leader demands the sweetroll, or else he and his friends will beat you and take it.",
{"Drop the sweetroll and step on it, then get ready for the fight.",
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 10
{"Entering town you find that you are witness to a very well-dressed man running from a crowd. He screams to you for help. The crowd behind him seem very angry.",
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
}
} };
}
using namespace MWGui;
CharacterCreation::CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment)
: mNameDialog(0)
, mRaceDialog(0)
, mDialogueWindow(0)
, mClassChoiceDialog(0)
, mGenerateClassQuestionDialog(0)
, mGenerateClassResultDialog(0)
, mPickClassDialog(0)
, mCreateClassDialog(0)
, mBirthSignDialog(0)
, mReviewDialog(0)
, mWM(_wm)
, mEnvironment(_environment)
{
mCreationStage = CSE_NotStarted;
}
void CharacterCreation::spawnDialog(const char id)
{
switch (id)
{
case GM_Name:
if(mNameDialog)
mWM->removeDialog(mNameDialog);
mNameDialog = new TextInputDialog(*mWM);
mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name"));
mNameDialog->setTextInput(mPlayerName);
mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
mNameDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
mNameDialog->open();
break;
case GM_Race:
if (mRaceDialog)
mWM->removeDialog(mRaceDialog);
mRaceDialog = new RaceDialog(*mWM);
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
mRaceDialog->setRaceId(mPlayerRaceId);
mRaceDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
mRaceDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
mRaceDialog->open();
break;
case GM_Class:
if (mClassChoiceDialog)
mWM->removeDialog(mClassChoiceDialog);
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
mClassChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
mClassChoiceDialog->open();
break;
case GM_ClassPick:
if (mPickClassDialog)
mWM->removeDialog(mPickClassDialog);
mPickClassDialog = new PickClassDialog(*mWM);
mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
mPickClassDialog->setClassId(mPlayerClass.name);
mPickClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
mPickClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
mPickClassDialog->open();
break;
case GM_Birth:
if (mBirthSignDialog)
mWM->removeDialog(mBirthSignDialog);
mBirthSignDialog = new BirthDialog(*mWM);
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
mBirthSignDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
mBirthSignDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
mBirthSignDialog->open();
break;
case GM_ClassCreate:
if (mCreateClassDialog)
mWM->removeDialog(mCreateClassDialog);
mCreateClassDialog = new CreateClassDialog(*mWM);
mCreateClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
mCreateClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
mCreateClassDialog->open();
break;
case GM_ClassGenerate:
mGenerateClassStep = 0;
mGenerateClass = "";
mGenerateClassSpecializations[0] = 0;
mGenerateClassSpecializations[1] = 0;
mGenerateClassSpecializations[2] = 0;
showClassQuestionDialog();
break;
case GM_Review:
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mReviewDialog = new ReviewDialog(*mWM);
mReviewDialog->setPlayerName(mPlayerName);
mReviewDialog->setRace(mPlayerRaceId);
mReviewDialog->setClass(mPlayerClass);
mReviewDialog->setBirthSign(mPlayerBirthSignId);
mReviewDialog->setHealth(mPlayerHealth);
mReviewDialog->setMagicka(mPlayerMagicka);
mReviewDialog->setFatigue(mPlayerFatigue);
{
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator end = mPlayerAttributes.end();
for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = mPlayerAttributes.begin(); it != end; ++it)
{
mReviewDialog->setAttribute(it->first, it->second);
}
}
{
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator end = mPlayerSkillValues.end();
for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = mPlayerSkillValues.begin(); it != end; ++it)
{
mReviewDialog->setSkillValue(it->first, it->second);
}
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
}
mReviewDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
mReviewDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
mReviewDialog->eventActivateDialog = MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
mReviewDialog->open();
break;
}
}
void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<int>& value)
{
mPlayerHealth = value;
}
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<int>& value)
{
mPlayerMagicka = value;
}
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<int>& value)
{
mPlayerFatigue = value;
}
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
{
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Game);
}
void CharacterCreation::onReviewDialogBack()
{
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Birth);
}
void CharacterCreation::onReviewActivateDialog(int parDialog)
{
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mCreationStage = CSE_ReviewNext;
switch(parDialog)
{
case ReviewDialog::NAME_DIALOG:
mWM->setGuiMode(GM_Name);
break;
case ReviewDialog::RACE_DIALOG:
mWM->setGuiMode(GM_Race);
break;
case ReviewDialog::CLASS_DIALOG:
mWM->setGuiMode(GM_Class);
break;
case ReviewDialog::BIRTHSIGN_DIALOG:
mWM->setGuiMode(GM_Birth);
};
}
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
{
if (mPickClassDialog)
{
const std::string &classId = mPickClassDialog->getClassId();
if (!classId.empty())
mEnvironment->mMechanicsManager->setPlayerClass(classId);
const ESM::Class *klass = mEnvironment->mWorld->getStore().classes.find(classId);
if (klass)
{
mPlayerClass = *klass;
mWM->setPlayerClass(mPlayerClass);
}
mWM->removeDialog(mPickClassDialog);
}
//TODO This bit gets repeated a few times; wrap it in a function
if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review);
else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth);
else
{
mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game);
}
}
void CharacterCreation::onPickClassDialogBack()
{
if (mPickClassDialog)
{
const std::string classId = mPickClassDialog->getClassId();
if (!classId.empty())
mEnvironment->mMechanicsManager->setPlayerClass(classId);
mWM->removeDialog(mPickClassDialog);
}
mWM->setGuiMode(GM_Class);
}
void CharacterCreation::onClassChoice(int _index)
{
if (mClassChoiceDialog)
{
mWM->removeDialog(mClassChoiceDialog);
}
switch(_index)
{
case ClassChoiceDialog::Class_Generate:
mWM->setGuiMode(GM_ClassGenerate);
break;
case ClassChoiceDialog::Class_Pick:
mWM->setGuiMode(GM_ClassPick);
break;
case ClassChoiceDialog::Class_Create:
mWM->setGuiMode(GM_ClassCreate);
break;
case ClassChoiceDialog::Class_Back:
mWM->setGuiMode(GM_Race);
break;
};
}
void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
{
if (mNameDialog)
{
mPlayerName = mNameDialog->getTextInput();
mWM->setValue("name", mPlayerName);
mEnvironment->mMechanicsManager->setPlayerName(mPlayerName);
mWM->removeDialog(mNameDialog);
}
if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review);
else if (mCreationStage >= CSE_NameChosen)
mWM->setGuiMode(GM_Race);
else
{
mCreationStage = CSE_NameChosen;
mWM->setGuiMode(GM_Game);
}
}
void CharacterCreation::onRaceDialogBack()
{
if (mRaceDialog)
{
mPlayerRaceId = mRaceDialog->getRaceId();
if (!mPlayerRaceId.empty())
mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male);
mWM->removeDialog(mRaceDialog);
}
mWM->setGuiMode(GM_Name);
}
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
{
if (mRaceDialog)
{
mPlayerRaceId = mRaceDialog->getRaceId();
mWM->setValue("race", mPlayerRaceId);
if (!mPlayerRaceId.empty())
mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male);
mWM->removeDialog(mRaceDialog);
}
if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review);
else if(mCreationStage >= CSE_RaceChosen)
mWM->setGuiMode(GM_Class);
else
{
mCreationStage = CSE_RaceChosen;
mWM->setGuiMode(GM_Game);
}
}
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
{
if (mBirthSignDialog)
{
mPlayerBirthSignId = mBirthSignDialog->getBirthId();
mWM->setBirthSign(mPlayerBirthSignId);
if (!mPlayerBirthSignId.empty())
mEnvironment->mMechanicsManager->setPlayerBirthsign(mPlayerBirthSignId);
mWM->removeDialog(mBirthSignDialog);
}
if (mCreationStage >= CSE_BirthSignChosen)
mWM->setGuiMode(GM_Review);
else
{
mCreationStage = CSE_BirthSignChosen;
mWM->setGuiMode(GM_Game);
}
}
void CharacterCreation::onBirthSignDialogBack()
{
if (mBirthSignDialog)
{
mEnvironment->mMechanicsManager->setPlayerBirthsign(mBirthSignDialog->getBirthId());
mWM->removeDialog(mBirthSignDialog);
}
mWM->setGuiMode(GM_Class);
}
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
{
if (mCreateClassDialog)
{
ESM::Class klass;
klass.name = mCreateClassDialog->getName();
klass.description = mCreateClassDialog->getDescription();
klass.data.specialization = mCreateClassDialog->getSpecializationId();
klass.data.isPlayable = 0x1;
std::vector<int> attributes = mCreateClassDialog->getFavoriteAttributes();
assert(attributes.size() == 2);
klass.data.attribute[0] = attributes[0];
klass.data.attribute[1] = attributes[1];
std::vector<ESM::Skill::SkillEnum> majorSkills = mCreateClassDialog->getMajorSkills();
std::vector<ESM::Skill::SkillEnum> minorSkills = mCreateClassDialog->getMinorSkills();
assert(majorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
assert(minorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
for (size_t i = 0; i < sizeof(klass.data.skills)/sizeof(klass.data.skills[0]); ++i)
{
klass.data.skills[i][1] = majorSkills[i];
klass.data.skills[i][0] = minorSkills[i];
}
mEnvironment->mMechanicsManager->setPlayerClass(klass);
mPlayerClass = klass;
mWM->setPlayerClass(klass);
mWM->removeDialog(mCreateClassDialog);
}
if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review);
else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth);
else
{
mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game);
}
}
void CharacterCreation::onCreateClassDialogBack()
{
if (mCreateClassDialog)
mWM->removeDialog(mCreateClassDialog);
mWM->setGuiMode(GM_Class);
}
void CharacterCreation::onClassQuestionChosen(int _index)
{
if (mGenerateClassQuestionDialog)
mWM->removeDialog(mGenerateClassQuestionDialog);
if (_index < 0 || _index >= 3)
{
mWM->setGuiMode(GM_Class);
return;
}
ESM::Class::Specialization specialization = sGenerateClassSteps[mGenerateClassStep].mSpecializations[_index];
if (specialization == ESM::Class::Stealth)
++mGenerateClassSpecializations[0];
else if (specialization == ESM::Class::Combat)
++mGenerateClassSpecializations[1];
else if (specialization == ESM::Class::Magic)
++mGenerateClassSpecializations[2];
++mGenerateClassStep;
showClassQuestionDialog();
}
void CharacterCreation::showClassQuestionDialog()
{
if (mGenerateClassStep == sGenerateClassSteps.size())
{
static boost::array<ClassPoint, 23> classes = { {
{"Acrobat", {6, 2, 2}},
{"Agent", {6, 1, 3}},
{"Archer", {3, 5, 2}},
{"Archer", {5, 5, 0}},
{"Assassin", {6, 3, 1}},
{"Barbarian", {3, 6, 1}},
{"Bard", {3, 3, 3}},
{"Battlemage", {1, 3, 6}},
{"Crusader", {1, 6, 3}},
{"Healer", {3, 1, 6}},
{"Knight", {2, 6, 2}},
{"Monk", {5, 3, 2}},
{"Nightblade", {4, 2, 4}},
{"Pilgrim", {5, 2, 3}},
{"Rogue", {3, 4, 3}},
{"Rogue", {4, 4, 2}},
{"Rogue", {5, 4, 1}},
{"Scout", {2, 5, 3}},
{"Sorcerer", {2, 2, 6}},
{"Spellsword", {2, 4, 4}},
{"Spellsword", {5, 1, 4}},
{"Witchhunter", {2, 3, 5}},
{"Witchhunter", {5, 0, 5}}
} };
int match = -1;
for (unsigned i = 0; i < classes.size(); ++i)
{
if (mGenerateClassSpecializations[0] == classes[i].points[0] &&
mGenerateClassSpecializations[1] == classes[i].points[1] &&
mGenerateClassSpecializations[2] == classes[i].points[2])
{
match = i;
mGenerateClass = classes[i].id;
break;
}
}
if (match == -1)
{
if (mGenerateClassSpecializations[0] >= 7)
mGenerateClass = "Thief";
else if (mGenerateClassSpecializations[1] >= 7)
mGenerateClass = "Warrior";
else if (mGenerateClassSpecializations[2] >= 7)
mGenerateClass = "Mage";
else
{
std::cerr << "Failed to deduce class from chosen answers in generate class dialog" << std::endl;
mGenerateClass = "Thief";
}
}
if (mGenerateClassResultDialog)
mWM->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM);
mGenerateClassResultDialog->setClassId(mGenerateClass);
mGenerateClassResultDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
mGenerateClassResultDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
mGenerateClassResultDialog->open();
return;
}
if (mGenerateClassStep > sGenerateClassSteps.size())
{
mWM->setGuiMode(GM_Class);
return;
}
if (mGenerateClassQuestionDialog)
mWM->removeDialog(mGenerateClassQuestionDialog);
mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM);
InfoBoxDialog::ButtonList buttons;
mGenerateClassQuestionDialog->setText(sGenerateClassSteps[mGenerateClassStep].mText);
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[0]);
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[1]);
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]);
mGenerateClassQuestionDialog->setButtons(buttons);
mGenerateClassQuestionDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
mGenerateClassQuestionDialog->open();
}
void CharacterCreation::onGenerateClassBack()
{
if(mCreationStage < CSE_ClassChosen)
mCreationStage = CSE_ClassChosen;
if (mGenerateClassResultDialog)
mWM->removeDialog(mGenerateClassResultDialog);
mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass);
mWM->setGuiMode(GM_Class);
}
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
{
if (mGenerateClassResultDialog)
mWM->removeDialog(mGenerateClassResultDialog);
mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass);
if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review);
else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth);
else
{
mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game);
}
}
CharacterCreation::~CharacterCreation()
{
delete mNameDialog;
delete mRaceDialog;
delete mDialogueWindow;
delete mClassChoiceDialog;
delete mGenerateClassQuestionDialog;
delete mGenerateClassResultDialog;
delete mPickClassDialog;
delete mCreateClassDialog;
delete mBirthSignDialog;
delete mReviewDialog;
}

@ -0,0 +1,120 @@
#ifndef CHARACTER_CREATION_HPP
#define CHARACTER_CREATION_HPP
#include "window_manager.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwmechanics/stat.hpp"
#include "../mwworld/world.hpp"
#include <components/esm_store/store.hpp>
namespace MWGui
{
class WindowManager;
class WindowBase;
class TextInputDialog;
class InfoBoxDialog;
class RaceDialog;
class DialogueWindow;
class ClassChoiceDialog;
class GenerateClassResultDialog;
class PickClassDialog;
class CreateClassDialog;
class BirthDialog;
class ReviewDialog;
class MessageBoxManager;
class CharacterCreation
{
public:
typedef std::vector<int> SkillList;
CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment);
~CharacterCreation();
//Show a dialog
void spawnDialog(const char id);
void setPlayerHealth (const MWMechanics::DynamicStat<int>& value);
void setPlayerMagicka (const MWMechanics::DynamicStat<int>& value);
void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value);
private:
//Dialogs
TextInputDialog* mNameDialog;
RaceDialog* mRaceDialog;
DialogueWindow* mDialogueWindow;
ClassChoiceDialog* mClassChoiceDialog;
InfoBoxDialog* mGenerateClassQuestionDialog;
GenerateClassResultDialog* mGenerateClassResultDialog;
PickClassDialog* mPickClassDialog;
CreateClassDialog* mCreateClassDialog;
BirthDialog* mBirthSignDialog;
ReviewDialog* mReviewDialog;
WindowManager* mWM;
MWWorld::Environment* mEnvironment;
//Player data
std::string mPlayerName;
std::string mPlayerRaceId;
std::string mPlayerBirthSignId;
ESM::Class mPlayerClass;
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<int> mPlayerHealth;
MWMechanics::DynamicStat<int> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue;
//Class generation vars
unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog
unsigned mGenerateClassSpecializations[3]; // A counter for each specialization which is increased when an answer is chosen
std::string mGenerateClass; // In order: Stealth, Combat, Magic
////Dialog events
//Name dialog
void onNameDialogDone(WindowBase* parWindow);
//Race dialog
void onRaceDialogDone(WindowBase* parWindow);
void onRaceDialogBack();
//Class dialogs
void onClassChoice(int _index);
void onPickClassDialogDone(WindowBase* parWindow);
void onPickClassDialogBack();
void onCreateClassDialogDone(WindowBase* parWindow);
void onCreateClassDialogBack();
void showClassQuestionDialog();
void onClassQuestionChosen(int _index);
void onGenerateClassBack();
void onGenerateClassDone(WindowBase* parWindow);
//Birthsign dialog
void onBirthSignDialogDone(WindowBase* parWindow);
void onBirthSignDialogBack();
//Review dialog
void onReviewDialogDone(WindowBase* parWindow);
void onReviewDialogBack();
void onReviewActivateDialog(int parDialog);
enum CSE //Creation Stage Enum
{
CSE_NotStarted,
CSE_NameChosen,
CSE_RaceChosen,
CSE_ClassChosen,
CSE_BirthSignChosen,
CSE_ReviewNext
};
CSE mCreationStage; // Which state the character creating is in, controls back/next/ok buttons
};
}
#endif

@ -1,9 +1,6 @@
#include "window_manager.hpp" #include "window_manager.hpp"
#include "layouts.hpp" #include "layouts.hpp"
#include "text_input.hpp" #include "text_input.hpp"
#include "race.hpp"
#include "class.hpp"
#include "birth.hpp"
#include "review.hpp" #include "review.hpp"
#include "dialogue.hpp" #include "dialogue.hpp"
#include "dialogue_history.hpp" #include "dialogue_history.hpp"
@ -15,6 +12,7 @@
#include "console.hpp" #include "console.hpp"
#include "journalwindow.hpp" #include "journalwindow.hpp"
#include "charactercreation.hpp"
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
@ -22,20 +20,10 @@
using namespace MWGui; using namespace MWGui;
WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment, WindowManager::WindowManager(MWWorld::Environment& environment,
const Compiler::Extensions& extensions, int fpsLevel, bool newGame) const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath)
: environment(environment) : environment(environment)
, nameDialog(nullptr)
, raceDialog(nullptr)
, dialogueWindow(nullptr) , dialogueWindow(nullptr)
, classChoiceDialog(nullptr)
, generateClassQuestionDialog(nullptr)
, generateClassResultDialog(nullptr)
, pickClassDialog(nullptr)
, createClassDialog(nullptr)
, birthSignDialog(nullptr)
, reviewDialog(nullptr)
, gui(_gui)
, mode(GM_Game) , mode(GM_Game)
, nextMode(GM_Game) , nextMode(GM_Game)
, needModeChange(false) , needModeChange(false)
@ -44,7 +32,9 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
{ {
showFPSLevel = fpsLevel; showFPSLevel = fpsLevel;
creationStage = NotStarted; // Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath);
gui = mGuiManager->getGui();
//Register own widgets with MyGUI //Register own widgets with MyGUI
MyGUI::FactoryManager::getInstance().registerFactory<DialogeHistory>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<DialogeHistory>("Widget");
@ -58,9 +48,6 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
menu = new MainMenu(w,h); menu = new MainMenu(w,h);
map = new MapWindow(); map = new MapWindow();
stats = new StatsWindow(*this); stats = new StatsWindow(*this);
#if 0
inventory = new InventoryWindow ();
#endif
console = new Console(w,h, environment, extensions); console = new Console(w,h, environment, extensions);
mJournal = new JournalWindow(*this); mJournal = new JournalWindow(*this);
mMessageBoxManager = new MessageBoxManager(this); mMessageBoxManager = new MessageBoxManager(this);
@ -68,6 +55,8 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
// The HUD is always on // The HUD is always on
hud->setVisible(true); hud->setVisible(true);
mCharGen = new CharacterCreation(this, &environment);
// Setup player stats // Setup player stats
for (int i = 0; i < ESM::Attribute::Length; ++i) for (int i = 0; i < ESM::Attribute::Length; ++i)
{ {
@ -91,6 +80,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
WindowManager::~WindowManager() WindowManager::~WindowManager()
{ {
delete mGuiManager;
delete console; delete console;
delete mMessageBoxManager; delete mMessageBoxManager;
delete hud; delete hud;
@ -98,20 +88,9 @@ WindowManager::~WindowManager()
delete menu; delete menu;
delete stats; delete stats;
delete mJournal; delete mJournal;
#if 0
delete inventory;
#endif
delete nameDialog;
delete raceDialog;
delete dialogueWindow; delete dialogueWindow;
delete classChoiceDialog;
delete generateClassQuestionDialog; delete mCharGen;
delete generateClassResultDialog;
delete pickClassDialog;
delete createClassDialog;
delete birthSignDialog;
delete reviewDialog;
cleanupGarbage(); cleanupGarbage();
} }
@ -168,9 +147,6 @@ void WindowManager::updateVisible()
map->setVisible(false); map->setVisible(false);
menu->setVisible(false); menu->setVisible(false);
stats->setVisible(false); stats->setVisible(false);
#if 0
inventory->setVisible(false);
#endif
console->disable(); console->disable();
mJournal->setVisible(false); mJournal->setVisible(false);
@ -178,7 +154,7 @@ void WindowManager::updateVisible()
gui->setVisiblePointer(isGuiMode()); gui->setVisiblePointer(isGuiMode());
// If in game mode, don't show anything. // If in game mode, don't show anything.
if(mode == GM_Game) if(mode == GM_Game) //Use a switch/case structure
{ {
return; return;
} }
@ -196,126 +172,10 @@ void WindowManager::updateVisible()
return; return;
} }
if (mode == GM_Name) //There must be a more elegant solution
{ if (mode == GM_Name || mode == GM_Race || mode == GM_Class || mode == GM_ClassPick || mode == GM_ClassCreate || mode == GM_Birth || mode == GM_ClassGenerate || mode == GM_Review)
if (nameDialog)
removeDialog(nameDialog);
nameDialog = new TextInputDialog(*this);
std::string sName = getGameSettingString("sName", "Name");
nameDialog->setTextLabel(sName);
nameDialog->setTextInput(playerName);
nameDialog->setNextButtonShow(creationStage >= NameChosen);
nameDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onNameDialogDone);
nameDialog->open();
return;
}
if (mode == GM_Race)
{
if (raceDialog)
removeDialog(raceDialog);
raceDialog = new RaceDialog(*this);
raceDialog->setNextButtonShow(creationStage >= RaceChosen);
raceDialog->setRaceId(playerRaceId);
raceDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onRaceDialogDone);
raceDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onRaceDialogBack);
raceDialog->open();
return;
}
if (mode == GM_Class)
{
if (classChoiceDialog)
removeDialog(classChoiceDialog);
classChoiceDialog = new ClassChoiceDialog(*this);
classChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &WindowManager::onClassChoice);
classChoiceDialog->open();
return;
}
if (mode == GM_ClassGenerate)
{
generateClassStep = 0;
generateClass = "";
generateClassSpecializations[0] = 0;
generateClassSpecializations[1] = 0;
generateClassSpecializations[2] = 0;
showClassQuestionDialog();
return;
}
if (mode == GM_ClassPick)
{ {
if (pickClassDialog) mCharGen->spawnDialog(mode);
removeDialog(pickClassDialog);
pickClassDialog = new PickClassDialog(*this);
pickClassDialog->setNextButtonShow(creationStage >= ClassChosen);
pickClassDialog->setClassId(playerClass.name);
pickClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogDone);
pickClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogBack);
pickClassDialog->open();
return;
}
if (mode == GM_ClassCreate)
{
if (createClassDialog)
removeDialog(createClassDialog);
createClassDialog = new CreateClassDialog(*this);
createClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogDone);
createClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogBack);
createClassDialog->open();
return;
}
if (mode == GM_Birth)
{
if (birthSignDialog)
removeDialog(birthSignDialog);
birthSignDialog = new BirthDialog(*this);
birthSignDialog->setNextButtonShow(creationStage >= BirthSignChosen);
birthSignDialog->setBirthId(playerBirthSignId);
birthSignDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogDone);
birthSignDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogBack);
birthSignDialog->open();
return;
}
if (mode == GM_Review)
{
if (reviewDialog)
removeDialog(reviewDialog);
reviewDialog = new ReviewDialog(*this);
reviewDialog->setPlayerName(playerName);
reviewDialog->setRace(playerRaceId);
reviewDialog->setClass(playerClass);
reviewDialog->setBirthSign(playerBirthSignId);
reviewDialog->setHealth(playerHealth);
reviewDialog->setMagicka(playerMagicka);
reviewDialog->setFatigue(playerFatigue);
{
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator end = playerAttributes.end();
for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = playerAttributes.begin(); it != end; ++it)
{
reviewDialog->setAttribute(it->first, it->second);
}
}
{
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator end = playerSkillValues.end();
for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = playerSkillValues.begin(); it != end; ++it)
{
reviewDialog->setSkillValue(it->first, it->second);
}
reviewDialog->configureSkills(playerMajorSkills, playerMinorSkills);
}
reviewDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onReviewDialogDone);
reviewDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onReviewDialogBack);
reviewDialog->eventActivateDialog = MyGUI::newDelegate(this, &WindowManager::onReviewActivateDialog);
reviewDialog->open();
return; return;
} }
@ -330,9 +190,6 @@ void WindowManager::updateVisible()
// Show the windows we want // Show the windows we want
map -> setVisible( (eff & GW_Map) != 0 ); map -> setVisible( (eff & GW_Map) != 0 );
stats -> setVisible( (eff & GW_Stats) != 0 ); stats -> setVisible( (eff & GW_Stats) != 0 );
#if 0
// inventory -> setVisible( eff & GW_Inventory );
#endif
return; return;
} }
@ -362,7 +219,6 @@ void WindowManager::updateVisible()
return; return;
} }
// Unsupported mode, switch back to game // Unsupported mode, switch back to game
// Note: The call will eventually end up this method again but // Note: The call will eventually end up this method again but
// will stop at the check if(mode == GM_Game) above. // will stop at the check if(mode == GM_Game) above.
@ -410,13 +266,34 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
stats->setValue (id, value); stats->setValue (id, value);
hud->setValue (id, value); hud->setValue (id, value);
if (id == "HBar") if (id == "HBar")
{
playerHealth = value; playerHealth = value;
mCharGen->setPlayerHealth (value);
}
else if (id == "MBar") else if (id == "MBar")
{
playerMagicka = value; playerMagicka = value;
mCharGen->setPlayerMagicka (value);
}
else if (id == "FBar") else if (id == "FBar")
{
playerFatigue = value; playerFatigue = value;
mCharGen->setPlayerFatigue (value);
}
} }
#if 0
MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id)
{
if(id == "HBar")
return playerHealth;
else if (id == "MBar")
return playerMagicka;
else if (id == "FBar")
return playerFatigue;
}
#endif
void WindowManager::setValue (const std::string& id, const std::string& value) void WindowManager::setValue (const std::string& id, const std::string& value)
{ {
stats->setValue (id, value); stats->setValue (id, value);
@ -505,49 +382,6 @@ const std::string &WindowManager::getGameSettingString(const std::string &id, co
return default_; return default_;
} }
void WindowManager::onNameDialogDone(WindowBase* parWindow)
{
if (nameDialog)
{
playerName = nameDialog->getTextInput();
environment.mMechanicsManager->setPlayerName(playerName);
removeDialog(nameDialog);
}
// Go to next dialog if name was previously chosen
if (creationStage == ReviewNext)
setGuiMode(GM_Review);
else if (creationStage >= NameChosen)
setGuiMode(GM_Race);
else
{
creationStage = NameChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onRaceDialogDone(WindowBase* parWindow)
{
if (raceDialog)
{
playerRaceId = raceDialog->getRaceId();
if (!playerRaceId.empty())
environment.mMechanicsManager->setPlayerRace(playerRaceId, raceDialog->getGender() == RaceDialog::GM_Male);
removeDialog(raceDialog);
}
// Go to next dialog if race was previously chosen
if (creationStage == ReviewNext)
setGuiMode(GM_Review);
else if(creationStage >= RaceChosen)
setGuiMode(GM_Class);
else
{
creationStage = RaceChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onDialogueWindowBye() void WindowManager::onDialogueWindowBye()
{ {
if (dialogueWindow) if (dialogueWindow)
@ -558,434 +392,11 @@ void WindowManager::onDialogueWindowBye()
setGuiMode(GM_Game); setGuiMode(GM_Game);
} }
void WindowManager::onRaceDialogBack()
{
if (raceDialog)
{
playerRaceId = raceDialog->getRaceId();
if (!playerRaceId.empty())
environment.mMechanicsManager->setPlayerRace(playerRaceId, raceDialog->getGender() == RaceDialog::GM_Male);
removeDialog(raceDialog);
}
setGuiMode(GM_Name);
}
void WindowManager::onClassChoice(int _index)
{
if (classChoiceDialog)
{
removeDialog(classChoiceDialog);
}
switch(_index)
{
case ClassChoiceDialog::Class_Generate:
setGuiMode(GM_ClassGenerate);
break;
case ClassChoiceDialog::Class_Pick:
setGuiMode(GM_ClassPick);
break;
case ClassChoiceDialog::Class_Create:
setGuiMode(GM_ClassCreate);
break;
case ClassChoiceDialog::Class_Back:
setGuiMode(GM_Race);
break;
};
}
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
{ {
mMessageBoxManager->onFrame(frameDuration); mMessageBoxManager->onFrame(frameDuration);
} }
namespace MWGui
{
struct Step
{
const char* text;
const char* buttons[3];
// The specialization for each answer
ESM::Class::Specialization specializations[3];
};
static boost::array<Step, 10> generateClassSteps = { {
// Question 1
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
{"Draw your dagger, mercifully endings its life with a single thrust.",
"Use herbs from your pack to put it to sleep.",
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 2
{"One Summer afternoon your father gives you a choice of chores.",
{"Work in the forge with him casting iron for a new plow.",
"Gather herbs for your mother who is preparing dinner.",
"Go catch fish at the stream using a net and line."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 3
{"Your cousin has given you a very embarrassing nickname and, even worse, likes to call you it in front of your friends. You asked him to stop, but he finds it very amusing to watch you blush.",
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 4
{"There is a lot of heated discussion at the local tavern over a grouped of people called 'Telepaths'. They have been hired by certain City-State kings. Rumor has it these Telepaths read a person's mind and tell their lord whether a follower is telling the truth or not.",
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 5
{"Your mother sends you to the market with a list of goods to buy. After you finish you find that by mistake a shopkeeper has given you too much money back in exchange for one of the items.",
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
"Decide to put the extra money to good use and purchase items that would help your family?",
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 6
{"While in the market place you witness a thief cut a purse from a noble. Even as he does so, the noble notices and calls for the city guards. In his haste to get away, the thief drops the purse near you. Surprisingly no one seems to notice the bag of coins at your feet.",
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
"Leave the bag there, knowing that it is better not to get involved.",
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 7
{"Your father sends you on a task which you loathe, cleaning the stables. On the way there, pitchfork in hand, you run into your friend from the homestead near your own. He offers to do it for you, in return for a future favor of his choosing.",
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 8
{"Your mother asks you to help fix the stove. While you are working, a very hot pipe slips its mooring and falls towards her.",
{"Position yourself between the pipe and your mother.",
"Grab the hot pipe and try to push it away.",
"Push your mother out of the way."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 9
{"While in town the baker gives you a sweetroll. Delighted, you take it into an alley to enjoy only to be intercepted by a gang of three other kids your age. The leader demands the sweetroll, or else he and his friends will beat you and take it.",
{"Drop the sweetroll and step on it, then get ready for the fight.",
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
},
// Question 10
{"Entering town you find that you are witness to a very well-dressed man running from a crowd. He screams to you for help. The crowd behind him seem very angry.",
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
}
} };
}
void WindowManager::showClassQuestionDialog()
{
if (generateClassStep == generateClassSteps.size())
{
static boost::array<ClassPoint, 23> classes = { {
{"Acrobat", {6, 2, 2}},
{"Agent", {6, 1, 3}},
{"Archer", {3, 5, 2}},
{"Archer", {5, 5, 0}},
{"Assassin", {6, 3, 1}},
{"Barbarian", {3, 6, 1}},
{"Bard", {3, 3, 3}},
{"Battlemage", {1, 3, 6}},
{"Crusader", {1, 6, 3}},
{"Healer", {3, 1, 6}},
{"Knight", {2, 6, 2}},
{"Monk", {5, 3, 2}},
{"Nightblade", {4, 2, 4}},
{"Pilgrim", {5, 2, 3}},
{"Rogue", {3, 4, 3}},
{"Rogue", {4, 4, 2}},
{"Rogue", {5, 4, 1}},
{"Scout", {2, 5, 3}},
{"Sorcerer", {2, 2, 6}},
{"Spellsword", {2, 4, 4}},
{"Spellsword", {5, 1, 4}},
{"Witchhunter", {2, 3, 5}},
{"Witchhunter", {5, 0, 5}}
} };
int match = -1;
for (unsigned i = 0; i < classes.size(); ++i)
{
if (generateClassSpecializations[0] == classes[i].points[0] &&
generateClassSpecializations[1] == classes[i].points[1] &&
generateClassSpecializations[2] == classes[i].points[2])
{
match = i;
generateClass = classes[i].id;
break;
}
}
if (match == -1)
{
if (generateClassSpecializations[0] >= 7)
generateClass = "Thief";
else if (generateClassSpecializations[1] >= 7)
generateClass = "Warrior";
else if (generateClassSpecializations[2] >= 7)
generateClass = "Mage";
else
{
std::cerr
<< "Failed to deduce class from chosen answers in generate class dialog"
<< std::endl;
generateClass = "Thief";
}
}
if (generateClassResultDialog)
removeDialog(generateClassResultDialog);
generateClassResultDialog = new GenerateClassResultDialog(*this);
generateClassResultDialog->setClassId(generateClass);
generateClassResultDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onGenerateClassBack);
generateClassResultDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onGenerateClassDone);
generateClassResultDialog->open();
return;
}
if (generateClassStep > generateClassSteps.size())
{
setGuiMode(GM_Class);
return;
}
if (generateClassQuestionDialog)
removeDialog(generateClassQuestionDialog);
generateClassQuestionDialog = new InfoBoxDialog(*this);
InfoBoxDialog::ButtonList buttons;
generateClassQuestionDialog->setText(generateClassSteps[generateClassStep].text);
buttons.push_back(generateClassSteps[generateClassStep].buttons[0]);
buttons.push_back(generateClassSteps[generateClassStep].buttons[1]);
buttons.push_back(generateClassSteps[generateClassStep].buttons[2]);
generateClassQuestionDialog->setButtons(buttons);
generateClassQuestionDialog->eventButtonSelected = MyGUI::newDelegate(this, &WindowManager::onClassQuestionChosen);
generateClassQuestionDialog->open();
}
void WindowManager::onClassQuestionChosen(int _index)
{
if (generateClassQuestionDialog)
removeDialog(generateClassQuestionDialog);
if (_index < 0 || _index >= 3)
{
setGuiMode(GM_Class);
return;
}
ESM::Class::Specialization specialization = generateClassSteps[generateClassStep].specializations[_index];
if (specialization == ESM::Class::Stealth)
++generateClassSpecializations[0];
else if (specialization == ESM::Class::Combat)
++generateClassSpecializations[1];
else if (specialization == ESM::Class::Magic)
++generateClassSpecializations[2];
++generateClassStep;
showClassQuestionDialog();
}
void WindowManager::onGenerateClassBack()
{
if(creationStage < ClassChosen)
creationStage = ClassChosen;
if (generateClassResultDialog)
removeDialog(generateClassResultDialog);
environment.mMechanicsManager->setPlayerClass(generateClass);
setGuiMode(GM_Class);
}
void WindowManager::onGenerateClassDone(WindowBase* parWindow)
{
if (generateClassResultDialog)
removeDialog(generateClassResultDialog);
environment.mMechanicsManager->setPlayerClass(generateClass);
// Go to next dialog if class was previously chosen
if (creationStage == ReviewNext)
setGuiMode(GM_Review);
else if (creationStage >= ClassChosen)
setGuiMode(GM_Birth);
else
{
creationStage = ClassChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onPickClassDialogDone(WindowBase* parWindow)
{
if (pickClassDialog)
{
const std::string &classId = pickClassDialog->getClassId();
if (!classId.empty())
environment.mMechanicsManager->setPlayerClass(classId);
const ESM::Class *klass = environment.mWorld->getStore().classes.find(classId);
if (klass)
playerClass = *klass;
removeDialog(pickClassDialog);
}
// Go to next dialog if class was previously chosen
if (creationStage == ReviewNext)
setGuiMode(GM_Review);
else if (creationStage >= ClassChosen)
setGuiMode(GM_Birth);
else
{
creationStage = ClassChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onPickClassDialogBack()
{
if (pickClassDialog)
{
const std::string classId = pickClassDialog->getClassId();
if (!classId.empty())
environment.mMechanicsManager->setPlayerClass(classId);
removeDialog(pickClassDialog);
}
setGuiMode(GM_Class);
}
void WindowManager::onCreateClassDialogDone(WindowBase* parWindow)
{
if (createClassDialog)
{
ESM::Class klass;
klass.name = createClassDialog->getName();
klass.description = createClassDialog->getDescription();
klass.data.specialization = createClassDialog->getSpecializationId();
klass.data.isPlayable = 0x1;
std::vector<int> attributes = createClassDialog->getFavoriteAttributes();
assert(attributes.size() == 2);
klass.data.attribute[0] = attributes[0];
klass.data.attribute[1] = attributes[1];
std::vector<ESM::Skill::SkillEnum> majorSkills = createClassDialog->getMajorSkills();
std::vector<ESM::Skill::SkillEnum> minorSkills = createClassDialog->getMinorSkills();
assert(majorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
assert(minorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
for (size_t i = 0; i < sizeof(klass.data.skills)/sizeof(klass.data.skills[0]); ++i)
{
klass.data.skills[i][1] = majorSkills[i];
klass.data.skills[i][0] = minorSkills[i];
}
environment.mMechanicsManager->setPlayerClass(klass);
playerClass = klass;
removeDialog(createClassDialog);
}
// Go to next dialog if class was previously chosen
if (creationStage == ReviewNext)
setGuiMode(GM_Review);
else if (creationStage >= ClassChosen)
setGuiMode(GM_Birth);
else
{
creationStage = ClassChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onCreateClassDialogBack()
{
if (createClassDialog)
removeDialog(createClassDialog);
setGuiMode(GM_Class);
}
void WindowManager::onBirthSignDialogDone(WindowBase* parWindow)
{
if (birthSignDialog)
{
playerBirthSignId = birthSignDialog->getBirthId();
if (!playerBirthSignId.empty())
environment.mMechanicsManager->setPlayerBirthsign(playerBirthSignId);
removeDialog(birthSignDialog);
}
// Go to next dialog if birth sign was previously chosen
if (creationStage >= BirthSignChosen)
setGuiMode(GM_Review);
else
{
creationStage = BirthSignChosen;
setGuiMode(GM_Game);
}
}
void WindowManager::onBirthSignDialogBack()
{
if (birthSignDialog)
{
environment.mMechanicsManager->setPlayerBirthsign(birthSignDialog->getBirthId());
removeDialog(birthSignDialog);
}
setGuiMode(GM_Class);
}
void WindowManager::onReviewDialogDone(WindowBase* parWindow)
{
if (reviewDialog)
removeDialog(reviewDialog);
setGuiMode(GM_Game);
}
void WindowManager::onReviewDialogBack()
{
if (reviewDialog)
removeDialog(reviewDialog);
setGuiMode(GM_Birth);
}
void WindowManager::onReviewActivateDialog(int parDialog)
{
if (reviewDialog)
removeDialog(reviewDialog);
creationStage = ReviewNext;
switch(parDialog)
{
case ReviewDialog::NAME_DIALOG:
setGuiMode(GM_Name);
break;
case ReviewDialog::RACE_DIALOG:
setGuiMode(GM_Race);
break;
case ReviewDialog::CLASS_DIALOG:
setGuiMode(GM_Class);
break;
case ReviewDialog::BIRTHSIGN_DIALOG:
setGuiMode(GM_Birth);
};
}
const ESMS::ESMStore& WindowManager::getStore() const const ESMS::ESMStore& WindowManager::getStore() const
{ {
return environment.mWorld->getStore(); return environment.mWorld->getStore();

@ -8,13 +8,15 @@
MyGUI should be initialized separately before creating instances of MyGUI should be initialized separately before creating instances of
this class. this class.
*/ **/
#include <string> #include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include <openengine/ogre/renderer.hpp>
#include <openengine/gui/manager.hpp>
#include "../mwmechanics/stat.hpp" #include "../mwmechanics/stat.hpp"
#include "mode.hpp" #include "mode.hpp"
@ -32,6 +34,12 @@ namespace Compiler
namespace MWWorld namespace MWWorld
{ {
class Environment; class Environment;
class World;
}
namespace MWMechanics
{
class MechanicsManager;
} }
namespace OEngine namespace OEngine
@ -52,17 +60,11 @@ namespace MWGui
class InventoryWindow; class InventoryWindow;
class Console; class Console;
class JournalWindow; class JournalWindow;
class CharacterCreation;
class TextInputDialog; class TextInputDialog;
class InfoBoxDialog; class InfoBoxDialog;
class RaceDialog;
class DialogueWindow; class DialogueWindow;
class ClassChoiceDialog;
class GenerateClassResultDialog;
class PickClassDialog;
class CreateClassDialog;
class BirthDialog;
class ReviewDialog;
class MessageBoxManager; class MessageBoxManager;
struct ClassPoint struct ClassPoint
@ -80,95 +82,11 @@ namespace MWGui
typedef std::vector<Faction> FactionList; typedef std::vector<Faction> FactionList;
typedef std::vector<int> SkillList; typedef std::vector<int> SkillList;
private: WindowManager(MWWorld::Environment& environment, const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath);
MWWorld::Environment& environment; virtual ~WindowManager();
HUD *hud;
MapWindow *map;
MainMenu *menu;
StatsWindow *stats;
MessageBoxManager *mMessageBoxManager;
#if 0
InventoryWindow *inventory;
#endif
Console *console;
JournalWindow* mJournal;
// Character creation
TextInputDialog *nameDialog;
RaceDialog *raceDialog;
DialogueWindow *dialogueWindow;
ClassChoiceDialog *classChoiceDialog;
InfoBoxDialog *generateClassQuestionDialog;
GenerateClassResultDialog *generateClassResultDialog;
PickClassDialog *pickClassDialog;
CreateClassDialog *createClassDialog;
BirthDialog *birthSignDialog;
ReviewDialog *reviewDialog;
// Keeps track of current step in Generate Class dialogs
unsigned generateClassStep;
// A counter for each specialization which is increased when an answer is chosen, in order: Stealth, Combat, Magic
unsigned generateClassSpecializations[3];
std::string generateClass;
// Various stats about player as needed by window manager
std::string playerName;
ESM::Class playerClass;
std::string playerRaceId, playerBirthSignId;
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > playerAttributes;
SkillList playerMajorSkills, playerMinorSkills;
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > playerSkillValues;
MWMechanics::DynamicStat<int> playerHealth, playerMagicka, playerFatigue;
// Gui
MyGUI::Gui *gui;
// Current gui mode
GuiMode mode;
/**
* Next mode to activate in update().
*/
GuiMode nextMode;
/**
* Whether a mode change is needed in update().
* Will use @a nextMode as the new mode.
*/
bool needModeChange;
std::vector<OEngine::GUI::Layout*> garbageDialogs;
void cleanupGarbage();
// Currently shown windows in inventory mode
GuiWindow shown;
/* Currently ALLOWED windows in inventory mode. This is used at
the start of the game, when windows are enabled one by one
through script commands. You can manipulate this through using
allow() and disableAll().
The setting should also affect visibility of certain HUD
elements, but this is not done yet.
*/
GuiWindow allowed;
// Update visibility of all windows based on mode, shown and
// allowed settings.
void updateVisible();
void setGuiMode(GuiMode newMode); void setGuiMode(GuiMode newMode);
int showFPSLevel;
float mFPS;
size_t mTriangleCount;
size_t mBatchCount;
public:
/// The constructor needs the main Gui object
WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment,
const Compiler::Extensions& extensions, int fpsLevel, bool newGame);
virtual ~WindowManager();
/** /**
* Should be called each frame to update windows/gui elements. * Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening * This could mean updating sizes of gui elements or opening
@ -190,8 +108,7 @@ namespace MWGui
GuiMode getMode() const { return mode; } GuiMode getMode() const { return mode; }
// Everything that is not game mode is considered "gui mode" bool isGuiMode() const { return getMode() != GM_Game; } // Everything that is not game mode is considered "gui mode"
bool isGuiMode() const { return getMode() != GM_Game; }
// Disallow all inventory mode windows // Disallow all inventory mode windows
void disallowAll() void disallowAll()
@ -216,53 +133,30 @@ namespace MWGui
mBatchCount = batchCount; mBatchCount = batchCount;
} }
void setValue (const std::string& id, const MWMechanics::Stat<int>& value); // MWMechanics::DynamicStat<int> getValue(const std::string& id);
///< Set value for the given ID.
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
///< Set value for the given ID. ///< Set value for the given ID.
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
///< Set value for the given ID.
void setValue (const std::string& id, const std::string& value); void setValue (const std::string& id, const std::string& value);
///< set value for the given ID.
void setValue (const std::string& id, int value); void setValue (const std::string& id, int value);
///< set value for the given ID.
void setPlayerClass (const ESM::Class &class_);
///< set current class of player
void configureSkills (const SkillList& major, const SkillList& minor);
///< configure skill groups, each set contains the skill ID for that group.
void setFactions (const FactionList& factions); void setPlayerClass (const ESM::Class &class_); ///< set current class of player
///< set faction and rank to display on stat window, use an empty vector to disable void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group.
void setFactions (const FactionList& factions); ///< set faction and rank to display on stat window, use an empty vector to disable
void setBirthSign (const std::string &signId); ///< set birth sign to display on stat window, use an empty string to disable.
void setReputation (int reputation); ///< set the current reputation value
void setBounty (int bounty); ///< set the current bounty value
void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
void setBirthSign (const std::string &signId);
///< set birth sign to display on stat window, use an empty string to disable.
void setReputation (int reputation);
///< set the current reputation value
void setBounty (int bounty);
///< set the current bounty value
void updateSkillArea();
///< update display of skills, factions, birth sign, reputation and bounty
template<typename T> template<typename T>
void removeDialog(T*& dialog); void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted.
void removeDialog(OEngine::GUI::Layout* dialog);
///< Hides dialog and schedules dialog to be deleted.
void messageBox (const std::string& message, const std::vector<std::string>& buttons); void messageBox (const std::string& message, const std::vector<std::string>& buttons);
int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
int readPressedButton ();
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
void onFrame (float frameDuration); void onFrame (float frameDuration);
@ -278,54 +172,58 @@ namespace MWGui
const ESMS::ESMStore& getStore() const; const ESMS::ESMStore& getStore() const;
private: private:
OEngine::GUI::MyGUIManager *mGuiManager;
MWWorld::Environment& environment;
HUD *hud;
MapWindow *map;
MainMenu *menu;
StatsWindow *stats;
MessageBoxManager *mMessageBoxManager;
Console *console;
JournalWindow* mJournal;
DialogueWindow *dialogueWindow;
void onDialogueWindowBye(); CharacterCreation* mCharGen;
// Various stats about player as needed by window manager
ESM::Class playerClass;
std::string playerName;
std::string playerRaceId;
std::string playerBirthSignId;
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > playerAttributes;
SkillList playerMajorSkills, playerMinorSkills;
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > playerSkillValues;
MWMechanics::DynamicStat<int> playerHealth, playerMagicka, playerFatigue;
// Character generation: Name dialog
void onNameDialogDone(WindowBase* parWindow);
// Character generation: Race dialog MyGUI::Gui *gui; // Gui
void onRaceDialogDone(WindowBase* parWindow); GuiMode mode; // Current gui mode
void onRaceDialogBack(); GuiMode nextMode; // Next mode to activate in update()
bool needModeChange; //Whether a mode change is needed in update() [will use nextMode]
// Character generation: Choose class process std::vector<OEngine::GUI::Layout*> garbageDialogs;
void onClassChoice(int _index); void cleanupGarbage();
// Character generation: Generate Class GuiWindow shown; // Currently shown windows in inventory mode
void showClassQuestionDialog();
void onClassQuestionChosen(int _index);
void onGenerateClassBack();
void onGenerateClassDone(WindowBase* parWindow);
// Character generation: Pick Class dialog /* Currently ALLOWED windows in inventory mode. This is used at
void onPickClassDialogDone(WindowBase* parWindow); the start of the game, when windows are enabled one by one
void onPickClassDialogBack(); through script commands. You can manipulate this through using
allow() and disableAll().
// Character generation: Create Class dialog The setting should also affect visibility of certain HUD
void onCreateClassDialogDone(WindowBase* parWindow); elements, but this is not done yet.
void onCreateClassDialogBack(); */
GuiWindow allowed;
// Character generation: Birth sign dialog void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
void onBirthSignDialogDone(WindowBase* parWindow);
void onBirthSignDialogBack();
// Character generation: Review dialog int showFPSLevel;
void onReviewDialogDone(WindowBase* parWindow); float mFPS;
void onReviewDialogBack(); size_t mTriangleCount;
void onReviewActivateDialog(int parDialog); size_t mBatchCount;
enum CreationStageEnum void onDialogueWindowBye();
{
NotStarted,
NameChosen,
RaceChosen,
ClassChosen,
BirthSignChosen,
ReviewNext
};
// Which state the character creating is in, controls back/next/ok buttons
CreationStageEnum creationStage;
}; };
template<typename T> template<typename T>

@ -19,14 +19,10 @@ using namespace Ogre;
namespace MWRender { namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mDebugging(engine) :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
{ {
mRendering.createScene("PlayerCam", 55, 5); mRendering.createScene("PlayerCam", 55, 5);
//mSkyManager = 0;
mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), resDir);
// Set default mipmap level (NB some APIs ignore this) // Set default mipmap level (NB some APIs ignore this)
TextureManager::getSingleton().setDefaultNumMipmaps(5); TextureManager::getSingleton().setDefaultNumMipmaps(5);
@ -54,6 +50,9 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
cameraPitchNode->attachObject(mRendering.getCamera()); cameraPitchNode->attachObject(mRendering.getCamera());
//mSkyManager = 0;
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0; mSun = 0;
} }
@ -65,6 +64,10 @@ RenderingManager::~RenderingManager ()
delete mSkyManager; delete mSkyManager;
} }
MWRender::SkyManager* RenderingManager::getSkyManager()
{
return mSkyManager;
}
MWRender::Objects& RenderingManager::getObjects(){ MWRender::Objects& RenderingManager::getObjects(){
return mObjects; return mObjects;
@ -77,6 +80,11 @@ MWRender::Player& RenderingManager::getPlayer(){
return (*mPlayer); return (*mPlayer);
} }
OEngine::Render::Fader* RenderingManager::getFader()
{
return mRendering.getFader();
}
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){ void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){
mObjects.removeCell(store); mObjects.removeCell(store);
mActors.removeCell(store); mActors.removeCell(store);
@ -125,6 +133,10 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve
void RenderingManager::update (float duration){ void RenderingManager::update (float duration){
mActors.update (duration); mActors.update (duration);
mSkyManager->update(duration);
mRendering.update(duration);
} }
void RenderingManager::skyEnable () void RenderingManager::skyEnable ()
@ -167,8 +179,24 @@ void RenderingManager::skySetMoonColour (bool red){
if(mSkyManager) if(mSkyManager)
mSkyManager->setMoonColour(red); mSkyManager->setMoonColour(red);
} }
bool RenderingManager::toggleRenderMode(int mode){
return mDebugging.toggleRenderMode(mode); bool RenderingManager::toggleRenderMode(int mode)
{
if (mode == MWWorld::World::Render_CollisionDebug)
return mDebugging.toggleRenderMode(mode);
else // if (mode == MWWorld::World::Render_Wireframe)
{
if (mRendering.getCamera()->getPolygonMode() == PM_SOLID)
{
mRendering.getCamera()->setPolygonMode(PM_WIREFRAME);
return true;
}
else
{
mRendering.getCamera()->setPolygonMode(PM_SOLID);
return false;
}
}
} }
void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell) void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
@ -176,14 +204,22 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
Ogre::ColourValue color; Ogre::ColourValue color;
color.setAsABGR (mCell.cell->ambi.fog); color.setAsABGR (mCell.cell->ambi.fog);
float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity); configureFog(mCell.cell->ambi.fogDensity, color);
float low = 200; }
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
{
/// \todo make the viewing distance and fog start/end configurable
float low = 3000 / density;
float high = 6200 / density;
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);
mRendering.getScene()->setFog (FOG_LINEAR, color, 0, low, high); mRendering.getCamera()->setFarClipDistance ( high );
mRendering.getCamera()->setFarClipDistance (high + 10); mRendering.getViewport()->setBackgroundColour (colour);
mRendering.getViewport()->setBackgroundColour (color);
} }
void RenderingManager::setAmbientMode() void RenderingManager::setAmbientMode()
{ {
switch (mAmbientMode) switch (mAmbientMode)
@ -252,4 +288,38 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
mActors.skipAnimation(ptr); mActors.skipAnimation(ptr);
} }
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
{
mSun->setDiffuseColour(colour);
}
void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
{
mRendering.getScene()->setAmbientLight(colour);
}
void RenderingManager::sunEnable()
{
if (mSun) mSun->setVisible(true);
} }
void RenderingManager::sunDisable()
{
if (mSun) mSun->setVisible(false);
}
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
{
// direction * -1 (because 'direction' is camera to sun vector and not sun to camera),
// then convert from MW to ogre coordinates (swap y,z and make y negative)
if (mSun) mSun->setDirection(Vector3(-direction.x, -direction.z, direction.y));
mSkyManager->setSunDirection(direction);
}
void RenderingManager::setGlare(bool glare)
{
mSkyManager->setGlare(glare);
}
} // namespace

@ -9,6 +9,7 @@
#include <utility> #include <utility>
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/ogre/fader.hpp>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <vector> #include <vector>
@ -61,9 +62,13 @@ class RenderingManager: private RenderingInterface {
/// MWWorld::Player has been rewritten to not need access /// MWWorld::Player has been rewritten to not need access
/// to internal details of the rendering system anymore /// to internal details of the rendering system anymore
SkyManager* getSkyManager();
void toggleLight(); void toggleLight();
bool toggleRenderMode(int mode); bool toggleRenderMode(int mode);
OEngine::Render::Fader* getFader();
void removeCell (MWWorld::Ptr::CellStore *store); void removeCell (MWWorld::Ptr::CellStore *store);
/// \todo this function should be removed later. Instead the rendering subsystems should track /// \todo this function should be removed later. Instead the rendering subsystems should track
@ -82,6 +87,13 @@ class RenderingManager: private RenderingInterface {
void update (float duration); void update (float duration);
void setAmbientColour(const Ogre::ColourValue& colour);
void setSunColour(const Ogre::ColourValue& colour);
void setSunDirection(const Ogre::Vector3& direction);
void sunEnable();
void sunDisable();
void setGlare(bool glare);
void skyEnable (); void skyEnable ();
void skyDisable (); void skyDisable ();
void skySetHour (double hour); void skySetHour (double hour);
@ -90,9 +102,13 @@ class RenderingManager: private RenderingInterface {
int skyGetSecundaPhase() const; int skyGetSecundaPhase() const;
void skySetMoonColour (bool red); void skySetMoonColour (bool red);
void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell); void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell);
/// configure fog according to cell /// configure fog according to cell
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell); void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
/// configure fog manually
void configureFog(const float density, const Ogre::ColourValue& colour);
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
int number = 1); int number = 1);
///< Run animation for a MW-reference. Calls to this function for references that are currently not ///< Run animation for a MW-reference. Calls to this function for references that are currently not
@ -108,7 +124,9 @@ class RenderingManager: private RenderingInterface {
private: private:
void setAmbientMode(); void setAmbientMode();
SkyManager* mSkyManager; SkyManager* mSkyManager;
OEngine::Render::OgreRenderer &mRendering; OEngine::Render::OgreRenderer &mRendering;
MWRender::Objects mObjects; MWRender::Objects mObjects;

@ -1,116 +1,764 @@
#include "sky.hpp" #include "sky.hpp"
#include "Caelum.h"
namespace MWRender
{
//
// Implements a Caelum sky with default settings.
//
// Note: this is intended as a temporary solution to provide some form of
// 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.
//
class CaelumManager : public SkyManager
{
protected:
Caelum::CaelumSystem* mpCaelumSystem;
public: #include <OgreCamera.h>
CaelumManager (Ogre::RenderWindow* pRenderWindow, #include <OgreRenderWindow.h>
Ogre::Camera* pCamera, #include <OgreSceneNode.h>
const boost::filesystem::path& resDir); #include <OgreMesh.h>
virtual ~CaelumManager (); #include <OgreSceneManager.h>
#include <OgreHardwareVertexBuffer.h>
#include <OgreHighLevelGpuProgramManager.h>
virtual void enable() {} #include <components/nifogre/ogre_nif_loader.hpp>
virtual void disable() {} using namespace MWRender;
using namespace Ogre;
virtual void setHour (double hour) {} // the speed at which the clouds are animated
///< will be called even when sky is disabled. #define CLOUD_SPEED 0.001
virtual void setDate (int day, int month) {} // this distance has to be set accordingly so that the
///< will be called even when sky is disabled. // celestial bodies are behind the clouds, but in front of the atmosphere
#define CELESTIAL_BODY_DISTANCE 1000.f
virtual int getMasserPhase() const { return 0; } BillboardObject::BillboardObject( const String& textureName,
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half, const float initialSize,
/// 3 waxing or waning gibbous, 4 full moon const Vector3& position,
SceneNode* rootNode)
{
init(textureName, initialSize, position, rootNode);
}
virtual int getSecundaPhase() const { return 0; } BillboardObject::BillboardObject()
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half, {
/// 3 waxing or waning gibbous, 4 full moon }
virtual void setMoonColour (bool red) {} void BillboardObject::setVisible(const bool visible)
}; {
mNode->setVisible(visible);
}
CaelumManager::CaelumManager (Ogre::RenderWindow* pRenderWindow, void BillboardObject::setSize(const float size)
Ogre::Camera* pCamera, {
const boost::filesystem::path& resDir) mNode->setScale(size, size, size);
: mpCaelumSystem (NULL) }
{
using namespace Ogre;
using namespace Caelum;
assert(pCamera); void BillboardObject::setVisibility(const float visibility)
assert(pRenderWindow); {
mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility);
}
// Load the Caelum resources void BillboardObject::setPosition(const Vector3& pPosition)
// {
ResourceGroupManager::getSingleton().addResourceLocation((resDir / "caelum").string(), "FileSystem", "Caelum"); Vector3 normalised = pPosition.normalisedCopy();
ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE;
// Load the Caelum resources mBBSet->setCommonDirection( -normalised );
//
Ogre::SceneManager* pScene = pCamera->getSceneManager();
Caelum::CaelumSystem::CaelumComponent componentMask = CaelumSystem::CAELUM_COMPONENTS_DEFAULT;
mpCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), pScene, componentMask);
// Set time acceleration. mNode->setPosition(finalPosition);
mpCaelumSystem->getUniversalClock()->setTimeScale(128); }
// Disable fog since OpenMW is handling OGRE fog elsewhere Vector3 BillboardObject::getPosition() const
mpCaelumSystem->setManageSceneFog(false); {
return mNode->getPosition();
}
void BillboardObject::setColour(const ColourValue& pColour)
{
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
}
void BillboardObject::setRenderQueue(unsigned int id)
{
mBBSet->setRenderQueueGroup(id);
}
SceneNode* BillboardObject::getNode()
{
return mNode;
}
void BillboardObject::init(const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode)
{
SceneManager* sceneMgr = rootNode->getCreator();
// Change the camera far distance to make sure the sky is not clipped Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
pCamera->setFarClipDistance(50000);
// Register Caelum as an OGRE listener static unsigned int bodyCount=0;
pRenderWindow->addListener(mpCaelumSystem);
Root::getSingletonPtr()->addFrameListener(mpCaelumSystem); /// \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, &currentVertex );
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;
} }
CaelumManager::~CaelumManager() // 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)
{ {
if (mpCaelumSystem) MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
mpCaelumSystem->shutdown (false); 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;
} }
/// Creates and connects the sky rendering component to OGRE. // Stars vertex shader
/// HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
/// \return NULL on failure. "cg", GPT_VERTEX_PROGRAM);
/// vshader3->setParameter("profiles", "vs_2_x arbvp1");
SkyManager* SkyManager::create (Ogre::RenderWindow* pRenderWindow, vshader3->setParameter("entry_point", "main_vp");
Ogre::Camera* pCamera, StringUtil::StrStreamType outStream4;
const boost::filesystem::path& resDir) 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());
// Clouds
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();
// Clouds vertex shader
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
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());
// Clouds fragment shader
mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1");
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);
ModVertexAlpha(clouds_ent, 1);
// I'm not sure if the materials are being used by any other objects
// 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);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
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);
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
}
SkyManager::~SkyManager()
{
delete mSun;
delete mSunGlare;
delete mMasser;
delete mSecunda;
}
int SkyManager::getMasserPhase() const
{
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)
{ {
SkyManager* pSkyManager = NULL; 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;
try if (mGlareEnabled)
{ {
pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir); mGlareFade += duration*3;
if (mGlareFade > 1) mGlareFade = 1;
} }
catch (Ogre::Exception& e) else
{ {
std::cout << "\nOGRE Exception when attempting to add sky: " mGlareFade -= duration*3;
<< e.getFullDescription().c_str() << std::endl; if (mGlareFade < 0.3) mGlareFade = 0;
}
catch (std::exception& e)
{
std::cout << "\nException when attempting to add sky: "
<< e.what() << std::endl;
} }
return pSkyManager; mSunGlare->setSize(val * (mGlareFade));
} }
mSunGlare->setVisible(mGlareFade>0 && mSunEnabled);
mSun->setVisible(mSunEnabled);
mMasser->setVisible(mMasserEnabled);
mSecunda->setVisible(mSecundaEnabled);
}
void SkyManager::enable()
{
mRootNode->setVisible(true);
mEnabled = true;
}
void SkyManager::disable()
{
mRootNode->setVisible(false);
mEnabled = false;
}
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)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
}
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;
} }

@ -1,40 +1,211 @@
#ifndef _GAME_RENDER_SKY_H #ifndef _GAME_RENDER_SKY_H
#define _GAME_RENDER_SKY_H #define _GAME_RENDER_SKY_H
#include <boost/filesystem.hpp> #include <OgreVector3.h>
#include <OgreString.h>
#include <OgreMaterial.h>
#include <OgreColourValue.h>
#include <OgreHighLevelGpuProgram.h>
#include "sky.hpp"
#include "../mwworld/weather.hpp"
namespace Ogre namespace Ogre
{ {
class RenderWindow; class RenderWindow;
class SceneNode;
class Camera; class Camera;
class Viewport;
class SceneManager;
class Entity;
class BillboardSet;
class TextureUnitState;
class Overlay;
} }
namespace MWRender namespace MWRender
{ {
/// class BillboardObject
/// Interface for the sky rendering system {
/// public:
BillboardObject( const Ogre::String& textureName,
const float size,
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode
);
BillboardObject();
void setColour(const Ogre::ColourValue& pColour);
void setPosition(const Ogre::Vector3& pPosition);
void setVisible(const bool visible);
void setRenderQueue(unsigned int id);
void setSize(const float size);
Ogre::Vector3 getPosition() const;
void setVisibility(const float visibility);
Ogre::SceneNode* getNode();
protected:
virtual void init(const Ogre::String& textureName,
const float size,
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode);
Ogre::SceneNode* mNode;
Ogre::MaterialPtr mMaterial;
Ogre::BillboardSet* mBBSet;
};
/*
* The moons need a seperate class because of their shader (which allows them to be partially transparent)
*/
class Moon : public BillboardObject
{
public:
Moon( const Ogre::String& textureName,
const float size,
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode
);
enum Phase
{
Phase_New = 0,
Phase_WaxingCrescent,
Phase_WaxingHalf,
Phase_WaxingGibbous,
Phase_Full,
Phase_WaningGibbous,
Phase_WaningHalf,
Phase_WaningCrescent
};
enum Type
{
Type_Masser = 0,
Type_Secunda
};
void setPhase(const Phase& phase);
void setType(const Type& type);
Phase getPhase() const;
unsigned int getPhaseInt() const;
private:
Type mType;
Phase mPhase;
};
class SkyManager class SkyManager
{ {
public: public:
static SkyManager* create (Ogre::RenderWindow* pRenderWindow, SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera);
Ogre::Camera* pCamera, ~SkyManager();
const boost::filesystem::path& resDir);
virtual ~SkyManager() {} void update(float duration);
void enable();
void disable();
void setHour (double hour);
///< will be called even when sky is disabled.
void setDate (int day, int month);
///< will be called even when sky is disabled.
int getMasserPhase() const;
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
/// 3 waxing or waning gibbous, 4 full moon
int getSecundaPhase() const;
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
/// 3 waxing or waning gibbous, 4 full moon
void setMoonColour (bool red);
///< change Secunda colour to red
void setCloudsOpacity(float opacity);
///< change opacity of the clouds
void setWeather(const MWWorld::WeatherResult& weather);
void sunEnable();
void sunDisable();
void setSunDirection(const Ogre::Vector3& direction);
void setMasserDirection(const Ogre::Vector3& direction);
void setSecundaDirection(const Ogre::Vector3& direction);
void setMasserFade(const float fade);
void setSecundaFade(const float fade);
void masserEnable();
void masserDisable();
void secundaEnable();
void secundaDisable();
void setThunder(const float factor);
void setGlare(bool glare);
Ogre::Vector3 getRealSunPos();
private:
float mHour;
int mDay;
int mMonth;
BillboardObject* mSun;
BillboardObject* mSunGlare;
Moon* mMasser;
Moon* mSecunda;
Ogre::Viewport* mViewport;
Ogre::SceneNode* mRootNode;
Ogre::SceneManager* mSceneMgr;
Ogre::SceneNode* mAtmosphereDay;
Ogre::SceneNode* mAtmosphereNight;
Ogre::MaterialPtr mCloudMaterial;
Ogre::MaterialPtr mAtmosphereMaterial;
Ogre::MaterialPtr mStarsMaterials[7];
virtual void enable() = 0; Ogre::HighLevelGpuProgramPtr mCloudFragmentShader;
virtual void disable() = 0; // remember some settings so we don't have to apply them again if they didnt change
Ogre::String mClouds;
Ogre::String mNextClouds;
float mCloudBlendFactor;
float mCloudOpacity;
float mCloudSpeed;
float mStarsOpacity;
Ogre::ColourValue mCloudColour;
Ogre::ColourValue mSkyColour;
virtual void setHour (double hour) = 0; Ogre::Overlay* mThunderOverlay;
Ogre::TextureUnitState* mThunderTextureUnit;
virtual void setDate (int day, int month) = 0; float mRemainingTransitionTime;
virtual int getMasserPhase() const = 0; float mGlareFade;
virtual int getSecundaPhase() const = 0; void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
virtual void setMoonColour (bool red) = 0; bool mEnabled;
bool mGlareEnabled;
bool mSunEnabled;
bool mMasserEnabled;
bool mSecundaEnabled;
}; };
} }

@ -11,7 +11,7 @@
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/containerutil.hpp" #include "../mwworld/containerstore.hpp"
#include "interpretercontext.hpp" #include "interpretercontext.hpp"
#include "ref.hpp" #include "ref.hpp"
@ -45,8 +45,7 @@ namespace MWScript
ref.getPtr().getRefData().setCount (count); ref.getPtr().getRefData().setCount (count);
MWWorld::Class::get (ref.getPtr()).insertIntoContainer (ref.getPtr(), MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr());
MWWorld::Class::get (ptr).getContainerStore (ptr));
} }
}; };
@ -59,25 +58,16 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string item = runtime.getStringLiteral (runtime[0].mInteger); std::string item = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
std::vector<MWWorld::Ptr> list; MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
MWWorld::listItemsInContainer (item,
MWWorld::Class::get (ptr).getContainerStore (ptr),
context.getWorld().getStore(), list);
Interpreter::Type_Integer sum = 0; Interpreter::Type_Integer sum = 0;
for (std::vector<MWWorld::Ptr>::iterator iter (list.begin()); iter!=list.end(); for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
++iter) if (iter->getCellRef().refID==item)
{ sum += iter->getRefData().getCount();
sum += iter->getRefData().getCount();
}
runtime.push (sum); runtime.push (sum);
} }
@ -92,9 +82,6 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string item = runtime.getStringLiteral (runtime[0].mInteger); std::string item = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
@ -104,25 +91,23 @@ namespace MWScript
if (count<0) if (count<0)
throw std::runtime_error ("second argument for RemoveItem must be non-negative"); throw std::runtime_error ("second argument for RemoveItem must be non-negative");
std::vector<MWWorld::Ptr> list; MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
MWWorld::listItemsInContainer (item, for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count;
MWWorld::Class::get (ptr).getContainerStore (ptr),
context.getWorld().getStore(), list);
for (std::vector<MWWorld::Ptr>::iterator iter (list.begin());
iter!=list.end() && count;
++iter) ++iter)
{ {
if (iter->getRefData().getCount()<=count) if (iter->getCellRef().refID==item)
{
count -= iter->getRefData().getCount();
iter->getRefData().setCount (0);
}
else
{ {
iter->getRefData().setCount (iter->getRefData().getCount()-count); if (iter->getRefData().getCount()<=count)
count = 0; {
count -= iter->getRefData().getCount();
iter->getRefData().setCount (0);
}
else
{
iter->getRefData().setCount (iter->getRefData().getCount()-count);
count = 0;
}
} }
} }

@ -115,4 +115,10 @@ op 0x2000136: GetPCCell
op 0x2000137: GetButtonPressed op 0x2000137: GetButtonPressed
op 0x2000138: SkipAnim op 0x2000138: SkipAnim
op 0x2000139: SkipAnim, expplicit reference op 0x2000139: SkipAnim, expplicit reference
opcodes 0x200013a-0x3ffffff unused op 0x200013b: twf
op 0x200013c: FadeIn
op 0x200013d: FadeOut
op 0x200013e: FadeTo
op 0x200013f: GetCurrentWeather
op 0x2000140: ChangeWeather
opcodes 0x2000141-0x3ffffff unused

@ -103,7 +103,75 @@ namespace MWScript
context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug); context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug);
context.report (enabled ? context.report (enabled ?
"Collsion Mesh Rendering -> On" : "Collision Mesh Rendering -> Off"); "Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
}
};
class OpToggleWireframe : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
bool enabled =
context.getWorld().toggleRenderMode (MWWorld::World::Render_Wireframe);
context.report (enabled ?
"Wireframe Rendering -> On" : "Wireframe Rendering -> Off");
}
};
class OpFadeIn : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeIn(time);
}
};
class OpFadeOut : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeOut(time);
}
};
class OpFadeTo : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
Interpreter::Type_Float alpha = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop();
context.getWorld().getFader()->fadeTo(alpha, time);
} }
}; };
@ -115,6 +183,10 @@ namespace MWScript
const int opcodeUnlock = 0x200008c; const int opcodeUnlock = 0x200008c;
const int opcodeUnlockExplicit = 0x200008d; const int opcodeUnlockExplicit = 0x200008d;
const int opcodeToggleCollisionDebug = 0x2000132; const int opcodeToggleCollisionDebug = 0x2000132;
const int opcodeToggleWireframe = 0x200013b;
const int opcodeFadeIn = 0x200013c;
const int opcodeFadeOut = 0x200013d;
const int opcodeFadeTo = 0x200013e;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -127,6 +199,11 @@ namespace MWScript
extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug); extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug);
extensions.registerInstruction ("tcb", "", opcodeToggleCollisionDebug); extensions.registerInstruction ("tcb", "", opcodeToggleCollisionDebug);
extensions.registerInstruction ("tcg", "", opcodeToggleCollisionDebug); extensions.registerInstruction ("tcg", "", opcodeToggleCollisionDebug);
extensions.registerInstruction ("twf", "", opcodeToggleWireframe);
extensions.registerInstruction ("togglewireframe", "", opcodeToggleWireframe);
extensions.registerInstruction ("fadein", "f", opcodeFadeIn);
extensions.registerInstruction ("fadeout", "f", opcodeFadeOut);
extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -139,6 +216,10 @@ namespace MWScript
interpreter.installSegment5 (opcodeUnlock, new OpUnlock<ImplicitRef>); interpreter.installSegment5 (opcodeUnlock, new OpUnlock<ImplicitRef>);
interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock<ExplicitRef>); interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock<ExplicitRef>);
interpreter.installSegment5 (opcodeToggleCollisionDebug, new OpToggleCollisionDebug); interpreter.installSegment5 (opcodeToggleCollisionDebug, new OpToggleCollisionDebug);
interpreter.installSegment5 (opcodeToggleWireframe, new OpToggleWireframe);
interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn);
interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut);
interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
} }
} }
} }

@ -80,11 +80,45 @@ namespace MWScript
} }
}; };
class OpGetCurrentWeather : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
runtime.push (context.getWorld().getCurrentWeather());
}
};
class OpChangeWeather : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
std::string region = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer id = runtime[0].mInteger;
runtime.pop();
context.getWorld().changeWeather(region, id);
}
};
const int opcodeToggleSky = 0x2000021; const int opcodeToggleSky = 0x2000021;
const int opcodeTurnMoonWhite = 0x2000022; const int opcodeTurnMoonWhite = 0x2000022;
const int opcodeTurnMoonRed = 0x2000023; const int opcodeTurnMoonRed = 0x2000023;
const int opcodeGetMasserPhase = 0x2000024; const int opcodeGetMasserPhase = 0x2000024;
const int opcodeGetSecundaPhase = 0x2000025; const int opcodeGetSecundaPhase = 0x2000025;
const int opcodeGetCurrentWeather = 0x200013f;
const int opcodeChangeWeather = 0x2000140;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -92,8 +126,10 @@ namespace MWScript
extensions.registerInstruction ("ts", "", opcodeToggleSky); extensions.registerInstruction ("ts", "", opcodeToggleSky);
extensions.registerInstruction ("turnmoonwhite", "", opcodeTurnMoonWhite); extensions.registerInstruction ("turnmoonwhite", "", opcodeTurnMoonWhite);
extensions.registerInstruction ("turnmoonred", "", opcodeTurnMoonRed); extensions.registerInstruction ("turnmoonred", "", opcodeTurnMoonRed);
extensions.registerInstruction ("changeweather", "Sl", opcodeChangeWeather);
extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase);
extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase);
extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -103,6 +139,8 @@ namespace MWScript
interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed); interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed);
interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase); interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase);
interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase);
interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather);
interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather);
} }
} }
} }

@ -10,6 +10,7 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "interpretercontext.hpp" #include "interpretercontext.hpp"
#include "ref.hpp" #include "ref.hpp"

@ -4,6 +4,7 @@
#include "class.hpp" #include "class.hpp"
#include "environment.hpp" #include "environment.hpp"
#include "world.hpp" #include "world.hpp"
#include "containerstore.hpp"
namespace MWWorld namespace MWWorld
{ {
@ -14,8 +15,7 @@ namespace MWWorld
// insert into player's inventory // insert into player's inventory
MWWorld::Ptr player = environment.mWorld->getPtr ("player", true); MWWorld::Ptr player = environment.mWorld->getPtr ("player", true);
MWWorld::Class::get (mObject).insertIntoContainer (mObject, MWWorld::Class::get (player).getContainerStore (player).add (mObject);
MWWorld::Class::get (player).getContainerStore (player));
// remove from world // remove from world
environment.mWorld->deleteObject (mObject); environment.mWorld->deleteObject (mObject);

@ -7,6 +7,7 @@
#include "ptr.hpp" #include "ptr.hpp"
#include "nullaction.hpp" #include "nullaction.hpp"
#include "containerstore.hpp"
namespace MWWorld namespace MWWorld
{ {
@ -71,16 +72,11 @@ namespace MWWorld
return boost::shared_ptr<Action> (new NullAction); return boost::shared_ptr<Action> (new NullAction);
} }
ContainerStore<RefData>& Class::getContainerStore (const Ptr& ptr) const ContainerStore& Class::getContainerStore (const Ptr& ptr) const
{ {
throw std::runtime_error ("class does not have a container store"); throw std::runtime_error ("class does not have a container store");
} }
void Class::insertIntoContainer (const Ptr& ptr, ContainerStore<RefData>& containerStore) const
{
throw std::runtime_error ("class does not support inserting into a container");
}
void Class::lock (const Ptr& ptr, int lockLevel) const void Class::lock (const Ptr& ptr, int lockLevel) const
{ {
throw std::runtime_error ("class does not support locking"); throw std::runtime_error ("class does not support locking");

@ -7,11 +7,11 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "action.hpp" #include "action.hpp"
#include "containerstore.hpp"
#include "refdata.hpp" #include "refdata.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "physicssystem.hpp" #include "physicssystem.hpp"
#include "../mwrender/renderinginterface.hpp"
namespace Ogre namespace Ogre
{ {
class Vector3; class Vector3;
@ -33,6 +33,7 @@ namespace MWWorld
{ {
class Ptr; class Ptr;
class Environment; class Environment;
class ContainerStore;
/// \brief Base class for referenceable esm records /// \brief Base class for referenceable esm records
class Class class Class
@ -61,8 +62,6 @@ namespace MWWorld
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
/// (default implementation: throw an exception) /// (default implementation: throw an exception)
virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering (default implementation: don't render anything). ///< Add reference into a cell for rendering (default implementation: don't render anything).
@ -105,15 +104,10 @@ namespace MWWorld
///< Generate action for using via inventory menu (default implementation: return a ///< Generate action for using via inventory menu (default implementation: return a
/// null action). /// null action).
virtual ContainerStore<RefData>& getContainerStore (const Ptr& ptr) const; virtual ContainerStore& getContainerStore (const Ptr& ptr) const;
///< Return container store or throw an exception, if class does not have a ///< Return container store or throw an exception, if class does not have a
/// container store (default implementation: throw an exceoption) /// container store (default implementation: throw an exceoption)
virtual void insertIntoContainer (const Ptr& ptr, ContainerStore<RefData>& containerStore)
const;
///< Insert into a container or throw an exception, if class does not support inserting into
/// a container.
virtual void lock (const Ptr& ptr, int lockLevel) const; virtual void lock (const Ptr& ptr, int lockLevel) const;
///< Lock object (default implementation: throw an exception) ///< Lock object (default implementation: throw an exception)

@ -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);
}

@ -3,24 +3,134 @@
#include <components/esm_store/cell_store.hpp> #include <components/esm_store/cell_store.hpp>
#include "refdata.hpp"
#include "ptr.hpp"
namespace MWWorld namespace MWWorld
{ {
template<typename D> class ContainerStoreIterator;
struct ContainerStore
class ContainerStore
{ {
ESMS::CellRefList<ESM::Potion, D> potions; public:
ESMS::CellRefList<ESM::Apparatus, D> appas;
ESMS::CellRefList<ESM::Armor, D> armors; static const int Type_Potion = 0x0001;
ESMS::CellRefList<ESM::Book, D> books; static const int Type_Apparatus = 0x0002;
ESMS::CellRefList<ESM::Clothing, D> clothes; static const int Type_Armor = 0x0004;
ESMS::CellRefList<ESM::Ingredient, D> ingreds; static const int Type_Book = 0x0008;
ESMS::CellRefList<ESM::Light, D> lights; static const int Type_Clothing = 0x0010;
ESMS::CellRefList<ESM::Tool, D> lockpicks; static const int Type_Ingredient = 0x0020;
ESMS::CellRefList<ESM::Miscellaneous, D> miscItems; static const int Type_Light = 0x0040;
ESMS::CellRefList<ESM::Probe, D> probes; static const int Type_Lockpick = 0x0080;
ESMS::CellRefList<ESM::Repair, D> repairs; static const int Type_Miscellaneous = 0x0100;
ESMS::CellRefList<ESM::Weapon, D> weapons; static const int Type_Probe = 0x0200;
static const int Type_Repair = 0x0400;
static const int Type_Weapon = 0x0800;
static const int Type_Last = Type_Weapon;
static const int Type_All = 0xffff;
private:
ESMS::CellRefList<ESM::Potion, RefData> potions;
ESMS::CellRefList<ESM::Apparatus, RefData> appas;
ESMS::CellRefList<ESM::Armor, RefData> armors;
ESMS::CellRefList<ESM::Book, RefData> books;
ESMS::CellRefList<ESM::Clothing, RefData> clothes;
ESMS::CellRefList<ESM::Ingredient, RefData> ingreds;
ESMS::CellRefList<ESM::Light, RefData> lights;
ESMS::CellRefList<ESM::Tool, RefData> lockpicks;
ESMS::CellRefList<ESM::Miscellaneous, RefData> miscItems;
ESMS::CellRefList<ESM::Probe, RefData> probes;
ESMS::CellRefList<ESM::Repair, RefData> repairs;
ESMS::CellRefList<ESM::Weapon, RefData> weapons;
public:
ContainerStoreIterator begin (int mask = Type_All);
ContainerStoreIterator end();
void add (const Ptr& ptr);
///< Add the item pointed to by \a ptr to this container.
///
/// \note The item pointed to is not required to exist beyond this function call.
///
/// \attention Do not add items to an existing stack by increasing the count instead of
/// calling this function!
static int getType (const Ptr& ptr);
///< This function throws an exception, if ptr does not point to an object, that can be
/// put into a container.
friend class ContainerStoreIterator;
}; };
/// \brief Iteration over a subset of objects in a ContainerStore
///
/// \note The iterator will automatically skip over deleted objects.
class ContainerStoreIterator
{
int mType;
int mMask;
ContainerStore *mContainer;
mutable Ptr mPtr;
ESMS::CellRefList<ESM::Potion, RefData>::List::iterator mPotion;
ESMS::CellRefList<ESM::Apparatus, RefData>::List::iterator mApparatus;
ESMS::CellRefList<ESM::Armor, RefData>::List::iterator mArmor;
ESMS::CellRefList<ESM::Book, RefData>::List::iterator mBook;
ESMS::CellRefList<ESM::Clothing, RefData>::List::iterator mClothing;
ESMS::CellRefList<ESM::Ingredient, RefData>::List::iterator mIngredient;
ESMS::CellRefList<ESM::Light, RefData>::List::iterator mLight;
ESMS::CellRefList<ESM::Tool, RefData>::List::iterator mLockpick;
ESMS::CellRefList<ESM::Miscellaneous, RefData>::List::iterator mMiscellaneous;
ESMS::CellRefList<ESM::Probe, RefData>::List::iterator mProbe;
ESMS::CellRefList<ESM::Repair, RefData>::List::iterator mRepair;
ESMS::CellRefList<ESM::Weapon, RefData>::List::iterator mWeapon;
private:
ContainerStoreIterator (ContainerStore *container);
///< End-iterator
ContainerStoreIterator (int mask, ContainerStore *container);
///< Begin-iterator
void incType();
void nextType();
bool resetIterator();
///< Reset iterator for selected type.
///
/// \return Type not empty?
bool incIterator();
///< Increment iterator for selected type.
///
/// \return reached the end?
public:
Ptr *operator->() const;
Ptr operator*() const;
ContainerStoreIterator& operator++();
ContainerStoreIterator operator++ (int);
bool isEqual (const ContainerStoreIterator& iter) const;
int getType() const;
friend class ContainerStore;
};
bool operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right);
bool operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right);
} }
#endif #endif

@ -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,17 @@
#ifndef GAME_MWWORLD_CUSTOMDATA_H
#define GAME_MWWORLD_CUSTOMDATA_H
namespace MWWorld
{
/// \brief Base class for the MW-class-specific part of RefData
class CustomData
{
public:
virtual ~CustomData() {}
virtual CustomData *clone() const = 0;
};
}
#endif

@ -82,6 +82,7 @@ namespace MWWorld
// initialise // initialise
ESM::CellRef& cellRef = mPtr.getCellRef(); ESM::CellRef& cellRef = mPtr.getCellRef();
cellRef.refID = name;
cellRef.refnum = -1; cellRef.refnum = -1;
cellRef.scale = 1; cellRef.scale = 1;
cellRef.factIndex = 0; cellRef.factIndex = 0;

@ -3,6 +3,7 @@
#include "physicssystem.hpp" #include "physicssystem.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/world.hpp" // FIXME #include "../mwworld/world.hpp" // FIXME
#include <components/nifbullet/bullet_nif_loader.hpp>
#include "OgreRoot.h" #include "OgreRoot.h"
#include "OgreRenderWindow.h" #include "OgreRenderWindow.h"
@ -16,16 +17,24 @@ using namespace Ogre;
namespace MWWorld namespace MWWorld
{ {
PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng) : PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) :
mRender(_rend), mEngine(physEng), mFreeFly (true) mRender(_rend), mEngine(0), mFreeFly (true)
{ {
// Create physics. shapeLoader is deleted by the physic engine
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
} }
PhysicsSystem::~PhysicsSystem() PhysicsSystem::~PhysicsSystem()
{ {
delete mEngine;
} }
OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
{
return mEngine;
}
std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world) std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world)
{ {
std::string handle = ""; std::string handle = "";
@ -42,6 +51,17 @@ namespace MWWorld
return mEngine->rayTest(from,to); return mEngine->rayTest(from,to);
} }
bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to)
{
btVector3 _from, _to;
_from = btVector3(from.x, from.y, from.z);
_to = btVector3(to.x, to.y, to.z);
std::pair<std::string, float> result = mEngine->rayTest(_from, _to);
return !(result.first == "");
}
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration, std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors) const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)

@ -12,7 +12,7 @@ namespace MWWorld
class PhysicsSystem class PhysicsSystem
{ {
public: public:
PhysicsSystem (OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng); PhysicsSystem (OEngine::Render::OgreRenderer &_rend);
~PhysicsSystem (); ~PhysicsSystem ();
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration, std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration,
@ -33,11 +33,17 @@ namespace MWWorld
void scaleObject (const std::string& handle, float scale); void scaleObject (const std::string& handle, float scale);
bool toggleCollisionMode(); bool toggleCollisionMode();
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
// cast ray, return true if it hit something
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);
void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model); void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model);
void insertActorPhysics(const MWWorld::Ptr&, std::string model); void insertActorPhysics(const MWWorld::Ptr&, std::string model);
OEngine::Physic::PhysicEngine* getEngine();
private: private:
OEngine::Render::OgreRenderer &mRender; OEngine::Render::OgreRenderer &mRender;

@ -3,6 +3,8 @@
#include "../mwrender/player.hpp" #include "../mwrender/player.hpp"
#include "../mwmechanics/movement.hpp"
#include "world.hpp" #include "world.hpp"
#include "class.hpp" #include "class.hpp"

@ -5,6 +5,8 @@
#include <boost/any.hpp> #include <boost/any.hpp>
#include <components/esm/loadcell.hpp>
#include <components/esm_store/cell_store.hpp> #include <components/esm_store/cell_store.hpp>
#include "refdata.hpp" #include "refdata.hpp"

@ -0,0 +1,144 @@
#include "refdata.hpp"
#include <components/esm_store/cell_store.hpp>
#include "customdata.hpp"
namespace MWWorld
{
void RefData::copy (const RefData& refData)
{
mBaseNode = refData.mBaseNode;
mLocals = refData.mLocals;
mHasLocals = refData.mHasLocals;
mEnabled = refData.mEnabled;
mCount = refData.mCount;
mPosition = refData.mPosition;
mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0;
}
void RefData::cleanup()
{
mBaseNode = 0;
delete mCustomData;
mCustomData = 0;
}
RefData::RefData (const ESM::CellRef& cellRef)
: mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.pos),
mCustomData (0)
{}
RefData::RefData (const RefData& refData)
: mBaseNode(0), mCustomData (0)
{
try
{
copy (refData);
}
catch (...)
{
cleanup();
throw;
}
}
RefData& RefData::operator= (const RefData& refData)
{
try
{
cleanup();
copy (refData);
}
catch (...)
{
cleanup();
throw;
}
return *this;
}
RefData::~RefData()
{
try
{
cleanup();
}
catch (...)
{}
}
std::string RefData::getHandle()
{
return mBaseNode->getName();
}
Ogre::SceneNode* RefData::getBaseNode()
{
return mBaseNode;
}
void RefData::setBaseNode(Ogre::SceneNode* base)
{
mBaseNode = base;
}
int RefData::getCount() const
{
return mCount;
}
void RefData::setLocals (const ESM::Script& script)
{
if (!mHasLocals)
{
mLocals.configure (script);
mHasLocals = true;
}
}
void RefData::setCount (int count)
{
mCount = count;
}
MWScript::Locals& RefData::getLocals()
{
return mLocals;
}
bool RefData::isEnabled() const
{
return mEnabled;
}
void RefData::enable()
{
mEnabled = true;
}
void RefData::disable()
{
mEnabled = true;
}
ESM::Position& RefData::getPosition()
{
return mPosition;
}
void RefData::setCustomData (CustomData *data)
{
delete mCustomData;
mCustomData = data;
}
CustomData *RefData::getCustomData()
{
return mCustomData;
}
}

@ -3,24 +3,22 @@
#include <string> #include <string>
#include <boost/shared_ptr.hpp> #include <Ogre.h>
#include "../mwscript/locals.hpp"
#include "../mwmechanics/creaturestats.hpp" #include <components/esm/defs.hpp>
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/movement.hpp"
#include "containerstore.hpp" #include "../mwscript/locals.hpp"
#include <Ogre.h>
namespace ESM namespace ESM
{ {
class Script; class Script;
class CellRef;
} }
namespace MWWorld namespace MWWorld
{ {
class CustomData;
class RefData class RefData
{ {
Ogre::SceneNode* mBaseNode; Ogre::SceneNode* mBaseNode;
@ -33,102 +31,58 @@ namespace MWWorld
bool mEnabled; bool mEnabled;
int mCount; // 0: deleted int mCount; // 0: deleted
// we are using shared pointer here to avoid having to create custom copy-constructor, ESM::Position mPosition;
// assignment operator and destructor. As a consequence though copying a RefData object
// manually will probably give unexcepted results. This is not a problem since RefData
// are never copied outside of container operations.
boost::shared_ptr<MWMechanics::CreatureStats> mCreatureStats;
boost::shared_ptr<MWMechanics::NpcStats> mNpcStats;
boost::shared_ptr<MWMechanics::Movement> mMovement;
boost::shared_ptr<ContainerStore<RefData> > mContainerStore; CustomData *mCustomData;
ESM::Position mPosition; void copy (const RefData& refData);
void cleanup();
public: public:
/// @param cr Used to copy constant data such as position into this class where it can
/// be altered without effecting the original data. This makes it possible /// @param cellRef Used to copy constant data such as position into this class where it can
/// to reset the position as the orignal data is still held in the CellRef /// be altered without effecting the original data. This makes it possible
RefData(const ESMS::CellRef& cr) : mBaseNode(0), mHasLocals (false), mEnabled (true), /// to reset the position as the orignal data is still held in the CellRef
mCount (1), mPosition(cr.pos) {} RefData (const ESM::CellRef& cellRef);
RefData (const RefData& refData);
std::string getHandle()
{ ~RefData();
return mBaseNode->getName();
} RefData& operator= (const RefData& refData);
Ogre::SceneNode* getBaseNode(){
return mBaseNode; /// Return OGRE handle (may be empty).
} std::string getHandle();
void setBaseNode(Ogre::SceneNode* base){
mBaseNode = base; /// Return OGRE base node (can be a null pointer).
} Ogre::SceneNode* getBaseNode();
int getCount() const /// Set OGRE base node (can be a null pointer).
{ void setBaseNode (Ogre::SceneNode* base);
return mCount;
} int getCount() const;
void setLocals (const ESM::Script& script) void setLocals (const ESM::Script& script);
{
if (!mHasLocals) void setCount (int count);
{
mLocals.configure (script); MWScript::Locals& getLocals();
mHasLocals = true;
} bool isEnabled() const;
}
void enable();
void setCount (int count) void disable();
{
mCount = count; ESM::Position& getPosition();
}
void setCustomData (CustomData *data);
MWScript::Locals& getLocals() ///< Set custom data (potentially replacing old custom data). The ownership of \æ data is
{ /// transferred to this.
return mLocals;
} CustomData *getCustomData();
///< May return a 0-pointer. The ownership of the return data object is not transferred.
bool isEnabled() const
{
return mEnabled;
}
void enable()
{
mEnabled = true;
}
void disable()
{
mEnabled = true;
}
boost::shared_ptr<MWMechanics::CreatureStats>& getCreatureStats()
{
return mCreatureStats;
}
boost::shared_ptr<MWMechanics::NpcStats>& getNpcStats()
{
return mNpcStats;
}
boost::shared_ptr<MWMechanics::Movement>& getMovement()
{
return mMovement;
}
boost::shared_ptr<ContainerStore<RefData> >& getContainerStore()
{
return mContainerStore;
}
ESM::Position& getPosition()
{
return mPosition;
}
}; };
} }

@ -236,6 +236,9 @@ namespace MWWorld
mCurrentCell = cell; mCurrentCell = cell;
playerCellChange (cell, position); playerCellChange (cell, position);
// adjust fog
mRendering.configureFog(*cell);
// Sky system // Sky system
mWorld->adjustSky(); mWorld->adjustSky();

@ -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

@ -13,15 +13,20 @@
#include "../mwsound/soundmanager.hpp" #include "../mwsound/soundmanager.hpp"
#include "ptr.hpp" #include "ptr.hpp"
#include "environment.hpp" #include "environment.hpp"
#include "class.hpp" #include "class.hpp"
#include "player.hpp" #include "player.hpp"
#include "weather.hpp"
#include "refdata.hpp" #include "refdata.hpp"
#include "globals.hpp" #include "globals.hpp"
#include "cellfunctors.hpp" #include "cellfunctors.hpp"
#include <OgreVector3.h>
using namespace Ogre;
namespace namespace
{ {
template<typename T> template<typename T>
@ -135,24 +140,31 @@ namespace MWWorld
void World::adjustSky() void World::adjustSky()
{ {
if (mSky) if (mSky && (isCellExterior() || isCellQuasiExterior()))
{ {
toggleSky(); mRendering->skySetHour (mGlobalVariables->getFloat ("gamehour"));
// TODO set weather mRendering->skySetDate (mGlobalVariables->getInt ("day"),
toggleSky(); mGlobalVariables->getInt ("month"));
mRendering->getSkyManager()->enable();
} }
else
mRendering->getSkyManager()->disable();
} }
World::World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, World::World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment, const std::string& encoding) bool newGame, Environment& environment, const std::string& encoding)
: mRendering (renderer,resDir, physEng, environment),mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (false), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this) mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this)
{ {
mPhysEngine = physEng; mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine();
mRendering = new MWRender::RenderingManager(renderer, resDir, mPhysEngine, environment);
mPhysics = new PhysicsSystem(renderer, physEng); mWeatherManager = new MWWorld::WeatherManager(mRendering, &environment);
boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master));
@ -163,7 +175,7 @@ namespace MWWorld
mEsm.open (masterPath.string()); mEsm.open (masterPath.string());
mStore.load (mEsm); mStore.load (mEsm);
MWRender::Player* play = &(mRendering.getPlayer()); MWRender::Player* play = &(mRendering->getPlayer());
mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this); mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this);
mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0));
@ -176,18 +188,17 @@ namespace MWWorld
mGlobalVariables->setInt ("chargenstate", 1); mGlobalVariables->setInt ("chargenstate", 1);
} }
mPhysEngine = physEng; mWorldScene = new Scene(environment, this, *mRendering, mPhysics);
mWorldScene = new Scene(environment, this, mRendering, mPhysics);
} }
World::~World() World::~World()
{ {
delete mWeatherManager;
delete mWorldScene; delete mWorldScene;
delete mGlobalVariables; delete mGlobalVariables;
delete mRendering;
delete mPhysics; delete mPhysics;
delete mPlayer; delete mPlayer;
@ -369,7 +380,9 @@ namespace MWWorld
mGlobalVariables->setFloat ("gamehour", hour); mGlobalVariables->setFloat ("gamehour", hour);
mRendering.skySetHour (hour); mRendering->skySetHour (hour);
mWeatherManager->setHour (hour);
if (days>0) if (days>0)
setDay (days + mGlobalVariables->getInt ("day")); setDay (days + mGlobalVariables->getInt ("day"));
@ -404,7 +417,11 @@ namespace MWWorld
mGlobalVariables->setInt ("day", day); mGlobalVariables->setInt ("day", day);
mGlobalVariables->setInt ("month", month); mGlobalVariables->setInt ("month", month);
mRendering.skySetDate (day, month); mRendering->skySetDate (day, month);
mWeatherManager->setDate (day, month);
} }
void World::setMonth (int month) void World::setMonth (int month)
@ -425,7 +442,7 @@ namespace MWWorld
if (years>0) if (years>0)
mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year")); mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year"));
mRendering.skySetDate (mGlobalVariables->getInt ("day"), month); mRendering->skySetDate (mGlobalVariables->getInt ("day"), month);
} }
bool World::toggleSky() bool World::toggleSky()
@ -433,34 +450,30 @@ namespace MWWorld
if (mSky) if (mSky)
{ {
mSky = false; mSky = false;
mRendering.skyDisable(); mRendering->skyDisable();
return false; return false;
} }
else else
{ {
mSky = true; mSky = true;
// TODO check for extorior or interior with sky. mRendering->skyEnable();
mRendering.skySetHour (mGlobalVariables->getFloat ("gamehour"));
mRendering.skySetDate (mGlobalVariables->getInt ("day"),
mGlobalVariables->getInt ("month"));
mRendering.skyEnable();
return true; return true;
} }
} }
int World::getMasserPhase() const int World::getMasserPhase() const
{ {
return mRendering.skyGetMasserPhase(); return mRendering->skyGetMasserPhase();
} }
int World::getSecundaPhase() const int World::getSecundaPhase() const
{ {
return mRendering.skyGetSecundaPhase(); return mRendering->skyGetSecundaPhase();
} }
void World::setMoonColour (bool red) void World::setMoonColour (bool red)
{ {
mRendering.skySetMoonColour (red); mRendering->skySetMoonColour (red);
} }
float World::getTimeScaleFactor() const float World::getTimeScaleFactor() const
@ -506,7 +519,7 @@ namespace MWWorld
mEnvironment.mSoundManager->stopSound3D (ptr); mEnvironment.mSoundManager->stopSound3D (ptr);
mPhysics->removeObject (ptr.getRefData().getHandle()); mPhysics->removeObject (ptr.getRefData().getHandle());
mRendering.removeObject(ptr); mRendering->removeObject(ptr);
mLocalScripts.remove (ptr); mLocalScripts.remove (ptr);
} }
@ -543,7 +556,7 @@ namespace MWWorld
/// \todo cell change for non-player ref /// \todo cell change for non-player ref
mRendering.moveObject (ptr, Ogre::Vector3 (x, y, z)); mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z));
} }
void World::moveObject (Ptr ptr, float x, float y, float z) void World::moveObject (Ptr ptr, float x, float y, float z)
@ -617,7 +630,7 @@ namespace MWWorld
bool World::toggleRenderMode (RenderMode mode) bool World::toggleRenderMode (RenderMode mode)
{ {
return mRendering.toggleRenderMode (mode); return mRendering->toggleRenderMode (mode);
} }
std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record) std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
@ -678,16 +691,67 @@ namespace MWWorld
void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
int number) int number)
{ {
mRendering.playAnimationGroup (ptr, groupName, mode, number); mRendering->playAnimationGroup (ptr, groupName, mode, number);
} }
void World::skipAnimation (const MWWorld::Ptr& ptr) void World::skipAnimation (const MWWorld::Ptr& ptr)
{ {
mRendering.skipAnimation (ptr); mRendering->skipAnimation (ptr);
} }
void World::update (float duration) void World::update (float duration)
{ {
mWorldScene->update (duration); mWorldScene->update (duration);
mWeatherManager->update (duration);
// cast a ray from player to sun to detect if the sun is visible
// this is temporary until we find a better place to put this code
// currently its here because we need to access the physics system
float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
Vector3 sun = mRendering->getSkyManager()->getRealSunPos();
sun = Vector3(sun.x, -sun.z, sun.y);
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
}
bool World::isCellExterior() const
{
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
if (currentCell)
{
if (!(currentCell->cell->data.flags & ESM::Cell::Interior))
return true;
else
return false;
}
return false;
}
bool World::isCellQuasiExterior() const
{
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
if (currentCell)
{
if (!(currentCell->cell->data.flags & ESM::Cell::QuasiEx))
return false;
else
return true;
}
return false;
}
int World::getCurrentWeather() const
{
return mWeatherManager->getWeatherID();
}
void World::changeWeather(const std::string& region, const unsigned int id)
{
mWeatherManager->changeWeather(region, id);
}
OEngine::Render::Fader* World::getFader()
{
return mRendering->getFader();
} }
} }

@ -20,6 +20,7 @@
#include "localscripts.hpp" #include "localscripts.hpp"
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <openengine/ogre/fader.hpp>
namespace Ogre namespace Ogre
{ {
@ -49,6 +50,7 @@ namespace MWRender
namespace MWWorld namespace MWWorld
{ {
class WeatherManager;
class Environment; class Environment;
class Player; class Player;
@ -60,12 +62,15 @@ namespace MWWorld
enum RenderMode enum RenderMode
{ {
Render_CollisionDebug Render_CollisionDebug,
Render_Wireframe
}; };
private: private:
MWRender::RenderingManager mRendering; MWRender::RenderingManager* mRendering;
MWWorld::WeatherManager* mWeatherManager;
MWWorld::Scene *mWorldScene; MWWorld::Scene *mWorldScene;
MWWorld::Player *mPlayer; MWWorld::Player *mPlayer;
@ -95,13 +100,15 @@ namespace MWWorld
public: public:
World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment, const std::string& encoding); Environment& environment, const std::string& encoding);
~World(); ~World();
OEngine::Render::Fader* getFader();
Ptr::CellStore *getExterior (int x, int y); Ptr::CellStore *getExterior (int x, int y);
Ptr::CellStore *getInterior (const std::string& name); Ptr::CellStore *getInterior (const std::string& name);
@ -119,6 +126,9 @@ namespace MWWorld
bool hasCellChanged() const; bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame? ///< Has the player moved to a different cell, since the last frame?
bool isCellExterior() const;
bool isCellQuasiExterior() const;
Globals::Data& getGlobalVariable (const std::string& name); Globals::Data& getGlobalVariable (const std::string& name);
Globals::Data getGlobalVariable (const std::string& name) const; Globals::Data getGlobalVariable (const std::string& name) const;
@ -154,6 +164,10 @@ namespace MWWorld
bool toggleSky(); bool toggleSky();
///< \return Resulting mode ///< \return Resulting mode
void changeWeather(const std::string& region, const unsigned int id);
int getCurrentWeather() const;
int getMasserPhase() const; int getMasserPhase() const;
int getSecundaPhase() const; int getSecundaPhase() const;

@ -1,115 +1,542 @@
# Find OGRE includes and library #-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/
# #
# This module defines # The contents of this file are placed in the public domain. Feel
# OGRE_INCLUDE_DIR # free to make use of it in any way you like.
# OGRE_LIBRARIES, the libraries to link against to use OGRE. #-------------------------------------------------------------------
# OGRE_LIB_DIR, the location of the libraries
# OGRE_FOUND, If false, do not try to use OGRE # - Try to find OGRE
# If you have multiple versions of Ogre installed, use the CMake or
# the environment variable OGRE_HOME to point to the path where the
# desired Ogre version can be found.
# By default this script will look for a dynamic Ogre build. If you
# need to link against static Ogre libraries, set the CMake variable
# OGRE_STATIC to TRUE.
#
# Once done, this will define
#
# OGRE_FOUND - system has OGRE
# OGRE_INCLUDE_DIRS - the OGRE include directories
# OGRE_LIBRARIES - link these to use the OGRE core
# OGRE_BINARY_REL - location of the main Ogre binary (win32 non-static only, release)
# OGRE_BINARY_DBG - location of the main Ogre binaries (win32 non-static only, debug)
#
# Additionally this script searches for the following optional
# parts of the Ogre package:
# Plugin_BSPSceneManager, Plugin_CgProgramManager,
# Plugin_OctreeSceneManager, Plugin_OctreeZone,
# Plugin_ParticleFX, Plugin_PCZSceneManager,
# RenderSystem_GL, RenderSystem_Direct3D9,
# Paging, Terrain
# #
# Copyright © 2007, Matt Williams # For each of these components, the following variables are defined:
# #
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. # OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available
CMAKE_POLICY(PUSH) # OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT}
# OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT}
IF (OGRE_LIBRARIES AND OGRE_INCLUDE_DIR AND OGRE_LIB_DIR AND OGRE_PLUGIN_DIR) # OGRE_${COMPONENT}_BINARY_REL - location of the component binary (win32 non-static only, release)
SET(OGRE_FIND_QUIETLY TRUE) # Already in cache, be silent # OGRE_${COMPONENT}_BINARY_DBG - location of the component binary (win32 non-static only, debug)
ENDIF (OGRE_LIBRARIES AND OGRE_INCLUDE_DIR AND OGRE_LIB_DIR AND OGRE_PLUGIN_DIR) #
# Finally, the following variables are defined:
IF (WIN32) #Windows #
MESSAGE(STATUS "Looking for OGRE") # OGRE_PLUGIN_DIR_REL - The directory where the release versions of
SET(OGRESDK $ENV{OGRE_HOME}) # the OGRE plugins are located
SET(OGRESOURCE $ENV{OGRE_SRC}) # OGRE_PLUGIN_DIR_DBG - The directory where the debug versions of
IF (OGRESDK) # the OGRE plugins are located
MESSAGE(STATUS "Using OGRE SDK") # OGRE_MEDIA_DIR - The directory where the OGRE sample media is
STRING(REGEX REPLACE "[\\]" "/" OGRESDK "${OGRESDK}") # located, if available
SET(OGRE_INCLUDE_DIR ${OGRESDK}/include)
SET(OGRE_LIB_DIR ${OGRESDK}/lib) include(FindPkgMacros)
SET(OGRE_LIBRARIES debug OgreMain_d optimized OgreMain) include(PreprocessorUtils)
ELSEIF (OGRESOURCE) findpkg_begin(OGRE)
MESSAGE(STATUS "Using OGRE built from source")
SET(OGRE_INCLUDE_DIR $ENV{OGRE_SRC}/OgreMain/include)
SET(OGRE_LIB_DIR $ENV{OGRE_SRC}/lib) # Get path, convert backslashes as ${ENV_${var}}
SET(OGRE_LIBRARIES debug OgreMain_d optimized OgreMain) getenv_path(OGRE_HOME)
ELSE (OGRESDK) getenv_path(OGRE_SDK)
MESSAGE(STATUS "Using OGRE paths from CMake") getenv_path(OGRE_SOURCE)
SET(OGRE_LIBRARIES debug OgreMain_d optimized OgreMain) getenv_path(OGRE_BUILD)
ENDIF (OGRESDK) getenv_path(OGRE_DEPENDENCIES_DIR)
ENDIF (WIN32) getenv_path(PROGRAMFILES)
IF (UNIX AND NOT APPLE) # Determine whether to search for a dynamic or static build
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) if (OGRE_STATIC)
FIND_PACKAGE(PkgConfig REQUIRED) set(OGRE_LIB_SUFFIX "Static")
# Don't mark REQUIRED, but use PKG_CHECK_MODULES below (otherwise PkgConfig else ()
# complains even if OGRE_* are set by hand). set(OGRE_LIB_SUFFIX "")
PKG_SEARCH_MODULE(OGRE OGRE) endif ()
SET(OGRE_INCLUDE_DIR ${OGRE_INCLUDE_DIRS})
SET(OGRE_LIB_DIR ${OGRE_LIBDIR})
SET(OGRE_LIBRARIES ${OGRE_LIBRARIES} CACHE STRING "") set(OGRE_LIBRARY_NAMES "OgreMain${OGRE_LIB_SUFFIX}")
PKG_CHECK_MODULES(OGRE OGRE) get_debug_names(OGRE_LIBRARY_NAMES)
ENDIF (UNIX AND NOT APPLE)
# construct search paths from environmental hints and
# on OS X we need Ogre SDK because framework doesn't include all libs, just Ogre Main lib # OS specific guesses
IF (APPLE) if (WIN32)
IF (OGRESDK) set(OGRE_PREFIX_GUESSES
MESSAGE(STATUS "Using Ogre SDK") ${ENV_PROGRAMFILES}/OGRE
SET(OGRE_LIB_DIR ${OGRESDK}/lib) C:/OgreSDK
ELSE (OGRESDK) )
MESSAGE(FATAL_ERROR "Path to Ogre SDK not specified. Specify OGRESDK.") elseif (UNIX)
ENDIF (OGRESDK) set(OGRE_PREFIX_GUESSES
/opt/ogre
/opt/OGRE
FIND_PATH(OGRE_INCLUDE_DIR Ogre.h /usr/lib${LIB_SUFFIX}/ogre
PATHS /usr/lib${LIB_SUFFIX}/OGRE
/Library/Frameworks /usr/local/lib${LIB_SUFFIX}/ogre
/opt/local /usr/local/lib${LIB_SUFFIX}/OGRE
) $ENV{HOME}/ogre
FIND_LIBRARY(OGRE_LIBRARIES $ENV{HOME}/OGRE
NAMES Ogre )
PATHS endif ()
/Library/Frameworks set(OGRE_PREFIX_PATH
/opt/local ${OGRE_HOME} ${OGRE_SDK} ${ENV_OGRE_HOME} ${ENV_OGRE_SDK}
) ${OGRE_PREFIX_GUESSES}
ENDIF (APPLE) )
create_search_paths(OGRE)
#Do some preparation # If both OGRE_BUILD and OGRE_SOURCE are set, prepare to find Ogre in a build dir
SEPARATE_ARGUMENTS(OGRE_INCLUDE_DIR) set(OGRE_PREFIX_SOURCE ${OGRE_SOURCE} ${ENV_OGRE_SOURCE})
SEPARATE_ARGUMENTS(OGRE_LIBRARIES) set(OGRE_PREFIX_BUILD ${OGRE_BUILD} ${ENV_OGRE_BUILD})
set(OGRE_PREFIX_DEPENDENCIES_DIR ${OGRE_DEPENDENCIES_DIR} ${ENV_OGRE_DEPENDENCIES_DIR})
SET(OGRE_INCLUDE_DIR ${OGRE_INCLUDE_DIR} CACHE PATH "") if (OGRE_PREFIX_SOURCE AND OGRE_PREFIX_BUILD)
SET(OGRE_LIBRARIES ${OGRE_LIBRARIES} CACHE STRING "") foreach(dir ${OGRE_PREFIX_SOURCE})
SET(OGRE_LIB_DIR ${OGRE_LIB_DIR} CACHE PATH "") set(OGRE_INC_SEARCH_PATH ${dir}/OgreMain/include ${dir}/Dependencies/include ${dir}/iPhoneDependencies/include ${OGRE_INC_SEARCH_PATH})
set(OGRE_LIB_SEARCH_PATH ${dir}/lib ${dir}/Dependencies/lib ${dir}/iPhoneDependencies/lib ${OGRE_LIB_SEARCH_PATH})
if(OGRE_LIB_DIR) set(OGRE_BIN_SEARCH_PATH ${dir}/Samples/Common/bin ${OGRE_BIN_SEARCH_PATH})
CMAKE_POLICY(SET CMP0009 NEW) endforeach(dir)
IF (WIN32) foreach(dir ${OGRE_PREFIX_BUILD})
FILE(GLOB_RECURSE OGRE_PLUGINS "${OGRE_LIB_DIR}/Plugin_*.lib") set(OGRE_INC_SEARCH_PATH ${dir}/include ${OGRE_INC_SEARCH_PATH})
ENDIF (WIN32) set(OGRE_LIB_SEARCH_PATH ${dir}/lib ${OGRE_LIB_SEARCH_PATH})
IF (NOT APPLE AND NOT WIN32) set(OGRE_BIN_SEARCH_PATH ${dir}/bin ${OGRE_BIN_SEARCH_PATH})
FILE(GLOB_RECURSE OGRE_PLUGINS "${OGRE_LIB_DIR}/Plugin_*.so") set(OGRE_BIN_SEARCH_PATH ${dir}/Samples/Common/bin ${OGRE_BIN_SEARCH_PATH})
ENDIF (NOT APPLE AND NOT WIN32) endforeach(dir)
IF (APPLE)
FILE(GLOB_RECURSE OGRE_PLUGINS "${OGRE_LIB_DIR}/Plugin_*.dylib") if (OGRE_PREFIX_DEPENDENCIES_DIR)
ENDIF (APPLE) set(OGRE_INC_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/include ${OGRE_INC_SEARCH_PATH})
FOREACH (OGRE_PLUGINS_FILE ${OGRE_PLUGINS}) set(OGRE_LIB_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/lib ${OGRE_LIB_SEARCH_PATH})
STRING(REGEX REPLACE "/[^/]*$" "" OGRE_PLUGIN_DIR ${OGRE_PLUGINS_FILE}) set(OGRE_BIN_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/bin ${OGRE_BIN_SEARCH_PATH})
ENDFOREACH(OGRE_PLUGINS_FILE) endif()
else()
set(OGRE_PREFIX_SOURCE "NOTFOUND")
set(OGRE_PREFIX_BUILD "NOTFOUND")
endif ()
# redo search if any of the environmental hints changed
set(OGRE_COMPONENTS Paging Terrain
Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager
Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX
RenderSystem_Direct3D11 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES RenderSystem_GLES2)
set(OGRE_RESET_VARS
OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR
OGRE_LIBRARY_FWK OGRE_LIBRARY_REL OGRE_LIBRARY_DBG
OGRE_PLUGIN_DIR_DBG OGRE_PLUGIN_DIR_REL OGRE_MEDIA_DIR)
foreach (comp ${OGRE_COMPONENTS})
set(OGRE_RESET_VARS ${OGRE_RESET_VARS}
OGRE_${comp}_INCLUDE_DIR OGRE_${comp}_LIBRARY_FWK
OGRE_${comp}_LIBRARY_DBG OGRE_${comp}_LIBRARY_REL
)
endforeach (comp)
set(OGRE_PREFIX_WATCH ${OGRE_PREFIX_PATH} ${OGRE_PREFIX_SOURCE} ${OGRE_PREFIX_BUILD})
clear_if_changed(OGRE_PREFIX_WATCH ${OGRE_RESET_VARS})
# try to locate Ogre via pkg-config
use_pkgconfig(OGRE_PKGC "OGRE${OGRE_LIB_SUFFIX}")
if(NOT OGRE_BUILD_PLATFORM_APPLE_IOS)
# try to find framework on OSX
findpkg_framework(OGRE)
else()
set(OGRE_LIBRARY_FWK "")
endif()
# locate Ogre include files
find_path(OGRE_CONFIG_INCLUDE_DIR NAMES OgreBuildSettings.h HINTS ${OGRE_INC_SEARCH_PATH} ${OGRE_FRAMEWORK_INCLUDES} ${OGRE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES "OGRE")
find_path(OGRE_INCLUDE_DIR NAMES OgreRoot.h HINTS ${OGRE_CONFIG_INCLUDE_DIR} ${OGRE_INC_SEARCH_PATH} ${OGRE_FRAMEWORK_INCLUDES} ${OGRE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES "OGRE")
set(OGRE_INCOMPATIBLE FALSE)
if (OGRE_INCLUDE_DIR)
if (NOT OGRE_CONFIG_INCLUDE_DIR)
set(OGRE_CONFIG_INCLUDE_DIR ${OGRE_INCLUDE_DIR})
endif ()
# determine Ogre version
file(READ ${OGRE_INCLUDE_DIR}/OgrePrerequisites.h OGRE_TEMP_VERSION_CONTENT)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MAJOR OGRE_VERSION_MAJOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_MINOR OGRE_VERSION_MINOR)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_PATCH OGRE_VERSION_PATCH)
get_preprocessor_entry(OGRE_TEMP_VERSION_CONTENT OGRE_VERSION_NAME OGRE_VERSION_NAME)
set(OGRE_VERSION "${OGRE_VERSION_MAJOR}.${OGRE_VERSION_MINOR}.${OGRE_VERSION_PATCH}")
pkg_message(OGRE "Found Ogre ${OGRE_VERSION_NAME} (${OGRE_VERSION})")
# determine configuration settings
set(OGRE_CONFIG_HEADERS
${OGRE_CONFIG_INCLUDE_DIR}/OgreBuildSettings.h
${OGRE_CONFIG_INCLUDE_DIR}/OgreConfig.h
)
foreach(CFG_FILE ${OGRE_CONFIG_HEADERS})
if (EXISTS ${CFG_FILE})
set(OGRE_CONFIG_HEADER ${CFG_FILE})
break()
endif()
endforeach()
if (OGRE_CONFIG_HEADER)
file(READ ${OGRE_CONFIG_HEADER} OGRE_TEMP_CONFIG_CONTENT)
has_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_STATIC_LIB OGRE_CONFIG_STATIC)
get_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_THREAD_SUPPORT OGRE_CONFIG_THREADS)
get_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_THREAD_PROVIDER OGRE_CONFIG_THREAD_PROVIDER)
get_preprocessor_entry(OGRE_TEMP_CONFIG_CONTENT OGRE_NO_FREEIMAGE OGRE_CONFIG_FREEIMAGE)
if (OGRE_CONFIG_STATIC AND OGRE_STATIC)
elseif (OGRE_CONFIG_STATIC OR OGRE_STATIC)
pkg_message(OGRE "Build type (static, dynamic) does not match the requested one.")
set(OGRE_INCOMPATIBLE TRUE)
endif ()
else ()
pkg_message(OGRE "Could not determine Ogre build configuration.")
set(OGRE_INCOMPATIBLE TRUE)
endif ()
else ()
set(OGRE_INCOMPATIBLE FALSE)
endif ()
find_library(OGRE_LIBRARY_REL NAMES ${OGRE_LIBRARY_NAMES} HINTS ${OGRE_LIB_SEARCH_PATH} ${OGRE_PKGC_LIBRARY_DIRS} ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel")
find_library(OGRE_LIBRARY_DBG NAMES ${OGRE_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIB_SEARCH_PATH} ${OGRE_PKGC_LIBRARY_DIRS} ${OGRE_FRAMEWORK_SEARCH_PATH} PATH_SUFFIXES "" "debug")
make_library_set(OGRE_LIBRARY)
if(APPLE)
set(OGRE_LIBRARY_DBG ${OGRE_LIB_SEARCH_PATH})
endif() endif()
if (OGRE_INCOMPATIBLE)
set(OGRE_LIBRARY "NOTFOUND")
endif ()
set(OGRE_INCLUDE_DIR ${OGRE_CONFIG_INCLUDE_DIR} ${OGRE_INCLUDE_DIR})
list(REMOVE_DUPLICATES OGRE_INCLUDE_DIR)
findpkg_finish(OGRE)
add_parent_dir(OGRE_INCLUDE_DIRS OGRE_INCLUDE_DIR)
if (OGRE_SOURCE)
# If working from source rather than SDK, add samples include
set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} "${OGRE_SOURCE}/Samples/Common/include")
endif()
mark_as_advanced(OGRE_CONFIG_INCLUDE_DIR OGRE_MEDIA_DIR OGRE_PLUGIN_DIR_REL OGRE_PLUGIN_DIR_DBG)
if (NOT OGRE_FOUND)
return()
endif ()
# look for required Ogre dependencies in case of static build and/or threading
if (OGRE_STATIC)
set(OGRE_DEPS_FOUND TRUE)
find_package(Cg QUIET)
find_package(DirectX QUIET)
find_package(FreeImage QUIET)
find_package(Freetype QUIET)
find_package(OpenGL QUIET)
find_package(OpenGLES QUIET)
find_package(OpenGLES2 QUIET)
find_package(ZLIB QUIET)
find_package(ZZip QUIET)
if (UNIX AND NOT APPLE)
find_package(X11 QUIET)
find_library(XAW_LIBRARY NAMES Xaw Xaw7 PATHS ${DEP_LIB_SEARCH_DIR} ${X11_LIB_SEARCH_PATH})
if (NOT XAW_LIBRARY OR NOT X11_Xt_FOUND)
set(X11_FOUND FALSE)
endif ()
endif ()
if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS)
find_package(Cocoa QUIET)
find_package(Carbon QUIET)
find_package(CoreVideo QUIET)
if (NOT Cocoa_FOUND OR NOT Carbon_FOUND OR NOT CoreVideo_FOUND)
set(OGRE_DEPS_FOUND FALSE)
endif ()
endif ()
if (APPLE AND OGRE_BUILD_PLATFORM_APPLE_IOS)
find_package(iPhoneSDK QUIET)
if (NOT iPhoneSDK_FOUND)
set(OGRE_DEPS_FOUND FALSE)
endif ()
endif ()
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} )
if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS)
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB} ${Carbon_LIBRARIES} ${Cocoa_LIBRARIES})
endif()
if (NOT ZLIB_FOUND OR NOT ZZip_FOUND)
set(OGRE_DEPS_FOUND FALSE)
endif ()
if (NOT FreeImage_FOUND AND NOT OGRE_CONFIG_FREEIMAGE)
set(OGRE_DEPS_FOUND FALSE)
endif ()
if (NOT FREETYPE_FOUND)
set(OGRE_DEPS_FOUND FALSE)
endif ()
if (UNIX AND NOT APPLE)
if (NOT X11_FOUND)
set(OGRE_DEPS_FOUND FALSE)
endif ()
endif ()
if (OGRE_CONFIG_THREADS)
if (OGRE_CONFIG_THREAD_PROVIDER EQUAL 1)
find_package(Boost COMPONENTS thread QUIET)
if (NOT Boost_THREAD_FOUND)
set(OGRE_DEPS_FOUND FALSE)
else ()
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${Boost_LIBRARIES})
set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
endif ()
elseif (OGRE_CONFIG_THREAD_PROVIDER EQUAL 2)
find_package(POCO QUIET)
if (NOT POCO_FOUND)
set(OGRE_DEPS_FOUND FALSE)
else ()
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${POCO_LIBRARIES})
set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} ${POCO_INCLUDE_DIRS})
endif ()
elseif (OGRE_CONFIG_THREAD_PROVIDER EQUAL 3)
find_package(TBB QUIET)
if (NOT TBB_FOUND)
set(OGRE_DEPS_FOUND FALSE)
else ()
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${TBB_LIBRARIES})
set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS})
endif ()
endif ()
endif ()
if (NOT OGRE_DEPS_FOUND)
pkg_message(OGRE "Could not find all required dependencies for the Ogre package.")
set(OGRE_FOUND FALSE)
endif ()
endif ()
if (NOT OGRE_FOUND)
return()
endif ()
get_filename_component(OGRE_LIBRARY_DIR_REL "${OGRE_LIBRARY_REL}" PATH)
get_filename_component(OGRE_LIBRARY_DIR_DBG "${OGRE_LIBRARY_DBG}" PATH)
set(OGRE_LIBRARY_DIRS ${OGRE_LIBRARY_DIR_REL} ${OGRE_LIBRARY_DIR_DBG})
# find binaries
if (NOT OGRE_STATIC)
if (WIN32)
find_file(OGRE_BINARY_REL NAMES "OgreMain.dll" HINTS ${OGRE_BIN_SEARCH_PATH}
PATH_SUFFIXES "" release relwithdebinfo minsizerel)
find_file(OGRE_BINARY_DBG NAMES "OgreMain_d.dll" HINTS ${OGRE_BIN_SEARCH_PATH}
PATH_SUFFIXES "" debug )
endif()
mark_as_advanced(OGRE_BINARY_REL OGRE_BINARY_DBG)
endif()
#########################################################
# Find Ogre components
#########################################################
set(OGRE_COMPONENT_SEARCH_PATH_REL
${OGRE_LIBRARY_DIR_REL}/..
${OGRE_LIBRARY_DIR_REL}/../..
${OGRE_BIN_SEARCH_PATH}
)
set(OGRE_COMPONENT_SEARCH_PATH_DBG
${OGRE_LIBRARY_DIR_DBG}/..
${OGRE_LIBRARY_DIR_DBG}/../..
${OGRE_BIN_SEARCH_PATH}
)
macro(ogre_find_component COMPONENT HEADER)
findpkg_begin(OGRE_${COMPONENT})
find_path(OGRE_${COMPONENT}_INCLUDE_DIR NAMES ${HEADER} HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES ${COMPONENT} OGRE/${COMPONENT} Components/${COMPONENT}/include)
set(OGRE_${COMPONENT}_LIBRARY_NAMES "Ogre${COMPONENT}${OGRE_LIB_SUFFIX}")
get_debug_names(OGRE_${COMPONENT}_LIBRARY_NAMES)
find_library(OGRE_${COMPONENT}_LIBRARY_REL NAMES ${OGRE_${COMPONENT}_LIBRARY_NAMES} HINTS ${OGRE_LIBRARY_DIR_REL} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel")
find_library(OGRE_${COMPONENT}_LIBRARY_DBG NAMES ${OGRE_${COMPONENT}_LIBRARY_NAMES_DBG} HINTS ${OGRE_LIBRARY_DIR_DBG} PATH_SUFFIXES "" "debug")
make_library_set(OGRE_${COMPONENT}_LIBRARY)
findpkg_finish(OGRE_${COMPONENT})
if (OGRE_${COMPONENT}_FOUND)
# find binaries
if (NOT OGRE_STATIC)
if (WIN32)
find_file(OGRE_${COMPONENT}_BINARY_REL NAMES "Ogre${COMPONENT}.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_REL} PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel release)
find_file(OGRE_${COMPONENT}_BINARY_DBG NAMES "Ogre${COMPONENT}_d.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_DBG} PATH_SUFFIXES "" bin bin/debug debug)
endif()
mark_as_advanced(OGRE_${COMPONENT}_BINARY_REL OGRE_${COMPONENT}_BINARY_DBG)
endif()
endif()
endmacro()
# look for Paging component
ogre_find_component(Paging OgrePaging.h)
# look for Terrain component
ogre_find_component(Terrain OgreTerrain.h)
# look for Property component
ogre_find_component(Property OgreProperty.h)
# look for RTShaderSystem component
ogre_find_component(RTShaderSystem OgreRTShaderSystem.h)
#########################################################
# Find Ogre plugins
#########################################################
macro(ogre_find_plugin PLUGIN HEADER)
# On Unix, the plugins might have no prefix
if (CMAKE_FIND_LIBRARY_PREFIXES)
set(TMP_CMAKE_LIB_PREFIX ${CMAKE_FIND_LIBRARY_PREFIXES})
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "")
endif()
# strip RenderSystem_ or Plugin_ prefix from plugin name
string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN})
string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP})
# header files for plugins are not usually needed, but find them anyway if they are present
set(OGRE_PLUGIN_PATH_SUFFIXES
PlugIns PlugIns/${PLUGIN_NAME} Plugins Plugins/${PLUGIN_NAME} ${PLUGIN}
RenderSystems RenderSystems/${PLUGIN_NAME} ${ARGN})
find_path(OGRE_${PLUGIN}_INCLUDE_DIR NAMES ${HEADER}
HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE}
PATH_SUFFIXES ${OGRE_PLUGIN_PATH_SUFFIXES})
# find link libraries for plugins
set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}")
get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES)
set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK})
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt)
make_library_set(OGRE_${PLUGIN}_LIBRARY)
if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR)
set(OGRE_${PLUGIN}_FOUND TRUE)
if (OGRE_${PLUGIN}_INCLUDE_DIR)
set(OGRE_${PLUGIN}_INCLUDE_DIRS ${OGRE_${PLUGIN}_INCLUDE_DIR})
endif()
set(OGRE_${PLUGIN}_LIBRARIES ${OGRE_${PLUGIN}_LIBRARY})
endif ()
mark_as_advanced(OGRE_${PLUGIN}_INCLUDE_DIR OGRE_${PLUGIN}_LIBRARY_REL OGRE_${PLUGIN}_LIBRARY_DBG OGRE_${PLUGIN}_LIBRARY_FWK)
# look for plugin dirs
if (OGRE_${PLUGIN}_FOUND)
if (NOT OGRE_PLUGIN_DIR_REL OR NOT OGRE_PLUGIN_DIR_DBG)
if (WIN32)
set(OGRE_PLUGIN_SEARCH_PATH_REL
${OGRE_LIBRARY_DIR_REL}/..
${OGRE_LIBRARY_DIR_REL}/../..
${OGRE_BIN_SEARCH_PATH}
)
set(OGRE_PLUGIN_SEARCH_PATH_DBG
${OGRE_LIBRARY_DIR_DBG}/..
${OGRE_LIBRARY_DIR_DBG}/../..
${OGRE_BIN_SEARCH_PATH}
)
find_path(OGRE_PLUGIN_DIR_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_SEARCH_PATH_REL}
PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel release)
find_path(OGRE_PLUGIN_DIR_DBG NAMES "${PLUGIN}_d.dll" HINTS ${OGRE_PLUGIN_SEARCH_PATH_DBG}
PATH_SUFFIXES "" bin bin/debug debug)
elseif (UNIX)
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH)
set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)" FORCE)
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH)
set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)" FORCE)
endif ()
endif ()
# find binaries
if (NOT OGRE_STATIC)
if (WIN32)
find_file(OGRE_${PLUGIN}_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_DIR_REL})
find_file(OGRE_${PLUGIN}_DBG NAMES "${PLUGIN}_d.dll" HINTS ${OGRE_PLUGIN_DIR_DBG})
endif()
mark_as_advanced(OGRE_${PLUGIN}_REL OGRE_${PLUGIN}_DBG)
endif()
endif ()
if (TMP_CMAKE_LIB_PREFIX)
set(CMAKE_FIND_LIBRARY_PREFIXES ${TMP_CMAKE_LIB_PREFIX})
endif ()
endmacro(ogre_find_plugin)
ogre_find_plugin(Plugin_PCZSceneManager OgrePCZSceneManager.h PCZ PlugIns/PCZSceneManager/include)
ogre_find_plugin(Plugin_OctreeZone OgreOctreeZone.h PCZ PlugIns/OctreeZone/include)
ogre_find_plugin(Plugin_BSPSceneManager OgreBspSceneManager.h PlugIns/BSPSceneManager/include)
ogre_find_plugin(Plugin_CgProgramManager OgreCgProgram.h PlugIns/CgProgramManager/include)
ogre_find_plugin(Plugin_OctreeSceneManager OgreOctreeSceneManager.h PlugIns/OctreeSceneManager/include)
ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include)
ogre_find_plugin(RenderSystem_GL OgreGLRenderSystem.h RenderSystems/GL/include)
ogre_find_plugin(RenderSystem_GLES OgreGLESRenderSystem.h RenderSystems/GLES/include)
ogre_find_plugin(RenderSystem_GLES2 OgreGLES2RenderSystem.h RenderSystems/GLES2/include)
ogre_find_plugin(RenderSystem_Direct3D9 OgreD3D9RenderSystem.h RenderSystems/Direct3D9/include)
ogre_find_plugin(RenderSystem_Direct3D11 OgreD3D11RenderSystem.h RenderSystems/Direct3D11/include)
if (OGRE_STATIC)
# check if dependencies for plugins are met
if (NOT DirectX_FOUND)
set(OGRE_RenderSystem_Direct3D9_FOUND FALSE)
endif ()
if (NOT DirectX_D3D11_FOUND)
set(OGRE_RenderSystem_Direct3D11_FOUND FALSE)
endif ()
if (NOT OPENGL_FOUND)
set(OGRE_RenderSystem_GL_FOUND FALSE)
endif ()
if (NOT OPENGLES_FOUND)
set(OGRE_RenderSystem_GLES_FOUND FALSE)
endif ()
if (NOT OPENGLES2_FOUND)
set(OGRE_RenderSystem_GLES2_FOUND FALSE)
endif ()
if (NOT Cg_FOUND)
set(OGRE_Plugin_CgProgramManager_FOUND FALSE)
endif ()
set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES}
${DirectX_LIBRARIES}
)
set(OGRE_RenderSystem_Direct3D11_LIBRARIES ${OGRE_RenderSystem_Direct3D11_LIBRARIES}
${DirectX_D3D11_LIBRARIES}
)
set(OGRE_RenderSystem_GL_LIBRARIES ${OGRE_RenderSystem_GL_LIBRARIES}
${OPENGL_LIBRARIES}
)
set(OGRE_RenderSystem_GLES_LIBRARIES ${OGRE_RenderSystem_GLES_LIBRARIES}
${OPENGLES_LIBRARIES}
)
set(OGRE_RenderSystem_GLES2_LIBRARIES ${OGRE_RenderSystem_GLES2_LIBRARIES}
${OPENGLES2_LIBRARIES}
)
set(OGRE_Plugin_CgProgramManager_LIBRARIES ${OGRE_Plugin_CgProgramManager_LIBRARIES}
${Cg_LIBRARIES}
)
endif ()
# look for the media directory
set(OGRE_MEDIA_SEARCH_PATH
${OGRE_SOURCE}
${OGRE_LIBRARY_DIR_REL}/..
${OGRE_LIBRARY_DIR_DBG}/..
${OGRE_LIBRARY_DIR_REL}/../..
${OGRE_LIBRARY_DIR_DBG}/../..
${OGRE_PREFIX_SOURCE}
)
set(OGRE_MEDIA_SEARCH_SUFFIX
Samples/Media
Media
media
share/OGRE/media
)
IF (OGRE_INCLUDE_DIR AND OGRE_LIBRARIES) clear_if_changed(OGRE_PREFIX_WATCH OGRE_MEDIA_DIR)
SET(OGRE_FOUND TRUE) find_path(OGRE_MEDIA_DIR NAMES packs/cubemapsJS.zip HINTS ${OGRE_MEDIA_SEARCH_PATH}
ENDIF (OGRE_INCLUDE_DIR AND OGRE_LIBRARIES) PATHS ${OGRE_PREFIX_PATH} PATH_SUFFIXES ${OGRE_MEDIA_SEARCH_SUFFIX})
IF (OGRE_FOUND)
IF (NOT OGRE_FIND_QUIETLY)
MESSAGE(STATUS " libraries : ${OGRE_LIBRARIES} from ${OGRE_LIB_DIR}")
MESSAGE(STATUS " includes : ${OGRE_INCLUDE_DIR}")
MESSAGE(STATUS " plugins : ${OGRE_PLUGIN_DIR}")
ENDIF (NOT OGRE_FIND_QUIETLY)
ELSE (OGRE_FOUND)
IF (OGRE_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find OGRE")
ENDIF (OGRE_FIND_REQUIRED)
ENDIF (OGRE_FOUND)
CMAKE_POLICY(POP)

@ -50,6 +50,11 @@ endmacro(create_search_paths)
# clear cache variables if a certain variable changed # clear cache variables if a certain variable changed
macro(clear_if_changed TESTVAR) macro(clear_if_changed TESTVAR)
# test against internal check variable # test against internal check variable
# HACK: Apparently, adding a variable to the cache cleans up the list
# a bit. We need to also remove any empty strings from the list, but
# at the same time ensure that we are actually dealing with a list.
list(APPEND ${TESTVAR} "")
list(REMOVE_ITEM ${TESTVAR} "")
if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}")
message(STATUS "${TESTVAR} changed.") message(STATUS "${TESTVAR} changed.")
foreach(var ${ARGN}) foreach(var ${ARGN})
@ -129,9 +134,18 @@ MACRO(findpkg_framework fwk)
/System/Library/Frameworks /System/Library/Frameworks
/Network/Library/Frameworks /Network/Library/Frameworks
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/ /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/
${CMAKE_CURRENT_SOURCE_DIR}/../lib/Release ${CMAKE_CURRENT_SOURCE_DIR}/lib/Release
${CMAKE_CURRENT_SOURCE_DIR}/../lib/Debug ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug
) )
# These could be arrays of paths, add each individually to the search paths
foreach(i ${OGRE_PREFIX_PATH})
set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug)
endforeach(i)
foreach(i ${OGRE_PREFIX_BUILD})
set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug)
endforeach(i)
FOREACH(dir ${${fwk}_FRAMEWORK_PATH}) FOREACH(dir ${${fwk}_FRAMEWORK_PATH})
SET(fwkpath ${dir}/${fwk}.framework) SET(fwkpath ${dir}/${fwk}.framework)
IF(EXISTS ${fwkpath}) IF(EXISTS ${fwkpath})

@ -0,0 +1,60 @@
#-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
macro(get_preprocessor_entry CONTENTS KEYWORD VARIABLE)
string(REGEX MATCH
"# *define +${KEYWORD} +((\"([^\n]*)\")|([^ \n]*))"
PREPROC_TEMP_VAR
${${CONTENTS}}
)
if (CMAKE_MATCH_3)
set(${VARIABLE} ${CMAKE_MATCH_3})
else ()
set(${VARIABLE} ${CMAKE_MATCH_4})
endif ()
endmacro()
macro(has_preprocessor_entry CONTENTS KEYWORD VARIABLE)
string(REGEX MATCH
"\n *# *define +(${KEYWORD})"
PREPROC_TEMP_VAR
${${CONTENTS}}
)
if (CMAKE_MATCH_1)
set(${VARIABLE} TRUE)
else ()
set(${VARIABLE} FALSE)
endif ()
endmacro()
macro(replace_preprocessor_entry VARIABLE KEYWORD NEW_VALUE)
string(REGEX REPLACE
"(// *)?# *define +${KEYWORD} +[^ \n]*"
"#define ${KEYWORD} ${NEW_VALUE}"
${VARIABLE}_TEMP
${${VARIABLE}}
)
set(${VARIABLE} ${${VARIABLE}_TEMP})
endmacro()
macro(set_preprocessor_entry VARIABLE KEYWORD ENABLE)
if (${ENABLE})
set(TMP_REPLACE_STR "#define ${KEYWORD}")
else ()
set(TMP_REPLACE_STR "// #define ${KEYWORD}")
endif ()
string(REGEX REPLACE
"(// *)?# *define +${KEYWORD} *\n"
${TMP_REPLACE_STR}
${VARIABLE}_TEMP
${${VARIABLE}}
)
set(${VARIABLE} ${${VARIABLE}_TEMP})
endmacro()

@ -153,7 +153,7 @@ public:
*************************************************************************/ *************************************************************************/
int getVer() { return mCtx.header.version; } int getVer() { return mCtx.header.version; }
float getFVer() { return *((float*)&mCtx.header.version); } float getFVer() { if(mCtx.header.version == VER_12) return 1.2; else return 1.3; }
int getSpecial() { return mSpf; } int getSpecial() { return mSpf; }
const std::string getAuthor() { return mCtx.header.author.toString(); } const std::string getAuthor() { return mCtx.header.author.toString(); }
const std::string getDesc() { return mCtx.header.desc.toString(); } const std::string getDesc() { return mCtx.header.desc.toString(); }

@ -12,7 +12,6 @@
#include "store.hpp" #include "store.hpp"
#include "components/esm/records.hpp" #include "components/esm/records.hpp"
#include "components/esm/loadcell.hpp"
#include <list> #include <list>
#include <string> #include <string>

@ -1,66 +0,0 @@
project(Caelum)
IF(MSVC)
add_definitions("-D_SCL_SECURE_NO_WARNINGS /wd4305 /wd4244" )
ENDIF(MSVC)
ADD_DEFINITIONS(-DCAELUM_STATIC)
INCLUDE_DIRECTORIES(
${CMAKE_HOME_DIRECTORY}/extern/caelum/include
${OGRE_INCLUDE_DIR}/Ogre
)
file(GLOB_RECURSE CAELUM_SRC src/*)
file(GLOB_RECURSE CAELUM_HDR include/*)
set(SOURCES ${CAELUM_SRC} ${CAELUM_HDR})
add_library(caelum STATIC ${SOURCES})
#
# Resources
#
SET(CAELUM_RES_DEST "${OpenMW_BINARY_DIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/AtmosphereDepth.png "${CAELUM_RES_DEST}/resources/caelum/AtmosphereDepth.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CaelumGroundFog.cg "${CAELUM_RES_DEST}/resources/caelum/CaelumGroundFog.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CaelumLayeredClouds.cg "${CAELUM_RES_DEST}/resources/caelum/CaelumLayeredClouds.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CaelumPhaseMoon.cg "${CAELUM_RES_DEST}/resources/caelum/CaelumPhaseMoon.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CaelumPointStarfield.cg "${CAELUM_RES_DEST}/resources/caelum/CaelumPointStarfield.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CaelumSkyDome.cg "${CAELUM_RES_DEST}/resources/caelum/CaelumSkyDome.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/CloudCoverLookup.png "${CAELUM_RES_DEST}/resources/caelum/CloudCoverLookup.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/DepthComposer.cg "${CAELUM_RES_DEST}/resources/caelum/DepthComposer.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/DepthComposer.compositor "${CAELUM_RES_DEST}/resources/caelum/DepthComposer.compositor" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/DepthComposer.material "${CAELUM_RES_DEST}/resources/caelum/DepthComposer.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/DepthRender.program "${CAELUM_RES_DEST}/resources/caelum/DepthRender.program" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/EarthClearSky2.png "${CAELUM_RES_DEST}/resources/caelum/EarthClearSky2.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/GroundFog.material "${CAELUM_RES_DEST}/resources/caelum/GroundFog.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/GroundFog.program "${CAELUM_RES_DEST}/resources/caelum/GroundFog.program" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Haze.program "${CAELUM_RES_DEST}/resources/caelum/Haze.program" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/LayeredClouds.material "${CAELUM_RES_DEST}/resources/caelum/LayeredClouds.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/MinimalCompositorVP.cg "${CAELUM_RES_DEST}/resources/caelum/MinimalCompositorVP.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/MinimalCompositorVP.program "${CAELUM_RES_DEST}/resources/caelum/MinimalCompositorVP.program" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/moon.material "${CAELUM_RES_DEST}/resources/caelum/moon.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/moon_disc.dds "${CAELUM_RES_DEST}/resources/caelum/moon_disc.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/noise1.dds "${CAELUM_RES_DEST}/resources/caelum/noise1.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/noise2.dds "${CAELUM_RES_DEST}/resources/caelum/noise2.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/noise3.dds "${CAELUM_RES_DEST}/resources/caelum/noise3.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/noise4.dds "${CAELUM_RES_DEST}/resources/caelum/noise4.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/PointStarfield.material "${CAELUM_RES_DEST}/resources/caelum/PointStarfield.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Precipitation.cg "${CAELUM_RES_DEST}/resources/caelum/Precipitation.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Precipitation.compositor "${CAELUM_RES_DEST}/resources/caelum/Precipitation.compositor" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Precipitation.material "${CAELUM_RES_DEST}/resources/caelum/Precipitation.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_drizzle.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_drizzle.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_hail.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_hail.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_icecrystals.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_icecrystals.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_icepellets.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_icepellets.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_rain.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_rain.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_smallhail.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_smallhail.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_snow.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_snow.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/precipitation_snowgrains.png "${CAELUM_RES_DEST}/resources/caelum/precipitation_snowgrains.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/SkyDome.material "${CAELUM_RES_DEST}/resources/caelum/SkyDome.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/sphere.mesh "${CAELUM_RES_DEST}/resources/caelum/sphere.mesh" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Starfield.jpg "${CAELUM_RES_DEST}/resources/caelum/Starfield.jpg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Starfield.material "${CAELUM_RES_DEST}/resources/caelum/Starfield.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/Sun.material "${CAELUM_RES_DEST}/resources/caelum/Sun.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/SunGradient.png "${CAELUM_RES_DEST}/resources/caelum/SunGradient.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resources/sun_disc.png "${CAELUM_RES_DEST}/resources/caelum/sun_disc.png" COPYONLY)

@ -1,228 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__ASTRONOMY_H
#define CAELUM__ASTRONOMY_H
#include "CaelumPrerequisites.h"
namespace Caelum
{
/** Static class with astronomy routines.
* This class contains various astronomical routines useful in Caelum.
*
* Most of the formulas are from http://stjarnhimlen.se/comp/ppcomp.html
* That site contains much more than was implemented here; it has code
* for determining the positions of all the planets. Only the sun and
* moon are actually useful for caelum.
*
* The formulas are isolated here in pure procedural code for easier
* testing (Tests are done as assertions in the demo).
*
* Precision is vital here, so this class uses Caelum::LongReal(double)
* instead of Ogre::Real(float) for precission. All angles are in degrees
* unless otherwise mentioned. Ogre::Degree and Ogre::Radian use
* Ogre::Real and should be avoided here.
*/
class CAELUM_EXPORT Astronomy
{
private:
Astronomy() {}
static const LongReal PI;
/** Normalize an angle to the 0, 360 range.
* @param x The angle to normalize
*/
static LongReal normalizeDegrees (LongReal x);
/// Convert radians to degrees.
static LongReal radToDeg (LongReal x);
/// Convert degrees to radians.
static LongReal degToRad (LongReal x);
static LongReal sinDeg (LongReal x);
static LongReal cosDeg (LongReal x);
static LongReal atan2Deg (LongReal y, LongReal x);
public:
/// January 1, 2000, noon
static const LongReal J2000;
/** Convert from ecliptic to ecuatorial spherical coordinates, in radians.
* @param lon Ecliptic longitude
* @param lat Ecliptic latitude
* @param rasc Right ascension
* @param decl Declination
* @warning: This function works in radians.
*/
static void convertEclipticToEquatorialRad (
LongReal lon, LongReal lat,
LongReal& rasc, LongReal& decl);
static void convertRectangularToSpherical (
LongReal x, LongReal y, LongReal z,
LongReal &rasc, LongReal &decl, LongReal &dist);
static void convertSphericalToRectangular (
LongReal rasc, LongReal decl, LongReal dist,
LongReal &x, LongReal &y, LongReal &z);
/** Convert from equatorial to horizontal coordinates.
* This function converts from angles relative to the earth's equator
* to angle relative to the horizon at a given point.
* @param jday Astronomical time as julian day.
* @param longitude Observer's longitude in degrees east.
* @param latitude Observer's latitude in degrees north.
* @param rasc Object's right ascension.
* @param decl Object's declination.
* @param azimuth Object's azimuth (clockwise degrees from true north).
* @param altitude Object's altitude (degrees above the horizon).
*/
static void convertEquatorialToHorizontal (
LongReal jday,
LongReal longitude, LongReal latitude,
LongReal rasc, LongReal decl,
LongReal &azimuth, LongReal &altitude);
/** Get the sun's position in the sky in, relative to the horizon.
* @param jday Astronomical time as julian day.
* @param longitude Observer longitude
* @param latitude Observer latitude
* @param azimuth Astronomical azimuth, measured clockwise from North = 0.
* @param altitude Astronomical altitude, elevation above the horizon.
*/
static void getHorizontalSunPosition (
LongReal jday,
LongReal longitude, LongReal latitude,
LongReal &azimuth, LongReal &altitude);
static void getHorizontalSunPosition (
LongReal jday,
Ogre::Degree longitude, Ogre::Degree latitude,
Ogre::Degree &azimuth, Ogre::Degree &altitude);
/// Gets the moon position at a specific time in ecliptic coordinates
/// @param lon: Ecliptic longitude, in radians.
/// @param lat: Ecliptic latitude, in radians.
static void getEclipticMoonPositionRad (
LongReal jday,
LongReal &lon,
LongReal &lat);
static void getHorizontalMoonPosition (
LongReal jday,
LongReal longitude, LongReal latitude,
LongReal &azimuth, LongReal &altitude);
static void getHorizontalMoonPosition (
LongReal jday,
Ogre::Degree longitude, Ogre::Degree latitude,
Ogre::Degree &azimuth, Ogre::Degree &altitude);
/** Get astronomical julian day from normal gregorian calendar.
* From wikipedia: the integer number of days that have elapsed
* since the initial epoch defined as
* noon Universal Time (UT) Monday, January 1, 4713 BC
* @note this is the time at noon, not midnight.
*/
static int getJulianDayFromGregorianDate (
int year, int month, int day);
/** Get astronomical julian day from normal gregorian calendar.
* Calculate julian day from a day in the normal gregorian calendar.
* Time should be given as UTC.
* @see http://en.wikipedia.org/wiki/Julian_day
*/
static LongReal getJulianDayFromGregorianDateTime (
int year, int month, int day,
int hour, int minute, LongReal second);
/** Get astronomical julian day from normal gregorian calendar.
* @see above (I don't know the proper doxygen syntax).
*/
static LongReal getJulianDayFromGregorianDateTime (
int year, int month, int day,
LongReal secondsFromMidnight);
/// Get gregorian date from integer julian day.
static void getGregorianDateFromJulianDay (
int julianDay, int &year, int &month, int &day);
/// Get gregorian date time from floating point julian day.
static void getGregorianDateTimeFromJulianDay (
LongReal julianDay, int &year, int &month, int &day,
int &hour, int &minute, LongReal &second);
/// Get gregorian date from floating point julian day.
static void getGregorianDateFromJulianDay (
LongReal julianDay, int &year, int &month, int &day);
/** Enter high-precission floating-point mode.
*
* By default Direct3D decreases the precission of ALL floating
* point calculations, enough to stop Caelum's astronomy routines
* from working correctly.
*
* To trigger this behaviour in a standard ogre demo select the
* Direct3D render system and set "Floating-point mode" to
* "Fastest". Otherwise it's not a problem.
*
* It can be fixed by changing the precission only inside caelum's
* astronomy routines using the _controlfp function. This only works
* for MSVC on WIN32; This is a no-op on other compilers.
*
* @note: Must be paired with restoreFloatingPointMode.
* @return Value to pass to restoreFloatingModeMode.
*/
static int enterHighPrecissionFloatingPointMode ();
/** Restore old floating point precission.
* @see enterHighPrecissionFloatingPointMode.
*/
static void restoreFloatingPointMode (int oldMode);
};
/** Dummy class to increase floting point precission in a block
* This class will raise precission in the ctor and restore it
* in the destructor. During it's lifetime floating-point
* precission will be increased.
*
* To use this class just create a instance on the stack at the start of a block.
*
* @see Astronomy::enterHighPrecissionFloatingPointMode
*/
class CAELUM_EXPORT ScopedHighPrecissionFloatSwitch
{
private:
int mOldFpMode;
public:
inline ScopedHighPrecissionFloatSwitch() {
mOldFpMode = Astronomy::enterHighPrecissionFloatingPointMode ();
}
inline ~ScopedHighPrecissionFloatSwitch() {
Astronomy::restoreFloatingPointMode (mOldFpMode);
}
};
}
#endif // CAELUM__ASTRONOMY_H

@ -1,44 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM_H
#define CAELUM_H
#include "CaelumPrerequisites.h"
#include "CaelumScriptTranslator.h"
#include "TypeDescriptor.h"
#include "CaelumPlugin.h"
#include "CaelumExceptions.h"
#include "CaelumSystem.h"
#include "CameraBoundElement.h"
#include "SkyDome.h"
#include "Sun.h"
#include "Moon.h"
#include "UniversalClock.h"
#include "Astronomy.h"
#include "CloudSystem.h"
#include "PrecipitationController.h"
#include "FlatCloudLayer.h"
#include "ImageStarfield.h"
#include "PointStarfield.h"
#include "GroundFog.h"
#include "DepthComposer.h"
#endif // CAELUM_H

@ -1,54 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAELUM_EXCEPTIONS_H
#define CAELUM__CAELUM_EXCEPTIONS_H
#include "CaelumPrerequisites.h"
namespace Caelum
{
/** Exception class for unsupported features.
* This is frequently thrown if a certain required material does not load;
* most likely because the hardware does not support the required shaders.
*/
class CAELUM_EXPORT UnsupportedException : public Ogre::Exception
{
public:
/// Constructor.
UnsupportedException
(
int number,
const Ogre::String &description,
const Ogre::String &source,
const char *file,
long line
):
Ogre::Exception (number, description, source, "UnsupportedException", file, line)
{
}
};
#define CAELUM_THROW_UNSUPPORTED_EXCEPTION(desc, src) \
throw UnsupportedException(-1, (desc), (src), __FILE__, __LINE__);
}
#endif // CAELUM__CAELUM_EXCEPTIONS_H

@ -1,97 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAELUM_PLUGIN_H
#define CAELUM__CAELUM_PLUGIN_H
#include "CaelumPrerequisites.h"
#include "CaelumScriptTranslator.h"
#include "TypeDescriptor.h"
#include "OgrePlugin.h"
namespace Caelum
{
/** Implement an Ogre::Plugin for Caelum.
*
* Ogre plugins are usually loaded from config files and they register
* various stuff in ogre managers. But you can also just link to the
* library normally and call install functions manually.
*/
class CAELUM_EXPORT CaelumPlugin: public Ogre::Singleton<CaelumPlugin>, public Ogre::Plugin
{
public:
/// Get reference to singleton instance; or crash if N/A.
static CaelumPlugin& getSingleton(void);
/// Get pointer to singleton instance; or pointer if N/A.
static CaelumPlugin* getSingletonPtr(void);
CaelumPlugin();
~CaelumPlugin();
virtual void install ();
virtual void initialise ();
virtual void shutdown ();
virtual void uninstall ();
static const Ogre::String CAELUM_PLUGIN_NAME;
virtual const String& getName () const;
// Determine if the plugin was installed (if install was called).
inline bool isInstalled () const { return mIsInstalled; }
private:
bool mIsInstalled;
#if CAELUM_TYPE_DESCRIPTORS
public:
/// Get default type descriptor data for caelum components.
CaelumDefaultTypeDescriptorData* getTypeDescriptorData () { return &mTypeDescriptorData; }
private:
CaelumDefaultTypeDescriptorData mTypeDescriptorData;
#endif
#if CAELUM_SCRIPT_SUPPORT
public:
/** Load CaelumSystem and it's components from a script file.
* @param sys Target CaelumSystem.
* This is cleared using CaelumSystem::clear before loading.
* If scripting data is not found then this is not modified.
* @param objectName Name of caelum_sky_system from *.os file.
* @param scriptFileGroup The group to search in (unused in Ogre 1.6)
*/
void loadCaelumSystemFromScript (
CaelumSystem* sys,
const Ogre::String& objectName,
const Ogre::String& scriptFileGroup = Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME
);
/// @see PropScriptResourceManager
PropScriptResourceManager* getPropScriptResourceManager () { return &mPropScriptResourceManager; }
CaelumScriptTranslatorManager* getScriptTranslatorManager () { return &mScriptTranslatorManager; }
private:
PropScriptResourceManager mPropScriptResourceManager;
CaelumScriptTranslatorManager mScriptTranslatorManager;
#endif
};
}
#endif // CAELUM__CAELUM_PLUGIN_H

@ -1,25 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2007 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __APPLE__
#include "Ogre/Ogre.h"
#else
#include "Ogre.h"
#endif

@ -1,180 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAELUM_PREREQUISITES_H
#define CAELUM__CAELUM_PREREQUISITES_H
// Include external headers
#ifdef __APPLE__
#include "Ogre/Ogre.h"
#else
#include "Ogre.h"
#endif
#include <memory>
// Define the dll export qualifier if compiling for Windows
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#ifdef CAELUM_STATIC
// Don't use dll export qualifier when built as a static lib
#define CAELUM_EXPORT
#elif CAELUM_LIB
#define CAELUM_EXPORT __declspec (dllexport)
#else
#ifdef __MINGW32__
#define CAELUM_EXPORT
#else
#define CAELUM_EXPORT __declspec (dllimport)
#endif
#endif
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#define CAELUM_EXPORT __attribute__ ((visibility("default")))
#else
#define CAELUM_EXPORT
#endif
// Define the version code
#define CAELUM_VERSION_MAIN 0
#define CAELUM_VERSION_SEC 5
#define CAELUM_VERSION_TER 0
#define CAELUM_VERSION = (CAELUM_VERSION_MAIN << 16) | (CAELUM_VERSION_SEC << 8) | CAELUM_VERSION_TER
// By default only compile type descriptors for scripting.
#ifndef CAELUM_TYPE_DESCRIPTORS
#if (OGRE_VERSION >= 0x00010600) && OGRE_USE_NEW_COMPILERS
#define CAELUM_TYPE_DESCRIPTORS 1
#else
#define CAELUM_TYPE_DESCRIPTORS 0
#endif
#endif
// Scripting support requires Ogre 1.6
// Can be also configured on compiler command line
#ifndef CAELUM_SCRIPT_SUPPORT
#if (OGRE_VERSION >= 0x00010600) && OGRE_USE_NEW_COMPILERS
#define CAELUM_SCRIPT_SUPPORT 1
#else
#define CAELUM_SCRIPT_SUPPORT 0
#endif
#else
#if !(OGRE_VERSION > 0x00010600)
#error "Caelum script support requires Ogre 1.6."
#endif
#if !(OGRE_USE_NEW_COMPILERS)
#error "Caelum script support requires Ogre 1.6 with OGRE_USE_NEW_COMPILERS."
#endif
#if !(CAELUM_TYPE_DESCRIPTORS)
#error "Caelum script support also requires type descriptors."
#endif
#endif
/// @file
/** @mainpage
*
* %Caelum is an Ogre add-on for atmospheric rendering. It is composed of a
* number of small mostly self-contained components and a big
* Caelum::CaelumSystem class which ties them all together in an easy-to-use
* way.
*
* More information is available on the wiki page:
* http://www.ogre3d.org/wiki/index.php/Caelum
*
* You can discuss and report issues in the forum:
* http://www.ogre3d.org/addonforums/viewforum.php?f=21
*/
/** Caelum namespace
*
* All of %Caelum is inside this namespace (except for macros).
*
* @note: This was caelum with a lowercase 'c' in version 0.3
*/
namespace Caelum
{
// Caelum needs a lot of precission for astronomical calculations.
// Very few calculations use it, and the precission IS required.
typedef double LongReal;
// Use some ogre types.
using Ogre::uint8;
using Ogre::uint16;
using Ogre::ushort;
using Ogre::uint32;
using Ogre::uint;
using Ogre::Real;
using Ogre::String;
/// Resource group name for caelum resources.
static const String RESOURCE_GROUP_NAME = "Caelum";
// Render group for caelum stuff
// It's best to have them all together
enum CaelumRenderQueueGroupId
{
CAELUM_RENDER_QUEUE_STARFIELD = Ogre::RENDER_QUEUE_SKIES_EARLY + 0,
CAELUM_RENDER_QUEUE_MOON_BACKGROUND = Ogre::RENDER_QUEUE_SKIES_EARLY + 1,
CAELUM_RENDER_QUEUE_SKYDOME = Ogre::RENDER_QUEUE_SKIES_EARLY + 2,
CAELUM_RENDER_QUEUE_MOON = Ogre::RENDER_QUEUE_SKIES_EARLY + 3,
CAELUM_RENDER_QUEUE_SUN = Ogre::RENDER_QUEUE_SKIES_EARLY + 4,
CAELUM_RENDER_QUEUE_CLOUDS = Ogre::RENDER_QUEUE_SKIES_EARLY + 5,
CAELUM_RENDER_QUEUE_GROUND_FOG = Ogre::RENDER_QUEUE_SKIES_EARLY + 6,
};
// Forward declarations
class UniversalClock;
class SkyDome;
class BaseSkyLight;
class Moon;
class SphereSun;
class SpriteSun;
class ImageStarfield;
class PointStarfield;
class CloudSystem;
class CaelumSystem;
class FlatCloudLayer;
class PrecipitationController;
class PrecipitationInstance;
class GroundFog;
class DepthComposer;
class DepthComposerInstance;
class DepthRenderer;
}
namespace Ogre
{
#if OGRE_VERSION <= 0x010602
// Write an Ogre::Degree to a stream.
//
// Ogre::Any requires that the wrapped type can be written to a stream;
// otherwise it will fail on instantation. This function was placed here
// so it's available everywhere. This can't be placed in namespace Caelum.
//
// Ogre 1.6.3 and up already include this operator; so it's ifdefed out.
//
// This function is never actually used; the output does not matter.
inline std::ostream& operator << (std::ostream& out, Ogre::Degree deg) {
return out << deg.valueDegrees();
}
#endif
}
#endif // CAELUM__CAELUM_PREREQUISITES_H

@ -1,216 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAELUM_SCRIPT_TRANSLATOR_H
#define CAELUM__CAELUM_SCRIPT_TRANSLATOR_H
#if CAELUM_SCRIPT_SUPPORT
#include "CaelumPrerequisites.h"
#include "OgreScriptTranslator.h"
#include "TypeDescriptor.h"
namespace Caelum
{
/** Dummy resources created for property script blocks.
*
* When parsing material scripts the singleton rendersystem is available
* and materials are created using it. But Caelum's scriptable components
* require at least an active scene scene manager; and you can't require
* something like that when initializing resources.
*
* So instead a dummy resource like this is created which only remembers
* the location of the script block in the resources. Actually loading the
* properties will always reparse the script.
*
* The original file name is available from Ogre::Resource::getOrigin
*
* These resources are managed by the PropScriptResourceManager. Resource
* operations like loading and unloading are meaningless.
*/
class CAELUM_EXPORT PropScriptResource: public Ogre::Resource {
protected:
virtual void loadImpl () { }
virtual void unloadImpl () { }
virtual size_t calculateSize () const { return 0; }
public:
PropScriptResource (
Ogre::ResourceManager* creator, const Ogre::String& name, Ogre::ResourceHandle handle,
const Ogre::String& group, bool isManual, Ogre::ManualResourceLoader* loader);
~PropScriptResource();
};
/** Resource manager for PropScriptResource.
*/
class CAELUM_EXPORT PropScriptResourceManager: public Ogre::ResourceManager
{
public:
PropScriptResourceManager();
virtual PropScriptResource* createImpl(
const String& name, Ogre::ResourceHandle handle, const String& group,
bool isManual, Ogre::ManualResourceLoader* loader, const Ogre::NameValuePairList* createParams);
};
/** An Ogre::ScriptTranslator based on a TypeDescriptor.
* This class implements an Ogre::ScriptTranslator based on data from a TypeDescriptor.
*
* The target object is never created; it must be passed in the context member of the
* root node. Some other ScriptTranslator must cooperate and set the context member;
* this is similar to how Ogre::PassTranslator depends on Ogre::MaterialTranslator
* setting the context.
*
* Ogre::AbstractNode::context is an Ogre::Any which boxes objects in a way which
* stores the static (compile-time) type at assignment. You must cast the
* object into a void* before setting it as the context.
*
* Most of the actual translation functionality is in static functions; a class can
* translate based on TypeDescriptor data without deriving from this class.
*/
class CAELUM_EXPORT TypeDescriptorScriptTranslator: public Ogre::ScriptTranslator
{
public:
/** Get the value of a property or report the appropriate error.
* @return Success value.
*/
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, int& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, float& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, double& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, bool& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, Ogre::Degree& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, Ogre::ColourValue& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, Ogre::String& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, Ogre::Vector3& value);
static bool getPropValueOrAddError (Ogre::ScriptCompiler* compiler, Ogre::PropertyAbstractNode* prop, Ogre::Vector2& value);
/** Translate a property using a TypeDescriptor; or report error to compiler.
*/
static void translateProperty (
Ogre::ScriptCompiler* compiler,
Ogre::PropertyAbstractNode* prop,
void* targetObject,
const TypeDescriptor* typeDescriptor);
public:
explicit TypeDescriptorScriptTranslator (TypeDescriptor* type = 0);
virtual void translate (Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr& node);
inline const TypeDescriptor* getTypeDescriptor () const { return mTypeDescriptor; }
inline TypeDescriptor* getTypeDescriptor () { return mTypeDescriptor; }
private:
TypeDescriptor* mTypeDescriptor;
};
/** Script translator for CaelumSystem
*/
struct CAELUM_EXPORT CaelumSystemScriptTranslator: public Ogre::ScriptTranslator
{
public:
CaelumSystemScriptTranslator();
virtual void translate (Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr& node);
void setTranslationTarget (CaelumSystem* target, const Ogre::String& name);
void clearTranslationTarget ();
inline bool hasTranslationTarget () const { return mTranslationTarget != 0; }
inline bool foundTranslationTarget () const { return mTranslationTargetFound; }
inline CaelumSystem* getTranslationTarget () const { return mTranslationTarget; }
inline const Ogre::String& getTranslationTargetName () const { return mTranslationTargetName; }
inline void setResourceManager (PropScriptResourceManager* value) { mResourceManager = value; }
inline PropScriptResourceManager* getResourceManager () const { return mResourceManager; }
private:
PropScriptResourceManager* mResourceManager;
CaelumSystem* mTranslationTarget;
Ogre::String mTranslationTargetName;
bool mTranslationTargetFound;
public:
/** Type descriptor for CaelumSystem itself.
* This is use for simple top-level properties.
* Components (sun, moon etc) are handled with custom code.
*/
inline const TypeDescriptor* getTypeDescriptor () const { return mTypeDescriptor; }
inline void setTypeDescriptor (const TypeDescriptor* value) { mTypeDescriptor = value; }
private:
const TypeDescriptor* mTypeDescriptor;
};
/** Script translator for CloudSystem
* Caelum::CloudSystem requires a special translator because it's made up of separate layers.
*
* Layers of different types are not supported; only instances of FlatCloudLayer.
* CloudSystem doesn't have any top-level properties.
*
* Overriding works just like for ogre texture units; and you can use name-based overriding.
* Names are not preserved after script translation; they're only used inside Ogre's script
* compilation steps.
*/
struct CAELUM_EXPORT CloudSystemScriptTranslator: public Ogre::ScriptTranslator
{
public:
virtual void translate (Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr& node);
};
/** ScriptTranslatorManager for caelum's scriptable objects.
* This class contains Ogre::ScriptTranslators for Caelum components.
*/
class CAELUM_EXPORT CaelumScriptTranslatorManager: public Ogre::ScriptTranslatorManager
{
public:
explicit CaelumScriptTranslatorManager (CaelumDefaultTypeDescriptorData* typeData);
virtual size_t getNumTranslators () const;
/// @copydoc Ogre::ScriptTranslatorManager::getTranslator.
virtual Ogre::ScriptTranslator* getTranslator (const Ogre::AbstractNodePtr& node);
void _setPropScriptResourceManager (PropScriptResourceManager* mgr);
inline CaelumSystemScriptTranslator* getCaelumSystemTranslator () { return &mCaelumSystemTranslator; }
private:
CaelumSystemScriptTranslator mCaelumSystemTranslator;
CloudSystemScriptTranslator mCloudSystemTranslator;
TypeDescriptorScriptTranslator mFlatCloudLayerTranslator;
TypeDescriptorScriptTranslator mSunTranslator;
TypeDescriptorScriptTranslator mMoonTranslator;
TypeDescriptorScriptTranslator mPointStarfieldTranslator;
TypeDescriptorScriptTranslator mGroundFogTranslator;
TypeDescriptorScriptTranslator mDepthComposerTranslator;
TypeDescriptorScriptTranslator mPrecipitationTranslator;
TypeDescriptorScriptTranslator mSkyDomeTranslator;
/// Maps class name to script translator.
/// Does not own memory; just holds pointers to members.
typedef std::map<Ogre::String, Ogre::ScriptTranslator*> ScriptTranslatorMap;
ScriptTranslatorMap mTranslatorMap;
};
}
#endif // CAELUM_SCRIPT_SUPPORT
#endif // CAELUM__CAELUM_SCRIPT_TRANSLATOR_H

@ -1,672 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAELUM_SYSTEM_H
#define CAELUM__CAELUM_SYSTEM_H
#include "CaelumPrerequisites.h"
#include "UniversalClock.h"
#include "ImageStarfield.h"
#include "PointStarfield.h"
#include "SkyLight.h"
#include "Sun.h"
#include "Moon.h"
#include "CloudSystem.h"
#include "SkyDome.h"
#include "DepthComposer.h"
#include "PrecipitationController.h"
#include "GroundFog.h"
#include "PrivatePtr.h"
namespace Caelum
{
/** This is the "root class" of caelum.
*
* This class is created once for one SceneManager and will render the sky
* for that scene. CaelumSystem will be visible in all viewports on the
* scene and must be notified when those viewports are created and
* destroyed.
*
* @par Components
*
* %Caelum is built from several classes for different sky elements (the sun,
* clouds, etc). Those classes know very little about each other and are
* connected through this class. This class is responsible for tracking and
* updating sub-components.
*
* This class "owns" all of the subcomponents, using std::auto_ptr members.
* When you call functions like setXxx(new Xxx()) this class takes
* ownership of the object's lifetime and will try to update it as
* appropriate. All components are optional; disable one component should
* never cause a crash. When something is broken disabling components one
* by one is a very good way to find the source of the problem.
*
* The constructor can create a bunch of components with default settings
* for you; based on the CaelumSystem::CaelumComponent flags passed.
*
* @par Updating
*
* This class is responsible for updating subcomponents. There are two
* update functions which must be get called to keep CaelumSystem
* functioning properly. One is per-frame and the other is per-camera.
*
* CaelumSystem::updateSubcomponents must be called once per frame to
* advance world time and tie components together. That function will
* set certain properties on the subcomponents making up CaelumSystem
* If you want to force some properties beyond what CaelumSystem does by
* default you can do that AFTER the call to updateSubcompoments. For
* example you can override the moon's phase by calling Moon::setPhase.
*
* CaelumSystem::notifyCameraChanged must be called for each camera
* before rendering with that camera. All viewport tweaks and camera
* movement must be done BEFORE calling this function. This method will
* recenter Caelum's domes on the camera. Also, some subcomponents
* can actually depend on field-of-view and viewport resolution (like
* PointStarfield).
*
* You can register CaelumSystem as an Ogre::FrameListener and
* updateSubcomponents will be automatically called inside Ogre's
* rendering loop (inside frameStarted). If you want more control you
* should call updateSubcomponents in your own main loop. That way you
* can avoid potential issues with the ordering of multiple FrameListeners.
*
* You can register CaelumSystem as an Ogre::RenderTargetListener and
* notifyCameraChanged will be automatically called inside
* preViewportUpdate. That behaviour can be disabled with
* setAutoNotifyCameraChanged(false). It is recommended that you
* call notifyCameraChanged manually before updating viewports.
*
* RenderTargetListener::preViewportUpdate does not work as expected
* when compositors are involved (those inside Caelum or external).
* Compositors plug into preRenderTargetUpdate and render the scene to a
* texture BEFORE preViewportUpdate; this means that notifyCameraChanged
* will execute before the final compositor pass but after actual scene
* rendering.
*
* If notifyCameraChanged is not called correctly the most likely result
* is "flickering" when moving the camera. If you move the camera AFTER
* notifyCameraChanged then the domes will not be positioned correctly
* and will appear to lag slightly after the camera. Since updates are
* always done every frame keeping the camera still will make problems
* disappear.
*
* If you notice z-buffer issues while the camera is still update order
* is probably not the cause.
*/
class CAELUM_EXPORT CaelumSystem:
public Ogre::FrameListener,
public Ogre::RenderTargetListener
{
private:
/// Root of the Ogre engine.
Ogre::Root *mOgreRoot;
/// Scene manager.
Ogre::SceneManager *mSceneMgr;
/// Caelum scene node for camera-bound elements (most).
PrivateSceneNodePtr mCaelumCameraNode;
/// Caelum scene node for ground-bound elements (only clouds currently).
PrivateSceneNodePtr mCaelumGroundNode;
/// Cleanup requested flag.
bool mCleanup;
/// Automatically move the camera node.
bool mAutoMoveCameraNode;
/// Automatically call this->notifyCameraChanged.
bool mAutoNotifyCameraChanged;
/// Automatically attach compositors to viewports
bool mAutoAttachViewportsToComponents;
/// Automatically set the viewport colour to black.
bool mAutoViewportBackground;
/// Flag to indicate if Caelum manages standard Ogre::Scene fog.
bool mManageSceneFog;
Real mGlobalFogDensityMultiplier;
Ogre::ColourValue mGlobalFogColourMultiplier;
Real mSceneFogDensityMultiplier;
Ogre::ColourValue mSceneFogColourMultiplier;
Real mGroundFogDensityMultiplier;
Ogre::ColourValue mGroundFogColourMultiplier;
/// Flag for managing scene ambient light.
bool mManageAmbientLight;
/// Minimum ambient light; only useful if mManageAmbientLight
Ogre::ColourValue mMinimumAmbientLight;
/// If only one light source should enabled at a time.
bool mEnsureSingleLightSource;
/// Ensure only one of the light sources casts shadows.
bool mEnsureSingleShadowSource;
/// The sky gradients image (for lookups).
std::auto_ptr<Ogre::Image> mSkyGradientsImage;
/// The sun gradients image (for lookups).
std::auto_ptr<Ogre::Image> mSunColoursImage;
/// Observer Latitude (on the earth).
Ogre::Degree mObserverLatitude;
/// Observer Longitude (on the earth).
Ogre::Degree mObserverLongitude;
static const Ogre::Vector3 makeDirection (
Ogre::Degree azimuth, Ogre::Degree altitude);
// References to sub-components
std::auto_ptr<UniversalClock> mUniversalClock;
std::auto_ptr<SkyDome> mSkyDome;
std::auto_ptr<BaseSkyLight> mSun;
std::auto_ptr<Moon> mMoon;
std::auto_ptr<ImageStarfield> mImageStarfield;
std::auto_ptr<PointStarfield> mPointStarfield;
std::auto_ptr<GroundFog> mGroundFog;
std::auto_ptr<CloudSystem> mCloudSystem;
std::auto_ptr<PrecipitationController> mPrecipitationController;
std::auto_ptr<DepthComposer> mDepthComposer;
public:
typedef std::set<Ogre::Viewport*> AttachedViewportSet;
private:
AttachedViewportSet mAttachedViewports;
public:
/** Flags enumeration for caelum components.
* This is an enumeration for the components to create by default in
* Caelum's constructor. You can still pass 0 and create everything
* by hand.
*
* CaelumSystem's constructor used to take a number of bools but now
* there are too many components and this is nicer.
*
* CAELUM_COMPONENT_ members are for individual components.
* CAELUM_COMPONENTS_ are standard bitmasks.
* CAELUM_COMPONENTS_DEFAULT picks elements that don't require
* modifications to external materials (right now it excludes ground fog).
*/
enum CaelumComponent
{
CAELUM_COMPONENT_SKY_DOME = 1 << 1,
CAELUM_COMPONENT_MOON = 1 << 3,
CAELUM_COMPONENT_SUN = 1 << 4,
CAELUM_COMPONENT_IMAGE_STARFIELD = 1 << 5,
CAELUM_COMPONENT_POINT_STARFIELD = 1 << 6,
CAELUM_COMPONENT_CLOUDS = 1 << 7,
CAELUM_COMPONENT_PRECIPITATION = 1 << 8,
CAELUM_COMPONENT_SCREEN_SPACE_FOG = 1 << 9,
// This has nasty dependencies on materials.
CAELUM_COMPONENT_GROUND_FOG = 1 << (16 + 0),
// Groups
CAELUM_COMPONENTS_NONE = 0,
CAELUM_COMPONENTS_DEFAULT = 0
| CAELUM_COMPONENT_SKY_DOME
| CAELUM_COMPONENT_MOON
| CAELUM_COMPONENT_SUN
| CAELUM_COMPONENT_POINT_STARFIELD
| CAELUM_COMPONENT_CLOUDS,
CAELUM_COMPONENTS_ALL = 0
| CAELUM_COMPONENTS_DEFAULT
| CAELUM_COMPONENT_PRECIPITATION
| CAELUM_COMPONENT_SCREEN_SPACE_FOG
| CAELUM_COMPONENT_GROUND_FOG,
};
static const String DEFAULT_SKY_GRADIENTS_IMAGE;
static const String DEFAULT_SUN_COLOURS_IMAGE;
/** Constructor.
* Registers itself in the Ogre engine and initialises the system.
*
* @param root The Ogre root.
* @param scene The Ogre scene manager.
* @param componentsToCreate Default components for @see autoConfigure.
*/
CaelumSystem (
Ogre::Root *root,
Ogre::SceneManager *sceneMgr,
CaelumComponent componentsToCreate);
/** Revert everything to defaults.
*
* This function will delete all subcomponents and revert everything
* to default values (the values which are also set on construction).
*/
void clear ();
/** Create some default component with resonable default settings.
* This results in a slightly cloudy morning sky.
* This will always call clear() before creating components.
* autoConfigure (0); is equivalent to clear();
*/
void autoConfigure (
CaelumComponent componentsToCreate);
/** Destructor.
*/
~CaelumSystem ();
/** Shuts down the system and detaches itself from the Ogre engine.
*
* shutdown(true) is equivalent to deleting CaelumSystem yourself.
* shutdown(false) delays destruction to the next time caelum is called as
* a frame listener. This makes it safe to shutdown Caelum from inside
* another frame listener.
*
* @param cleanup If this is true then detach and destroy the CaelumSystem instantly.
*/
void shutdown (bool cleanup);
/** Update the whole system manually.
* You have to call this yourself if you don't register CaelumSystem
* as an ogre frame listener. Otherwise it's called automatically.
*
* @param timeSinceLastFrame: Time passed since last frame.
*/
void updateSubcomponents (Real timeSinceLastFrame);
/** Notify subcomponents of camera changes.
* This function must be called after camera changes but before
* rendering with that camera. If multiple cameras are used it must
* be called for each camera before the camera is rendered with.
*
* This function will move caelum's camera node to the camera
* position, but only if getAutoMoveCameraNode.
* It will also call CameraBoundElement::notifyCameraChanged
*/
void notifyCameraChanged(Ogre::Camera* cam);
/** Get the scene manager for this caelum system.
* This is set in the constructor. CaelumSystem can't exist without a valid scene manager.
*/
inline Ogre::SceneManager* getSceneMgr() const { return mSceneMgr; }
/// Gets root scene node for camera-bound elements
inline Ogre::SceneNode* getCaelumCameraNode(void) const { return mCaelumCameraNode.get(); }
/// Gets root scene node for ground-bound elements.
inline Ogre::SceneNode* getCaelumGroundNode(void) const { return mCaelumGroundNode.get(); }
/** If true; listen to preViewportUpdate and automatically notifyCameraChanged();
*
* This is on by default; but does not work with compositors.
*
* You must attach CaelumSystem as a RenderTargetListener manually for
* this to work; as in version 0.3.
*/
inline void setAutoNotifyCameraChanged(bool value) { mAutoNotifyCameraChanged = value; }
/// @see setAutoNotifyCameraChanged
inline bool getAutoNotifyCameraChanged() const { return mAutoNotifyCameraChanged; }
/** If true; automatically attach viewports to subcomponents.
*
* Some subcomponents use compositors and those compositors need to
* be attached to individual viewports. By default CaelumSystem will
* try take to take care of that automatically.
*
* This property allows you to disable that behaviour. If set to false
* you must call functions like
* PrecipitationController::createViewportInstance manually.
*
* @see attachViewport detachViewport
*/
inline void setAutoAttachViewportsToComponents(bool value) { mAutoAttachViewportsToComponents = value; }
/// @see setAutoAttachViewportsToComponents.
inline bool getAutoAttachViewportsToComponents() const { return mAutoAttachViewportsToComponents; }
/** If true (default); automatically move the camera node in notifyCameraChanged.
* If disable you get full control of the camera node; and in theory
* you can attach it to the scene graph however you please.
*/
inline void setAutoMoveCameraNode(bool value) { mAutoMoveCameraNode = value; }
/// @see setAutoMoveCameraNode
inline bool getAutoMoveCameraNode() { return mAutoMoveCameraNode; }
/** If true; automatically set the viewport color to black.
* Caelum's domes relies on the viewport background being black.
* There's generally no reason to disable this and it's on by default.
*/
inline void setAutoViewportBackground(bool value) { mAutoViewportBackground = value; }
/// @see setAutoViewportBackground
inline bool getAutoViewportBackground() const { return mAutoViewportBackground; }
/// Get the observer's longitude. East is positive, west is negative.
inline const Ogre::Degree getObserverLongitude () const { return mObserverLongitude; }
/// Set the observer's longitude. East is positive, west is negative.
inline void setObserverLongitude (Ogre::Degree value) { mObserverLongitude = value; }
/// Get the observer's latitude. North is positive, south is negative.
inline const Ogre::Degree getObserverLatitude () const { return mObserverLatitude; }
/// Set the observer's latitude. North is positive, south is negative.
inline void setObserverLatitude (Ogre::Degree value) { mObserverLatitude = value; }
inline LongReal getJulianDay () const { return mUniversalClock->getJulianDay (); }
inline void setJulianDay (LongReal value) { mUniversalClock->setJulianDay (value); }
inline Real getTimeScale () const { return mUniversalClock->getTimeScale (); }
inline void setTimeScale (Real value) { mUniversalClock->setTimeScale (value); }
public:
/** Attach CaelumSystem to a viewport.
* You should call this for every new viewport looking at the scene
* where CaelumSystem is created.
*
* If the viewport is already attached then nothing happens.
*
* If getAutoAttachViewportsToComponents() this will add Caelum's compositors.
*/
void attachViewport (Ogre::Viewport* rt);
/** Reverse of @see attachViewport.
* You need to call this when you destroy a viewport.
*
* If the viewport is not already attached nothing happens.
*/
void detachViewport (Ogre::Viewport* rt);
/** Check if one particular viewport is attached.
*/
bool isViewportAttached (Ogre::Viewport* vp) const;
/** Detach from all viewports.
*/
void detachAllViewports ();
/// Get a reference to the set of attached viewports.
const AttachedViewportSet& _getAttachedViewportSet () { return mAttachedViewports; }
protected:
// Do the work behind attach/detach viewport.
void attachViewportImpl (Ogre::Viewport* rt);
void detachViewportImpl (Ogre::Viewport* rt);
public:
/// Gets the universal clock.
inline UniversalClock *getUniversalClock () const { return mUniversalClock.get(); }
/// Get the current sky dome, or null if disabled.
inline SkyDome* getSkyDome () const { return mSkyDome.get (); }
/// Set the skydome, or null to disable.
void setSkyDome (SkyDome *obj);
/// Gets the current sun, or null if disabled.
inline BaseSkyLight* getSun () const { return mSun.get (); }
/// Set the sun, or null to disable.
void setSun (BaseSkyLight* obj);
/// Gets the current moon, or null if disabled.
inline Moon* getMoon () const { return mMoon.get (); }
/// Set the moon, or null to disable.
void setMoon (Moon* obj);
/// Gets the current image starfield, or null if disabled.
inline ImageStarfield* getImageStarfield () const { return mImageStarfield.get (); }
/// Set image starfield, or null to disable.
void setImageStarfield (ImageStarfield* obj);
/// Gets the current point starfield, or null if disabled.
inline PointStarfield* getPointStarfield () const { return mPointStarfield.get (); }
/// Set image starfield, or null to disable.
void setPointStarfield (PointStarfield* obj);
/// Get ground fog; if enabled.
inline GroundFog* getGroundFog () { return mGroundFog.get (); }
/// Sets ground fog system, or null to disable.
void setGroundFog (GroundFog *obj);
/// Get cloud system; or null if disabled.
inline CloudSystem* getCloudSystem () { return mCloudSystem.get (); }
/// Set cloud system; or null to disable.
void setCloudSystem (CloudSystem *obj);
/// Get precipitation controller; or null if disabled.
inline PrecipitationController* getPrecipitationController () { return mPrecipitationController.get (); }
/// Set precipitation controller; or null to disable.
void setPrecipitationController (PrecipitationController *obj);
/// Get depth composer; or null if disabled.
inline DepthComposer* getDepthComposer () { return mDepthComposer.get (); }
/// Set depth composer; or null to disable.
void setDepthComposer (DepthComposer *obj);
/** Enables/disables Caelum managing standard Ogre::Scene fog.
This makes CaelumSystem control standard Ogre::Scene fogging. It
will use EXP2 fog with density from SkyColourModel.
Fog density multipliers are used; final scene fog density is:
SceneMultiplier * GlobalMultiplier * SkyColourModel.GetFogDensity
When this is set to false it also disables all scene fog (but you
control it afterwards).
@param value New value
*/
void setManageSceneFog (bool value);
/** Tells if Caelum is managing the fog or not.
@return The value set in setManageSceneFog.
*/
bool getManageSceneFog () const;
/** Multiplier for scene fog density (default 1).
This is an additional multiplier for Ogre::Scene fog density.
This has no effect if getManageSceneFog is false.
Final scene fog density is:
SceneMultiplier * GlobalMultiplier * SkyColourModel.GetFogDensity
*/
void setSceneFogDensityMultiplier (Real value);
/** Get the value set by setSceneFogDensityMultiplier.
*/
Real getSceneFogDensityMultiplier () const;
/** Set an additional multiplier for fog colour as it comes from SkyColourModel.
* This is 0.7 by default; to be compatible with previous versions.
*/
inline void setSceneFogColourMultiplier (const Ogre::ColourValue& value) { mSceneFogColourMultiplier = value; }
/// See setSceneFogColourMultiplier.
inline const Ogre::ColourValue getSceneFogColourMultiplier () const { return mSceneFogColourMultiplier; }
/** Multiplier for ground fog density (default 1).
* This is an additional multiplier for Caelum::GroundFog DepthComposer ground fog density.
*
* Final ground fog density is:
* GroundFogMultipler * GlobalMultiplier * SkyColourModel.GetFogDensity
*/
void setGroundFogDensityMultiplier (Real value);
/** Get the value set by setGroundFogDensityMultiplier.
*/
Real getGroundFogDensityMultiplier () const;
/** Set an additional multiplier for ground fog colour as it comes from SkyColourModel.
* This is OgreColour::White by default; which has no effect.
*/
inline void setGroundFogColourMultiplier (const Ogre::ColourValue& value) { mGroundFogColourMultiplier = value; }
/// See setGroundFogColourMultiplier.
inline const Ogre::ColourValue getGroundFogColourMultiplier () const { return mGroundFogColourMultiplier; }
/** Multiplier for global fog density (default 1).
* This is an additional multiplier for fog density as received from
* SkyColourModel. There are other multipliers you can tweak for
* individual kinds of fog; but this is what you should change from
* whatever "game logic" you might have.
*/
void setGlobalFogDensityMultiplier (Real value);
/** Get the value set by setSceneFogDensityMultiplier.
*/
Real getGlobalFogDensityMultiplier () const;
/** Set an additional multiplier for fog colour.
* This will also affect stuff like clouds or precipitation. Careful!
* This is OgreColour::White by default; which has no effect.
*/
inline void setGlobalFogColourMultiplier (const Ogre::ColourValue& value) { mGlobalFogColourMultiplier = value; }
/// See setGlobalFogColourMultiplier.
inline const Ogre::ColourValue getGlobalFogColourMultiplier () const { return mGlobalFogColourMultiplier; }
/** Set this to true to have CaelumSystem manage the scene's ambient light.
* The colour and AmbientMultiplier of the sun and moon are used.
* This is false by default.
*/
inline void setManageAmbientLight (bool value) { mManageAmbientLight = value; }
/// Check if CaelumSystem is managing ambient lighting.
inline bool getManageAmbientLight () const { return mManageAmbientLight; }
/** Set the minimum value for scene ambient lighting,
* This is only used if getManageAmbientLight() is true.
* By default this value is Ogre::ColourValue::Black, so it has no effect.
*/
inline void setMinimumAmbientLight (const Ogre::ColourValue &value) { mMinimumAmbientLight = value; }
/// @see setMinimumAmbientLight
inline const Ogre::ColourValue getMinimumAmbientLight () const { return mMinimumAmbientLight; }
/** Ensure only one of caelum's light sources is active at a time (the brightest).
* This uses SkyLight::setForceDisable to disable low-intensity lightsources.
* Their contribution to ambient lighting is not affected.
* This implies a single shadow caster.
* This is disabled by default; and you can tweak light disabling by yourself.
*/
inline void setEnsureSingleLightSource (bool value) { mEnsureSingleLightSource = value; }
/// See setEnsureSingleLightSource
inline bool getEnsureSingleLightSource () const { return mEnsureSingleLightSource; }
/** Ensure only one of caelum's light sources casts shadows (the brightest).
* Disabled by default.
*/
inline void setEnsureSingleShadowSource (bool value) { mEnsureSingleShadowSource = value; }
/// See setEnsureSingleShadowSource
inline bool getEnsureSingleShadowSource () const { return mEnsureSingleShadowSource; }
/** Gets the fog colour for a certain daytime.
@param time The current time.
@param sunDir The sun direction.
@return The fog colour.
*/
Ogre::ColourValue getFogColour (Real time, const Ogre::Vector3 &sunDir);
/** Gets the fog density for a certain daytime.
@param time The current time.
@param sunDir The sun direction.
@return The fog density.
*/
Real getFogDensity (Real time, const Ogre::Vector3 &sunDir);
/** Get the colour of the sun sphere.
* This colour is used to draw the sun sphere in the sky.
* @return The colour of the sun.
*/
Ogre::ColourValue getSunSphereColour (Real time, const Ogre::Vector3 &sunDir);
/** Gets the colour of sun light.
* This color is used to illuminate the scene.
* @return The colour of the sun's light
*/
Ogre::ColourValue getSunLightColour (Real time, const Ogre::Vector3 &sunDir);
/// Gets the colour of moon's body.
Ogre::ColourValue getMoonBodyColour (const Ogre::Vector3 &moonDir);
/// Gets the colour of moon's light.
Ogre::ColourValue getMoonLightColour (const Ogre::Vector3 &moonDir);
/// Set the sun gradients image.
void setSkyGradientsImage (const Ogre::String &filename = DEFAULT_SKY_GRADIENTS_IMAGE);
/// Set the sun colours image.
/// Sun colour is taken from this image.
void setSunColoursImage (const Ogre::String &filename = DEFAULT_SUN_COLOURS_IMAGE);
/** Get the sun's direction at a certain time.
* @param jday astronomical julian day.
* @see UniversalClock for julian day calculations.
*/
const Ogre::Vector3 getSunDirection (LongReal jday);
/** Get the moon's direction at a certain time.
* @param jday astronomical julian day.
*/
const Ogre::Vector3 getMoonDirection (LongReal jday);
/** Fake function to get the phase of the moon
* @param jday Julian day
* @return the phase of the moon; ranging from 0(full moon) to 2(new moon).
* The calculations performed by this function are completely fake.
* It's a triangle wave with a period of 28.5 days.
*/
const Ogre::Real getMoonPhase (LongReal jday);
private:
/** Handle FrameListener::frameStarted to call updateSubcomponents every frame.
* If you don't register CaelumSystem as a an ogre frame listener you have to
* call updateSubcomponents yourself.
*/
virtual bool frameStarted (const Ogre::FrameEvent &e);
/** Event trigger called just before rendering a viewport in a render target Caelum is attached to.
Useful to make objects follow every camera that renders a viewport in a certain render target.
*/
virtual void preViewportUpdate (const Ogre::RenderTargetViewportEvent &e);
/** Free all subcomponents, but not CaelumSystem itself. Can be called multiple times.
* @param everything To destroy things that can't be rebuilt.
*/
void destroySubcomponents (bool everything);
public:
/** Call setQueryFlags for all subcomponents now.
*
* This is not persistent; you can adjust the query masks of
* individual objects afterwards. This also means you should call
* this only after you created all other objects.
*
* Has no effect on compositor-based stuff (precipitation will still show up).
*/
void forceSubcomponentQueryFlags (uint mask);
/** Same as @see forceSubcomponentQueryMask; but for visibility
*/
void forceSubcomponentVisibilityFlags (uint mask);
};
}
#endif // CAELUM__CAELUM_SYSTEM_H

@ -1,112 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CAMERA_BOUND_ELEMENT_H
#define CAELUM__CAMERA_BOUND_ELEMENT_H
#include "CaelumPrerequisites.h"
namespace Caelum
{
/** A camera-bound element.
*
* This should be used as a base class for domes which follow the camera.
* It is only meant to be used inside Caelum.
*
* By default this class work in autoradius mode; where it automatically
* resizes itself for camera near/far clipping radius. It will correctly
* handle infinite far clip planes.
*
* This is meant to be used with depth_check and depth_write off.
* Trying to place an object "as far as possible" causes precision
* troubles; and was removed in version 0.4.
*
* If far clip distance is finite the radius will be (near + far) / 2.
* If far clip distance is infinite (0) the radius will be 10 * near/
*/
class CAELUM_EXPORT CameraBoundElement
{
private:
/// Defines if the element has an automatic "far" radius or not.
bool mAutoRadius;
public:
/** Constructor. Sets auto radius to true.
*/
CameraBoundElement();
/// Virtual Destructor.
virtual ~CameraBoundElement ();
/** Notify new camera conditions.
* This method notifies that a new camera is about to be used, so
* this element can follow it or perform other operations.
* The default implementation calls setRadius if in autoRadius mode.
* @param cam The new camera.
*/
virtual void notifyCameraChanged (Ogre::Camera *cam) = 0;
/** Forces the "far" size of the element to a specific radius.
*
* If greater than zero this disables AutoRadius mode and forces a
* fixed radius. If this is negative or zero the radius is set
* automatically in notifyCameraChanged.
*
* AutoRadius is turned on by default.
*
* @param radius The positive radius of the element, or a
* negative/zero value for AutoRadius mode.
*/
void forceFarRadius (Ogre::Real radius);
/** Checks if this element is in auto-radius mode.
* While in autoradius mode the element is automatically resized fit
* between the near and far radius.
*/
bool getAutoRadius () const;
/** Re-enable auto-radius; if disabled.
* Auto-radius is on by default; but can be disabled. This function
* can turn it back on.
*/
void setAutoRadius ();
/** Camera distances multiplier for the far clipping distance.
* This threshold will be multiplied with the far clipping distance,
* if the camera doesn't use an infinite far clipping plane.
*/
static const Ogre::Real CAMERA_FAR_DISTANCE_MULTIPLIER;
/** Camera distances multiplier for the near clipping distance.
* This threshold will be multiplied with the near clipping distance,
* if the camera does use an infinite far clipping plane.
*/
static const Ogre::Real CAMERA_NEAR_DISTANCE_MULTIPLIER;
protected:
/** Abstract method to set the radius for this elements
* Derived classes should override this and resize their domes.
* The actual radius for the dome is controlled in the base class.
*/
virtual void setFarRadius (Ogre::Real radius);
};
}
#endif // CAELUM__CAMERA_BOUND_ELEMENT_H

@ -1,89 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__CLOUD_SYSTEM_H
#define CAELUM__CLOUD_SYSTEM_H
#include "CaelumPrerequisites.h"
namespace Caelum
{
/** A cloud system is implemented by a number of cloud layers.
* Different cloud layers could implement different kinds of clouds (cirrus, stratus).
*/
class CAELUM_EXPORT CloudSystem
{
public:
CloudSystem (
Ogre::SceneManager *sceneMgr,
Ogre::SceneNode *cloudRoot);
~CloudSystem();
typedef std::vector<FlatCloudLayer*> LayerVector;
private:
Ogre::SceneManager *mSceneMgr;
Ogre::SceneNode *mCloudRoot;
LayerVector mLayers;
public:
/** Direct access to the layer vector.
*/
LayerVector& getLayerVector() { return mLayers; }
/// Clears all cloud layers.
void clearLayers();
/// Create a new cloud layer with default settings at height 0.
/// @return pointer to the new layer.
FlatCloudLayer* createLayer();
/// Create a new cloud layer with default settings at a certain height.
/// @return pointer to the new layer.
FlatCloudLayer* createLayerAtHeight(Ogre::Real height);
/// Add new layer. Takes ownership of the layer.
void addLayer(FlatCloudLayer* layer);
/// Get a pointer to a certain layer.
inline FlatCloudLayer* getLayer(int index) { return mLayers[index]; }
/// Get the total number of layers.
inline int getLayerCount() { return static_cast<int> (mLayers.size ()); }
/** Update function called every frame from high above.
*/
void update (
Ogre::Real timePassed,
const Ogre::Vector3 &sunDirection,
const Ogre::ColourValue &sunLightColour,
const Ogre::ColourValue &fogColour,
const Ogre::ColourValue &sunSphereColour);
/// Similar to @see CaelumSystem::forceSubcomponentQueryFlags.
virtual void forceLayerQueryFlags (uint flags);
/// Similar to @see CaelumSystem::forceSubcomponentVisibilityFlags.
virtual void forceLayerVisibilityFlags (uint flags);
};
}
#endif // CAELUM__CLOUD_SYSTEM_H

@ -1,280 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__DEPTH_COMPOSER_H
#define CAELUM__DEPTH_COMPOSER_H
#include "CaelumPrerequisites.h"
#include "FastGpuParamRef.h"
namespace Caelum
{
/** Compositor-based precipitation controller.
* This class will add and control precipitation controllers to viewports.
*
* Compositors clone the composing materials. This controller will
* register itself as a compositor listener and change the material in notifyMaterialSetup.
*/
class CAELUM_EXPORT DepthComposer
{
private:
Ogre::SceneManager *mSceneMgr;
void onCompositorMaterialChanged ();
const String& getCompositorName ();
protected:
inline Ogre::SceneManager* getSceneManager() const { return mSceneMgr; }
friend class DepthComposerInstance;
public:
DepthComposer(Ogre::SceneManager *sceneMgr);
virtual ~DepthComposer();
void update ();
public:
typedef std::map<Ogre::Viewport*, DepthComposerInstance*> ViewportInstanceMap;
ViewportInstanceMap mViewportInstanceMap;
public:
DepthComposerInstance* createViewportInstance(Ogre::Viewport* viewport);
void destroyViewportInstance(Ogre::Viewport* viewport);
DepthComposerInstance* getViewportInstance(Ogre::Viewport* viewport);
void destroyAllViewportInstances();
private:
bool mDebugDepthRender;
public:
/// Enables drawing the depth buffer
void setDebugDepthRender (bool value);
bool getDebugDepthRender () const { return mDebugDepthRender; }
private:
bool mSkyDomeHazeEnabled;
Ogre::Vector3 mSunDirection;
Ogre::ColourValue mHazeColour;
public:
/// Enables skydome haze.
void setSkyDomeHazeEnabled (bool value);
bool getSkyDomeHazeEnabled () const { return mSkyDomeHazeEnabled; }
void setSunDirection (const Ogre::Vector3& value) { mSunDirection = value; }
const Ogre::Vector3 getSunDirection () const { return mSunDirection; }
void setHazeColour (const Ogre::ColourValue& value) { mHazeColour = value; }
const Ogre::ColourValue getHazeColour () const { return mHazeColour; }
private:
bool mGroundFogEnabled;
Real mGroundFogDensity;
Real mGroundFogBaseLevel;
Real mGroundFogVerticalDecay;
Ogre::ColourValue mGroundFogColour;
public:
/// Enables exponential ground fog.
void setGroundFogEnabled (bool value);
bool getGroundFogEnabled () const { return mGroundFogEnabled; }
/// Sets ground fog density
void setGroundFogDensity (Real value) { mGroundFogDensity = value; }
/// Get ground fog density
Real getGroundFogDensity () const { return mGroundFogDensity; }
/// Sets ground fog level
/// At ground level fogginess is equal to GroundFogDensity
void setGroundFogBaseLevel (Real value) { mGroundFogBaseLevel = value; }
/// Get ground fog density
Real getGroundFogBaseLevel () const { return mGroundFogBaseLevel; }
/// Sets ground fog vertical decay
void setGroundFogVerticalDecay (Real value) { mGroundFogVerticalDecay = value; }
/// Get ground fog density
Real getGroundFogVerticalDecay () const { return mGroundFogVerticalDecay; }
/// Sets ground fog colour
void setGroundFogColour (const Ogre::ColourValue& value) { mGroundFogColour = value; }
/// Get ground fog colour
const Ogre::ColourValue getGroundFogColour () const { return mGroundFogColour; }
};
/** Per-viewport instance of @see DepthComposer
* This will create and control one ogre::CompositorInstance.
*/
class CAELUM_EXPORT DepthComposerInstance: private Ogre::CompositorInstance::Listener
{
private:
DepthComposer* mParent;
Ogre::Viewport* mViewport;
Ogre::CompositorInstance* mCompInst;
std::auto_ptr<DepthRenderer> mDepthRenderer;
virtual void notifyMaterialSetup(uint pass_id, Ogre::MaterialPtr &mat);
virtual void notifyMaterialRender(uint pass_id, Ogre::MaterialPtr &mat);
struct Params {
void setup(Ogre::GpuProgramParametersSharedPtr params);
Ogre::GpuProgramParametersSharedPtr fpParams;
FastGpuParamRef invViewProjMatrix;
FastGpuParamRef worldCameraPos;
FastGpuParamRef groundFogDensity;
FastGpuParamRef groundFogVerticalDecay;
FastGpuParamRef groundFogBaseLevel;
FastGpuParamRef groundFogColour;
FastGpuParamRef sunDirection;
FastGpuParamRef hazeColour;
} mParams;
protected:
/// Called from DepthComposer::update
void _update ();
void addCompositor ();
void removeCompositor ();
bool isCompositorEnabled () { return mCompInst != 0; }
friend class DepthComposer;
public:
/// Get parent DepthComposer; with all the interesting parameters.
DepthComposer* getParent() const { return mParent; }
/// Get the viewport this instance is attached to.
Ogre::Viewport* getViewport() const { return mViewport; }
/// Get compositor instance; attached to the viewport.
Ogre::CompositorInstance* getCompositorInstance() const { return mCompInst; }
/** Get the underlying depth renderer.
* Allow the user to tweak the depth renderer.
*/
Caelum::DepthRenderer* getDepthRenderer () const { return mDepthRenderer.get(); }
DepthComposerInstance(DepthComposer* parent, Ogre::Viewport* view);
virtual ~DepthComposerInstance();
};
/** Render the depth buffer to a texture.
*
* This class tries to be as generic and flexible as possible; but it
* is currently only used by the depth composer.
*/
class CAELUM_EXPORT DepthRenderer: private Ogre::RenderQueue::RenderableListener
{
private:
Ogre::Viewport* mMasterViewport;
Ogre::Viewport* mDepthRenderViewport;
Ogre::TexturePtr mDepthRenderTexture;
bool mDepthRenderingNow;
Ogre::MaterialPtr mDepthRenderMaterial;
// Override materials during all rendering.
#if OGRE_VERSION < 0x00010600
virtual bool renderableQueued(
Ogre::Renderable* rend,
Ogre::uint8 groupId,
Ogre::ushort priority,
Ogre::Technique** ppTech);
#else
virtual bool renderableQueued(
Ogre::Renderable* rend,
Ogre::uint8 groupId,
Ogre::ushort priority,
Ogre::Technique** ppTech,
Ogre::RenderQueue* pQueue);
#endif // OGRE_VERSION
inline Ogre::Material* getDepthRenderMaterial() const { return mDepthRenderMaterial.get(); }
int mMinRenderGroupId;
int mMaxRenderGroupId;
int mViewportVisibilityMask;
public:
DepthRenderer (Ogre::Viewport* viewport);
~DepthRenderer ();
inline Ogre::Viewport* getMasterViewport() { return mMasterViewport; }
inline Ogre::Texture* getDepthRenderTexture () { return mDepthRenderTexture.get(); }
inline Ogre::Viewport* getDepthRenderViewport () { return mDepthRenderViewport; }
inline Ogre::RenderTexture* getDepthRenderTarget () {
return mDepthRenderTexture->getBuffer()->getRenderTarget ();
}
/// Render the depth buffer now!
void update ();
/** Render only the render groups in a certain range.
* Call this to only render objects in certain render queue groups.
* The range is inclusive.
* This is a very primitive sort of filter.
*/
void setRenderGroupRangeFilter (int minGroup, int maxGroup);
/// @see setRenderGroupRangeFilter
int getRenderGroupRangeFilterMin () { return mMinRenderGroupId; }
int getRenderGroupRangeFilterMax () { return mMaxRenderGroupId; }
/** Disable the effects of @see setRenderGroupRangeFilter
*/
void disableRenderGroupRangeFilter ();
/** Query mask for the depth rendering viewport.
* Enforces on every update ();
*/
void setViewportVisibilityMask (uint value) { mViewportVisibilityMask = value; }
uint getViewportVisibilityMask () { return mViewportVisibilityMask; }
void disableViewportVisibilityMask () { mViewportVisibilityMask = ~0; }
public:
/** If true then use a user-supplied material scheme which outputs depth.
*
* The depth output of most materials is obvious and can be guessed most of the time.
* When that fails you can provide a custom material scheme for certain materials which
* renders the depth buffer.
*
* This is enabled by default for a scheme called CaelumDepth.
*/
inline void setUseCustomDepthScheme (bool value) { mUseCustomDepthScheme = value; }
inline bool getUseCustomDepthScheme () { return mUseCustomDepthScheme; }
/** Set the name of the custom depth scheme (default is CaelumDepth).
*/
inline void setCustomDepthSchemeName (const Ogre::String& value) { mCustomDepthSchemeName = value; }
inline const Ogre::String& getCustomDepthSchemeName () { return mCustomDepthSchemeName; }
/// Default name of the custom scheme.
static const String DEFAULT_CUSTOM_DEPTH_SCHEME_NAME;
private:
bool mUseCustomDepthScheme;
Ogre::String mCustomDepthSchemeName;
};
}
#endif // CAELUM__DEPTH_COMPOSER_H

@ -1,143 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2009 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__FAST_GPU_PARAM_REF_H
#define CAELUM__FAST_GPU_PARAM_REF_H
#include "CaelumPrerequisites.h"
namespace Caelum
{
/** @file */
/** Controls if FastGpuParamRef checks pointer match when setting.
* This setting trades safety for performance. By default it's equal to OGRE_DEBUG_MODE.
*/
#define CAELUM_DEBUG_PARAM_REF OGRE_DEBUG_MODE
/** An optimized reference to a gpu shared parameter.
*
* Profiling shows that GpuProgramParameters::_findNamedConstantDefinition is not free.
*
* This class avoids hash lookups when updating. It's uses no additional
* memory than if you were to implement the same thing manually.
*
* You must also keep the matching Ogre::GpuProgramParametersSharedPtr
* and send it whenever you call FastGpuParamRef::set. This is required
* to save memory in release mode. Debug mode checks the pointer you
* pass to set is the same as the pointer you called bind on; but uses more memory.
*
* Also; please note that fetching gpu params from a material every frame is not free either.
*/
class CAELUM_EXPORT FastGpuParamRef
{
public:
/// Default constructor. Starts as unbound
FastGpuParamRef(): mPhysicalIndex(InvalidPhysicalIndex)
{
// mParams needs no initialization; SharedPtrs start as 0.
}
/// Create and bind.
FastGpuParamRef(Ogre::GpuProgramParametersSharedPtr paramsPtr, const Ogre::String& name);
/** Bind to a certain parameter.
*
* @param paramsPtr params to bind to. Can't be null; you must unbind explicitly.
* @param name The name of the parameter to bind.
* @param throwIfNotFound Argument to GpuProgramParameters::_findNamedConstantDefinition.
*
* If throwIfNotFound is false (the default) missing parameters are
* ignored and the param ref will remand unbound. Calling set will
* then have no effect.
*/
void bind(
Ogre::GpuProgramParametersSharedPtr paramsPtr,
const Ogre::String& name,
bool throwIfNotFound = false);
/** Unbind ParamRef.
*
* If CAELUM_DEBUG_PARAM_REF is 1 this will also release the hold
* on GpuProgramParametersSharedPtr.
*/
void unbind();
/// Return if this param ref is bound to an actual param.
inline bool isBound() const { return mPhysicalIndex != InvalidPhysicalIndex; }
/// Return the physical index. Only valid if this->isBound().
inline size_t getPhysicalIndex () const { return mPhysicalIndex; }
protected:
/** Set the value. No effect if !this->isBound()
*
* @param params Parameter pointer. Can't be null
* @param arg Argument to set.
*
* Will check params pointer matches the bound pointer if #CAELUM_DEBUG_PARAM_REF.
* Otherwise a mismatched params pointer can result in memory corruption.
*/
template<typename ArgumentT>
inline void doSet(const Ogre::GpuProgramParametersSharedPtr& params, ArgumentT arg) const {
#if CAELUM_DEBUG_PARAM_REF
assert(params.getPointer() == mParams.getPointer());
#endif
assert(!params.isNull());
if (mPhysicalIndex != InvalidPhysicalIndex) {
params->_writeRawConstant(mPhysicalIndex, arg);
}
}
template<typename ArgumentT>
inline void doSet(const Ogre::GpuProgramParametersSharedPtr& params, ArgumentT arg, size_t count) const {
#if CAELUM_DEBUG_PARAM_REF
assert(params.getPointer() == mParams.getPointer());
#endif
assert(!params.isNull());
if (mPhysicalIndex != InvalidPhysicalIndex) {
params->_writeRawConstant(mPhysicalIndex, arg, count);
}
}
public:
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, int val) const { doSet<int>(params, val); }
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, Ogre::Real val) const { doSet<Ogre::Real>(params, val); }
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, const Ogre::Vector3& val) const { doSet<const Ogre::Vector3&>(params, val); }
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, const Ogre::Vector4& val) const { doSet<const Ogre::Vector4&>(params, val); }
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, const Ogre::ColourValue& val) const { doSet<const Ogre::ColourValue&>(params, val); }
/// @copydoc FastGpuParamRef::doSet
inline void set(const Ogre::GpuProgramParametersSharedPtr& params, const Ogre::Matrix4& val) const { doSet<const Ogre::Matrix4*>(params, &val, 1); }
private:
#if CAELUM_DEBUG_PARAM_REF
Ogre::GpuProgramParametersSharedPtr mParams;
#endif
static const size_t InvalidPhysicalIndex = 0xFFFFFFFF;
size_t mPhysicalIndex;
};
}
#endif /* CAELUM__FAST_GPU_PARAM_REF_H */

@ -1,366 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__FLAT_CLOUD_LAYER_H
#define CAELUM__FLAT_CLOUD_LAYER_H
#include "CaelumPrerequisites.h"
#include "InternalUtilities.h"
#include "PrivatePtr.h"
#include "FastGpuParamRef.h"
namespace Caelum
{
/** A flat cloud layer; drawn as a simple plane.
* Supports movement and variable cloud cover.
*
* There are significant incompatible difference between this and the
* LayeredClouds from version 0.3. This implementation of clouds is
* positioned in world space while the old implementation was a curved
* plane moving with the camera. It is not possible to perfectly simulate
* the older implementation.
*
* @note This is tighly integrated with LayeredCloud.cg and LayeredClouds.material.
*/
class CAELUM_EXPORT FlatCloudLayer
{
public:
FlatCloudLayer(
Ogre::SceneManager *sceneMgr,
Ogre::SceneNode *cloudRoot);
~FlatCloudLayer();
/** Update function called each frame from above.
* This can be reproduced with calls to other public functions.
*/
void update (
Ogre::Real timePassed,
const Ogre::Vector3 &sunDirection,
const Ogre::ColourValue &sunLightColour,
const Ogre::ColourValue &fogColour,
const Ogre::ColourValue &sunSphereColour);
/// Advance cloud animation (the time part of FlatCloudLayer::update).
void advanceAnimation (Ogre::Real timePassed);
/** Reset most tweak settings to their default values
*/
void reset ();
private:
Ogre::Vector2 mCloudSpeed;
Ogre::Vector2 mCloudMassOffset;
Ogre::Vector2 mCloudDetailOffset;
// Set texture offsets.
// Animated every frame.
void setCloudMassOffset(const Ogre::Vector2 &cloudMassOffset);
void setCloudDetailOffset(const Ogre::Vector2 &cloudDetailOffset);
public:
/** Sets cloud movement speed.
* @param cloudSpeed Cloud movement speed.
*/
void setCloudSpeed (const Ogre::Vector2 &cloudSpeed);
/** Gets cloud movement speed.
* @param cloudSpeed Cloud movement speed.
*/
const Ogre::Vector2 getCloudSpeed () const { return mCloudSpeed; }
private:
Ogre::Vector3 mSunDirection;
Ogre::ColourValue mSunLightColour;
Ogre::ColourValue mSunSphereColour;
Ogre::ColourValue mFogColour;
public:
void setSunDirection(const Ogre::Vector3 &sunDirection);
void setSunLightColour(const Ogre::ColourValue &sunLightColour);
void setSunSphereColour(const Ogre::ColourValue &sunSphereColour);
void setFogColour(const Ogre::ColourValue &fogColour);
const Ogre::Vector3 getSunDirection () const;
const Ogre::ColourValue getSunLightColour () const;
const Ogre::ColourValue getSunSphereColour () const;
const Ogre::ColourValue getFogColour () const;
private:
/// Pointer to scene manager.
Ogre::SceneManager *mSceneMgr;
// Note: objects are destroyed in reverse order of declaration.
// This means that objects must be ordered by dependency.
/// Cloned cloud material.
PrivateMaterialPtr mMaterial;
struct Params
{
void setup(Ogre::GpuProgramParametersSharedPtr fpParams, Ogre::GpuProgramParametersSharedPtr vpParams);
Ogre::GpuProgramParametersSharedPtr vpParams;
Ogre::GpuProgramParametersSharedPtr fpParams;
FastGpuParamRef cloudCoverageThreshold;
FastGpuParamRef cloudMassOffset;
FastGpuParamRef cloudDetailOffset;
FastGpuParamRef cloudMassBlend;
FastGpuParamRef vpSunDirection;
FastGpuParamRef fpSunDirection;
FastGpuParamRef sunLightColour;
FastGpuParamRef sunSphereColour;
FastGpuParamRef fogColour;
FastGpuParamRef layerHeight;
FastGpuParamRef cloudUVFactor;
FastGpuParamRef heightRedFactor;
FastGpuParamRef nearFadeDist;
FastGpuParamRef farFadeDist;
FastGpuParamRef fadeDistMeasurementVector;
} mParams;
private:
PrivateMeshPtr mMesh;
PrivateSceneNodePtr mNode;
PrivateEntityPtr mEntity;
// Mesh parameters.
bool mMeshDirty;
Real mMeshWidth, mMeshHeight;
int mMeshWidthSegments, mMeshHeightSegments;
public:
/** Regenerate the plane mesh and recreate entity.
* This automatically happens in update.
*/
void _ensureGeometry();
/** Regenerate the plane mesh and recreate entity.
* This automatically happens when mesh parameters are changed.
*/
void _invalidateGeometry();
/** Reset all mesh parameters.
*/
void setMeshParameters (
Real meshWidth, Real meshHeight,
int meshWidthSegments, int meshHeightSegments);
/// @see setMeshParameters
inline void setMeshWidth (Real value) { mMeshWidth = value; _invalidateGeometry (); }
inline void setMeshHeight (Real value) { mMeshHeight = value; _invalidateGeometry (); }
inline void setMeshWidthSegments (int value) { mMeshWidthSegments = value; _invalidateGeometry (); }
inline void setMeshHeightSegments (int value) { mMeshHeightSegments = value; _invalidateGeometry (); }
inline Real getMeshWidth () const { return mMeshWidth; }
inline Real getMeshHeight () const { return mMeshHeight; }
inline int getMeshWidthSegments () const { return mMeshWidthSegments; }
inline int getMeshHeightSegments () const { return mMeshHeightSegments; }
private:
/// Lookup used for cloud coverage, @see setCloudCoverLookup.
std::auto_ptr<Ogre::Image> mCloudCoverLookup;
/// Filename of mCloudCoverLookup
Ogre::String mCloudCoverLookupFileName;
/// Value passed to setCloudCover (before lookup).
Ogre::Real mCloudCover;
public:
/** Sets cloud cover, between 0 (completely clear) and 1 (completely covered)
* @param cloudCover Cloud cover between 0 and 1
*/
void setCloudCover (const Ogre::Real cloudCover);
/** Gets the current cloud cover.
* @return Cloud cover, between 0 and 1
*/
inline Ogre::Real getCloudCover () const { return mCloudCover; }
/** Set the image used to lookup the cloud coverage threshold.
* This image is used to calculate the cloud coverage threshold
* based on the desired cloud cover.
*
* The cloud coverage threshold is substracted from cloud intensity
* at any point; to generate fewer or more clouds. That threshold is
* not linear, a lookup is required to ensure that setCloudCover(0.1)
* will actually have 10% the clouds at setCloudCover(1).
*
* The lookup is the inverse of the sum on the histogram, and was
* calculated with a small hacky tool.
*/
void setCloudCoverLookup (const Ogre::String& fileName);
/** Get the filename of the cloud cover lookup image.
* This returns the value set by setCloudCoverLookup or an empty
* string if disabled.
*/
const Ogre::String getCloudCoverLookupFileName () const;
/** Disable any cloud cover lookup.
* @see setCloudCoverLookup.
*/
void disableCloudCoverLookup ();
private:
Ogre::Real mCloudCoverVisibilityThreshold;
protected:
/** Enforce setCloudCoverVisibilityThreshold.
*/
void _updateVisibilityThreshold ();
public:
/// Get cloud cover visiblity threshold.
/// Beneath this cloud coverage nothing is drawn anymore.
Ogre::Real getCloudCoverVisibilityThreshold () const { return mCloudCoverVisibilityThreshold; }
/** Set cloud cover visiblity threshold.
*
* Beneath this cloud coverage nothing is drawn anymore.
* Default value is very very low (0.001). All this does is save you from
* destroying/recreating layers when they're too thin to bother drawing.
*/
void setCloudCoverVisibilityThreshold (const Ogre::Real value);
private:
/// Height of this cloud layer; equal to node's y position.
Ogre::Real mHeight;
public:
/** Set the height of the cloud layer.
* @param height In world units above the cloud root node.
*/
void setHeight(Ogre::Real height);
/** Get the height of the cloud layer.
* @return height In world units above the cloud root node.
*/
Ogre::Real getHeight() const;
private:
/// Current cloud blend position; from 0 to mNoiseTextureNames.size()
Ogre::Real mCloudBlendPos;
/// Current index in the set of textures.
/// Cached to avoid setting textures every frame.
int mCurrentTextureIndex;
/// Time required to blend two cloud shapes.
Ogre::Real mCloudBlendTime;
/// Names of noise textures.
std::vector<String> mNoiseTextureNames;
public:
/** Sets the time it takes to blend two cloud shaped together, in seconds.
* This will also reset the animation at the current time.
* @param value Cloud shape blend time in seconds
*/
void setCloudBlendTime (const Ogre::Real value);
/** Gets the time it takes to blend two cloud shaped together, in seconds.
* @return Cloud shape blend time in seconds
*/
Ogre::Real getCloudBlendTime () const;
/** Set the current blending position; between noise textures.
* Integer values are used for single textures. Float values blend between two textures.
* Values outside [0, textureCount) are wrapped around.
* @param value New cloud blending position
*/
void setCloudBlendPos (const Ogre::Real value);
/// @see setCloudBlendPos
Ogre::Real getCloudBlendPos () const;
private:
Ogre::Real mCloudUVFactor;
public:
/** Cloud texture coordinates are multiplied with this.
* Higher values result in more spread-out clouds.
* Very low value result in ugly texture repeats.
*/
void setCloudUVFactor (const Ogre::Real value);
/// @see setCloudUVFactor
inline Ogre::Real getCloudUVFactor () const { return mCloudUVFactor; }
private:
Ogre::Real mHeightRedFactor;
public:
/** High-altitude clouds are tinted red in the evening.
* Higher values attenuate the effect.
*/
void setHeightRedFactor (const Ogre::Real value);
/// @see setCloudUVFactor
Ogre::Real getHeightRedFactor () const { return mHeightRedFactor; }
private:
Ogre::Real mNearFadeDist;
Ogre::Real mFarFadeDist;
Ogre::Vector3 mFadeDistMeasurementVector;
public:
/** Cloud fade distances.
*
* These are measured horizontally in meters (height is not used).
*
* The effect is a fade based on alpha blending which occurs between
* nearValue and farValue. After farValue nothing is visibile from
* this layer.
*
* Default values are 10000 and 140000
*/
void setFadeDistances (Ogre::Real nearValue, Ogre::Real farValue);
/// Set only near fade distance (see setFadeDistances).
void setNearFadeDist (const Ogre::Real value);
/// Get near fade distance (see setFadeDistances).
Ogre::Real getNearFadeDist () const { return mNearFadeDist; }
/// Set only far fade distance (see setFadeDistances).
void setFarFadeDist (const Ogre::Real value);
/// Get fade distance (see setFadeDistances).
Ogre::Real getFarFadeDist () const { return mFarFadeDist; }
/** Set on which components is the fade distance measured.
*
* Default is Vector3(0, 1, 1) which measures fade distance
* horizontally in caelum's default assumed coordinate system.
*
* If you're in a Z-up system you probably want to set this to (1, 1, 0).
*
* Fade distance is always measured relative to the camera.
*/
void setFadeDistMeasurementVector (const Ogre::Vector3& value);
/// Get the value set by setFadeDistMeasurementVector.
const Ogre::Vector3 getFadeDistMeasurementVector () const { return mFadeDistMeasurementVector; }
public:
void setQueryFlags (uint flags) { mEntity->setQueryFlags (flags); }
uint getQueryFlags () const { return mEntity->getQueryFlags (); }
void setVisibilityFlags (uint flags) { mEntity->setVisibilityFlags (flags); }
uint getVisibilityFlags () const { return mEntity->getVisibilityFlags (); }
};
}
#endif // CAELUM__FLAT_CLOUD_LAYER_H

@ -1,202 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2007 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GROUNDFOG_H
#define GROUNDFOG_H
#include "CaelumPrerequisites.h"
#include "CameraBoundElement.h"
#include "PrivatePtr.h"
#include "FastGpuParamRef.h"
namespace Caelum
{
/** Exponential ground fog system implementation.
*
* This class controls CaelumGroundFog passes in a potentially large number
* of materials, changing shader program parameters. This class keeps a list
* of passes to control; which can be build based on pass name.
*
* This simulates a field of fog where "absorption" at a certain point is
* exp(-verticalDecay * (h - fogLevel)). This absorption is multiplicative,
* the total fog alpha is e^(-density * absorption_on_view_path).
*
* You can set verticalDecay to 0 and get standard GL_EXP fog. Don't actually
* do that though because you'll get a division by 0.
*
* @note: This is deprecated starting from Caelum 0.4. The DepthComposer class
* provides similar functionality with less intrusion on your materials.
*/
class CAELUM_EXPORT GroundFog: public CameraBoundElement
{
public:
static const Ogre::String DEFAULT_PASS_NAME;
/** Constructor.
*/
GroundFog (Ogre::SceneManager *scene,
Ogre::SceneNode *caelumRootNode,
const Ogre::String &domeMaterialName = "CaelumGroundFogDome",
const Ogre::String &domeEntityName = "CaelumGroundFogDome");
/** Virtual destructor.
*/
virtual ~GroundFog ();
/** Typedef for easier manipulation of a set of Passes.
*/
typedef std::set<Ogre::Pass *> PassSet;
/** Get the set of currently controlled passes.
* This is provided if you really want to change the set by hand.
* You should call forceUpdate after modifying this set.
*/
PassSet& getPasses();
/** Get the set of currently controlled passes.
* This is a const overload which doesn't let you modify the
* underlying collection.
*/
const PassSet& getPasses () const;
/** Find caelum fog passes to control by name.
* By default this looks for passes called "CaleumGroundFog".
* @note This calls forceUpdate()
*/
void findFogPassesByName (const Ogre::String& passName = DEFAULT_PASS_NAME);
/// Sets the fog density multiplier
void setDensity (Ogre::Real density);
/// Get the fog density multiplier
Ogre::Real getDensity () const;
/// Sets fog colour
void setColour (const Ogre::ColourValue &colour);
/// Gets fog colour
const Ogre::ColourValue getColour () const;
/// Sets the vertical fog decay constant.
void setVerticalDecay (Ogre::Real verticalDecay);
/// Get the vertical fog decay constant.
Ogre::Real getVerticalDecay () const;
/** Sets the ground level.
* At ground level 'fogginess' is equal to 1.
*/
void setGroundLevel (Ogre::Real GroundLevela);
/** Get the ground level.
*/
Ogre::Real getGroundLevel () const;
/** Forces an update of all the passes. You have to use this if you modify
* the set of passes by hand, otherwise avoid it.
*/
void forceUpdate ();
private:
/// Cached Density
Ogre::Real mDensity;
/// Cached VerticalDecay
Ogre::Real mVerticalDecay;
/// Cached GroundLevel
Ogre::Real mGroundLevel;
/// Fog colour
Ogre::ColourValue mFogColour;
private:
/// The scene to control fog in.
Ogre::SceneManager* mScene;
/// Sky dome material
PrivateMaterialPtr mDomeMaterial;
/// Sky dome node
PrivateSceneNodePtr mDomeNode;
/// Sky dome entity
PrivateEntityPtr mDomeEntity;
// Called whenever something changes to update the sky dome.
void updateSkyFogging();
protected:
/// Handle far radius.
virtual void setFarRadius (Ogre::Real radius);
public:
/// Handle camera change.
virtual void notifyCameraChanged (Ogre::Camera *cam);
void setQueryFlags (uint flags) { mDomeEntity->setQueryFlags (flags); }
uint getQueryFlags () const { return mDomeEntity->getQueryFlags (); }
void setVisibilityFlags (uint flags) { mDomeEntity->setVisibilityFlags (flags); }
uint getVisibilityFlags () const { return mDomeEntity->getVisibilityFlags (); }
private:
/// The passes to control.
PassSet mPasses;
/// Params references.
struct FogParamsBase
{
void setup(Ogre::GpuProgramParametersSharedPtr fpParams);
Ogre::GpuProgramParametersSharedPtr fpParams;
FastGpuParamRef fogDensity;
FastGpuParamRef fogColour;
FastGpuParamRef fogVerticalDecay;
FastGpuParamRef fogGroundLevel;
};
struct DomeFogParams: public FogParamsBase {
void setup(Ogre::GpuProgramParametersSharedPtr fpParams);
FastGpuParamRef cameraHeight;
} mDomeParams;
struct PassFogParams: public FogParamsBase {
PassFogParams(Ogre::GpuProgramParametersSharedPtr fpParams) { setup(fpParams); }
static inline bool lessThanByParams(const PassFogParams& a, const PassFogParams& b) {
return a.fpParams.get() <= b.fpParams.get();
}
static inline bool equalByParams(const PassFogParams& a, const PassFogParams& b) {
return a.fpParams.get() == b.fpParams.get();
}
};
typedef std::vector<PassFogParams> PassFogParamsVector;
PassFogParamsVector mPassFogParams;
/// Update mPassFogParams based on mPasses
void updatePassFogParams();
};
}
#endif //GROUNDFOG_H

@ -1,102 +0,0 @@
/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAELUM__IMAGE_STARFIELD_H
#define CAELUM__IMAGE_STARFIELD_H
#include "CaelumPrerequisites.h"
#include "CameraBoundElement.h"
#include "PrivatePtr.h"
namespace Caelum
{
/** Image-based starfield class.
* This class implements a starfield based on mapping a single large
* texture on a sphere. @see PointStarfield for a better solution.
*/
class CAELUM_EXPORT ImageStarfield : public CameraBoundElement
{
protected:
/// Reference to the dome node.
PrivateSceneNodePtr mNode;
/// Reference to the (cloned) starfield material.
PrivateMaterialPtr mStarfieldMaterial;
/// Reference to the dome entity.
PrivateEntityPtr mEntity;
/// Name of the spheric dome resource.
static const Ogre::String STARFIELD_DOME_NAME;
/// Name of the starfield material.
static const Ogre::String STARFIELD_MATERIAL_NAME;
/** Inclination of the starfield.
*/
Ogre::Degree mInclination;
public:
static const String DEFAULT_TEXTURE_NAME;
/** Constructor.
@param sceneMgr The scene manager this dome will belong to.
*/
ImageStarfield (
Ogre::SceneManager *sceneMgr,
Ogre::SceneNode *caelumRootNode,
const Ogre::String &textureName = DEFAULT_TEXTURE_NAME);
/** Destructor.
*/
virtual ~ImageStarfield ();
/** Sets the starfield inclination. This inclination is the angle between the starfield rotation axis and the horizon plane.
@param inc The starfield inclination in degrees. It`s equal to observer latitude taken with opposite sign.
*/
void setInclination (Ogre::Degree inc);
/** Updates the starfield position/orientation.
@param time Local time in [0, 1] range.
*/
void update (const float time);
/** Updates the starfield material.
@param mapName The new starfield texture map name.
*/
void setTexture (const Ogre::String &mapName);
public:
/// Handle camera change.
virtual void notifyCameraChanged (Ogre::Camera *cam);
protected:
/// Handle far radius.
virtual void setFarRadius (Ogre::Real radius);
public:
void setQueryFlags (uint flags) { mEntity->setQueryFlags (flags); }
uint getQueryFlags () const { return mEntity->getQueryFlags (); }
void setVisibilityFlags (uint flags) { mEntity->setVisibilityFlags (flags); }
uint getVisibilityFlags () const { return mEntity->getVisibilityFlags (); }
};
}
#endif // CAELUM__IMAGE_STARFIELD_H

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save