mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:56:39 +00:00 
			
		
		
		
	Merge branch 'master' into dialogue
Conflicts: apps/openmw/mwscript/docs/vmformat.txt
This commit is contained in:
		
						commit
						4bdfbb6d4f
					
				
					 208 changed files with 4769 additions and 25129 deletions
				
			
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -7,6 +7,9 @@ Docs/mainpage.hpp | |||
| CMakeFiles | ||||
| */CMakeFiles | ||||
| CMakeCache.txt | ||||
| moc_*.cxx | ||||
| cmake_install.cmake | ||||
| *.[ao] | ||||
| Makefile | ||||
| makefile | ||||
| data | ||||
|  |  | |||
							
								
								
									
										204
									
								
								CMakeLists.txt
									
									
									
									
									
								
							
							
						
						
									
										204
									
								
								CMakeLists.txt
									
									
									
									
									
								
							|  | @ -1,11 +1,13 @@ | |||
| project(OpenMW) | ||||
| 
 | ||||
| IF (APPLE) | ||||
|     set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/OpenMW.app") | ||||
| if (APPLE) | ||||
|     set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app") | ||||
| 
 | ||||
|     set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}") | ||||
| 
 | ||||
|     # using 10.6 sdk | ||||
|     set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk") | ||||
| ENDIF (APPLE) | ||||
| endif (APPLE) | ||||
| 
 | ||||
| # Macros | ||||
| 
 | ||||
|  | @ -16,8 +18,8 @@ include (OpenMWMacros) | |||
| # Version | ||||
| 
 | ||||
| set (OPENMW_VERSION_MAJOR 0) | ||||
| set (OPENMW_VERSION_MINOR 11) | ||||
| set (OPENMW_VERSION_RELEASE 1) | ||||
| set (OPENMW_VERSION_MINOR 12) | ||||
| set (OPENMW_VERSION_RELEASE 0) | ||||
| 
 | ||||
| set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") | ||||
| 
 | ||||
|  | @ -94,6 +96,7 @@ source_group(libs\\mangle FILES ${MANGLE_ALL}) | |||
| set(OENGINE_OGRE | ||||
|   ${LIBDIR}/openengine/ogre/renderer.cpp | ||||
|   ${LIBDIR}/openengine/ogre/mouselook.cpp | ||||
|   ${LIBDIR}/openengine/ogre/fader.cpp | ||||
| ) | ||||
| set(OENGINE_GUI | ||||
|   ${LIBDIR}/openengine/gui/events.cpp | ||||
|  | @ -188,9 +191,8 @@ find_package(OpenAL REQUIRED) | |||
| find_package(Bullet REQUIRED) | ||||
| include_directories("." | ||||
|     ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE | ||||
|     ${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR} | ||||
|     ${OIS_INCLUDE_DIRS} ${Boost_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/OgrePlatform/include | ||||
|     ${OPENAL_INCLUDE_DIR} | ||||
|  | @ -200,7 +202,14 @@ include_directories("." | |||
| 
 | ||||
| link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR}) | ||||
| 
 | ||||
| add_subdirectory( extern/caelum ) | ||||
| if(APPLE) | ||||
|     # List used Ogre plugins | ||||
|     SET(USED_OGRE_PLUGINS "RenderSystem_GL" | ||||
|                           "Plugin_OctreeSceneManager" | ||||
|                           "Plugin_CgProgramManager" | ||||
|                           "Plugin_ParticleFX") | ||||
| endif(APPLE) | ||||
| 
 | ||||
| add_subdirectory( extern/mygui_3.0.1 ) | ||||
| 
 | ||||
| # Make sure that certain libraries are used as static libraries | ||||
|  | @ -210,9 +219,6 @@ add_subdirectory( extern/mygui_3.0.1 ) | |||
| # MyGUI: extern/mygui_3.0.0/ | ||||
| add_definitions(-DMYGUI_STATIC) | ||||
| 
 | ||||
| # Caelum: extern/caelum/ | ||||
| add_definitions(-DCAELUM_STATIC) | ||||
| 
 | ||||
| # Specify build paths | ||||
| 
 | ||||
| if (APPLE) | ||||
|  | @ -243,22 +249,17 @@ if (APPLE) | |||
|         "${OpenMW_BINARY_DIR}/plugins.cfg") | ||||
| 
 | ||||
|     configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist | ||||
|         "${APP_BUNDLE_DIR}/Contents/Info.plist" COPYONLY) | ||||
|         "${APP_BUNDLE_DIR}/Contents/Info.plist") | ||||
| 
 | ||||
|     configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns | ||||
|         "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) | ||||
| 
 | ||||
| 
 | ||||
|     # prepare plugins | ||||
|     configure_file(${OGRE_PLUGIN_DIR}/RenderSystem_GL.dylib | ||||
|         "${APP_BUNDLE_DIR}/Contents/Plugins/RenderSystem_GL.dylib" COPYONLY) | ||||
| 
 | ||||
|     configure_file(${OGRE_PLUGIN_DIR}/Plugin_OctreeSceneManager.dylib | ||||
|         "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_OctreeSceneManager.dylib" COPYONLY) | ||||
| 
 | ||||
|     configure_file(${OGRE_PLUGIN_DIR}/Plugin_ParticleFX.dylib | ||||
|         "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_ParticleFX.dylib" COPYONLY) | ||||
| 
 | ||||
|     foreach(plugin ${USED_OGRE_PLUGINS}) | ||||
|         configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib" | ||||
|                         "${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib" | ||||
|                         COPYONLY) | ||||
|     endforeach() | ||||
| endif (APPLE) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -268,36 +269,6 @@ if (CMAKE_COMPILER_IS_GNUCC) | |||
|     add_definitions (-Wall) | ||||
| endif (CMAKE_COMPILER_IS_GNUCC) | ||||
| 
 | ||||
| # Apple bundling | ||||
| # TODO REWRITE! | ||||
| if (APPLE) | ||||
|     set(MISC_FILES | ||||
|         ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg | ||||
|         ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) | ||||
| 
 | ||||
|     set(OGRE_PLUGINS | ||||
|         ${APP_BUNDLE_DIR}/Contents/Plugins/*) | ||||
| 
 | ||||
| install(FILES ${MISC_FILES} DESTINATION ../MacOS) | ||||
| install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) | ||||
| install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) | ||||
| set(CPACK_GENERATOR "Bundle") | ||||
| set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") | ||||
| set(CPACK_BUNDLE_ICON  "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") | ||||
| set(CPACK_BUNDLE_NAME "OpenMW") | ||||
| set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) | ||||
| set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) | ||||
| set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) | ||||
| set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) | ||||
| 
 | ||||
| include(CPack) | ||||
| 
 | ||||
| set(CMAKE_EXE_LINKER_FLAGS "-arch i386") | ||||
| set(CMAKE_CXX_FLAGS "-arch i386") | ||||
| 
 | ||||
| endif (APPLE) | ||||
| 
 | ||||
| 
 | ||||
| if(DPKG_PROGRAM) | ||||
|     SET(CMAKE_INSTALL_PREFIX "/usr") | ||||
| 
 | ||||
|  | @ -326,7 +297,7 @@ if(DPKG_PROGRAM) | |||
| 
 | ||||
|     SET(CPACK_GENERATOR "DEB") | ||||
|     SET(CPACK_PACKAGE_NAME "openmw") | ||||
|     SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://openmw.com") | ||||
|     SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://openmw.org") | ||||
|     SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") | ||||
|     SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "${PACKAGE_MAINTAINER}") | ||||
|     SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "A reimplementation of The Elder Scrolls III: Morrowind | ||||
|  | @ -351,6 +322,54 @@ if(DPKG_PROGRAM) | |||
|     include(CPack) | ||||
| endif(DPKG_PROGRAM) | ||||
| 
 | ||||
| if(WIN32) | ||||
|     FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*") | ||||
|     INSTALL(FILES ${files} DESTINATION ".") | ||||
|     INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") | ||||
|     INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") | ||||
| 
 | ||||
|     SET(CPACK_GENERATOR "NSIS") | ||||
|     SET(CPACK_PACKAGE_NAME "OpenMW") | ||||
|     SET(CPACK_PACKAGE_VENDOR "OpenMW.org") | ||||
|     SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) | ||||
|     SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) | ||||
|     SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) | ||||
|     SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) | ||||
|     SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher") | ||||
|     SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt") | ||||
|     SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt") | ||||
|     SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") | ||||
|     SET(CPACK_NSIS_DISPLAY_NAME "OpenMW") | ||||
|     SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") | ||||
|     SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") | ||||
|     SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") | ||||
| 
 | ||||
|     SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") | ||||
|     if(EXISTS ${VCREDIST32}) | ||||
|         INSTALL(FILES ${VCREDIST32} DESTINATION "redist") | ||||
|         SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) | ||||
|     endif(EXISTS ${VCREDIST32}) | ||||
| 
 | ||||
|     SET(VCREDIST64 "${OpenMW_BINARY_DIR}/vcredist_x64.exe") | ||||
|     if(EXISTS ${VCREDIST64}) | ||||
|         INSTALL(FILES ${VCREDIST64} DESTINATION "redist") | ||||
|         SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x64.exe\\\" /q'" ) | ||||
|     endif(EXISTS ${VCREDIST64}) | ||||
| 
 | ||||
|     SET(OALREDIST "${OpenMW_BINARY_DIR}/oalinst.exe") | ||||
|     if(EXISTS ${OALREDIST}) | ||||
|         INSTALL(FILES ${OALREDIST} DESTINATION "redist") | ||||
|         SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} | ||||
|             ExecWait '\\\"$INSTDIR\\\\redist\\\\oalinst.exe\\\" /s'" ) | ||||
|     endif(EXISTS ${OALREDIST}) | ||||
| 
 | ||||
|     if(CMAKE_CL_64) | ||||
|         SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") | ||||
|     endif() | ||||
| 
 | ||||
|     include(CPack) | ||||
| endif(WIN32) | ||||
| 
 | ||||
| # Components | ||||
| add_subdirectory (components) | ||||
| 
 | ||||
|  | @ -405,3 +424,82 @@ if (WIN32) | |||
|   #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") | ||||
|   #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") | ||||
| endif() | ||||
| 
 | ||||
| # Apple bundling | ||||
| if (APPLE) | ||||
|     set(INSTALL_SUBDIR OpenMW) | ||||
| 
 | ||||
|     install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) | ||||
|     install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) | ||||
|     install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) | ||||
| 
 | ||||
|     install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) | ||||
|     install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) | ||||
|     set(CPACK_GENERATOR "DragNDrop") | ||||
|     set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) | ||||
|     set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) | ||||
|     set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) | ||||
|     set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) | ||||
| 
 | ||||
|     set(APPS "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}") | ||||
|     set(PLUGINS "") | ||||
| 
 | ||||
|     # Scan Plugins dir for *.dylibs | ||||
|     set(PLUGIN_SEARCH_ROOT "${APP_BUNDLE_DIR}/Contents/Plugins") | ||||
|     file(GLOB_RECURSE ALL_PLUGINS "${PLUGIN_SEARCH_ROOT}/*.dylib") | ||||
| 
 | ||||
|     set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins") | ||||
|     foreach(PLUGIN ${ALL_PLUGINS}) | ||||
|         string(REPLACE "${PLUGIN_SEARCH_ROOT}/" "" PLUGIN_RELATIVE "${PLUGIN}") | ||||
|         set(PLUGINS ${PLUGINS} "${PLUGIN_INSTALL_BASE}/${PLUGIN_RELATIVE}") | ||||
|     endforeach() | ||||
| 
 | ||||
|     #For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail | ||||
|     set(DIRS "") | ||||
| 
 | ||||
|     # Overriding item resolving during installation, it needed if | ||||
|     # some library already has be "fixed up", i.e. its id name contains @executable_path, | ||||
|     # but library is not embedded in bundle. For example, it's Ogre.framework from Ogre SDK. | ||||
|     # Current implementation of GetPrerequsities/BundleUtilities doesn't handle that case. | ||||
|     # | ||||
|     # Current limitations: | ||||
|     #   1. Handles only frameworks, not simple libs | ||||
|     INSTALL(CODE " | ||||
|         set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES}) | ||||
|         set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) | ||||
|         set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH}) | ||||
| 
 | ||||
|         set(OPENMW_RESOLVED_ITEMS \"\") | ||||
| 
 | ||||
|         function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) | ||||
|             if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}}) | ||||
|                 if (item MATCHES \"Frameworks\") # if it is a framework | ||||
|                     # get last segment of path | ||||
|                     get_filename_component(fname \"\${item}\" NAME_WE) | ||||
|                     find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks) | ||||
|                     if (ri) | ||||
|                         message(STATUS \"found \${ri} for \${item}\") | ||||
|                         string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item}) | ||||
|                         set(ri \"\${ri}\${item_part}\") | ||||
|                         set(\${resolved_item_var} \${ri} PARENT_SCOPE) | ||||
|                         set(\${resolved_var} 1 PARENT_SCOPE) | ||||
|                         set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri}) | ||||
|                     endif() | ||||
|                 else() | ||||
|                     # code path for standard (non-framework) libs (ogre & qt pugins) | ||||
|                 endif() | ||||
|             endif() | ||||
|         endfunction(gp_resolve_item_override) | ||||
| 
 | ||||
|         cmake_policy(SET CMP0009 OLD) | ||||
|         set(BU_CHMOD_BUNDLE_ITEMS ON) | ||||
|         include(BundleUtilities) | ||||
|         fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\") | ||||
|         " COMPONENT Runtime) | ||||
| 
 | ||||
| include(CPack) | ||||
| 
 | ||||
| set(CMAKE_EXE_LINKER_FLAGS "-arch i386") | ||||
| set(CMAKE_CXX_FLAGS "-arch i386") | ||||
| 
 | ||||
| endif (APPLE) | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| set(ESMTOOL | ||||
|   esmtool_cmd.c | ||||
|   esmtool_cmd.h | ||||
|   esmtool.cpp | ||||
| ) | ||||
| source_group(apps\\esmtool FILES ${ESMTOOL}) | ||||
|  |  | |||
|  | @ -1,35 +1,138 @@ | |||
| #include <iostream> | ||||
| 
 | ||||
| #include <boost/program_options.hpp> | ||||
| 
 | ||||
| #include <components/esm/esm_reader.hpp> | ||||
| #include <components/esm/records.hpp> | ||||
| 
 | ||||
| #include "esmtool_cmd.h" | ||||
| 
 | ||||
| #include <iostream> | ||||
| #define ESMTOOL_VERSION 1.1 | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace ESM; | ||||
| 
 | ||||
| // Create a local alias for brevity
 | ||||
| namespace bpo = boost::program_options; | ||||
| 
 | ||||
| void printRaw(ESMReader &esm); | ||||
| 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) | ||||
|     return 1; | ||||
| bool parseOptions (int argc, char** argv, Arguments &info) | ||||
| { | ||||
|     bpo::options_description desc("Inspect and extract from Morrowind ES files (ESM, ESP, ESS)\nSyntax: esmtool [options] file \nAllowed options"); | ||||
| 
 | ||||
|   if(info.inputs_num != 1) | ||||
|     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."; | ||||
| 
 | ||||
|     // 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) | ||||
|         cout << "ERROR: missing ES file\n\n"; | ||||
|       else | ||||
|         cout << "ERROR: more than one ES file specified\n\n"; | ||||
|       cmdline_parser_print_help(); | ||||
|       return 1; | ||||
|         std::cout << desc << finalText << std::endl; | ||||
|         return false; | ||||
|     } | ||||
|     if (variables.count ("version")) | ||||
|     { | ||||
|         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; | ||||
|   const char* filename = info.inputs[0]; | ||||
|   esm.setEncoding(info.encoding); | ||||
| 
 | ||||
|   string filename = info.filename; | ||||
|   cout << "\nFile: " << filename << endl; | ||||
| 
 | ||||
|   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 */ | ||||
|  | @ -41,8 +41,10 @@ source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC | |||
| find_package(Qt4 REQUIRED) | ||||
| set(QT_USE_QTGUI 1) | ||||
| 
 | ||||
| find_package(PNG REQUIRED) | ||||
| include_directories(${PNG_INCLUDE_DIR}) | ||||
| if (NOT APPLE) # this dependency can be completely removed, but now it only tested on OS X | ||||
|     find_package(PNG REQUIRED) | ||||
|     include_directories(${PNG_INCLUDE_DIR}) | ||||
| endif() | ||||
| 
 | ||||
| QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) | ||||
| QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) | ||||
|  | @ -71,9 +73,13 @@ endif() | |||
| if (APPLE) | ||||
|     configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss | ||||
|         "${APP_BUNDLE_DIR}/../launcher.qss") | ||||
|     configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss | ||||
|     configure_file(${CMAKE_SOURCE_DIR}/files/launcher.cfg | ||||
|         "${APP_BUNDLE_DIR}/../launcher.cfg") | ||||
| else() | ||||
|     configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss | ||||
|         "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources/launcher.qss") | ||||
| 
 | ||||
|     # Fallback in case getGlobalDataPath does not point to resources | ||||
|     configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss | ||||
|         "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| #include <components/esm/esm_reader.hpp> | ||||
| #include <components/files/collections.hpp> | ||||
| #include <components/files/multidircollection.hpp> | ||||
| #include <components/cfg/configurationmanager.hpp> | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| 
 | ||||
| #include "datafilespage.hpp" | ||||
| #include "lineedit.hpp" | ||||
|  | @ -26,7 +26,9 @@ bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) | |||
|     return index1.row() <= index2.row(); | ||||
| } | ||||
| 
 | ||||
| DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent) | ||||
| DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) | ||||
|     : QWidget(parent) | ||||
|     , mCfgMgr(cfg) | ||||
| { | ||||
|     mDataFilesModel = new QStandardItemModel(); // Contains all plugins with masters
 | ||||
|     mPluginsModel = new PluginsModel(); // Contains selectable plugins
 | ||||
|  | @ -121,23 +123,88 @@ DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent) | |||
| 
 | ||||
| 
 | ||||
|     setupConfig(); | ||||
|     setupDataFiles(); | ||||
|     createActions(); | ||||
| } | ||||
| 
 | ||||
| void DataFilesPage::setupDataFiles(const QStringList &paths, bool strict) | ||||
| void DataFilesPage::setupConfig() | ||||
| { | ||||
|     // Put the paths in a boost::filesystem vector to use with Files::Collections
 | ||||
|     Files::PathContainer dataDirs; | ||||
|     QString config = QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.cfg").string()); | ||||
|     QFile file(config); | ||||
| 
 | ||||
|     foreach (const QString ¤tPath, paths) { | ||||
|         dataDirs.push_back(boost::filesystem::path(currentPath.toStdString())); | ||||
|     if (!file.exists()) { | ||||
|         config = QString::fromStdString((mCfgMgr.getUserPath() / "launcher.cfg").string()); | ||||
|     } | ||||
| 
 | ||||
|     // Open our config file
 | ||||
|     mLauncherConfig = new QSettings(config, QSettings::IniFormat); | ||||
|     mLauncherConfig->sync(); | ||||
| 
 | ||||
| 
 | ||||
|     // Make sure we have no groups open
 | ||||
|     while (!mLauncherConfig->group().isEmpty()) { | ||||
|         mLauncherConfig->endGroup(); | ||||
|     } | ||||
| 
 | ||||
|     mLauncherConfig->beginGroup("Profiles"); | ||||
|     QStringList profiles = mLauncherConfig->childGroups(); | ||||
| 
 | ||||
|     if (profiles.isEmpty()) { | ||||
|         // Add a default profile
 | ||||
|         profiles.append("Default"); | ||||
|     } | ||||
| 
 | ||||
|     mProfilesComboBox->addItems(profiles); | ||||
| 
 | ||||
|     QString currentProfile = mLauncherConfig->value("CurrentProfile").toString(); | ||||
| 
 | ||||
|     if (currentProfile.isEmpty()) { | ||||
|         // No current profile selected
 | ||||
|         currentProfile = "Default"; | ||||
|     } | ||||
|     mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(currentProfile)); | ||||
| 
 | ||||
|     mLauncherConfig->endGroup(); | ||||
| 
 | ||||
|     // Now we connect the combobox to do something if the profile changes
 | ||||
|     // This prevents strange behaviour while reading and appending the profiles
 | ||||
|     connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&))); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void DataFilesPage::setupDataFiles() | ||||
| { | ||||
|     // We use the Configuration Manager to retrieve the configuration values
 | ||||
|     boost::program_options::variables_map variables; | ||||
|     boost::program_options::options_description desc; | ||||
| 
 | ||||
|     desc.add_options() | ||||
|         ("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()) | ||||
| //        ("data-local", boost::program_options::value<std::string>()->default_value(""))
 | ||||
|         ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false)) | ||||
|         ("encoding", boost::program_options::value<std::string>()->default_value("win1252")); | ||||
| 
 | ||||
|     mCfgMgr.readConfiguration(variables, desc); | ||||
| 
 | ||||
|     // Put the paths in a boost::filesystem vector to use with Files::Collections
 | ||||
|     Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>()); | ||||
| 
 | ||||
| //    std::string local(variables["data-local"].as<std::string>());
 | ||||
| //    if (!local.empty())
 | ||||
| //    {
 | ||||
| //        dataDirs.push_back(Files::PathContainer::value_type(local));
 | ||||
| //    }
 | ||||
| 
 | ||||
|     if (dataDirs.size()>1) | ||||
|         dataDirs.resize (1); | ||||
| 
 | ||||
|     mCfgMgr.processPaths(dataDirs); | ||||
| 
 | ||||
|     // Create a file collection for the dataDirs
 | ||||
|     Files::Collections mFileCollections(dataDirs, strict); | ||||
|     Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as<bool>()); | ||||
| 
 | ||||
|      // First we add all the master files
 | ||||
|     const Files::MultiDirCollection &esm = mFileCollections.getCollection(".esm"); | ||||
|     const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); | ||||
|     unsigned int i = 0; // Row number
 | ||||
| 
 | ||||
|     for (Files::MultiDirCollection::TIter iter(esm.begin()); iter!=esm.end(); ++iter) | ||||
|  | @ -157,14 +224,14 @@ void DataFilesPage::setupDataFiles(const QStringList &paths, bool strict) | |||
|     } | ||||
| 
 | ||||
|     // Now on to the plugins
 | ||||
|     const Files::MultiDirCollection &esp = mFileCollections.getCollection(".esp"); | ||||
|     const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp"); | ||||
| 
 | ||||
|     for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) | ||||
|     { | ||||
|         ESMReader fileReader; | ||||
|         QStringList availableMasters; // Will contain all found masters
 | ||||
| 
 | ||||
|         fileReader.setEncoding("win1252"); // FIXME: This should be configurable!
 | ||||
|         fileReader.setEncoding(variables["encoding"].as<std::string>()); | ||||
|         fileReader.open(iter->second.string()); | ||||
| 
 | ||||
|         // First we fill the availableMasters and the mMastersWidget
 | ||||
|  | @ -234,54 +301,6 @@ void DataFilesPage::setupDataFiles(const QStringList &paths, bool strict) | |||
|     readConfig(); | ||||
| } | ||||
| 
 | ||||
| void DataFilesPage::setupConfig() | ||||
| { | ||||
|     Cfg::ConfigurationManager cfg; | ||||
| 
 | ||||
|     QString config = (cfg.getRuntimeConfigPath() / "launcher.cfg").string().c_str(); | ||||
|     QFile file(config); | ||||
| 
 | ||||
|     if (!file.exists()) { | ||||
|         config = QString::fromStdString((cfg.getLocalConfigPath() / "launcher.cfg").string()); | ||||
|     } | ||||
| 
 | ||||
|     file.setFileName(config); // Just for displaying information
 | ||||
| 
 | ||||
|     // Open our config file
 | ||||
|     mLauncherConfig = new QSettings(config, QSettings::IniFormat); | ||||
|     mLauncherConfig->sync(); | ||||
| 
 | ||||
| 
 | ||||
|     // Make sure we have no groups open
 | ||||
|     while (!mLauncherConfig->group().isEmpty()) { | ||||
|         mLauncherConfig->endGroup(); | ||||
|     } | ||||
| 
 | ||||
|     mLauncherConfig->beginGroup("Profiles"); | ||||
|     QStringList profiles = mLauncherConfig->childGroups(); | ||||
| 
 | ||||
|     if (profiles.isEmpty()) { | ||||
|         // Add a default profile
 | ||||
|         profiles.append("Default"); | ||||
|     } | ||||
| 
 | ||||
|     mProfilesComboBox->addItems(profiles); | ||||
| 
 | ||||
|     QString currentProfile = mLauncherConfig->value("CurrentProfile").toString(); | ||||
| 
 | ||||
|     if (currentProfile.isEmpty()) { | ||||
|         // No current profile selected
 | ||||
|         currentProfile = "Default"; | ||||
|     } | ||||
|     mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(currentProfile)); | ||||
| 
 | ||||
|     mLauncherConfig->endGroup(); | ||||
| 
 | ||||
|     // Now we connect the combobox to do something if the profile changes
 | ||||
|     // This prevents strange behaviour while reading and appending the profiles
 | ||||
|     connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&))); | ||||
| } | ||||
| 
 | ||||
