diff --git a/.gitmodules b/.gitmodules index 6278081a7..1ce6250b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "libs/mangle"] path = libs/mangle - url = git://github.com/korslund/mangle.git + url = git://github.com/zinnschlag/mangle.git [submodule "libs/openengine"] path = libs/openengine - url = git://github.com/korslund/OpenEngine + url = git://github.com/zinnschlag/OpenEngine diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ad1c5a9e..7dc5ba3f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,22 @@ option(USE_AUDIERE "use Audiere for sound" OFF) option(USE_FFMPEG "use ffmpeg for sound" OFF) option(USE_MPG123 "use mpg123 + libsndfile for sound" ON) +find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems") + # Location of morrowind data files -set(MORROWIND_DATA_FILES "data" - CACHE PATH "location of Morrowind data files") +if(DPKG_PROGRAM) + set(MORROWIND_DATA_FILES "/usr/share/games/openmw/data/" CACHE PATH "location of Morrowind data files") + set(MORROWIND_RESOURCE_FILES "/usr/share/games/openmw/resources/" CACHE PATH "location of Morrowind data files") +else() + if (APPLE) + # set path inside bundle + set(MORROWIND_DATA_FILES "Contents/Resources/data" CACHE PATH "location of Morrowind data files") + set(MORROWIND_RESOURCE_FILES "Contents/Resources/resources" CACHE PATH "location of Morrowind data files") + else() + set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files") + set(MORROWIND_RESOURCE_FILES "resources" CACHE PATH "location of Morrowind data files") + endif(APPLE) +endif(DPKG_PROGRAM) if (WIN32) option(USE_DEBUG_CONSOLE "whether a debug console should be enabled for debug builds, if false debug output is redirected to Visual Studio output" ON) @@ -16,31 +29,30 @@ endif() # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) - # # Pre-built binaries being used? # IF(EXISTS "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd/ogre_1_7_1") set(PREBUILT_DIR "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd") message (STATUS "OpenMW pre-built binaries found at ${PREBUILT_DIR}.") - + SET(ENV{OGRE_HOME} "${PREBUILT_DIR}/ogre_1_7_1") - + SET(ENV{BOOST_ROOT} "${PREBUILT_DIR}/boost_1_42_0") set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(ENV{BOOST_INCLUDEDIR} "${BOOST_ROOT}/include") set(ENV{BOOST_LIBRARYDIR} "${BOOST_ROOT}/lib") - + set(ENV{FREETYPE_DIR} "${PREBUILT_DIR}/freetype-2.3.5-1") - + set(USE_MPG123 OFF) - set(USE_AUDIERE ON) + set(USE_AUDIERE ON) set(AUDIERE_INCLUDE_DIR "${PREBUILT_DIR}/audiere-1.9.4/include") set(AUDIERE_LIBRARY "${PREBUILT_DIR}/audiere-1.9.4/lib/audiere.lib") - + set(ENV{OPENALDIR} "${PREBUILT_DIR}/OpenAL 1.1 SDK") - + ELSE() message (STATUS "OpenMW pre-built binaries not found. Using standard locations.") ENDIF() @@ -81,6 +93,12 @@ set(NIFOGRE_HEADER ${COMP_DIR}/nifogre/ogre_nif_loader.hpp) source_group(components\\nifogre FILES ${NIFOGRE} ${NIFOGRE_HEADER}) +set(NIFBULLET + ${COMP_DIR}/nifbullet/bullet_nif_loader.cpp) +set(NIFBULLET_HEADER + ${COMP_DIR}/nifbullet/bullet_nif_loader.hpp) +source_group(components\\nifbullet FILES ${NIFBULLET} ${NIFBULLET_HEADER}) + set(TO_UTF8 ${COMP_DIR}/to_utf8/to_utf8.cpp) set(TO_UTF8_HEADER @@ -130,10 +148,10 @@ file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp) source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} ${TO_UTF8} - ${COMPILER} ${INTERPRETER} ${ESM} ${FILE_FINDER}) + ${COMPILER} ${INTERPRETER} ${ESM} ${FILE_FINDER} ${NIFBULLET}) set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER} ${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${TO_UTF8_HEADER} - ${INTERPRETER_HEADER} ${FILE_FINDER_HEADER}) + ${INTERPRETER_HEADER} ${FILE_FINDER_HEADER} ${NIFBULLET_HEADER}) # source directory: libs @@ -153,6 +171,21 @@ set(OENGINE_GUI ${LIBDIR}/openengine/gui/manager.cpp ) +set(OENGINE_BULLET + ${LIBDIR}/openengine/bullet/btKinematicCharacterController.cpp + ${LIBDIR}/openengine/bullet/btKinematicCharacterController.h + ${LIBDIR}/openengine/bullet/BtOgre.cpp + ${LIBDIR}/openengine/bullet/BtOgreExtras.h + ${LIBDIR}/openengine/bullet/BtOgreGP.h + ${LIBDIR}/openengine/bullet/BtOgrePG.h + ${LIBDIR}/openengine/bullet/CMotionState.cpp + ${LIBDIR}/openengine/bullet/CMotionState.h + ${LIBDIR}/openengine/bullet/physic.cpp + ${LIBDIR}/openengine/bullet/physic.hpp + ${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp + ${LIBDIR}/openengine/bullet/BulletShapeLoader.h +) + # Sound setup if (USE_AUDIERE) set(MANGLE_SOUND_OUTPUT @@ -193,7 +226,7 @@ set(OENGINE_SOUND ${LIBDIR}/mangle/sound/outputs/openal_out.cpp ${MANGLE_SOUND_OUTPUT} ) -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND}) +set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND} ${OENGINE_BULLET}) source_group(libs\\openengine FILES ${OENGINE_ALL}) set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) @@ -205,25 +238,34 @@ if (WIN32) add_definitions(-DBOOST_ALL_NO_LIB) else (WIN32) set(PLATFORM_INCLUDE_DIR "") +find_path (UUID_INCLUDE_DIR uuid/uuid.h) +include_directories(${UUID_INCLUDE_DIR}) endif (WIN32) if (MSVC10) -set(PLATFORM_INCLUDE_DIR "") + set(PLATFORM_INCLUDE_DIR "") + add_definitions(-DMYGUI_DONT_REPLACE_NULLPTR) endif() +if (APPLE) + set(Boost_USE_STATIC_LIBS ON) +endif (APPLE) + # Dependencies find_package(OGRE REQUIRED) find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread) find_package(OIS REQUIRED) find_package(OpenAL REQUIRED) +find_package(Bullet REQUIRED) include_directories("." - ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre + ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OIS_INCLUDE_DIR} ${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} + ${UUID_INCLUDE_DIR} ${LIBDIR} ) @@ -251,21 +293,19 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}") if (WIN32) configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.win32 "${OpenMW_BINARY_DIR}/plugins.cfg" COPYONLY) -else (WIN32) -configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.linux - "${OpenMW_BINARY_DIR}/plugins.cfg" COPYONLY) endif (WIN32) +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") +configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.linux + "${OpenMW_BINARY_DIR}/plugins.cfg") +endif() +if (APPLE) +configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac + "${OpenMW_BINARY_DIR}/plugins.cfg") +endif (APPLE) configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg") -if (APPLE) - set(APPLE_BUNDLE_RESOURCES - ${CMAKE_SOURCE_DIR}/files/openmw.cfg - ${CMAKE_SOURCE_DIR}/files/mac/plugins.cfg - ) -endif (APPLE) - # Compiler settings if (CMAKE_COMPILER_IS_GNUCC) #add_definitions (-Wall -Werror) @@ -275,21 +315,17 @@ endif (CMAKE_COMPILER_IS_GNUCC) # Apple bundling if (APPLE) set(MISC_FILES - ${CMAKE_SOURCE_DIR}/files/openmw.cfg - ${CMAKE_SOURCE_DIR}/files/mac/plugins.cfg - ${CMAKE_SOURCE_DIR}/files/mac/ogre.cfg) -install(TARGETS openmw - BUNDLE DESTINATION . - RUNTIME DESTINATION ../MacOS - COMPONENT Runtime) + ${OpenMW_BINARY_DIR}/openmw.cfg + ${OpenMW_BINARY_DIR}/plugins.cfg) install(FILES ${MISC_FILES} DESTINATION ../MacOS) +install(DIRECTORY "${OpenMW_BINARY_DIR}/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 "0.07") +set(CPACK_PACKAGE_VERSION "0.10") set(CPACK_PACKAGE_VERSION_MAJOR "0") -set(CPACK_PACKAGE_VERSION_MINOR "07") +set(CPACK_PACKAGE_VERSION_MINOR "10") set(CPACK_PACKAGE_VERSION_PATCH "") include(CPack) @@ -299,6 +335,57 @@ set(CMAKE_CXX_FLAGS "-arch i386") endif (APPLE) + +if(DPKG_PROGRAM) + SET(CMAKE_INSTALL_PREFIX "/usr") + + if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") + exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "describe" OUTPUT_VARIABLE GIT_VERSION ) + STRING(REGEX REPLACE "openmw-" "" VERSION_STRING "${GIT_VERSION}") + exec_program("git" ARGS "config --get user.name" OUTPUT_VARIABLE GIT_NAME ) + exec_program("git" ARGS "config --get user.email" OUTPUT_VARIABLE GIT_EMAIL) + set(PACKAGE_MAINTAINER "${GIT_NAME} <${GIT_EMAIL}>") + else() + #FIXME this should probably be read from some file like ${CMAKE_CURRENT_SOURCE_DIR}/VERSION or something that gets updated when changing version + set(VERSION_STRING "0.10.0") + set(PACKAGE_MAINTAINER "unknown") + endif() + + #Install global configuration files + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + + #Install resources + INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") + INSTALL(DIRECTORY DESTINATION "share/games/openmw/data/" COMPONENT "Resources") + + SET(CPACK_GENERATOR "DEB") + SET(CPACK_PACKAGE_NAME "openmw") + SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://openmw.com") + 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 + OpenMW is a reimplementation of the Bethesda Game Studios game The Elder Scrolls III: Morrowind. + Data files from the original game is required to run it.") + SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") + SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libogremain-1.7.1 (>= 1.7.1-1), libbullet2.77 (>= 2.77), libboost-filesystem1.42.0 (>= 1.42.0), libboost-program-options1.42.0 (>= 1.42.0), libboost-system1.42.0 (>= 1.42.0), libboost-thread1.42.0 (>= 1.42.0), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.2.0 (>= 1.2.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2)") + + SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") + + string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE) + execute_process( + COMMAND ${DPKG_PROGRAM} --print-architecture + OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME_LOWERCASE}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") + + + include(CPack) +endif(DPKG_PROGRAM) + # Apps and tools add_subdirectory( apps/openmw ) @@ -308,22 +395,40 @@ if (BUILD_ESMTOOL) endif() if (WIN32) + if (MSVC) if (USE_DEBUG_CONSOLE) - set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") - set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") + set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") + set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") else() - # Turn off debug console, debug output will be written to visual studio output instead - set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS") - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS") + # Turn off debug console, debug output will be written to visual studio output instead + set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS") + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS") endif() # Release builds use the debug console set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE") + endif(MSVC) - # TODO: At some point release builds should not use the console but rather write to a log file - #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") - #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") + # Same for MinGW + if (MINGW) + if (USE_DEBUG_CONSOLE) + set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,console") + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,console") + set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") + else(USE_DEBUG_CONSOLE) + set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,windows") + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,windows") + endif(USE_DEBUG_CONSOLE) + + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "-Wl,-subsystem,console") + set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "-Wl,-subsystem,console") + set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") + endif(MINGW) + + # TODO: At some point release builds should not use the console but rather write to a log file + #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") + #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") endif() diff --git a/README_Mac.md b/README_Mac.md index 3bac3f0c5..ee5faca98 100644 --- a/README_Mac.md +++ b/README_Mac.md @@ -29,22 +29,28 @@ Getting OpenMW Working ---------------------- 1. Clone this repository. -2. Install `bjam` through MacPorts. -3. Download [boost][] 1.43 and install it with the following command: +2. Note about libs: I prefer not to install them globally (i. e. in /usr/local/), so I installing them in directory in my home directory. If OpenMW sources is in $HOME/path/openmw, I'm using $HOME/path/libs/root as prefix for boost and other libs. + It's useful to create env var for lib install prefix: + $ export OMW_LIB_PREFIX=$HOME/path/libs/root - $ mkdir build && sudo bjam --build-dir=build \ - --layout=versioned --toolset=darwin architecture=i386 \ - address-model=32 --link=shared,static install +3. First of all, set for current terminal some env vars: + $ export CFLAGS="-arch i386" + $ export CXXFLAGS="-arch i386" + $ export LDFLAGS="-arch i386" + All libs will build with correct architecture. + If you close your terminal, you should set env vars again before pcoceeding to next steps! + +4. Download [boost][] (tested with 1.45) and install it with the following command: + + $ cd /path/to/boost/source + $ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX + $ ./bjam --build-dir=build --layout=versioned \ + --toolset=darwin architecture=x86 address-model=32 \ + --link-shared,static --prefix=$OMW_LIB_PREFIX install -4. Download [Ogre][] 1.7.1 and build and Xcode project with CMake: - - $ mdkir build && cd build && \ - BOOST_INCLUDEDIR=/usr/local/include/boost-1_43 \ - BOOST_LIBRARYDIR=/usr/local/lib cmake -G Xcode .. - -5. Once the build completes, move `lib/Release/Ogre.framework` into - `/Library/Frameworks`. +5. Download [Ogre][] SDK (tested with 1.7.2) and move `lib/Release/Ogre.framework` into + `Library/Frameworks`. 6. Download [OIS][] and use the XCode project provided in `ois/Mac/XCode-2.2`. Be sure to set your build architecture to @@ -52,20 +58,89 @@ Getting OpenMW Working builds, move `ois/Mac/XCode-2.2/build/Debug/OIS.framework` to `/Library/Frameworks`. -7. Generate the Makefile for OpenMW as follows: +7. Download [mpg123][] and build it: + $ cd /path/to/mpg123/source + $ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \ + --disable-dependency-tracking \ + --with-optimization=4 \ + --with-audio=coreaudio \ + --with-default-audio=coreaudio \ + --with-cpu=sse_alone \ + $ make install - $ mkdir build && cd build && \ - BOOST_INCLUDEDIR=/usr/local/include/boost-1_43 \ - BOOST_LIBRARYDIR=/usr/local/lib CMAKE_OSX_ARCHITECTURES=i386 \ - cmake .. +8. Download [libsndfile][] and build it: + $ cd /path/to/libsndfile/source + $ ./configure --prefix=$OMW_LIB_PREFIX \ + --disable-dependency-tracking + $ make install -8. Move your Morrowind `Data Files` directory into the root `openmw` - directory with the name `data`. Symlink it into the build directory. +9. Download [Bullet][] and build it: + $ cd /path/to/bullet/source + $ mkdir build + $ cd build + $ cmake -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$OMW_LIB_PREFIX \ + -DBUILD_EXTRAS=OFF \ + -DBUILD_DEMOS=OFF \ + -DCMAKE_OSX_ARCHITECTURES=i386 \ + -DCMAKE_INSTALL_NAME_DIR=$OMW_LIB_RPEFIX/lib \ + -G"Unix Makefiles" ../ + $ make install - $ cd build && ln -s ../data data +10. Generate the Makefile for OpenMW as follows and build OpenMW: + $ mkdir /path/to/openmw/build/dir + $ cd /path/to/open/build/dir + $ cmake \ + -D CMAKE_OSX_ARCHITECTURES=i386 \ + -D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \ + -D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \ + -D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \ + -D SNDFILE_LIBRARY=$OMW_LIB_PREFIX/lib/libsndfile.a \ + -D MPG123_LIBRARY=$OMW_LIB_PREFIX/lib/libmpg123.a \ + -D MPG123_INCLUDE_DIR=$OMW_LIB_PREFIX/include \ + -D BULLET_DYNAMICS_LIBRARY=$OMW_LIB_PREFIX/lib/libBulletDynamics.a \ + -D BULLET_COLLISION_LIBRARY=$OMW_LIB_PREFIX/lib/libBulletCollision.a \ + -D BULLET_MATH_LIBRARY=$OMW_LIB_PREFIX/lib/libLinearMath.a \ + -D BULLET_SOFTBODY_LIBRARY=$OMW_LIB_PREFIX/lib/libBulletSoftBody.a \ + -D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \ + -G "Unix Makefiles" /path/to/openmw/source/dir + $ make + You can use -G"Xcode" if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles" + if you prefer Eclipse. You also can specify -D CMAKE_BUILD_TYPE=Debug for debug + build. + +11. In build directory create directory for game resources: + $ cd /path/to/openmw/build/dir + $ mkdir Contents + $ mkdir Contents/Resources + $ mkdir Contents/Plugins + Copy Ogre plugins from Ogre SDK to Plugins subdir: + $ cp /path/to/ogre/sdk/lib/*.dylib Contents/Plugins + Create symlink to resources subdirectory: + $ ln -s resources Contents/Resources/resources + Create symlinks for *.cfg files: + $ ln -s plugins.cfg Contents/MacOS/plugins.cfg + $ ln -s openmw.cfg Contents/MacOS/openmw.cfg + +12. Move your Morrowind `Data Files` directory into the `Contents/Resources` + with the name `data` or create symlink: + $ ln -s /path/to/morrowind/data/files Contents/Resources/data + +13. From your build directory run: + $ ./openmw + Enjoy! + +14. Optionally you can create .app bundle: + $ make package + But for now you shold manually copy Contents directory from build directory to bundle + (because there is no plugins and resources in generated .app). + [boost]: http://www.boost.org [Ogre]: http://www.ogre3d.org +[Bullet]: http://bulletphysics.org [OIS]: http://wgois.sf.net +[mpg123]: http://www.mpg123.de +[libsndfile]: http://www.mega-nerd.com/libsndfile [official website]: http://openmw.com [Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/ diff --git a/apps/esmtool/esmtool_cmd.c b/apps/esmtool/esmtool_cmd.c index f7e4d2d32..d6556d9e7 100644 --- a/apps/esmtool/esmtool_cmd.c +++ b/apps/esmtool/esmtool_cmd.c @@ -354,45 +354,45 @@ struct option /* Names for the values of the `has_arg' field of `struct option'. */ #ifndef no_argument -#define no_argument 0 +#define no_argument 0 #endif #ifndef required_argument -#define required_argument 1 +#define required_argument 1 #endif #ifndef optional_argument -#define optional_argument 2 +#define optional_argument 2 #endif struct custom_getopt_data { - /* - * These have exactly the same meaning as the corresponding global variables, - * except that they are used for the reentrant versions of getopt. - */ - int custom_optind; - int custom_opterr; - int custom_optopt; - char *custom_optarg; + /* + * These have exactly the same meaning as the corresponding global variables, + * except that they are used for the reentrant versions of getopt. + */ + int custom_optind; + int custom_opterr; + int custom_optopt; + char *custom_optarg; - /* True if the internal members have been initialized. */ - int initialized; + /* True if the internal members have been initialized. */ + int initialized; - /* - * The next char to be scanned in the option-element in which the last option - * character we returned was found. This allows us to pick up the scan where - * we left off. If this is zero, or a null string, it means resume the scan by - * advancing to the next ARGV-element. - */ - char *nextchar; + /* + * The next char to be scanned in the option-element in which the last option + * character we returned was found. This allows us to pick up the scan where + * we left off. If this is zero, or a null string, it means resume the scan by + * advancing to the next ARGV-element. + */ + char *nextchar; - /* - * Describe the part of ARGV that contains non-options that have been skipped. - * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is - * the index after the last of them. - */ - int first_nonopt; - int last_nonopt; + /* + * Describe the part of ARGV that contains non-options that have been skipped. + * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is + * the index after the last of them. + */ + int first_nonopt; + int last_nonopt; }; /* @@ -448,137 +448,137 @@ static int custom_optopt = '?'; */ static void exchange(char **argv, struct custom_getopt_data *d) { - int bottom = d->first_nonopt; - int middle = d->last_nonopt; - int top = d->custom_optind; - char *tem; + int bottom = d->first_nonopt; + int middle = d->last_nonopt; + int top = d->custom_optind; + char *tem; - /* - * Exchange the shorter segment with the far end of the longer segment. - * That puts the shorter segment into the right place. It leaves the - * longer segment in the right place overall, but it consists of two - * parts that need to be swapped next. - */ - while (top > middle && middle > bottom) { - if (top - middle > middle - bottom) { - /* Bottom segment is the short one. */ - int len = middle - bottom; - int i; + /* + * Exchange the shorter segment with the far end of the longer segment. + * That puts the shorter segment into the right place. It leaves the + * longer segment in the right place overall, but it consists of two + * parts that need to be swapped next. + */ + while (top > middle && middle > bottom) { + if (top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + int i; - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = - argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } else { - /* Top segment is the short one. */ - int len = top - middle; - int i; + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = + argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + int i; - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - /* Update records for the slots the non-options now occupy. */ - d->first_nonopt += (d->custom_optind - d->last_nonopt); - d->last_nonopt = d->custom_optind; + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + /* Update records for the slots the non-options now occupy. */ + d->first_nonopt += (d->custom_optind - d->last_nonopt); + d->last_nonopt = d->custom_optind; } /* Initialize the internal data when the first call is made. */ static void custom_getopt_initialize(struct custom_getopt_data *d) { - /* - * Start processing options with ARGV-element 1 (since ARGV-element 0 - * is the program name); the sequence of previously skipped non-option - * ARGV-elements is empty. - */ - d->first_nonopt = d->last_nonopt = d->custom_optind; - d->nextchar = NULL; - d->initialized = 1; + /* + * Start processing options with ARGV-element 1 (since ARGV-element 0 + * is the program name); the sequence of previously skipped non-option + * ARGV-elements is empty. + */ + d->first_nonopt = d->last_nonopt = d->custom_optind; + d->nextchar = NULL; + d->initialized = 1; } #define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\0') /* return: zero: continue, nonzero: return given value to user */ static int shuffle_argv(int argc, char *const *argv,const struct option *longopts, - struct custom_getopt_data *d) + struct custom_getopt_data *d) { - /* - * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been - * moved back by the user (who may also have changed the arguments). - */ - if (d->last_nonopt > d->custom_optind) - d->last_nonopt = d->custom_optind; - if (d->first_nonopt > d->custom_optind) - d->first_nonopt = d->custom_optind; - /* - * If we have just processed some options following some - * non-options, exchange them so that the options come first. - */ - if (d->first_nonopt != d->last_nonopt && - d->last_nonopt != d->custom_optind) - exchange((char **) argv, d); - else if (d->last_nonopt != d->custom_optind) - d->first_nonopt = d->custom_optind; - /* - * Skip any additional non-options and extend the range of - * non-options previously skipped. - */ - while (d->custom_optind < argc && NONOPTION_P) - d->custom_optind++; - d->last_nonopt = d->custom_optind; - /* - * The special ARGV-element `--' means premature end of options. Skip - * it like a null option, then exchange with previous non-options as if - * it were an option, then skip everything else like a non-option. - */ - if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) { - d->custom_optind++; - if (d->first_nonopt != d->last_nonopt - && d->last_nonopt != d->custom_optind) - exchange((char **) argv, d); - else if (d->first_nonopt == d->last_nonopt) - d->first_nonopt = d->custom_optind; - d->last_nonopt = argc; - d->custom_optind = argc; - } - /* - * If we have done all the ARGV-elements, stop the scan and back over - * any non-options that we skipped and permuted. - */ - if (d->custom_optind == argc) { - /* - * Set the next-arg-index to point at the non-options that we - * previously skipped, so the caller will digest them. - */ - if (d->first_nonopt != d->last_nonopt) - d->custom_optind = d->first_nonopt; - return -1; - } - /* - * If we have come to a non-option and did not permute it, either stop - * the scan or describe it to the caller and pass it by. - */ - if (NONOPTION_P) { - d->custom_optarg = argv[d->custom_optind++]; - return 1; - } - /* - * We have found another option-ARGV-element. Skip the initial - * punctuation. - */ - d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-')); - return 0; + /* + * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been + * moved back by the user (who may also have changed the arguments). + */ + if (d->last_nonopt > d->custom_optind) + d->last_nonopt = d->custom_optind; + if (d->first_nonopt > d->custom_optind) + d->first_nonopt = d->custom_optind; + /* + * If we have just processed some options following some + * non-options, exchange them so that the options come first. + */ + if (d->first_nonopt != d->last_nonopt && + d->last_nonopt != d->custom_optind) + exchange((char **) argv, d); + else if (d->last_nonopt != d->custom_optind) + d->first_nonopt = d->custom_optind; + /* + * Skip any additional non-options and extend the range of + * non-options previously skipped. + */ + while (d->custom_optind < argc && NONOPTION_P) + d->custom_optind++; + d->last_nonopt = d->custom_optind; + /* + * The special ARGV-element `--' means premature end of options. Skip + * it like a null option, then exchange with previous non-options as if + * it were an option, then skip everything else like a non-option. + */ + if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) { + d->custom_optind++; + if (d->first_nonopt != d->last_nonopt + && d->last_nonopt != d->custom_optind) + exchange((char **) argv, d); + else if (d->first_nonopt == d->last_nonopt) + d->first_nonopt = d->custom_optind; + d->last_nonopt = argc; + d->custom_optind = argc; + } + /* + * If we have done all the ARGV-elements, stop the scan and back over + * any non-options that we skipped and permuted. + */ + if (d->custom_optind == argc) { + /* + * Set the next-arg-index to point at the non-options that we + * previously skipped, so the caller will digest them. + */ + if (d->first_nonopt != d->last_nonopt) + d->custom_optind = d->first_nonopt; + return -1; + } + /* + * If we have come to a non-option and did not permute it, either stop + * the scan or describe it to the caller and pass it by. + */ + if (NONOPTION_P) { + d->custom_optarg = argv[d->custom_optind++]; + return 1; + } + /* + * We have found another option-ARGV-element. Skip the initial + * punctuation. + */ + d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-')); + return 0; } /* @@ -592,180 +592,180 @@ static int shuffle_argv(int argc, char *const *argv,const struct option *longopt * */ static int check_long_opt(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind, - int print_errors, struct custom_getopt_data *d) + const struct option *longopts, int *longind, + int print_errors, struct custom_getopt_data *d) { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; - for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; + for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; - /* Test all long options for either exact match or abbreviated matches */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) { - if ((unsigned int) (nameend - d->nextchar) - == (unsigned int) strlen(p->name)) { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } else if (pfound == NULL) { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } else if (pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) { - if (print_errors) { - fprintf(stderr, - "%s: option `%s' is ambiguous\n", - argv[0], argv[d->custom_optind]); - } - d->nextchar += strlen(d->nextchar); - d->custom_optind++; - d->custom_optopt = 0; - return '?'; - } - if (pfound) { - option_index = indfound; - d->custom_optind++; - if (*nameend) { - if (pfound->has_arg != no_argument) - d->custom_optarg = nameend + 1; - else { - if (print_errors) { - if (argv[d->custom_optind - 1][1] == '-') { - /* --option */ - fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - } else { - /* +option or -option */ - fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[d->custom_optind - 1][0], pfound->name); - } + /* Test all long options for either exact match or abbreviated matches */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) { + if ((unsigned int) (nameend - d->nextchar) + == (unsigned int) strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else if (pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) { + if (print_errors) { + fprintf(stderr, + "%s: option `%s' is ambiguous\n", + argv[0], argv[d->custom_optind]); + } + d->nextchar += strlen(d->nextchar); + d->custom_optind++; + d->custom_optopt = 0; + return '?'; + } + if (pfound) { + option_index = indfound; + d->custom_optind++; + if (*nameend) { + if (pfound->has_arg != no_argument) + d->custom_optarg = nameend + 1; + else { + if (print_errors) { + if (argv[d->custom_optind - 1][1] == '-') { + /* --option */ + fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + } else { + /* +option or -option */ + fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[d->custom_optind - 1][0], pfound->name); + } - } - d->nextchar += strlen(d->nextchar); - d->custom_optopt = pfound->val; - return '?'; - } - } else if (pfound->has_arg == required_argument) { - if (d->custom_optind < argc) - d->custom_optarg = argv[d->custom_optind++]; - else { - if (print_errors) { - fprintf(stderr, - "%s: option `%s' requires an argument\n", - argv[0], - argv[d->custom_optind - 1]); - } - d->nextchar += strlen(d->nextchar); - d->custom_optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->nextchar += strlen(d->nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - /* - * Can't find it as a long option. If this is not getopt_long_only, or - * the option starts with '--' or is not a valid short option, then - * it's an error. Otherwise interpret it as a short option. - */ - if (print_errors) { - if (argv[d->custom_optind][1] == '-') { - /* --option */ - fprintf(stderr, - "%s: unrecognized option `--%s'\n", - argv[0], d->nextchar); - } else { - /* +option or -option */ - fprintf(stderr, - "%s: unrecognized option `%c%s'\n", - argv[0], argv[d->custom_optind][0], - d->nextchar); - } - } - d->nextchar = (char *) ""; - d->custom_optind++; - d->custom_optopt = 0; - return '?'; + } + d->nextchar += strlen(d->nextchar); + d->custom_optopt = pfound->val; + return '?'; + } + } else if (pfound->has_arg == required_argument) { + if (d->custom_optind < argc) + d->custom_optarg = argv[d->custom_optind++]; + else { + if (print_errors) { + fprintf(stderr, + "%s: option `%s' requires an argument\n", + argv[0], + argv[d->custom_optind - 1]); + } + d->nextchar += strlen(d->nextchar); + d->custom_optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->nextchar += strlen(d->nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* + * Can't find it as a long option. If this is not getopt_long_only, or + * the option starts with '--' or is not a valid short option, then + * it's an error. Otherwise interpret it as a short option. + */ + if (print_errors) { + if (argv[d->custom_optind][1] == '-') { + /* --option */ + fprintf(stderr, + "%s: unrecognized option `--%s'\n", + argv[0], d->nextchar); + } else { + /* +option or -option */ + fprintf(stderr, + "%s: unrecognized option `%c%s'\n", + argv[0], argv[d->custom_optind][0], + d->nextchar); + } + } + d->nextchar = (char *) ""; + d->custom_optind++; + d->custom_optopt = 0; + return '?'; } static int check_short_opt(int argc, char *const *argv, const char *optstring, - int print_errors, struct custom_getopt_data *d) + int print_errors, struct custom_getopt_data *d) { - char c = *d->nextchar++; - const char *temp = strchr(optstring, c); + char c = *d->nextchar++; + const char *temp = strchr(optstring, c); - /* Increment `custom_optind' when we start to process its last character. */ - if (*d->nextchar == '\0') - ++d->custom_optind; - if (!temp || c == ':') { - if (print_errors) - fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); + /* Increment `custom_optind' when we start to process its last character. */ + if (*d->nextchar == '\0') + ++d->custom_optind; + if (!temp || c == ':') { + if (print_errors) + fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); - d->custom_optopt = c; - return '?'; - } - if (temp[1] == ':') { - if (temp[2] == ':') { - /* This is an option that accepts an argument optionally. */ - if (*d->nextchar != '\0') { - d->custom_optarg = d->nextchar; - d->custom_optind++; - } else - d->custom_optarg = NULL; - d->nextchar = NULL; - } else { - /* This is an option that requires an argument. */ - if (*d->nextchar != '\0') { - d->custom_optarg = d->nextchar; - /* - * If we end this ARGV-element by taking the - * rest as an arg, we must advance to the next - * element now. - */ - d->custom_optind++; - } else if (d->custom_optind == argc) { - if (print_errors) { - fprintf(stderr, - "%s: option requires an argument -- %c\n", - argv[0], c); - } - d->custom_optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } else - /* - * We already incremented `custom_optind' once; - * increment it again when taking next ARGV-elt - * as argument. - */ - d->custom_optarg = argv[d->custom_optind++]; - d->nextchar = NULL; - } - } - return c; + d->custom_optopt = c; + return '?'; + } + if (temp[1] == ':') { + if (temp[2] == ':') { + /* This is an option that accepts an argument optionally. */ + if (*d->nextchar != '\0') { + d->custom_optarg = d->nextchar; + d->custom_optind++; + } else + d->custom_optarg = NULL; + d->nextchar = NULL; + } else { + /* This is an option that requires an argument. */ + if (*d->nextchar != '\0') { + d->custom_optarg = d->nextchar; + /* + * If we end this ARGV-element by taking the + * rest as an arg, we must advance to the next + * element now. + */ + d->custom_optind++; + } else if (d->custom_optind == argc) { + if (print_errors) { + fprintf(stderr, + "%s: option requires an argument -- %c\n", + argv[0], c); + } + d->custom_optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } else + /* + * We already incremented `custom_optind' once; + * increment it again when taking next ARGV-elt + * as argument. + */ + d->custom_optarg = argv[d->custom_optind++]; + d->nextchar = NULL; + } + } + return c; } /* @@ -839,59 +839,59 @@ static int check_short_opt(int argc, char *const *argv, const char *optstring, */ static int getopt_internal_r(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind, - struct custom_getopt_data *d) + const struct option *longopts, int *longind, + struct custom_getopt_data *d) { - int ret, print_errors = d->custom_opterr; + int ret, print_errors = d->custom_opterr; - if (optstring[0] == ':') - print_errors = 0; - if (argc < 1) - return -1; - d->custom_optarg = NULL; + if (optstring[0] == ':') + print_errors = 0; + if (argc < 1) + return -1; + d->custom_optarg = NULL; - /* - * This is a big difference with GNU getopt, since optind == 0 - * means initialization while here 1 means first call. - */ - if (d->custom_optind == 0 || !d->initialized) { - if (d->custom_optind == 0) - d->custom_optind = 1; /* Don't scan ARGV[0], the program name. */ - custom_getopt_initialize(d); - } - if (d->nextchar == NULL || *d->nextchar == '\0') { - ret = shuffle_argv(argc, argv, longopts, d); - if (ret) - return ret; - } - if (longopts && (argv[d->custom_optind][1] == '-' )) - return check_long_opt(argc, argv, optstring, longopts, - longind, print_errors, d); - return check_short_opt(argc, argv, optstring, print_errors, d); + /* + * This is a big difference with GNU getopt, since optind == 0 + * means initialization while here 1 means first call. + */ + if (d->custom_optind == 0 || !d->initialized) { + if (d->custom_optind == 0) + d->custom_optind = 1; /* Don't scan ARGV[0], the program name. */ + custom_getopt_initialize(d); + } + if (d->nextchar == NULL || *d->nextchar == '\0') { + ret = shuffle_argv(argc, argv, longopts, d); + if (ret) + return ret; + } + if (longopts && (argv[d->custom_optind][1] == '-' )) + return check_long_opt(argc, argv, optstring, longopts, + longind, print_errors, d); + return check_short_opt(argc, argv, optstring, print_errors, d); } static int custom_getopt_internal(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind) + const struct option *longopts, int *longind) { - int result; - /* Keep a global copy of all internal members of d */ - static struct custom_getopt_data d; + int result; + /* Keep a global copy of all internal members of d */ + static struct custom_getopt_data d; - d.custom_optind = custom_optind; - d.custom_opterr = custom_opterr; - result = getopt_internal_r(argc, argv, optstring, longopts, - longind, &d); - custom_optind = d.custom_optind; - custom_optarg = d.custom_optarg; - custom_optopt = d.custom_optopt; - return result; + d.custom_optind = custom_optind; + d.custom_opterr = custom_opterr; + result = getopt_internal_r(argc, argv, optstring, longopts, + longind, &d); + custom_optind = d.custom_optind; + custom_optarg = d.custom_optarg; + custom_optopt = d.custom_optopt; + return result; } static int custom_getopt_long (int argc, char *const *argv, const char *options, - const struct option *long_options, int *opt_index) + const struct option *long_options, int *opt_index) { - return custom_getopt_internal(argc, argv, options, long_options, - opt_index); + return custom_getopt_internal(argc, argv, options, long_options, + opt_index); } @@ -989,7 +989,7 @@ cmdline_parser_internal ( int argc, char * const *argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { - int c; /* Character of the parsed option. */ + int c; /* Character of the parsed option. */ int error = 0; struct gengetopt_args_info local_args_info; @@ -1026,11 +1026,11 @@ cmdline_parser_internal ( int option_index = 0; static struct option long_options[] = { - { "help", 0, NULL, 'h' }, - { "version", 0, NULL, 'V' }, - { "raw", 0, NULL, 'r' }, - { "quiet", 0, NULL, 'q' }, - { "loadcells", 0, NULL, 'C' }, + { "help", 0, NULL, 'h' }, + { "version", 0, NULL, 'V' }, + { "raw", 0, NULL, 'r' }, + { "quiet", 0, NULL, 'q' }, + { "loadcells", 0, NULL, 'C' }, { 0, 0, 0, 0 } }; @@ -1046,21 +1046,21 @@ cmdline_parser_internal ( opterr = custom_opterr; optopt = custom_optopt; - if (c == -1) break; /* Exit from `while (1)' loop. */ + if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { - case 'h': /* Print help and exit. */ + case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); - case 'V': /* Print version and exit. */ + case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); - case 'r': /* Show an unformattet list of all records and subrecords. */ + case 'r': /* Show an unformattet list of all records and subrecords. */ if (update_arg( 0 , @@ -1072,7 +1072,7 @@ cmdline_parser_internal ( goto failure; break; - case 'q': /* Supress all record information. Useful for speed tests.. */ + case 'q': /* Supress all record information. Useful for speed tests.. */ if (update_arg( 0 , @@ -1084,7 +1084,7 @@ cmdline_parser_internal ( goto failure; break; - case 'C': /* Browse through contents of all cells.. */ + case 'C': /* Browse through contents of all cells.. */ if (update_arg( 0 , @@ -1097,12 +1097,12 @@ cmdline_parser_internal ( break; - case 0: /* Long option with no short option */ - case '?': /* Invalid option. */ + case 0: /* Long option with no short option */ + case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; - default: /* bug: option not considered. */ + default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ diff --git a/apps/esmtool/esmtool_cmd.h b/apps/esmtool/esmtool_cmd.h index c2561c00a..8c420c189 100644 --- a/apps/esmtool/esmtool_cmd.h +++ b/apps/esmtool/esmtool_cmd.h @@ -43,11 +43,11 @@ struct gengetopt_args_info 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. */ + 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 */ diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 88aaaecd4..0fa027f0c 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -4,7 +4,8 @@ project(OpenMW) set(GAME main.cpp - engine.cpp) + engine.cpp + path.cpp) set(GAME_HEADER engine.hpp) source_group(game FILES ${GAME} ${GAME_HEADER}) @@ -14,16 +15,18 @@ set(GAMEREND mwrender/cellimp.cpp mwrender/interior.cpp mwrender/exterior.cpp - mwrender/playerpos.cpp - mwrender/sky.cpp) + mwrender/sky.cpp + mwrender/player.cpp + ) set(GAMEREND_HEADER mwrender/cell.hpp mwrender/cellimp.hpp mwrender/mwscene.hpp mwrender/interior.hpp mwrender/exterior.hpp - mwrender/playerpos.hpp - mwrender/sky.hpp) + mwrender/sky.hpp + mwrender/player.hpp + ) source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER}) set(GAMEINPUT @@ -46,6 +49,7 @@ set(GAMEGUI_HEADER mwgui/dialogue.hpp mwgui/dialogue_history.hpp mwgui/window_base.hpp + mwgui/stats_window.hpp ) set(GAMEGUI mwgui/window_manager.cpp @@ -60,6 +64,7 @@ set(GAMEGUI mwgui/dialogue.cpp mwgui/dialogue_history.cpp mwgui/window_base.cpp + mwgui/stats_window.cpp ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) @@ -103,6 +108,7 @@ set(GAMESCRIPT_HEADER mwscript/controlextensions.hpp mwscript/extensions.hpp mwscript/globalscripts.hpp + mwscript/ref.hpp ) source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER}) @@ -120,6 +126,8 @@ set(GAMEWORLD mwworld/actiontalk.cpp mwworld/actiontake.cpp mwworld/containerutil.cpp + mwworld/player.cpp + mwworld/doingphysics.cpp ) set(GAMEWORLD_HEADER mwworld/refdata.hpp @@ -137,6 +145,9 @@ set(GAMEWORLD_HEADER mwworld/containerstore.hpp mwworld/manualref.hpp mwworld/containerutil.hpp + mwworld/player.hpp + mwworld/doingphysics.hpp + mwworld/cellfunctors.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) @@ -198,6 +209,7 @@ set(GAMEMECHANICS_HEADER mwmechanics/stat.hpp mwmechanics/creaturestats.hpp mwmechanics/magiceffects.hpp + mwmechanics/movement.hpp ) source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER}) @@ -219,7 +231,7 @@ add_executable(openmw # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING # when we change the backend. -include_directories(${SOUND_INPUT_INCLUDES}) +include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS}) add_definitions(${SOUND_DEFINE}) target_link_libraries(openmw @@ -228,6 +240,7 @@ target_link_libraries(openmw ${Boost_LIBRARIES} ${OPENAL_LIBRARY} ${SOUND_INPUT_LIBRARY} + ${BULLET_LIBRARIES} caelum MyGUIEngine MyGUIOgrePlatform @@ -236,4 +249,12 @@ 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) + INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw) +endif() diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d0f09c214..78ddffbe8 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -6,6 +6,8 @@ #include #include +#include + #include "components/esm/records.hpp" #include #include @@ -29,6 +31,7 @@ #include "mwworld/ptr.hpp" #include "mwworld/environment.hpp" #include "mwworld/class.hpp" +#include "mwworld/player.hpp" #include "mwclass/classes.hpp" @@ -38,11 +41,15 @@ #include +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE +#include +#endif + #include #include "mwgui/class.hpp" +#include "path.hpp" - - +#include "components/nifbullet/bullet_nif_loader.hpp" //using namespace ESM; @@ -69,73 +76,76 @@ void OMW::Engine::executeLocalScripts() bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) { - if(! (mEnvironment.mSoundManager->isMusicPlaying())) - { - // Play some good 'ol tunes - mEnvironment.mSoundManager->startRandomTitle(); - } + if(mShowFPS) + { + mEnvironment.mWindowManager->wmSetFPS(mOgre.getFPS()); + } - std::string effect; + if(mUseSound && !(mEnvironment.mSoundManager->isMusicPlaying())) + { + // Play some good 'ol tunes + mEnvironment.mSoundManager->startRandomTitle(); + } - - - MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayerPos().getPlayer().getCell(); - //If the region has changed - if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ - timer.restart(); - if (test.name != current->cell->region) - { - total = 0; - test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); - } - - if(test.soundList.size() > 0) - { - std::vector::iterator soundIter = test.soundList.begin(); - //mEnvironment.mSoundManager - if(total == 0){ - while (!(soundIter == test.soundList.end())) - { - ESM::NAME32 go = soundIter->sound; - int chance = (int) soundIter->chance; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - soundIter++; - total += chance; - } - } + std::string effect; - srand ( time(NULL) ); - int r = rand() % total; //old random code - int pos = 0; - soundIter = test.soundList.begin(); - while (!(soundIter == test.soundList.end())) - { - const ESM::NAME32 go = soundIter->sound; - int chance = (int) soundIter->chance; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - 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); - - break; + 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){ + timer.restart(); + if (test.name != current->cell->region) + { + total = 0; + test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); + } - } - pos += chance; - } - } - - //mEnvironment.mSoundManager->playSound(effect, 1.0, 1.0); - //printf("REGION: %s\n", test.name); + if(test.soundList.size() > 0) + { + std::vector::iterator soundIter = test.soundList.begin(); + //mEnvironment.mSoundManager + if(total == 0){ + while (!(soundIter == test.soundList.end())) + { + ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + total += chance; + } + } - } - else if(current->cell->data.flags & current->cell->Interior) - { - test.name = ""; - } + srand ( time(NULL) ); + int r = rand() % total; //old random code + int pos = 0; + soundIter = test.soundList.begin(); + while (!(soundIter == test.soundList.end())) + { + const ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + 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); + + break; + + } + pos += chance; + } + } + + //mEnvironment.mSoundManager->playSound(effect, 1.0, 1.0); + //printf("REGION: %s\n", test.name); + + } + else if(current->cell->data.flags & current->cell->Interior) + { + test.name = ""; + } try { @@ -160,7 +170,8 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) mEnvironment.mWorld->markCellAsUnchanged(); // update actors - mEnvironment.mMechanicsManager->update(); + std::vector > movement; + mEnvironment.mMechanicsManager->update (movement); if (focusFrameCounter++ == focusUpdateFrame) { @@ -181,21 +192,27 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) focusFrameCounter = 0; } + + if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game) + mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration); } catch (const std::exception& e) { std::cerr << "Error in framelistener: " << e.what() << std::endl; } - //std::cout << "TESTING2"; + //std::cout << "TESTING2"; return true; } OMW::Engine::Engine() - : mDebug (false) + : mPhysicEngine (0) + , mShowFPS (false) + , mDebug (false) , mVerboseScripts (false) , mNewGame (false) , mUseSound (true) + , mCompileAll (false) , mScriptManager (0) , mScriptContext (0) , mGuiManager (0) @@ -213,6 +230,7 @@ OMW::Engine::~Engine() delete mEnvironment.mDialogueManager; delete mScriptManager; delete mScriptContext; + delete mPhysicEngine; } // Load all BSA files in data directory. @@ -226,7 +244,7 @@ void OMW::Engine::loadBSA() if (boost::filesystem::extension (iter->path())==".bsa") { std::cout << "Adding " << iter->path().string() << std::endl; - addBSA(iter->path().file_string()); + addBSA(iter->path().string()); } } } @@ -236,7 +254,7 @@ void OMW::Engine::loadBSA() void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path) { - mOgre.getRoot()->addResourceLocation (path.file_string(), "FileSystem", + mOgre.getRoot()->addResourceLocation (path.string(), "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); } @@ -247,6 +265,12 @@ void OMW::Engine::setDataDir (const boost::filesystem::path& dataDir) mDataDir = boost::filesystem::system_complete (dataDir); } +// Set resource dir +void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir) +{ + mResDir = boost::filesystem::system_complete(parResDir); +} + // Set start cell name (only interiors for now) void OMW::Engine::setCell (const std::string& cellName) @@ -295,55 +319,60 @@ void OMW::Engine::go() assert (!mCellName.empty()); assert (!mMaster.empty()); - test.name = ""; - total = 0; + test.name = ""; + total = 0; + - std::cout << "Data directory: " << mDataDir << "\n"; - const char* plugCfg = "plugins.cfg"; + std::string cfgDir = OMW::Path::getPath(OMW::Path::GLOBAL_CFG_PATH, "openmw", ""); + std::string cfgUserDir = OMW::Path::getPath(OMW::Path::USER_CFG_PATH, "openmw", ""); + std::string plugCfg = "plugins.cfg"; + std::string ogreCfg = "ogre.cfg"; + ogreCfg.insert(0, cfgUserDir); - mOgre.configure(!isFile("ogre.cfg"), plugCfg, false); + //A local plugins.cfg will be used if it exist, otherwise look in the default path + if(!isFile(plugCfg.c_str())) + { + plugCfg.insert(0, cfgDir); + } + + mOgre.configure(!isFile(ogreCfg.c_str()), cfgUserDir, plugCfg, false); addResourcesDirectory (mDataDir / "Meshes"); addResourcesDirectory (mDataDir / "Textures"); - //boost::filesystem::copy_file("meshes\\b\\B_N_Argonian_F_Skins.nif",mDataDir / "b2\\B_N_Argonian_F_Skins.nif",boost::filesystem::copy_option::overwrite_if_exists); - /*CFileOperation fo; // create object - - fo.SetOverwriteMode(false); // reset OverwriteMode flag (optional) - - if (!fo.Copy("c:\\source", "c:\\dest")) // do Copy - { - fo.ShowError(); // if copy fails show error message - }*/ - // This has to be added BEFORE MyGUI is initialized, as it needs // to find core.xml here. - addResourcesDirectory("resources/mygui/"); + addResourcesDirectory(mResDir / "mygui"); // Create the window mOgre.createWindow("OpenMW"); loadBSA(); + // Create physics. shapeLoader is deleted by the physic engine + ManualBulletShapeLoader* shapeLoader = new ManualBulletShapeLoader(); + mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader); + // Create the world - mEnvironment.mWorld = new MWWorld::World (mOgre, mDataDir, mMaster, mNewGame, mEnvironment); + mEnvironment.mWorld = new MWWorld::World (mOgre, mPhysicEngine, mDataDir, mMaster, mResDir, mNewGame, mEnvironment); + // Set up the GUI system - mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), - mOgre.getScene()); + mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), mOgre.getScene(), false, cfgDir); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui(), mEnvironment, - mExtensions, mNewGame); + mExtensions, mShowFPS, mNewGame); // Create sound system mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), @@ -371,12 +400,23 @@ void OMW::Engine::go() // load cell ESM::Position pos; - pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - mEnvironment.mWorld->changeCell (mCellName, pos); + pos.pos[2] = 0; + + if (const ESM::Cell *exterior = mEnvironment.mWorld->getExterior (mCellName)) + { + mEnvironment.mWorld->indexToPosition (exterior->data.gridX, exterior->data.gridY, + pos.pos[0], pos.pos[1], true); + mEnvironment.mWorld->changeToExteriorCell (pos); + } + else + { + pos.pos[0] = pos.pos[1] = 0; + mEnvironment.mWorld->changeToInteriorCell (mCellName, pos); + } // Sets up the input system - MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayerPos(), + MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayer(), *mEnvironment.mWindowManager, mDebug, *this); mEnvironment.mInputManager = &input; @@ -389,6 +429,29 @@ void OMW::Engine::go() // Play some good 'ol tunes mEnvironment.mSoundManager->startRandomTitle(); + // scripts + if (mCompileAll) + { + typedef ESMS::ScriptListT::MapType Container; + + Container scripts = mEnvironment.mWorld->getStore().scripts.list; + + int count = 0; + int success = 0; + + for (Container::const_iterator iter (scripts.begin()); iter!=scripts.end(); ++iter, ++count) + if (mScriptManager->compile (iter->first)) + ++success; + + if (count) + std::cout + << "compiled " << success << " of " << count << " scripts (" + << 100*static_cast (success)/count + << "%)" + << std::endl; + + } + // Start the main rendering loop mOgre.start(); @@ -397,35 +460,49 @@ void OMW::Engine::go() void OMW::Engine::activate() { - std::string handle = mEnvironment.mWorld->getFacedHandle(); - - if (handle.empty()) - return; - - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - - if (ptr.isEmpty()) - return; - - MWScript::InterpreterContext interpreterContext (mEnvironment, - &ptr.getRefData().getLocals(), ptr); - - boost::shared_ptr action = - MWWorld::Class::get (ptr).activate (ptr, mEnvironment.mWorld->getPlayerPos().getPlayer(), - mEnvironment); - - interpreterContext.activate (ptr, action); - - std::string script = MWWorld::Class::get (ptr).getScript (ptr); - - if (!script.empty()) + // TODO: This is only a workaround. The input dispatcher should catch any exceptions thrown inside + // the input handling functions. Looks like this will require an OpenEngine modification. + try { - mIgnoreLocalPtr = ptr; - mScriptManager->run (script, interpreterContext); + std::string handle = mEnvironment.mWorld->getFacedHandle(); + + if (handle.empty()) + return; + + MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + + if (ptr.isEmpty()) + return; + + MWScript::InterpreterContext interpreterContext (mEnvironment, + &ptr.getRefData().getLocals(), ptr); + + boost::shared_ptr action = + MWWorld::Class::get (ptr).activate (ptr, mEnvironment.mWorld->getPlayer().getPlayer(), + mEnvironment); + + interpreterContext.activate (ptr, action); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (!script.empty()) + { + mIgnoreLocalPtr = ptr; + mScriptManager->run (script, interpreterContext); + } + + if (!interpreterContext.hasActivationBeenHandled()) + { + interpreterContext.executeActivation(); + } } - - if (!interpreterContext.hasActivationBeenHandled()) + catch (const std::exception& e) { - interpreterContext.executeActivation(); + std::cerr << "Activation failed: " << e.what() << std::endl; } } + +void OMW::Engine::setCompileAll (bool all) +{ + mCompileAll = all; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 4f8f5af9c..2f8a5b1d2 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "mwworld/environment.hpp" @@ -55,11 +56,14 @@ namespace OMW class Engine : private Ogre::FrameListener { - //int nFiles; + //int nFiles; boost::filesystem::path mDataDir; + boost::filesystem::path mResDir; OEngine::Render::OgreRenderer mOgre; + OEngine::Physic::PhysicEngine* mPhysicEngine; std::string mCellName; std::string mMaster; + bool mShowFPS; bool mDebug; bool mVerboseScripts; bool mNewGame; @@ -72,8 +76,8 @@ namespace OMW Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; OEngine::GUI::MyGUIManager *mGuiManager; - ESM::Region test; - boost::timer timer; + ESM::Region test; + boost::timer timer; int focusFrameCounter; static const int focusUpdateFrame = 10; @@ -107,6 +111,9 @@ namespace OMW /// Set data dir void setDataDir (const boost::filesystem::path& dataDir); + /// Set resource dir + void setResourceDir (const boost::filesystem::path& parResDir); + /// Set start cell name (only interiors for now) void setCell (const std::string& cellName); @@ -115,6 +122,9 @@ namespace OMW /// - Currently OpenMW only supports one master at the same time. void addMaster (const std::string& master); + /// Enable fps counter + void showFPS() { mShowFPS = true; } + /// Enable debug mode: /// - non-exclusive input void enableDebugMode(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 74508d77f..4d7e6595c 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -7,9 +7,10 @@ #include #include "engine.hpp" +#include "path.hpp" #if defined(_WIN32) && !defined(_CONSOLE) -#include +#include #include # if !defined(_DEBUG) @@ -42,10 +43,13 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) ("help", "print help message") ("data", bpo::value()->default_value ("data"), "set data directory") + ("resources", bpo::value()->default_value ("resources"), + "set resources directory") ("start", bpo::value()->default_value ("Beshara"), "set initial cell") ("master", bpo::value()->default_value ("Morrowind"), "master file") + ( "showfps", "show fps counter") ( "debug", "debug mode" ) ( "nosound", "disable all sound" ) ( "script-verbose", "verbose script output" ) @@ -55,20 +59,23 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) bpo::variables_map variables; -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE - std::string configFilePath(macBundlePath() + "/Contents/MacOS/openmw.cfg"); - std::ifstream configFile (configFilePath.c_str()); -#else - std::ifstream configFile ("openmw.cfg"); -#endif + std::string cfgFile = OMW::Path::getPath(OMW::Path::GLOBAL_CFG_PATH, "openmw", "openmw.cfg"); + std::cout << "Using global config file: " << cfgFile << std::endl; + std::ifstream globalConfigFile(cfgFile.c_str()); + + cfgFile = OMW::Path::getPath(OMW::Path::USER_CFG_PATH, "openmw", "openmw.cfg"); + std::cout << "Using user config file: " << cfgFile << std::endl; + std::ifstream userConfigFile(cfgFile.c_str()); bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); bpo::store(valid_opts, variables); bpo::notify(variables); - if (configFile.is_open()) - bpo::store ( bpo::parse_config_file (configFile, desc), variables); + if (userConfigFile.is_open()) + bpo::store ( bpo::parse_config_file (userConfigFile, desc), variables); + if (globalConfigFile.is_open()) + bpo::store ( bpo::parse_config_file (globalConfigFile, desc), variables); if (variables.count ("help")) { @@ -77,9 +84,13 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) } engine.setDataDir (variables["data"].as()); + engine.setResourceDir (variables["resources"].as()); engine.setCell (variables["start"].as()); engine.addMaster (variables["master"].as()); + if (variables.count ("showfps")) + engine.showFPS(); + if (variables.count ("debug")) engine.enableDebugMode(); @@ -100,6 +111,11 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) int main(int argc, char**argv) { +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE + // set current dir to bundle path + boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()); + boost::filesystem::current_path(bundlePath); +#endif try { diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 6c96811d8..7a72ddb8c 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -23,6 +23,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 1d4afc096..2dbeae360 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 1217d56a6..d63795641 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 3679eb7ee..964ccbdfe 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 07ded0264..a264f2a1c 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index ea61508b8..1da55e6f6 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -23,6 +23,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 7a50fcb2a..8cde67671 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -35,6 +35,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertActorPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } @@ -90,7 +91,7 @@ namespace MWClass const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); - } + } MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) const @@ -106,7 +107,7 @@ namespace MWClass } return *ptr.getRefData().getContainerStore(); - } + } std::string Creature::getScript (const MWWorld::Ptr& ptr) const { diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 32b33e95a..8a34d3abe 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -5,8 +5,7 @@ #include -#include "../mwrender/playerpos.hpp" - +#include "../mwworld/player.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/nullaction.hpp" #include "../mwworld/actionteleport.hpp" @@ -31,6 +30,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } @@ -65,7 +65,7 @@ namespace MWClass if (ref->ref.teleport) { // teleport door - if (environment.mWorld->getPlayerPos().getPlayer()==actor) + if (environment.mWorld->getPlayer().getPlayer()==actor) { // the player is using the door return boost::shared_ptr ( diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index e4ea509f9..c88e1794b 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index de5c06a73..159196eb2 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -31,6 +31,7 @@ namespace MWClass MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); // Extract the color and convert to floating point const int color = ref->base->data.color; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 3b08ff199..9a4b98b43 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index d4ffdce38..f9995b77f 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index a64db189b..bb5578f6d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -16,6 +16,12 @@ #include "../mwmechanics/mechanicsmanager.hpp" #include +namespace +{ + const Ogre::Radian kOgrePi (Ogre::Math::PI); + const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0)); +} + namespace MWClass { std::string Npc::getId (const MWWorld::Ptr& ptr) const @@ -29,227 +35,236 @@ namespace MWClass void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const { - //Ogre::SceneNode *chest; + //Ogre::SceneNode *chest; ESMS::LiveCellRef *ref = ptr.get(); - - //Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1] - //Ex. Fargothchest , Fargothneck + + //Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1] + //Ex. Fargothchest , Fargothneck assert (ref->base != NULL); - std::string hairID = ref->base->hair; + std::string hairID = ref->base->hair; std::string headID = ref->base->head; - std::string npcName = ref->base->name; - //std::cout << "NPC: " << npcName << "\n"; + + // very ugly workaround to stop OGRE from chocking on non-unique scene node handles + static int uniqueId = 0; + + std::ostringstream stream; + stream << "npc$" << uniqueId++; + + std::string npcName = stream.str(); // ref->base->name; + //std::cout << "NPC: " << npcName << "\n"; //get the part of the bodypart id which describes the race and the gender std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); std::string headModel = "meshes\\" + environment.mWorld->getStore().bodyParts.find(headID)->model; - std::string hairModel = "meshes\\" + + std::string hairModel = "meshes\\" + environment.mWorld->getStore().bodyParts.find(hairID)->model; MWRender::Rendering rendering (cellRender, ref->ref); - + + + //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the + // right place const ESM::BodyPart *bodyPart = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); - //bodyPart->model-> - Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20); - Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1); - Ogre::Radian angle = Ogre::Radian(0); - - std::string addresses[6] = {"", "", "", "","", ""}; - std::string addresses2[6] = {"", "", "", "", "", ""}; - std::string upperleft[5] = {"", "", "", "", ""}; - std::string upperright[5] = {"", "", "", "", ""}; - std::string neckandup[5] = {"", "", "","",""}; - std::string empty[6] = {"", "", "", "","", ""}; - int numbers = 0; - int uppernumbers = 0; - int neckNumbers = 0; - + //bodyPart->model-> + Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20); + Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1); + Ogre::Radian angle = Ogre::Radian(0); + + std::string addresses[6] = {"", "", "", "","", ""}; + std::string addresses2[6] = {"", "", "", "", "", ""}; + std::string upperleft[5] = {"", "", "", "", ""}; + std::string upperright[5] = {"", "", "", "", ""}; + std::string neckandup[5] = {"", "", "","",""}; + int numbers = 0; + int uppernumbers = 0; + int neckNumbers = 0; + if (bodyPart){ - + cellRender.insertMesh("meshes\\" + bodyPart->model, pos, axis, angle, npcName + "chest", addresses, numbers, true); //2 0 - addresses2[numbers] = npcName + "chest"; - addresses[numbers++] = npcName + "chest"; - upperleft[uppernumbers] = npcName + "chest"; - upperright[uppernumbers++] = npcName + "chest"; - neckandup[neckNumbers++] = npcName + "chest"; - } - //std::cout << "GETTING NPC PART"; - //Orgre::SceneNode test = cellRender.getNpcPart(); + addresses2[numbers] = npcName + "chest"; + addresses[numbers++] = npcName + "chest"; + upperleft[uppernumbers] = npcName + "chest"; + upperright[uppernumbers++] = npcName + "chest"; + neckandup[neckNumbers++] = npcName + "chest"; + } + //std::cout << "GETTING NPC PART"; + //Orgre::SceneNode test = cellRender.getNpcPart(); - const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); - const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); - const ESM::BodyPart *arm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); - const ESM::BodyPart *neck = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); - const ESM::BodyPart *knee = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); - const ESM::BodyPart *ankle = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); - const ESM::BodyPart *foot = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); - const ESM::BodyPart *feet = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); - const ESM::BodyPart *tail = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); - const ESM::BodyPart *wrist = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); - const ESM::BodyPart *forearm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); - const ESM::BodyPart *hand = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand.1st"); - const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st"); + const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); + const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); + const ESM::BodyPart *arm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); + const ESM::BodyPart *neck = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); + const ESM::BodyPart *knee = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); + const ESM::BodyPart *ankle = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); + const ESM::BodyPart *foot = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); + const ESM::BodyPart *feet = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); + const ESM::BodyPart *tail = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); + const ESM::BodyPart *wrist = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); + const ESM::BodyPart *forearm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); + const ESM::BodyPart *hand = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand.1st"); + const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st"); - //std::cout << "RACE" << bodyRaceID << "\n"; + //std::cout << "RACE" << bodyRaceID << "\n"; + + Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75); - Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75); - std::string upperarmpath[2] = {npcName + "chest", npcName + "upper arm"}; - if (groin){ - cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, Ogre::Radian(3.14), npcName + "groin", addresses, numbers); - addresses2[numbers] = npcName + "groin"; - addresses[numbers++] = npcName + "groin"; - } - if (tail) { - cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, Ogre::Radian(3.14), npcName + "tail", addresses, numbers, "tail"); - //std::cout << "TAIL\n"; - } - - //addresses[1] = npcName + "groin"; - if(upperleg){ - cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, Ogre::Radian(3.14), npcName + "upper leg", addresses, numbers); //-18 - cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); - addresses2[numbers] = npcName + "upper leg2"; - addresses[numbers++] = npcName + "upper leg"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - if(knee) - { - cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee", addresses, numbers); - //cellRender.rotateMesh(Ogre::Vector3(0, 1, 0), Ogre::Radian (1), npcName + "upper arm"); - cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee2", addresses2, numbers); - - addresses2[numbers] = npcName + "knee2"; - addresses[numbers++] = npcName + "knee"; - } - if(ankle){ - - cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, 0, -20), axis, Ogre::Radian(0), npcName + "ankle", addresses, numbers); //-1 - cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0,0, -20), axis, Ogre::Radian(0), npcName + "ankle2", addresses2, numbers); //-1 - - addresses2[numbers] = npcName + "ankle2"; - addresses[numbers++] = npcName + "ankle"; - } - if(foot){ - if(bodyRaceID.compare("b_n_khajiit_m_") == 0) - { - feet = foot; - } - else - { - cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot", addresses, numbers); + cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, kOgrePi, npcName + "groin", addresses, numbers); + addresses2[numbers] = npcName + "groin"; + addresses[numbers++] = npcName + "groin"; + } + if (tail) { + cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail"); + //std::cout << "TAIL\n"; + } - cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot2", addresses2, numbers); - addresses2[numbers] = npcName + "foot2"; - addresses[numbers++] = npcName + "foot"; - } - //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - if(feet){ - - cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, Ogre::Radian(3.14), npcName + "foot", addresses, numbers); //9, 0, -14 + //addresses[1] = npcName + "groin"; + if(upperleg){ + cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18 + cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); + addresses2[numbers] = npcName + "upper leg2"; + addresses[numbers++] = npcName + "upper leg"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + if(knee) + { + cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee", addresses, numbers); + //cellRender.rotateMesh(Ogre::Vector3(0, 1, 0), Ogre::Radian (1), npcName + "upper arm"); + cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee2", addresses2, numbers); - cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, Ogre::Radian(3.14), npcName + "foot2", addresses2, numbers); - addresses2[numbers] = npcName + "foot2"; - addresses[numbers++] = npcName + "foot"; - //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - - - if (arm){ - //010 - cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(-12.5, 0, 104), Ogre::Vector3(0, 1, 0), Ogre::Radian(-3.14 / 2), npcName + "upper arm", upperleft, uppernumbers); //1, 0,.75 - //cellRender.rotateMesh(Ogre::Vector3(1, 0, 0), Ogre::Radian (.45), upperarmpath, 2); //-.5, 0, -.75 - cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(12.5, 0, 105), Ogre::Vector3(-.5, 0, -.75), Ogre::Radian(3.14), npcName + "upper arm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "upper arm"; - upperright[uppernumbers++] = npcName + "upper arm2"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); //1 -1 1 - cellRender.rotateMesh(Ogre::Vector3(0, .1, 0), Ogre::Radian(3.14/2), upperleft, uppernumbers); - } + addresses2[numbers] = npcName + "knee2"; + addresses[numbers++] = npcName + "knee"; + } + if(ankle){ - if (forearm) - { - //addresses[1] = npcName + "upper arm"; - cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "forearm"; - upperright[uppernumbers++] = npcName + "forearm2"; - } - //else - // std::cout << npcName << "has no forearm"; - if (wrist) - { - if(upperleft[uppernumbers - 1].compare(npcName + "upper arm") == 0) - { - cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "forearm"; - upperright[uppernumbers++] = npcName + "forearm2"; + cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, 0, -20), axis, Ogre::Radian(0), npcName + "ankle", addresses, numbers); //-1 + cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0,0, -20), axis, Ogre::Radian(0), npcName + "ankle2", addresses2, numbers); //-1 - } - cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "wrist", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "wrist2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "wrist"; - upperright[uppernumbers++] = npcName + "wrist2"; - } - + addresses2[numbers] = npcName + "ankle2"; + addresses[numbers++] = npcName + "ankle"; + } + if(foot){ + if(bodyRaceID.compare("b_n_khajiit_m_") == 0) + { + feet = foot; + } + else + { + cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot", addresses, numbers); - if(hand) - { - //std::cout << "WE FOUND A HAND\n"; - //-50, 0, -120 - //std::cout << "WE FOUND HANDS\n"; - std::string pass; - if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0) - pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF"; - else - pass = hand->model; - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "hand", upperleft, uppernumbers,false); //0, 100, -100 0,0,120 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), Ogre::Radian(3.14), npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 - upperleft[uppernumbers] = npcName + "hand"; - upperright[uppernumbers++] = npcName + "hand2"; - //cellRender.rotateMesh(Ogre::Vector3(0, 0,0), Ogre::Radian(3.14), upperleft, uppernumbers); - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); - } - if(hands) - { - std::string pass; - if(hands->model.compare("b\\B_N_Redguard_F_Hands.1st.nif")==0 && bodyRaceID.compare("b_n_redguard_m_") == 0) - pass = "b\\B_N_Redguard_M_Hands.1st.nif"; - else if(hands->model.compare("b\\B_N_Imperial_M_Hands.1st.nif") == 0 && bodyRaceID.compare("b_n_nord_m_") == 0) - pass = "b\\B_N_Nord_M_Hands.1st.nif"; - else - pass =hands->model; //-50, 0, -120 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 - //cellRender.insertMesh("meshes\\" + hands->model, Ogre::Vector3(42, 0,110), Ogre::Vector3(1, 0, 0), Ogre::Radian(3.14), npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 - upperleft[uppernumbers] = npcName + "hand"; - upperright[uppernumbers++] = npcName + "hand2"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); - } + cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot2", addresses2, numbers); + addresses2[numbers] = npcName + "foot2"; + addresses[numbers++] = npcName + "foot"; + } + //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + if(feet){ - if(neck) - { - cellRender.insertMesh ("meshes\\" + neck->model, Ogre::Vector3( 0, 0, 120), axis, Ogre::Radian(3.14), npcName + "neck", neckandup, neckNumbers); - neckandup[neckNumbers++] = npcName + "neck"; - } - cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers); - neckandup[neckNumbers++] = npcName + "head"; - cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers); - cellRender.insertMesh("meshes\\base_anim.nif"); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); - // - } + cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot", addresses, numbers); //9, 0, -14 + + cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot2", addresses2, numbers); + addresses2[numbers] = npcName + "foot2"; + addresses[numbers++] = npcName + "foot"; + //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + + + if (arm){ + //010 + cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(-12.5, 0, 104), Ogre::Vector3(0, 1, 0), -kOgrePiOverTwo, npcName + "upper arm", upperleft, uppernumbers); //1, 0,.75 + //cellRender.rotateMesh(Ogre::Vector3(1, 0, 0), Ogre::Radian (.45), upperarmpath, 2); //-.5, 0, -.75 + cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(12.5, 0, 105), Ogre::Vector3(-.5, 0, -.75), kOgrePi, npcName + "upper arm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "upper arm"; + upperright[uppernumbers++] = npcName + "upper arm2"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); //1 -1 1 + cellRender.rotateMesh(Ogre::Vector3(0, .1, 0), kOgrePiOverTwo, upperleft, uppernumbers); + } + + if (forearm) + { + //addresses[1] = npcName + "upper arm"; + cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "forearm"; + upperright[uppernumbers++] = npcName + "forearm2"; + } + //else + // std::cout << npcName << "has no forearm"; + if (wrist) + { + if(upperleft[uppernumbers - 1].compare(npcName + "upper arm") == 0) + { + cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "forearm"; + upperright[uppernumbers++] = npcName + "forearm2"; + + } + cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "wrist"; + upperright[uppernumbers++] = npcName + "wrist2"; + } + + + if(hand) + { + //std::cout << "WE FOUND A HAND\n"; + //-50, 0, -120 + //std::cout << "WE FOUND HANDS\n"; + std::string pass; + if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0) + pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF"; + else + pass = hand->model; + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers,false); //0, 100, -100 0,0,120 + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 + upperleft[uppernumbers] = npcName + "hand"; + upperright[uppernumbers++] = npcName + "hand2"; + //cellRender.rotateMesh(Ogre::Vector3(0, 0,0), kOgrePi, upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); + } + if(hands) + { + std::string pass; + if(hands->model.compare("b\\B_N_Redguard_F_Hands.1st.nif")==0 && bodyRaceID.compare("b_n_redguard_m_") == 0) + pass = "b\\B_N_Redguard_M_Hands.1st.nif"; + else if(hands->model.compare("b\\B_N_Imperial_M_Hands.1st.nif") == 0 && bodyRaceID.compare("b_n_nord_m_") == 0) + pass = "b\\B_N_Nord_M_Hands.1st.nif"; + else + pass =hands->model; //-50, 0, -120 + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 + //cellRender.insertMesh("meshes\\" + hands->model, Ogre::Vector3(42, 0,110), Ogre::Vector3(1, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 + upperleft[uppernumbers] = npcName + "hand"; + upperright[uppernumbers++] = npcName + "hand2"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); + } + + //neck will reset chest counter + if(neck) + { + cellRender.insertMesh ("meshes\\" + neck->model, Ogre::Vector3( 0, 0, 120), axis, kOgrePi, npcName + "neck", neckandup, neckNumbers); + neckandup[neckNumbers++] = npcName + "neck"; + } + cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers); + neckandup[neckNumbers++] = npcName + "head"; + cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers); + + cellRender.insertActorPhysics(); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + } void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const { @@ -302,7 +317,6 @@ namespace MWClass { if (!ptr.getRefData().getNpcStats().get()) { - // xxx boost::shared_ptr stats ( new MWMechanics::NpcStats); @@ -354,6 +368,113 @@ namespace MWClass return ref->base->script; } + void Npc::setForceStance (const MWWorld::Ptr& ptr, Stance stance, bool force) const + { + MWMechanics::NpcStats& stats = getNpcStats (ptr); + + switch (stance) + { + case Run: + + stats.mForceRun = force; + break; + + case Sneak: + + stats.mForceSneak = force; + break; + + case Combat: + + throw std::runtime_error ("combat stance not enforcable for NPCs"); + } + } + + void Npc::setStance (const MWWorld::Ptr& ptr, Stance stance, bool set) const + { + MWMechanics::NpcStats& stats = getNpcStats (ptr); + + switch (stance) + { + case Run: + + stats.mRun = set; + break; + + case Sneak: + + stats.mSneak = set; + break; + + case Combat: + + stats.mCombat = set; + break; + } + } + + bool Npc::getStance (const MWWorld::Ptr& ptr, Stance stance, bool ignoreForce) const + { + MWMechanics::NpcStats& stats = getNpcStats (ptr); + + switch (stance) + { + case Run: + + if (!ignoreForce && stats.mForceRun) + return true; + + return stats.mRun; + + case Sneak: + + if (!ignoreForce && stats.mForceSneak) + return true; + + return stats.mSneak; + + case Combat: + + return stats.mCombat; + } + + return false; + } + + float Npc::getSpeed (const MWWorld::Ptr& ptr) const + { + return getStance (ptr, Run) ? 600 : 300; // TODO calculate these values from stats + } + + MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const + { + if (!ptr.getRefData().getMovement().get()) + { + boost::shared_ptr movement ( + new MWMechanics::Movement); + + ptr.getRefData().getMovement() = movement; + } + + return *ptr.getRefData().getMovement(); + } + + Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const + { + Ogre::Vector3 vector (0, 0, 0); + + if (ptr.getRefData().getMovement().get()) + { + vector.x = - ptr.getRefData().getMovement()->mLeftRight * 200; + vector.y = ptr.getRefData().getMovement()->mForwardBackward * 200; + + if (getStance (ptr, Run, false)) + vector *= 2; + } + + return vector; + } + void Npc::registerSelf() { boost::shared_ptr instance (new Npc); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 946c30733..9f29878da 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -8,7 +8,7 @@ namespace MWClass class Npc : public MWWorld::Class { public: - + virtual std::string getId (const MWWorld::Ptr& ptr) const; ///< Return ID of \a ptr @@ -43,6 +43,26 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr + virtual void setForceStance (const MWWorld::Ptr& ptr, Stance stance, bool force) const; + ///< Force or unforce a stance. + + virtual void setStance (const MWWorld::Ptr& ptr, Stance stance, bool set) const; + ///< Set or unset a stance. + + virtual bool getStance (const MWWorld::Ptr& ptr, Stance stance, bool ignoreForce = false) + const; + ////< Check if a stance is active or not. + + virtual float getSpeed (const MWWorld::Ptr& ptr) const; + ///< Return movement speed. + + virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; + ///< Return desired movement. + + virtual Ogre::Vector3 getMovementVector (const MWWorld::Ptr& ptr) const; + ///< Return desired movement vector (determined based on movement settings, + /// stance and stats). + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index e163473f7..6c9889a7b 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 9188ae9ea..028d8b5e3 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 7b42bc95c..b9b5036fb 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 33e3e0ed4..851b4d7bf 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -21,6 +21,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 4c14e58ea..a985a7e42 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -26,6 +26,7 @@ namespace MWClass { MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); + cellRender.insertObjectPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 0f6e73276..f78160cd7 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -13,6 +13,7 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/refdata.hpp" +#include "../mwworld/player.hpp" #include "../mwinput/inputmanager.hpp" @@ -225,7 +226,7 @@ namespace MWDialogue // check cell if (!info.cell.empty()) - if (mEnvironment.mWorld->getPlayerPos().getPlayer().getCell()->cell->name != info.cell) + if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell) return false; // TODO check DATAstruct diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 84814d778..7db93a508 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -1,6 +1,4 @@ #include "birth.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" @@ -11,8 +9,8 @@ using namespace MWGui; using namespace Widgets; -BirthDialog::BirthDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_birth_layout.xml", environment) +BirthDialog::BirthDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_birth_layout.xml", parWindowManager) { // Centre dialog center(); @@ -94,7 +92,7 @@ void BirthDialog::setBirthId(const std::string &birthId) void BirthDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void BirthDialog::onBackClicked(MyGUI::Widget* _sender) @@ -121,7 +119,7 @@ void BirthDialog::updateBirths() { birthList->removeAllItems(); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); ESMS::RecListT::MapType::const_iterator it = store.birthSigns.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.birthSigns.list.end(); @@ -151,7 +149,7 @@ void BirthDialog::updateSpells() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, spellArea->getWidth(), 18); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::BirthSign *birth = store.birthSigns.find(currentBirthId); std::string texturePath = std::string("textures\\") + birth->texture; @@ -191,7 +189,7 @@ void BirthDialog::updateSpells() if (!categories[category].spells.empty()) { MyGUI::StaticTextPtr label = spellArea->createWidget("SandBrightText", coord, MyGUI::Align::Default, std::string("Label")); - label->setCaption(environment.mWindowManager->getGameSettingString(categories[category].label, "")); + label->setCaption(mWindowManager.getGameSettingString(categories[category].label, "")); spellItems.push_back(label); coord.top += lineHeight; @@ -200,7 +198,7 @@ void BirthDialog::updateSpells() { const std::string &spellId = *it; spellWidget = spellArea->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("Spell") + boost::lexical_cast(i)); - spellWidget->setEnvironment(&environment); + spellWidget->setWindowManager(&mWindowManager); spellWidget->setSpellId(spellId); spellItems.push_back(spellWidget); diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index 5a8d11b7e..a55a774a5 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -3,11 +3,6 @@ #include "window_base.hpp" -namespace MWWorld -{ - class Environment; -} - /* This file contains the dialog for choosing a birth sign. Layout is defined by resources/mygui/openmw_chargen_race_layout.xml. @@ -17,10 +12,12 @@ namespace MWGui { using namespace MyGUI; + class WindowManager; + class BirthDialog : public WindowBase { public: - BirthDialog(MWWorld::Environment& environment); + BirthDialog(WindowManager& parWindowManager); enum Gender { @@ -42,11 +39,6 @@ namespace MWGui */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onSelectBirth(MyGUI::List* _sender, size_t _index); diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index feabddd05..01516cfe2 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -1,6 +1,4 @@ #include "class.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "components/esm_store/store.hpp" @@ -10,18 +8,20 @@ #include #include +#undef min +#undef max + using namespace MWGui; /* GenerateClassResultDialog */ -GenerateClassResultDialog::GenerateClassResultDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_generate_class_result_layout.xml", environment) +GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_generate_class_result_layout.xml", parWindowManager) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - setText("ReflectT", wm->getGameSettingString("sMessageQuestionAnswer1", "")); + setText("ReflectT", mWindowManager.getGameSettingString("sMessageQuestionAnswer1", "")); getWidget(classImage, "ClassImage"); getWidget(className, "ClassName"); @@ -50,7 +50,7 @@ void GenerateClassResultDialog::setClassId(const std::string &classId) { currentClassId = classId; classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); className->setCaption(store.classes.find(currentClassId)->name); } @@ -58,7 +58,7 @@ void GenerateClassResultDialog::setClassId(const std::string &classId) void GenerateClassResultDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender) @@ -68,31 +68,30 @@ void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender) /* PickClassDialog */ -PickClassDialog::PickClassDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_class_layout.xml", environment) +PickClassDialog::PickClassDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_class_layout.xml", parWindowManager) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - setText("SpecializationT", wm->getGameSettingString("sChooseClassMenu1", "Specialization")); + setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - setText("FavoriteAttributesT", wm->getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); + setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(favoriteAttribute[0], "FavoriteAttribute0"); getWidget(favoriteAttribute[1], "FavoriteAttribute1"); - favoriteAttribute[0]->setWindowManager(wm); - favoriteAttribute[1]->setWindowManager(wm); + favoriteAttribute[0]->setWindowManager(&mWindowManager); + favoriteAttribute[1]->setWindowManager(&mWindowManager); - setText("MajorSkillT", wm->getGameSettingString("sChooseClassMenu3", "Major Skills:")); - setText("MinorSkillT", wm->getGameSettingString("sChooseClassMenu4", "Minor Skills:")); + setText("MajorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu3", "Major Skills:")); + setText("MinorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu4", "Minor Skills:")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; getWidget(majorSkill[i], std::string("MajorSkill").append(1, theIndex)); getWidget(minorSkill[i], std::string("MinorSkill").append(1, theIndex)); - majorSkill[i]->setWindowManager(wm); - minorSkill[i]->setWindowManager(wm); + majorSkill[i]->setWindowManager(&mWindowManager); + minorSkill[i]->setWindowManager(&mWindowManager); } getWidget(classList, "ClassList"); @@ -170,7 +169,7 @@ void PickClassDialog::setClassId(const std::string &classId) void PickClassDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void PickClassDialog::onBackClicked(MyGUI::Widget* _sender) @@ -197,7 +196,7 @@ void PickClassDialog::updateClasses() { classList->removeAllItems(); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); ESMS::RecListT::MapType::const_iterator it = store.classes.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.classes.list.end(); @@ -221,8 +220,7 @@ void PickClassDialog::updateStats() { if (currentClassId.empty()) return; - WindowManager *wm = environment.mWindowManager; - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Class *klass = store.classes.search(currentClassId); if (!klass) return; @@ -234,7 +232,7 @@ void PickClassDialog::updateStats() "sSpecializationMagic", "sSpecializationStealth" }; - specializationName->setCaption(wm->getGameSettingString(specIds[specialization], specIds[specialization])); + specializationName->setCaption(mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization])); favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]); favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]); @@ -280,8 +278,8 @@ void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin) widget->setSize(width, pos); } -InfoBoxDialog::InfoBoxDialog(MWWorld::Environment& environment) - : WindowBase("openmw_infobox_layout.xml", environment) +InfoBoxDialog::InfoBoxDialog(WindowManager& parWindowManager) + : WindowBase("openmw_infobox_layout.xml", parWindowManager) , currentButton(-1) { getWidget(textBox, "TextBox"); @@ -355,7 +353,7 @@ void InfoBoxDialog::onButtonClicked(MyGUI::WidgetPtr _sender) if (*it == _sender) { currentButton = i; - eventButtonSelected(_sender, i); + eventButtonSelected(i); return; } ++i; @@ -364,23 +362,22 @@ void InfoBoxDialog::onButtonClicked(MyGUI::WidgetPtr _sender) /* ClassChoiceDialog */ -ClassChoiceDialog::ClassChoiceDialog(MWWorld::Environment& environment) - : InfoBoxDialog(environment) +ClassChoiceDialog::ClassChoiceDialog(WindowManager& parWindowManager) + : InfoBoxDialog(parWindowManager) { - WindowManager *mw = environment.mWindowManager; setText(""); ButtonList buttons; - buttons.push_back(mw->getGameSettingString("sClassChoiceMenu1", "")); - buttons.push_back(mw->getGameSettingString("sClassChoiceMenu2", "")); - buttons.push_back(mw->getGameSettingString("sClassChoiceMenu3", "")); - buttons.push_back(mw->getGameSettingString("sBack", "")); + buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu1", "")); + buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu2", "")); + buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu3", "")); + buttons.push_back(mWindowManager.getGameSettingString("sBack", "")); setButtons(buttons); } /* CreateClassDialog */ -CreateClassDialog::CreateClassDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_create_class_layout.xml", environment) +CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_create_class_layout.xml", parWindowManager) , specDialog(nullptr) , attribDialog(nullptr) , skillDialog(nullptr) @@ -389,22 +386,21 @@ CreateClassDialog::CreateClassDialog(MWWorld::Environment& environment) // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - setText("SpecializationT", wm->getGameSettingString("sChooseClassMenu1", "Specialization")); + setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - specializationName->setCaption(wm->getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); + specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); specializationName->eventMouseButtonClick = MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); - setText("FavoriteAttributesT", wm->getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); + setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(favoriteAttribute0, "FavoriteAttribute0"); getWidget(favoriteAttribute1, "FavoriteAttribute1"); - favoriteAttribute0->setWindowManager(wm); - favoriteAttribute1->setWindowManager(wm); + favoriteAttribute0->setWindowManager(&mWindowManager); + favoriteAttribute1->setWindowManager(&mWindowManager); favoriteAttribute0->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); favoriteAttribute1->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); - setText("MajorSkillT", wm->getGameSettingString("sSkillClassMajor", "")); - setText("MinorSkillT", wm->getGameSettingString("sSkillClassMinor", "")); + setText("MajorSkillT", mWindowManager.getGameSettingString("sSkillClassMajor", "")); + setText("MinorSkillT", mWindowManager.getGameSettingString("sSkillClassMinor", "")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -417,11 +413,11 @@ CreateClassDialog::CreateClassDialog(MWWorld::Environment& environment) std::vector::const_iterator end = skills.end(); for (std::vector::const_iterator it = skills.begin(); it != end; ++it) { - (*it)->setWindowManager(wm); + (*it)->setWindowManager(&mWindowManager); (*it)->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onSkillClicked); } - setText("LabelT", wm->getGameSettingString("sName", "")); + setText("LabelT", mWindowManager.getGameSettingString("sName", "")); getWidget(editName, "EditName"); // Make sure the edit box has focus @@ -563,7 +559,7 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) { if (specDialog) delete specDialog; - specDialog = new SelectSpecializationDialog(environment, environment.mWindowManager->getGui()->getViewSize()); + specDialog = new SelectSpecializationDialog(mWindowManager); specDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); specDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected); specDialog->setVisible(true); @@ -572,7 +568,7 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) void CreateClassDialog::onSpecializationSelected() { specializationId = specDialog->getSpecializationId(); - specializationName->setCaption(environment.mWindowManager->getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); + specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); specDialog->setVisible(false); } @@ -580,7 +576,7 @@ void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) { if (attribDialog) delete attribDialog; - attribDialog = new SelectAttributeDialog(environment, environment.mWindowManager->getGui()->getViewSize()); + attribDialog = new SelectAttributeDialog(mWindowManager); attribDialog->setAffectedWidget(_sender); attribDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); attribDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected); @@ -609,7 +605,7 @@ void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) { if (skillDialog) delete skillDialog; - skillDialog = new SelectSkillDialog(environment, environment.mWindowManager->getGui()->getViewSize()); + skillDialog = new SelectSkillDialog(mWindowManager); skillDialog->setAffectedWidget(_sender); skillDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); skillDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected); @@ -640,21 +636,21 @@ void CreateClassDialog::onSkillSelected() void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) { - descDialog = new DescriptionDialog(environment, environment.mWindowManager->getGui()->getViewSize()); + descDialog = new DescriptionDialog(mWindowManager); descDialog->setTextInput(description); descDialog->eventDone = MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered); descDialog->setVisible(true); } -void CreateClassDialog::onDescriptionEntered() +void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) { description = descDialog->getTextInput(); - environment.mWindowManager->removeDialog(descDialog); + mWindowManager.removeDialog(descDialog); } void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender) @@ -664,31 +660,29 @@ void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender) /* SelectSpecializationDialog */ -SelectSpecializationDialog::SelectSpecializationDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize) - : WindowBase("openmw_chargen_select_specialization_layout.xml", environment) +SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_select_specialization_layout.xml", parWindowManager) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - - setText("LabelT", wm->getGameSettingString("sSpecializationMenu1", "")); + setText("LabelT", mWindowManager.getGameSettingString("sSpecializationMenu1", "")); getWidget(specialization0, "Specialization0"); getWidget(specialization1, "Specialization1"); getWidget(specialization2, "Specialization2"); - specialization0->setCaption(wm->getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); + specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); specialization0->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization1->setCaption(wm->getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); + specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); specialization1->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization2->setCaption(wm->getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); + specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); specialization2->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specializationId = ESM::Class::Combat; // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(wm->getGameSettingString("sCancel", "")); + cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); } @@ -715,15 +709,13 @@ void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectAttributeDialog */ -SelectAttributeDialog::SelectAttributeDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize) - : WindowBase("openmw_chargen_select_attribute_layout.xml", environment) +SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_select_attribute_layout.xml", parWindowManager) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - - setText("LabelT", wm->getGameSettingString("sAttributesMenu1", "")); + setText("LabelT", mWindowManager.getGameSettingString("sAttributesMenu1", "")); for (int i = 0; i < 8; ++i) { @@ -731,7 +723,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWWorld::Environment& environment, char theIndex = '0'+i; getWidget(attribute, std::string("Attribute").append(1, theIndex)); - attribute->setWindowManager(wm); + attribute->setWindowManager(&parWindowManager); attribute->setAttributeId(ESM::Attribute::attributeIds[i]); attribute->eventClicked = MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); } @@ -739,7 +731,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWWorld::Environment& environment, // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(wm->getGameSettingString("sCancel", "")); + cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); } @@ -760,18 +752,16 @@ void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectSkillDialog */ -SelectSkillDialog::SelectSkillDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize) - : WindowBase("openmw_chargen_select_skill_layout.xml", environment) +SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_select_skill_layout.xml", parWindowManager) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - - setText("LabelT", wm->getGameSettingString("sSkillsMenu1", "")); - setText("CombatLabelT", wm->getGameSettingString("sSpecializationCombat", "")); - setText("MagicLabelT", wm->getGameSettingString("sSpecializationMagic", "")); - setText("StealthLabelT", wm->getGameSettingString("sSpecializationStealth", "")); + setText("LabelT", mWindowManager.getGameSettingString("sSkillsMenu1", "")); + setText("CombatLabelT", mWindowManager.getGameSettingString("sSpecializationCombat", "")); + setText("MagicLabelT", mWindowManager.getGameSettingString("sSpecializationMagic", "")); + setText("StealthLabelT", mWindowManager.getGameSettingString("sSpecializationStealth", "")); for(int i = 0; i < 9; i++) { @@ -821,7 +811,7 @@ SelectSkillDialog::SelectSkillDialog(MWWorld::Environment& environment, MyGUI::I { for (int i = 0; i < 9; ++i) { - skills[spec][i].widget->setWindowManager(wm); + skills[spec][i].widget->setWindowManager(&mWindowManager); skills[spec][i].widget->setSkillId(skills[spec][i].skillId); skills[spec][i].widget->eventClicked = MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); } @@ -830,7 +820,7 @@ SelectSkillDialog::SelectSkillDialog(MWWorld::Environment& environment, MyGUI::I // TODO: These buttons should be managed by a Dialog class MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(wm->getGameSettingString("sCancel", "")); + cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); } @@ -849,8 +839,8 @@ void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender) /* DescriptionDialog */ -DescriptionDialog::DescriptionDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize) - : WindowBase("openmw_chargen_class_description_layout.xml", environment) +DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_class_description_layout.xml", parWindowManager) { // Centre dialog center(); @@ -861,7 +851,7 @@ DescriptionDialog::DescriptionDialog(MWWorld::Environment& environment, MyGUI::I MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked); - okButton->setCaption(environment.mWindowManager->getGameSettingString("sInputMenu1", "")); + okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", "")); // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); @@ -871,5 +861,5 @@ DescriptionDialog::DescriptionDialog(MWWorld::Environment& environment, MyGUI::I void DescriptionDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index d2a198737..5f1734b19 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -5,11 +5,6 @@ #include "widgets.hpp" #include "window_base.hpp" -namespace MWWorld -{ - class Environment; -} - /* This file contains the dialogs for choosing a class. Layout is defined by resources/mygui/openmw_chargen_class_layout.xml. @@ -19,10 +14,12 @@ namespace MWGui { using namespace MyGUI; + class WindowManager; + class InfoBoxDialog : public WindowBase { public: - InfoBoxDialog(MWWorld::Environment& environment); + InfoBoxDialog(WindowManager& parWindowManager); typedef std::vector ButtonList; @@ -34,12 +31,12 @@ namespace MWGui int getChosenButton() const; // Events - typedef delegates::CDelegate2 EventHandle_WidgetInt; + typedef delegates::CDelegate1 EventHandle_Int; /** Event : Button was clicked.\n signature : void method(MyGUI::WidgetPtr widget, int index)\n */ - EventHandle_WidgetInt eventButtonSelected; + EventHandle_Int eventButtonSelected; protected: void onButtonClicked(MyGUI::WidgetPtr _sender); @@ -67,13 +64,13 @@ namespace MWGui Class_Create = 2, Class_Back = 3 }; - ClassChoiceDialog(MWWorld::Environment& environment); + ClassChoiceDialog(WindowManager& parWindowManager); }; class GenerateClassResultDialog : public WindowBase { public: - GenerateClassResultDialog(MWWorld::Environment& environment); + GenerateClassResultDialog(WindowManager& parWindowManager); std::string getClassId() const; void setClassId(const std::string &classId); @@ -88,11 +85,6 @@ namespace MWGui */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onOkClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender); @@ -107,7 +99,7 @@ namespace MWGui class PickClassDialog : public WindowBase { public: - PickClassDialog(MWWorld::Environment& environment); + PickClassDialog(WindowManager& parWindowManager); const std::string &getClassId() const { return currentClassId; } void setClassId(const std::string &classId); @@ -123,11 +115,6 @@ namespace MWGui */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onSelectClass(MyGUI::List* _sender, size_t _index); @@ -151,7 +138,7 @@ namespace MWGui class SelectSpecializationDialog : public WindowBase { public: - SelectSpecializationDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize); + SelectSpecializationDialog(WindowManager& parWindowManager); ESM::Class::Specialization getSpecializationId() const { return specializationId; } @@ -181,7 +168,7 @@ namespace MWGui class SelectAttributeDialog : public WindowBase { public: - SelectAttributeDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize); + SelectAttributeDialog(WindowManager& parWindowManager); ESM::Attribute::AttributeID getAttributeId() const { return attributeId; } Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; } @@ -213,7 +200,7 @@ namespace MWGui class SelectSkillDialog : public WindowBase { public: - SelectSkillDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize); + SelectSkillDialog(WindowManager& parWindowManager); ESM::Skill::SkillEnum getSkillId() const { return skillId; } Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; } @@ -248,19 +235,11 @@ namespace MWGui class DescriptionDialog : public WindowBase { public: - DescriptionDialog(MWWorld::Environment& environment, MyGUI::IntSize gameWindowSize); + DescriptionDialog(WindowManager& parWindowManager); std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } - // Events - typedef delegates::CDelegate0 EventHandle_Void; - - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onOkClicked(MyGUI::Widget* _sender); @@ -271,7 +250,7 @@ namespace MWGui class CreateClassDialog : public WindowBase { public: - CreateClassDialog(MWWorld::Environment& environment); + CreateClassDialog(WindowManager& parWindowManager); virtual ~CreateClassDialog(); std::string getName() const; @@ -292,11 +271,6 @@ namespace MWGui */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onOkClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender); @@ -308,7 +282,7 @@ namespace MWGui void onSkillClicked(Widgets::MWSkillPtr _sender); void onSkillSelected(); void onDescriptionClicked(MyGUI::Widget* _sender); - void onDescriptionEntered(); + void onDescriptionEntered(WindowBase* parWindow); void onDialogCancel(); private: diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 471b2810b..836a0f0db 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -1,6 +1,8 @@ #include "console.hpp" +#include + #include #include "../mwscript/extensions.hpp" @@ -67,6 +69,31 @@ namespace MWGui printError ((type==ErrorMessage ? "error: " : "warning: ") + message); } + void Console::listNames() + { + if (mNames.empty()) + { + // keywords + std::istringstream input (""); + + Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions()); + + scanner.listKeywords (mNames); + + // identifier + const ESMS::ESMStore& store = mEnvironment.mWorld->getStore(); + + for (ESMS::RecListList::const_iterator iter (store.recLists.begin()); + iter!=store.recLists.end(); ++iter) + { + iter->second->listIdentifier (mNames); + } + + // sort + std::sort (mNames.begin(), mNames.end()); + } + } + Console::Console(int w, int h, MWWorld::Environment& environment, const Compiler::Extensions& extensions) : Layout("openmw_console_layout.xml"), diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 25212d627..d08ac5887 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -21,10 +21,11 @@ namespace MWGui class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler { private: - + MWScript::CompilerContext mCompilerContext; MWWorld::Environment& mEnvironment; - + std::vector mNames; + bool compile (const std::string& cmd, Compiler::Output& output); /// Report error to the user. @@ -32,7 +33,13 @@ namespace MWGui /// Report a file related error virtual void report (const std::string& message, Type type); - + + void listNames(); + ///< Write all valid identifiers and keywords into mNames and sort them. + /// \note If mNames is not empty, this function is a no-op. + /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same + /// time). + public: MyGUI::EditPtr command; MyGUI::EditPtr history; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index fe43cabc9..e48c142aa 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -1,7 +1,5 @@ #include "dialogue.hpp" #include "dialogue_history.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" @@ -16,8 +14,8 @@ using namespace MWGui; using namespace Widgets; -DialogueWindow::DialogueWindow(MWWorld::Environment& environment) - : WindowBase("openmw_dialogue_window_layout.xml", environment) +DialogueWindow::DialogueWindow(WindowManager& parWindowManager) + : WindowBase("openmw_dialogue_window_layout.xml", parWindowManager) { // Centre dialog center(); diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 3e4852203..ddb6f8a4c 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -4,9 +4,9 @@ #include "window_base.hpp" #include -namespace MWWorld +namespace MWGui { - class Environment; + class WindowManager; } /* @@ -23,7 +23,7 @@ namespace MWGui class DialogueWindow: public WindowBase { public: - DialogueWindow(MWWorld::Environment& environment); + DialogueWindow(WindowManager& parWindowManager); void open(); diff --git a/apps/openmw/mwgui/dialogue_history.cpp b/apps/openmw/mwgui/dialogue_history.cpp index d7a274f7a..aaa559d24 100644 --- a/apps/openmw/mwgui/dialogue_history.cpp +++ b/apps/openmw/mwgui/dialogue_history.cpp @@ -1,6 +1,4 @@ #include "dialogue_history.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" diff --git a/apps/openmw/mwgui/layouts.cpp b/apps/openmw/mwgui/layouts.cpp index e03805e65..10740e224 100644 --- a/apps/openmw/mwgui/layouts.cpp +++ b/apps/openmw/mwgui/layouts.cpp @@ -1,412 +1,126 @@ #include "layouts.hpp" -#include "../mwworld/class.hpp" #include "../mwmechanics/mechanicsmanager.hpp" -#include "../mwgui/window_manager.hpp" +#include "window_manager.hpp" +#include #include #include -#include + +#undef min +#undef max using namespace MWGui; -const int StatsWindow::lineHeight = 18; -StatsWindow::StatsWindow (MWWorld::Environment& environment) - : WindowBase("openmw_stats_window_layout.xml", environment) - , lastPos(0) - , reputation(0) - , bounty(0) +HUD::HUD(int width, int height, bool fpsSwitch) + : Layout("openmw_hud_layout.xml") { - setCoord(0,0,498, 342); + setCoord(0,0, width, height); - const char *names[][2] = - { - { "Attrib1", "sAttributeStrength" }, - { "Attrib2", "sAttributeIntelligence" }, - { "Attrib3", "sAttributeWillpower" }, - { "Attrib4", "sAttributeAgility" }, - { "Attrib5", "sAttributeSpeed" }, - { "Attrib6", "sAttributeEndurance" }, - { "Attrib7", "sAttributePersonality" }, - { "Attrib8", "sAttributeLuck" }, - { "Health_str", "sHealth" }, - { "Magicka_str", "sMagic" }, - { "Fatigue_str", "sFatigue" }, - { "Level_str", "sLevel" }, - { "Race_str", "sRace" }, - { "Class_str", "sClass" }, - { 0, 0 } - }; + // Energy bars + getWidget(health, "Health"); + getWidget(magicka, "Magicka"); + getWidget(stamina, "Stamina"); - const ESMS::ESMStore &store = environment.mWorld->getStore(); - for (int i=0; names[i][0]; ++i) - { - setText (names[i][0], store.gameSettings.find (names[i][1])->str); - } + // Item and spell images and status bars + getWidget(weapImage, "WeapImage"); + getWidget(weapStatus, "WeapStatus"); + getWidget(spellImage, "SpellImage"); + getWidget(spellStatus, "SpellStatus"); - getWidget(skillAreaWidget, "Skills"); - getWidget(skillClientWidget, "SkillClient"); - getWidget(skillScrollerWidget, "SkillScroller"); + getWidget(effectBox, "EffectBox"); + getWidget(effect1, "Effect1"); - skillScrollerWidget->eventScrollChangePosition = MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition); - updateScroller(); + getWidget(minimap, "MiniMap"); + getWidget(compass, "Compass"); - for (int i = 0; i < ESM::Skill::Length; ++i) - { - skillValues.insert(std::pair >(i, MWMechanics::Stat())); - skillWidgetMap.insert(std::pair(i, (MyGUI::StaticTextPtr) nullptr)); - } + getWidget(crosshair, "Crosshair"); - MyGUI::WindowPtr t = static_cast(mMainWidget); - t->eventWindowChangeCoord = MyGUI::newDelegate(this, &StatsWindow::onWindowResize); + getWidget(fpsbox, "FPSBox"); + getWidget(fpscounter, "FPSCounter"); + + fpsbox->setVisible(fpsSwitch); + + compass->setImageTexture("textures\\compass.dds"); + crosshair->setImageTexture("textures\\target.dds"); + + // These are just demo values, you should replace these with + // real calls from outside the class later. + setWeapIcon("icons\\w\\tx_knife_iron.dds"); + setWeapStatus(90, 100); + setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); + setSpellStatus(65, 100); + setEffect("icons\\s\\tx_s_chameleon.dds"); } -void StatsWindow::onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos) +void HUD::setFPS(float fps) { - int diff = lastPos - pos; - // Adjust position of all widget according to difference - if (diff == 0) - return; - lastPos = pos; - - std::vector::const_iterator end = skillWidgets.end(); - for (std::vector::const_iterator it = skillWidgets.begin(); it != end; ++it) - { - (*it)->setCoord((*it)->getCoord() + MyGUI::IntPoint(0, diff)); - } + fpscounter->setCaption(boost::lexical_cast((int)fps)); } -void StatsWindow::onWindowResize(MyGUI::WidgetPtr window) + +void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax) { - updateScroller(); + health->setProgressRange(hmax); + health->setProgressPosition(h); + magicka->setProgressRange(mmax); + magicka->setProgressPosition(m); + stamina->setProgressRange(smax); + stamina->setProgressPosition(s); } -void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max) +void HUD::setWeapIcon(const char *str) { - MyGUI::ProgressPtr pt; - getWidget(pt, name); - pt->setProgressRange(max); - pt->setProgressPosition(val); - - std::stringstream out; - out << val << "/" << max; - setText(tname, out.str().c_str()); + weapImage->setImageTexture(str); } -void StatsWindow::setPlayerName(const std::string& playerName) +void HUD::setSpellIcon(const char *str) { - mMainWidget->setCaption(playerName); + spellImage->setImageTexture(str); } -void StatsWindow::setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value) +void HUD::setWeapStatus(int s, int smax) { - widget->setCaption(value); - if (style == CS_Super) - widget->setTextColour(MyGUI::Colour(0, 1, 0)); - else if (style == CS_Sub) - widget->setTextColour(MyGUI::Colour(1, 0, 0)); - else - widget->setTextColour(MyGUI::Colour(1, 1, 1)); + weapStatus->setProgressRange(smax); + weapStatus->setProgressPosition(s); } -void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) +void HUD::setSpellStatus(int s, int smax) +{ + spellStatus->setProgressRange(smax); + spellStatus->setProgressPosition(s); +} + +void HUD::setEffect(const char *img) +{ + effect1->setImageTexture(img); +} + +void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& value) { static const char *ids[] = { - "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", - "AttribVal6", "AttribVal7", "AttribVal8", - 0 + "HBar", "MBar", "FBar", 0 }; for (int i=0; ids[i]; ++i) if (ids[i]==id) { - std::ostringstream valueString; - valueString << value.getModified(); - setText (id, valueString.str()); - - if (value.getModified()>value.getBase()) - setTextColor (id, 0, 1, 0); - else if (value.getModified()& value) -{ - static const char *ids[] = - { - "HBar", "MBar", "FBar", - 0 - }; - - for (int i=0; ids[i]; ++i) - if (ids[i]==id) - { - std::string id (ids[i]); - setBar (id, id + "T", value.getCurrent(), value.getModified()); - } -} - -void StatsWindow::setValue (const std::string& id, const std::string& value) -{ - if (id=="name") - setPlayerName (value); - else if (id=="race") - setText ("RaceText", value); - else if (id=="class") - setText ("ClassText", value); -} - -void StatsWindow::setValue (const std::string& id, int value) -{ - if (id=="level") - { - std::ostringstream text; - text << value; - setText("LevelText", text.str()); - } -} - -void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) -{ - static struct {const char *id; ESM::Skill::SkillEnum skillId; } skillMap[] = - { - {"SkillBlock", ESM::Skill::Block}, - {"SkillArmorer", ESM::Skill::Armorer}, - {"SkillMediumArmor", ESM::Skill::MediumArmor}, - {"SkillHeavyArmor", ESM::Skill::HeavyArmor}, - {"SkillBluntWeapon", ESM::Skill::BluntWeapon}, - {"SkillLongBlade", ESM::Skill::LongBlade}, - {"SkillAxe", ESM::Skill::Axe}, - {"SkillSpear", ESM::Skill::Spear}, - {"SkillAthletics", ESM::Skill::Athletics}, - {"SkillEnchant", ESM::Skill::Armorer}, - {"SkillDestruction", ESM::Skill::Destruction}, - {"SkillAlteration", ESM::Skill::Alteration}, - {"SkillIllusion", ESM::Skill::Illusion}, - {"SkillConjuration", ESM::Skill::Conjuration}, - {"SkillMysticism", ESM::Skill::Mysticism}, - {"SkillRestoration", ESM::Skill::Restoration}, - {"SkillAlchemy", ESM::Skill::Alchemy}, - {"SkillUnarmored", ESM::Skill::Unarmored}, - {"SkillSecurity", ESM::Skill::Security}, - {"SkillSneak", ESM::Skill::Sneak}, - {"SkillAcrobatics", ESM::Skill::Acrobatics}, - {"SkillLightArmor", ESM::Skill::LightArmor}, - {"SkillShortBlade", ESM::Skill::ShortBlade}, - {"SkillMarksman", ESM::Skill::Marksman}, - {"SkillMercantile", ESM::Skill::Mercantile}, - {"SkillSpeechcraft", ESM::Skill::Speechcraft}, - {"SkillHandToHand", ESM::Skill::HandToHand}, - }; - for (size_t i = 0; i < sizeof(skillMap)/sizeof(skillMap[0]); ++i) - { - if (skillMap[i].id == id) - { - int skillId = skillMap[i].skillId; - skillValues[skillId] = value; - MyGUI::StaticTextPtr widget = skillWidgetMap[skillId]; - if (widget) + switch (i) { - float modified = value.getModified(), base = value.getBase(); - std::string text = boost::lexical_cast(std::floor(modified)); - ColorStyle style = CS_Normal; - if (modified > base) - style = CS_Super; - else if (modified < base) - style = CS_Sub; - - setStyledText(widget, style, text); + case 0: + health->setProgressRange (value.getModified()); + health->setProgressPosition (value.getCurrent()); + break; + case 1: + magicka->setProgressRange (value.getModified()); + magicka->setProgressPosition (value.getCurrent()); + break; + case 2: + stamina->setProgressRange (value.getModified()); + stamina->setProgressPosition (value.getCurrent()); + break; } - break; } - } -} - -void StatsWindow::configureSkills (const std::vector& major, const std::vector& minor) -{ - majorSkills = major; - minorSkills = minor; - - // Update misc skills with the remaining skills not in major or minor - std::set skillSet; - std::copy(major.begin(), major.end(), std::inserter(skillSet, skillSet.begin())); - std::copy(minor.begin(), minor.end(), std::inserter(skillSet, skillSet.begin())); - boost::array::const_iterator end = ESM::Skill::skillIds.end(); - miscSkills.clear(); - for (boost::array::const_iterator it = ESM::Skill::skillIds.begin(); it != end; ++it) - { - int skill = *it; - if (skillSet.find(skill) == skillSet.end()) - miscSkills.push_back(skill); - } -} - -void StatsWindow::setFactions (const std::vector& factions) -{ - this->factions = factions; -} - -void StatsWindow::setBirthSign (const std::string& signId) -{ - birthSignId = signId; -} - -void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::StaticImagePtr separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); - skillWidgets.push_back(separator); - - coord1.top += separator->getHeight(); - coord2.top += separator->getHeight(); -} - -void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::StaticTextPtr groupWidget = skillClientWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); - groupWidget->setCaption(label); - skillWidgets.push_back(groupWidget); - - coord1.top += lineHeight; - coord2.top += lineHeight; -} - -MyGUI::StaticTextPtr StatsWindow::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::StaticTextPtr skillNameWidget, skillValueWidget; - - skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); - skillNameWidget->setCaption(text); - - skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Default); - setStyledText(skillValueWidget, style, value); - - skillWidgets.push_back(skillNameWidget); - skillWidgets.push_back(skillValueWidget); - - coord1.top += lineHeight; - coord2.top += lineHeight; - - return skillValueWidget; -} - -void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::StaticTextPtr skillNameWidget; - - skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); - skillNameWidget->setCaption(text); - - skillWidgets.push_back(skillNameWidget); - - coord1.top += lineHeight; - coord2.top += lineHeight; -} - -void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - WindowManager *wm = environment.mWindowManager; - - // Add a line separator if there are items above - if (!skillWidgets.empty()) - { - addSeparator(coord1, coord2); - } - - addGroup(wm->getGameSettingString(titleId, titleDefault), coord1, coord2); - - SkillList::const_iterator end = skills.end(); - for (SkillList::const_iterator it = skills.begin(); it != end; ++it) - { - int skillId = *it; - if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes - continue; - assert(skillId >= 0 && skillId < ESM::Skill::Length); - const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; - const MWMechanics::Stat &stat = skillValues.find(skillId)->second; - float base = stat.getBase(); - float modified = stat.getModified(); - - ColorStyle style = CS_Normal; - if (modified > base) - style = CS_Super; - else if (modified < base) - style = CS_Sub; - MyGUI::StaticTextPtr widget = addValueItem(wm->getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); - skillWidgetMap[skillId] = widget; - } -} - -void StatsWindow::updateSkillArea() -{ - for (std::vector::iterator it = skillWidgets.begin(); it != skillWidgets.end(); ++it) - { - MyGUI::Gui::getInstance().destroyWidget(*it); - } - skillWidgets.clear(); - - const int valueSize = 40; - MyGUI::IntCoord coord1(10, 0, skillClientWidget->getWidth() - (10 + valueSize), 18); - MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); - - if (!majorSkills.empty()) - addSkills(majorSkills, "sSkillClassMajor", "Major Skills", coord1, coord2); - - if (!minorSkills.empty()) - addSkills(minorSkills, "sSkillClassMinor", "Minor Skills", coord1, coord2); - - if (!miscSkills.empty()) - addSkills(miscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); - - WindowManager *wm = environment.mWindowManager; - ESMS::ESMStore &store = environment.mWorld->getStore(); - - if (!factions.empty()) - { - // Add a line separator if there are items above - if (!skillWidgets.empty()) - addSeparator(coord1, coord2); - - addGroup(wm->getGameSettingString("sFaction", "Faction"), coord1, coord2); - FactionList::const_iterator end = factions.end(); - for (FactionList::const_iterator it = factions.begin(); it != end; ++it) - { - const ESM::Faction *faction = store.factions.find(it->first); - addItem(faction->name, coord1, coord2); - // TODO: Faction rank should be placed in tooltip - } - } - - if (!birthSignId.empty()) - { - // Add a line separator if there are items above - if (!skillWidgets.empty()) - addSeparator(coord1, coord2); - - addGroup(wm->getGameSettingString("sSign", "Sign"), coord1, coord2); - const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); - addItem(sign->name, coord1, coord2); - } - - // Add a line separator if there are items above - if (!skillWidgets.empty()) - addSeparator(coord1, coord2); - - addValueItem(wm->getGameSettingString("sReputation", "Reputation"), boost::lexical_cast(static_cast(reputation)), CS_Normal, coord1, coord2); - addValueItem(wm->getGameSettingString("sBounty", "Bounty"), boost::lexical_cast(static_cast(bounty)), CS_Normal, coord1, coord2); - - clientHeight = coord1.top; - updateScroller(); -} - -void StatsWindow::updateScroller() -{ - skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); - skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); } diff --git a/apps/openmw/mwgui/layouts.hpp b/apps/openmw/mwgui/layouts.hpp index 097790163..ab91f4217 100644 --- a/apps/openmw/mwgui/layouts.hpp +++ b/apps/openmw/mwgui/layouts.hpp @@ -3,9 +3,8 @@ #include -#include - #include +#include #include #include @@ -13,12 +12,10 @@ #include #include "../mwmechanics/stat.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_base.hpp" /* - This file contains classes corresponding to all the window layouts + This file contains classes corresponding to window layouts defined in resources/mygui/ *.xml. Each class inherites GUI::Layout and loads the XML file, and @@ -35,117 +32,27 @@ namespace MWGui class HUD : public OEngine::GUI::Layout { public: - HUD(int width, int height) - : Layout("openmw_hud_layout.xml") - { - setCoord(0,0, width, height); - - // Energy bars - getWidget(health, "Health"); - getWidget(magicka, "Magicka"); - getWidget(stamina, "Stamina"); - - // Item and spell images and status bars - getWidget(weapImage, "WeapImage"); - getWidget(weapStatus, "WeapStatus"); - getWidget(spellImage, "SpellImage"); - getWidget(spellStatus, "SpellStatus"); - - getWidget(effectBox, "EffectBox"); - getWidget(effect1, "Effect1"); - - getWidget(minimap, "MiniMap"); - getWidget(compass, "Compass"); - - getWidget(crosshair, "Crosshair"); - - compass->setImageTexture("textures\\compass.dds"); - crosshair->setImageTexture("textures\\target.dds"); - - // These are just demo values, you should replace these with - // real calls from outside the class later. - setWeapIcon("icons\\w\\tx_knife_iron.dds"); - setWeapStatus(90, 100); - setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); - setSpellStatus(65, 100); - setEffect("icons\\s\\tx_s_chameleon.dds"); - } - - void setStats(int h, int hmax, int m, int mmax, int s, int smax) - { - health->setProgressRange(hmax); - health->setProgressPosition(h); - magicka->setProgressRange(mmax); - magicka->setProgressPosition(m); - stamina->setProgressRange(smax); - stamina->setProgressPosition(s); - } - - void setWeapIcon(const char *str) - { weapImage->setImageTexture(str); } - void setSpellIcon(const char *str) - { spellImage->setImageTexture(str); } - - void setWeapStatus(int s, int smax) - { - weapStatus->setProgressRange(smax); - weapStatus->setProgressPosition(s); - } - void setSpellStatus(int s, int smax) - { - spellStatus->setProgressRange(smax); - spellStatus->setProgressPosition(s); - } - - void setEffect(const char *img) - { effect1->setImageTexture(img); } - - void setValue (const std::string& id, const MWMechanics::DynamicStat& value) - { - static const char *ids[] = - { - "HBar", "MBar", "FBar", - 0 - }; - - for (int i=0; ids[i]; ++i) - if (ids[i]==id) - { - switch (i) - { - case 0: - - health->setProgressRange (value.getModified()); - health->setProgressPosition (value.getCurrent()); - break; - - case 1: - - magicka->setProgressRange (value.getModified()); - magicka->setProgressPosition (value.getCurrent()); - break; - - case 2: - - stamina->setProgressRange (value.getModified()); - stamina->setProgressPosition (value.getCurrent()); - break; - } - } - } + HUD(int width, int height, bool fpsSwitch); + void setStats(int h, int hmax, int m, int mmax, int s, int smax); + void setWeapIcon(const char *str); + void setSpellIcon(const char *str); + void setWeapStatus(int s, int smax); + void setSpellStatus(int s, int smax); + void setEffect(const char *img); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setFPS(float fps); MyGUI::ProgressPtr health, magicka, stamina; - MyGUI::StaticImagePtr weapImage, spellImage; MyGUI::ProgressPtr weapStatus, spellStatus; - MyGUI::WidgetPtr effectBox; MyGUI::StaticImagePtr effect1; - MyGUI::StaticImagePtr minimap; MyGUI::StaticImagePtr compass; - MyGUI::StaticImagePtr crosshair; + + MyGUI::WidgetPtr fpsbox; + MyGUI::StaticTextPtr fpscounter; }; class MapWindow : public OEngine::GUI::Layout @@ -178,68 +85,6 @@ namespace MWGui } }; - class StatsWindow : public WindowBase - { - public: - typedef std::pair Faction; - typedef std::vector FactionList; - - typedef std::vector SkillList; - - StatsWindow (MWWorld::Environment& environment); - - void setBar(const std::string& name, const std::string& tname, int val, int max); - void setPlayerName(const std::string& playerName); - - /// Set value for the given ID. - void setValue (const std::string& id, const MWMechanics::Stat& value); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setValue (const std::string& id, const std::string& value); - void setValue (const std::string& id, int value); - - void setValue (const std::string& id, const MWMechanics::Stat& value); - - void configureSkills (const SkillList& major, const SkillList& minor); - void setFactions (const std::vector& factions); - void setBirthSign (const std::string &signId); - void setReputation (int reputation) { this->reputation = reputation; } - void setBounty (int bounty) { this->bounty = bounty; } - void updateSkillArea(); - - private: - enum ColorStyle - { - CS_Sub, - CS_Normal, - CS_Super - }; - void setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value); - void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::StaticTextPtr addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void updateScroller(); - - void onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos); - void onWindowResize(MyGUI::WidgetPtr window); - - static const int lineHeight; - - MyGUI::WidgetPtr skillAreaWidget, skillClientWidget; - MyGUI::VScrollPtr skillScrollerWidget; - int lastPos, clientHeight; - - SkillList majorSkills, minorSkills, miscSkills; - std::map > skillValues; - std::map skillWidgetMap; - std::map factionWidgetMap; - FactionList factions; ///< Stores a list of factions and the current rank - std::string birthSignId; - int reputation, bounty; - std::vector skillWidgets; //< Skills and other information - }; - #if 0 class InventoryWindow : public OEngine::GUI::Layout { diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 8ba9d8fe2..65e6afd2e 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -1,6 +1,4 @@ #include "race.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" @@ -15,8 +13,8 @@ using namespace MWGui; using namespace Widgets; -RaceDialog::RaceDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_race_layout.xml", environment) +RaceDialog::RaceDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_race_layout.xml", parWindowManager) , genderIndex(0) , faceIndex(0) , hairIndex(0) @@ -29,8 +27,7 @@ RaceDialog::RaceDialog(MWWorld::Environment& environment) // These are just demo values, you should replace these with // real calls from outside the class later. - WindowManager *wm = environment.mWindowManager; - setText("AppearanceT", wm->getGameSettingString("sRaceMenu1", "Appearance")); + setText("AppearanceT", mWindowManager.getGameSettingString("sRaceMenu1", "Appearance")); getWidget(appearanceBox, "AppearanceBox"); getWidget(headRotate, "HeadRotate"); @@ -42,34 +39,34 @@ RaceDialog::RaceDialog(MWWorld::Environment& environment) // Set up next/previous buttons MyGUI::ButtonPtr prevButton, nextButton; - setText("GenderChoiceT", wm->getGameSettingString("sRaceMenu2", "Change Sex")); + setText("GenderChoiceT", mWindowManager.getGameSettingString("sRaceMenu2", "Change Sex")); getWidget(prevButton, "PrevGenderButton"); getWidget(nextButton, "NextGenderButton"); prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousGender); nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextGender); - setText("FaceChoiceT", wm->getGameSettingString("sRaceMenu3", "Change Face")); + setText("FaceChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Face")); getWidget(prevButton, "PrevFaceButton"); getWidget(nextButton, "NextFaceButton"); prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); - setText("HairChoiceT", wm->getGameSettingString("sRaceMenu3", "Change Hair")); + setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair")); getWidget(prevButton, "PrevHairButton"); getWidget(nextButton, "NextHairButton"); prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextHair); - setText("RaceT", wm->getGameSettingString("sRaceMenu4", "Race")); + setText("RaceT", mWindowManager.getGameSettingString("sRaceMenu4", "Race")); getWidget(raceList, "RaceList"); raceList->setScrollVisible(true); raceList->eventListSelectAccept = MyGUI::newDelegate(this, &RaceDialog::onSelectRace); raceList->eventListMouseItemActivate = MyGUI::newDelegate(this, &RaceDialog::onSelectRace); raceList->eventListChangePosition = MyGUI::newDelegate(this, &RaceDialog::onSelectRace); - setText("SkillsT", wm->getGameSettingString("sBonusSkillTitle", "Skill Bonus")); + setText("SkillsT", mWindowManager.getGameSettingString("sBonusSkillTitle", "Skill Bonus")); getWidget(skillList, "SkillList"); - setText("SpellPowerT", wm->getGameSettingString("sRaceMenu7", "Specials")); + setText("SpellPowerT", mWindowManager.getGameSettingString("sRaceMenu7", "Specials")); getWidget(spellPowerList, "SpellPowerList"); // TODO: These buttons should be managed by a Dialog class @@ -152,7 +149,7 @@ int wrap(int index, int max) void RaceDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void RaceDialog::onBackClicked(MyGUI::Widget* _sender) @@ -215,7 +212,7 @@ void RaceDialog::updateRaces() { raceList->removeAllItems(); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); ESMS::RecListT::MapType::const_iterator it = store.races.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.races.list.end(); @@ -249,8 +246,7 @@ void RaceDialog::updateSkills() const int lineHeight = 18; MyGUI::IntCoord coord1(0, 0, skillList->getWidth(), 18); - WindowManager *wm = environment.mWindowManager; - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Race *race = store.races.find(currentRaceId); int count = sizeof(race->data.bonus)/sizeof(race->data.bonus[0]); // TODO: Find a portable macro for this ARRAYSIZE? for (int i = 0; i < count; ++i) @@ -261,7 +257,7 @@ void RaceDialog::updateSkills() skillWidget = skillList->createWidget("MW_StatNameValue", coord1, MyGUI::Align::Default, std::string("Skill") + boost::lexical_cast(i)); - skillWidget->setWindowManager(wm); + skillWidget->setWindowManager(&mWindowManager); skillWidget->setSkillNumber(skillId); skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus)); @@ -286,7 +282,7 @@ void RaceDialog::updateSpellPowers() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, spellPowerList->getWidth(), 18); - ESMS::ESMStore &store = environment.mWorld->getStore(); + ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Race *race = store.races.find(currentRaceId); std::vector::const_iterator it = race->powers.list.begin(); @@ -295,7 +291,7 @@ void RaceDialog::updateSpellPowers() { const std::string &spellpower = *it; spellPowerWidget = spellPowerList->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast(i)); - spellPowerWidget->setEnvironment(&environment); + spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setSpellId(spellpower); spellPowerItems.push_back(spellPowerWidget); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 47774703c..f2aac3a18 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -7,9 +7,9 @@ #include -namespace MWWorld +namespace MWGui { - class Environment; + class WindowManager; } /* @@ -24,7 +24,7 @@ namespace MWGui class RaceDialog : public WindowBase { public: - RaceDialog(MWWorld::Environment& environment); + RaceDialog(WindowManager& parWindowManager); enum Gender { @@ -53,11 +53,6 @@ namespace MWGui */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onHeadRotate(MyGUI::VScroll* _sender, size_t _position); diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 6caba6238..e770ec235 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -1,6 +1,4 @@ #include "review.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "window_manager.hpp" #include "widgets.hpp" #include "components/esm_store/store.hpp" @@ -8,53 +6,56 @@ #include #include +#include + +#undef min +#undef max + using namespace MWGui; using namespace Widgets; const int ReviewDialog::lineHeight = 18; -ReviewDialog::ReviewDialog(MWWorld::Environment& environment) - : WindowBase("openmw_chargen_review_layout.xml", environment) +ReviewDialog::ReviewDialog(WindowManager& parWindowManager) + : WindowBase("openmw_chargen_review_layout.xml", parWindowManager) , lastPos(0) { // Centre dialog center(); - WindowManager *wm = environment.mWindowManager; - // Setup static stats ButtonPtr button; getWidget(nameWidget, "NameText"); getWidget(button, "NameButton"); - button->setCaption(wm->getGameSettingString("sName", "")); + button->setCaption(mWindowManager.getGameSettingString("sName", "")); button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);; getWidget(raceWidget, "RaceText"); getWidget(button, "RaceButton"); - button->setCaption(wm->getGameSettingString("sRace", "")); + button->setCaption(mWindowManager.getGameSettingString("sRace", "")); button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);; getWidget(classWidget, "ClassText"); getWidget(button, "ClassButton"); - button->setCaption(wm->getGameSettingString("sClass", "")); + button->setCaption(mWindowManager.getGameSettingString("sClass", "")); button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);; getWidget(birthSignWidget, "SignText"); getWidget(button, "SignButton"); - button->setCaption(wm->getGameSettingString("sBirthSign", "")); + button->setCaption(mWindowManager.getGameSettingString("sBirthSign", "")); button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);; // Setup dynamic stats getWidget(health, "Health"); - health->setTitle(wm->getGameSettingString("sHealth", "")); + health->setTitle(mWindowManager.getGameSettingString("sHealth", "")); health->setValue(45, 45); getWidget(magicka, "Magicka"); - magicka->setTitle(wm->getGameSettingString("sMagic", "")); + magicka->setTitle(mWindowManager.getGameSettingString("sMagic", "")); magicka->setValue(50, 50); getWidget(fatigue, "Fatigue"); - fatigue->setTitle(wm->getGameSettingString("sFatigue", "")); + fatigue->setTitle(mWindowManager.getGameSettingString("sFatigue", "")); fatigue->setValue(160, 160); // Setup attributes @@ -64,7 +65,7 @@ ReviewDialog::ReviewDialog(MWWorld::Environment& environment) { getWidget(attribute, std::string("Attribute") + boost::lexical_cast(idx)); attributeWidgets.insert(std::make_pair(static_cast(ESM::Attribute::attributeIds[idx]), attribute)); - attribute->setWindowManager(wm); + attribute->setWindowManager(&mWindowManager); attribute->setAttributeId(ESM::Attribute::attributeIds[idx]); attribute->setAttributeValue(MWAttribute::AttributeValue(0, 0)); } @@ -79,8 +80,8 @@ ReviewDialog::ReviewDialog(MWWorld::Environment& environment) for (int i = 0; i < ESM::Skill::Length; ++i) { - skillValues.insert(std::pair >(i, MWMechanics::Stat())); - skillWidgetMap.insert(std::pair(i, (MyGUI::StaticTextPtr)nullptr)); + skillValues.insert(std::make_pair(i, MWMechanics::Stat())); + skillWidgetMap.insert(std::make_pair(i, static_cast (0))); } static_cast(mMainWidget)->eventWindowChangeCoord = MyGUI::newDelegate(this, &ReviewDialog::onWindowResize); @@ -116,7 +117,7 @@ void ReviewDialog::onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos } } -void ReviewDialog::onWindowResize(MyGUI::WidgetPtr window) +void ReviewDialog::onWindowResize(MyGUI::Window* window) { updateScroller(); } @@ -129,7 +130,7 @@ void ReviewDialog::setPlayerName(const std::string &name) void ReviewDialog::setRace(const std::string &raceId_) { raceId = raceId_; - const ESM::Race *race = environment.mWorld->getStore().races.search(raceId); + const ESM::Race *race = mWindowManager.getStore().races.search(raceId); if (race) raceWidget->setCaption(race->name); } @@ -143,7 +144,7 @@ void ReviewDialog::setClass(const ESM::Class& class_) void ReviewDialog::setBirthSign(const std::string& signId) { birthSignId = signId; - const ESM::BirthSign *sign = environment.mWorld->getStore().birthSigns.search(birthSignId); + const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId); if (sign) birthSignWidget->setCaption(sign->name); } @@ -273,15 +274,13 @@ void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGU void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { - WindowManager *wm = environment.mWindowManager; - // Add a line separator if there are items above if (!skillWidgets.empty()) { addSeparator(coord1, coord2); } - addGroup(wm->getGameSettingString(titleId, titleDefault), coord1, coord2); + addGroup(mWindowManager.getGameSettingString(titleId, titleDefault), coord1, coord2); SkillList::const_iterator end = skills.end(); for (SkillList::const_iterator it = skills.begin(); it != end; ++it) @@ -300,7 +299,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId style = CS_Super; else if (modified < base) style = CS_Sub; - MyGUI::StaticTextPtr widget = addValueItem(wm->getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); + MyGUI::StaticTextPtr widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); skillWidgetMap[skillId] = widget; } } @@ -340,7 +339,7 @@ void ReviewDialog::updateScroller() void ReviewDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void ReviewDialog::onBackClicked(MyGUI::Widget* _sender) @@ -350,20 +349,20 @@ void ReviewDialog::onBackClicked(MyGUI::Widget* _sender) void ReviewDialog::onNameClicked(MyGUI::Widget* _sender) { - eventNameActivated(); + eventActivateDialog(NAME_DIALOG); } void ReviewDialog::onRaceClicked(MyGUI::Widget* _sender) { - eventRaceActivated(); + eventActivateDialog(RACE_DIALOG); } void ReviewDialog::onClassClicked(MyGUI::Widget* _sender) { - eventClassActivated(); + eventActivateDialog(CLASS_DIALOG); } void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender) { - eventBirthSignActivated(); + eventActivateDialog(BIRTHSIGN_DIALOG); } diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 25a183f65..5846804f7 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -5,9 +5,9 @@ #include "../mwmechanics/stat.hpp" #include "widgets.hpp" -namespace MWWorld +namespace MWGui { - class Environment; + class WindowManager; } /* @@ -22,9 +22,15 @@ namespace MWGui class ReviewDialog : public WindowBase { public: + enum Dialogs { + NAME_DIALOG, + RACE_DIALOG, + CLASS_DIALOG, + BIRTHSIGN_DIALOG + }; typedef std::vector SkillList; - ReviewDialog(MWWorld::Environment& environment); + ReviewDialog(WindowManager& parWindowManager); void setPlayerName(const std::string &name); void setRace(const std::string &raceId); @@ -44,36 +50,14 @@ namespace MWGui // Events typedef delegates::CDelegate0 EventHandle_Void; + typedef delegates::CDelegate1 EventHandle_Int; /** Event : Back button clicked.\n signature : void method()\n */ EventHandle_Void eventBack; - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - - /** Event : Activate name dialog.\n - signature : void method()\n - */ - EventHandle_Void eventNameActivated; - - /** Event : Activate race dialog.\n - signature : void method()\n - */ - EventHandle_Void eventRaceActivated; - - /** Event : Activate class dialog.\n - signature : void method()\n - */ - EventHandle_Void eventClassActivated; - - /** Event : Activate birth sign dialog.\n - signature : void method()\n - */ - EventHandle_Void eventBirthSignActivated; + EventHandle_Int eventActivateDialog; protected: void onOkClicked(MyGUI::Widget* _sender); @@ -101,7 +85,7 @@ namespace MWGui void updateSkillArea(); void onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos); - void onWindowResize(MyGUI::WidgetPtr window); + void onWindowResize(MyGUI::Window* window); static const int lineHeight; diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp new file mode 100644 index 000000000..d08e6384d --- /dev/null +++ b/apps/openmw/mwgui/stats_window.cpp @@ -0,0 +1,370 @@ +#include "stats_window.hpp" + +#include "../mwmechanics/mechanicsmanager.hpp" +#include "window_manager.hpp" + +#include +#include +#include +#include + +using namespace MWGui; +const int StatsWindow::lineHeight = 18; + +StatsWindow::StatsWindow (WindowManager& parWindowManager) + : WindowBase("openmw_stats_window_layout.xml", parWindowManager) + , lastPos(0) + , reputation(0) + , bounty(0) +{ + setCoord(0,0,498, 342); + + const char *names[][2] = + { + { "Attrib1", "sAttributeStrength" }, + { "Attrib2", "sAttributeIntelligence" }, + { "Attrib3", "sAttributeWillpower" }, + { "Attrib4", "sAttributeAgility" }, + { "Attrib5", "sAttributeSpeed" }, + { "Attrib6", "sAttributeEndurance" }, + { "Attrib7", "sAttributePersonality" }, + { "Attrib8", "sAttributeLuck" }, + { "Health_str", "sHealth" }, + { "Magicka_str", "sMagic" }, + { "Fatigue_str", "sFatigue" }, + { "Level_str", "sLevel" }, + { "Race_str", "sRace" }, + { "Class_str", "sClass" }, + { 0, 0 } + }; + + const ESMS::ESMStore &store = mWindowManager.getStore(); + for (int i=0; names[i][0]; ++i) + { + setText (names[i][0], store.gameSettings.find (names[i][1])->str); + } + + getWidget(skillAreaWidget, "Skills"); + getWidget(skillClientWidget, "SkillClient"); + getWidget(skillScrollerWidget, "SkillScroller"); + + skillScrollerWidget->eventScrollChangePosition = MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition); + updateScroller(); + + for (int i = 0; i < ESM::Skill::Length; ++i) + { + skillValues.insert(std::pair >(i, MWMechanics::Stat())); + skillWidgetMap.insert(std::pair(i, nullptr)); + } + + MyGUI::WindowPtr t = static_cast(mMainWidget); + t->eventWindowChangeCoord = MyGUI::newDelegate(this, &StatsWindow::onWindowResize); +} + +void StatsWindow::onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos) +{ + int diff = lastPos - pos; + // Adjust position of all widget according to difference + if (diff == 0) + return; + lastPos = pos; + + std::vector::const_iterator end = skillWidgets.end(); + for (std::vector::const_iterator it = skillWidgets.begin(); it != end; ++it) + { + (*it)->setCoord((*it)->getCoord() + MyGUI::IntPoint(0, diff)); + } +} + +void StatsWindow::onWindowResize(MyGUI::Window* window) +{ + updateScroller(); +} + +void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max) +{ + MyGUI::ProgressPtr pt; + getWidget(pt, name); + pt->setProgressRange(max); + pt->setProgressPosition(val); + + std::stringstream out; + out << val << "/" << max; + setText(tname, out.str().c_str()); +} + +void StatsWindow::setPlayerName(const std::string& playerName) +{ + mMainWidget->setCaption(playerName); +} + +void StatsWindow::setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value) +{ + widget->setCaption(value); + if (style == CS_Super) + widget->setTextColour(MyGUI::Colour(0, 1, 0)); + else if (style == CS_Sub) + widget->setTextColour(MyGUI::Colour(1, 0, 0)); + else + widget->setTextColour(MyGUI::Colour(1, 1, 1)); +} + +void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) +{ + static const char *ids[] = + { + "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", + "AttribVal6", "AttribVal7", "AttribVal8", + 0 + }; + + for (int i=0; ids[i]; ++i) + if (ids[i]==id) + { + std::ostringstream valueString; + valueString << value.getModified(); + setText (id, valueString.str()); + + if (value.getModified()>value.getBase()) + setTextColor (id, 0, 1, 0); + else if (value.getModified()& value) +{ + static const char *ids[] = + { + "HBar", "MBar", "FBar", + 0 + }; + + for (int i=0; ids[i]; ++i) + if (ids[i]==id) + { + std::string id (ids[i]); + setBar (id, id + "T", value.getCurrent(), value.getModified()); + } +} + +void StatsWindow::setValue (const std::string& id, const std::string& value) +{ + if (id=="name") + setPlayerName (value); + else if (id=="race") + setText ("RaceText", value); + else if (id=="class") + setText ("ClassText", value); +} + +void StatsWindow::setValue (const std::string& id, int value) +{ + if (id=="level") + { + std::ostringstream text; + text << value; + setText("LevelText", text.str()); + } +} + +void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value) +{ + skillValues[parSkill] = value; + MyGUI::StaticTextPtr widget = skillWidgetMap[(int)parSkill]; + if (widget) + { + float modified = value.getModified(), base = value.getBase(); + std::string text = boost::lexical_cast(std::floor(modified)); + ColorStyle style = CS_Normal; + if (modified > base) + style = CS_Super; + else if (modified < base) + style = CS_Sub; + + setStyledText(widget, style, text); + } +} + +void StatsWindow::configureSkills (const std::vector& major, const std::vector& minor) +{ + majorSkills = major; + minorSkills = minor; + + // Update misc skills with the remaining skills not in major or minor + std::set skillSet; + std::copy(major.begin(), major.end(), std::inserter(skillSet, skillSet.begin())); + std::copy(minor.begin(), minor.end(), std::inserter(skillSet, skillSet.begin())); + boost::array::const_iterator end = ESM::Skill::skillIds.end(); + miscSkills.clear(); + for (boost::array::const_iterator it = ESM::Skill::skillIds.begin(); it != end; ++it) + { + int skill = *it; + if (skillSet.find(skill) == skillSet.end()) + miscSkills.push_back(skill); + } +} + +void StatsWindow::setFactions (const std::vector& factions) +{ + this->factions = factions; +} + +void StatsWindow::setBirthSign (const std::string& signId) +{ + birthSignId = signId; +} + +void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::StaticImagePtr separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); + skillWidgets.push_back(separator); + + coord1.top += separator->getHeight(); + coord2.top += separator->getHeight(); +} + +void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::StaticTextPtr groupWidget = skillClientWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); + groupWidget->setCaption(label); + skillWidgets.push_back(groupWidget); + + coord1.top += lineHeight; + coord2.top += lineHeight; +} + +MyGUI::StaticTextPtr StatsWindow::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::StaticTextPtr skillNameWidget, skillValueWidget; + + skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); + skillNameWidget->setCaption(text); + + skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Default); + setStyledText(skillValueWidget, style, value); + + skillWidgets.push_back(skillNameWidget); + skillWidgets.push_back(skillValueWidget); + + coord1.top += lineHeight; + coord2.top += lineHeight; + + return skillValueWidget; +} + +void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::StaticTextPtr skillNameWidget; + + skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); + skillNameWidget->setCaption(text); + + skillWidgets.push_back(skillNameWidget); + + coord1.top += lineHeight; + coord2.top += lineHeight; +} + +void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + // Add a line separator if there are items above + if (!skillWidgets.empty()) + { + addSeparator(coord1, coord2); + } + + addGroup(mWindowManager.getGameSettingString(titleId, titleDefault), coord1, coord2); + + SkillList::const_iterator end = skills.end(); + for (SkillList::const_iterator it = skills.begin(); it != end; ++it) + { + int skillId = *it; + if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes + continue; + assert(skillId >= 0 && skillId < ESM::Skill::Length); + const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const MWMechanics::Stat &stat = skillValues.find(skillId)->second; + float base = stat.getBase(); + float modified = stat.getModified(); + + ColorStyle style = CS_Normal; + if (modified > base) + style = CS_Super; + else if (modified < base) + style = CS_Sub; + MyGUI::StaticTextPtr widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), style, coord1, coord2); + skillWidgetMap[skillId] = widget; + } +} + +void StatsWindow::updateSkillArea() +{ + for (std::vector::iterator it = skillWidgets.begin(); it != skillWidgets.end(); ++it) + { + MyGUI::Gui::getInstance().destroyWidget(*it); + } + skillWidgets.clear(); + + const int valueSize = 40; + MyGUI::IntCoord coord1(10, 0, skillClientWidget->getWidth() - (10 + valueSize), 18); + MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); + + if (!majorSkills.empty()) + addSkills(majorSkills, "sSkillClassMajor", "Major Skills", coord1, coord2); + + if (!minorSkills.empty()) + addSkills(minorSkills, "sSkillClassMinor", "Minor Skills", coord1, coord2); + + if (!miscSkills.empty()) + addSkills(miscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); + + ESMS::ESMStore &store = mWindowManager.getStore(); + + if (!factions.empty()) + { + // Add a line separator if there are items above + if (!skillWidgets.empty()) + addSeparator(coord1, coord2); + + addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2); + FactionList::const_iterator end = factions.end(); + for (FactionList::const_iterator it = factions.begin(); it != end; ++it) + { + const ESM::Faction *faction = store.factions.find(it->first); + addItem(faction->name, coord1, coord2); + // TODO: Faction rank should be placed in tooltip + } + } + + if (!birthSignId.empty()) + { + // Add a line separator if there are items above + if (!skillWidgets.empty()) + addSeparator(coord1, coord2); + + addGroup(mWindowManager.getGameSettingString("sSign", "Sign"), coord1, coord2); + const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); + addItem(sign->name, coord1, coord2); + } + + // Add a line separator if there are items above + if (!skillWidgets.empty()) + addSeparator(coord1, coord2); + + addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), boost::lexical_cast(static_cast(reputation)), CS_Normal, coord1, coord2); + addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), boost::lexical_cast(static_cast(bounty)), CS_Normal, coord1, coord2); + + clientHeight = coord1.top; + updateScroller(); +} + +void StatsWindow::updateScroller() +{ + skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); + skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); +} diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp new file mode 100644 index 000000000..9db5c240b --- /dev/null +++ b/apps/openmw/mwgui/stats_window.hpp @@ -0,0 +1,80 @@ +#ifndef MWGUI_STATS_WINDOW_H +#define MWGUI_STATS_WINDOW_H + +#include + +#include +#include +#include +#include + +#include "../mwmechanics/stat.hpp" +#include "window_base.hpp" + +namespace MWGui +{ + class WindowManager; + + class StatsWindow : public WindowBase + { + public: + typedef std::pair Faction; + typedef std::vector FactionList; + + typedef std::vector SkillList; + + StatsWindow(WindowManager& parWindowManager); + + void setBar(const std::string& name, const std::string& tname, int val, int max); + void setPlayerName(const std::string& playerName); + + /// Set value for the given ID. + void setValue (const std::string& id, const MWMechanics::Stat& value); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setValue (const std::string& id, const std::string& value); + void setValue (const std::string& id, int value); + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); + + void configureSkills (const SkillList& major, const SkillList& minor); + void setFactions (const std::vector& factions); + void setBirthSign (const std::string &signId); + void setReputation (int reputation) { this->reputation = reputation; } + void setBounty (int bounty) { this->bounty = bounty; } + void updateSkillArea(); + + private: + enum ColorStyle + { + CS_Sub, + CS_Normal, + CS_Super + }; + void setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value); + void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::StaticTextPtr addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void updateScroller(); + + void onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos); + void onWindowResize(MyGUI::Window* window); + + static const int lineHeight; + + MyGUI::WidgetPtr skillAreaWidget, skillClientWidget; + MyGUI::VScrollPtr skillScrollerWidget; + int lastPos, clientHeight; + + SkillList majorSkills, minorSkills, miscSkills; + std::map > skillValues; + std::map skillWidgetMap; + std::map factionWidgetMap; + FactionList factions; ///< Stores a list of factions and the current rank + std::string birthSignId; + int reputation, bounty; + std::vector skillWidgets; //< Skills and other information + }; +} +#endif + diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index 3758e75e6..83ebef657 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -1,12 +1,10 @@ #include "text_input.hpp" #include "window_manager.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" using namespace MWGui; -TextInputDialog::TextInputDialog(MWWorld::Environment& environment) - : WindowBase("openmw_text_input_layout.xml", environment) +TextInputDialog::TextInputDialog(WindowManager& parWindowManager) + : WindowBase("openmw_text_input_layout.xml", parWindowManager) { // Centre dialog center(); @@ -55,10 +53,10 @@ void TextInputDialog::open() void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(); + eventDone(this); } void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) { - eventDone(); + eventDone(this); } diff --git a/apps/openmw/mwgui/text_input.hpp b/apps/openmw/mwgui/text_input.hpp index 9ca55715b..fe355655f 100644 --- a/apps/openmw/mwgui/text_input.hpp +++ b/apps/openmw/mwgui/text_input.hpp @@ -3,9 +3,9 @@ #include "window_base.hpp" -namespace MWWorld +namespace MWGui { - class Environment; + class WindowManager; } /* @@ -18,7 +18,7 @@ namespace MWGui class TextInputDialog : public WindowBase { public: - TextInputDialog(MWWorld::Environment& environment); + TextInputDialog(WindowManager& parWindowManager); std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } @@ -27,14 +27,6 @@ namespace MWGui void setTextLabel(const std::string &label); void open(); - // Events - typedef delegates::CDelegate0 EventHandle_Void; - - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_Void eventDone; - protected: void onOkClicked(MyGUI::Widget* _sender); void onTextAccepted(MyGUI::Edit* _sender); diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index e4819c80c..861939b7e 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -1,11 +1,12 @@ #include "widgets.hpp" #include "window_manager.hpp" -#include "../mwworld/environment.hpp" -#include "../mwworld/world.hpp" #include "components/esm_store/store.hpp" #include +#undef min +#undef max + using namespace MWGui; using namespace MWGui::Widgets; @@ -89,53 +90,53 @@ void MWSkill::onClicked(MyGUI::Widget* _sender) void MWSkill::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name) { - Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name); + Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name); - initialiseWidgetSkin(_info); + initialiseWidgetSkin(_info); } MWSkill::~MWSkill() { - shutdownWidgetSkin(); + shutdownWidgetSkin(); } void MWSkill::baseChangeWidgetSkin(ResourceSkin* _info) { - shutdownWidgetSkin(); - Base::baseChangeWidgetSkin(_info); - initialiseWidgetSkin(_info); + shutdownWidgetSkin(); + Base::baseChangeWidgetSkin(_info); + initialiseWidgetSkin(_info); } void MWSkill::initialiseWidgetSkin(ResourceSkin* _info) { for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter) - { + { const std::string &name = *(*iter)->_getInternalData(); - if (name == "StatName") - { - MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned"); - skillNameWidget = (*iter)->castType(); - } - else if (name == "StatValue") - { - MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned"); - skillValueWidget = (*iter)->castType(); - } - else if (name == "StatNameButton") - { - MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned"); + if (name == "StatName") + { + MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned"); + skillNameWidget = (*iter)->castType(); + } + else if (name == "StatValue") + { + MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned"); + skillValueWidget = (*iter)->castType(); + } + else if (name == "StatNameButton") + { + MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned"); MyGUI::ButtonPtr button = (*iter)->castType