| void DataFilesPage::createActions() | ||||
| { | ||||
|     // Refresh the plugins
 | ||||
|  | @ -968,8 +987,8 @@ void DataFilesPage::readConfig() | |||
| 
 | ||||
| void DataFilesPage::writeConfig(QString profile) | ||||
| { | ||||
|     // Don't overwrite the config if no plugins are found
 | ||||
|     if (mPluginsModel->rowCount() < 1) { | ||||
|     // Don't overwrite the config if no masters are found
 | ||||
|     if (mMastersWidget->rowCount() < 1) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -981,6 +1000,61 @@ void DataFilesPage::writeConfig(QString profile) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Prepare the OpenMW config
 | ||||
|     QString config = QString::fromStdString((mCfgMgr.getLocalPath() / "openmw.cfg").string()); | ||||
|     QFile file(config); | ||||
| 
 | ||||
|     if (!file.exists()) { | ||||
|         config = QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string()); | ||||
|     } | ||||
| 
 | ||||
|     // Open the config as a QFile
 | ||||
|     file.setFileName(config); | ||||
| 
 | ||||
|     if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { | ||||
|         // File cannot be opened or created
 | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error writing OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not open or create %0</b><br><br> \
 | ||||
|         Please make sure you have the right permissions and try again.<br>").arg(file.fileName())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     QTextStream in(&file); | ||||
|     QByteArray buffer; | ||||
| 
 | ||||
|     // Remove all previous master/plugin entries from config
 | ||||
|     while (!in.atEnd()) { | ||||
|         QString line = in.readLine(); | ||||
|         if (!line.contains("master") && !line.contains("plugin")) { | ||||
|             buffer += line += "\n"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
| 
 | ||||
|     // Now we write back the other config entries
 | ||||
|     if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error writing OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not write to %0</b><br><br> \
 | ||||
|         Please make sure you have the right permissions and try again.<br>").arg(file.fileName())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     file.write(buffer); | ||||
|     QTextStream gameConfig(&file); | ||||
| 
 | ||||
|     // Make sure we have no groups open
 | ||||
|     while (!mLauncherConfig->group().isEmpty()) { | ||||
|         mLauncherConfig->endGroup(); | ||||
|  | @ -993,13 +1067,16 @@ void DataFilesPage::writeConfig(QString profile) | |||
|     mLauncherConfig->beginGroup(profile); | ||||
|     mLauncherConfig->remove(""); // Clear the subgroup
 | ||||
| 
 | ||||
|     // First write the masters to the config
 | ||||
|     const QStringList masterList = selectedMasters(); | ||||
|     // First write the masters to the configs
 | ||||
|     const QStringList masters = selectedMasters(); | ||||
| 
 | ||||
|     // We don't use foreach because we need i
 | ||||
|     for (int i = 0; i < masterList.size(); ++i) { | ||||
|         const QString master = masterList.at(i); | ||||
|         mLauncherConfig->setValue(QString("Master%0").arg(i), master); | ||||
|     for (int i = 0; i < masters.size(); ++i) { | ||||
|         const QString currentMaster = masters.at(i); | ||||
| 
 | ||||
|         mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); | ||||
|         gameConfig << "master=" << currentMaster << endl; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // Now write all checked plugins
 | ||||
|  | @ -1007,10 +1084,13 @@ void DataFilesPage::writeConfig(QString profile) | |||
| 
 | ||||
|     for (int i = 0; i < plugins.size(); ++i) | ||||
|     { | ||||
|         mLauncherConfig->setValue(QString("Plugin%1").arg(i), plugins.at(i)); | ||||
|         const QString currentPlugin = plugins.at(i); | ||||
|         mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); | ||||
|         gameConfig << "plugin=" << currentPlugin << endl; | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
|     mLauncherConfig->endGroup(); | ||||
|     mLauncherConfig->endGroup(); | ||||
| 
 | ||||
|     mLauncherConfig->sync(); | ||||
| } | ||||
|  |  | |||
|  | @ -19,24 +19,19 @@ class PluginsModel; | |||
| class PluginsView; | ||||
| class ComboBox; | ||||
| 
 | ||||
| namespace Files { struct ConfigurationManager; } | ||||
| 
 | ||||
| class DataFilesPage : public QWidget | ||||
| { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     DataFilesPage(QWidget *parent = 0); | ||||
|     DataFilesPage(Files::ConfigurationManager& cfg, QWidget *parent = 0); | ||||
| 
 | ||||
|     ComboBox *mProfilesComboBox; | ||||
|     QSettings *mLauncherConfig; | ||||
| 
 | ||||
|     const QStringList checkedPlugins(); | ||||
|     const QStringList selectedMasters(); | ||||
|     void setupConfig(); | ||||
|     void readConfig(); | ||||
|     void writeConfig(QString profile = QString()); | ||||
| 
 | ||||
|     void setupDataFiles(const QStringList &paths, bool strict); | ||||
| 
 | ||||
| public slots: | ||||
|     void masterSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); | ||||
|     void setCheckState(QModelIndex index); | ||||
|  | @ -81,11 +76,20 @@ private: | |||
|     QAction *mCheckAction; | ||||
|     QAction *mUncheckAction; | ||||
| 
 | ||||
|     Files::ConfigurationManager &mCfgMgr; | ||||
| 
 | ||||
|     QSettings *mLauncherConfig; | ||||
| 
 | ||||
|     const QStringList checkedPlugins(); | ||||
|     const QStringList selectedMasters(); | ||||
| 
 | ||||
|     void addPlugins(const QModelIndex &index); | ||||
|     void removePlugins(const QModelIndex &index); | ||||
|     void uncheckPlugins(); | ||||
|     void createActions(); | ||||
| 
 | ||||
|     void setupDataFiles(); | ||||
|     void setupConfig(); | ||||
|     void readConfig(); | ||||
|     void scrollToSelection(); | ||||
| 
 | ||||
| }; | ||||
|  |  | |||
|  | @ -1,8 +1,11 @@ | |||
| #include <QtGui> | ||||
| 
 | ||||
| #include "graphicspage.hpp" | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| 
 | ||||
| GraphicsPage::GraphicsPage(QWidget *parent) : QWidget(parent) | ||||
| GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) | ||||
|     : QWidget(parent) | ||||
|     , mCfgMgr(cfg) | ||||
| { | ||||
|     QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this); | ||||
| 
 | ||||
|  | @ -147,21 +150,21 @@ void GraphicsPage::createPages() | |||
| 
 | ||||
| void GraphicsPage::setupConfig() | ||||
| { | ||||
|     QString ogreCfg = mCfg.getOgreConfigPath().string().c_str(); | ||||
|     QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str(); | ||||
|     QFile file(ogreCfg); | ||||
|     mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat); | ||||
| } | ||||
| 
 | ||||
| void GraphicsPage::setupOgre() | ||||
| { | ||||
|     QString pluginCfg = mCfg.getPluginsConfigPath().string().c_str(); | ||||
|     QString pluginCfg = mCfgMgr.getPluginsConfigPath().string().c_str(); | ||||
|     QFile file(pluginCfg); | ||||
| 
 | ||||
|     // Create a log manager so we can surpress debug text to stdout/stderr
 | ||||
|     Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; | ||||
|     logMgr->createLog((mCfg.getLogPath().string() + "/launcherOgre.log"), true, false, false); | ||||
|     logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); | ||||
| 
 | ||||
|     QString ogreCfg = QString::fromStdString(mCfg.getOgreConfigPath().string()); | ||||
|     QString ogreCfg = QString::fromStdString(mCfgMgr.getOgreConfigPath().string()); | ||||
|     file.setFileName(ogreCfg); | ||||
| 
 | ||||
|     //we need to check that the path to the configuration file exists before we
 | ||||
|  | @ -177,7 +180,7 @@ void GraphicsPage::setupOgre() | |||
|         Make sure you have write access to<br>%1<br><br>")).arg(configDir.path())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -200,7 +203,7 @@ void GraphicsPage::setupOgre() | |||
| 
 | ||||
|         qCritical("Error creating Ogre::Root, the error reported was:\n %s", qPrintable(ogreError)); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -234,7 +237,7 @@ void GraphicsPage::setupOgre() | |||
|         Please make sure the plugins.cfg file exists and contains a valid rendering plugin.<br>")); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -420,7 +423,7 @@ void GraphicsPage::writeConfig() | |||
| 
 | ||||
|         qCritical("Error validating configuration"); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -446,7 +449,8 @@ void GraphicsPage::writeConfig() | |||
| 
 | ||||
|         qCritical("Error saving Ogre configuration, the error reported was:\n %s", qPrintable(ogreError)); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|         qApp->exit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -7,21 +7,20 @@ | |||
| #include <OgreRenderSystem.h> | ||||
| #include <OgreConfigFile.h> | ||||
| #include <OgreConfigDialog.h> | ||||
| #include <components/cfg/configurationmanager.hpp> | ||||
| 
 | ||||
| class QComboBox; | ||||
| class QCheckBox; | ||||
| class QStackedWidget; | ||||
| class QSettings; | ||||
| 
 | ||||
| namespace Files { struct ConfigurationManager; } | ||||
| 
 | ||||
| class GraphicsPage : public QWidget | ||||
| { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     GraphicsPage(QWidget *parent = 0); | ||||
| 
 | ||||
|     QSettings *mOgreConfig; | ||||
|     GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0); | ||||
| 
 | ||||
|     void writeConfig(); | ||||
| 
 | ||||
|  | @ -29,7 +28,6 @@ public slots: | |||
|     void rendererChanged(const QString &renderer); | ||||
| 
 | ||||
| private: | ||||
|     Cfg::ConfigurationManager mCfg; | ||||
|     Ogre::Root *mOgre; | ||||
|     Ogre::RenderSystem *mSelectedRenderSystem; | ||||
|     Ogre::RenderSystem *mOpenGLRenderSystem; | ||||
|  | @ -59,6 +57,10 @@ private: | |||
|     QCheckBox *mD3DVSyncCheckBox; | ||||
|     QCheckBox *mD3DFullScreenCheckBox; | ||||
| 
 | ||||
|     QSettings *mOgreConfig; | ||||
| 
 | ||||
|     Files::ConfigurationManager &mCfgMgr; | ||||
| 
 | ||||
|     QString getConfigValue(const QString &key, Ogre::RenderSystem *renderer); | ||||
|     QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| #include <QApplication> | ||||
| #include <QDir> | ||||
| #include <QFile> | ||||
| #include <QtDebug> | ||||
| 
 | ||||
| #include "maindialog.hpp" | ||||
| 
 | ||||
|  | @ -17,17 +18,19 @@ int main(int argc, char *argv[]) | |||
|         dir.cdUp(); | ||||
|         dir.cdUp(); | ||||
|     } | ||||
| 
 | ||||
|     // force Qt to load only LOCAL plugins, don't touch system Qt installation
 | ||||
|     QDir pluginsPath(QCoreApplication::applicationDirPath()); | ||||
|     pluginsPath.cdUp(); | ||||
|     pluginsPath.cd("Plugins"); | ||||
| 
 | ||||
|     QStringList libraryPaths; | ||||
|     libraryPaths << pluginsPath.path() << QCoreApplication::applicationDirPath(); | ||||
|     app.setLibraryPaths(libraryPaths); | ||||
|     #endif | ||||
| 
 | ||||
|     QDir::setCurrent(dir.absolutePath()); | ||||
| 
 | ||||
|     // Load the stylesheet
 | ||||
|     QFile file("./launcher.qss"); | ||||
| 
 | ||||
|     file.open(QFile::ReadOnly); | ||||
|     QString styleSheet = QLatin1String(file.readAll()); | ||||
|     app.setStyleSheet(styleSheet); | ||||
| 
 | ||||
|     MainDialog dialog; | ||||
|     return dialog.exec(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -45,6 +45,20 @@ MainDialog::MainDialog() | |||
|     setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); | ||||
|     setMinimumSize(QSize(575, 575)); | ||||
| 
 | ||||
|     // Load the stylesheet
 | ||||
|     QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string()); | ||||
|     QFile file(config); | ||||
| 
 | ||||
|     if (!file.exists()) { | ||||
|         file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string())); | ||||
|     } | ||||
| 
 | ||||
|     file.open(QFile::ReadOnly); | ||||
|     QString styleSheet = QLatin1String(file.readAll()); | ||||
|     qApp->setStyleSheet(styleSheet); | ||||
|     file.close(); | ||||
| 
 | ||||
| 
 | ||||
|     connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); | ||||
|     connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); | ||||
| 
 | ||||
|  | @ -85,116 +99,13 @@ void MainDialog::createIcons() | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| QStringList MainDialog::readConfig(const QString &fileName) | ||||
| { | ||||
|     // We can't use QSettings directly because it
 | ||||
|     // does not support multiple keys with the same name
 | ||||
|     QFile file(fileName); | ||||
| 
 | ||||
|     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error opening OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not open %0</b><br><br> \
 | ||||
|         Please make sure you have the right permissions and try again.<br>").arg(file.fileName())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(); // File cannot be opened or created
 | ||||
|     } | ||||
| 
 | ||||
|     QTextStream in(&file); | ||||
|     QStringList dataDirs; | ||||
|     QString dataLocal; | ||||
| 
 | ||||
|     // Read the config line by line
 | ||||
|     while (!in.atEnd()) { | ||||
|         QString line = in.readLine(); | ||||
| 
 | ||||
|         if (line.startsWith("data=")) { | ||||
|             dataDirs.append(line.remove("data=")); | ||||
|         } | ||||
| 
 | ||||
|         // Read the data-local key, if more than one are found only the last is used
 | ||||
|         if (line.startsWith("data-local=")) { | ||||
|             dataLocal = line.remove("data-local="); | ||||
|         } | ||||
| 
 | ||||
|         // Read fs-strict key
 | ||||
|         if (line.startsWith("fs-strict=")) { | ||||
|             QString value = line.remove("fs-strict="); | ||||
| 
 | ||||
|             (value.toLower() == QLatin1String("true")) | ||||
|             ? mStrict = true | ||||
|             : mStrict = false; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // Add the data-local= key to the end of the dataDirs for priority reasons
 | ||||
|     if (!dataLocal.isEmpty()) { | ||||
|         dataDirs.append(dataLocal); | ||||
|     } | ||||
| 
 | ||||
|     if (!dataDirs.isEmpty()) | ||||
|     { | ||||
|         // Reset the global datadirs to the newly read entries
 | ||||
|         // Else return the previous dataDirs because nothing was found in this file;
 | ||||
|         mDataDirs = dataDirs; | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
| 
 | ||||
|     return mDataDirs; | ||||
| } | ||||
| 
 | ||||
| void MainDialog::createPages() | ||||
| { | ||||
|     mPlayPage = new PlayPage(this); | ||||
|     mGraphicsPage = new GraphicsPage(this); | ||||
|     mDataFilesPage = new DataFilesPage(this); | ||||
|     mGraphicsPage = new GraphicsPage(mCfgMgr, this); | ||||
|     mDataFilesPage = new DataFilesPage(mCfgMgr, this); | ||||
| 
 | ||||
|     // Retrieve all data entries from the configs
 | ||||
|     QStringList dataDirs; | ||||
| 
 | ||||
|     // Global location
 | ||||
|     QFile file(QString::fromStdString((mCfg.getGlobalConfigPath()/"openmw.cfg").string())); | ||||
|     if (file.exists()) { | ||||
|         dataDirs = readConfig(file.fileName()); | ||||
|     } | ||||
| 
 | ||||
|     // User location
 | ||||
|     file.setFileName(QString::fromStdString((mCfg.getLocalConfigPath()/"openmw.cfg").string())); | ||||
|     if (file.exists()) { | ||||
|         dataDirs = readConfig(file.fileName()); | ||||
|     } | ||||
| 
 | ||||
|     // Local location
 | ||||
|     file.setFileName("./openmw.cfg"); | ||||
| 
 | ||||
|     if (file.exists()) { | ||||
|         dataDirs = readConfig(file.fileName()); | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
| 
 | ||||
|     if (!dataDirs.isEmpty()) { | ||||
|         // Now pass the datadirs on to the DataFilesPage
 | ||||
|         mDataFilesPage->setupDataFiles(dataDirs, mStrict); | ||||
|     } else { | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error reading OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not read the location of the data files</b><br><br> \
 | ||||
|                         Please make sure OpenMW is correctly configured and try again.<br>")); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(); // No data or data-local entries in openmw.cfg
 | ||||
|     } | ||||
| 
 | ||||
|     // Set the combobox of the play page to imitate the comobox on the datafilespage
 | ||||
|     // Set the combobox of the play page to imitate the combobox on the datafilespage
 | ||||
|     mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); | ||||
|     mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); | ||||
| 
 | ||||
|  | @ -246,14 +157,16 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) | |||
| void MainDialog::closeEvent(QCloseEvent *event) | ||||
| { | ||||
|     // Now write all config files
 | ||||
|     writeConfig(); | ||||
|     mDataFilesPage->writeConfig(); | ||||
|     mGraphicsPage->writeConfig(); | ||||
|     event->accept(); | ||||
| } | ||||
| 
 | ||||
| void MainDialog::play() | ||||
| { | ||||
|     // First do a write of all the configs, just to be sure
 | ||||
|     writeConfig(); | ||||
|     mDataFilesPage->writeConfig(); | ||||
|     mGraphicsPage->writeConfig(); | ||||
| 
 | ||||
| #ifdef Q_WS_WIN | ||||
|     QString game = "./openmw.exe"; | ||||
|  | @ -313,75 +226,3 @@ void MainDialog::play() | |||
|         close(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void MainDialog::writeConfig() | ||||
| { | ||||
|     // Write the profiles
 | ||||
|     mDataFilesPage->writeConfig(); | ||||
|     mDataFilesPage->mLauncherConfig->sync(); | ||||
| 
 | ||||
|     // Write the graphics settings
 | ||||
|     mGraphicsPage->writeConfig(); | ||||
|     mGraphicsPage->mOgreConfig->sync(); | ||||
| 
 | ||||
|     QStringList dataFiles = mDataFilesPage->selectedMasters(); | ||||
|     dataFiles.append(mDataFilesPage->checkedPlugins()); | ||||
| 
 | ||||
|     // Open the config as a QFile
 | ||||
|     QFile file(QString::fromStdString((mCfg.getLocalConfigPath()/"openmw.cfg").string())); | ||||
| 
 | ||||
|     if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { | ||||
|         // File cannot be opened or created
 | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error writing OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not open or create %0</b><br><br> \
 | ||||
|                         Please make sure you have the right permissions and try again.<br>").arg(file.fileName())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|     } | ||||
| 
 | ||||
|     QTextStream in(&file); | ||||
|     QByteArray buffer; | ||||
| 
 | ||||
|     // Remove all previous master/plugin entries from config
 | ||||
|     while (!in.atEnd()) { | ||||
|         QString line = in.readLine(); | ||||
|         if (!line.contains("master") && !line.contains("plugin")) { | ||||
|             buffer += line += "\n"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
| 
 | ||||
|     // Now we write back the other config entries
 | ||||
|     if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { | ||||
|         QMessageBox msgBox; | ||||
|         msgBox.setWindowTitle("Error writing OpenMW configuration file"); | ||||
|         msgBox.setIcon(QMessageBox::Critical); | ||||
|         msgBox.setStandardButtons(QMessageBox::Ok); | ||||
|         msgBox.setText(tr("<br><b>Could not write to %0</b><br><br> \
 | ||||
|                         Please make sure you have the right permissions and try again.<br>").arg(file.fileName())); | ||||
|         msgBox.exec(); | ||||
| 
 | ||||
|         QApplication::exit(1); | ||||
|     } | ||||
| 
 | ||||
|     file.write(buffer); | ||||
| 
 | ||||
|     QTextStream out(&file); | ||||
| 
 | ||||
|     // Write the list of game files to the config
 | ||||
|     foreach (const QString ¤tFile, dataFiles) { | ||||
| 
 | ||||
|         if (currentFile.endsWith(QString(".esm"), Qt::CaseInsensitive)) { | ||||
|             out << "master=" << currentFile << endl; | ||||
|         } else if (currentFile.endsWith(QString(".esp"), Qt::CaseInsensitive)) { | ||||
|             out << "plugin=" << currentFile << endl; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     file.close(); | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 
 | ||||
| #include <QDialog> | ||||
| 
 | ||||
| #include <components/cfg/configurationmanager.hpp> | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| 
 | ||||
| class QListWidget; | ||||
| class QListWidgetItem; | ||||
|  | @ -28,15 +28,11 @@ public slots: | |||
|     void play(); | ||||
|     void profileChanged(int index); | ||||
| 
 | ||||
| 
 | ||||
| private: | ||||
|     void createIcons(); | ||||
|     void createPages(); | ||||
|     void writeConfig(); | ||||
|     void closeEvent(QCloseEvent *event); | ||||
| 
 | ||||
|     QStringList readConfig(const QString &fileName); | ||||
| 
 | ||||
|     QListWidget *mIconWidget; | ||||
|     QStackedWidget *mPagesWidget; | ||||
| 
 | ||||
|  | @ -44,10 +40,7 @@ private: | |||
|     GraphicsPage *mGraphicsPage; | ||||
|     DataFilesPage *mDataFilesPage; | ||||
| 
 | ||||
|     QStringList mDataDirs; | ||||
|     bool mStrict; | ||||
| 
 | ||||
|     Cfg::ConfigurationManager mCfg; | ||||
|     Files::ConfigurationManager mCfgMgr; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -43,8 +43,8 @@ add_openmw_dir (mwsound | |||
| 
 | ||||
| add_openmw_dir (mwworld | ||||
|     refdata world physicssystem scene environment globals class action nullaction actionteleport | ||||
|     containerstore actiontalk actiontake containerstore manualref containerutil player cellfunctors | ||||
|     cells localscripts customdata | ||||
|     containerstore actiontalk actiontake manualref player cellfunctors | ||||
|     cells localscripts customdata weather | ||||
|     ) | ||||
| 
 | ||||
| add_openmw_dir (mwclass | ||||
|  | @ -77,7 +77,6 @@ target_link_libraries(openmw | |||
|     ${OPENAL_LIBRARY} | ||||
|     ${SOUND_INPUT_LIBRARY} | ||||
|     ${BULLET_LIBRARIES} | ||||
|     caelum | ||||
|     components | ||||
|     MyGUIEngine | ||||
|     MyGUIOgrePlatform | ||||
|  | @ -86,10 +85,6 @@ target_link_libraries(openmw | |||
| if(APPLE) | ||||
|     find_library(CARBON_FRAMEWORK Carbon) | ||||
|     target_link_libraries(openmw ${CARBON_FRAMEWORK}) | ||||
|     install(TARGETS openmw | ||||
|         BUNDLE DESTINATION . | ||||
|         RUNTIME DESTINATION ../MacOS | ||||
|         COMPONENT Runtime) | ||||
| endif(APPLE) | ||||
| 
 | ||||
| if(DPKG_PROGRAM) | ||||
|  |  | |||
|  | @ -18,7 +18,9 @@ | |||
| #include <components/esm_store/cell_store.hpp> | ||||
| #include <components/bsa/bsa_archive.hpp> | ||||
| #include <components/esm/esm_reader.hpp> | ||||
| #include <components/files/path.hpp> | ||||
| #include <components/files/fixedpath.hpp> | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| 
 | ||||
| #include <components/nifbullet/bullet_nif_loader.hpp> | ||||
| #include <components/nifogre/ogre_nif_loader.hpp> | ||||
| 
 | ||||
|  | @ -171,7 +173,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager) | ||||
| OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) | ||||
|   : mOgre (0) | ||||
|   , mFpsLevel(0) | ||||
|   , mDebug (false) | ||||
|  | @ -208,15 +210,16 @@ OMW::Engine::~Engine() | |||
| void OMW::Engine::loadBSA() | ||||
| { | ||||
|     const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa"); | ||||
| 
 | ||||
|     for (Files::MultiDirCollection::TIter iter (bsa.begin()); iter!=bsa.end(); ++iter) | ||||
|     std::string dataDirectory; | ||||
|     for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter) | ||||
|     { | ||||
|          std::cout << "Adding " << iter->second.string() << std::endl; | ||||
|          Bsa::addBSA (iter->second.string()); | ||||
|     } | ||||
|         std::cout << "Adding " << iter->second.string() << std::endl; | ||||
|         Bsa::addBSA(iter->second.string()); | ||||
| 
 | ||||
|     std::cout << "Data dir " << mDataDir.string() << std::endl; | ||||
|     Bsa::addDir(mDataDir.string(), mFSStrict); | ||||
|         dataDirectory = iter->second.parent_path().string(); | ||||
|         std::cout << "Data dir " << dataDirectory << std::endl; | ||||
|         Bsa::addDir(dataDirectory, mFSStrict); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // add resources directory
 | ||||
|  | @ -237,9 +240,7 @@ void OMW::Engine::enableFSStrict(bool fsStrict) | |||
| 
 | ||||
| void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs) | ||||
| { | ||||
|     /// \todo remove mDataDir, once resources system can handle multiple directories
 | ||||
|     assert (!dataDirs.empty()); | ||||
|     mDataDir = dataDirs.back(); | ||||
|     mDataDirs = dataDirs; | ||||
|     mFileCollections = Files::Collections (dataDirs, !mFSStrict); | ||||
| } | ||||
| 
 | ||||
|  | @ -315,7 +316,7 @@ void OMW::Engine::go() | |||
|     } | ||||
|     mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), | ||||
|         mCfgMgr.getOgreConfigPath().string(), | ||||
|         mCfgMgr.getLogPath().string() + std::string("/"), | ||||
|         mCfgMgr.getLogPath().string(), | ||||
|         mCfgMgr.getPluginsConfigPath().string(), false); | ||||
| 
 | ||||
|     // This has to be added BEFORE MyGUI is initialized, as it needs
 | ||||
|  | @ -341,7 +342,7 @@ void OMW::Engine::go() | |||
|     mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(), | ||||
|                                                            mOgre->getCamera(), | ||||
|                                                            mEnvironment.mWorld->getStore(), | ||||
|                                                            (mDataDir), | ||||
|                                                            mDataDirs, | ||||
|                                                            mUseSound, mFSStrict, mEnvironment); | ||||
| 
 | ||||
|     // Create script system
 | ||||
|  | @ -445,6 +446,28 @@ void OMW::Engine::activate() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void OMW::Engine::screenshot() | ||||
| { | ||||
|     // Count screenshots.
 | ||||
|     int shotCount = 0; | ||||
| 
 | ||||
|     const std::string screenshotPath = mCfgMgr.getUserPath().string(); | ||||
| 
 | ||||
|     // Find the first unused filename with a do-while
 | ||||
|     std::ostringstream stream; | ||||
|     do | ||||
|     { | ||||
|         // Reset the stream
 | ||||
|         stream.str(""); | ||||
|         stream.clear(); | ||||
| 
 | ||||
|         stream << screenshotPath << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << ".png"; | ||||
| 
 | ||||
|     } while (boost::filesystem::exists(stream.str())); | ||||
| 
 | ||||
|     mOgre->screenshot(stream.str()); | ||||
| } | ||||
| 
 | ||||
| void OMW::Engine::setCompileAll (bool all) | ||||
| { | ||||
|     mCompileAll = all; | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ | |||
| 
 | ||||
| #include <components/compiler/extensions.hpp> | ||||
| #include <components/files/collections.hpp> | ||||
| #include <components/cfg/configurationmanager.hpp> | ||||
| 
 | ||||
| #include "mwworld/environment.hpp" | ||||
| #include "mwworld/ptr.hpp" | ||||
|  | @ -52,13 +51,18 @@ namespace OEngine | |||
|   } | ||||
| } | ||||
| 
 | ||||
| namespace Files | ||||
| { | ||||
|     struct ConfigurationManager; | ||||
| } | ||||
| 
 | ||||
| namespace OMW | ||||
| { | ||||
|     /// \brief Main engine class, that brings together all the components of OpenMW
 | ||||
|     class Engine : private Ogre::FrameListener | ||||
|     { | ||||
|             std::string mEncoding; | ||||
|             boost::filesystem::path mDataDir; | ||||
|             Files::PathContainer mDataDirs; | ||||
|             boost::filesystem::path mResDir; | ||||
|             OEngine::Render::OgreRenderer *mOgre; | ||||
|             std::string mCellName; | ||||
|  | @ -101,7 +105,7 @@ namespace OMW | |||
|             virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); | ||||
| 
 | ||||
|         public: | ||||
|             Engine(Cfg::ConfigurationManager& configurationManager); | ||||
|             Engine(Files::ConfigurationManager& configurationManager); | ||||
|             virtual ~Engine(); | ||||
| 
 | ||||
|             /// Enable strict filesystem mode (do not fold case)
 | ||||
|  | @ -149,6 +153,9 @@ namespace OMW | |||
|             /// Activate the focussed object.
 | ||||
|             void activate(); | ||||
| 
 | ||||
|             /// Write screenshot to file.
 | ||||
|             void screenshot(); | ||||
| 
 | ||||
|             /// Compile all scripts (excludign dialogue scripts) at startup?
 | ||||
|             void setCompileAll (bool all); | ||||
| 
 | ||||
|  | @ -158,7 +165,7 @@ namespace OMW | |||
|             void setAnimationVerbose(bool animverbose); | ||||
| 
 | ||||
|         private: | ||||
|             Cfg::ConfigurationManager& mCfgMgr; | ||||
|             Files::ConfigurationManager& mCfgMgr; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,9 +6,9 @@ | |||
| #include <boost/program_options.hpp> | ||||
| 
 | ||||
| #include <components/files/fileops.hpp> | ||||
| #include <components/files/path.hpp> | ||||
| #include <components/files/fixedpath.hpp> | ||||
| #include <components/files/collections.hpp> | ||||
| #include <components/cfg/configurationmanager.hpp> | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| 
 | ||||
| #include "engine.hpp" | ||||
| 
 | ||||
|  | @ -35,6 +35,23 @@ | |||
| 
 | ||||
| #include "config.hpp" | ||||
| 
 | ||||
| #include <boost/version.hpp> | ||||
| /**
 | ||||
|  * Workaround for problems with whitespaces in paths in older versions of Boost library | ||||
|  */ | ||||
| #if (BOOST_VERSION <= 104600) | ||||
| namespace boost | ||||
| { | ||||
| 
 | ||||
| template<> | ||||
| inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg) | ||||
| { | ||||
|     return boost::filesystem::path(arg); | ||||
| } | ||||
| 
 | ||||
| } /* namespace boost */ | ||||
| #endif /* (BOOST_VERSION <= 104600) */ | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -46,7 +63,7 @@ using namespace std; | |||
|  * \retval true - Everything goes OK | ||||
|  * \retval false - Error | ||||
|  */ | ||||
| bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::ConfigurationManager& cfgMgr) | ||||
| bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::ConfigurationManager& cfgMgr) | ||||
| { | ||||
|     // Create a local alias for brevity
 | ||||
|     namespace bpo = boost::program_options; | ||||
|  | @ -164,14 +181,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio | |||
|     std::string local(variables["data-local"].as<std::string>()); | ||||
|     if (!local.empty()) | ||||
|     { | ||||
|         dataDirs.push_back(Files::PathContainer::value_type(local)); | ||||
|         std::cout << "Ignoring data-local (currently not supported)" << std::endl; | ||||
| //        dataDirs.push_back(Files::PathContainer::value_type(local));
 | ||||
|     } | ||||
| 
 | ||||
|     if (dataDirs.empty()) | ||||
|     if (dataDirs.size()>1) | ||||
|     { | ||||
|         dataDirs.push_back(cfgMgr.getLocalDataPath()); | ||||
|         dataDirs.resize (1); | ||||
|         std::cout << "Ignoring all but the first data path (multiple data paths currently not supported)" | ||||
|             << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     cfgMgr.processPaths(dataDirs); | ||||
| 
 | ||||
|     engine.setDataDirs(dataDirs); | ||||
| 
 | ||||
|     engine.setResourceDir(variables["resources"].as<std::string>()); | ||||
|  | @ -224,7 +246,7 @@ int main(int argc, char**argv) | |||
| 
 | ||||
|     try | ||||
|     { | ||||
|         Cfg::ConfigurationManager cfgMgr; | ||||
|         Files::ConfigurationManager cfgMgr; | ||||
|         OMW::Engine engine(cfgMgr); | ||||
| 
 | ||||
|         if (parseOptions(argc, argv, engine, cfgMgr)) | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|    void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -59,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -71,12 +69,6 @@ namespace MWClass | |||
|         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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -28,10 +28,6 @@ namespace MWClass | |||
|             virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -61,12 +59,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -59,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,16 +6,20 @@ | |||
| #include <components/esm_store/cell_store.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<MWWorld::RefData> mContainerStore; | ||||
|         MWWorld::ContainerStore mContainerStore; | ||||
| 
 | ||||
|         virtual MWWorld::CustomData *clone() const; | ||||
|     }; | ||||
|  | @ -71,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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref = | ||||
|  | @ -79,7 +115,7 @@ namespace MWClass | |||
|         return ref->base->name; | ||||
|     } | ||||
| 
 | ||||
|     MWWorld::ContainerStore<MWWorld::RefData>& Container::getContainerStore (const MWWorld::Ptr& ptr) | ||||
|     MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) | ||||
|         const | ||||
|     { | ||||
|         ensureCustomData (ptr); | ||||
|  |  | |||
|  | @ -20,8 +20,11 @@ namespace MWClass | |||
|             ///< \return name (the one that is to be presented to the user; not the internal one);
 | ||||
|             /// can return an empty string.
 | ||||
| 
 | ||||
|             virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( | ||||
|                 const MWWorld::Ptr& ptr) const; | ||||
|             virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, | ||||
|                 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
 | ||||
| 
 | ||||
|             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 | ||||
|  | @ -17,7 +17,7 @@ namespace | |||
|     struct CustomData : public MWWorld::CustomData | ||||
|     { | ||||
|         MWMechanics::CreatureStats mCreatureStats; | ||||
|         MWWorld::ContainerStore<MWWorld::RefData> mContainerStore; | ||||
|         MWWorld::ContainerStore mContainerStore; | ||||
| 
 | ||||
|         virtual MWWorld::CustomData *clone() const; | ||||
|     }; | ||||
|  | @ -118,7 +118,7 @@ namespace MWClass | |||
|         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 | ||||
|     { | ||||
|         ensureCustomData (ptr); | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< Generate action for activation
 | ||||
| 
 | ||||
|             virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( | ||||
|             virtual MWWorld::ContainerStore& getContainerStore ( | ||||
|                 const MWWorld::Ptr& ptr) const; | ||||
|             ///< Return container store
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,8 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "../mwsound/soundmanager.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -61,15 +63,28 @@ namespace MWClass | |||
|         ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref = | ||||
|             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) | ||||
|         { | ||||
|             // TODO check for key
 | ||||
|             // TODO report failure to player (message, sound?). Look up behaviour of original MW.
 | ||||
|             std::cout << "Locked!" << std::endl; | ||||
|             environment.mSoundManager->playSound(lockedSound, 1.0, 1.0); | ||||
|             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) | ||||
|         { | ||||
|  | @ -77,6 +92,7 @@ namespace MWClass | |||
|             if (environment.mWorld->getPlayer().getPlayer()==actor) | ||||
|             { | ||||
|                 // the player is using the door
 | ||||
|                 environment.mSoundManager->playSound(openSound, 1.0, 1.0); | ||||
|                 return boost::shared_ptr<MWWorld::Action> ( | ||||
|                     new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); | ||||
|             } | ||||
|  | @ -91,6 +107,9 @@ namespace MWClass | |||
|         { | ||||
|             // animated 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); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -57,12 +55,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,8 +14,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -26,18 +24,18 @@ namespace MWClass | |||
|         assert (ref->base != NULL); | ||||
|         const std::string &model = ref->base->model; | ||||
| 
 | ||||
|         MWRender::Objects& objects = renderingInterface.getObjects(); | ||||
|         objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); | ||||
| 
 | ||||
|         if (!model.empty()) | ||||
|         { | ||||
|             MWRender::Objects& objects = renderingInterface.getObjects(); | ||||
|             objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); | ||||
|             objects.insertMesh(ptr, "meshes\\" + model); | ||||
|             const int color = ref->base->data.color; | ||||
|             const float r = ((color >> 0) & 0xFF) / 255.0f; | ||||
|             const float g = ((color >> 8) & 0xFF) / 255.0f; | ||||
|             const float b = ((color >> 16) & 0xFF) / 255.0f; | ||||
|             const float radius = float (ref->base->data.radius); | ||||
|             objects.insertLight (ptr, r, g, b, radius); | ||||
|         } | ||||
| 
 | ||||
|         const int color = ref->base->data.color; | ||||
|         const float r = ((color >> 0) & 0xFF) / 255.0f; | ||||
|         const float g = ((color >> 8) & 0xFF) / 255.0f; | ||||
|         const float b = ((color >> 16) & 0xFF) / 255.0f; | ||||
|         const float radius = float (ref->base->data.radius); | ||||
|         objects.insertLight (ptr, r, g, b, radius); | ||||
|     } | ||||
| 
 | ||||
|     void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const | ||||
|  | @ -45,13 +43,12 @@ namespace MWClass | |||
|         ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref = | ||||
|             ptr.get<ESM::Light>(); | ||||
| 
 | ||||
| 
 | ||||
|         const std::string &model = ref->base->model; | ||||
|         assert (ref->base != NULL); | ||||
|         const std::string &model = ref->base->model; | ||||
| 
 | ||||
|         if(!model.empty()){ | ||||
|             physics.insertObjectPhysics(ptr, "meshes\\" + model); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const | ||||
|  | @ -89,12 +86,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -27,10 +27,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -60,12 +58,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -59,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ namespace | |||
|         MWMechanics::NpcStats mNpcStats; | ||||
|         MWMechanics::CreatureStats mCreatureStats; | ||||
|         MWMechanics::Movement mMovement; | ||||
|         MWWorld::ContainerStore<MWWorld::RefData> mContainerStore; | ||||
|         MWWorld::ContainerStore mContainerStore; | ||||
| 
 | ||||
|         virtual MWWorld::CustomData *clone() const; | ||||
|     }; | ||||
|  | @ -156,7 +156,7 @@ namespace MWClass | |||
|         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 | ||||
|     { | ||||
|         ensureCustomData (ptr); | ||||
|  |  | |||
|  | @ -35,8 +35,7 @@ namespace MWClass | |||
|             virtual MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Return NPC stats
 | ||||
| 
 | ||||
|             virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( | ||||
|                 const MWWorld::Ptr& ptr) const; | ||||
|             virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Return container store
 | ||||
| 
 | ||||
|             virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -59,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ | |||
| #include "../mwworld/ptr.hpp" | ||||
| #include "../mwworld/actiontake.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
|  | @ -20,7 +19,7 @@ namespace MWClass | |||
| 
 | ||||
|         assert (ref->base != NULL); | ||||
|         const std::string &model = ref->base->model; | ||||
|          | ||||
| 
 | ||||
|         if (!model.empty()) | ||||
|         { | ||||
|             MWRender::Objects& objects = renderingInterface.getObjects(); | ||||
|  | @ -58,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -59,12 +57,6 @@ namespace MWClass | |||
|             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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ namespace MWClass | |||
|                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ namespace MWClass | |||
|         if (!model.empty()) | ||||
|         { | ||||
|             MWRender::Objects& objects = renderingInterface.getObjects(); | ||||
|             objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); | ||||
|             objects.insertBegin(ptr, ptr.getRefData().isEnabled(), true); | ||||
|             objects.insertMesh(ptr, "meshes\\" + model); | ||||
|         } | ||||
|     } | ||||
|  | @ -30,13 +30,12 @@ namespace MWClass | |||
|         ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref = | ||||
|             ptr.get<ESM::Static>(); | ||||
| 
 | ||||
| 
 | ||||
|         const std::string &model = ref->base->model; | ||||
|         assert (ref->base != NULL); | ||||
|         const std::string &model = ref->base->model; | ||||
| 
 | ||||
|         if(!model.empty()){ | ||||
|             physics.insertObjectPhysics(ptr, "meshes\\" + model); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     std::string Static::getName (const MWWorld::Ptr& ptr) const | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ | |||
| 
 | ||||
| #include "../mwrender/objects.hpp" | ||||
| 
 | ||||
| #include "containerutil.hpp" | ||||
| 
 | ||||
| namespace MWClass | ||||
| { | ||||
|     void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const | ||||
|  | @ -72,12 +70,6 @@ namespace MWClass | |||
|         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 | ||||
|     { | ||||
|         ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref = | ||||
|  |  | |||
|  | @ -28,10 +28,6 @@ namespace MWClass | |||
|             virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; | ||||
|             ///< 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; | ||||
|             ///< Return name of the script attached to ptr
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,8 +32,8 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) | |||
|         mBook.pages.pop_back(); | ||||
|     } | ||||
| 
 | ||||
|     std::string::iterator wordBegin = text.begin(); | ||||
|     std::string::iterator wordEnd; | ||||
|     //std::string::iterator wordBegin = text.begin();
 | ||||
|     //std::string::iterator wordEnd;
 | ||||
| 
 | ||||
|     std::string cText = text; | ||||
| 
 | ||||
|  |  | |||
|  | @ -83,27 +83,14 @@ namespace MWInput | |||
|     MWGui::WindowManager &windows; | ||||
|     OMW::Engine& mEngine; | ||||
| 
 | ||||
|     // Count screenshots.
 | ||||
|     int shotCount; | ||||
| 
 | ||||
| 
 | ||||
|    /* InputImpl Methods */ | ||||
| 
 | ||||
|     // Write screenshot to file.
 | ||||
|     void screenshot() | ||||
|     { | ||||
| 
 | ||||
|       // Find the first unused filename with a do-while
 | ||||
|       char buf[50]; | ||||
|       do | ||||
|       { | ||||
|         snprintf(buf, 50, "screenshot%03d.png", shotCount++); | ||||
|       } while (boost::filesystem::exists(buf)); | ||||
| 
 | ||||
|       ogre.screenshot(buf); | ||||
|         mEngine.screenshot(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ | ||||
|     void toggleInventory() | ||||
|     { | ||||
|  | @ -183,8 +170,7 @@ namespace MWInput | |||
|         poller(input), | ||||
|         player(_player), | ||||
|         windows(_windows), | ||||
|         mEngine (engine), | ||||
|         shotCount(0) | ||||
|         mEngine (engine) | ||||
|     { | ||||
|       using namespace OEngine::Input; | ||||
|       using namespace OEngine::Render; | ||||
|  |  | |||
|  | @ -99,14 +99,15 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store){ | |||
|         mRend.getScene()->destroySceneNode(base); | ||||
|         base = 0; | ||||
|     } | ||||
| 	for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) | ||||
| 	{ | ||||
| 		if(iter->first.getCell() == store){ | ||||
| 			delete iter->second; | ||||
| 			mAllActors.erase(iter); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); ) | ||||
|     { | ||||
|         if(iter->first.getCell() == store){ | ||||
|             delete iter->second; | ||||
|             mAllActors.erase(iter++); | ||||
|         } | ||||
|         else | ||||
|             ++iter; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){ | ||||
|  |  | |||
|  | @ -101,7 +101,6 @@ namespace MWRender{ | |||
|     } | ||||
| 
 | ||||
|    void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ | ||||
|        bool useHandles = skel == creaturemodel->getSkeleton(); | ||||
|         shapeNumber = 0; | ||||
| 
 | ||||
|         std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter; | ||||
|  | @ -112,6 +111,9 @@ namespace MWRender{ | |||
| 
 | ||||
| 			Nif::NiTriShapeCopy& copy = *allshapesiter; | ||||
| 			std::vector<Ogre::Vector3>* allvertices = ©.vertices; | ||||
| 			std::vector<Ogre::Vector3>* allnormals = ©.normals; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 			//std::set<unsigned int> vertices;
 | ||||
| 			//std::set<unsigned int> normals;
 | ||||
|  | @ -121,8 +123,7 @@ namespace MWRender{ | |||
| 			//std::cout << "Name " << copy.sname << "\n";
 | ||||
| 			Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); | ||||
| 		            Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); | ||||
| 			       //Ogre::HardwareVertexBufferSharedPtr vbufNormal = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(1);
 | ||||
| 		           // Ogre::Real* pRealNormal = static_cast<Ogre::Real*>(vbufNormal->lock(Ogre::HardwareBuffer::HBL_NORMAL));
 | ||||
| 
 | ||||
| 
 | ||||
| 				std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices(); | ||||
| 				//Each shape has multiple indices
 | ||||
|  | @ -181,146 +182,76 @@ namespace MWRender{ | |||
|                     std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second; | ||||
|                     int verIndex = iter->first; | ||||
|                     Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; | ||||
|                     Ogre::Vector3 currentNormal = (*allnormals)[verIndex]; | ||||
|                     Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); | ||||
|                     Ogre::Bone *bonePtr = 0; | ||||
|                     if(useHandles) | ||||
|                     { | ||||
|                         bonePtr = skel->getBone(boneinfocopy->bonehandle); | ||||
|                     } | ||||
|                     else | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                     Ogre::Vector3 vecPos; | ||||
|                     Ogre::Quaternion vecRot; | ||||
| 					std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot>::iterator result = vecRotPos.find(boneinfocopy); | ||||
| 
 | ||||
|                     if(result == vecRotPos.end()){ | ||||
|                         bonePtr = skel->getBone(boneinfocopy->bonename); | ||||
| 
 | ||||
|                     Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; | ||||
|                     Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; | ||||
| 
 | ||||
| 
 | ||||
|                     /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){
 | ||||
|                         vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; | ||||
|                         vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; | ||||
| 
 | ||||
|                         if(useHandles){ | ||||
| 
 | ||||
|                              PosAndRot both; | ||||
|                             both.vecPos = vecPos; | ||||
|                             both.vecRot = vecRot; | ||||
|                             vecPosRot[boneinfocopy->bonehandle] = both; | ||||
|                         } | ||||
|                             vecRotPos[boneinfocopy] = both; | ||||
| 
 | ||||
|                     } | ||||
|                     else{ | ||||
|                         PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; | ||||
|                         PosAndRot both = result->second; | ||||
|                         vecPos = both.vecPos; | ||||
|                         vecRot = both.vecRot; | ||||
|                     }*/ | ||||
|                     } | ||||
| 
 | ||||
|                     Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                     for(std::size_t i = 1; i < inds.size(); i++){ | ||||
|                         boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); | ||||
|                         if(useHandles) | ||||
|                             bonePtr = skel->getBone(boneinfocopy->bonehandle); | ||||
|                         else | ||||
|                             bonePtr = skel->getBone(boneinfocopy->bonename); | ||||
|                         vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; | ||||
|                             vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; | ||||
|                         result = vecRotPos.find(boneinfocopy); | ||||
| 
 | ||||
|                         /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){
 | ||||
| 
 | ||||
|                         if(result == vecRotPos.end()){ | ||||
|                             bonePtr = skel->getBone(boneinfocopy->bonename); | ||||
|                             vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; | ||||
|                             vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; | ||||
| 
 | ||||
|                             if(useHandles){ | ||||
|                                 PosAndRot both; | ||||
|                                 both.vecPos = vecPos; | ||||
|                                 both.vecRot = vecRot; | ||||
|                                 vecPosRot[boneinfocopy->bonehandle] = both; | ||||
|                             } | ||||
|                                 vecRotPos[boneinfocopy] = both; | ||||
| 
 | ||||
|                         } | ||||
|                          else{ | ||||
|                                 PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; | ||||
|                                 PosAndRot both = result->second; | ||||
|                                 vecPos = both.vecPos; | ||||
|                                 vecRot = both.vecRot; | ||||
|                         }*/ | ||||
|                         } | ||||
| 
 | ||||
| 
 | ||||
|                         absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; | ||||
| 
 | ||||
| 
 | ||||
|                     } | ||||
|                      Ogre::Real* addr = (pReal + 3 * verIndex); | ||||
| 							  *addr = absVertPos.x; | ||||
| 							  *(addr+1) = absVertPos.y; | ||||
| 				              *(addr+2) = absVertPos.z; | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
| #if 0 | ||||
| 				for (unsigned int i = 0; i < boneinfovector.size(); i++) | ||||
| 				{ | ||||
| 					Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[i]; | ||||
| 					if(skel->hasBone(boneinfo.bonename)){ | ||||
| 					Ogre::Bone *bonePtr = skel->getBone(boneinfo.bonename); | ||||
| 					Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans; | ||||
| 					Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation; | ||||
| 
 | ||||
| 					 for (unsigned int j=0; j < boneinfo.weights.size(); j++) | ||||
| 					 { | ||||
| 						  unsigned int verIndex = boneinfo.weights[j].vertex; | ||||
| 						  if(vertices.find(verIndex) == vertices.end()) | ||||
| 						  { | ||||
| 							  Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex]; | ||||
| 							  absVertPos = absVertPos * boneinfo.weights[j].weight; | ||||
| 							  vertices.insert(verIndex); | ||||
| 							   Ogre::Real* addr = (pReal + 3 * verIndex); | ||||
| 							  *addr = absVertPos.x; | ||||
| 							  *(addr+1) = absVertPos.y; | ||||
| 				              *(addr+2) = absVertPos.z; | ||||
| 
 | ||||
| 
 | ||||
| 						  } | ||||
| 						  else | ||||
| 						  { | ||||
| 
 | ||||
| 							   Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex]; | ||||
| 							   absVertPos = absVertPos * boneinfo.weights[j].weight; | ||||
| 							   Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex); | ||||
| 							   absVertPos = absVertPos + old; | ||||
| 							   Ogre::Real* addr = (pReal + 3 * verIndex); | ||||
| 							  *addr = absVertPos.x; | ||||
| 							  *(addr+1) = absVertPos.y; | ||||
| 				              *(addr+2) = absVertPos.z; | ||||
| 
 | ||||
| 							  //std::cout << "Vertex" << verIndex << "Weight: " << boneinfo.weights[i].weight << "was seen twice\n";
 | ||||
| 
 | ||||
| 						  } | ||||
| 
 | ||||
| 						  if(normals.find(verIndex) == normals.end()) | ||||
| 						  { | ||||
| 							  Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex]; | ||||
| 							  absNormalsPos = absNormalsPos * boneinfo.weights[j].weight; | ||||
| 							  normals.insert(verIndex); | ||||
| 							  Ogre::Real* addr = (pRealNormal + 3 * verIndex); | ||||
| 							  *addr = absNormalsPos.x; | ||||
| 				              *(addr+1) = absNormalsPos.y; | ||||
| 				              *(addr+2) = absNormalsPos.z; | ||||
| 						  } | ||||
| 						  else | ||||
| 						  { | ||||
| 							   Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex]; | ||||
| 							  absNormalsPos = absNormalsPos * boneinfo.weights[j].weight; | ||||
| 							 Ogre::Vector3 old = Ogre::Vector3(pRealNormal + 3 * verIndex); | ||||
| 							 absNormalsPos = absNormalsPos + old; | ||||
| 
 | ||||
| 							  Ogre::Real* addr = (pRealNormal + 3 * verIndex); | ||||
| 							  *addr = absNormalsPos.x; | ||||
| 				              *(addr+1) = absNormalsPos.y; | ||||
| 				              *(addr+2) = absNormalsPos.z; | ||||
| 
 | ||||
| 						  } | ||||
| #endif | ||||
| 					 //}
 | ||||
| 				//}
 | ||||
| 
 | ||||
| 
 | ||||
| 				//}   //Comment out
 | ||||
| 
 | ||||
| 				   ; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
|  | @ -329,11 +260,13 @@ namespace MWRender{ | |||
| 					Ogre::Vector3 shapetrans = copy.trafo.trans; | ||||
| 					float shapescale = copy.trafo.scale; | ||||
| 					std::vector<std::string> boneSequence = copy.boneSequence; | ||||
| 					std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin(); | ||||
| 
 | ||||
| 					Ogre::Vector3 transmult; | ||||
| 						Ogre::Quaternion rotmult; | ||||
| 						float scale; | ||||
| 					if(skel->hasBone(*boneSequenceIter)){ | ||||
| 					if(boneSequence.size() > 0){ | ||||
|                         std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin(); | ||||
|                         if(skel->hasBone(*boneSequenceIter)){ | ||||
| 					Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -360,6 +293,7 @@ namespace MWRender{ | |||
| 
 | ||||
| 						//std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n";
 | ||||
| 					} | ||||
|                     } | ||||
| 					else | ||||
| 					{ | ||||
| 						transmult = shapetrans; | ||||
|  | @ -392,7 +326,7 @@ namespace MWRender{ | |||
| 
 | ||||
| 				} | ||||
| 				vbuf->unlock(); | ||||
| 					//vbufNormal->unlock();
 | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
|     } | ||||
|  | @ -465,22 +399,18 @@ namespace MWRender{ | |||
| 
 | ||||
|          base->getAllAnimationStates()->_notifyDirty(); | ||||
|      //base->_updateAnimation();
 | ||||
|    base->_notifyMoved(); | ||||
|    //base->_notifyMoved();
 | ||||
| 
 | ||||
|     for(unsigned int i = 0; i < entityparts.size(); i++){ | ||||
|          Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton(); | ||||
|    for(unsigned int i = 0; i < entityparts.size(); i++){ | ||||
|          //Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton();
 | ||||
| 
 | ||||
|         Ogre::Bone* b = skel->getRootBone(); | ||||
| 	   b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick
 | ||||
| 
 | ||||
|         skel->_updateTransforms(); | ||||
| 	   // skel->_notifyManualBonesDirty();
 | ||||
| 
 | ||||
|          entityparts[i]->getAllAnimationStates()->_notifyDirty(); | ||||
|         //entityparts[i]->_updateAnimation();
 | ||||
|          entityparts[i]->_notifyMoved(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     std::vector<Nif::NiKeyframeData>::iterator iter; | ||||
|     int slot = 0; | ||||
|     if(transformations){ | ||||
|  | @ -488,9 +418,7 @@ namespace MWRender{ | |||
|         if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) | ||||
| 	    { | ||||
|             slot++; | ||||
|             //iter++;
 | ||||
| 		    continue; | ||||
| 
 | ||||
| 	    } | ||||
| 
 | ||||
|          float x; | ||||
|  | @ -511,7 +439,6 @@ namespace MWRender{ | |||
| 
 | ||||
|         timeIndex(time, ttime, tindexI[slot], tindexJ, x); | ||||
| 
 | ||||
| 		//std::cout << "X: " << x << " X2: " << x2 << "\n";
 | ||||
|         Ogre::Vector3 t; | ||||
|         Ogre::Quaternion r; | ||||
| 
 | ||||
|  | @ -526,7 +453,6 @@ namespace MWRender{ | |||
|         bool bQuats = quats.size() > 0; | ||||
| 	    if(bQuats){ | ||||
| 		    r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); | ||||
| 		    //bone->setOrientation(r);
 | ||||
| 	    } | ||||
|         skel = base->getSkeleton(); | ||||
|     if(skel->hasBone(iter->getBonename())){ | ||||
|  | @ -539,27 +465,10 @@ namespace MWRender{ | |||
| 
 | ||||
| 
 | ||||
|         skel->_updateTransforms(); | ||||
| 	    //skel->_notifyManualBonesDirty();
 | ||||
|         base->getAllAnimationStates()->_notifyDirty(); | ||||
|         //base->_updateAnimation();
 | ||||
| 	    base->_notifyMoved(); | ||||
| 	} | ||||
|     for(std::size_t i = 0; i < entityparts.size(); i++){ | ||||
|         skel = entityparts[i]->getSkeleton(); | ||||
|          if(skel->hasBone(iter->getBonename())){ | ||||
|             Ogre::Bone* bone = skel->getBone(iter->getBonename()); | ||||
|             if(bTrans) | ||||
|                 bone->setPosition(t); | ||||
|             if(bQuats) | ||||
|                 bone->setOrientation(r); | ||||
| 
 | ||||
|             skel->_updateTransforms(); | ||||
| 	        //skel->_notifyManualBonesDirty();
 | ||||
|             entityparts[i]->getAllAnimationStates()->_notifyDirty(); | ||||
|            // entityparts[i]->_updateAnimation();
 | ||||
| 	        entityparts[i]->_notifyMoved(); | ||||
| 	    } | ||||
|     } | ||||
| 	} | ||||
| 
 | ||||
|     slot++; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ class Animation{ | |||
|     Ogre::SceneNode* insert; | ||||
|     OEngine::Render::OgreRenderer &mRend; | ||||
|     MWWorld::Environment& mEnvironment; | ||||
|     std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot> vecRotPos; | ||||
|     static std::map<std::string, int> mUniqueIDs; | ||||
|      | ||||
|     | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environme | |||
| } | ||||
| 
 | ||||
| void CreatureAnimation::runAnimation(float timepassed){ | ||||
|     vecRotPos.clear(); | ||||
| 	if(animate > 0){ | ||||
| 		//Add the amount of time passed to time
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O | |||
| 		char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); | ||||
| 		bool female = tolower(secondtolast) == 'f'; | ||||
| 		bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; | ||||
| 
 | ||||
|         /*std::cout << "Race: " << ref->base->race ;
 | ||||
|         if(female){ | ||||
|            std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; | ||||
|  | @ -67,6 +68,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O | |||
|                                                //stay in the same place when we skipanim, or open a gui window
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ | ||||
| 
 | ||||
|         for(unsigned int init = 0; init < transformations->size(); init++){ | ||||
|  | @ -177,7 +179,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O | |||
| 		if(clavicler) | ||||
| 			insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/ | ||||
| 
 | ||||
| 
 | ||||
| 		if(neck) | ||||
| 		{ | ||||
| 			insertBoundedPart("meshes\\" + neck->model, "Neck"); | ||||
|  | @ -213,6 +214,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O | |||
| } | ||||
| 
 | ||||
| Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ | ||||
|     | ||||
|     NIFLoader::load(mesh); | ||||
|     Entity* ent = mRend.getScene()->createEntity(mesh); | ||||
| 
 | ||||
|  | @ -225,15 +227,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf | |||
| 
 | ||||
|     Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered); | ||||
| 
 | ||||
|         /*MaterialPtr material = ent->getSubEntity(0)->getMaterial();
 | ||||
|         material->removeAllTechniques(); | ||||
| 
 | ||||
|         Ogre::Technique* tech = material->createTechnique(); | ||||
| 
 | ||||
|          Pass* pass2 = tech->createPass(); | ||||
|         pass2->setVertexProgram("Ogre/HardwareSkinningTwoWeights"); | ||||
|         pass2->setColourWriteEnabled(false); | ||||
|         //tech->setSchemeName("blahblah");*/
 | ||||
|       | ||||
| 
 | ||||
| 
 | ||||
|     insert->attachObject(ent); | ||||
|  | @ -249,6 +243,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf | |||
| 
 | ||||
| 
 | ||||
| void NpcAnimation::runAnimation(float timepassed){ | ||||
|      | ||||
|     //1. Add the amount of time passed to time
 | ||||
| 
 | ||||
| 	//2. Handle the animation transforms dependent on time
 | ||||
|  | @ -267,22 +262,17 @@ void NpcAnimation::runAnimation(float timepassed){ | |||
|         } | ||||
| 
 | ||||
|         handleAnimationTransforms(); | ||||
|         Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); | ||||
| 
 | ||||
|         std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin(); | ||||
|         std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin(); | ||||
|         while(shapepartsiter != shapeparts.end()) | ||||
|         { | ||||
|             vecRotPos.clear(); | ||||
|             std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter; | ||||
|             Ogre::Entity* theentity = *entitypartsiter; | ||||
|             /*
 | ||||
|             Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0); | ||||
|             if (pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded()) | ||||
|                 std::cout << "It's hardware\n"; | ||||
|                 else | ||||
|                 std::cout << "It's software\n";*/ | ||||
| 
 | ||||
|             handleShapes(shapes, theentity, theentity->getSkeleton()); | ||||
| 
 | ||||
|             handleShapes(shapes, theentity, base->getSkeleton()); | ||||
|             shapepartsiter++; | ||||
|             entitypartsiter++; | ||||
|         } | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| #include "objects.hpp" | ||||
| 
 | ||||
| #include <OgreSceneNode.h> | ||||
| 
 | ||||
| #include <components/nifogre/ogre_nif_loader.hpp> | ||||
| 
 | ||||
| using namespace Ogre; | ||||
| using namespace MWRender; | ||||
| 
 | ||||
| 
 | ||||
| bool Objects::lightConst = false; | ||||
| float Objects::lightConstValue = 0.0f; | ||||
| 
 | ||||
|  | @ -23,10 +23,24 @@ bool Objects::lightOutQuadInLin = false; | |||
| 
 | ||||
| int Objects::uniqueID = 0; | ||||
| 
 | ||||
| void Objects::setMwRoot(Ogre::SceneNode* root){ | ||||
| void Objects::clearSceneNode (Ogre::SceneNode *node) | ||||
| { | ||||
|     /// \todo This should probably be moved into OpenEngine at some point.
 | ||||
|     for (int i=node->numAttachedObjects()-1; i>=0; --i) | ||||
|     { | ||||
|         Ogre::MovableObject *object = node->getAttachedObject (i); | ||||
|         node->detachObject (object); | ||||
|         mRenderer.getScene()->destroyMovableObject (object); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Objects::setMwRoot(Ogre::SceneNode* root) | ||||
| { | ||||
|     mMwRoot = root; | ||||
| } | ||||
| void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ | ||||
| 
 | ||||
| void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_) | ||||
| { | ||||
|     Ogre::SceneNode* root = mMwRoot; | ||||
|     Ogre::SceneNode* cellnode; | ||||
|     if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) | ||||
|  | @ -49,90 +63,98 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ | |||
|     f = ptr.getCellRef().pos.rot; | ||||
| 
 | ||||
|     // Rotate around X axis
 | ||||
|     Quaternion xr(Radian(-f[0]), Vector3::UNIT_X); | ||||
|     Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); | ||||
| 
 | ||||
|     // Rotate around Y axis
 | ||||
|     Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y); | ||||
|     Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y); | ||||
| 
 | ||||
|     // Rotate around Z axis
 | ||||
|     Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z); | ||||
|     Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z); | ||||
| 
 | ||||
|    // Rotates first around z, then y, then x
 | ||||
|     // Rotates first around z, then y, then x
 | ||||
|     insert->setOrientation(xr*yr*zr); | ||||
| 
 | ||||
|     if (!enabled) | ||||
|          insert->setVisible (false); | ||||
|     ptr.getRefData().setBaseNode(insert); | ||||
|     isStatic = static_; | ||||
| 
 | ||||
| 
 | ||||
|     mIsStatic = static_; | ||||
| } | ||||
| void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){ | ||||
| 
 | ||||
| void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) | ||||
| { | ||||
|     Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); | ||||
|     assert(insert); | ||||
| 
 | ||||
|     NifOgre::NIFLoader::load(mesh); | ||||
|     Entity *ent = mRend.getScene()->createEntity(mesh); | ||||
|     Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh); | ||||
| 
 | ||||
|     if(!isStatic) | ||||
|     if(!mIsStatic) | ||||
|     { | ||||
|         insert->attachObject(ent); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Ogre::StaticGeometry* sg = 0; | ||||
|         if(mSG.find(ptr.getCell()) == mSG.end()) | ||||
|         if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) | ||||
|         { | ||||
|             uniqueID = uniqueID +1; | ||||
|             sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); | ||||
|             sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); | ||||
|             //Create the scenenode and put it in the map
 | ||||
|             mSG[ptr.getCell()] = sg; | ||||
|             mStaticGeometry[ptr.getCell()] = sg; | ||||
| 
 | ||||
|             // This specifies the size of a single batch region.
 | ||||
|             // If it is set too high:
 | ||||
|             //  - there will be problems choosing the correct lights
 | ||||
|             //  - the culling will be more inefficient
 | ||||
|             // If it is set too low:
 | ||||
|             //  - there will be too many batches.
 | ||||
|             sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             sg = mSG[ptr.getCell()]; | ||||
|             sg = mStaticGeometry[ptr.getCell()]; | ||||
|         } | ||||
| 
 | ||||
|         sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); | ||||
|         sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000)); | ||||
| 
 | ||||
| 
 | ||||
|         mRend.getScene()->destroyEntity(ent); | ||||
|         mRenderer.getScene()->destroyEntity(ent); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){ | ||||
|     Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle()); | ||||
| 
 | ||||
| void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius) | ||||
| { | ||||
|     Ogre::SceneNode* insert = mRenderer.getScene()->getSceneNode(ptr.getRefData().getHandle()); | ||||
|     assert(insert); | ||||
|     Ogre::Light *light = mRend.getScene()->createLight(); | ||||
|     Ogre::Light *light = mRenderer.getScene()->createLight(); | ||||
|     light->setDiffuseColour (r, g, b); | ||||
| 
 | ||||
|     float cval=0.0f, lval=0.0f, qval=0.0f; | ||||
| 
 | ||||
|     if(lightConst) | ||||
|          cval = lightConstValue; | ||||
|   if(!lightOutQuadInLin) | ||||
|   { | ||||
|     if(lightLinear) | ||||
|       radius *= lightLinearRadiusMult; | ||||
|     if(lightQuadratic) | ||||
|       radius *= lightQuadraticRadiusMult; | ||||
| 
 | ||||
|     if(lightLinear) | ||||
|       lval = lightLinearValue / pow(radius, lightLinearMethod); | ||||
|     if(lightQuadratic) | ||||
|       qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     // FIXME:
 | ||||
|     // Do quadratic or linear, depending if we're in an exterior or interior
 | ||||
|     // cell, respectively. Ignore lightLinear and lightQuadratic.
 | ||||
|   } | ||||
|     if(!lightOutQuadInLin) | ||||
|     { | ||||
|         if(lightLinear) | ||||
|             radius *= lightLinearRadiusMult; | ||||
|         if(lightQuadratic) | ||||
|             radius *= lightQuadraticRadiusMult; | ||||
| 
 | ||||
|   light->setAttenuation(10*radius, cval, lval, qval); | ||||
|         if(lightLinear) | ||||
|             lval = lightLinearValue / pow(radius, lightLinearMethod); | ||||
|         if(lightQuadratic) | ||||
|             qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // FIXME:
 | ||||
|         // Do quadratic or linear, depending if we're in an exterior or interior
 | ||||
|         // cell, respectively. Ignore lightLinear and lightQuadratic.
 | ||||
|     } | ||||
| 
 | ||||
|   insert->attachObject(light); | ||||
|     light->setAttenuation(10*radius, cval, lval, qval); | ||||
| 
 | ||||
|     insert->attachObject(light); | ||||
| } | ||||
| 
 | ||||
| bool Objects::deleteObject (const MWWorld::Ptr& ptr) | ||||
|  | @ -145,8 +167,9 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr) | |||
|             mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) | ||||
|             if (iter->second==parent) | ||||
|             { | ||||
|                 clearSceneNode (base); | ||||
|                 base->removeAndDestroyAllChildren(); | ||||
|                 mRend.getScene()->destroySceneNode (base); | ||||
|                 mRenderer.getScene()->destroySceneNode (base); | ||||
|                 ptr.getRefData().setBaseNode (0); | ||||
|                 return true; | ||||
|             } | ||||
|  | @ -157,29 +180,35 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr) | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void Objects::removeCell(MWWorld::Ptr::CellStore* store){ | ||||
| void Objects::removeCell(MWWorld::Ptr::CellStore* store) | ||||
| { | ||||
|     if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) | ||||
|     { | ||||
|         Ogre::SceneNode* base = mCellSceneNodes[store]; | ||||
| 
 | ||||
|         for (int i=0; i<base->numChildren(); ++i) | ||||
|             clearSceneNode (static_cast<Ogre::SceneNode *> (base->getChild (i))); | ||||
| 
 | ||||
|         base->removeAndDestroyAllChildren(); | ||||
|         mCellSceneNodes.erase(store); | ||||
|         mRend.getScene()->destroySceneNode(base); | ||||
|         mRenderer.getScene()->destroySceneNode(base); | ||||
|         base = 0; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     if(mSG.find(store) != mSG.end()) | ||||
|     if(mStaticGeometry.find(store) != mStaticGeometry.end()) | ||||
|     { | ||||
|         Ogre::StaticGeometry* sg = mSG[store]; | ||||
|         mSG.erase(store); | ||||
|         mRend.getScene()->destroyStaticGeometry (sg); | ||||
|         Ogre::StaticGeometry* sg = mStaticGeometry[store]; | ||||
|         mStaticGeometry.erase(store); | ||||
|         mRenderer.getScene()->destroyStaticGeometry (sg); | ||||
|         sg = 0; | ||||
|     } | ||||
| } | ||||
| void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell){ | ||||
|     if(mSG.find(&cell) != mSG.end()) | ||||
| 
 | ||||
| void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell) | ||||
| { | ||||
|     if(mStaticGeometry.find(&cell) != mStaticGeometry.end()) | ||||
|     { | ||||
|         Ogre::StaticGeometry* sg = mSG[&cell]; | ||||
|         Ogre::StaticGeometry* sg = mStaticGeometry[&cell]; | ||||
|         sg->build(); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,20 +1,21 @@ | |||
| #ifndef _GAME_RENDER_OBJECTS_H | ||||
| #define _GAME_RENDER_OBJECTS_H | ||||
| 
 | ||||
| #include "components/esm_store/cell_store.hpp" | ||||
| #include <openengine/ogre/renderer.hpp> | ||||
| 
 | ||||
| #include <components/esm_store/cell_store.hpp> | ||||
| 
 | ||||
| #include "../mwworld/refdata.hpp" | ||||
| #include "../mwworld/ptr.hpp" | ||||
| #include <openengine/ogre/renderer.hpp> | ||||
| 
 | ||||
| namespace MWRender{ | ||||
| 
 | ||||
| class Objects{ | ||||
|     OEngine::Render::OgreRenderer &mRend; | ||||
|     OEngine::Render::OgreRenderer &mRenderer; | ||||
|     std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes; | ||||
|     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mSG; | ||||
|     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry; | ||||
|     Ogre::SceneNode* mMwRoot; | ||||
|     bool isStatic; | ||||
|     bool mIsStatic; | ||||
|     static int uniqueID; | ||||
|     static bool lightConst; | ||||
|     static float lightConstValue; | ||||
|  | @ -30,8 +31,12 @@ class Objects{ | |||
|     static float lightQuadraticRadiusMult; | ||||
| 
 | ||||
|     static bool lightOutQuadInLin; | ||||
| 
 | ||||
|     void clearSceneNode (Ogre::SceneNode *node); | ||||
|     ///< Remove all movable objects from \a node.
 | ||||
| 
 | ||||
| public: | ||||
|     Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){} | ||||
|     Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){} | ||||
|     ~Objects(){} | ||||
|     void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); | ||||
|     void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); | ||||
|  |  | |||
|  | @ -20,10 +20,9 @@ using namespace Ogre; | |||
| namespace MWRender { | ||||
| 
 | ||||
| RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) | ||||
| :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mDebugging(engine) | ||||
| :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine) | ||||
| { | ||||
|     mRendering.createScene("PlayerCam", 55, 5); | ||||
|     mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), resDir); | ||||
| 
 | ||||
|     // Set default mipmap level (NB some APIs ignore this)
 | ||||
|     TextureManager::getSingleton().setDefaultNumMipmaps(5); | ||||
|  | @ -41,7 +40,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const | |||
|     mMwRoot->pitch(Degree(-90)); | ||||
|     mObjects.setMwRoot(mMwRoot); | ||||
|     mActors.setMwRoot(mMwRoot); | ||||
| 
 | ||||
|          | ||||
|     //used to obtain ingame information of ogre objects (which are faced or selected)
 | ||||
|     mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray()); | ||||
| 
 | ||||
|  | @ -50,6 +49,9 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const | |||
|     Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); | ||||
|     Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); | ||||
|     cameraPitchNode->attachObject(mRendering.getCamera()); | ||||
|      | ||||
|     //mSkyManager = 0;
 | ||||
|     mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); | ||||
| 
 | ||||
|     mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); | ||||
|     mSun = 0; | ||||
|  | @ -62,6 +64,10 @@ RenderingManager::~RenderingManager () | |||
|     delete mSkyManager; | ||||
| } | ||||
| 
 | ||||
| MWRender::SkyManager* RenderingManager::getSkyManager() | ||||
| { | ||||
|     return mSkyManager; | ||||
| } | ||||
| 
 | ||||
| MWRender::Objects& RenderingManager::getObjects(){ | ||||
|     return mObjects; | ||||
|  | @ -74,6 +80,11 @@ MWRender::Player& RenderingManager::getPlayer(){ | |||
|     return (*mPlayer); | ||||
| } | ||||
| 
 | ||||
| OEngine::Render::Fader* RenderingManager::getFader() | ||||
| { | ||||
|     return mRendering.getFader(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){ | ||||
|     mObjects.removeCell(store); | ||||
|     mActors.removeCell(store); | ||||
|  | @ -122,31 +133,40 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve | |||
| void RenderingManager::update (float duration){ | ||||
| 
 | ||||
|     mActors.update (duration); | ||||
|      | ||||
|     mSkyManager->update(duration); | ||||
|      | ||||
|     mRendering.update(duration); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::skyEnable () | ||||
| { | ||||
|     if(mSkyManager) | ||||
|     mSkyManager->enable(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::skyDisable () | ||||
| { | ||||
|     mSkyManager->disable(); | ||||
|     if(mSkyManager) | ||||
|         mSkyManager->disable(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::skySetHour (double hour) | ||||
| { | ||||
|     mSkyManager->setHour(hour); | ||||
|     if(mSkyManager) | ||||
|         mSkyManager->setHour(hour); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void RenderingManager::skySetDate (int day, int month) | ||||
| { | ||||
|     mSkyManager->setDate(day, month); | ||||
|     if(mSkyManager) | ||||
|         mSkyManager->setDate(day, month); | ||||
| } | ||||
| 
 | ||||
| int RenderingManager::skyGetMasserPhase() const | ||||
| { | ||||
|     | ||||
|     return mSkyManager->getMasserPhase(); | ||||
| } | ||||
| 
 | ||||
|  | @ -155,12 +175,28 @@ int RenderingManager::skyGetSecundaPhase() const | |||
|     return mSkyManager->getSecundaPhase(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::skySetMoonColour (bool red) | ||||
| { | ||||
|     mSkyManager->setMoonColour(red); | ||||
| void RenderingManager::skySetMoonColour (bool red){ | ||||
|     if(mSkyManager) | ||||
|         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) | ||||
|  | @ -168,14 +204,22 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell) | |||
|   Ogre::ColourValue color; | ||||
|   color.setAsABGR (mCell.cell->ambi.fog); | ||||
| 
 | ||||
|   float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity); | ||||
|   float low = 200; | ||||
| 
 | ||||
|   mRendering.getScene()->setFog (FOG_LINEAR, color, 0, low, high); | ||||
|   mRendering.getCamera()->setFarClipDistance (high + 10); | ||||
|   mRendering.getViewport()->setBackgroundColour (color); | ||||
|   configureFog(mCell.cell->ambi.fogDensity, color); | ||||
| } | ||||
| 
 | ||||
| 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.getCamera()->setFarClipDistance ( high ); | ||||
|   mRendering.getViewport()->setBackgroundColour (colour); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void RenderingManager::setAmbientMode() | ||||
| { | ||||
|   switch (mAmbientMode) | ||||
|  | @ -244,4 +288,38 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& 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 <openengine/ogre/renderer.hpp> | ||||
| #include <openengine/ogre/fader.hpp> | ||||
| #include <openengine/bullet/physic.hpp> | ||||
| 
 | ||||
| #include <vector> | ||||
|  | @ -61,8 +62,12 @@ class RenderingManager: private RenderingInterface { | |||
|                                             /// MWWorld::Player has been rewritten to not need access
 | ||||
|                                             /// to internal details of the rendering system anymore
 | ||||
| 
 | ||||
|     SkyManager* getSkyManager(); | ||||
| 
 | ||||
|     void toggleLight(); | ||||
|     bool toggleRenderMode(int mode); | ||||
|      | ||||
|     OEngine::Render::Fader* getFader(); | ||||
| 
 | ||||
|     void removeCell (MWWorld::Ptr::CellStore *store); | ||||
| 
 | ||||
|  | @ -81,7 +86,14 @@ class RenderingManager: private RenderingInterface { | |||
|     void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store); | ||||
| 
 | ||||
|     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 skyDisable (); | ||||
|     void skySetHour (double hour); | ||||
|  | @ -90,9 +102,13 @@ class RenderingManager: private RenderingInterface { | |||
|     int skyGetSecundaPhase() const; | ||||
|     void skySetMoonColour (bool red); | ||||
|     void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell); | ||||
|      | ||||
|     /// configure fog according to cell
 | ||||
|     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, | ||||
|         int number = 1); | ||||
|     ///< 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: | ||||
| 
 | ||||
|     void setAmbientMode(); | ||||
|      | ||||
|     SkyManager* mSkyManager; | ||||
|      | ||||
|     OEngine::Render::OgreRenderer &mRendering; | ||||
| 
 | ||||
|     MWRender::Objects mObjects; | ||||
|  |  | |||
|  | @ -1,116 +1,764 @@ | |||
| #include "sky.hpp" | ||||
| #include "Caelum.h" | ||||
| 
 | ||||
| namespace MWRender | ||||
| #include <OgreCamera.h> | ||||
| #include <OgreRenderWindow.h> | ||||
| #include <OgreSceneNode.h> | ||||
| #include <OgreMesh.h> | ||||
| #include <OgreSceneManager.h> | ||||
| #include <OgreHardwareVertexBuffer.h> | ||||
| #include <OgreHighLevelGpuProgramManager.h> | ||||
| 
 | ||||
| #include <components/nifogre/ogre_nif_loader.hpp> | ||||
| 
 | ||||
| using namespace MWRender; | ||||
| using namespace Ogre; | ||||
| 
 | ||||
| // the speed at which the clouds are animated
 | ||||
| #define CLOUD_SPEED 0.001 | ||||
| 
 | ||||
| // this distance has to be set accordingly so that the
 | ||||
| // celestial bodies are behind the clouds, but in front of the atmosphere
 | ||||
| #define CELESTIAL_BODY_DISTANCE 1000.f | ||||
| 
 | ||||
| BillboardObject::BillboardObject( const String& textureName, | ||||
|                     const float initialSize, | ||||
|                     const Vector3& position, | ||||
|                     SceneNode* rootNode) | ||||
| { | ||||
|     //
 | ||||
|     // 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 | ||||
|     init(textureName, initialSize, position, rootNode); | ||||
| } | ||||
| 
 | ||||
| BillboardObject::BillboardObject() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void BillboardObject::setVisible(const bool visible) | ||||
| { | ||||
|     mNode->setVisible(visible); | ||||
| } | ||||
| 
 | ||||
| void BillboardObject::setSize(const float size) | ||||
| { | ||||
|     mNode->setScale(size, size, size); | ||||
| } | ||||
| 
 | ||||
| void BillboardObject::setVisibility(const float visibility) | ||||
| { | ||||
|     mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility); | ||||
| } | ||||
| 
 | ||||
| void BillboardObject::setPosition(const Vector3& pPosition) | ||||
| { | ||||
|     Vector3 normalised = pPosition.normalisedCopy(); | ||||
|     Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE; | ||||
| 
 | ||||
|     mBBSet->setCommonDirection( -normalised ); | ||||
| 
 | ||||
|     mNode->setPosition(finalPosition); | ||||
| } | ||||
| 
 | ||||
| Vector3 BillboardObject::getPosition() const | ||||
| { | ||||
|     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(); | ||||
| 
 | ||||
|     Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE; | ||||
| 
 | ||||
|     static unsigned int bodyCount=0; | ||||
| 
 | ||||
|     /// \todo These billboards are not 100% correct, might want to revisit them later
 | ||||
|     mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1); | ||||
|     mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize); | ||||
|     mBBSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2); | ||||
|     mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON); | ||||
|     mBBSet->setCommonDirection( -position.normalisedCopy() ); | ||||
|     mNode = rootNode->createChildSceneNode(); | ||||
|     mNode->setPosition(finalPosition); | ||||
|     mNode->attachObject(mBBSet); | ||||
|     mBBSet->createBillboard(0,0,0); | ||||
| 
 | ||||
|     mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); | ||||
|     mMaterial->removeAllTechniques(); | ||||
|     Pass* p = mMaterial->createTechnique()->createPass(); | ||||
|     p->setSceneBlending(SBT_TRANSPARENT_ALPHA); | ||||
|     p->setDepthCheckEnabled(false); | ||||
|     p->setDepthWriteEnabled(false); | ||||
|     p->setSelfIllumination(1.0,1.0,1.0); | ||||
|     p->setDiffuse(0.0,0.0,0.0,1.0); | ||||
|     p->setAmbient(0.0,0.0,0.0); | ||||
|     p->createTextureUnitState(textureName); | ||||
|     mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); | ||||
| 
 | ||||
|     bodyCount++; | ||||
| } | ||||
| 
 | ||||
| Moon::Moon( const String& textureName, | ||||
|                     const float initialSize, | ||||
|                     const Vector3& position, | ||||
|                     SceneNode* rootNode) | ||||
| { | ||||
|     init(textureName, initialSize, position, rootNode); | ||||
| 
 | ||||
|     HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); | ||||
|     HighLevelGpuProgramPtr vshader; | ||||
|     if (mgr.resourceExists("Moon_VP")) | ||||
|         vshader = mgr.getByName("Moon_VP"); | ||||
|     else | ||||
|         vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); | ||||
|     vshader->setParameter("profiles", "vs_2_x arbvp1"); | ||||
|     vshader->setParameter("entry_point", "main_vp"); | ||||
|     StringUtil::StrStreamType outStream; | ||||
|     outStream << | ||||
|     "void main_vp(	\n" | ||||
|     "	float4 position : POSITION,	\n" | ||||
|     "   in float2 uv : TEXCOORD0, \n" | ||||
|     "   out float2 oUV : TEXCOORD0, \n" | ||||
|     "	out float4 oPosition : POSITION,	\n" | ||||
|     "	uniform float4x4 worldViewProj	\n" | ||||
|     ")	\n" | ||||
|     "{	\n" | ||||
|     "   oUV = uv; \n" | ||||
|     "	oPosition = mul( worldViewProj, position );  \n" | ||||
|     "}"; | ||||
|     vshader->setSource(outStream.str()); | ||||
|     vshader->load(); | ||||
|     vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); | ||||
|     mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); | ||||
| 
 | ||||
|     HighLevelGpuProgramPtr fshader; | ||||
|     if (mgr.resourceExists("Moon_FP")) | ||||
|         fshader = mgr.getByName("Moon_FP"); | ||||
|     else | ||||
|         fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); | ||||
| 
 | ||||
|     fshader->setParameter("profiles", "ps_2_x arbfp1"); | ||||
|     fshader->setParameter("entry_point", "main_fp"); | ||||
|     StringUtil::StrStreamType outStream2; | ||||
|     outStream2 << | ||||
|     "void main_fp(	\n" | ||||
|     "   in float2 uv : TEXCOORD0, \n" | ||||
|     "	out float4 oColor    : COLOR, \n" | ||||
|     "   uniform sampler2D texture : TEXUNIT0, \n" | ||||
|     "   uniform float4 diffuse, \n" | ||||
|     "   uniform float4 emissive \n" | ||||
|     ")	\n" | ||||
|     "{	\n" | ||||
|     "   float4 tex = tex2D(texture, uv); \n" | ||||
|     "   oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n" | ||||
|     "   float bump = pow((1-diffuse.a),4); \n" | ||||
|     "   oColor.rgb += float3(bump, bump, bump)*0.5; \n" | ||||
|     "}"; | ||||
|     fshader->setSource(outStream2.str()); | ||||
|     fshader->load(); | ||||
|     fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); | ||||
|     fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); | ||||
|     mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); | ||||
| 
 | ||||
|     setVisibility(1.0); | ||||
| 
 | ||||
|     mPhase = Moon::Phase_Full; | ||||
| } | ||||
| 
 | ||||
| void Moon::setType(const Moon::Type& type) | ||||
| { | ||||
|     mType = type; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
 | ||||
| void Moon::setPhase(const Moon::Phase& phase) | ||||
| { | ||||
|     Ogre::String textureName = "textures\\tx_"; | ||||
| 
 | ||||
|     if (mType == Moon::Type_Secunda) textureName += "secunda_"; | ||||
|     else textureName += "masser_"; | ||||
| 
 | ||||
|     if      (phase == Moon::Phase_New)              textureName += "new"; | ||||
|     else if (phase == Moon::Phase_WaxingCrescent)   textureName += "one_wax"; | ||||
|     else if (phase == Moon::Phase_WaxingHalf)       textureName += "half_wax"; | ||||
|     else if (phase == Moon::Phase_WaxingGibbous)    textureName += "three_wax"; | ||||
|     else if (phase == Moon::Phase_WaningCrescent)   textureName += "one_wan"; | ||||
|     else if (phase == Moon::Phase_WaningHalf)       textureName += "half_wan"; | ||||
|     else if (phase == Moon::Phase_WaningGibbous)    textureName += "three_wan"; | ||||
|     else if (phase == Moon::Phase_Full)             textureName += "full"; | ||||
| 
 | ||||
|     textureName += ".dds"; | ||||
| 
 | ||||
|     mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName); | ||||
| 
 | ||||
|     mPhase = phase; | ||||
| } | ||||
| 
 | ||||
| Moon::Phase Moon::getPhase() const | ||||
| { | ||||
|     return mPhase; | ||||
| } | ||||
| 
 | ||||
| unsigned int Moon::getPhaseInt() const | ||||
| { | ||||
|     if      (mPhase == Moon::Phase_New)              return 0; | ||||
|     else if (mPhase == Moon::Phase_WaxingCrescent)   return 1; | ||||
|     else if (mPhase == Moon::Phase_WaningCrescent)   return 1; | ||||
|     else if (mPhase == Moon::Phase_WaxingHalf)       return 2; | ||||
|     else if (mPhase == Moon::Phase_WaningHalf)       return 2; | ||||
|     else if (mPhase == Moon::Phase_WaxingGibbous)    return 3; | ||||
|     else if (mPhase == Moon::Phase_WaningGibbous)    return 3; | ||||
|     else if (mPhase == Moon::Phase_Full)             return 4; | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) | ||||
| { | ||||
|     // Get the vertex colour buffer of this mesh
 | ||||
|     const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE ); | ||||
|     HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource()); | ||||
| 
 | ||||
|     // Lock
 | ||||
|     void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL); | ||||
| 
 | ||||
|     // Iterate over all vertices
 | ||||
|     int vertex_size = colourBuffer->getVertexSize(); | ||||
|     float * currentVertex = NULL; | ||||
|     for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i) | ||||
|     { | ||||
|     protected: | ||||
|         Caelum::CaelumSystem*   mpCaelumSystem; | ||||
|         // Get a pointer to the vertex colour
 | ||||
|         ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex ); | ||||
| 
 | ||||
|     public: | ||||
|                  CaelumManager (Ogre::RenderWindow* pRenderWindow,  | ||||
|                                    Ogre::Camera* pCamera, | ||||
|                                    const boost::filesystem::path& resDir); | ||||
|         virtual ~CaelumManager (); | ||||
|          | ||||
|         virtual void enable() {} | ||||
|          | ||||
|         virtual void disable() {} | ||||
|          | ||||
|         virtual void setHour (double hour) {} | ||||
|         ///< will be called even when sky is disabled.
 | ||||
|          | ||||
|         virtual void setDate (int day, int month) {} | ||||
|         ///< will be called even when sky is disabled.
 | ||||
|          | ||||
|         virtual int getMasserPhase() const { return 0; } | ||||
|         ///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
 | ||||
|         /// 3 waxing or waning gibbous, 4 full moon
 | ||||
|          | ||||
|         virtual int getSecundaPhase() const { return 0; } | ||||
|         ///< 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) {} | ||||
|     }; | ||||
| 
 | ||||
|     CaelumManager::CaelumManager (Ogre::RenderWindow* pRenderWindow,  | ||||
|                                   Ogre::Camera* pCamera, | ||||
|                                   const boost::filesystem::path& resDir) | ||||
|         : mpCaelumSystem        (NULL) | ||||
|     { | ||||
|         using namespace Ogre; | ||||
|         using namespace Caelum; | ||||
| 
 | ||||
|         assert(pCamera); | ||||
|         assert(pRenderWindow); | ||||
| 
 | ||||
|         // Load the Caelum resources
 | ||||
|         //
 | ||||
|         ResourceGroupManager::getSingleton().addResourceLocation((resDir / "caelum").string(), "FileSystem", "Caelum"); | ||||
|         ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); | ||||
| 
 | ||||
|         // Load the Caelum resources
 | ||||
|         //
 | ||||
|         Ogre::SceneManager* pScene = pCamera->getSceneManager(); | ||||
|         Caelum::CaelumSystem::CaelumComponent componentMask = CaelumSystem::CAELUM_COMPONENTS_DEFAULT; | ||||
|         mpCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), pScene, componentMask); | ||||
|          | ||||
|         // Set time acceleration.
 | ||||
|         mpCaelumSystem->getUniversalClock()->setTimeScale(128);        | ||||
| 
 | ||||
|         // Disable fog since OpenMW is handling OGRE fog elsewhere
 | ||||
|         mpCaelumSystem->setManageSceneFog(false); | ||||
| 
 | ||||
|         // Change the camera far distance to make sure the sky is not clipped
 | ||||
|         pCamera->setFarClipDistance(50000); | ||||
| 
 | ||||
|         // Register Caelum as an OGRE listener
 | ||||
|         pRenderWindow->addListener(mpCaelumSystem); | ||||
|         Root::getSingletonPtr()->addFrameListener(mpCaelumSystem); | ||||
|     } | ||||
| 
 | ||||
|     CaelumManager::~CaelumManager()  | ||||
|     { | ||||
|         if (mpCaelumSystem)  | ||||
|             mpCaelumSystem->shutdown (false); | ||||
|     } | ||||
| 
 | ||||
|     /// Creates and connects the sky rendering component to OGRE.
 | ||||
|     ///
 | ||||
|     /// \return NULL on failure.
 | ||||
|     /// 
 | ||||
|     SkyManager* SkyManager::create (Ogre::RenderWindow* pRenderWindow,  | ||||
|                                     Ogre::Camera*       pCamera, | ||||
|                                     const boost::filesystem::path& resDir) | ||||
|     { | ||||
|         SkyManager* pSkyManager = NULL; | ||||
| 
 | ||||
|         try | ||||
|         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) | ||||
|         { | ||||
|             pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir); | ||||
|         } | ||||
|         catch (Ogre::Exception& e) | ||||
|         { | ||||
|             std::cout << "\nOGRE Exception when attempting to add sky: "  | ||||
|                 << e.getFullDescription().c_str() << std::endl; | ||||
|         } | ||||
|         catch (std::exception& e) | ||||
|         { | ||||
|             std::cout << "\nException when attempting to add sky: "  | ||||
|                 << e.what() << std::endl; | ||||
|             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; | ||||
|         } | ||||
| 
 | ||||
|         return pSkyManager; | ||||
|         uint8 tmpR = static_cast<uint8>(255); | ||||
|         uint8 tmpG = static_cast<uint8>(255); | ||||
|         uint8 tmpB = static_cast<uint8>(255); | ||||
|         uint8 tmpA = static_cast<uint8>(alpha); | ||||
| 
 | ||||
|         // This does not matter since R and B are always 1.
 | ||||
|         /*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
 | ||||
|         switch (format) | ||||
|         { | ||||
|         case VET_COLOUR_ARGB: | ||||
|             std::swap(tmpR, tmpB); | ||||
|             break; | ||||
|         case VET_COLOUR_ABGR: | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         }*/ | ||||
| 
 | ||||
|         // Modify
 | ||||
|         *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24); | ||||
| 
 | ||||
|         // Move to the next vertex
 | ||||
|         pData = static_cast<unsigned char *> (pData) + vertex_size; | ||||
|     } | ||||
| }  | ||||
| 
 | ||||
|     // Unlock
 | ||||
|     ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock(); | ||||
| } | ||||
| 
 | ||||
| SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) : | ||||
|     mGlareFade(0), mGlareEnabled(false) | ||||
| { | ||||
|     mViewport = pCamera->getViewport(); | ||||
|     mSceneMgr = pMwRoot->getCreator(); | ||||
|     mRootNode = pCamera->getParentSceneNode()->createChildSceneNode(); | ||||
|     mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates
 | ||||
|     mRootNode->setInheritOrientation(false); | ||||
| 
 | ||||
|     /// \todo preload all the textures and meshes that are used for sky rendering
 | ||||
| 
 | ||||
|     // Create overlay used for thunderstorm
 | ||||
|     MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); | ||||
|     Pass* pass = material->getTechnique(0)->getPass(0); | ||||
|     pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); | ||||
|     mThunderTextureUnit = pass->createTextureUnitState(); | ||||
|     mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour
 | ||||
|     mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f); | ||||
|     OverlayManager& ovm = OverlayManager::getSingleton(); | ||||
|     mThunderOverlay = ovm.create( "ThunderOverlay" ); | ||||
|     OverlayContainer* overlay_panel; | ||||
|     overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel"); | ||||
|     overlay_panel->_setPosition(0, 0); | ||||
|     overlay_panel->_setDimensions(1, 1); | ||||
|     overlay_panel->setMaterialName( "ThunderMaterial" ); | ||||
|     overlay_panel->show(); | ||||
|     mThunderOverlay->add2D(overlay_panel); | ||||
|     mThunderOverlay->hide(); | ||||
| 
 | ||||
|     mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode); | ||||
|     mSecunda->setType(Moon::Type_Secunda); | ||||
|     mSecunda->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+4); | ||||
| 
 | ||||
|     mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode); | ||||
|     mMasser->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+3); | ||||
|     mMasser->setType(Moon::Type_Masser); | ||||
| 
 | ||||
|     mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode); | ||||
|     mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode); | ||||
|     mSunGlare->setRenderQueue(RENDER_QUEUE_SKIES_LATE); | ||||
| 
 | ||||
| 
 | ||||
|     HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); | ||||
| 
 | ||||
|     // Stars
 | ||||
|     /// \todo sky_night_02.nif (available in Bloodmoon)
 | ||||
|     MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); | ||||
|     Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif"); | ||||
|     night1_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1); | ||||
| 
 | ||||
|     mAtmosphereNight = mRootNode->createChildSceneNode(); | ||||
|     mAtmosphereNight->attachObject(night1_ent); | ||||
| 
 | ||||
|     for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i) | ||||
|     { | ||||
|         MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); | ||||
|         mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); | ||||
|         mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); | ||||
|         mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); | ||||
|         mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); | ||||
|         mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); | ||||
|         mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); | ||||
| 
 | ||||
|         mStarsMaterials[i] = mp; | ||||
|     } | ||||
| 
 | ||||
|     // Stars vertex shader
 | ||||
|     HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||
|         "cg", GPT_VERTEX_PROGRAM); | ||||
|     vshader3->setParameter("profiles", "vs_2_x arbvp1"); | ||||
|     vshader3->setParameter("entry_point", "main_vp"); | ||||
|     StringUtil::StrStreamType outStream4; | ||||
|     outStream4 << | ||||
|     "void main_vp(	\n" | ||||
|     "	float4 position : POSITION,	\n" | ||||
|     "   in float2 uv : TEXCOORD0, \n" | ||||
|     "   out float2 oUV : TEXCOORD0, \n" | ||||
|     "   out float oFade : TEXCOORD1, \n" | ||||
|     "	out float4 oPosition : POSITION,	\n" | ||||
|     "	uniform float4x4 worldViewProj	\n" | ||||
|     ")	\n" | ||||
|     "{	\n" | ||||
|     "   oUV = uv; \n" | ||||
|     "   oFade = (position.z > 50) ? 1.f : 0.f; \n" | ||||
|     "	oPosition = mul( worldViewProj, position );  \n" | ||||
|     "}"; | ||||
|     vshader3->setSource(outStream4.str()); | ||||
|     vshader3->load(); | ||||
|     vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); | ||||
|     night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName()); | ||||
| 
 | ||||
|     // Stars fragment shader
 | ||||
|     HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||
|         "cg", GPT_FRAGMENT_PROGRAM); | ||||
|     stars_fp->setParameter("profiles", "ps_2_x arbfp1"); | ||||
|     stars_fp->setParameter("entry_point", "main_fp"); | ||||
|     StringUtil::StrStreamType outStream5; | ||||
|     outStream5 << | ||||
|     "void main_fp(	\n" | ||||
|     "   in float2 uv : TEXCOORD0, \n" | ||||
|     "	out float4 oColor    : COLOR, \n" | ||||
|     "   in float fade : TEXCOORD1, \n" | ||||
|     "   uniform sampler2D texture : TEXUNIT0, \n" | ||||
|     "   uniform float opacity, \n" | ||||
|     "   uniform float4 diffuse, \n" | ||||
|     "   uniform float4 emissive \n" | ||||
|     ")	\n" | ||||
|     "{	\n" | ||||
|     "   oColor =  tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n" | ||||
|     "}"; | ||||
|     stars_fp->setSource(outStream5.str()); | ||||
|     stars_fp->load(); | ||||
|     stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); | ||||
|     stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); | ||||
|     night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); | ||||
| 
 | ||||
|     // Atmosphere (day)
 | ||||
|     mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); | ||||
|     Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif"); | ||||
| 
 | ||||
|     ModVertexAlpha(atmosphere_ent, 0); | ||||
| 
 | ||||
|     atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY); | ||||
|     mAtmosphereDay = mRootNode->createChildSceneNode(); | ||||
|     mAtmosphereDay->attachObject(atmosphere_ent); | ||||
|     mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); | ||||
| 
 | ||||
|     // Atmosphere shader
 | ||||
|     HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||
|         "cg", GPT_VERTEX_PROGRAM); | ||||
| 
 | ||||
|     vshader->setParameter("profiles", "vs_2_x arbvp1"); | ||||
|     vshader->setParameter("entry_point", "main_vp"); | ||||
| 
 | ||||
|     StringUtil::StrStreamType outStream; | ||||
|     outStream << | ||||
|     "void main_vp(	\n" | ||||
|     "	float4 position : POSITION,	\n" | ||||
|     "	in float4 color	: COLOR,	\n" | ||||
|     "	out float4 oPosition : POSITION,	\n" | ||||
|     "	out float4 oColor    : COLOR, \n" | ||||
|     "   uniform float4 emissive, \n" | ||||
|     "	uniform float4x4 worldViewProj	\n" | ||||
|     ")	\n" | ||||
|     "{	\n" | ||||
|     "	oPosition = mul( worldViewProj, position );  \n" | ||||
|     "   oColor = color * emissive; \n" | ||||
|     "}"; | ||||
|     vshader->setSource(outStream.str()); | ||||
|     vshader->load(); | ||||
| 
 | ||||
|     vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); | ||||
|     vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); | ||||
|     mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); | ||||
| 
 | ||||
|     // 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) | ||||
|     { | ||||
|         Vector3 sun = mSunGlare->getPosition(); | ||||
|         sun = Vector3(sun.x, sun.z, -sun.y); | ||||
|         Vector3 cam = mViewport->getCamera()->getRealDirection(); | ||||
|         const Degree angle = sun.angleBetween( cam ); | ||||
|         float val = 1- (angle.valueDegrees() / 180.f); | ||||
|         val = (val*val*val*val)*2; | ||||
| 
 | ||||
|         if (mGlareEnabled) | ||||
|         { | ||||
|             mGlareFade += duration*3; | ||||
|             if (mGlareFade > 1) mGlareFade = 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             mGlareFade -= duration*3; | ||||
|             if (mGlareFade < 0.3) mGlareFade = 0; | ||||
|         } | ||||
| 
 | ||||
|         mSunGlare->setSize(val * (mGlareFade)); | ||||
|     } | ||||
| 
 | ||||
|     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 | ||||
| #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 | ||||
| { | ||||
|     class RenderWindow; | ||||
|     class SceneNode; | ||||
|     class Camera; | ||||
|     class Viewport; | ||||
|     class SceneManager; | ||||
|     class Entity; | ||||
|     class BillboardSet; | ||||
|     class TextureUnitState; | ||||
|     class Overlay; | ||||
| } | ||||
| 
 | ||||
| namespace MWRender | ||||
| { | ||||
|     ///
 | ||||
|     /// Interface for the sky rendering system
 | ||||
|     ///
 | ||||
|     class BillboardObject | ||||
|     { | ||||
|     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 | ||||
|     { | ||||
|     public: | ||||
|         static SkyManager* create (Ogre::RenderWindow* pRenderWindow,  | ||||
|                                    Ogre::Camera* pCamera, | ||||
|                                    const boost::filesystem::path& resDir); | ||||
|         virtual ~SkyManager() {} | ||||
|         SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera); | ||||
|         ~SkyManager(); | ||||
|          | ||||
|         virtual void enable() = 0; | ||||
|         void update(float duration); | ||||
|          | ||||
|         virtual void disable() = 0; | ||||
|         void enable(); | ||||
|          | ||||
|         virtual void setHour (double hour) = 0; | ||||
|         void disable(); | ||||
|          | ||||
|         virtual void setDate (int day, int month) = 0; | ||||
|         void setHour (double hour); | ||||
|         ///< will be called even when sky is disabled.
 | ||||
|          | ||||
|         virtual int getMasserPhase() const = 0; | ||||
|         void setDate (int day, int month); | ||||
|         ///< will be called even when sky is disabled.
 | ||||
|          | ||||
|         virtual int getSecundaPhase() const = 0; | ||||
|         int getMasserPhase() const; | ||||
|         ///< 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) = 0; | ||||
|         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]; | ||||
|          | ||||
|         Ogre::HighLevelGpuProgramPtr mCloudFragmentShader; | ||||
|          | ||||
|         // 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; | ||||
|          | ||||
|         Ogre::Overlay* mThunderOverlay; | ||||
|         Ogre::TextureUnitState* mThunderTextureUnit; | ||||
|                  | ||||
|         float mRemainingTransitionTime; | ||||
|          | ||||
|         float mGlareFade; | ||||
|          | ||||
|         void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType); | ||||
|          | ||||
|         bool mEnabled; | ||||
|         bool mGlareEnabled; | ||||
|         bool mSunEnabled; | ||||
|         bool mMasserEnabled; | ||||
|         bool mSecundaEnabled; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| 
 | ||||
| #include "../mwworld/manualref.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/containerutil.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| 
 | ||||
| #include "interpretercontext.hpp" | ||||
| #include "ref.hpp" | ||||
|  | @ -45,8 +45,7 @@ namespace MWScript | |||
| 
 | ||||
|                     ref.getPtr().getRefData().setCount (count); | ||||
| 
 | ||||
|                     MWWorld::Class::get (ref.getPtr()).insertIntoContainer (ref.getPtr(), | ||||
|                         MWWorld::Class::get (ptr).getContainerStore (ptr)); | ||||
|                     MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr()); | ||||
|                 } | ||||
|         }; | ||||
| 
 | ||||
|  | @ -59,25 +58,16 @@ namespace MWScript | |||
|                 { | ||||
|                     MWWorld::Ptr ptr = R()(runtime); | ||||
| 
 | ||||
|                     MWScript::InterpreterContext& context | ||||
|                         = static_cast<MWScript::InterpreterContext&> (runtime.getContext()); | ||||
| 
 | ||||
|                     std::string item = runtime.getStringLiteral (runtime[0].mInteger); | ||||
|                     runtime.pop(); | ||||
| 
 | ||||
|                     std::vector<MWWorld::Ptr> list; | ||||
| 
 | ||||
|                     MWWorld::listItemsInContainer (item, | ||||
|                         MWWorld::Class::get (ptr).getContainerStore (ptr), | ||||
|                         context.getWorld().getStore(), list); | ||||
|                     MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); | ||||
| 
 | ||||
|                     Interpreter::Type_Integer sum = 0; | ||||
| 
 | ||||
|                     for (std::vector<MWWorld::Ptr>::iterator iter (list.begin()); iter!=list.end(); | ||||
|                         ++iter) | ||||
|                     { | ||||
|                         sum += iter->getRefData().getCount(); | ||||
|                     } | ||||
|                     for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) | ||||
|                         if (iter->getCellRef().refID==item) | ||||
|                             sum += iter->getRefData().getCount(); | ||||
| 
 | ||||
|                     runtime.push (sum); | ||||
|                 } | ||||
|  | @ -92,9 +82,6 @@ namespace MWScript | |||
|                 { | ||||
|                     MWWorld::Ptr ptr = R()(runtime); | ||||
| 
 | ||||
|                     MWScript::InterpreterContext& context | ||||
|                         = static_cast<MWScript::InterpreterContext&> (runtime.getContext()); | ||||
| 
 | ||||
|                     std::string item = runtime.getStringLiteral (runtime[0].mInteger); | ||||
|                     runtime.pop(); | ||||
| 
 | ||||
|  | @ -104,25 +91,23 @@ namespace MWScript | |||
|                     if (count<0) | ||||
|                         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, | ||||
|                         MWWorld::Class::get (ptr).getContainerStore (ptr), | ||||
|                         context.getWorld().getStore(), list); | ||||
| 
 | ||||
|                     for (std::vector<MWWorld::Ptr>::iterator iter (list.begin()); | ||||
|                         iter!=list.end() && count; | ||||
|                     for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; | ||||
|                         ++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); | ||||
|                             count = 0; | ||||
|                             if (iter->getRefData().getCount()<=count) | ||||
|                             { | ||||
|                                 count -= iter->getRefData().getCount(); | ||||
|                                 iter->getRefData().setCount (0); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 iter->getRefData().setCount (iter->getRefData().getCount()-count); | ||||
|                                 count = 0; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -116,4 +116,10 @@ op 0x2000137: GetButtonPressed | |||
| op 0x2000138: SkipAnim | ||||
| op 0x2000139: SkipAnim, expplicit reference | ||||
| op 0x200013a: AddTopic | ||||
| opcodes 0x200013b-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.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 opcodeUnlockExplicit = 0x200008d; | ||||
|         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) | ||||
|         { | ||||
|  | @ -127,6 +199,11 @@ namespace MWScript | |||
|             extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug); | ||||
|             extensions.registerInstruction ("tcb", "", 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) | ||||
|  | @ -139,6 +216,10 @@ namespace MWScript | |||
|             interpreter.installSegment5 (opcodeUnlock, new OpUnlock<ImplicitRef>); | ||||
|             interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock<ExplicitRef>); | ||||
|             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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -79,12 +79,46 @@ namespace MWScript | |||
|                     runtime.push (context.getWorld().getSecundaPhase()); | ||||
|                 } | ||||
|         }; | ||||
|          | ||||
|         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 opcodeTurnMoonWhite = 0x2000022; | ||||
|         const int opcodeTurnMoonRed = 0x2000023; | ||||
|         const int opcodeGetMasserPhase = 0x2000024; | ||||
|         const int opcodeGetSecundaPhase = 0x2000025; | ||||
|         const int opcodeGetCurrentWeather = 0x200013f; | ||||
|         const int opcodeChangeWeather = 0x2000140; | ||||
| 
 | ||||
|         void registerExtensions (Compiler::Extensions& extensions) | ||||
|         { | ||||
|  | @ -92,8 +126,10 @@ namespace MWScript | |||
|             extensions.registerInstruction ("ts", "", opcodeToggleSky); | ||||
|             extensions.registerInstruction ("turnmoonwhite", "", opcodeTurnMoonWhite); | ||||
|             extensions.registerInstruction ("turnmoonred", "", opcodeTurnMoonRed); | ||||
|             extensions.registerInstruction ("changeweather", "Sl", opcodeChangeWeather); | ||||
|             extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); | ||||
|             extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); | ||||
|             extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather); | ||||
|         } | ||||
| 
 | ||||
|         void installOpcodes (Interpreter::Interpreter& interpreter) | ||||
|  | @ -103,6 +139,8 @@ namespace MWScript | |||
|             interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed); | ||||
|             interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase); | ||||
|             interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); | ||||
|             interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather); | ||||
|             interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -4,8 +4,6 @@ | |||
| #include <algorithm> | ||||
| #include <map> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| #include <OgreRoot.h> | ||||
| 
 | ||||
| #include <openengine/sound/sndmanager.hpp> | ||||
|  | @ -15,6 +13,7 @@ using namespace std; | |||
| #include <components/file_finder/file_finder.hpp> | ||||
| #include <components/esm_store/store.hpp> | ||||
| 
 | ||||
| 
 | ||||
| #include "../mwworld/environment.hpp" | ||||
| #include "../mwworld/world.hpp" | ||||
| #include "../mwworld/player.hpp" | ||||
|  | @ -90,24 +89,28 @@ namespace MWSound | |||
|     // relative to the sound dir, and translates them into full paths
 | ||||
|     // of existing files in the filesystem, if they exist.
 | ||||
|     bool FSstrict; | ||||
|     FileFinder::FileFinder files; | ||||
|     FileFinder::FileFinderStrict strict; | ||||
|     FileFinder::FileFinder musicpath; | ||||
|     FileFinder::FileFinderStrict musicpathStrict; | ||||
|     FileFinder::LessTreeFileFinder files; | ||||
|     FileFinder::StrictTreeFileFinder strict; | ||||
|     FileFinder::LessTreeFileFinder musicpath; | ||||
|     FileFinder::StrictTreeFileFinder musicpathStrict; | ||||
| 
 | ||||
|     SoundImpl(Ogre::Root *root, Ogre::Camera *camera, | ||||
|               const ESMS::ESMStore &str, | ||||
|               const std::string &soundDir, const std::string &musicDir, bool fsstrict) | ||||
|     SoundImpl(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &str, | ||||
|         const Files::PathContainer& soundDir, | ||||
|         const Files::PathContainer& musicDir, | ||||
|         bool fsstrict) | ||||
|       : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) | ||||
|       , updater(mgr) | ||||
|       , cameraTracker(mgr) | ||||
|       , store(str) | ||||
|       , files(soundDir), strict(soundDir) | ||||
|       ,musicpath(musicDir), musicpathStrict(musicDir) | ||||
|       , FSstrict(fsstrict) | ||||
|       , files(soundDir) | ||||
|       , strict(soundDir) | ||||
|       , musicpath(musicDir) | ||||
|       , musicpathStrict(musicDir) | ||||
|     { | ||||
|       FSstrict = fsstrict; | ||||
|       cout << "Sound output:  " << SOUND_OUT << endl; | ||||
|       cout << "Sound decoder: " << SOUND_IN << endl; | ||||
| 
 | ||||
|       std::cout << "Sound output:  " << SOUND_OUT << std::endl; | ||||
|       std::cout << "Sound decoder: " << SOUND_IN << std::endl; | ||||
|       // Attach the camera to the camera tracker
 | ||||
|       cameraTracker.followCamera(camera); | ||||
| 
 | ||||
|  | @ -136,36 +139,49 @@ namespace MWSound | |||
| 
 | ||||
|     bool hasFile(const std::string &str, bool music = false) | ||||
|     { | ||||
|         if(FSstrict == false) | ||||
|         bool found = false; | ||||
|         if(!FSstrict) | ||||
|         { | ||||
|             if(music) | ||||
|             { | ||||
|                 if(musicpath.has(str)) return true; | ||||
| 
 | ||||
|                 found = musicpath.has(str); | ||||
|                 // Not found? Try with .mp3
 | ||||
|                 return musicpath.has(toMp3(str)); | ||||
|                 if (!found) | ||||
|                 { | ||||
|                     found = musicpath.has(toMp3(str)); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(files.has(str)) return true; | ||||
|                 return files.has(toMp3(str)); | ||||
|                 found = files.has(str); | ||||
|                 if (!found) | ||||
|                 { | ||||
|                     found = files.has(toMp3(str)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if(music) | ||||
|             { | ||||
|                 if(musicpathStrict.has(str)) return true; | ||||
| 
 | ||||
|                 found = musicpathStrict.has(str); | ||||
|                 // Not found? Try with .mp3
 | ||||
|                 return musicpathStrict.has(toMp3(str)); | ||||
|                 if (!found) | ||||
|                 { | ||||
|                     found = musicpathStrict.has(toMp3(str)); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(strict.has(str)) return true; | ||||
|                     return strict.has(toMp3(str)); | ||||
|                 found = strict.has(str); | ||||
|                 if (!found) | ||||
|                 { | ||||
|                     found = strict.has(toMp3(str)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return found; | ||||
|     } | ||||
| 
 | ||||
|     // Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
 | ||||
|  | @ -258,13 +274,13 @@ namespace MWSound | |||
|         } | ||||
|       catch(...) | ||||
|         { | ||||
|           cout << "Error loading " << file << ", skipping.\n"; | ||||
|           std::cout << "Error loading " << file << ", skipping.\n"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Clears all the sub-elements of a given iterator, and then
 | ||||
|     // removes it from 'sounds'.
 | ||||
|     void clearAll(PtrMap::iterator it) | ||||
|     void clearAll(PtrMap::iterator& it) | ||||
|     { | ||||
|       IDMap::iterator sit = it->second.begin(); | ||||
| 
 | ||||
|  | @ -362,9 +378,9 @@ namespace MWSound | |||
|             } | ||||
|         } | ||||
|     } | ||||
|   }; | ||||
|   }; /* SoundImpl */ | ||||
| 
 | ||||
|   void SoundManager::streamMusicFull (const std::string& filename) | ||||
|   void SoundManager::streamMusicFull(const std::string& filename) | ||||
|   { | ||||
|     if(!mData) return; | ||||
| 
 | ||||
|  | @ -381,20 +397,24 @@ namespace MWSound | |||
|   } | ||||
| 
 | ||||
|   SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, | ||||
|                              const ESMS::ESMStore &store, | ||||
|                              boost::filesystem::path dataDir, | ||||
|                              bool useSound, bool fsstrict, MWWorld::Environment& environment) | ||||
|     : mData(NULL), fsStrict (fsstrict), mEnvironment (environment) | ||||
|     const ESMS::ESMStore &store, const Files::PathContainer& dataDirs, | ||||
|     bool useSound, bool fsstrict, MWWorld::Environment& environment) | ||||
|     : mData(NULL) | ||||
|     , fsStrict(fsstrict) | ||||
|     , mEnvironment(environment) | ||||
|   { | ||||
|     MP3Lookup(dataDir / "Music/Explore/"); | ||||
|     if(useSound) | ||||
|       mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string(), (dataDir / "Music").string(), fsstrict); | ||||
|     for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) | ||||
|     { | ||||
|         MP3Lookup((*it) / "Music/Explore/"); | ||||
|     } | ||||
| 
 | ||||
|     if(useSound) | ||||
|     { | ||||
|       mData = new SoundImpl(root, camera, store, dataDirs /* Sound */, dataDirs /* Music */, fsstrict); | ||||
|     } | ||||
| 
 | ||||
|     test.name = ""; | ||||
|     total = 0; | ||||
| 
 | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   SoundManager::~SoundManager() | ||||
|  | @ -407,14 +427,12 @@ namespace MWSound | |||
|     { | ||||
|         if(mData->hasFile(filename, true)) | ||||
|         { | ||||
|             std::string fullpath = mData->convertPath(filename, true); | ||||
|             streamMusicFull(fullpath); | ||||
|             streamMusicFull(mData->convertPath(filename, true)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|   void SoundManager::MP3Lookup(boost::filesystem::path dir) | ||||
| { | ||||
|   void SoundManager::MP3Lookup(const boost::filesystem::path& dir) | ||||
|   { | ||||
|     boost::filesystem::directory_iterator dir_iter(dir), dir_end; | ||||
| 
 | ||||
|     std::string mp3extension = ".mp3"; | ||||
|  | @ -425,35 +443,30 @@ namespace MWSound | |||
|             files.push_back(*dir_iter); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   } | ||||
| 
 | ||||
|   void SoundManager::startRandomTitle() | ||||
| { | ||||
|     std::vector<boost::filesystem::path>::iterator fileIter; | ||||
| 
 | ||||
|     if(files.size() > 0) | ||||
|   { | ||||
|     if(!files.empty()) | ||||
|     { | ||||
|         fileIter = files.begin(); | ||||
|         srand ( time(NULL) ); | ||||
|         Files::PathContainer::iterator fileIter = files.begin(); | ||||
|         srand( time(NULL) ); | ||||
|         int r = rand() % files.size() + 1;        //old random code
 | ||||
| 
 | ||||
|         for(int i = 1; i < r; i++) | ||||
|         { | ||||
|             fileIter++; | ||||
|         } | ||||
|         std::advance(fileIter, r - 1); | ||||
|         std::string music = fileIter->string(); | ||||
|         std::cout << "Playing " << music << "\n"; | ||||
| 
 | ||||
|         try | ||||
|         { | ||||
|             std::cout << "Playing " << music << "\n"; | ||||
|             streamMusicFull(music); | ||||
|         } | ||||
|         catch(std::exception &e) | ||||
|         catch (std::exception &e) | ||||
|         { | ||||
|             std::cout << "  Music Error: " << e.what() << "\n"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|     bool SoundManager::isMusicPlaying() | ||||
|     { | ||||
|  | @ -465,14 +478,12 @@ namespace MWSound | |||
|         return test; | ||||
|     } | ||||
| 
 | ||||
|    SoundManager::SoundImpl SoundManager::getMData() | ||||
|   SoundManager::SoundImpl SoundManager::getMData() | ||||
|   { | ||||
|      // bool test = mData->music->isPlaying();
 | ||||
|       return *mData; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) | ||||
|   { | ||||
|     // The range values are not tested
 | ||||
|  | @ -480,7 +491,7 @@ namespace MWSound | |||
|     if(mData->hasFile(filename)) | ||||
|       mData->add(mData->convertPath(filename), ptr, "_say_sound", 1, 1, 100, 20000, false); | ||||
|     else | ||||
|       cout << "Sound file " << filename << " not found, skipping.\n"; | ||||
|       std::cout << "Sound file " << filename << " not found, skipping.\n"; | ||||
|   } | ||||
| 
 | ||||
|   bool SoundManager::sayDone (MWWorld::Ptr ptr) const | ||||
|  | @ -490,20 +501,20 @@ namespace MWSound | |||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   void SoundManager::playSound (const std::string& soundId, float volume, float pitch) | ||||
|   void SoundManager::playSound(const std::string& soundId, float volume, float pitch) | ||||
|   { | ||||
|     if(!mData) return; | ||||
|     // Play and forget
 | ||||
|     float min, max; | ||||
|     const std::string &file = mData->lookup(soundId, volume, min, max); | ||||
|     if(file != "") | ||||
|       { | ||||
|     if (file != "") | ||||
|     { | ||||
|         SoundPtr snd = mData->mgr->load(file); | ||||
|         snd->setVolume(volume); | ||||
|         snd->setRange(min,max); | ||||
|         snd->setPitch(pitch); | ||||
|         snd->play(); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, | ||||
|  | @ -514,7 +525,7 @@ namespace MWSound | |||
|     // Look up the sound in the ESM data
 | ||||
|     float min, max; | ||||
|     const std::string &file = mData->lookup(soundId, volume, min, max); | ||||
|     if(file != "") | ||||
|     if (file != "") | ||||
|       mData->add(file, ptr, soundId, volume, pitch, min, max, loop); | ||||
|   } | ||||
| 
 | ||||
|  | @ -541,18 +552,19 @@ namespace MWSound | |||
| 
 | ||||
|   void SoundManager::updateObject(MWWorld::Ptr ptr) | ||||
|   { | ||||
|     if(!mData) return; | ||||
|     mData->updatePositions(ptr); | ||||
|     if (mData != NULL) | ||||
|     { | ||||
|         mData->updatePositions(ptr); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void SoundManager::update (float duration) | ||||
|   { | ||||
|         std::string effect; | ||||
| 
 | ||||
|         MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); | ||||
| 
 | ||||
|         //If the region has changed
 | ||||
|         if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ | ||||
|         if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10) | ||||
|         { | ||||
|             timer.restart(); | ||||
|             if (test.name != current->cell->region) | ||||
|             { | ||||
|  | @ -564,11 +576,12 @@ namespace MWSound | |||
|             { | ||||
|                 std::vector<ESM::Region::SoundRef>::iterator soundIter = test.soundList.begin(); | ||||
|                 //mEnvironment.mSoundManager
 | ||||
|                 if(total == 0){ | ||||
|                     while (!(soundIter == test.soundList.end())) | ||||
|                 if(total == 0) | ||||
|                 { | ||||
|                     while (soundIter != test.soundList.end()) | ||||
|                     { | ||||
|                         ESM::NAME32 go = soundIter->sound; | ||||
|                         int chance = (int) soundIter->chance; | ||||
|                         //ESM::NAME32 go = soundIter->sound;
 | ||||
|                         //std::cout << "Sound: " << go.name <<" Chance:" <<  chance << "\n";
 | ||||
|                         soundIter++; | ||||
|                         total += chance; | ||||
|  | @ -578,7 +591,7 @@ namespace MWSound | |||
|                 int r = rand() % total;        //old random code
 | ||||
|                 int pos = 0; | ||||
|                 soundIter = test.soundList.begin(); | ||||
|                 while (!(soundIter == test.soundList.end())) | ||||
|                 while (soundIter != test.soundList.end()) | ||||
|                 { | ||||
|                     const ESM::NAME32 go = soundIter->sound; | ||||
|                     int chance = (int) soundIter->chance; | ||||
|  | @ -586,13 +599,11 @@ namespace MWSound | |||
|                     soundIter++; | ||||
|                     if( r - pos < chance) | ||||
|                     { | ||||
|                         effect = go.name; | ||||
|                         //play sound
 | ||||
|                         std::cout << "Sound: " << go.name <<" Chance:" <<  chance << "\n"; | ||||
|                         mEnvironment.mSoundManager->playSound(effect, 20.0, 1.0); | ||||
|                         mEnvironment.mSoundManager->playSound(go.name, 20.0, 1.0); | ||||
| 
 | ||||
|                         break; | ||||
| 
 | ||||
|                     } | ||||
|                     pos += chance; | ||||
|                 } | ||||
|  |  | |||
|  | @ -2,14 +2,15 @@ | |||
| #define GAME_SOUND_SOUNDMANAGER_H | ||||
| 
 | ||||
| #include <string> | ||||
| #include <map> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/timer.hpp> | ||||
| 
 | ||||
| #include "../mwworld/ptr.hpp" | ||||
| #include <openengine/sound/sndmanager.hpp> | ||||
| #include <components/files/multidircollection.hpp> | ||||
| 
 | ||||
| 
 | ||||
| #include <boost/timer.hpp> | ||||
| 
 | ||||
| namespace Ogre | ||||
| { | ||||
|  | @ -37,7 +38,7 @@ namespace MWSound | |||
|             struct SoundImpl; | ||||
| 
 | ||||
|             SoundImpl *mData; | ||||
|             std::vector<boost::filesystem::path> files; | ||||
|             Files::PathContainer files; | ||||
|             bool fsStrict; | ||||
|             MWWorld::Environment& mEnvironment; | ||||
| 
 | ||||
|  | @ -52,7 +53,7 @@ namespace MWSound | |||
|         public: | ||||
| 
 | ||||
|             SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, | ||||
|                    boost::filesystem::path dataDir, bool useSound, bool fsstrict, | ||||
|                    const Files::PathContainer& dataDir, bool useSound, bool fsstrict, | ||||
|                    MWWorld::Environment& environment); | ||||
|             ~SoundManager(); | ||||
| 
 | ||||
|  | @ -61,7 +62,7 @@ namespace MWSound | |||
|             /// \param filename name of a sound file in "Music/" in the data directory.
 | ||||
| 
 | ||||
|             void startRandomTitle(); | ||||
|             void MP3Lookup(boost::filesystem::path dir); | ||||
|             void MP3Lookup(const boost::filesystem::path& dir); | ||||
| 
 | ||||
|             bool isMusicPlaying(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| #include "class.hpp" | ||||
| #include "environment.hpp" | ||||
| #include "world.hpp" | ||||
| #include "containerstore.hpp" | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|  | @ -14,8 +15,7 @@ namespace MWWorld | |||
|         // insert into player's inventory
 | ||||
|         MWWorld::Ptr player = environment.mWorld->getPtr ("player", true); | ||||
| 
 | ||||
|         MWWorld::Class::get (mObject).insertIntoContainer (mObject, | ||||
|             MWWorld::Class::get (player).getContainerStore (player)); | ||||
|         MWWorld::Class::get (player).getContainerStore (player).add (mObject); | ||||
| 
 | ||||
|         // remove from world
 | ||||
|         environment.mWorld->deleteObject (mObject); | ||||
|  |  | |||
|  | @ -63,10 +63,11 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) | |||
| 
 | ||||
|         result = mExteriors.insert (std::make_pair ( | ||||
|             std::make_pair (x, y), Ptr::CellStore (cell))).first; | ||||
| 
 | ||||
|         result->second.load (mStore, mReader); | ||||
|     } | ||||
| 
 | ||||
|     if (result->second.mState!=Ptr::CellStore::State_Loaded) | ||||
|         result->second.load (mStore, mReader); | ||||
| 
 | ||||
|     return &result->second; | ||||
| } | ||||
| 
 | ||||
|  | @ -79,10 +80,11 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) | |||
|         const ESM::Cell *cell = mStore.cells.findInt (name); | ||||
| 
 | ||||
|         result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; | ||||
| 
 | ||||
|         result->second.load (mStore, mReader); | ||||
|     } | ||||
| 
 | ||||
|     if (result->second.mState!=Ptr::CellStore::State_Loaded) | ||||
|         result->second.load (mStore, mReader); | ||||
| 
 | ||||
|     return &result->second; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| #include "ptr.hpp" | ||||
| #include "nullaction.hpp" | ||||
| #include "containerstore.hpp" | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|  | @ -71,16 +72,11 @@ namespace MWWorld | |||
|         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"); | ||||
|     } | ||||
| 
 | ||||
|     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 | ||||
|     { | ||||
|         throw std::runtime_error ("class does not support locking"); | ||||
|  |  | |||
|  | @ -7,11 +7,11 @@ | |||
| #include <boost/shared_ptr.hpp> | ||||
| 
 | ||||
| #include "action.hpp" | ||||
| #include "containerstore.hpp" | ||||
| #include "refdata.hpp" | ||||
| #include "../mwrender/renderinginterface.hpp" | ||||
| #include "physicssystem.hpp" | ||||
| 
 | ||||
| #include "../mwrender/renderinginterface.hpp" | ||||
| 
 | ||||
| namespace Ogre | ||||
| { | ||||
|     class Vector3; | ||||
|  | @ -33,6 +33,7 @@ namespace MWWorld | |||
| { | ||||
|     class Ptr; | ||||
|     class Environment; | ||||
|     class ContainerStore; | ||||
| 
 | ||||
|     /// \brief Base class for referenceable esm records
 | ||||
|     class Class | ||||
|  | @ -61,8 +62,6 @@ namespace MWWorld | |||
|             ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
 | ||||
|             /// (default implementation: throw an exception)
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) 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).
 | ||||
|  | @ -105,15 +104,10 @@ namespace MWWorld | |||
|             ///< Generate action for using via inventory menu (default implementation: return a
 | ||||
|             /// 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
 | ||||
|             /// 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; | ||||
|             ///< Lock object (default implementation: throw an exception)
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										342
									
								
								apps/openmw/mwworld/containerstore.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								apps/openmw/mwworld/containerstore.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 "refdata.hpp" | ||||
| #include "ptr.hpp" | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|     template<typename D> | ||||
|     struct ContainerStore | ||||
|     class ContainerStoreIterator; | ||||
| 
 | ||||
|     class ContainerStore | ||||
|     { | ||||
|             ESMS::CellRefList<ESM::Potion, D>            potions; | ||||
|             ESMS::CellRefList<ESM::Apparatus, D>         appas; | ||||
|             ESMS::CellRefList<ESM::Armor, D>             armors; | ||||
|             ESMS::CellRefList<ESM::Book, D>              books; | ||||
|             ESMS::CellRefList<ESM::Clothing, D>          clothes; | ||||
|             ESMS::CellRefList<ESM::Ingredient, D>        ingreds; | ||||
|             ESMS::CellRefList<ESM::Light, D>             lights; | ||||
|             ESMS::CellRefList<ESM::Tool, D>              lockpicks; | ||||
|             ESMS::CellRefList<ESM::Miscellaneous, D>     miscItems; | ||||
|             ESMS::CellRefList<ESM::Probe, D>             probes; | ||||
|             ESMS::CellRefList<ESM::Repair, D>            repairs; | ||||
|             ESMS::CellRefList<ESM::Weapon, D>            weapons; | ||||
|         public: | ||||
| 
 | ||||
|             static const int Type_Potion = 0x0001; | ||||
|             static const int Type_Apparatus = 0x0002; | ||||
|             static const int Type_Armor = 0x0004; | ||||
|             static const int Type_Book = 0x0008; | ||||
|             static const int Type_Clothing = 0x0010; | ||||
|             static const int Type_Ingredient = 0x0020; | ||||
|             static const int Type_Light = 0x0040; | ||||
|             static const int Type_Lockpick = 0x0080; | ||||
|             static const int Type_Miscellaneous = 0x0100; | ||||
|             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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -82,6 +82,7 @@ namespace MWWorld | |||
| 
 | ||||
|                 // initialise
 | ||||
|                 ESM::CellRef& cellRef = mPtr.getCellRef(); | ||||
|                 cellRef.refID = name; | ||||
|                 cellRef.refnum = -1; | ||||
|                 cellRef.scale = 1; | ||||
|                 cellRef.factIndex = 0; | ||||
|  |  | |||
|  | @ -50,6 +50,17 @@ namespace MWWorld | |||
| 
 | ||||
|         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, | ||||
|  | @ -109,7 +120,7 @@ namespace MWWorld | |||
|     void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh, | ||||
|         const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) | ||||
|     { | ||||
|         OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle); | ||||
|         OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale); | ||||
|         mEngine->addRigidBody(body); | ||||
|         btTransform tr; | ||||
|         tr.setOrigin(btVector3(position.x,position.y,position.z)); | ||||
|  |  | |||
|  | @ -33,11 +33,15 @@ namespace MWWorld | |||
|             void scaleObject (const std::string& handle, float scale); | ||||
| 
 | ||||
|             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 insertActorPhysics(const MWWorld::Ptr&, std::string model); | ||||
|             void insertActorPhysics(const MWWorld::Ptr&, std::string model); | ||||
| 
 | ||||
|             OEngine::Physic::PhysicEngine* getEngine(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -60,12 +60,12 @@ namespace MWWorld | |||
|         std::cout << "Unloading cell\n"; | ||||
|         ListHandles functor; | ||||
| 
 | ||||
|         MWWorld::Ptr::CellStore* active = *iter; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         active->forEach<ListHandles>(functor); | ||||
| 
 | ||||
|         (*iter)->forEach<ListHandles>(functor); | ||||
| 
 | ||||
|         { | ||||
| 
 | ||||
|  | @ -77,13 +77,15 @@ namespace MWWorld | |||
|                 mPhysics->removeObject (node->getName()); | ||||
|             } | ||||
|         } | ||||
| 		mRendering.removeCell(active); | ||||
| 		mRendering.removeCell(*iter); | ||||
| 		//mPhysics->removeObject("Unnamed_43");
 | ||||
|         mWorld->getLocalScripts().clearCell (active); | ||||
|         mEnvironment.mMechanicsManager->dropActors (active); | ||||
|         mEnvironment.mSoundManager->stopSound (active); | ||||
| 		mActiveCells.erase(active); | ||||
| 
 | ||||
|         mWorld->getLocalScripts().clearCell (*iter); | ||||
|         mEnvironment.mMechanicsManager->dropActors (*iter); | ||||
|         mEnvironment.mSoundManager->stopSound (*iter); | ||||
| 		mActiveCells.erase(*iter); | ||||
|          | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     void Scene::loadCell (Ptr::CellStore *cell) | ||||
|  | @ -233,6 +235,9 @@ namespace MWWorld | |||
|         // adjust player
 | ||||
|         mCurrentCell = cell; | ||||
|         playerCellChange (cell, position); | ||||
|          | ||||
|         // adjust fog
 | ||||
|         mRendering.configureFog(*cell); | ||||
| 
 | ||||
|         // Sky system
 | ||||
|         mWorld->adjustSky(); | ||||
|  |  | |||
							
								
								
									
										803
									
								
								apps/openmw/mwworld/weather.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										803
									
								
								apps/openmw/mwworld/weather.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||
| } | ||||
							
								
								
									
										272
									
								
								apps/openmw/mwworld/weather.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								apps/openmw/mwworld/weather.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 "ptr.hpp" | ||||
| #include "environment.hpp" | ||||
| #include "class.hpp" | ||||
| #include "player.hpp" | ||||
| #include "weather.hpp" | ||||
| 
 | ||||
| #include "refdata.hpp" | ||||
| #include "globals.hpp" | ||||
| #include "cellfunctors.hpp" | ||||
| 
 | ||||
| #include <OgreVector3.h> | ||||
| using namespace Ogre; | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     template<typename T> | ||||
|  | @ -135,12 +140,16 @@ namespace MWWorld | |||
| 
 | ||||
|     void World::adjustSky() | ||||
|     { | ||||
|         if (mSky) | ||||
|         if (mSky && (isCellExterior() || isCellQuasiExterior())) | ||||
|         { | ||||
|             toggleSky(); | ||||
|             // TODO set weather
 | ||||
|             toggleSky(); | ||||
|             mRendering->skySetHour (mGlobalVariables->getFloat ("gamehour")); | ||||
|             mRendering->skySetDate (mGlobalVariables->getInt ("day"), | ||||
|                 mGlobalVariables->getInt ("month")); | ||||
| 
 | ||||
|             mRendering->getSkyManager()->enable(); | ||||
|         } | ||||
|         else | ||||
|             mRendering->getSkyManager()->disable(); | ||||
|     } | ||||
| 
 | ||||
|     World::World (OEngine::Render::OgreRenderer& renderer, | ||||
|  | @ -148,12 +157,14 @@ namespace MWWorld | |||
|         const std::string& master, const boost::filesystem::path& resDir, | ||||
|         bool newGame, Environment& environment, const std::string& encoding) | ||||
|     : 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) | ||||
|     { | ||||
|         mPhysics = new PhysicsSystem(renderer); | ||||
|         mPhysEngine = mPhysics->getEngine(); | ||||
|          | ||||
|         mRendering = new MWRender::RenderingManager(renderer, resDir, mPhysEngine, environment); | ||||
|          | ||||
|         mWeatherManager = new MWWorld::WeatherManager(mRendering, &environment); | ||||
| 
 | ||||
|         boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); | ||||
| 
 | ||||
|  | @ -181,8 +192,10 @@ namespace MWWorld | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     World::~World() | ||||
|     { | ||||
|         delete mWeatherManager; | ||||
|         delete mWorldScene; | ||||
|         delete mGlobalVariables; | ||||
|         delete mRendering; | ||||
|  | @ -368,6 +381,8 @@ namespace MWWorld | |||
|         mGlobalVariables->setFloat ("gamehour", hour); | ||||
| 
 | ||||
|         mRendering->skySetHour (hour); | ||||
|          | ||||
|         mWeatherManager->setHour (hour); | ||||
| 
 | ||||
|         if (days>0) | ||||
|             setDay (days + mGlobalVariables->getInt ("day")); | ||||
|  | @ -403,6 +418,10 @@ namespace MWWorld | |||
|         mGlobalVariables->setInt ("month", month); | ||||
| 
 | ||||
|         mRendering->skySetDate (day, month); | ||||
|          | ||||
|         mWeatherManager->setDate (day, month); | ||||
|          | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     void World::setMonth (int month) | ||||
|  | @ -437,10 +456,6 @@ namespace MWWorld | |||
|         else | ||||
|         { | ||||
|             mSky = true; | ||||
|             // TODO check for extorior or interior with sky.
 | ||||
|             mRendering->skySetHour (mGlobalVariables->getFloat ("gamehour")); | ||||
|             mRendering->skySetDate (mGlobalVariables->getInt ("day"), | ||||
|                 mGlobalVariables->getInt ("month")); | ||||
|             mRendering->skyEnable(); | ||||
|             return true; | ||||
|         } | ||||
|  | @ -610,7 +625,7 @@ namespace MWWorld | |||
| 
 | ||||
|     bool World::toggleCollisionMode() | ||||
|     { | ||||
|         return mPhysics->toggleCollisionMode(); | ||||
|         return mPhysics->toggleCollisionMode();; | ||||
|     } | ||||
| 
 | ||||
|     bool World::toggleRenderMode (RenderMode mode) | ||||
|  | @ -687,5 +702,56 @@ namespace MWWorld | |||
|     void World::update (float 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 <openengine/bullet/physic.hpp> | ||||
| #include <openengine/ogre/fader.hpp> | ||||
| 
 | ||||
| namespace Ogre | ||||
| { | ||||
|  | @ -49,6 +50,7 @@ namespace MWRender | |||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|     class WeatherManager; | ||||
|     class Environment; | ||||
|     class Player; | ||||
| 
 | ||||
|  | @ -60,12 +62,15 @@ namespace MWWorld | |||
| 
 | ||||
|             enum RenderMode | ||||
|             { | ||||
|                 Render_CollisionDebug | ||||
|                 Render_CollisionDebug, | ||||
|                 Render_Wireframe | ||||
|             }; | ||||
| 
 | ||||
|         private: | ||||
| 
 | ||||
|             MWRender::RenderingManager* mRendering; | ||||
|              | ||||
|             MWWorld::WeatherManager* mWeatherManager; | ||||
| 
 | ||||
|             MWWorld::Scene *mWorldScene; | ||||
|             MWWorld::Player *mPlayer; | ||||
|  | @ -101,11 +106,13 @@ namespace MWWorld | |||
|                 Environment& environment, const std::string& encoding); | ||||
| 
 | ||||
|             ~World(); | ||||
|              | ||||
|             OEngine::Render::Fader* getFader(); | ||||
| 
 | ||||
|             Ptr::CellStore *getExterior (int x, int y); | ||||
| 
 | ||||
|             Ptr::CellStore *getInterior (const std::string& name); | ||||
| 
 | ||||
|              | ||||
|             void adjustSky(); | ||||
| 
 | ||||
|             MWWorld::Player& getPlayer(); | ||||
|  | @ -118,6 +125,9 @@ namespace MWWorld | |||
| 
 | ||||
|             bool hasCellChanged() const; | ||||
|             ///< 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); | ||||
| 
 | ||||
|  | @ -153,6 +163,10 @@ namespace MWWorld | |||
| 
 | ||||
|             bool toggleSky(); | ||||
|             ///< \return Resulting mode
 | ||||
|              | ||||
|             void changeWeather(const std::string& region, const unsigned int id); | ||||
|              | ||||
|             int getCurrentWeather() const; | ||||
| 
 | ||||
|             int getMasserPhase() const; | ||||
| 
 | ||||
|  | @ -224,6 +238,7 @@ namespace MWWorld | |||
|             /// references that are currently not in the rendered scene should be ignored.
 | ||||
| 
 | ||||
|             void update (float duration); | ||||
| 
 | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ | |||
| # Once done, this will define | ||||
| # | ||||
| #  OGRE_FOUND - system has OGRE | ||||
| #  OGRE_INCLUDE_DIRS - the OGRE include directories  | ||||
| #  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) | ||||
|  | @ -33,9 +33,10 @@ | |||
| # | ||||
| # For each of these components, the following variables are defined: | ||||
| # | ||||
| 
 | ||||
| #  OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available | ||||
| #  OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT} | ||||
| #  OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT}  | ||||
| #  OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT} | ||||
| #  OGRE_${COMPONENT}_BINARY_REL - location of the component binary (win32 non-static only, release) | ||||
| #  OGRE_${COMPONENT}_BINARY_DBG - location of the component binary (win32 non-static only, debug) | ||||
| # | ||||
|  | @ -112,7 +113,7 @@ if (OGRE_PREFIX_SOURCE AND OGRE_PREFIX_BUILD) | |||
|     set(OGRE_BIN_SEARCH_PATH ${dir}/bin ${OGRE_BIN_SEARCH_PATH}) | ||||
| 	set(OGRE_BIN_SEARCH_PATH ${dir}/Samples/Common/bin ${OGRE_BIN_SEARCH_PATH}) | ||||
|   endforeach(dir) | ||||
|    | ||||
| 
 | ||||
|   if (OGRE_PREFIX_DEPENDENCIES_DIR) | ||||
|     set(OGRE_INC_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/include ${OGRE_INC_SEARCH_PATH}) | ||||
|     set(OGRE_LIB_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/lib ${OGRE_LIB_SEARCH_PATH}) | ||||
|  | @ -124,12 +125,12 @@ else() | |||
| endif () | ||||
| 
 | ||||
| # redo search if any of the environmental hints changed | ||||
| set(OGRE_COMPONENTS Paging Terrain  | ||||
| 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  | ||||
| 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}) | ||||
|  | @ -265,7 +266,7 @@ if (OGRE_STATIC) | |||
|   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 () | ||||
|  | @ -308,7 +309,7 @@ if (OGRE_STATIC) | |||
|       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) | ||||
|  | @ -340,7 +341,7 @@ endif() | |||
| # Find Ogre components | ||||
| ######################################################### | ||||
| 
 | ||||
| set(OGRE_COMPONENT_SEARCH_PATH_REL  | ||||
| set(OGRE_COMPONENT_SEARCH_PATH_REL | ||||
|   ${OGRE_LIBRARY_DIR_REL}/.. | ||||
|   ${OGRE_LIBRARY_DIR_REL}/../.. | ||||
|   ${OGRE_BIN_SEARCH_PATH} | ||||
|  | @ -392,17 +393,17 @@ macro(ogre_find_plugin PLUGIN HEADER) | |||
|     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}  | ||||
|     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}   | ||||
|   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}") | ||||
|  | @ -428,7 +429,7 @@ macro(ogre_find_plugin PLUGIN HEADER) | |||
|   if (OGRE_${PLUGIN}_FOUND) | ||||
|     if (NOT OGRE_PLUGIN_DIR_REL OR NOT OGRE_PLUGIN_DIR_DBG) | ||||
|       if (WIN32) | ||||
|         set(OGRE_PLUGIN_SEARCH_PATH_REL  | ||||
|         set(OGRE_PLUGIN_SEARCH_PATH_REL | ||||
|           ${OGRE_LIBRARY_DIR_REL}/.. | ||||
|           ${OGRE_LIBRARY_DIR_REL}/../.. | ||||
| 		  ${OGRE_BIN_SEARCH_PATH} | ||||
|  | @ -449,7 +450,7 @@ macro(ogre_find_plugin PLUGIN HEADER) | |||
|         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) | ||||
|  | @ -458,7 +459,7 @@ macro(ogre_find_plugin PLUGIN HEADER) | |||
| 		endif() | ||||
| 		mark_as_advanced(OGRE_${PLUGIN}_REL OGRE_${PLUGIN}_DBG) | ||||
| 	endif() | ||||
| 	 | ||||
| 
 | ||||
|   endif () | ||||
| 
 | ||||
|   if (TMP_CMAKE_LIB_PREFIX) | ||||
|  | @ -498,7 +499,7 @@ if (OGRE_STATIC) | |||
|   if (NOT Cg_FOUND) | ||||
|     set(OGRE_Plugin_CgProgramManager_FOUND FALSE) | ||||
|   endif () | ||||
|    | ||||
| 
 | ||||
|   set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES} | ||||
|     ${DirectX_LIBRARIES} | ||||
|   ) | ||||
|  | @ -539,4 +540,3 @@ set(OGRE_MEDIA_SEARCH_SUFFIX | |||
| clear_if_changed(OGRE_PREFIX_WATCH OGRE_MEDIA_DIR) | ||||
| find_path(OGRE_MEDIA_DIR NAMES packs/cubemapsJS.zip HINTS ${OGRE_MEDIA_SEARCH_PATH} | ||||
|   PATHS ${OGRE_PREFIX_PATH} PATH_SUFFIXES ${OGRE_MEDIA_SEARCH_SUFFIX}) | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,10 +6,6 @@ add_component_dir (bsa | |||
|     bsa_archive bsa_file | ||||
|     ) | ||||
| 
 | ||||
| add_component_dir (cfg | ||||
|     configurationmanager | ||||
|     ) | ||||
| 
 | ||||
| add_component_dir (nif | ||||
|     controlled effect nif_types record controller extra node record_ptr data nif_file property | ||||
|     ) | ||||
|  | @ -47,7 +43,7 @@ add_component_dir (misc | |||
|     ) | ||||
| 
 | ||||
| add_component_dir (files | ||||
|     linuxpath windowspath macospath path multidircollection collections fileops | ||||
|     linuxpath windowspath macospath fixedpath multidircollection collections fileops configurationmanager | ||||
|     ) | ||||
| 
 | ||||
| add_component_dir (compiler | ||||
|  |  | |||
|  | @ -1,157 +0,0 @@ | |||
| #include "configurationmanager.hpp" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| 
 | ||||
| namespace Cfg | ||||
| { | ||||
| 
 | ||||
| static const char* const openmwCfgFile = "openmw.cfg"; | ||||
| static const char* const ogreCfgFile = "ogre.cfg"; | ||||
| static const char* const pluginsCfgFile = "plugins.cfg"; | ||||
| 
 | ||||
| 
 | ||||
| ConfigurationManager::ConfigurationManager() | ||||
|     : mPath("openmw") | ||||
| { | ||||
|     /**
 | ||||
|      * According to task #168 plugins.cfg file shall be located in global | ||||
|      * configuration path or in runtime configuration path. | ||||
|      */ | ||||
|     mPluginsCfgPath = mPath.getGlobalConfigPath() / pluginsCfgFile; | ||||
|     if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) | ||||
|     { | ||||
|         mPluginsCfgPath = mPath.getRuntimeConfigPath() / pluginsCfgFile; | ||||
|         if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) | ||||
|         { | ||||
|             std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl; | ||||
|             mPluginsCfgPath.clear(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * According to task #168 ogre.cfg file shall be located only | ||||
|      * in user configuration path. | ||||
|      */ | ||||
|     mOgreCfgPath = mPath.getLocalConfigPath() / ogreCfgFile; | ||||
| 
 | ||||
|     mLogPath = mPath.getLocalConfigPath(); | ||||
| } | ||||
| 
 | ||||
| ConfigurationManager::~ConfigurationManager() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables, | ||||
|     boost::program_options::options_description& description) | ||||
| { | ||||
|     loadConfig(mPath.getLocalConfigPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
|     loadConfig(mPath.getRuntimeConfigPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
|     loadConfig(mPath.getGlobalConfigPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::loadConfig(const boost::filesystem::path& path, | ||||
|     boost::program_options::variables_map& variables, | ||||
|     boost::program_options::options_description& description) | ||||
| { | ||||
|     boost::filesystem::path cfgFile(path); | ||||
|     cfgFile /= std::string(openmwCfgFile); | ||||
|     if (boost::filesystem::is_regular_file(cfgFile)) | ||||
|     { | ||||
|         std::cout << "Loading config file: " << cfgFile.string() << "... "; | ||||
| 
 | ||||
|         std::ifstream configFileStream(cfgFile.string().c_str()); | ||||
|         if (configFileStream.is_open()) | ||||
|         { | ||||
|             boost::program_options::store(boost::program_options::parse_config_file( | ||||
|                 configFileStream, description), variables); | ||||
| 
 | ||||
|             std::cout << "done." << std::endl; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             std::cout << "failed." << std::endl; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getGlobalConfigPath() const | ||||
| { | ||||
|     return mPath.getGlobalConfigPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setGlobalConfigPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setGlobalConfigPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getLocalConfigPath() const | ||||
| { | ||||
|     return mPath.getLocalConfigPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setLocalConfigPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setLocalConfigPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getRuntimeConfigPath() const | ||||
| { | ||||
|     return mPath.getRuntimeConfigPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setRuntimeConfigPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setRuntimeConfigPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getGlobalDataPath() const | ||||
| { | ||||
|     return mPath.getGlobalDataPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setGlobalDataPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setGlobalDataPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getLocalDataPath() const | ||||
| { | ||||
|     return mPath.getLocalDataPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setLocalDataPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setLocalDataPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getRuntimeDataPath() const | ||||
| { | ||||
|     return mPath.getRuntimeDataPath(); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setRuntimeDataPath(const boost::filesystem::path& newPath) | ||||
| { | ||||
|     mPath.setRuntimeDataPath(newPath); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const | ||||
| { | ||||
|     return mOgreCfgPath; | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const | ||||
| { | ||||
|     return mPluginsCfgPath; | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getLogPath() const | ||||
| { | ||||
|     return mLogPath; | ||||
| } | ||||
| 
 | ||||
| } /* namespace Cfg */ | ||||
|  | @ -1,62 +0,0 @@ | |||
| #ifndef COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP | ||||
| #define COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP | ||||
| 
 | ||||
| #include <boost/program_options.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #include <components/files/path.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Cfg | ||||
|  */ | ||||
| namespace Cfg | ||||
| { | ||||
| 
 | ||||
| /**
 | ||||
|  * \struct ConfigurationManager | ||||
|  */ | ||||
| struct ConfigurationManager | ||||
| { | ||||
|     ConfigurationManager(); | ||||
|     virtual ~ConfigurationManager(); | ||||
| 
 | ||||
|     void readConfiguration(boost::program_options::variables_map& variables, | ||||
|         boost::program_options::options_description& description); | ||||
| 
 | ||||
|     const boost::filesystem::path& getGlobalConfigPath() const; | ||||
|     void setGlobalConfigPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getLocalConfigPath() const; | ||||
|     void setLocalConfigPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getRuntimeConfigPath() const; | ||||
|     void setRuntimeConfigPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getGlobalDataPath() const; | ||||
|     void setGlobalDataPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getLocalDataPath() const; | ||||
|     void setLocalDataPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getRuntimeDataPath() const; | ||||
|     void setRuntimeDataPath(const boost::filesystem::path& newPath); | ||||
| 
 | ||||
|     const boost::filesystem::path& getOgreConfigPath() const; | ||||
|     const boost::filesystem::path& getPluginsConfigPath() const; | ||||
|     const boost::filesystem::path& getLogPath() const; | ||||
| 
 | ||||
|     private: | ||||
|         void loadConfig(const boost::filesystem::path& path, | ||||
|             boost::program_options::variables_map& variables, | ||||
|             boost::program_options::options_description& description); | ||||
| 
 | ||||
|         Files::Path<> mPath; | ||||
| 
 | ||||
|         boost::filesystem::path mOgreCfgPath; | ||||
|         boost::filesystem::path mPluginsCfgPath; | ||||
|         boost::filesystem::path mLogPath; | ||||
| }; | ||||
| 
 | ||||
| } /* namespace Cfg */ | ||||
| 
 | ||||
| #endif /* COMPONENTS_CFG_CONFIGURATIONMANAGER_HPP */ | ||||
|  | @ -153,7 +153,7 @@ public: | |||
|    *************************************************************************/ | ||||
| 
 | ||||
|   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; } | ||||
|   const std::string getAuthor() { return mCtx.header.author.toString(); } | ||||
|   const std::string getDesc() { return mCtx.header.desc.toString(); } | ||||
|  |  | |||
|  | @ -1,9 +1,11 @@ | |||
| #ifndef FILE_FINDER_MAIN_H | ||||
| #define FILE_FINDER_MAIN_H | ||||
| 
 | ||||
| #include <map> | ||||
| 
 | ||||
| #include "search.hpp" | ||||
| #include "filename_less.hpp" | ||||
| #include <map> | ||||
| #include <components/files/multidircollection.hpp> | ||||
| 
 | ||||
| namespace FileFinder | ||||
| { | ||||
|  | @ -11,7 +13,8 @@ namespace FileFinder | |||
| template <typename LESS> | ||||
| class FileFinderT | ||||
| { | ||||
|   std::map<std::string, std::string, LESS> table; | ||||
|   typedef std::map<std::string, std::string, LESS> TableContainer; | ||||
|   TableContainer table; | ||||
| 
 | ||||
|   struct Inserter : ReturnPath | ||||
|   { | ||||
|  | @ -35,12 +38,12 @@ public: | |||
| 
 | ||||
|     // Remember the original path length, so we can cut it away from
 | ||||
|     // the relative paths used as keys
 | ||||
|     std::string pstring = path.string(); | ||||
|     const std::string& pstring = path.string(); | ||||
|     inserter.cut = pstring.size(); | ||||
| 
 | ||||
|     // If the path does not end in a slash, then boost will add one
 | ||||
|     // later, which means one more character we have to remove.
 | ||||
|     char last = pstring[pstring.size()-1]; | ||||
|     char last = *pstring.rbegin(); | ||||
|     if(last != '\\' && last != '/') | ||||
|       inserter.cut++; | ||||
| 
 | ||||
|  | @ -56,12 +59,84 @@ public: | |||
|   // Find the full path from a relative path.
 | ||||
|   const std::string &lookup(const std::string& file) const | ||||
|   { | ||||
|         return table.find(file)->second; | ||||
|     static std::string empty; | ||||
|     typename TableContainer::const_iterator it = table.find(file); | ||||
|     return (it != table.end()) ? it->second : empty; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template | ||||
| < | ||||
|     class LESS | ||||
| > | ||||
| struct TreeFileFinder | ||||
| { | ||||
|     typedef TreeFileFinder<LESS> finder_t; | ||||
| 
 | ||||
|     TreeFileFinder(const Files::PathContainer& paths, bool recurse = true) | ||||
|     { | ||||
|         struct : ReturnPath | ||||
|         { | ||||
|             finder_t *owner; | ||||
|             int cut; | ||||
| 
 | ||||
|             void add(const boost::filesystem::path &pth) | ||||
|             { | ||||
|                 std::string file = pth.string(); | ||||
|                 std::string key = file.substr(cut); | ||||
|                 owner->mTable[key] = file; | ||||
|             } | ||||
|         } inserter; | ||||
| 
 | ||||
|         inserter.owner = this; | ||||
| 
 | ||||
|         for (Files::PathContainer::const_iterator it = paths.begin(); it != paths.end(); ++it) | ||||
|         { | ||||
| 
 | ||||
|             // Remember the original path length, so we can cut it away from
 | ||||
|             // the relative paths used as keys
 | ||||
|             const std::string& pstring = it->string(); | ||||
|             inserter.cut = pstring.size(); | ||||
| 
 | ||||
|             // If the path does not end in a slash, then boost will add one
 | ||||
|             // later, which means one more character we have to remove.
 | ||||
|             char last = *pstring.rbegin(); | ||||
|             if (last != '\\' && last != '/') | ||||
|             { | ||||
|               inserter.cut++; | ||||
|             } | ||||
| 
 | ||||
|             // Fill the map
 | ||||
|             find(*it, inserter, recurse); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool has(const std::string& file) const | ||||
|     { | ||||
|         return mTable.find(file) != mTable.end(); | ||||
|     } | ||||
| 
 | ||||
|     const std::string& lookup(const std::string& file) const | ||||
|     { | ||||
|         static std::string empty; | ||||
|         typename TableContainer::const_iterator it = mTable.find(file); | ||||
|         return (it != mTable.end()) ? it->second : empty; | ||||
|     } | ||||
| 
 | ||||
|     private: | ||||
|         typedef std::map<std::string, std::string, LESS> TableContainer; | ||||
|         TableContainer mTable; | ||||
| 
 | ||||
| //        Inserter inserter;
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // The default is to use path_less for equality checks
 | ||||
| typedef FileFinderT<path_less> FileFinder; | ||||
| typedef FileFinderT<path_slash> FileFinderStrict; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| typedef TreeFileFinder<path_less> LessTreeFileFinder; | ||||
| typedef TreeFileFinder<path_slash> StrictTreeFileFinder; | ||||
| 
 | ||||
| } /* namespace FileFinder */ | ||||
| #endif /* FILE_FINDER_MAIN_H */ | ||||
|  |  | |||
|  | @ -2,27 +2,35 @@ | |||
| 
 | ||||
| #include <iostream> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace boost::filesystem; | ||||
| 
 | ||||
| void FileFinder::find(const path & dir_path, ReturnPath &ret, bool recurse) | ||||
| void FileFinder::find(const boost::filesystem::path & dir_path, ReturnPath &ret, bool recurse) | ||||
| { | ||||
|   if ( !exists( dir_path ) ) | ||||
|     if (boost::filesystem::exists(dir_path)) | ||||
|     { | ||||
|       cout << "Path " << dir_path << " not found\n"; | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   directory_iterator end_itr; // default construction yields past-the-end
 | ||||
|   for ( directory_iterator itr(dir_path); | ||||
|         itr != end_itr; | ||||
|         ++itr ) | ||||
|     { | ||||
|       if ( is_directory( *itr ) ) | ||||
|         if (!recurse) | ||||
|         { | ||||
|           if(recurse) find(*itr, ret); | ||||
|             boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
 | ||||
|             for (boost::filesystem::directory_iterator itr(dir_path); itr != end_itr; ++itr) | ||||
|             { | ||||
|                 if (!boost::filesystem::is_directory( *itr )) | ||||
|                 { | ||||
|                     ret.add(*itr); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         ret.add(*itr); | ||||
|         else | ||||
|         { | ||||
|             boost::filesystem::recursive_directory_iterator end_itr; // default construction yields past-the-end
 | ||||
|             for (boost::filesystem::recursive_directory_iterator itr(dir_path); itr != end_itr; ++itr) | ||||
|             { | ||||
|                 if (!boost::filesystem::is_directory(*itr)) | ||||
|                 { | ||||
|                     ret.add(*itr); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         std::cout << "Path " << dir_path << " not found" << std::endl; | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										182
									
								
								components/files/configurationmanager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								components/files/configurationmanager.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,182 @@ | |||
| #include "configurationmanager.hpp" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/algorithm/string/erase.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Files | ||||
|  */ | ||||
| namespace Files | ||||
| { | ||||
| 
 | ||||
| static const char* const openmwCfgFile = "openmw.cfg"; | ||||
| static const char* const ogreCfgFile = "ogre.cfg"; | ||||
| static const char* const pluginsCfgFile = "plugins.cfg"; | ||||
| 
 | ||||
| const char* const mwToken = "?mw?"; | ||||
| const char* const localToken = "?local?"; | ||||
| const char* const userToken = "?user?"; | ||||
| const char* const globalToken = "?global?"; | ||||
| 
 | ||||
| ConfigurationManager::ConfigurationManager() | ||||
|     : mFixedPath("openmw") | ||||
| { | ||||
|     setupTokensMapping(); | ||||
| 
 | ||||
|     mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile; | ||||
|     if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) | ||||
|     { | ||||
|         mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile; | ||||
|         if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) | ||||
|         { | ||||
|             std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl; | ||||
|             mPluginsCfgPath.clear(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     mOgreCfgPath = mFixedPath.getUserPath() / ogreCfgFile; | ||||
|     mLogPath = mFixedPath.getUserPath(); | ||||
| } | ||||
| 
 | ||||
| ConfigurationManager::~ConfigurationManager() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::setupTokensMapping() | ||||
| { | ||||
|     mTokensMapping.insert(std::make_pair(mwToken, &FixedPath<>::getInstallPath)); | ||||
|     mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath)); | ||||
|     mTokensMapping.insert(std::make_pair(userToken, &FixedPath<>::getUserPath)); | ||||
|     mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath)); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables, | ||||
|     boost::program_options::options_description& description) | ||||
| { | ||||
|     loadConfig(mFixedPath.getUserPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
| 
 | ||||
|     loadConfig(mFixedPath.getLocalPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
|     loadConfig(mFixedPath.getGlobalPath(), variables, description); | ||||
|     boost::program_options::notify(variables); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::processPaths(Files::PathContainer& dataDirs) | ||||
| { | ||||
|     std::string path; | ||||
|     for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) | ||||
|     { | ||||
|         path = it->string(); | ||||
|         boost::erase_all(path, "\""); | ||||
|         *it = boost::filesystem::path(path); | ||||
| 
 | ||||
|         // Check if path contains a token
 | ||||
|         if (!path.empty() && *path.begin() == '?') | ||||
|         { | ||||
|             std::string::size_type pos = path.find('?', 1); | ||||
|             if (pos != std::string::npos && pos != 0) | ||||
|             { | ||||
|                 TokensMappingContainer::iterator tokenIt = mTokensMapping.find(path.substr(0, pos + 1)); | ||||
|                 if (tokenIt != mTokensMapping.end()) | ||||
|                 { | ||||
|                     boost::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))()); | ||||
|                     if (pos < path.length() - 1) | ||||
|                     { | ||||
|                         // There is something after the token, so we should
 | ||||
|                         // append it to the path
 | ||||
|                         tempPath /= path.substr(pos + 1, path.length() - pos); | ||||
|                     } | ||||
| 
 | ||||
|                     *it = tempPath; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // Clean invalid / unknown token, it will be removed outside the loop
 | ||||
|                     (*it).clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (!boost::filesystem::is_directory(*it)) | ||||
|         { | ||||
|             (*it).clear(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     dataDirs.erase(std::remove_if(dataDirs.begin(), dataDirs.end(), | ||||
|         boost::bind(&boost::filesystem::path::empty, _1)), dataDirs.end()); | ||||
| } | ||||
| 
 | ||||
| void ConfigurationManager::loadConfig(const boost::filesystem::path& path, | ||||
|     boost::program_options::variables_map& variables, | ||||
|     boost::program_options::options_description& description) | ||||
| { | ||||
|     boost::filesystem::path cfgFile(path); | ||||
|     cfgFile /= std::string(openmwCfgFile); | ||||
|     if (boost::filesystem::is_regular_file(cfgFile)) | ||||
|     { | ||||
|         std::cout << "Loading config file: " << cfgFile.string() << "... "; | ||||
| 
 | ||||
|         std::ifstream configFileStream(cfgFile.string().c_str()); | ||||
|         if (configFileStream.is_open()) | ||||
|         { | ||||
|             boost::program_options::store(boost::program_options::parse_config_file( | ||||
|                 configFileStream, description, true), variables); | ||||
| 
 | ||||
|             std::cout << "done." << std::endl; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             std::cout << "failed." << std::endl; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getGlobalPath() const | ||||
| { | ||||
|     return mFixedPath.getGlobalPath(); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getUserPath() const | ||||
| { | ||||
|     return mFixedPath.getUserPath(); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getLocalPath() const | ||||
| { | ||||
|     return mFixedPath.getLocalPath(); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getGlobalDataPath() const | ||||
| { | ||||
|     return mFixedPath.getGlobalDataPath(); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getInstallPath() const | ||||
| { | ||||
|     return mFixedPath.getInstallPath(); | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const | ||||
| { | ||||
|     return mOgreCfgPath; | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const | ||||
| { | ||||
|     return mPluginsCfgPath; | ||||
| } | ||||
| 
 | ||||
| const boost::filesystem::path& ConfigurationManager::getLogPath() const | ||||
| { | ||||
|     return mLogPath; | ||||
| } | ||||
| 
 | ||||
| } /* namespace Cfg */ | ||||
							
								
								
									
										71
									
								
								components/files/configurationmanager.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								components/files/configurationmanager.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| #ifndef COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP | ||||
| #define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #include <boost/tr1/tr1/unordered_map> | ||||
| #else | ||||
| #include <tr1/unordered_map> | ||||
| #endif | ||||
| 
 | ||||
| #include <boost/program_options.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #include <components/files/fixedpath.hpp> | ||||
| #include <components/files/collections.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Files | ||||
|  */ | ||||
| namespace Files | ||||
| { | ||||
| 
 | ||||
| /**
 | ||||
|  * \struct ConfigurationManager | ||||
|  */ | ||||
| struct ConfigurationManager | ||||
| { | ||||
|     ConfigurationManager(); | ||||
|     virtual ~ConfigurationManager(); | ||||
| 
 | ||||
|     void readConfiguration(boost::program_options::variables_map& variables, | ||||
|         boost::program_options::options_description& description); | ||||
|     void processPaths(Files::PathContainer& dataDirs); | ||||
| 
 | ||||
|     /**< Fixed paths */ | ||||
|     const boost::filesystem::path& getGlobalPath() const; | ||||
|     const boost::filesystem::path& getUserPath() const; | ||||
|     const boost::filesystem::path& getLocalPath() const; | ||||
| 
 | ||||
|     const boost::filesystem::path& getGlobalDataPath() const; | ||||
|     const boost::filesystem::path& getUserDataPath() const; | ||||
|     const boost::filesystem::path& getLocalDataPath() const; | ||||
|     const boost::filesystem::path& getInstallPath() const; | ||||
| 
 | ||||
|     const boost::filesystem::path& getOgreConfigPath() const; | ||||
|     const boost::filesystem::path& getPluginsConfigPath() const; | ||||
|     const boost::filesystem::path& getLogPath() const; | ||||
| 
 | ||||
|     private: | ||||
|         typedef Files::FixedPath<> FixedPathType; | ||||
| 
 | ||||
|         typedef const boost::filesystem::path& (FixedPathType::*path_type_f)() const; | ||||
|         typedef std::tr1::unordered_map<std::string, path_type_f> TokensMappingContainer; | ||||
| 
 | ||||
|         void loadConfig(const boost::filesystem::path& path, | ||||
|             boost::program_options::variables_map& variables, | ||||
|             boost::program_options::options_description& description); | ||||
| 
 | ||||
|         void setupTokensMapping(); | ||||
| 
 | ||||
|         FixedPathType mFixedPath; | ||||
| 
 | ||||
|         boost::filesystem::path mOgreCfgPath; | ||||
|         boost::filesystem::path mPluginsCfgPath; | ||||
|         boost::filesystem::path mLogPath; | ||||
| 
 | ||||
|         TokensMappingContainer mTokensMapping; | ||||
| }; | ||||
| 
 | ||||
| } /* namespace Cfg */ | ||||
| 
 | ||||
| #endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */ | ||||
							
								
								
									
										145
									
								
								components/files/fixedpath.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								components/files/fixedpath.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | |||
| /**
 | ||||
|  *  Open Morrowind - an opensource Elder Scrolls III: Morrowind | ||||
|  *  engine implementation. | ||||
|  * | ||||
|  *  Copyright (C) 2011 Open Morrowind Team | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| /** \file components/files/fixedpath.hpp */ | ||||
| 
 | ||||
| #ifndef COMPONENTS_FILES_FIXEDPATH_HPP | ||||
| #define COMPONENTS_FILES_FIXEDPATH_HPP | ||||
| 
 | ||||
| #include <string> | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #if defined(__linux__) || defined(__FreeBSD__) | ||||
|     #include <components/files/linuxpath.hpp> | ||||
|     namespace Files { typedef LinuxPath TargetPathType; } | ||||
| 
 | ||||
| #elif defined(__WIN32) || defined(__WINDOWS__) || defined(_WIN32) | ||||
|     #include <components/files/windowspath.hpp> | ||||
|     namespace Files { typedef WindowsPath TargetPathType; } | ||||
| 
 | ||||
| #elif defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__) | ||||
|     #include <components/files/macospath.hpp> | ||||
|     namespace Files { typedef MacOsPath TargetPathType; } | ||||
| 
 | ||||
| #else | ||||
|     #error "Unknown platform!" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Files | ||||
|  */ | ||||
| namespace Files | ||||
| { | ||||
| 
 | ||||
| /**
 | ||||
|  * \struct Path | ||||
|  * | ||||
|  * \tparam P - Path strategy class type (depends on target system) | ||||
|  * | ||||
|  */ | ||||
| template | ||||
| < | ||||
|     class P = TargetPathType | ||||
| > | ||||
| struct FixedPath | ||||
| { | ||||
|     typedef P PathType; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Path constructor. | ||||
|      * | ||||
|      * \param [in] application_name - Name of the application | ||||
|      */ | ||||
|     FixedPath(const std::string& application_name) | ||||
|         : mPath() | ||||
|         , mUserPath(mPath.getUserPath()) | ||||
|         , mGlobalPath(mPath.getGlobalPath()) | ||||
|         , mLocalPath(mPath.getLocalPath()) | ||||
|         , mGlobalDataPath(mPath.getGlobalDataPath()) | ||||
|         , mInstallPath(mPath.getInstallPath()) | ||||
|     { | ||||
|         if (!application_name.empty()) | ||||
|         { | ||||
|             boost::filesystem::path suffix(application_name + std::string("/")); | ||||
| 
 | ||||
|             mUserPath /= suffix; | ||||
|             mGlobalPath /= suffix; | ||||
|             mGlobalDataPath /= suffix; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path pointing to the user local configuration directory. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     const boost::filesystem::path& getUserPath() const | ||||
|     { | ||||
|         return mUserPath; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path pointing to the global (system) configuration directory. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     const boost::filesystem::path& getGlobalPath() const | ||||
|     { | ||||
|         return mGlobalPath; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path pointing to the directory where application was started. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     const boost::filesystem::path& getLocalPath() const | ||||
|     { | ||||
|         return mLocalPath; | ||||
|     } | ||||
| 
 | ||||
|     const boost::filesystem::path& getInstallPath() const | ||||
|     { | ||||
|         return mInstallPath; | ||||
|     } | ||||
| 
 | ||||
|     const boost::filesystem::path& getGlobalDataPath() const | ||||
|     { | ||||
|         return mGlobalDataPath; | ||||
|     } | ||||
| 
 | ||||
|     private: | ||||
|         PathType mPath; | ||||
| 
 | ||||
|         boost::filesystem::path mUserPath;       /**< User path  */ | ||||
|         boost::filesystem::path mGlobalPath;     /**< Global path */ | ||||
|         boost::filesystem::path mLocalPath;      /**< It is the same directory where application was run */ | ||||
| 
 | ||||
|         boost::filesystem::path mGlobalDataPath;        /**< Global application data path */ | ||||
| 
 | ||||
|         boost::filesystem::path mInstallPath; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| } /* namespace Files */ | ||||
| 
 | ||||
| #endif /* COMPONENTS_FILES_FIXEDPATH_HPP */ | ||||
|  | @ -22,12 +22,13 @@ | |||
| 
 | ||||
| #include "linuxpath.hpp" | ||||
| 
 | ||||
| #if defined(__linux__) | ||||
| #if defined(__linux__) || defined(__FreeBSD__) | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include <pwd.h> | ||||
| #include <unistd.h> | ||||
| #include <boost/filesystem/fstream.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Files | ||||
|  | @ -35,126 +36,128 @@ | |||
| namespace Files | ||||
| { | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getLocalConfigPath() const | ||||
| boost::filesystem::path LinuxPath::getUserPath() const | ||||
| { | ||||
|     boost::filesystem::path localConfigPath("."); | ||||
|     boost::filesystem::path userPath("."); | ||||
|     boost::filesystem::path suffix("/"); | ||||
| 
 | ||||
|     const char* theDir = getenv("OPENMW_CONFIG"); | ||||
|     const char* theDir = getenv("HOME"); | ||||
|     if (theDir == NULL) | ||||
|     { | ||||
|         theDir = getenv("XDG_CONFIG_HOME"); | ||||
|         if (theDir == NULL) | ||||
|         struct passwd* pwd = getpwuid(getuid()); | ||||
|         if (pwd != NULL) | ||||
|         { | ||||
|             theDir = getenv("HOME"); | ||||
|             if (theDir == NULL) | ||||
|             { | ||||
|                 struct passwd* pwd = getpwuid(getuid()); | ||||
|                 if (pwd != NULL) | ||||
|                 { | ||||
|                     theDir = pwd->pw_dir; | ||||
|                 } | ||||
|             } | ||||
|             if (theDir != NULL) | ||||
|             { | ||||
|                 suffix = boost::filesystem::path("/.config/"); | ||||
|             } | ||||
|             theDir = pwd->pw_dir; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (theDir != NULL) { | ||||
|         localConfigPath = boost::filesystem::path(theDir); | ||||
|     } | ||||
| 
 | ||||
|     localConfigPath /= suffix; | ||||
| 
 | ||||
|     return localConfigPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getGlobalConfigPath() const | ||||
| { | ||||
|     boost::filesystem::path globalConfigPath("/etc/xdg/"); | ||||
| 
 | ||||
|     char* theDir = getenv("XDG_CONFIG_DIRS"); | ||||
|     if (theDir != NULL) | ||||
|     { | ||||
|         // We take only first path from list
 | ||||
|         char* ptr = strtok(theDir, ":"); | ||||
|         if (ptr != NULL) | ||||
|         { | ||||
|             globalConfigPath = boost::filesystem::path(ptr); | ||||
|             globalConfigPath /= boost::filesystem::path("/"); | ||||
|         } | ||||
|         suffix = boost::filesystem::path("/.config/"); | ||||
|         userPath = boost::filesystem::path(theDir); | ||||
|     } | ||||
| 
 | ||||
|     return globalConfigPath; | ||||
|     userPath /= suffix; | ||||
| 
 | ||||
|     return userPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getRuntimeConfigPath() const | ||||
| boost::filesystem::path LinuxPath::getGlobalPath() const | ||||
| { | ||||
|     boost::filesystem::path globalPath("/etc/"); | ||||
|     return globalPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getLocalPath() const | ||||
| { | ||||
|     return boost::filesystem::path("./"); | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getLocalDataPath() const | ||||
| { | ||||
|     boost::filesystem::path localDataPath("."); | ||||
|     boost::filesystem::path suffix("/"); | ||||
| 
 | ||||
|     const char* theDir = getenv("OPENMW_DATA"); | ||||
|     if (theDir == NULL) | ||||
|     { | ||||
|         theDir = getenv("XDG_DATA_HOME"); | ||||
|         if (theDir == NULL) | ||||
|         { | ||||
|             theDir = getenv("HOME"); | ||||
|             if (theDir == NULL) | ||||
|             { | ||||
|                 struct passwd* pwd = getpwuid(getuid()); | ||||
|                 if (pwd != NULL) | ||||
|                 { | ||||
|                     theDir = pwd->pw_dir; | ||||
|                 } | ||||
|             } | ||||
|             if (theDir != NULL) | ||||
|             { | ||||
|                 suffix = boost::filesystem::path("/.local/share/"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (theDir != NULL) { | ||||
|         localDataPath = boost::filesystem::path(theDir); | ||||
|     } | ||||
| 
 | ||||
|     localDataPath /= suffix; | ||||
|     return localDataPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getGlobalDataPath() const | ||||
| { | ||||
|     boost::filesystem::path globalDataPath("/usr/local/share/"); | ||||
| 
 | ||||
|     char* theDir = getenv("XDG_DATA_DIRS"); | ||||
|     if (theDir != NULL) | ||||
|     { | ||||
|         // We take only first path from list
 | ||||
|         char* ptr = strtok(theDir, ":"); | ||||
|         if (ptr != NULL) | ||||
|         { | ||||
|             globalDataPath = boost::filesystem::path(ptr); | ||||
|             globalDataPath /= boost::filesystem::path("/"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     boost::filesystem::path globalDataPath("/usr/share/games/"); | ||||
|     return globalDataPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path LinuxPath::getRuntimeDataPath() const | ||||
| boost::filesystem::path LinuxPath::getInstallPath() const | ||||
| { | ||||
|     return boost::filesystem::path("./data/"); | ||||
| } | ||||
|     boost::filesystem::path installPath; | ||||
| 
 | ||||
|     char *homePath = getenv("HOME"); | ||||
|     if (homePath == NULL) | ||||
|     { | ||||
|         struct passwd* pwd = getpwuid(getuid()); | ||||
|         if (pwd != NULL) | ||||
|         { | ||||
|             homePath = pwd->pw_dir; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (homePath != NULL) | ||||
|     { | ||||
|         boost::filesystem::path wineDefaultRegistry(homePath); | ||||
|         wineDefaultRegistry /= ".wine/system.reg"; | ||||
| 
 | ||||
|         if (boost::filesystem::is_regular_file(wineDefaultRegistry)) | ||||
|         { | ||||
|             boost::filesystem::ifstream file(wineDefaultRegistry); | ||||
|             bool isRegEntry = false; | ||||
|             std::string line; | ||||
|             std::string mwpath; | ||||
| 
 | ||||
|             while (std::getline(file, line)) | ||||
|             { | ||||
|                 if (line[0] == '[') // we found an entry
 | ||||
|                 { | ||||
|                     if (isRegEntry) | ||||
|                     { | ||||
|                         break; | ||||
|                     } | ||||
| 
 | ||||
|                     isRegEntry = (line.find("Softworks\\\\Morrowind]") != std::string::npos); | ||||
|                 } | ||||
|                 else if (isRegEntry) | ||||
|                 { | ||||
|                     if (line[0] == '"') // empty line means new registry key
 | ||||
|                     { | ||||
|                         std::string key = line.substr(1, line.find('"', 1) - 1); | ||||
|                         if (strcasecmp(key.c_str(), "Installed Path") == 0) | ||||
|                         { | ||||
|                             std::string::size_type valuePos = line.find('=') + 2; | ||||
|                             mwpath = line.substr(valuePos, line.rfind('"') - valuePos); | ||||
| 
 | ||||
|                             std::string::size_type pos = mwpath.find("\\"); | ||||
|                             while (pos != std::string::npos) | ||||
|                             { | ||||
|                                mwpath.replace(pos, 2, "/"); | ||||
|                                pos = mwpath.find("\\", pos + 1); | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!mwpath.empty()) | ||||
|             { | ||||
|                 // Change drive letter to lowercase, so we could use
 | ||||
|                 // ~/.wine/dosdevices symlinks
 | ||||
|                 mwpath[0] = tolower(mwpath[0]); | ||||
|                 installPath /= homePath; | ||||
|                 installPath /= ".wine/dosdevices/"; | ||||
|                 installPath /= mwpath; | ||||
| 
 | ||||
|                 if (!boost::filesystem::is_directory(installPath)) | ||||
|                 { | ||||
|                     installPath.clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return installPath; | ||||
| } | ||||
| 
 | ||||
| } /* namespace Files */ | ||||
| 
 | ||||
| #endif /* defined(__linux__) */ | ||||
| #endif /* defined(__linux__) || defined(__FreeBSD__) */ | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ | |||
| #ifndef COMPONENTS_FILES_LINUXPATH_H | ||||
| #define COMPONENTS_FILES_LINUXPATH_H | ||||
| 
 | ||||
| #if defined(__linux__) | ||||
| #if defined(__linux__) || defined(__FreeBSD__) | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
|  | @ -39,18 +39,18 @@ namespace Files | |||
| struct LinuxPath | ||||
| { | ||||
|     /**
 | ||||
|      * \brief Return path to the local configuration directory. | ||||
|      * \brief Return path to the user directory. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getLocalConfigPath() const; | ||||
|     boost::filesystem::path getUserPath() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path to the global (system) configuration directory. | ||||
|      * \brief Return path to the global (system) directory where game files could be placed. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getGlobalConfigPath() const; | ||||
|     boost::filesystem::path getGlobalPath() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path to the runtime configuration directory which is the | ||||
|  | @ -58,33 +58,25 @@ struct LinuxPath | |||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getRuntimeConfigPath() const; | ||||
|     boost::filesystem::path getLocalPath() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path to the local data directory. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getLocalDataPath() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return path to the global (system) data directory. | ||||
|      * \brief | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getGlobalDataPath() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * \brief Return runtime data path which is a location where | ||||
|      * an application was started with 'data' suffix. | ||||
|      * \brief Gets the path of the installed Morrowind version if there is one. | ||||
|      * | ||||
|      * \return boost::filesystem::path | ||||
|      */ | ||||
|     boost::filesystem::path getRuntimeDataPath() const; | ||||
|     boost::filesystem::path getInstallPath() const; | ||||
| }; | ||||
| 
 | ||||
| } /* namespace Files */ | ||||
| 
 | ||||
| #endif /* defined(__linux__) */ | ||||
| #endif /* defined(__linux__) || defined(__FreeBSD__) */ | ||||
| 
 | ||||
| #endif /* COMPONENTS_FILES_LINUXPATH_H */ | ||||
|  |  | |||
|  | @ -27,6 +27,11 @@ | |||
| #include <cstdlib> | ||||
| #include <pwd.h> | ||||
| #include <unistd.h> | ||||
| #include <boost/filesystem/fstream.hpp> | ||||
| 
 | ||||
| /**
 | ||||
|  * FIXME: Someone with MacOS system should check this and correct if necessary | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \namespace Files | ||||
|  | @ -34,9 +39,9 @@ | |||
| namespace Files | ||||
| { | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getLocalConfigPath() const | ||||
| boost::filesystem::path MacOsPath::getUserPath() const | ||||
| { | ||||
|     boost::filesystem::path localConfigPath("."); | ||||
|     boost::filesystem::path userPath("."); | ||||
|     boost::filesystem::path suffix("/"); | ||||
| 
 | ||||
|     const char* theDir = getenv("HOME"); | ||||
|  | @ -50,66 +55,107 @@ boost::filesystem::path MacOsPath::getLocalConfigPath() const | |||
|     } | ||||
|     if (theDir != NULL) | ||||
|     { | ||||
|         localConfigPath = boost::filesystem::path(theDir) / "Library/Preferences/"; | ||||
|         userPath = boost::filesystem::path(theDir) / "Library/Preferences/"; | ||||
|     } | ||||
| 
 | ||||
|     localConfigPath /= suffix; | ||||
|     userPath /= suffix; | ||||
| 
 | ||||
|     return localConfigPath; | ||||
|     return userPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getGlobalConfigPath() const | ||||
| boost::filesystem::path MacOsPath::getGlobalPath() const | ||||
| { | ||||
|     boost::filesystem::path globalConfigPath("/Library/Preferences/"); | ||||
|     return globalConfigPath; | ||||
|     boost::filesystem::path globalPath("/Library/Preferences/"); | ||||
|     return globalPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getRuntimeConfigPath() const | ||||
| boost::filesystem::path MacOsPath::getLocalPath() const | ||||
| { | ||||
|     return boost::filesystem::path("./"); | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getLocalDataPath() const | ||||
| { | ||||
|     boost::filesystem::path localDataPath("."); | ||||
|     boost::filesystem::path suffix("/"); | ||||
| 
 | ||||
|     const char* theDir = getenv("OPENMW_DATA"); | ||||
|     if (theDir == NULL) | ||||
|     { | ||||
|         theDir = getenv("HOME"); | ||||
|         if (theDir == NULL) | ||||
|         { | ||||
|             struct passwd* pwd = getpwuid(getuid()); | ||||
|             if (pwd != NULL) | ||||
|             { | ||||
|                 theDir = pwd->pw_dir; | ||||
|             } | ||||
|         } | ||||
|         if (theDir != NULL) | ||||
|         { | ||||
|             suffix = boost::filesystem::path("/Library/Application Support/"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (theDir != NULL) | ||||
|     { | ||||
|         localDataPath = boost::filesystem::path(theDir); | ||||
|     } | ||||
| 
 | ||||
|     localDataPath /= suffix; | ||||
|     return localDataPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getGlobalDataPath() const | ||||
| { | ||||
|     boost::filesystem::path globalDataPath("/Library/Application Support/"); | ||||
|     return globalDataPath; | ||||
| } | ||||
| 
 | ||||
| boost::filesystem::path MacOsPath::getRuntimeDataPath() const | ||||
| boost::filesystem::path MacOsPath::getInstallPath() const | ||||
| { | ||||
|     return boost::filesystem::path("./data/"); | ||||
|     boost::filesystem::path installPath; | ||||
| 
 | ||||
|     char *homePath = getenv("HOME"); | ||||
|     if (homePath == NULL) | ||||
|     { | ||||
|         struct passwd* pwd = getpwuid(getuid()); | ||||
|         if (pwd != NULL) | ||||
|         { | ||||
|             homePath = pwd->pw_dir; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (homePath != NULL) | ||||
|     { | ||||
|         boost::filesystem::path wineDefaultRegistry(homePath); | ||||
|         wineDefaultRegistry /= ".wine/system.reg"; | ||||
| 
 | ||||
|         if (boost::filesystem::is_regular_file(wineDefaultRegistry)) | ||||
|         { | ||||
|             boost::filesystem::ifstream file(wineDefaultRegistry); | ||||
|             bool isRegEntry = false; | ||||
|             std::string line; | ||||
|             std::string mwpath; | ||||
| 
 | ||||
|             while (std::getline(file, line)) | ||||
|             { | ||||
|                 if (line[0] == '[') // we found an entry
 | ||||
|                 { | ||||
|                     if (isRegEntry) | ||||
|                     { | ||||
|                         break; | ||||
|                     } | ||||
| 
 | ||||
|                     isRegEntry = (line.find("Softworks\\\\Morrowind]") != std::string::npos); | ||||
|                 } | ||||
|                 else if (isRegEntry) | ||||
|                 { | ||||
|                     if (line[0] == '"') // empty line means new registry key
 | ||||
|                     { | ||||
|                         std::string key = line.substr(1, line.find('"', 1) - 1); | ||||
|                         if (strcasecmp(key.c_str(), "Installed Path") == 0) | ||||
|                         { | ||||
|                             std::string::size_type valuePos = line.find('=') + 2; | ||||
|                             mwpath = line.substr(valuePos, line.rfind('"') - valuePos); | ||||
| 
 | ||||
|                             std::string::size_type pos = mwpath.find("\\"); | ||||
|                             while (pos != std::string::npos) | ||||
|                             { | ||||
|                                mwpath.replace(pos, 2, "/"); | ||||
|                                pos = mwpath.find("\\", pos + 1); | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!mwpath.empty()) | ||||
|             { | ||||
|                 // Change drive letter to lowercase, so we could use ~/.wine/dosdevice symlinks
 | ||||
|                 mwpath[0] = tolower(mwpath[0]); | ||||
|                 installPath /= homePath; | ||||
|                 installPath /= ".wine/dosdevices/"; | ||||
|                 installPath /= mwpath; | ||||
| 
 | ||||
|                 if (!boost::filesystem::is_directory(installPath)) | ||||
|                 { | ||||
|                     installPath.clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return installPath; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue