mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 10:23:56 +00:00
Merge branch 'terrain18' into terraincollision
Conflicts: apps/openmw/mwworld/scene.cpp
This commit is contained in:
commit
58f7a03626
548 changed files with 7849 additions and 55164 deletions
123
Bitstream Vera License.txt
Normal file
123
Bitstream Vera License.txt
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
Bitstream Vera Fonts Copyright
|
||||||
|
|
||||||
|
The fonts have a generous copyright, allowing derivative works (as
|
||||||
|
long as "Bitstream" or "Vera" are not in the names), and full
|
||||||
|
redistribution (so long as they are not *sold* by themselves). They
|
||||||
|
can be be bundled, redistributed and sold with any software.
|
||||||
|
|
||||||
|
The fonts are distributed under the following copyright:
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
|
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
|
||||||
|
Vera is a trademark of Bitstream, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the fonts accompanying this license ("Fonts") and associated
|
||||||
|
documentation files (the "Font Software"), to reproduce and distribute
|
||||||
|
the Font Software, including without limitation the rights to use,
|
||||||
|
copy, merge, publish, distribute, and/or sell copies of the Font
|
||||||
|
Software, and to permit persons to whom the Font Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright and trademark notices and this permission notice
|
||||||
|
shall be included in all copies of one or more of the Font Software
|
||||||
|
typefaces.
|
||||||
|
|
||||||
|
The Font Software may be modified, altered, or added to, and in
|
||||||
|
particular the designs of glyphs or characters in the Fonts may be
|
||||||
|
modified and additional glyphs or characters may be added to the
|
||||||
|
Fonts, only if the fonts are renamed to names not containing either
|
||||||
|
the words "Bitstream" or the word "Vera".
|
||||||
|
|
||||||
|
This License becomes null and void to the extent applicable to Fonts
|
||||||
|
or Font Software that has been modified and is distributed under the
|
||||||
|
"Bitstream Vera" names.
|
||||||
|
|
||||||
|
The Font Software may be sold as part of a larger software package but
|
||||||
|
no copy of one or more of the Font Software typefaces may be sold by
|
||||||
|
itself.
|
||||||
|
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||||
|
BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
|
||||||
|
OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
|
||||||
|
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the names of Gnome, the Gnome
|
||||||
|
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||||
|
otherwise to promote the sale, use or other dealings in this Font
|
||||||
|
Software without prior written authorization from the Gnome Foundation
|
||||||
|
or Bitstream Inc., respectively. For further information, contact:
|
||||||
|
fonts at gnome dot org.
|
||||||
|
|
||||||
|
Copyright FAQ
|
||||||
|
=============
|
||||||
|
|
||||||
|
1. I don't understand the resale restriction... What gives?
|
||||||
|
|
||||||
|
Bitstream is giving away these fonts, but wishes to ensure its
|
||||||
|
competitors can't just drop the fonts as is into a font sale system
|
||||||
|
and sell them as is. It seems fair that if Bitstream can't make money
|
||||||
|
from the Bitstream Vera fonts, their competitors should not be able to
|
||||||
|
do so either. You can sell the fonts as part of any software package,
|
||||||
|
however.
|
||||||
|
|
||||||
|
2. I want to package these fonts separately for distribution and
|
||||||
|
sale as part of a larger software package or system. Can I do so?
|
||||||
|
|
||||||
|
Yes. A RPM or Debian package is a "larger software package" to begin
|
||||||
|
with, and you aren't selling them independently by themselves.
|
||||||
|
See 1. above.
|
||||||
|
|
||||||
|
3. Are derivative works allowed?
|
||||||
|
Yes!
|
||||||
|
|
||||||
|
4. Can I change or add to the font(s)?
|
||||||
|
Yes, but you must change the name(s) of the font(s).
|
||||||
|
|
||||||
|
5. Under what terms are derivative works allowed?
|
||||||
|
|
||||||
|
You must change the name(s) of the fonts. This is to ensure the
|
||||||
|
quality of the fonts, both to protect Bitstream and Gnome. We want to
|
||||||
|
ensure that if an application has opened a font specifically of these
|
||||||
|
names, it gets what it expects (though of course, using fontconfig,
|
||||||
|
substitutions could still could have occurred during font
|
||||||
|
opening). You must include the Bitstream copyright. Additional
|
||||||
|
copyrights can be added, as per copyright law. Happy Font Hacking!
|
||||||
|
|
||||||
|
6. If I have improvements for Bitstream Vera, is it possible they might get
|
||||||
|
adopted in future versions?
|
||||||
|
|
||||||
|
Yes. The contract between the Gnome Foundation and Bitstream has
|
||||||
|
provisions for working with Bitstream to ensure quality additions to
|
||||||
|
the Bitstream Vera font family. Please contact us if you have such
|
||||||
|
additions. Note, that in general, we will want such additions for the
|
||||||
|
entire family, not just a single font, and that you'll have to keep
|
||||||
|
both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add
|
||||||
|
glyphs to the font, they must be stylistically in keeping with Vera's
|
||||||
|
design. Vera cannot become a "ransom note" font. Jim Lyles will be
|
||||||
|
providing a document describing the design elements used in Vera, as a
|
||||||
|
guide and aid for people interested in contributing to Vera.
|
||||||
|
|
||||||
|
7. I want to sell a software package that uses these fonts: Can I do so?
|
||||||
|
|
||||||
|
Sure. Bundle the fonts with your software and sell your software
|
||||||
|
with the fonts. That is the intent of the copyright.
|
||||||
|
|
||||||
|
8. If applications have built the names "Bitstream Vera" into them,
|
||||||
|
can I override this somehow to use fonts of my choosing?
|
||||||
|
|
||||||
|
This depends on exact details of the software. Most open source
|
||||||
|
systems and software (e.g., Gnome, KDE, etc.) are now converting to
|
||||||
|
use fontconfig (see www.fontconfig.org) to handle font configuration,
|
||||||
|
selection and substitution; it has provisions for overriding font
|
||||||
|
names and subsituting alternatives. An example is provided by the
|
||||||
|
supplied local.conf file, which chooses the family Bitstream Vera for
|
||||||
|
"sans", "serif" and "monospace". Other software (e.g., the XFree86
|
||||||
|
core server) has other mechanisms for font substitution.
|
169
CMakeLists.txt
169
CMakeLists.txt
|
@ -4,9 +4,6 @@ if (APPLE)
|
||||||
set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
||||||
|
|
||||||
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
|
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
|
||||||
|
|
||||||
# using 10.6 sdk
|
|
||||||
set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk")
|
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
# Macros
|
# Macros
|
||||||
|
@ -18,7 +15,7 @@ include (OpenMWMacros)
|
||||||
# Version
|
# Version
|
||||||
|
|
||||||
set (OPENMW_VERSION_MAJOR 0)
|
set (OPENMW_VERSION_MAJOR 0)
|
||||||
set (OPENMW_VERSION_MINOR 12)
|
set (OPENMW_VERSION_MINOR 13)
|
||||||
set (OPENMW_VERSION_RELEASE 0)
|
set (OPENMW_VERSION_RELEASE 0)
|
||||||
|
|
||||||
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
@ -27,8 +24,9 @@ set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VE
|
||||||
|
|
||||||
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
|
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
|
||||||
|
|
||||||
|
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
|
||||||
|
|
||||||
# Sound source selection
|
# Sound source selection
|
||||||
option(USE_AUDIERE "use Audiere for sound" OFF)
|
|
||||||
option(USE_FFMPEG "use ffmpeg for sound" OFF)
|
option(USE_FFMPEG "use ffmpeg for sound" OFF)
|
||||||
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
||||||
|
|
||||||
|
@ -118,52 +116,31 @@ set(OENGINE_BULLET
|
||||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.h
|
${LIBDIR}/openengine/bullet/BulletShapeLoader.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sound setup
|
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET})
|
||||||
if (USE_AUDIERE)
|
|
||||||
set(MANGLE_SOUND_OUTPUT
|
|
||||||
${LIBDIR}/mangle/sound/sources/audiere_source.cpp
|
|
||||||
${LIBDIR}/mangle/sound/sources/sample_reader.cpp
|
|
||||||
${LIBDIR}/mangle/stream/clients/audiere_file.cpp)
|
|
||||||
find_package(Audiere REQUIRED)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE -DOPENMW_USE_AUDIERE)
|
|
||||||
endif (USE_AUDIERE)
|
|
||||||
|
|
||||||
if (USE_FFMPEG)
|
|
||||||
set(MANGLE_SOUND_OUTPUT
|
|
||||||
${LIBDIR}/mangle/sound/sources/ffmpeg_source.cpp)
|
|
||||||
find_package(FFMPEG REQUIRED)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
|
|
||||||
set(SOUND_DEFINE -DOPENMW_USE_FFMPEG)
|
|
||||||
endif (USE_FFMPEG)
|
|
||||||
|
|
||||||
if (USE_MPG123)
|
|
||||||
set(MANGLE_SOUND_OUTPUT
|
|
||||||
${LIBDIR}/mangle/sound/sources/mpg123_source.cpp
|
|
||||||
${LIBDIR}/mangle/sound/sources/libsndfile.cpp
|
|
||||||
${LIBDIR}/mangle/sound/sources/sample_reader.cpp)
|
|
||||||
find_package(MPG123 REQUIRED)
|
|
||||||
find_package(SNDFILE REQUIRED)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE -DOPENMW_USE_MPG123)
|
|
||||||
endif (USE_MPG123)
|
|
||||||
|
|
||||||
set(OENGINE_SOUND
|
|
||||||
# Mangle and OEngine sound files are sort of intertwined, so put
|
|
||||||
# them together here
|
|
||||||
${LIBDIR}/openengine/sound/sndmanager.cpp
|
|
||||||
${LIBDIR}/mangle/sound/outputs/openal_out.cpp
|
|
||||||
${MANGLE_SOUND_OUTPUT}
|
|
||||||
)
|
|
||||||
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND} ${OENGINE_BULLET})
|
|
||||||
source_group(libs\\openengine FILES ${OENGINE_ALL})
|
source_group(libs\\openengine FILES ${OENGINE_ALL})
|
||||||
|
|
||||||
set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL})
|
set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL})
|
||||||
set(OPENMW_LIBS_HEADER)
|
set(OPENMW_LIBS_HEADER)
|
||||||
|
|
||||||
|
# Sound setup
|
||||||
|
set(SOUND_INPUT_INCLUDES "")
|
||||||
|
set(SOUND_INPUT_LIBRARY "")
|
||||||
|
set(SOUND_DEFINE "")
|
||||||
|
if (USE_FFMPEG)
|
||||||
|
find_package(FFMPEG REQUIRED)
|
||||||
|
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIR})
|
||||||
|
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES})
|
||||||
|
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
|
||||||
|
endif (USE_FFMPEG)
|
||||||
|
|
||||||
|
if (USE_MPG123)
|
||||||
|
find_package(MPG123 REQUIRED)
|
||||||
|
find_package(SNDFILE REQUIRED)
|
||||||
|
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
||||||
|
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
||||||
|
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
|
||||||
|
endif (USE_MPG123)
|
||||||
|
|
||||||
# Platform specific
|
# Platform specific
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(PLATFORM_INCLUDE_DIR "platform")
|
set(PLATFORM_INCLUDE_DIR "platform")
|
||||||
|
@ -175,7 +152,6 @@ include_directories(${UUID_INCLUDE_DIR})
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
if (MSVC10)
|
if (MSVC10)
|
||||||
set(PLATFORM_INCLUDE_DIR "")
|
set(PLATFORM_INCLUDE_DIR "")
|
||||||
add_definitions(-DMYGUI_DONT_REPLACE_NULLPTR)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
@ -184,24 +160,38 @@ endif (APPLE)
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
|
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
find_package (Threads)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(OGRE REQUIRED)
|
find_package(OGRE REQUIRED)
|
||||||
|
find_package(MyGUI REQUIRED)
|
||||||
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
|
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
|
||||||
find_package(OIS REQUIRED)
|
find_package(OIS REQUIRED)
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
find_package(Bullet REQUIRED)
|
find_package(Bullet REQUIRED)
|
||||||
|
IF(OGRE_STATIC)
|
||||||
|
find_package(Cg REQUIRED)
|
||||||
|
IF(WIN32)
|
||||||
|
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
|
||||||
|
ELSE(WIN32)
|
||||||
|
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
|
||||||
|
ENDIF(WIN32)
|
||||||
|
ENDIF(OGRE_STATIC)
|
||||||
include_directories("."
|
include_directories("."
|
||||||
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE
|
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS}
|
||||||
${OGRE_Terrain_INCLUDE_DIR}
|
${OGRE_Terrain_INCLUDE_DIR}
|
||||||
${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}
|
${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}
|
||||||
${PLATFORM_INCLUDE_DIR}
|
${PLATFORM_INCLUDE_DIR}
|
||||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include
|
${MYGUI_INCLUDE_DIRS}
|
||||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/OgrePlatform/include
|
${MYGUI_PLATFORM_INCLUDE_DIRS}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
${UUID_INCLUDE_DIR}
|
${UUID_INCLUDE_DIR}
|
||||||
${LIBDIR}
|
${LIBDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR})
|
link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# List used Ogre plugins
|
# List used Ogre plugins
|
||||||
|
@ -211,14 +201,7 @@ if(APPLE)
|
||||||
"Plugin_ParticleFX")
|
"Plugin_ParticleFX")
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
add_subdirectory( extern/mygui_3.0.1 )
|
add_subdirectory( files/mygui )
|
||||||
|
|
||||||
# Make sure that certain libraries are used as static libraries
|
|
||||||
# This is in effect turns off __declspec (dllexport) for windows
|
|
||||||
# Each library will also need to be configured to build as a static lib
|
|
||||||
|
|
||||||
# MyGUI: extern/mygui_3.0.0/
|
|
||||||
add_definitions(-DMYGUI_STATIC)
|
|
||||||
|
|
||||||
# Specify build paths
|
# Specify build paths
|
||||||
|
|
||||||
|
@ -256,14 +239,8 @@ if (APPLE)
|
||||||
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
|
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
|
||||||
|
|
||||||
# prepare plugins
|
# prepare plugins
|
||||||
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
if (${CMAKE_BUILD_TYPE} MATCHES "Release" OR
|
||||||
set(OPENMW_RELEASE_BUILD 1)
|
${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo")
|
||||||
endif()
|
|
||||||
if (${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo")
|
|
||||||
set(OPENMW_RELEASE_BUILD 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (${OPENMW_RELEASE_BUILD})
|
|
||||||
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
|
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
|
||||||
else()
|
else()
|
||||||
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
|
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
|
||||||
|
@ -279,8 +256,16 @@ endif (APPLE)
|
||||||
|
|
||||||
# Compiler settings
|
# Compiler settings
|
||||||
if (CMAKE_COMPILER_IS_GNUCC)
|
if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
#add_definitions (-Wall -Werror)
|
add_definitions (-Wall -Wextra -Wno-unused-parameter -Wno-reorder)
|
||||||
add_definitions (-Wall)
|
|
||||||
|
# Silence warnings in OGRE headers. Remove once OGRE got fixed!
|
||||||
|
add_definitions (-Wno-ignored-qualifiers)
|
||||||
|
|
||||||
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||||
|
OUTPUT_VARIABLE GCC_VERSION)
|
||||||
|
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
||||||
|
add_definitions (-Wno-unused-but-set-parameter)
|
||||||
|
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
||||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
if(DPKG_PROGRAM)
|
if(DPKG_PROGRAM)
|
||||||
|
@ -320,7 +305,7 @@ if(DPKG_PROGRAM)
|
||||||
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
|
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher")
|
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libogre-1.7.3 (>= 1.7.3), libbullet0 (>= 2.77), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
|
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
|
||||||
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
|
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
|
||||||
|
|
||||||
|
@ -340,6 +325,7 @@ if(WIN32)
|
||||||
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
|
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
|
||||||
INSTALL(FILES ${files} DESTINATION ".")
|
INSTALL(FILES ${files} DESTINATION ".")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
||||||
|
INSTALL(FILES "${OpenMW_SOURCE_DIR}/readme.txt" DESTINATION ".")
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||||
|
|
||||||
SET(CPACK_GENERATOR "NSIS")
|
SET(CPACK_GENERATOR "NSIS")
|
||||||
|
@ -350,6 +336,7 @@ if(WIN32)
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher")
|
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher")
|
||||||
|
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
|
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
|
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
|
||||||
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||||
|
@ -419,6 +406,47 @@ if (WIN32)
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM: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 COMPILE_DEFINITIONS_RELEASE "_CONSOLE")
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE")
|
||||||
|
|
||||||
|
# Play a bit with the warning levels
|
||||||
|
|
||||||
|
set(WARNINGS "/Wall") # Since windows can only disable specific warnings, not enable them
|
||||||
|
|
||||||
|
set(WARNINGS_DISABLE
|
||||||
|
# Warnings that aren't enabled normally and don't need to be enabled
|
||||||
|
# They're unneeded and sometimes completely retarded warnings that /Wall enables
|
||||||
|
# Not going to bother commenting them as they tend to warn on every standard library files
|
||||||
|
4061 4263 4264 4266 4350 4514 4548 4571 4610 4619 4623 4625 4626 4628 4640 4668 4710 4711 4820 4826 4917 4946
|
||||||
|
|
||||||
|
# Warnings that are thrown on standard libraries and not OpenMW
|
||||||
|
4347 # Non-template function with same name and parameter count as template function
|
||||||
|
4365 # Variable signed/unsigned mismatch
|
||||||
|
4510 4512 # Unable to generate copy constructor/assignment operator as it's not public in the base
|
||||||
|
4706 # Assignment in conditional expression
|
||||||
|
4738 # Storing 32-bit float result in memory, possible loss of performance
|
||||||
|
4986 # Undocumented warning that occurs in the crtdbg.h file
|
||||||
|
4996 # Function was declared deprecated
|
||||||
|
|
||||||
|
# OpenMW specific warnings
|
||||||
|
4099 # Type mismatch, declared class or struct is defined with other type
|
||||||
|
4100 # Unreferenced formal parameter (-Wunused-parameter)
|
||||||
|
4127 # Conditional expression is constant
|
||||||
|
4242 # Storing value in a variable of a smaller type, possible loss of data
|
||||||
|
4244 # Storing value of one type in variable of another (size_t in int, for example)
|
||||||
|
4305 # Truncating value (double to float, for example)
|
||||||
|
4309 # Variable overflow, trying to store 128 in a signed char for example
|
||||||
|
4355 # Using 'this' in member initialization list
|
||||||
|
4701 # Potentially uninitialized local variable used
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(d ${WARNINGS_DISABLE})
|
||||||
|
set(WARNINGS "${WARNINGS} /wd${d}")
|
||||||
|
endforeach(d)
|
||||||
|
|
||||||
|
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
if (BUILD_LAUNCHER)
|
||||||
|
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
endif (BUILD_LAUNCHER)
|
||||||
|
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
# Same for MinGW
|
# Same for MinGW
|
||||||
|
@ -451,6 +479,7 @@ if (APPLE)
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
|
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
set(CPACK_GENERATOR "DragNDrop")
|
set(CPACK_GENERATOR "DragNDrop")
|
||||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||||
|
|
93
OFL.txt
Normal file
93
OFL.txt
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
Copyright (c) 2010, 2011 Georg Duffner (http://www.georgduffner.at)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
142
README_Mac.md
142
README_Mac.md
|
@ -1,80 +1,79 @@
|
||||||
NOTE: This README is for ardekantur's Mac branch of OpenMW. A README
|
#Getting OpenMW Working on OS X
|
||||||
for the main branch has yet to be written. If you want to submit one,
|
|
||||||
please send me a message!
|
|
||||||
|
|
||||||
OpenMW
|
## Initial setup
|
||||||
======
|
First of all, clone OpenMW repo.
|
||||||
|
|
||||||
From the [official website][]:
|
$ git clone github.com/zinnschlag/openmw
|
||||||
|
|
||||||
> OpenMW is an attempt to reimplement the popular role playing game
|
Or use your github url if you forked.
|
||||||
Morrowind. It aims to be a fully playable, open source
|
|
||||||
implementation of the game. You must own Morrowind to use OpenMW.
|
|
||||||
|
|
||||||
|
About dependencies: I prefer not to install them globally (i. e. in /usr/local/), so I'm 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.
|
||||||
|
|
||||||
About This Project
|
It's useful to create env var for lib install prefix:
|
||||||
------------------
|
|
||||||
|
$ export OMW_LIB_PREFIX=$HOME/path/libs/root`
|
||||||
|
|
||||||
This specific repository is a branch of OpenMW intended to keep pace
|
Most of libs can be installed from [Homebrew][homebrew]. Only mpg123 needs to be installed from source (due to lack of universal compilation support). I think that some of libs can be installed from MacPorts or Fink too.
|
||||||
with development of the project in order to provide a Mac build for
|
|
||||||
interested parties to contribute. This is not an official, sanctioned
|
|
||||||
branch of the OpenMW project. I will only be able to answer specific
|
|
||||||
questions about getting this project running on Mac OS X, **no other
|
|
||||||
platform**. I will not even be able to guarantee my changes maintain
|
|
||||||
backwards compatibility against builds in other operating systems. You
|
|
||||||
have been warned.
|
|
||||||
|
|
||||||
|
As OpenMW currently only supports i386 architecture on OS X, denendencies also should support it. Set some env vars in current terminal:
|
||||||
|
|
||||||
Getting OpenMW Working
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
1. Clone this repository.
|
|
||||||
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
|
|
||||||
|
|
||||||
3. First of all, set for current terminal some env vars:
|
|
||||||
$ export CFLAGS="-arch i386"
|
$ export CFLAGS="-arch i386"
|
||||||
$ export CXXFLAGS="-arch i386"
|
$ export CXXFLAGS="-arch i386"
|
||||||
$ export LDFLAGS="-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:
|
If you close your terminal, you should set env vars again before pcoceeding to next steps!
|
||||||
|
|
||||||
|
## Boost
|
||||||
|
Download [boost][boost] and install it with the following command:
|
||||||
|
|
||||||
$ cd /path/to/boost/source
|
$ cd /path/to/boost/source
|
||||||
$ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX
|
$ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX
|
||||||
$ ./bjam --build-dir=build --layout=versioned \
|
$ ./bjam --build-dir=build --layout=versioned \
|
||||||
--toolset=darwin architecture=x86 address-model=32 \
|
--toolset=darwin architecture=x86 address-model=32 \
|
||||||
--link-shared,static --prefix=$OMW_LIB_PREFIX install
|
--link-shared,static --prefix=$OMW_LIB_PREFIX install
|
||||||
|
|
||||||
|
|
||||||
|
Alternatively you can install boost with homebrew:
|
||||||
|
|
||||||
|
$ brew install boost --universal
|
||||||
|
|
||||||
5. Download [Ogre][] SDK (tested with 1.7.2), unpack it and move
|
I think MacPorts also should support universal build for boost.
|
||||||
`lib/Release/Ogre.framework` into `Library/Frameworks`.
|
|
||||||
|
|
||||||
6. Download [OIS][] and use the XCode project provided in
|
## Ogre
|
||||||
`ois/Mac/XCode-2.2`. Be sure to set your build architecture to
|
Download [Ogre][] SDK (tested with 1.7.3), unpack it somewhere and move
|
||||||
`i386` and your SDK platform to either 10.5 or 10.6. Once it
|
`lib/Release/Ogre.framework` into `/Library/Frameworks`.
|
||||||
builds, move `ois/Mac/XCode-2.2/build/Debug/OIS.framework` to
|
|
||||||
`/Library/Frameworks`.
|
## OIS
|
||||||
|
Download patched [OIS][] and use the XCode project provided. Be sure to set your build architecture to
|
||||||
|
`i386`. Once it built, locate built OIS.framework with Xcode and move it to `/Library/Frameworks`.
|
||||||
|
|
||||||
|
## mpg123
|
||||||
|
Download [MPG 123][mpg123] and build it:
|
||||||
|
|
||||||
7. Download [mpg123][] and build it:
|
|
||||||
$ cd /path/to/mpg123/source
|
$ cd /path/to/mpg123/source
|
||||||
$ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \
|
$ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \
|
||||||
--disable-dependency-tracking \
|
--disable-dependency-tracking \
|
||||||
--with-optimization=4 \
|
--with-optimization=4 \
|
||||||
--with-audio=coreaudio \
|
--with-audio=dummy \
|
||||||
--with-default-audio=coreaudio \
|
--with-default-audio=dummy \
|
||||||
--with-cpu=sse_alone \
|
--with-cpu=sse_alone \
|
||||||
$ make install
|
$ make install
|
||||||
|
|
||||||
8. Download [libsndfile][] and build it:
|
## libsndfile
|
||||||
|
Download [libsndfile][] and build it:
|
||||||
|
|
||||||
$ cd /path/to/libsndfile/source
|
$ cd /path/to/libsndfile/source
|
||||||
$ ./configure --prefix=$OMW_LIB_PREFIX \
|
$ ./configure --prefix=$OMW_LIB_PREFIX \
|
||||||
--disable-dependency-tracking
|
--disable-dependency-tracking
|
||||||
$ make install
|
$ make install
|
||||||
|
|
||||||
9. Download [Bullet][] and build it:
|
or install with homebrew:
|
||||||
|
|
||||||
|
$ brew install libsndfile --universal
|
||||||
|
|
||||||
|
## Bullet
|
||||||
|
Download [Bullet][] and build it:
|
||||||
|
|
||||||
$ cd /path/to/bullet/source
|
$ cd /path/to/bullet/source
|
||||||
$ mkdir build
|
$ mkdir build
|
||||||
$ cd build
|
$ cd build
|
||||||
|
@ -87,12 +86,25 @@ Getting OpenMW Working
|
||||||
-G"Unix Makefiles" ../
|
-G"Unix Makefiles" ../
|
||||||
$ make install
|
$ make install
|
||||||
|
|
||||||
10. Generate the Makefile for OpenMW as follows and build OpenMW:
|
or install with homebrew:
|
||||||
|
|
||||||
|
$ brew install bullet --HEAD --universal
|
||||||
|
|
||||||
|
I prefer head because 2.79 has some issue which causes OpenMW to lag. Also you can edit formula and install 2.77, which is stable and haven't mentioned issue.
|
||||||
|
|
||||||
|
## Qt
|
||||||
|
Install [Qt][qt]. Qt SDK distributed by Nokia is not an option because it's 64 bit only, and OpenMW currently doesn't build for 64 bit on OS X. I'm installing it from Homebrew:
|
||||||
|
|
||||||
|
$ brew install qt --universal
|
||||||
|
|
||||||
|
## Run CMake
|
||||||
|
Generate the Makefile for OpenMW as follows and build OpenMW:
|
||||||
|
|
||||||
$ mkdir /path/to/openmw/build/dir
|
$ mkdir /path/to/openmw/build/dir
|
||||||
$ cd /path/to/open/build/dir
|
$ cd /path/to/open/build/dir
|
||||||
$ cmake \
|
$ cmake \
|
||||||
-D CMAKE_OSX_ARCHITECTURES=i386 \
|
-D CMAKE_OSX_ARCHITECTURES=i386 \
|
||||||
-D OGRESDK=/path/to/ogre/sdk \
|
-D OGRE_SDK=/path/to/ogre/sdk \
|
||||||
-D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \
|
-D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \
|
||||||
-D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \
|
-D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \
|
||||||
-D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \
|
-D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \
|
||||||
|
@ -106,27 +118,43 @@ Getting OpenMW Working
|
||||||
-D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \
|
-D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \
|
||||||
-G "Unix Makefiles" /path/to/openmw/source/dir
|
-G "Unix Makefiles" /path/to/openmw/source/dir
|
||||||
$ make
|
$ 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
|
You can use `-G"Xcode"` if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles"
|
||||||
build.
|
if you prefer Eclipse. You also can specify `-D CMAKE_BUILD_TYPE=Debug` for debug
|
||||||
|
build. As for CMake 2.8.7 and Xcode 4.3, Xcode generator is broken. Sadly Eclipse CDT also cannot import generated project at least on my machine.
|
||||||
|
|
||||||
11. Copy your Morrowind `Data Files` directory into the OpenMW build dir
|
If all libs installed via homebrew (excluding mpg123), then command would be even simplier:
|
||||||
with the name `data` or create symlink:
|
|
||||||
$ ln -s /path/to/morrowind/data/files /path/to/openmw/build/dir/data
|
$ cmake \
|
||||||
|
-D CMAKE_OSX_ARCHITECTURES="i386" \
|
||||||
|
-D OGRE_SDK=/path/to/ogre/sdk \
|
||||||
|
-D MPG123_LIBRARY=$OMW_LIB_PREFIX/lib/libmpg123.a \
|
||||||
|
-D MPG123_INCLUDE_DIR=$OMW_LIB_PREFIX/include \
|
||||||
|
-G "Unix Makefiles" /path/to/openmw/source/dir
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Note for users with recent Xcode versions: you must explicitly specify what set of compilers do you use! If not, gcc will be used for C and Clang for C++. Just add this two -D's to command: `-D CMAKE_C_COMPILER=/usr/bin/clang` and `-D CMAKE_CXX_COMPILER=/usr/bin/clang`
|
||||||
|
|
||||||
|
Note for Xcode 4.3 users: you should specify full path to used SDK, because current CMake (2.8.7) couldn't find SDKs inside Xcode app bundle:
|
||||||
|
|
||||||
|
-D CMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
|
||||||
|
|
||||||
|
# Run
|
||||||
|
From your build directory run:
|
||||||
|
|
||||||
12. From your build directory run:
|
|
||||||
$ OpenMW.app/Contents/MacOS/openmw
|
$ OpenMW.app/Contents/MacOS/openmw
|
||||||
or:
|
or:
|
||||||
|
|
||||||
$ open OpenMW.app
|
$ open OpenMW.app
|
||||||
Enjoy!
|
Enjoy!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[homebrew]: https://github.com/mxcl/homebrew
|
||||||
[boost]: http://www.boost.org
|
[boost]: http://www.boost.org
|
||||||
[Ogre]: http://www.ogre3d.org
|
[Ogre]: http://www.ogre3d.org
|
||||||
[Bullet]: http://bulletphysics.org
|
[Bullet]: http://bulletphysics.org
|
||||||
[OIS]: http://wgois.sf.net
|
[OIS]: https://github.com/corristo/ois-fork
|
||||||
[mpg123]: http://www.mpg123.de
|
[mpg123]: http://www.mpg123.de
|
||||||
[libsndfile]: http://www.mega-nerd.com/libsndfile
|
[libsndfile]: http://www.mega-nerd.com/libsndfile
|
||||||
[official website]: http://openmw.com
|
[official website]: http://openmw.com
|
||||||
[Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/
|
[Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/
|
||||||
|
[qt]: http://qt.nokia.com/
|
|
@ -53,6 +53,15 @@ QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
IF(OGRE_STATIC)
|
||||||
|
IF(WIN32)
|
||||||
|
ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
|
||||||
|
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
|
||||||
|
ELSE(WIN32)
|
||||||
|
ADD_DEFINITIONS(-DENABLE_PLUGIN_GL)
|
||||||
|
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_GL_LIBRARIES})
|
||||||
|
ENDIF(WIN32)
|
||||||
|
ENDIF(OGRE_STATIC)
|
||||||
add_executable(omwlauncher
|
add_executable(omwlauncher
|
||||||
${GUI_TYPE}
|
${GUI_TYPE}
|
||||||
${LAUNCHER}
|
${LAUNCHER}
|
||||||
|
@ -63,6 +72,7 @@ add_executable(omwlauncher
|
||||||
target_link_libraries(omwlauncher
|
target_link_libraries(omwlauncher
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
|
${OGRE_STATIC_PLUGINS}
|
||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
|
@ -222,10 +222,10 @@ void DataFilesPage::setupDataFiles()
|
||||||
|
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle("Error detecting Morrowind installation");
|
msgBox.setWindowTitle("Error detecting Morrowind installation");
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
||||||
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
||||||
The directory containing the Data Files was not found.<br><br> \
|
The directory containing the data files was not found.<br><br> \
|
||||||
Press \"Browse...\" to specify the location manually.<br>"));
|
Press \"Browse...\" to specify the location manually.<br>"));
|
||||||
|
|
||||||
QAbstractButton *dirSelectButton =
|
QAbstractButton *dirSelectButton =
|
||||||
|
@ -279,72 +279,79 @@ void DataFilesPage::setupDataFiles()
|
||||||
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
|
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
|
||||||
|
|
||||||
for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) {
|
for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) {
|
||||||
ESMReader fileReader;
|
|
||||||
QStringList availableMasters; // Will contain all found masters
|
|
||||||
|
|
||||||
fileReader.setEncoding(variables["encoding"].as<std::string>());
|
try {
|
||||||
fileReader.open(iter->second.string());
|
ESMReader fileReader;
|
||||||
|
QStringList availableMasters; // Will contain all found masters
|
||||||
|
|
||||||
// First we fill the availableMasters and the mMastersWidget
|
fileReader.setEncoding(variables["encoding"].as<std::string>());
|
||||||
ESMReader::MasterList mlist = fileReader.getMasters();
|
fileReader.open(iter->second.string());
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
// First we fill the availableMasters and the mMastersWidget
|
||||||
const QString currentMaster = QString::fromStdString(mlist[i].name);
|
ESMReader::MasterList mlist = fileReader.getMasters();
|
||||||
availableMasters.append(currentMaster);
|
|
||||||
|
|
||||||
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
|
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
||||||
|
const QString currentMaster = QString::fromStdString(mlist[i].name);
|
||||||
|
availableMasters.append(currentMaster);
|
||||||
|
|
||||||
if (itemList.isEmpty()) { // Master is not yet in the widget
|
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
|
||||||
mMastersWidget->insertRow(i);
|
|
||||||
|
|
||||||
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
|
if (itemList.isEmpty()) { // Master is not yet in the widget
|
||||||
item->setForeground(Qt::red);
|
mMastersWidget->insertRow(i);
|
||||||
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
|
|
||||||
|
|
||||||
mMastersWidget->setItem(i, 0, item);
|
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
|
||||||
|
item->setForeground(Qt::red);
|
||||||
|
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
|
||||||
|
|
||||||
|
mMastersWidget->setItem(i, 0, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
availableMasters.sort(); // Sort the masters alphabetically
|
availableMasters.sort(); // Sort the masters alphabetically
|
||||||
|
|
||||||
// Now we put the current plugin in the mDataFilesModel under its masters
|
// Now we put the current plugin in the mDataFilesModel under its masters
|
||||||
QStandardItem *parent = new QStandardItem(availableMasters.join(","));
|
QStandardItem *parent = new QStandardItem(availableMasters.join(","));
|
||||||
|
|
||||||
QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
|
QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
|
||||||
QStandardItem *child = new QStandardItem(fileName);
|
QStandardItem *child = new QStandardItem(fileName);
|
||||||
|
|
||||||
// Tooltip information
|
// Tooltip information
|
||||||
QString author = QString::fromStdString(fileReader.getAuthor());
|
QString author = QString::fromStdString(fileReader.getAuthor());
|
||||||
float version = fileReader.getFVer();
|
float version = fileReader.getFVer();
|
||||||
QString description = QString::fromStdString(fileReader.getDesc());
|
QString description = QString::fromStdString(fileReader.getDesc());
|
||||||
|
|
||||||
// For the date created/modified
|
// For the date created/modified
|
||||||
QFileInfo fi(QString::fromStdString(iter->second.string()));
|
QFileInfo fi(QString::fromStdString(iter->second.string()));
|
||||||
|
|
||||||
QString toolTip= QString("<b>Author:</b> %1<br/> \
|
QString toolTip= QString("<b>Author:</b> %1<br/> \
|
||||||
<b>Version:</b> %2<br/><br/> \
|
<b>Version:</b> %2<br/><br/> \
|
||||||
<b>Description:</b><br/> \
|
<b>Description:</b><br/> \
|
||||||
%3<br/><br/> \
|
%3<br/><br/> \
|
||||||
<b>Created on:</b> %4<br/> \
|
<b>Created on:</b> %4<br/> \
|
||||||
<b>Last modified:</b> %5")
|
<b>Last modified:</b> %5")
|
||||||
.arg(author)
|
.arg(author)
|
||||||
.arg(version)
|
.arg(version)
|
||||||
.arg(description)
|
.arg(description)
|
||||||
.arg(fi.created().toString(Qt::TextDate))
|
.arg(fi.created().toString(Qt::TextDate))
|
||||||
.arg(fi.lastModified().toString(Qt::TextDate));
|
.arg(fi.lastModified().toString(Qt::TextDate));
|
||||||
|
|
||||||
child->setToolTip(toolTip);
|
child->setToolTip(toolTip);
|
||||||
|
|
||||||
const QList<QStandardItem*> masterList = mDataFilesModel->findItems(availableMasters.join(","));
|
const QList<QStandardItem*> masterList = mDataFilesModel->findItems(availableMasters.join(","));
|
||||||
|
|
||||||
if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
|
if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
|
||||||
parent->appendRow(child);
|
parent->appendRow(child);
|
||||||
mDataFilesModel->appendRow(parent);
|
mDataFilesModel->appendRow(parent);
|
||||||
} else {
|
} else {
|
||||||
// Masters node exists, append current plugin
|
// Masters node exists, append current plugin
|
||||||
foreach (QStandardItem *currentItem, masterList) {
|
foreach (QStandardItem *currentItem, masterList) {
|
||||||
currentItem->appendRow(child);
|
currentItem->appendRow(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
// An error occurred while reading the .esp
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,16 +1057,8 @@ void DataFilesPage::writeConfig(QString profile)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the OpenMW config
|
// Open the OpenMW config as a QFile
|
||||||
QString config = QString::fromStdString((mCfgMgr.getLocalPath() / "openmw.cfg").string());
|
QFile file(QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string()));
|
||||||
QFile file(config);
|
|
||||||
|
|
||||||
if (!file.exists()) {
|
|
||||||
config = QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the config as a QFile
|
|
||||||
file.setFileName(config);
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
// File cannot be opened or created
|
// File cannot be opened or created
|
||||||
|
|
|
@ -186,7 +186,11 @@ void GraphicsPage::setupOgre()
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9)
|
||||||
|
mOgre = new Ogre::Root("", file.fileName().toStdString(), "./launcherOgre.log");
|
||||||
|
#else
|
||||||
mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log");
|
mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch(Ogre::Exception &ex)
|
catch(Ogre::Exception &ex)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +211,15 @@ void GraphicsPage::setupOgre()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_PLUGIN_GL
|
||||||
|
mGLPlugin = new Ogre::GLPlugin();
|
||||||
|
mOgre->installPlugin(mGLPlugin);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_PLUGIN_Direct3D9
|
||||||
|
mD3D9Plugin = new Ogre::D3D9Plugin();
|
||||||
|
mOgre->installPlugin(mD3D9Plugin);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get the available renderers and put them in the combobox
|
// Get the available renderers and put them in the combobox
|
||||||
const Ogre::RenderSystemList &renderers = mOgre->getAvailableRenderers();
|
const Ogre::RenderSystemList &renderers = mOgre->getAvailableRenderers();
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
#include <OgreConfigFile.h>
|
#include <OgreConfigFile.h>
|
||||||
#include <OgreConfigDialog.h>
|
#include <OgreConfigDialog.h>
|
||||||
|
|
||||||
|
// Static plugin headers
|
||||||
|
#ifdef ENABLE_PLUGIN_GL
|
||||||
|
# include "OgreGLPlugin.h"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_PLUGIN_Direct3D9
|
||||||
|
# include "OgreD3D9Plugin.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QStackedWidget;
|
class QStackedWidget;
|
||||||
|
@ -32,6 +40,12 @@ private:
|
||||||
Ogre::RenderSystem *mSelectedRenderSystem;
|
Ogre::RenderSystem *mSelectedRenderSystem;
|
||||||
Ogre::RenderSystem *mOpenGLRenderSystem;
|
Ogre::RenderSystem *mOpenGLRenderSystem;
|
||||||
Ogre::RenderSystem *mDirect3DRenderSystem;
|
Ogre::RenderSystem *mDirect3DRenderSystem;
|
||||||
|
#ifdef ENABLE_PLUGIN_GL
|
||||||
|
Ogre::GLPlugin* mGLPlugin;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_PLUGIN_Direct3D9
|
||||||
|
Ogre::D3D9Plugin* mD3D9Plugin;
|
||||||
|
#endif
|
||||||
|
|
||||||
QComboBox *mRendererComboBox;
|
QComboBox *mRendererComboBox;
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,28 @@ MainDialog::MainDialog()
|
||||||
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
setMinimumSize(QSize(575, 575));
|
setMinimumSize(QSize(575, 575));
|
||||||
|
|
||||||
|
// Install the stylesheet font
|
||||||
|
QFile file;
|
||||||
|
QFontDatabase fontDatabase;
|
||||||
|
|
||||||
|
const QStringList fonts = fontDatabase.families();
|
||||||
|
|
||||||
|
// Check if the font is installed
|
||||||
|
if (!fonts.contains("EB Garamond")) {
|
||||||
|
|
||||||
|
QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
|
||||||
|
file.setFileName(font);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
|
||||||
|
}
|
||||||
|
|
||||||
|
fontDatabase.addApplicationFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
// Load the stylesheet
|
// Load the stylesheet
|
||||||
QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string());
|
QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string());
|
||||||
QFile file(config);
|
file.setFileName(config);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string()));
|
file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string()));
|
||||||
|
@ -175,6 +194,7 @@ void MainDialog::play()
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
QString game = dir.absoluteFilePath("openmw");
|
QString game = dir.absoluteFilePath("openmw");
|
||||||
QFile file(game);
|
QFile file(game);
|
||||||
|
game = "\"" + game + "\"";
|
||||||
#else
|
#else
|
||||||
QString game = "./openmw";
|
QString game = "./openmw";
|
||||||
QFile file(game);
|
QFile file(game);
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 50 KiB |
|
@ -14,7 +14,8 @@ set(GAME_HEADER
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky terrain terrainmaterial player animation npcanimation creatureanimation actors objects renderinginterface
|
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
||||||
|
renderinginterface localmap terrain terrainmaterial
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -38,13 +39,13 @@ add_openmw_dir (mwscript
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
soundmanager
|
soundmanager openal_output mpgsnd_decoder ffmpeg_decoder
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwworld
|
add_openmw_dir (mwworld
|
||||||
refdata world physicssystem scene environment globals class action nullaction actionteleport
|
refdata world physicssystem scene environment globals class action nullaction actionteleport
|
||||||
containerstore actiontalk actiontake manualref player cellfunctors
|
containerstore actiontalk actiontake manualref player cellfunctors
|
||||||
cells localscripts customdata weather inventorystore
|
cells localscripts customdata weather inventorystore ptr
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwclass
|
add_openmw_dir (mwclass
|
||||||
|
@ -57,6 +58,15 @@ add_openmw_dir (mwmechanics
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
IF(OGRE_STATIC)
|
||||||
|
IF(WIN32)
|
||||||
|
ADD_DEFINITIONS(-DENABLE_PLUGIN_CgProgramManager -DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
|
||||||
|
set(OGRE_STATIC_PLUGINS ${OGRE_Plugin_CgProgramManager_LIBRARIES} ${OGRE_Plugin_OctreeSceneManager_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES} ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
|
||||||
|
ELSE(WIN32)
|
||||||
|
ADD_DEFINITIONS(-DENABLE_PLUGIN_CgProgramManager -DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
|
||||||
|
set(OGRE_STATIC_PLUGINS ${OGRE_Plugin_CgProgramManager_LIBRARIES} ${Cg_LIBRARIES} ${OGRE_Plugin_OctreeSceneManager_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
|
||||||
|
ENDIF(WIN32)
|
||||||
|
ENDIF(OGRE_STATIC)
|
||||||
add_executable(openmw
|
add_executable(openmw
|
||||||
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
|
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
|
||||||
${COMPONENT_FILES}
|
${COMPONENT_FILES}
|
||||||
|
@ -73,16 +83,22 @@ add_definitions(${SOUND_DEFINE})
|
||||||
target_link_libraries(openmw
|
target_link_libraries(openmw
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
${OGRE_Terrain_LIBRARY}
|
${OGRE_Terrain_LIBRARY}
|
||||||
|
${OGRE_STATIC_PLUGINS}
|
||||||
${OIS_LIBRARIES}
|
${OIS_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
${SOUND_INPUT_LIBRARY}
|
${SOUND_INPUT_LIBRARY}
|
||||||
${BULLET_LIBRARIES}
|
${BULLET_LIBRARIES}
|
||||||
|
${MYGUI_LIBRARIES}
|
||||||
|
${MYGUI_PLATFORM_LIBRARIES}
|
||||||
components
|
components
|
||||||
MyGUIEngine
|
|
||||||
MyGUIOgrePlatform
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(CARBON_FRAMEWORK Carbon)
|
find_library(CARBON_FRAMEWORK Carbon)
|
||||||
target_link_libraries(openmw ${CARBON_FRAMEWORK})
|
target_link_libraries(openmw ${CARBON_FRAMEWORK})
|
||||||
|
|
|
@ -60,7 +60,7 @@ void OMW::Engine::executeLocalScripts()
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext (mEnvironment,
|
MWScript::InterpreterContext interpreterContext (mEnvironment,
|
||||||
&script.second.getRefData().getLocals(), script.second);
|
&script.second.getRefData().getLocals(), script.second);
|
||||||
mScriptManager->run (script.first, interpreterContext);
|
mEnvironment.mScriptManager->run (script.first, interpreterContext);
|
||||||
|
|
||||||
if (mEnvironment.mWorld->hasCellChanged())
|
if (mEnvironment.mWorld->hasCellChanged())
|
||||||
break;
|
break;
|
||||||
|
@ -117,11 +117,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
if (mUseSound)
|
if (mUseSound)
|
||||||
{
|
|
||||||
mEnvironment.mSoundManager->playPlaylist();
|
|
||||||
|
|
||||||
mEnvironment.mSoundManager->update (evt.timeSinceLastFrame);
|
mEnvironment.mSoundManager->update (evt.timeSinceLastFrame);
|
||||||
}
|
|
||||||
|
|
||||||
// update GUI
|
// update GUI
|
||||||
Ogre::RenderWindow* window = mOgre->getWindow();
|
Ogre::RenderWindow* window = mOgre->getWindow();
|
||||||
|
@ -182,7 +178,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
, mCompileAll (false)
|
, mCompileAll (false)
|
||||||
, mReportFocus (false)
|
, mReportFocus (false)
|
||||||
, mFocusTDiff (0)
|
, mFocusTDiff (0)
|
||||||
, mScriptManager (0)
|
|
||||||
, mScriptContext (0)
|
, mScriptContext (0)
|
||||||
, mFSStrict (false)
|
, mFSStrict (false)
|
||||||
, mCfgMgr(configurationManager)
|
, mCfgMgr(configurationManager)
|
||||||
|
@ -199,7 +194,7 @@ OMW::Engine::~Engine()
|
||||||
delete mEnvironment.mMechanicsManager;
|
delete mEnvironment.mMechanicsManager;
|
||||||
delete mEnvironment.mDialogueManager;
|
delete mEnvironment.mDialogueManager;
|
||||||
delete mEnvironment.mJournal;
|
delete mEnvironment.mJournal;
|
||||||
delete mScriptManager;
|
delete mEnvironment.mScriptManager;
|
||||||
delete mScriptContext;
|
delete mScriptContext;
|
||||||
delete mOgre;
|
delete mOgre;
|
||||||
}
|
}
|
||||||
|
@ -338,28 +333,25 @@ void OMW::Engine::go()
|
||||||
mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"));
|
mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"));
|
||||||
|
|
||||||
// Create sound system
|
// Create sound system
|
||||||
mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(),
|
mEnvironment.mSoundManager = new MWSound::SoundManager(mUseSound, mEnvironment);
|
||||||
mOgre->getCamera(),
|
|
||||||
mDataDirs,
|
|
||||||
mUseSound, mFSStrict, mEnvironment);
|
|
||||||
|
|
||||||
// Create script system
|
// Create script system
|
||||||
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
|
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
|
||||||
mEnvironment);
|
mEnvironment);
|
||||||
mScriptContext->setExtensions (&mExtensions);
|
mScriptContext->setExtensions (&mExtensions);
|
||||||
|
|
||||||
mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts,
|
mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(),
|
||||||
*mScriptContext);
|
mVerboseScripts, *mScriptContext);
|
||||||
|
|
||||||
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
|
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
|
||||||
*mScriptManager);
|
*mEnvironment.mScriptManager);
|
||||||
|
|
||||||
// Create game mechanics system
|
// Create game mechanics system
|
||||||
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
|
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
|
||||||
|
|
||||||
// Create dialog system
|
// Create dialog system
|
||||||
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
|
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
|
||||||
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment);
|
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment,mExtensions);
|
||||||
|
|
||||||
// load cell
|
// load cell
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
|
@ -393,7 +385,7 @@ void OMW::Engine::go()
|
||||||
// scripts
|
// scripts
|
||||||
if (mCompileAll)
|
if (mCompileAll)
|
||||||
{
|
{
|
||||||
std::pair<int, int> result = mScriptManager->compileAll();
|
std::pair<int, int> result = mEnvironment.mScriptManager->compileAll();
|
||||||
|
|
||||||
if (result.first)
|
if (result.first)
|
||||||
std::cout
|
std::cout
|
||||||
|
@ -411,6 +403,9 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
void OMW::Engine::activate()
|
void OMW::Engine::activate()
|
||||||
{
|
{
|
||||||
|
if (mEnvironment.mWindowManager->getMode()!=MWGui::GM_Game)
|
||||||
|
return;
|
||||||
|
|
||||||
std::string handle = mEnvironment.mWorld->getFacedHandle();
|
std::string handle = mEnvironment.mWorld->getFacedHandle();
|
||||||
|
|
||||||
if (handle.empty())
|
if (handle.empty())
|
||||||
|
@ -435,7 +430,7 @@ void OMW::Engine::activate()
|
||||||
if (!script.empty())
|
if (!script.empty())
|
||||||
{
|
{
|
||||||
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
|
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
|
||||||
mScriptManager->run (script, interpreterContext);
|
mEnvironment.mScriptManager->run (script, interpreterContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!interpreterContext.hasActivationBeenHandled())
|
if (!interpreterContext.hasActivationBeenHandled())
|
||||||
|
|
|
@ -78,10 +78,9 @@ namespace OMW
|
||||||
std::string mFocusName;
|
std::string mFocusName;
|
||||||
|
|
||||||
MWWorld::Environment mEnvironment;
|
MWWorld::Environment mEnvironment;
|
||||||
MWScript::ScriptManager *mScriptManager;
|
|
||||||
Compiler::Extensions mExtensions;
|
Compiler::Extensions mExtensions;
|
||||||
Compiler::Context *mScriptContext;
|
Compiler::Context *mScriptContext;
|
||||||
|
|
||||||
|
|
||||||
Files::Collections mFileCollections;
|
Files::Collections mFileCollections;
|
||||||
bool mFSStrict;
|
bool mFSStrict;
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -53,6 +56,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -71,4 +76,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Apparatus).name(), instance);
|
registerClass (typeid (ESM::Apparatus).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Apparatus::getUpSoundId (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
return std::string("Item Apparatus Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Apparatus::getDownSoundId (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
return std::string("Item Apparatus Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,15 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -57,6 +60,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -116,7 +121,7 @@ namespace MWClass
|
||||||
return std::make_pair (slots, false);
|
return std::make_pair (slots, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Armor::getEuqipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
int Armor::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Armor>();
|
ptr.get<ESM::Armor>();
|
||||||
|
@ -142,13 +147,13 @@ namespace MWClass
|
||||||
if (typeGmst.empty())
|
if (typeGmst.empty())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->f;
|
float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->i;
|
||||||
|
|
||||||
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f<=
|
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f>=
|
||||||
ref->base->data.weight)
|
ref->base->data.weight)
|
||||||
return ESM::Skill::LightArmor;
|
return ESM::Skill::LightArmor;
|
||||||
|
|
||||||
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f<=
|
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f>=
|
||||||
ref->base->data.weight)
|
ref->base->data.weight)
|
||||||
return ESM::Skill::MediumArmor;
|
return ESM::Skill::MediumArmor;
|
||||||
|
|
||||||
|
@ -161,4 +166,26 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Armor).name(), instance);
|
registerClass (typeid (ESM::Armor).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Armor::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
int es = getEquipmentSkill(ptr, environment);
|
||||||
|
if (es == ESM::Skill::LightArmor)
|
||||||
|
return std::string("Item Armor Light Up");
|
||||||
|
else if (es == ESM::Skill::MediumArmor)
|
||||||
|
return std::string("Item Armor Medium Up");
|
||||||
|
else
|
||||||
|
return std::string("Item Armor Heavy Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Armor::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
int es = getEquipmentSkill(ptr, environment);
|
||||||
|
if (es == ESM::Skill::LightArmor)
|
||||||
|
return std::string("Item Armor Light Down");
|
||||||
|
else if (es == ESM::Skill::MediumArmor)
|
||||||
|
return std::string("Item Armor Medium Down");
|
||||||
|
else
|
||||||
|
return std::string("Item Armor Heavy Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,18 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr,
|
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Environment& environment) const;
|
const MWWorld::Environment& environment) const;
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -55,6 +58,8 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// TODO implement reading
|
// TODO implement reading
|
||||||
|
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -73,4 +78,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Book).name(), instance);
|
registerClass (typeid (ESM::Book).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Book::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Book Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Book::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Book Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -54,6 +57,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -106,7 +111,7 @@ namespace MWClass
|
||||||
return std::make_pair (slots, false);
|
return std::make_pair (slots, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Clothing::getEuqipmentSkill (const MWWorld::Ptr& ptr,
|
int Clothing::getEquipmentSkill (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Environment& environment) const
|
const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
@ -124,4 +129,28 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Clothing).name(), instance);
|
registerClass (typeid (ESM::Clothing).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Clothing::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
|
if (ref->base->data.type == 8)
|
||||||
|
{
|
||||||
|
return std::string("Item Ring Up");
|
||||||
|
}
|
||||||
|
return std::string("Item Clothes Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Clothing::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
|
if (ref->base->data.type == 8)
|
||||||
|
{
|
||||||
|
return std::string("Item Ring Down");
|
||||||
|
}
|
||||||
|
return std::string("Item Clothes Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,18 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr,
|
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Environment& environment) const;
|
const MWWorld::Environment& environment) const;
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// TODO check for key
|
// TODO check for key
|
||||||
std::cout << "Locked container" << std::endl;
|
std::cout << "Locked container" << std::endl;
|
||||||
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
|
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -100,7 +100,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// Trap activation goes here
|
// Trap activation goes here
|
||||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||||
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
|
environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0, false);
|
||||||
ptr.getCellRef().trap = "";
|
ptr.getCellRef().trap = "";
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace MWClass
|
||||||
// TODO check for key
|
// TODO check for key
|
||||||
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
||||||
std::cout << "Locked!" << std::endl;
|
std::cout << "Locked!" << std::endl;
|
||||||
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
|
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// Trap activation
|
// Trap activation
|
||||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||||
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
|
environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0, false);
|
||||||
ptr.getCellRef().trap = "";
|
ptr.getCellRef().trap = "";
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ namespace MWClass
|
||||||
if (environment.mWorld->getPlayer().getPlayer()==actor)
|
if (environment.mWorld->getPlayer().getPlayer()==actor)
|
||||||
{
|
{
|
||||||
// the player is using the door
|
// the player is using the door
|
||||||
|
// The reason this is not 3D is that it would get interrupted when you teleport
|
||||||
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
|
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest));
|
new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest));
|
||||||
|
@ -109,7 +110,7 @@ namespace MWClass
|
||||||
// TODO return action for rotating the door
|
// TODO return action for rotating the door
|
||||||
|
|
||||||
// This is a little pointless, but helps with testing
|
// This is a little pointless, but helps with testing
|
||||||
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
|
environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0, false);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -51,6 +54,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -69,4 +74,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Ingredient).name(), instance);
|
registerClass (typeid (ESM::Ingredient).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Ingredient::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Ingredient Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Ingredient::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Ingredient Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ namespace MWClass
|
||||||
if (!(ref->base->data.flags & ESM::Light::Carry))
|
if (!(ref->base->data.flags & ESM::Light::Carry))
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
|
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -114,4 +116,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Light).name(), instance);
|
registerClass (typeid (ESM::Light).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Light::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Misc Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Light::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Misc Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,12 @@ namespace MWClass
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -55,6 +58,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -82,4 +87,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Tool).name(), instance);
|
registerClass (typeid (ESM::Tool).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Lockpick Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lockpick::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Lockpick Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,12 @@ namespace MWClass
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -53,6 +56,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -71,4 +76,28 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Miscellaneous).name(), instance);
|
registerClass (typeid (ESM::Miscellaneous).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
|
if (ref->base->name =="Gold")
|
||||||
|
{
|
||||||
|
return std::string("Item Gold Up");
|
||||||
|
}
|
||||||
|
return std::string("Item Misc Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
|
if (ref->base->name =="Gold")
|
||||||
|
{
|
||||||
|
return std::string("Item Gold Down");
|
||||||
|
}
|
||||||
|
return std::string("Item Misc Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -53,6 +56,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -71,4 +76,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Potion).name(), instance);
|
registerClass (typeid (ESM::Potion).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Potion::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Potion Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Potion::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Potion Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -54,6 +57,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -81,4 +86,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Probe).name(), instance);
|
registerClass (typeid (ESM::Probe).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Probe::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Probe Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Probe::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Probe Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,12 @@ namespace MWClass
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -53,6 +56,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -71,4 +76,14 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Repair).name(), instance);
|
registerClass (typeid (ESM::Repair).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Repair::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Repair Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Repair::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
return std::string("Item Repair Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace MWClass
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
|
@ -54,6 +57,8 @@ namespace MWClass
|
||||||
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
}
|
}
|
||||||
|
@ -103,7 +108,7 @@ namespace MWClass
|
||||||
return std::make_pair (slots, stack);
|
return std::make_pair (slots, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Weapon::getEuqipmentSkill (const MWWorld::Ptr& ptr,
|
int Weapon::getEquipmentSkill (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Environment& environment) const
|
const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
@ -140,4 +145,96 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::Weapon).name(), instance);
|
registerClass (typeid (ESM::Weapon).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Weapon::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
|
int type = ref->base->data.type;
|
||||||
|
// Ammo
|
||||||
|
if (type == 12 || type == 13)
|
||||||
|
{
|
||||||
|
return std::string("Item Ammo Up");
|
||||||
|
}
|
||||||
|
// Bow
|
||||||
|
if (type == 9)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Bow Up");
|
||||||
|
}
|
||||||
|
// Crossbow
|
||||||
|
if (type == 10)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Crossbow Up");
|
||||||
|
}
|
||||||
|
// Longblades, One hand and Two
|
||||||
|
if (type == 1 || type == 2)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Longblade Up");
|
||||||
|
}
|
||||||
|
// Shortblade and thrown weapons
|
||||||
|
// thrown weapons may not be entirely correct
|
||||||
|
if (type == 0 || type == 11)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Shortblade Up");
|
||||||
|
}
|
||||||
|
// Spear
|
||||||
|
if (type == 6)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Spear Up");
|
||||||
|
}
|
||||||
|
// Blunts and Axes
|
||||||
|
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Blunt Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string("Item Misc Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Weapon::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
|
int type = ref->base->data.type;
|
||||||
|
// Ammo
|
||||||
|
if (type == 12 || type == 13)
|
||||||
|
{
|
||||||
|
return std::string("Item Ammo Down");
|
||||||
|
}
|
||||||
|
// Bow
|
||||||
|
if (type == 9)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Bow Down");
|
||||||
|
}
|
||||||
|
// Crossbow
|
||||||
|
if (type == 10)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Crossbow Down");
|
||||||
|
}
|
||||||
|
// Longblades, One hand and Two
|
||||||
|
if (type == 1 || type == 2)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Longblade Down");
|
||||||
|
}
|
||||||
|
// Shortblade and thrown weapons
|
||||||
|
// thrown weapons may not be entirely correct
|
||||||
|
if (type == 0 || type == 11)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Shortblade Down");
|
||||||
|
}
|
||||||
|
// Spear
|
||||||
|
if (type == 6)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Spear Down");
|
||||||
|
}
|
||||||
|
// Blunts and Axes
|
||||||
|
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
|
||||||
|
{
|
||||||
|
return std::string("Item Weapon Blunt Down");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string("Item Misc Down");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,18 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
virtual int getEuqipmentSkill (const MWWorld::Ptr& ptr,
|
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Environment& environment) const;
|
const MWWorld::Environment& environment) const;
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the pick up sound Id
|
||||||
|
|
||||||
|
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
///< Return the put down sound Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,36 @@
|
||||||
|
|
||||||
#include <components/esm_store/store.hpp>
|
#include <components/esm_store/store.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
#include "../mwworld/refdata.hpp"
|
#include "../mwworld/refdata.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
#include "../mwinput/inputmanager.hpp"
|
#include "../mwinput/inputmanager.hpp"
|
||||||
|
#include "../mwgui/dialogue.hpp"
|
||||||
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
|
||||||
|
#include "journal.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../mwscript/extensions.hpp"
|
||||||
|
#include "../mwscript/scriptmanager.hpp"
|
||||||
|
|
||||||
|
#include <components/compiler/exception.hpp>
|
||||||
|
#include <components/compiler/errorhandler.hpp>
|
||||||
|
#include <components/compiler/scanner.hpp>
|
||||||
|
#include <components/compiler/locals.hpp>
|
||||||
|
#include <components/compiler/output.hpp>
|
||||||
|
#include <components/interpreter/interpreter.hpp>
|
||||||
|
|
||||||
|
#include "../mwscript/compilercontext.hpp"
|
||||||
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
|
#include <components/compiler/scriptparser.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::string toLower (const std::string& name)
|
std::string toLower (const std::string& name)
|
||||||
|
@ -31,17 +51,18 @@ namespace
|
||||||
return lowerCase;
|
return lowerCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
bool selectCompare (char comp, T1 value1, T2 value2)
|
bool selectCompare (char comp, T1 value1, T2 value2)
|
||||||
{
|
{
|
||||||
switch (comp)
|
switch (comp)
|
||||||
{
|
{
|
||||||
case '0': return value1==value2;
|
case '0': return value1==value2;
|
||||||
case '1': return value1!=value2;
|
case '1': return value1!=value2;
|
||||||
case '2': return value1>value2;
|
case '2': return value1>value2;
|
||||||
case '3': return value1>=value2;
|
case '3': return value1>=value2;
|
||||||
case '4': return value1<value2;
|
case '4': return value1<value2;
|
||||||
case '5': return value1<=value2;
|
case '5': return value1<=value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error ("unknown compare type in dialogue info select");
|
throw std::runtime_error ("unknown compare type in dialogue info select");
|
||||||
|
@ -87,26 +108,26 @@ namespace
|
||||||
{
|
{
|
||||||
switch (world.getGlobalVariableType (name))
|
switch (world.getGlobalVariableType (name))
|
||||||
{
|
{
|
||||||
case 's':
|
case 's':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
|
||||||
|
|
||||||
case ' ':
|
case ' ':
|
||||||
|
|
||||||
world.getGlobalVariable (name); // trigger exception
|
world.getGlobalVariable (name); // trigger exception
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
throw std::runtime_error ("unsupported gobal variable type");
|
throw std::runtime_error ("unsupported gobal variable type");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -115,6 +136,125 @@ namespace
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//helper function
|
||||||
|
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
|
||||||
|
{
|
||||||
|
return toLower(str).find(toLower(substr),pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
||||||
|
iter != info.selects.end(); ++iter)
|
||||||
|
{
|
||||||
|
ESM::DialInfo::SelectStruct select = *iter;
|
||||||
|
char type = select.selectRule[1];
|
||||||
|
if(type == '1')
|
||||||
|
{
|
||||||
|
char comp = select.selectRule[4];
|
||||||
|
std::string name = select.selectRule.substr (5);
|
||||||
|
std::string function = select.selectRule.substr(2,2);
|
||||||
|
|
||||||
|
int ifunction;
|
||||||
|
std::istringstream iss(function);
|
||||||
|
iss >> ifunction;
|
||||||
|
switch(ifunction)
|
||||||
|
{
|
||||||
|
case 39://PC Expelled
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 40://PC Common Disease
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 41://PC Blight Disease
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 43://PC Crime level
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 46://Same faction
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48://Detected
|
||||||
|
if(!selectCompare<int,int>(comp,1,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 49://Alarmed
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 50://choice
|
||||||
|
|
||||||
|
if(choice)
|
||||||
|
{
|
||||||
|
if(!selectCompare<int,int>(comp,mChoice,select.i)) return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 60://PC Vampire
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 61://Level
|
||||||
|
if(!selectCompare<int,int>(comp,1,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 62://Attacked
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 63://Talked to PC
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 64://PC Health
|
||||||
|
if(!selectCompare<int,int>(comp,50,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 65://Creature target
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 66://Friend hit
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 67://Fight
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 68://Hello????
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 69://Alarm
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 70://Flee
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 71://Should Attack
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
|
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
|
||||||
const ESM::DialInfo::SelectStruct& select) const
|
const ESM::DialInfo::SelectStruct& select) const
|
||||||
{
|
{
|
||||||
|
@ -124,58 +264,173 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
char comp = select.selectRule[4];
|
char comp = select.selectRule[4];
|
||||||
std::string name = select.selectRule.substr (5);
|
std::string name = select.selectRule.substr (5);
|
||||||
|
std::string function = select.selectRule.substr(1,2);
|
||||||
// TODO types 4, 5, 6, 7, 8, 9, A, B, C
|
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case '1': // function
|
case '1': // function
|
||||||
|
|
||||||
return false; // TODO implement functions
|
return true; // TODO implement functions
|
||||||
|
|
||||||
case '2': // global
|
case '2': // global
|
||||||
|
|
||||||
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
||||||
select.type==ESM::VT_Long)
|
select.type==ESM::VT_Long)
|
||||||
{
|
{
|
||||||
if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
|
if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (select.type==ESM::VT_Float)
|
else if (select.type==ESM::VT_Float)
|
||||||
{
|
{
|
||||||
if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
|
if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"unsupported variable type in dialogue info select");
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case '3': // local
|
case '3': // local
|
||||||
|
|
||||||
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
||||||
select.type==ESM::VT_Long)
|
select.type==ESM::VT_Long)
|
||||||
{
|
{
|
||||||
if (!checkLocal (comp, toLower (name), select.i, actor,
|
if (!checkLocal (comp, toLower (name), select.i, actor,
|
||||||
mEnvironment.mWorld->getStore()))
|
mEnvironment.mWorld->getStore()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (select.type==ESM::VT_Float)
|
else if (select.type==ESM::VT_Float)
|
||||||
{
|
{
|
||||||
if (!checkLocal (comp, toLower (name), select.f, actor,
|
if (!checkLocal (comp, toLower (name), select.f, actor,
|
||||||
mEnvironment.mWorld->getStore()))
|
mEnvironment.mWorld->getStore()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"unsupported variable type in dialogue info select");
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
case '4'://journal
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
if(!selectCompare<int,int>(comp,mEnvironment.mJournal->getJournalIndex(toLower(name)),select.i)) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
|
return true;
|
||||||
|
|
||||||
|
case '5'://item
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = mEnvironment.mWorld->getPlayer().getPlayer();
|
||||||
|
MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player);
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
|
||||||
|
if (iter->getCellRef().refID==name)
|
||||||
|
sum += iter->getRefData().getCount();
|
||||||
|
if(!selectCompare<int,int>(comp,sum,select.i)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
case '6'://dead
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
|
||||||
|
case '7':// not ID
|
||||||
|
if(select.type==ESM::VT_String ||select.type==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string
|
||||||
|
{
|
||||||
|
int isID = int(toLower(name)==toLower(MWWorld::Class::get (actor).getId (actor)));
|
||||||
|
if (selectCompare<int,int>(comp,!isID,select.i)) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case '8':// not faction
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isFaction = int(toLower(npc->base->faction) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(comp,!isFaction,select.i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case '9':// not class
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isClass = int(toLower(npc->base->cls) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(comp,!isClass,select.i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 'A'://not Race
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isRace = int(toLower(npc->base->race) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(comp,!isRace,select.i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 'B'://not Cell
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
int isCell = int(toLower(actor.getCell()->cell->name) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(comp,!isCell,select.i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 'C'://not local
|
||||||
|
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
||||||
|
select.type==ESM::VT_Long)
|
||||||
|
{
|
||||||
|
if (checkLocal (comp, toLower (name), select.i, actor,
|
||||||
|
mEnvironment.mWorld->getStore()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (select.type==ESM::VT_Float)
|
||||||
|
{
|
||||||
|
if (checkLocal (comp, toLower (name), select.f, actor,
|
||||||
|
mEnvironment.mWorld->getStore()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +444,10 @@ namespace MWDialogue
|
||||||
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
|
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
//PC Faction
|
||||||
|
if(!info.pcFaction.empty()) return false;
|
||||||
|
|
||||||
|
//NPC race
|
||||||
if (!info.race.empty())
|
if (!info.race.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -200,6 +459,7 @@ namespace MWDialogue
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NPC class
|
||||||
if (!info.clas.empty())
|
if (!info.clas.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -211,6 +471,7 @@ namespace MWDialogue
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NPC faction
|
||||||
if (!info.npcFaction.empty())
|
if (!info.npcFaction.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -220,66 +481,320 @@ namespace MWDialogue
|
||||||
|
|
||||||
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
|
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
//check NPC rank
|
||||||
|
if(cellRef->base->npdt52.gold != -10)
|
||||||
|
{
|
||||||
|
if(cellRef->base->npdt52.rank < info.data.rank) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(cellRef->base->npdt12.rank < info.data.rank) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check player faction
|
// TODO check player faction
|
||||||
|
|
||||||
|
//check gender
|
||||||
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
if(npc->base->flags&npc->base->Female)
|
||||||
|
{
|
||||||
|
if(static_cast<int> (info.data.gender)==0) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(static_cast<int> (info.data.gender)==1) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// check cell
|
// check cell
|
||||||
if (!info.cell.empty())
|
if (!info.cell.empty())
|
||||||
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
|
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO check DATAstruct
|
// TODO check DATAstruct
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
||||||
iter != info.selects.end(); ++iter)
|
iter != info.selects.end(); ++iter)
|
||||||
if (!isMatching (actor, *iter))
|
if (!isMatching (actor, *iter))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::cout
|
|
||||||
<< "unchecked entries:" << std::endl
|
|
||||||
<< " player faction: " << info.pcFaction << std::endl
|
|
||||||
<< " disposition: " << info.data.disposition << std::endl
|
|
||||||
<< " NPC rank: " << static_cast<int> (info.data.rank) << std::endl
|
|
||||||
<< " gender: " << static_cast<int> (info.data.gender) << std::endl
|
|
||||||
<< " PC rank: " << static_cast<int> (info.data.PCrank) << std::endl;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {}
|
DialogueManager::DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions) :
|
||||||
|
mEnvironment (environment),mCompilerContext (MWScript::CompilerContext::Type_Dialgoue, environment),
|
||||||
|
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
|
||||||
|
{
|
||||||
|
mChoice = -1;
|
||||||
|
mIsInChoice = false;
|
||||||
|
mCompilerContext.setExtensions (&extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::addTopic(std::string topic)
|
||||||
|
{
|
||||||
|
knownTopics[toLower(topic)] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::parseText(std::string text)
|
||||||
|
{
|
||||||
|
std::list<std::string>::iterator it;
|
||||||
|
for(it = actorKnownTopics.begin();it != actorKnownTopics.end();it++)
|
||||||
|
{
|
||||||
|
size_t pos = find_str_ci(text,*it,0);
|
||||||
|
if(pos !=std::string::npos)
|
||||||
|
{
|
||||||
|
if(pos==0)
|
||||||
|
{
|
||||||
|
knownTopics[*it] = true;
|
||||||
|
}
|
||||||
|
else if(text.substr(pos -1,1) == " ")
|
||||||
|
{
|
||||||
|
knownTopics[*it] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateTopics();
|
||||||
|
}
|
||||||
|
|
||||||
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl;
|
mChoice = -1;
|
||||||
|
mIsInChoice = false;
|
||||||
|
|
||||||
const ESM::Dialogue *dialogue = mEnvironment.mWorld->getStore().dialogs.find ("hello");
|
mActor = actor;
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
mDialogueMap.clear();
|
||||||
iter!=dialogue->mInfo.end(); ++iter)
|
actorKnownTopics.clear();
|
||||||
|
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
|
||||||
{
|
{
|
||||||
if (isMatching (actor, *iter))
|
mDialogueMap[it->first] = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
//initialise the GUI
|
||||||
|
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
win->startDialogue(MWWorld::Class::get (actor).getName (actor));
|
||||||
|
|
||||||
|
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
|
||||||
|
updateTopics();
|
||||||
|
|
||||||
|
//greeting
|
||||||
|
bool greetingFound = false;
|
||||||
|
//ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = it->second;
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Greeting)
|
||||||
{
|
{
|
||||||
// start dialogue
|
if (greetingFound) break;
|
||||||
std::cout << "found matching info record" << std::endl;
|
for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
|
||||||
|
iter!=it->second.mInfo.end(); ++iter)
|
||||||
std::cout << "response: " << iter->response << std::endl;
|
|
||||||
|
|
||||||
if (!iter->sound.empty())
|
|
||||||
{
|
{
|
||||||
// TODO play sound
|
if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true))
|
||||||
}
|
{
|
||||||
|
if (!iter->sound.empty())
|
||||||
|
{
|
||||||
|
// TODO play sound
|
||||||
|
}
|
||||||
|
|
||||||
if (!iter->resultScript.empty())
|
std::string text = iter->response;
|
||||||
{
|
parseText(text);
|
||||||
std::cout << "script: " << iter->resultScript << std::endl;
|
win->addText(iter->response);
|
||||||
// TODO execute script
|
executeScript(iter->resultScript);
|
||||||
|
greetingFound = true;
|
||||||
|
mLastTopic = it->first;
|
||||||
|
mLastDialogue = *iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mErrorHandler.reset();
|
||||||
|
|
||||||
|
std::istringstream input (cmd + "\n");
|
||||||
|
|
||||||
|
Compiler::Scanner scanner (mErrorHandler, input, mCompilerContext.getExtensions());
|
||||||
|
|
||||||
|
Compiler::Locals locals;
|
||||||
|
|
||||||
|
std::string actorScript = MWWorld::Class::get (mActor).getScript (mActor);
|
||||||
|
|
||||||
|
if (!actorScript.empty())
|
||||||
|
{
|
||||||
|
// grab local variables from actor's script, if available.
|
||||||
|
locals = mEnvironment.mScriptManager->getLocals (actorScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false);
|
||||||
|
|
||||||
|
scanner.scan (parser);
|
||||||
|
if(mErrorHandler.isGood())
|
||||||
|
{
|
||||||
|
parser.getCode(code);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (const Compiler::SourceException& error)
|
||||||
|
{
|
||||||
|
// error has already been reported via error handler
|
||||||
|
}
|
||||||
|
catch (const std::exception& error)
|
||||||
|
{
|
||||||
|
printError (std::string ("An exception has been thrown: ") + error.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::executeScript(std::string script)
|
||||||
|
{
|
||||||
|
std::vector<Interpreter::Type_Code> code;
|
||||||
|
if(compile(script,code))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext interpreterContext(mEnvironment,&mActor.getRefData().getLocals(),mActor);
|
||||||
|
Interpreter::Interpreter interpreter;
|
||||||
|
MWScript::installOpcodes (interpreter);
|
||||||
|
interpreter.run (&code[0], code.size(), interpreterContext);
|
||||||
|
}
|
||||||
|
catch (const std::exception& error)
|
||||||
|
{
|
||||||
|
printError (std::string ("An exception has been thrown: ") + error.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::updateTopics()
|
||||||
|
{
|
||||||
|
std::list<std::string> keywordList;
|
||||||
|
int choice = mChoice;
|
||||||
|
mChoice = -1;
|
||||||
|
actorKnownTopics.clear();
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = it->second;
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Topic)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
|
||||||
|
iter!=it->second.mInfo.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
|
||||||
|
{
|
||||||
|
actorKnownTopics.push_back(it->first);
|
||||||
|
//does the player know the topic?
|
||||||
|
if(knownTopics.find(toLower(it->first)) != knownTopics.end())
|
||||||
|
{
|
||||||
|
keywordList.push_back(it->first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
win->setKeywords(keywordList);
|
||||||
|
mChoice = choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::keywordSelected(std::string keyword)
|
||||||
|
{
|
||||||
|
if(!mIsInChoice)
|
||||||
|
{
|
||||||
|
if(mDialogueMap.find(keyword) != mDialogueMap.end())
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = mDialogueMap[keyword];
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Topic)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::const_iterator iter = ndialogue.mInfo.begin();
|
||||||
|
iter!=ndialogue.mInfo.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
|
||||||
|
{
|
||||||
|
std::string text = iter->response;
|
||||||
|
std::string script = iter->resultScript;
|
||||||
|
|
||||||
|
parseText(text);
|
||||||
|
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
win->addTitle(keyword);
|
||||||
|
win->addText(iter->response);
|
||||||
|
|
||||||
|
executeScript(script);
|
||||||
|
|
||||||
|
mLastTopic = keyword;
|
||||||
|
mLastDialogue = *iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTopics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::goodbyeSelected()
|
||||||
|
{
|
||||||
|
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Game);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::questionAnswered(std::string answere)
|
||||||
|
{
|
||||||
|
if(mChoiceMap.find(answere) != mChoiceMap.end())
|
||||||
|
{
|
||||||
|
mChoice = mChoiceMap[answere];
|
||||||
|
|
||||||
|
std::vector<ESM::DialInfo>::const_iterator iter;
|
||||||
|
if(mDialogueMap.find(mLastTopic) != mDialogueMap.end())
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = mDialogueMap[mLastTopic];
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Topic)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::const_iterator iter = ndialogue.mInfo.begin();
|
||||||
|
iter!=ndialogue.mInfo.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
|
||||||
|
{
|
||||||
|
mChoiceMap.clear();
|
||||||
|
mChoice = -1;
|
||||||
|
mIsInChoice = false;
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
std::string text = iter->response;
|
||||||
|
parseText(text);
|
||||||
|
win->addText(text);
|
||||||
|
executeScript(iter->resultScript);
|
||||||
|
mLastTopic = mLastTopic;
|
||||||
|
mLastDialogue = *iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateTopics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::printError(std::string error)
|
||||||
|
{
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
win->addText(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::askQuestion(std::string question, int choice)
|
||||||
|
{
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
win->askQuestion(question);
|
||||||
|
mChoiceMap[question] = choice;
|
||||||
|
mIsInChoice = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,13 @@
|
||||||
|
|
||||||
#include <components/esm/loadinfo.hpp>
|
#include <components/esm/loadinfo.hpp>
|
||||||
|
|
||||||
|
#include <components/compiler/streamerrorhandler.hpp>
|
||||||
|
#include "../mwscript/compilercontext.hpp"
|
||||||
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
|
#include <components/compiler/output.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -20,12 +26,48 @@ namespace MWDialogue
|
||||||
|
|
||||||
bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const;
|
bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const;
|
||||||
|
|
||||||
|
bool functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice);
|
||||||
|
|
||||||
|
void parseText(std::string text);
|
||||||
|
|
||||||
|
void updateTopics();
|
||||||
|
|
||||||
|
std::map<std::string,ESM::Dialogue> mDialogueMap;
|
||||||
|
std::map<std::string,bool> knownTopics;// Those are the topics the player knows.
|
||||||
|
std::list<std::string> actorKnownTopics;
|
||||||
|
|
||||||
|
MWScript::CompilerContext mCompilerContext;
|
||||||
|
std::ostream mErrorStream;
|
||||||
|
Compiler::StreamErrorHandler mErrorHandler;
|
||||||
|
|
||||||
|
|
||||||
|
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
||||||
|
void executeScript(std::string script);
|
||||||
|
MWWorld::Ptr mActor;
|
||||||
|
|
||||||
|
void printError(std::string error);
|
||||||
|
|
||||||
|
int mChoice;
|
||||||
|
std::map<std::string,int> mChoiceMap;
|
||||||
|
std::string mLastTopic;
|
||||||
|
ESM::DialInfo mLastDialogue;
|
||||||
|
bool mIsInChoice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DialogueManager (MWWorld::Environment& environment);
|
DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions);
|
||||||
|
|
||||||
void startDialogue (const MWWorld::Ptr& actor);
|
void startDialogue (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
void addTopic(std::string topic);
|
||||||
|
|
||||||
|
void askQuestion(std::string question,int choice);
|
||||||
|
|
||||||
|
//calbacks for the GUI
|
||||||
|
void keywordSelected(std::string keyword);
|
||||||
|
void goodbyeSelected();
|
||||||
|
void questionAnswered(std::string answere);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
#include "../mwgui/messagebox.hpp"
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
Quest& Journal::getQuest (const std::string& id)
|
Quest& Journal::getQuest (const std::string& id)
|
||||||
|
@ -34,6 +37,10 @@ namespace MWDialogue
|
||||||
Quest& quest = getQuest (id);
|
Quest& quest = getQuest (id);
|
||||||
|
|
||||||
quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here
|
quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here
|
||||||
|
|
||||||
|
std::vector<std::string> empty;
|
||||||
|
std::string notification = "Your Journal has been updated.";
|
||||||
|
mEnvironment.mWindowManager->messageBox (notification, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::setJournalIndex (const std::string& id, int index)
|
void Journal::setJournalIndex (const std::string& id, int index)
|
||||||
|
@ -60,7 +67,12 @@ namespace MWDialogue
|
||||||
|
|
||||||
int Journal::getJournalIndex (const std::string& id) const
|
int Journal::getJournalIndex (const std::string& id) const
|
||||||
{
|
{
|
||||||
return 0;
|
TQuestContainer::const_iterator iter = mQuests.find (id);
|
||||||
|
|
||||||
|
if (iter==mQuests.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return iter->second.getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Journal::TEntryIter Journal::begin() const
|
Journal::TEntryIter Journal::begin() const
|
||||||
|
|
|
@ -21,18 +21,18 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager)
|
||||||
|
|
||||||
getWidget(birthList, "BirthsignList");
|
getWidget(birthList, "BirthsignList");
|
||||||
birthList->setScrollVisible(true);
|
birthList->setScrollVisible(true);
|
||||||
birthList->eventListSelectAccept = MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
birthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
birthList->eventListMouseItemActivate = MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
birthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
birthList->eventListChangePosition = MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
birthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
|
||||||
|
|
||||||
updateBirths();
|
updateBirths();
|
||||||
updateSpells();
|
updateSpells();
|
||||||
|
@ -100,7 +100,7 @@ void BirthDialog::onBackClicked(MyGUI::Widget* _sender)
|
||||||
eventBack();
|
eventBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BirthDialog::onSelectBirth(MyGUI::List* _sender, size_t _index)
|
void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
@ -188,7 +188,7 @@ void BirthDialog::updateSpells()
|
||||||
{
|
{
|
||||||
if (!categories[category].spells.empty())
|
if (!categories[category].spells.empty())
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr label = spellArea->createWidget<MyGUI::StaticText>("SandBrightText", coord, MyGUI::Align::Default, std::string("Label"));
|
MyGUI::TextBox* label = spellArea->createWidget<MyGUI::TextBox>("SandBrightText", coord, MyGUI::Align::Default, std::string("Label"));
|
||||||
label->setCaption(mWindowManager.getGameSettingString(categories[category].label, ""));
|
label->setCaption(mWindowManager.getGameSettingString(categories[category].label, ""));
|
||||||
spellItems.push_back(label);
|
spellItems.push_back(label);
|
||||||
coord.top += lineHeight;
|
coord.top += lineHeight;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -40,7 +40,7 @@ namespace MWGui
|
||||||
EventHandle_Void eventBack;
|
EventHandle_Void eventBack;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectBirth(MyGUI::List* _sender, size_t _index);
|
void onSelectBirth(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
@ -49,9 +49,9 @@ namespace MWGui
|
||||||
void updateBirths();
|
void updateBirths();
|
||||||
void updateSpells();
|
void updateSpells();
|
||||||
|
|
||||||
MyGUI::ListPtr birthList;
|
MyGUI::ListBox* birthList;
|
||||||
MyGUI::WidgetPtr spellArea;
|
MyGUI::WidgetPtr spellArea;
|
||||||
MyGUI::StaticImagePtr birthImage;
|
MyGUI::ImageBox* birthImage;
|
||||||
std::vector<MyGUI::WidgetPtr> spellItems;
|
std::vector<MyGUI::WidgetPtr> spellItems;
|
||||||
|
|
||||||
std::string currentBirthId;
|
std::string currentBirthId;
|
||||||
|
|
|
@ -121,7 +121,7 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name"));
|
mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name"));
|
||||||
mNameDialog->setTextInput(mPlayerName);
|
mNameDialog->setTextInput(mPlayerName);
|
||||||
mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
|
mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
|
||||||
mNameDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
|
mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
|
||||||
mNameDialog->open();
|
mNameDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -131,8 +131,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mRaceDialog = new RaceDialog(*mWM);
|
mRaceDialog = new RaceDialog(*mWM);
|
||||||
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
|
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
|
||||||
mRaceDialog->setRaceId(mPlayerRaceId);
|
mRaceDialog->setRaceId(mPlayerRaceId);
|
||||||
mRaceDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
|
mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
|
||||||
mRaceDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
|
mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
|
||||||
mRaceDialog->open();
|
mRaceDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
if (mClassChoiceDialog)
|
if (mClassChoiceDialog)
|
||||||
mWM->removeDialog(mClassChoiceDialog);
|
mWM->removeDialog(mClassChoiceDialog);
|
||||||
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
|
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
|
||||||
mClassChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
|
mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
|
||||||
mClassChoiceDialog->open();
|
mClassChoiceDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -150,8 +150,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mPickClassDialog = new PickClassDialog(*mWM);
|
mPickClassDialog = new PickClassDialog(*mWM);
|
||||||
mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
||||||
mPickClassDialog->setClassId(mPlayerClass.name);
|
mPickClassDialog->setClassId(mPlayerClass.name);
|
||||||
mPickClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
|
mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
|
||||||
mPickClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
|
mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
|
||||||
mPickClassDialog->open();
|
mPickClassDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -161,8 +161,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mBirthSignDialog = new BirthDialog(*mWM);
|
mBirthSignDialog = new BirthDialog(*mWM);
|
||||||
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
|
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
|
||||||
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
|
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
|
||||||
mBirthSignDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
|
mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
|
||||||
mBirthSignDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
|
mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
|
||||||
mBirthSignDialog->open();
|
mBirthSignDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -170,8 +170,8 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
if (mCreateClassDialog)
|
if (mCreateClassDialog)
|
||||||
mWM->removeDialog(mCreateClassDialog);
|
mWM->removeDialog(mCreateClassDialog);
|
||||||
mCreateClassDialog = new CreateClassDialog(*mWM);
|
mCreateClassDialog = new CreateClassDialog(*mWM);
|
||||||
mCreateClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||||
mCreateClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||||
mCreateClassDialog->open();
|
mCreateClassDialog->open();
|
||||||
break;
|
break;
|
||||||
case GM_ClassGenerate:
|
case GM_ClassGenerate:
|
||||||
|
@ -212,9 +212,9 @@ void CharacterCreation::spawnDialog(const char id)
|
||||||
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
|
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
|
||||||
}
|
}
|
||||||
|
|
||||||
mReviewDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
|
mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
|
||||||
mReviewDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
||||||
mReviewDialog->eventActivateDialog = MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
|
mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
|
||||||
mReviewDialog->open();
|
mReviewDialog->open();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -559,8 +559,8 @@ void CharacterCreation::showClassQuestionDialog()
|
||||||
mWM->removeDialog(mGenerateClassResultDialog);
|
mWM->removeDialog(mGenerateClassResultDialog);
|
||||||
mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM);
|
mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM);
|
||||||
mGenerateClassResultDialog->setClassId(mGenerateClass);
|
mGenerateClassResultDialog->setClassId(mGenerateClass);
|
||||||
mGenerateClassResultDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
|
mGenerateClassResultDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
|
||||||
mGenerateClassResultDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
|
mGenerateClassResultDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
|
||||||
mGenerateClassResultDialog->open();
|
mGenerateClassResultDialog->open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -581,7 +581,7 @@ void CharacterCreation::showClassQuestionDialog()
|
||||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[1]);
|
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[1]);
|
||||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]);
|
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]);
|
||||||
mGenerateClassQuestionDialog->setButtons(buttons);
|
mGenerateClassQuestionDialog->setButtons(buttons);
|
||||||
mGenerateClassQuestionDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
||||||
mGenerateClassQuestionDialog->open();
|
mGenerateClassQuestionDialog->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,11 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateClassResultDialog::open()
|
void GenerateClassResultDialog::open()
|
||||||
|
@ -96,20 +96,20 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager)
|
||||||
|
|
||||||
getWidget(classList, "ClassList");
|
getWidget(classList, "ClassList");
|
||||||
classList->setScrollVisible(true);
|
classList->setScrollVisible(true);
|
||||||
classList->eventListSelectAccept = MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
classList->eventListSelectAccept += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
||||||
classList->eventListMouseItemActivate = MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
classList->eventListMouseItemActivate += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
||||||
classList->eventListChangePosition = MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
classList->eventListChangePosition += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
||||||
|
|
||||||
getWidget(classImage, "ClassImage");
|
getWidget(classImage, "ClassImage");
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
|
||||||
|
|
||||||
updateClasses();
|
updateClasses();
|
||||||
updateStats();
|
updateStats();
|
||||||
|
@ -177,7 +177,7 @@ void PickClassDialog::onBackClicked(MyGUI::Widget* _sender)
|
||||||
eventBack();
|
eventBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PickClassDialog::onSelectClass(MyGUI::List* _sender, size_t _index)
|
void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
@ -248,7 +248,7 @@ void PickClassDialog::updateStats()
|
||||||
|
|
||||||
/* InfoBoxDialog */
|
/* InfoBoxDialog */
|
||||||
|
|
||||||
void InfoBoxDialog::fitToText(MyGUI::StaticTextPtr widget)
|
void InfoBoxDialog::fitToText(MyGUI::TextBox* widget)
|
||||||
{
|
{
|
||||||
MyGUI::IntCoord inner = widget->getTextRegion();
|
MyGUI::IntCoord inner = widget->getTextRegion();
|
||||||
MyGUI::IntCoord outer = widget->getCoord();
|
MyGUI::IntCoord outer = widget->getCoord();
|
||||||
|
@ -267,7 +267,7 @@ void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin)
|
||||||
for (unsigned i = 0; i < count; ++i)
|
for (unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::WidgetPtr child = widget->getChildAt(i);
|
MyGUI::WidgetPtr child = widget->getChildAt(i);
|
||||||
if (!child->isVisible())
|
if (!child->getVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
child->setPosition(child->getLeft(), pos);
|
child->setPosition(child->getLeft(), pos);
|
||||||
|
@ -322,7 +322,7 @@ void InfoBoxDialog::setButtons(ButtonList &buttons)
|
||||||
button->getSubWidgetText()->setWordWrap(true);
|
button->getSubWidgetText()->setWordWrap(true);
|
||||||
button->setCaption(text);
|
button->setCaption(text);
|
||||||
fitToText(button);
|
fitToText(button);
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &InfoBoxDialog::onButtonClicked);
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &InfoBoxDialog::onButtonClicked);
|
||||||
coord.top += button->getHeight();
|
coord.top += button->getHeight();
|
||||||
this->buttons.push_back(button);
|
this->buttons.push_back(button);
|
||||||
}
|
}
|
||||||
|
@ -389,15 +389,15 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
|
||||||
setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization"));
|
setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization"));
|
||||||
getWidget(specializationName, "SpecializationName");
|
getWidget(specializationName, "SpecializationName");
|
||||||
specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""));
|
specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""));
|
||||||
specializationName->eventMouseButtonClick = MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked);
|
specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked);
|
||||||
|
|
||||||
setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:"));
|
setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:"));
|
||||||
getWidget(favoriteAttribute0, "FavoriteAttribute0");
|
getWidget(favoriteAttribute0, "FavoriteAttribute0");
|
||||||
getWidget(favoriteAttribute1, "FavoriteAttribute1");
|
getWidget(favoriteAttribute1, "FavoriteAttribute1");
|
||||||
favoriteAttribute0->setWindowManager(&mWindowManager);
|
favoriteAttribute0->setWindowManager(&mWindowManager);
|
||||||
favoriteAttribute1->setWindowManager(&mWindowManager);
|
favoriteAttribute1->setWindowManager(&mWindowManager);
|
||||||
favoriteAttribute0->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked);
|
favoriteAttribute0->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked);
|
||||||
favoriteAttribute1->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked);
|
favoriteAttribute1->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked);
|
||||||
|
|
||||||
setText("MajorSkillT", mWindowManager.getGameSettingString("sSkillClassMajor", ""));
|
setText("MajorSkillT", mWindowManager.getGameSettingString("sSkillClassMajor", ""));
|
||||||
setText("MinorSkillT", mWindowManager.getGameSettingString("sSkillClassMinor", ""));
|
setText("MinorSkillT", mWindowManager.getGameSettingString("sSkillClassMinor", ""));
|
||||||
|
@ -414,7 +414,7 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
|
||||||
for (std::vector<Widgets::MWSkillPtr>::const_iterator it = skills.begin(); it != end; ++it)
|
for (std::vector<Widgets::MWSkillPtr>::const_iterator it = skills.begin(); it != end; ++it)
|
||||||
{
|
{
|
||||||
(*it)->setWindowManager(&mWindowManager);
|
(*it)->setWindowManager(&mWindowManager);
|
||||||
(*it)->eventClicked = MyGUI::newDelegate(this, &CreateClassDialog::onSkillClicked);
|
(*it)->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onSkillClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
setText("LabelT", mWindowManager.getGameSettingString("sName", ""));
|
setText("LabelT", mWindowManager.getGameSettingString("sName", ""));
|
||||||
|
@ -426,15 +426,15 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr descriptionButton;
|
MyGUI::ButtonPtr descriptionButton;
|
||||||
getWidget(descriptionButton, "DescriptionButton");
|
getWidget(descriptionButton, "DescriptionButton");
|
||||||
descriptionButton->eventMouseButtonClick = MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
|
descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
|
||||||
|
|
||||||
// Set default skills, attributes
|
// Set default skills, attributes
|
||||||
|
|
||||||
|
@ -560,8 +560,8 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender)
|
||||||
if (specDialog)
|
if (specDialog)
|
||||||
delete specDialog;
|
delete specDialog;
|
||||||
specDialog = new SelectSpecializationDialog(mWindowManager);
|
specDialog = new SelectSpecializationDialog(mWindowManager);
|
||||||
specDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
specDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
||||||
specDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected);
|
specDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected);
|
||||||
specDialog->setVisible(true);
|
specDialog->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,8 +578,8 @@ void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
|
||||||
delete attribDialog;
|
delete attribDialog;
|
||||||
attribDialog = new SelectAttributeDialog(mWindowManager);
|
attribDialog = new SelectAttributeDialog(mWindowManager);
|
||||||
attribDialog->setAffectedWidget(_sender);
|
attribDialog->setAffectedWidget(_sender);
|
||||||
attribDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
attribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
||||||
attribDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected);
|
attribDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected);
|
||||||
attribDialog->setVisible(true);
|
attribDialog->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,8 +607,8 @@ void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender)
|
||||||
delete skillDialog;
|
delete skillDialog;
|
||||||
skillDialog = new SelectSkillDialog(mWindowManager);
|
skillDialog = new SelectSkillDialog(mWindowManager);
|
||||||
skillDialog->setAffectedWidget(_sender);
|
skillDialog->setAffectedWidget(_sender);
|
||||||
skillDialog->eventCancel = MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
skillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
|
||||||
skillDialog->eventItemSelected = MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected);
|
skillDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected);
|
||||||
skillDialog->setVisible(true);
|
skillDialog->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
descDialog = new DescriptionDialog(mWindowManager);
|
descDialog = new DescriptionDialog(mWindowManager);
|
||||||
descDialog->setTextInput(description);
|
descDialog->setTextInput(description);
|
||||||
descDialog->eventDone = MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered);
|
descDialog->eventDone += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered);
|
||||||
descDialog->setVisible(true);
|
descDialog->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,18 +672,18 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM
|
||||||
getWidget(specialization1, "Specialization1");
|
getWidget(specialization1, "Specialization1");
|
||||||
getWidget(specialization2, "Specialization2");
|
getWidget(specialization2, "Specialization2");
|
||||||
specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""));
|
specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""));
|
||||||
specialization0->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
||||||
specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], ""));
|
specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], ""));
|
||||||
specialization1->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
||||||
specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], ""));
|
specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], ""));
|
||||||
specialization2->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
|
||||||
specializationId = ESM::Class::Combat;
|
specializationId = ESM::Class::Combat;
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::ButtonPtr cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// widget controls
|
// widget controls
|
||||||
|
@ -725,14 +725,14 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager)
|
||||||
getWidget(attribute, std::string("Attribute").append(1, theIndex));
|
getWidget(attribute, std::string("Attribute").append(1, theIndex));
|
||||||
attribute->setWindowManager(&parWindowManager);
|
attribute->setWindowManager(&parWindowManager);
|
||||||
attribute->setAttributeId(ESM::Attribute::attributeIds[i]);
|
attribute->setAttributeId(ESM::Attribute::attributeIds[i]);
|
||||||
attribute->eventClicked = MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
|
attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::ButtonPtr cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// widget controls
|
// widget controls
|
||||||
|
@ -813,7 +813,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager)
|
||||||
{
|
{
|
||||||
skills[spec][i].widget->setWindowManager(&mWindowManager);
|
skills[spec][i].widget->setWindowManager(&mWindowManager);
|
||||||
skills[spec][i].widget->setSkillId(skills[spec][i].skillId);
|
skills[spec][i].widget->setSkillId(skills[spec][i].skillId);
|
||||||
skills[spec][i].widget->eventClicked = MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked);
|
skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,7 +821,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager)
|
||||||
MyGUI::ButtonPtr cancelButton;
|
MyGUI::ButtonPtr cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
|
||||||
cancelButton->eventMouseButtonClick = MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// widget controls
|
// widget controls
|
||||||
|
@ -850,7 +850,7 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager)
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked);
|
||||||
okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", ""));
|
okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", ""));
|
||||||
|
|
||||||
// Make sure the edit box has focus
|
// Make sure the edit box has focus
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace MWGui
|
||||||
int getChosenButton() const;
|
int getChosenButton() const;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate1<int> EventHandle_Int;
|
typedef delegates::CMultiDelegate1<int> EventHandle_Int;
|
||||||
|
|
||||||
/** Event : Button was clicked.\n
|
/** Event : Button was clicked.\n
|
||||||
signature : void method(MyGUI::WidgetPtr widget, int index)\n
|
signature : void method(MyGUI::WidgetPtr widget, int index)\n
|
||||||
|
@ -43,11 +43,11 @@ namespace MWGui
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void fitToText(MyGUI::StaticTextPtr widget);
|
void fitToText(MyGUI::TextBox* widget);
|
||||||
void layoutVertically(MyGUI::WidgetPtr widget, int margin);
|
void layoutVertically(MyGUI::WidgetPtr widget, int margin);
|
||||||
int currentButton;
|
int currentButton;
|
||||||
MyGUI::WidgetPtr textBox;
|
MyGUI::WidgetPtr textBox;
|
||||||
MyGUI::StaticTextPtr text;
|
MyGUI::TextBox* text;
|
||||||
MyGUI::WidgetPtr buttonBar;
|
MyGUI::WidgetPtr buttonBar;
|
||||||
std::vector<MyGUI::ButtonPtr> buttons;
|
std::vector<MyGUI::ButtonPtr> buttons;
|
||||||
};
|
};
|
||||||
|
@ -78,7 +78,7 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -90,8 +90,8 @@ namespace MWGui
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::StaticImagePtr classImage;
|
MyGUI::ImageBox* classImage;
|
||||||
MyGUI::StaticTextPtr className;
|
MyGUI::TextBox* className;
|
||||||
|
|
||||||
std::string currentClassId;
|
std::string currentClassId;
|
||||||
};
|
};
|
||||||
|
@ -108,7 +108,7 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -116,7 +116,7 @@ namespace MWGui
|
||||||
EventHandle_Void eventBack;
|
EventHandle_Void eventBack;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectClass(MyGUI::List* _sender, size_t _index);
|
void onSelectClass(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
@ -125,9 +125,9 @@ namespace MWGui
|
||||||
void updateClasses();
|
void updateClasses();
|
||||||
void updateStats();
|
void updateStats();
|
||||||
|
|
||||||
MyGUI::StaticImagePtr classImage;
|
MyGUI::ImageBox* classImage;
|
||||||
MyGUI::ListPtr classList;
|
MyGUI::ListBox* classList;
|
||||||
MyGUI::StaticTextPtr specializationName;
|
MyGUI::TextBox* specializationName;
|
||||||
Widgets::MWAttributePtr favoriteAttribute[2];
|
Widgets::MWAttributePtr favoriteAttribute[2];
|
||||||
Widgets::MWSkillPtr majorSkill[5];
|
Widgets::MWSkillPtr majorSkill[5];
|
||||||
Widgets::MWSkillPtr minorSkill[5];
|
Widgets::MWSkillPtr minorSkill[5];
|
||||||
|
@ -143,7 +143,7 @@ namespace MWGui
|
||||||
ESM::Class::Specialization getSpecializationId() const { return specializationId; }
|
ESM::Class::Specialization getSpecializationId() const { return specializationId; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Cancel button clicked.\n
|
/** Event : Cancel button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -160,7 +160,7 @@ namespace MWGui
|
||||||
void onCancelClicked(MyGUI::Widget* _sender);
|
void onCancelClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::WidgetPtr specialization0, specialization1, specialization2;
|
MyGUI::TextBox *specialization0, *specialization1, *specialization2;
|
||||||
|
|
||||||
ESM::Class::Specialization specializationId;
|
ESM::Class::Specialization specializationId;
|
||||||
};
|
};
|
||||||
|
@ -175,7 +175,7 @@ namespace MWGui
|
||||||
void setAffectedWidget(Widgets::MWAttributePtr widget) { affectedWidget = widget; }
|
void setAffectedWidget(Widgets::MWAttributePtr widget) { affectedWidget = widget; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Cancel button clicked.\n
|
/** Event : Cancel button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -207,7 +207,7 @@ namespace MWGui
|
||||||
void setAffectedWidget(Widgets::MWSkillPtr widget) { affectedWidget = widget; }
|
void setAffectedWidget(Widgets::MWSkillPtr widget) { affectedWidget = widget; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Cancel button clicked.\n
|
/** Event : Cancel button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -264,7 +264,7 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -287,7 +287,7 @@ namespace MWGui
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::EditPtr editName;
|
MyGUI::EditPtr editName;
|
||||||
MyGUI::WidgetPtr specializationName;
|
MyGUI::TextBox* specializationName;
|
||||||
Widgets::MWAttributePtr favoriteAttribute0, favoriteAttribute1;
|
Widgets::MWAttributePtr favoriteAttribute0, favoriteAttribute1;
|
||||||
Widgets::MWSkillPtr majorSkill[5];
|
Widgets::MWSkillPtr majorSkill[5];
|
||||||
Widgets::MWSkillPtr minorSkill[5];
|
Widgets::MWSkillPtr minorSkill[5];
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace MWGui
|
||||||
|
|
||||||
return isGood();
|
return isGood();
|
||||||
}
|
}
|
||||||
catch (const Compiler::SourceException& error)
|
catch (const Compiler::SourceException&)
|
||||||
{
|
{
|
||||||
// error has already been reported via error handler
|
// error has already been reported via error handler
|
||||||
}
|
}
|
||||||
|
@ -113,9 +113,9 @@ namespace MWGui
|
||||||
getWidget(history, "list_History");
|
getWidget(history, "list_History");
|
||||||
|
|
||||||
// Set up the command line box
|
// Set up the command line box
|
||||||
command->eventEditSelectAccept =
|
command->eventEditSelectAccept +=
|
||||||
newDelegate(this, &Console::acceptCommand);
|
newDelegate(this, &Console::acceptCommand);
|
||||||
command->eventKeyButtonPressed =
|
command->eventKeyButtonPressed +=
|
||||||
newDelegate(this, &Console::keyPress);
|
newDelegate(this, &Console::keyPress);
|
||||||
|
|
||||||
// Set up the log window
|
// Set up the log window
|
||||||
|
@ -139,6 +139,9 @@ namespace MWGui
|
||||||
void Console::disable()
|
void Console::disable()
|
||||||
{
|
{
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
// Remove keyboard focus from the console input whenever the
|
||||||
|
// console is turned off
|
||||||
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::setFont(const std::string &fntName)
|
void Console::setFont(const std::string &fntName)
|
||||||
|
@ -342,7 +345,7 @@ namespace MWGui
|
||||||
if( ( matches.front().find(' ') != string::npos ) ) {
|
if( ( matches.front().find(' ') != string::npos ) ) {
|
||||||
if( !has_front_quote )
|
if( !has_front_quote )
|
||||||
output.append(string("\""));
|
output.append(string("\""));
|
||||||
return output.append(matches.front() + string("\" "));
|
return output.append(matches.front() + string("\" "));
|
||||||
}
|
}
|
||||||
else if( has_front_quote ) {
|
else if( has_front_quote ) {
|
||||||
return output.append(matches.front() + string("\" "));
|
return output.append(matches.front() + string("\" "));
|
||||||
|
@ -361,7 +364,7 @@ namespace MWGui
|
||||||
/* Append the longest match to the end of the output string*/
|
/* Append the longest match to the end of the output string*/
|
||||||
output.append(matches.front().substr( 0, i));
|
output.append(matches.front().substr( 0, i));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "window_manager.hpp"
|
#include "window_manager.hpp"
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
#include "components/esm_store/store.hpp"
|
#include "components/esm_store/store.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwdialogue/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -14,107 +16,192 @@
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
using namespace Widgets;
|
||||||
|
|
||||||
DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
|
/**
|
||||||
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager)
|
*Copied from the internet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string lower_string(const std::string& str)
|
||||||
|
{
|
||||||
|
std::string lowerCase;
|
||||||
|
|
||||||
|
std::transform (str.begin(), str.end(), std::back_inserter (lowerCase),
|
||||||
|
(int(*)(int)) std::tolower);
|
||||||
|
|
||||||
|
return lowerCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
|
||||||
|
{
|
||||||
|
return lower_string(str).find(lower_string(substr),pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment)
|
||||||
|
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager),
|
||||||
|
mEnvironment(environment)
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
center();
|
center();
|
||||||
|
|
||||||
//WindowManager *wm = environment.mWindowManager;
|
//WindowManager *wm = environment.mWindowManager;
|
||||||
setText("NpcName", "Name of character");
|
setText("NpcName", "Name of character");
|
||||||
|
|
||||||
//History view
|
//History view
|
||||||
getWidget(history, "History");
|
getWidget(history, "History");
|
||||||
history->setOverflowToTheLeft(true);
|
history->setOverflowToTheLeft(true);
|
||||||
history->getClient()->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
|
history->setMaxTextLength(1000000);
|
||||||
|
Widget* eventbox;
|
||||||
//Topics list
|
|
||||||
|
//An EditBox cannot receive mouse click events, so we use an
|
||||||
|
//invisible widget on top of the editbox to receive them
|
||||||
|
/// \todo scrolling the dialogue history with the mouse wheel doesn't work using this solution
|
||||||
|
getWidget(eventbox, "EventBox");
|
||||||
|
eventbox->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
|
||||||
|
|
||||||
|
//Topics list
|
||||||
getWidget(topicsList, "TopicsList");
|
getWidget(topicsList, "TopicsList");
|
||||||
topicsList->setScrollVisible(true);
|
topicsList->setScrollVisible(true);
|
||||||
topicsList->eventListSelectAccept = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
//topicsList->eventListSelectAccept += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
topicsList->eventListMouseItemActivate = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
topicsList->eventListMouseItemActivate += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
topicsList->eventListChangePosition = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
//topicsList->eventListChangePosition += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
|
|
||||||
MyGUI::ButtonPtr byeButton;
|
MyGUI::ButtonPtr byeButton;
|
||||||
getWidget(byeButton, "ByeButton");
|
getWidget(byeButton, "ByeButton");
|
||||||
byeButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
||||||
|
|
||||||
updateOptions();
|
getWidget(pDispositionBar, "Disposition");
|
||||||
|
getWidget(pDispositionText,"DispositionText");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
ISubWidgetText* t = history->getSubWidgetText();
|
ISubWidgetText* t = history->getClient()->getSubWidgetText();
|
||||||
if(t == nullptr)
|
if(t == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const IntPoint& lastPressed = InputManager::getInstance().getLastLeftPressed();
|
const IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
|
||||||
|
|
||||||
size_t cursorPosition = t->getCursorPosition(lastPressed);
|
size_t cursorPosition = t->getCursorPosition(lastPressed);
|
||||||
if(history->getColorAtPos(cursorPosition) != "#FFFFFF")
|
MyGUI::UString color = history->getColorAtPos(cursorPosition);
|
||||||
|
if(color != "#B29154")
|
||||||
{
|
{
|
||||||
UString key = history->getColorTextAt(cursorPosition);
|
UString key = history->getColorTextAt(cursorPosition);
|
||||||
std::cout << "Clicked on key: " << key << std::endl;
|
if(color == "#686EBA") mEnvironment.mDialogueManager->keywordSelected(lower_string(key));
|
||||||
//eventTopicSelected(key);
|
|
||||||
|
if(color == "#572D21") mEnvironment.mDialogueManager->questionAnswered(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::open()
|
void DialogueWindow::open()
|
||||||
{
|
{
|
||||||
|
topicsList->removeAllItems();
|
||||||
|
pTopicsText.clear();
|
||||||
|
history->eraseText(0,history->getTextLength());
|
||||||
updateOptions();
|
updateOptions();
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
eventBye();
|
mEnvironment.mDialogueManager->goodbyeSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onSelectTopic(MyGUI::List* _sender, size_t _index)
|
void DialogueWindow::onSelectTopic(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
std::string topic = _sender->getItemNameAt(_index);
|
||||||
//const std::string* theTopic = topicsList->getItemDataAt<std::string>(_index);
|
mEnvironment.mDialogueManager->keywordSelected(lower_string(topic));
|
||||||
//std::cout << "Selected: "<< theTopic << std::endl;
|
|
||||||
//eventTopicSelected(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::startDialogue(std::string npcName)
|
||||||
|
{
|
||||||
|
setText("NpcName", npcName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||||
|
{
|
||||||
|
topicsList->removeAllItems();
|
||||||
|
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); it++)
|
||||||
|
{
|
||||||
|
topicsList->addItem(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::removeKeyword(std::string keyWord)
|
||||||
|
{
|
||||||
|
if(topicsList->findItemIndexWith(keyWord) != MyGUI::ITEM_NONE)
|
||||||
|
{
|
||||||
|
topicsList->removeItemAt(topicsList->findItemIndexWith(keyWord));
|
||||||
|
pTopicsText.erase(keyWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
while((pos = find_str_ci(str,keyword, pos)) != std::string::npos)
|
||||||
|
{
|
||||||
|
if(pos==0)
|
||||||
|
{
|
||||||
|
str.insert(pos,color1);
|
||||||
|
pos += color1.length();
|
||||||
|
pos += keyword.length();
|
||||||
|
str.insert(pos,color2);
|
||||||
|
pos+= color2.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(str.substr(pos -1,1) == " ")
|
||||||
|
{
|
||||||
|
str.insert(pos,color1);
|
||||||
|
pos += color1.length();
|
||||||
|
pos += keyword.length();
|
||||||
|
str.insert(pos,color2);
|
||||||
|
pos+= color2.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos += keyword.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DialogueWindow::parseText(std::string text)
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0;i<topicsList->getItemCount();i++)
|
||||||
|
{
|
||||||
|
std::string keyWord = topicsList->getItemNameAt(i);
|
||||||
|
addColorInString(text,keyWord,"#686EBA","#B29154");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::addText(std::string text)
|
||||||
|
{
|
||||||
|
history->addDialogText("#B29154"+parseText(text)+"#B29154");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::addTitle(std::string text)
|
||||||
|
{
|
||||||
|
history->addDialogHeading(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::askQuestion(std::string question)
|
||||||
|
{
|
||||||
|
history->addDialogText("#572D21"+question+"#B29154"+" ");
|
||||||
|
}
|
||||||
|
|
||||||
void DialogueWindow::updateOptions()
|
void DialogueWindow::updateOptions()
|
||||||
{
|
{
|
||||||
//FIXME Add this properly
|
|
||||||
history->addDialogText("Through the translucent surface of the orb, you see shifting images of distant locations...");
|
|
||||||
for(int z = 0; z < 10; z++)
|
|
||||||
{
|
|
||||||
history->addDialogHeading("Fort Frostmoth");
|
|
||||||
history->addDialogText("The image in the orb flickers, and you see.... The cold courtyard of #FF0000Fort Frostmoth#FFFFFF, battered bu werewolf attack, but still standing, still projecting Imperial might even to this distant and cold corner of the world.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clear the list of topics
|
//Clear the list of topics
|
||||||
topicsList->removeAllItems();
|
topicsList->removeAllItems();
|
||||||
int i = 0;
|
pTopicsText.clear();
|
||||||
topicsList->addItem("Ald'ruhn", i++);
|
history->eraseText(0,history->getTextLength());
|
||||||
topicsList->addItem("Balmora", i++);
|
|
||||||
topicsList->addItem("Sadrith Mora", i++);
|
|
||||||
topicsList->addItem("Vivec", i++);
|
|
||||||
topicsList->addItem("Ald Velothi", i++);
|
|
||||||
topicsList->addItem("Caldera", i++);
|
|
||||||
topicsList->addItem("Dagon Fel ", i++);
|
|
||||||
topicsList->addItem("Gnaar Mok", i++);
|
|
||||||
topicsList->addItem("Gnisis", i++);
|
|
||||||
topicsList->addItem("Hla Oad", i++);
|
|
||||||
topicsList->addItem("Khuul", i++);
|
|
||||||
topicsList->addItem("Maar Gan", i++);
|
|
||||||
topicsList->addItem("Molag Mar", i++);
|
|
||||||
topicsList->addItem("Pelagiad", i++);
|
|
||||||
topicsList->addItem("Seyda Neen", i++);
|
|
||||||
topicsList->addItem("Suran", i++);
|
|
||||||
topicsList->addItem("Tel Aruhn", i++);
|
|
||||||
topicsList->addItem("Tel Branora", i++);
|
|
||||||
topicsList->addItem("Tel Fyr", i++);
|
|
||||||
topicsList->addItem("Tel Mora", i++);
|
|
||||||
topicsList->addItem("Tel Vos", i++);
|
|
||||||
topicsList->addItem("Vos", i++);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pDispositionBar->setProgressRange(100);
|
||||||
|
pDispositionBar->setProgressPosition(40);
|
||||||
|
pDispositionText->eraseText(0,pDispositionText->getTextLength());
|
||||||
|
pDispositionText->addText("#B29154"+std::string("40/100")+"#B29154");
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@ namespace MWGui
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Environment;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file contains the dialouge window
|
This file contains the dialouge window
|
||||||
Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml.
|
Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml.
|
||||||
|
@ -16,35 +21,52 @@ namespace MWGui
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
class DialogeHistory;
|
class DialogueHistory;
|
||||||
|
|
||||||
using namespace MyGUI;
|
using namespace MyGUI;
|
||||||
|
|
||||||
class DialogueWindow: public WindowBase
|
class DialogueWindow: public WindowBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DialogueWindow(WindowManager& parWindowManager);
|
DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment);
|
||||||
|
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Dialog finished, OK button clicked.\n
|
/** Event : Dialog finished, OK button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
*/
|
*/
|
||||||
EventHandle_Void eventBye;
|
EventHandle_Void eventBye;
|
||||||
|
|
||||||
|
void startDialogue(std::string npcName);
|
||||||
|
void stopDialogue();
|
||||||
|
void setKeywords(std::list<std::string> keyWord);
|
||||||
|
void removeKeyword(std::string keyWord);
|
||||||
|
void addText(std::string text);
|
||||||
|
void addTitle(std::string text);
|
||||||
|
void askQuestion(std::string question);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectTopic(MyGUI::List* _sender, size_t _index);
|
void onSelectTopic(MyGUI::ListBox* _sender, size_t _index);
|
||||||
void onByeClicked(MyGUI::Widget* _sender);
|
void onByeClicked(MyGUI::Widget* _sender);
|
||||||
void onHistoryClicked(MyGUI::Widget* _sender);
|
void onHistoryClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateOptions();
|
void updateOptions();
|
||||||
|
/**
|
||||||
|
*Helper function that add topic keyword in blue in a text.
|
||||||
|
*/
|
||||||
|
std::string parseText(std::string text);
|
||||||
|
|
||||||
DialogeHistory* history;
|
DialogueHistory* history;
|
||||||
MyGUI::ListPtr topicsList;
|
MyGUI::ListBox* topicsList;
|
||||||
|
MyGUI::ProgressPtr pDispositionBar;
|
||||||
|
MyGUI::EditPtr pDispositionText;
|
||||||
|
std::map<std::string,std::string> pTopicsText;// this map links keyword and "real" text.
|
||||||
|
|
||||||
|
MWWorld::Environment& mEnvironment;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
using namespace Widgets;
|
||||||
|
|
||||||
UString DialogeHistory::getColorAtPos(size_t _pos)
|
UString DialogueHistory::getColorAtPos(size_t _pos)
|
||||||
{
|
{
|
||||||
UString colour = TextIterator::convertTagColour(mText->getTextColour());
|
UString colour = TextIterator::convertTagColour(getTextColour());
|
||||||
TextIterator iterator(mText->getCaption());
|
TextIterator iterator(getCaption());
|
||||||
while(iterator.moveNext())
|
while(iterator.moveNext())
|
||||||
{
|
{
|
||||||
size_t pos = iterator.getPosition();
|
size_t pos = iterator.getPosition();
|
||||||
|
@ -29,12 +29,12 @@ UString DialogeHistory::getColorAtPos(size_t _pos)
|
||||||
return colour;
|
return colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
UString DialogeHistory::getColorTextAt(size_t _pos)
|
UString DialogueHistory::getColorTextAt(size_t _pos)
|
||||||
{
|
{
|
||||||
bool breakOnNext = false;
|
bool breakOnNext = false;
|
||||||
UString colour = TextIterator::convertTagColour(mText->getTextColour());
|
UString colour = TextIterator::convertTagColour(getTextColour());
|
||||||
UString colour2 = colour;
|
UString colour2 = colour;
|
||||||
TextIterator iterator(mText->getCaption());
|
TextIterator iterator(getCaption());
|
||||||
TextIterator col_start = iterator;
|
TextIterator col_start = iterator;
|
||||||
while(iterator.moveNext())
|
while(iterator.moveNext())
|
||||||
{
|
{
|
||||||
|
@ -59,15 +59,15 @@ UString DialogeHistory::getColorTextAt(size_t _pos)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogeHistory::addDialogHeading(const UString& parText)
|
void DialogueHistory::addDialogHeading(const UString& parText)
|
||||||
{
|
{
|
||||||
UString head("\n#00FF00");
|
UString head("\n#D8C09A");
|
||||||
head.append(parText);
|
head.append(parText);
|
||||||
head.append("#FFFFFF\n");
|
head.append("#B29154\n");
|
||||||
addText(head);
|
addText(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogeHistory::addDialogText(const UString& parText)
|
void DialogueHistory::addDialogText(const UString& parText)
|
||||||
{
|
{
|
||||||
addText(parText);
|
addText(parText);
|
||||||
addText("\n");
|
addText("\n");
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
using namespace MyGUI;
|
using namespace MyGUI;
|
||||||
class DialogeHistory : public MyGUI::Edit
|
class DialogueHistory : public MyGUI::EditBox
|
||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED( DialogeHistory )
|
MYGUI_RTTI_DERIVED( DialogueHistory )
|
||||||
public:
|
public:
|
||||||
Widget* getClient() { return mClient; }
|
Widget* getClient() { return mClient; }
|
||||||
UString getColorAtPos(size_t _pos);
|
UString getColorAtPos(size_t _pos);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct book
|
struct book
|
||||||
|
@ -87,9 +89,9 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager)
|
||||||
getWidget(mLeftTextWidget, "LeftText");
|
getWidget(mLeftTextWidget, "LeftText");
|
||||||
getWidget(mRightTextWidget, "RightText");
|
getWidget(mRightTextWidget, "RightText");
|
||||||
getWidget(mPrevBtn, "PrevPageBTN");
|
getWidget(mPrevBtn, "PrevPageBTN");
|
||||||
mPrevBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyPrevPage);
|
mPrevBtn->eventMouseButtonClick += MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyPrevPage);
|
||||||
getWidget(mNextBtn, "NextPageBTN");
|
getWidget(mNextBtn, "NextPageBTN");
|
||||||
mNextBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyNextPage);
|
mNextBtn->eventMouseButtonClick += MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyNextPage);
|
||||||
//MyGUI::ItemBox* list = new MyGUI::ItemBox();
|
//MyGUI::ItemBox* list = new MyGUI::ItemBox();
|
||||||
//list->addItem("qaq","aqzazaz");
|
//list->addItem("qaq","aqzazaz");
|
||||||
//mScrollerWidget->addChildItem(list);
|
//mScrollerWidget->addChildItem(list);
|
||||||
|
@ -109,12 +111,14 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager)
|
||||||
//displayLeftText(list.front());
|
//displayLeftText(list.front());
|
||||||
|
|
||||||
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
||||||
t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize);
|
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &JournalWindow::onWindowResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWGui::JournalWindow::open()
|
void MWGui::JournalWindow::open()
|
||||||
{
|
{
|
||||||
mPageNumber = 0;
|
mPageNumber = 0;
|
||||||
|
std::string journalOpenSound = "book open";
|
||||||
|
mWindowManager.getEnvironment().mSoundManager->playSound (journalOpenSound, 1.0, 1.0);
|
||||||
if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end())
|
if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end())
|
||||||
{
|
{
|
||||||
book journal;
|
book journal;
|
||||||
|
@ -176,6 +180,8 @@ void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender)
|
||||||
{
|
{
|
||||||
if(mPageNumber < int(leftPages.size())-1)
|
if(mPageNumber < int(leftPages.size())-1)
|
||||||
{
|
{
|
||||||
|
std::string nextSound = "book page2";
|
||||||
|
mWindowManager.getEnvironment().mSoundManager->playSound (nextSound, 1.0, 1.0);
|
||||||
mPageNumber = mPageNumber + 1;
|
mPageNumber = mPageNumber + 1;
|
||||||
displayLeftText(leftPages[mPageNumber]);
|
displayLeftText(leftPages[mPageNumber]);
|
||||||
displayRightText(rightPages[mPageNumber]);
|
displayRightText(rightPages[mPageNumber]);
|
||||||
|
@ -186,6 +192,8 @@ void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender)
|
||||||
{
|
{
|
||||||
if(mPageNumber > 0)
|
if(mPageNumber > 0)
|
||||||
{
|
{
|
||||||
|
std::string prevSound = "book page";
|
||||||
|
mWindowManager.getEnvironment().mSoundManager->playSound (prevSound, 1.0, 1.0);
|
||||||
mPageNumber = mPageNumber - 1;
|
mPageNumber = mPageNumber - 1;
|
||||||
displayLeftText(leftPages[mPageNumber]);
|
displayLeftText(leftPages[mPageNumber]);
|
||||||
displayRightText(rightPages[mPageNumber]);
|
displayRightText(rightPages[mPageNumber]);
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWGui
|
||||||
static const int lineHeight;
|
static const int lineHeight;
|
||||||
|
|
||||||
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
||||||
MyGUI::VScrollPtr skillScrollerWidget;
|
MyGUI::ScrollBar* skillScrollerWidget;
|
||||||
int lastPos, clientHeight;
|
int lastPos, clientHeight;
|
||||||
MyGUI::EditPtr mLeftTextWidget;
|
MyGUI::EditPtr mLeftTextWidget;
|
||||||
MyGUI::EditPtr mRightTextWidget;
|
MyGUI::EditPtr mRightTextWidget;
|
||||||
|
@ -54,4 +54,4 @@ namespace MWGui
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,6 +15,22 @@ using namespace MWGui;
|
||||||
|
|
||||||
HUD::HUD(int width, int height, int fpsLevel)
|
HUD::HUD(int width, int height, int fpsLevel)
|
||||||
: Layout("openmw_hud_layout.xml")
|
: Layout("openmw_hud_layout.xml")
|
||||||
|
, health(NULL)
|
||||||
|
, magicka(NULL)
|
||||||
|
, stamina(NULL)
|
||||||
|
, weapImage(NULL)
|
||||||
|
, spellImage(NULL)
|
||||||
|
, weapStatus(NULL)
|
||||||
|
, spellStatus(NULL)
|
||||||
|
, effectBox(NULL)
|
||||||
|
, effect1(NULL)
|
||||||
|
, minimap(NULL)
|
||||||
|
, compass(NULL)
|
||||||
|
, crosshair(NULL)
|
||||||
|
, fpsbox(NULL)
|
||||||
|
, fpscounter(NULL)
|
||||||
|
, trianglecounter(NULL)
|
||||||
|
, batchcounter(NULL)
|
||||||
{
|
{
|
||||||
setCoord(0,0, width, height);
|
setCoord(0,0, width, height);
|
||||||
|
|
||||||
|
@ -61,6 +77,8 @@ HUD::HUD(int width, int height, int fpsLevel)
|
||||||
setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds");
|
setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds");
|
||||||
setSpellStatus(65, 100);
|
setSpellStatus(65, 100);
|
||||||
setEffect("icons\\s\\tx_s_chameleon.dds");
|
setEffect("icons\\s\\tx_s_chameleon.dds");
|
||||||
|
|
||||||
|
LocalMapBase::init(minimap, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::setFPS(float fps)
|
void HUD::setFPS(float fps)
|
||||||
|
@ -142,3 +160,162 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HUD::setPlayerDir(const float x, const float y)
|
||||||
|
{
|
||||||
|
MyGUI::ISubWidget* main = compass->getSubWidgetMain();
|
||||||
|
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
|
||||||
|
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
|
||||||
|
float angle = std::atan2(x,y);
|
||||||
|
rotatingSubskin->setAngle(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HUD::setPlayerPos(const float x, const float y)
|
||||||
|
{
|
||||||
|
MyGUI::IntSize size = minimap->getCanvasSize();
|
||||||
|
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
|
||||||
|
MyGUI::IntCoord viewsize = minimap->getCoord();
|
||||||
|
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
|
||||||
|
|
||||||
|
minimap->setViewOffset(pos);
|
||||||
|
compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
|
||||||
|
}
|
||||||
|
|
||||||
|
MapWindow::MapWindow()
|
||||||
|
: Layout("openmw_map_window_layout.xml"), mGlobal(false)
|
||||||
|
{
|
||||||
|
setCoord(500,0,320,300);
|
||||||
|
setText("WorldButton", "World");
|
||||||
|
setImage("Compass", "textures\\compass.dds");
|
||||||
|
|
||||||
|
// Obviously you should override this later on
|
||||||
|
setCellName("No Cell Loaded");
|
||||||
|
|
||||||
|
getWidget(mLocalMap, "LocalMap");
|
||||||
|
getWidget(mGlobalMap, "GlobalMap");
|
||||||
|
getWidget(mPlayerArrow, "Compass");
|
||||||
|
|
||||||
|
getWidget(mButton, "WorldButton");
|
||||||
|
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
|
||||||
|
|
||||||
|
MyGUI::Button* eventbox;
|
||||||
|
getWidget(eventbox, "EventBox");
|
||||||
|
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
||||||
|
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||||
|
|
||||||
|
LocalMapBase::init(mLocalMap, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::setVisible(bool b)
|
||||||
|
{
|
||||||
|
mMainWidget->setVisible(b);
|
||||||
|
if (b)
|
||||||
|
mVisible = true;
|
||||||
|
else
|
||||||
|
mVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::setCellName(const std::string& cellName)
|
||||||
|
{
|
||||||
|
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName);
|
||||||
|
adjustWindowCaption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::setPlayerPos(const float x, const float y)
|
||||||
|
{
|
||||||
|
if (mGlobal || mVisible) return;
|
||||||
|
MyGUI::IntSize size = mLocalMap->getCanvasSize();
|
||||||
|
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
|
||||||
|
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
|
||||||
|
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
|
||||||
|
mLocalMap->setViewOffset(pos);
|
||||||
|
|
||||||
|
mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::setPlayerDir(const float x, const float y)
|
||||||
|
{
|
||||||
|
if (!mVisible) return;
|
||||||
|
MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain();
|
||||||
|
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
|
||||||
|
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
|
||||||
|
float angle = std::atan2(x,y);
|
||||||
|
rotatingSubskin->setAngle(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||||
|
{
|
||||||
|
if (_id!=MyGUI::MouseButton::Left) return;
|
||||||
|
if (!mGlobal)
|
||||||
|
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||||
|
{
|
||||||
|
if (_id!=MyGUI::MouseButton::Left) return;
|
||||||
|
|
||||||
|
if (!mGlobal)
|
||||||
|
{
|
||||||
|
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
|
||||||
|
mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff );
|
||||||
|
|
||||||
|
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
{
|
||||||
|
mGlobal = !mGlobal;
|
||||||
|
mGlobalMap->setVisible(mGlobal);
|
||||||
|
mLocalMap->setVisible(!mGlobal);
|
||||||
|
|
||||||
|
mButton->setCaption( mGlobal ? "Local" : "World" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout)
|
||||||
|
{
|
||||||
|
mLocalMap = widget;
|
||||||
|
mLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::setCellPrefix(const std::string& prefix)
|
||||||
|
{
|
||||||
|
mPrefix = prefix;
|
||||||
|
mChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
||||||
|
{
|
||||||
|
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
|
||||||
|
for (int mx=0; mx<3; ++mx)
|
||||||
|
{
|
||||||
|
for (int my=0; my<3; ++my)
|
||||||
|
{
|
||||||
|
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
|
||||||
|
+ boost::lexical_cast<std::string>(my);
|
||||||
|
|
||||||
|
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_"
|
||||||
|
+ boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1)));
|
||||||
|
|
||||||
|
MyGUI::ImageBox* box;
|
||||||
|
mLayout->getWidget(box, name);
|
||||||
|
MyGUI::ImageBox* fog;
|
||||||
|
mLayout->getWidget(fog, name+"_fog");
|
||||||
|
|
||||||
|
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
|
||||||
|
box->setImageTexture(image);
|
||||||
|
else
|
||||||
|
box->setImageTexture("black.png");
|
||||||
|
|
||||||
|
if (MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0)
|
||||||
|
fog->setImageTexture(image+"_fog");
|
||||||
|
else
|
||||||
|
fog->setImageTexture("black.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mInterior = interior;
|
||||||
|
mCurX = x;
|
||||||
|
mCurY = y;
|
||||||
|
mChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "../mwmechanics/stat.hpp"
|
#include "../mwmechanics/stat.hpp"
|
||||||
#include "window_base.hpp"
|
#include "window_base.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file contains classes corresponding to window layouts
|
This file contains classes corresponding to window layouts
|
||||||
defined in resources/mygui/ *.xml.
|
defined in resources/mygui/ *.xml.
|
||||||
|
@ -29,7 +31,25 @@
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
class HUD : public OEngine::GUI::Layout
|
class LocalMapBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout);
|
||||||
|
|
||||||
|
void setCellPrefix(const std::string& prefix);
|
||||||
|
void setActiveCell(const int x, const int y, bool interior=false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int mCurX, mCurY;
|
||||||
|
bool mInterior;
|
||||||
|
MyGUI::ScrollView* mLocalMap;
|
||||||
|
std::string mPrefix;
|
||||||
|
bool mChanged;
|
||||||
|
|
||||||
|
OEngine::GUI::Layout* mLayout;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HUD : public OEngine::GUI::Layout, public LocalMapBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HUD(int width, int height, int fpsLevel);
|
HUD(int width, int height, int fpsLevel);
|
||||||
|
@ -43,40 +63,45 @@ namespace MWGui
|
||||||
void setFPS(float fps);
|
void setFPS(float fps);
|
||||||
void setTriangleCount(size_t count);
|
void setTriangleCount(size_t count);
|
||||||
void setBatchCount(size_t count);
|
void setBatchCount(size_t count);
|
||||||
|
void setPlayerDir(const float x, const float y);
|
||||||
|
void setPlayerPos(const float x, const float y);
|
||||||
|
|
||||||
MyGUI::ProgressPtr health, magicka, stamina;
|
MyGUI::ProgressPtr health, magicka, stamina;
|
||||||
MyGUI::StaticImagePtr weapImage, spellImage;
|
MyGUI::ImageBox *weapImage, *spellImage;
|
||||||
MyGUI::ProgressPtr weapStatus, spellStatus;
|
MyGUI::ProgressPtr weapStatus, spellStatus;
|
||||||
MyGUI::WidgetPtr effectBox;
|
MyGUI::WidgetPtr effectBox;
|
||||||
MyGUI::StaticImagePtr effect1;
|
MyGUI::ImageBox* effect1;
|
||||||
MyGUI::StaticImagePtr minimap;
|
MyGUI::ScrollView* minimap;
|
||||||
MyGUI::StaticImagePtr compass;
|
MyGUI::ImageBox* compass;
|
||||||
MyGUI::StaticImagePtr crosshair;
|
MyGUI::ImageBox* crosshair;
|
||||||
|
|
||||||
MyGUI::WidgetPtr fpsbox;
|
MyGUI::WidgetPtr fpsbox;
|
||||||
MyGUI::StaticTextPtr fpscounter;
|
MyGUI::TextBox* fpscounter;
|
||||||
MyGUI::StaticTextPtr trianglecounter;
|
MyGUI::TextBox* trianglecounter;
|
||||||
MyGUI::StaticTextPtr batchcounter;
|
MyGUI::TextBox* batchcounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapWindow : public OEngine::GUI::Layout
|
class MapWindow : public OEngine::GUI::Layout, public LocalMapBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapWindow()
|
MapWindow();
|
||||||
: Layout("openmw_map_window_layout.xml")
|
|
||||||
{
|
|
||||||
setCoord(500,0,320,300);
|
|
||||||
setText("WorldButton", "World");
|
|
||||||
setImage("Compass", "compass.dds");
|
|
||||||
|
|
||||||
// Obviously you should override this later on
|
void setVisible(bool b);
|
||||||
setCellName("No Cell Loaded");
|
void setPlayerPos(const float x, const float y);
|
||||||
}
|
void setPlayerDir(const float x, const float y);
|
||||||
|
void setCellName(const std::string& cellName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||||
|
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||||
|
void onWorldButtonClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
void setCellName(const std::string& cellName)
|
MyGUI::ScrollView* mGlobalMap;
|
||||||
{
|
MyGUI::ImageBox* mPlayerArrow;
|
||||||
mMainWidget->setCaption(cellName);
|
MyGUI::Button* mButton;
|
||||||
}
|
MyGUI::IntPoint mLastDragPos;
|
||||||
|
bool mVisible;
|
||||||
|
bool mGlobal;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainMenu : public OEngine::GUI::Layout
|
class MainMenu : public OEngine::GUI::Layout
|
||||||
|
@ -127,7 +152,7 @@ namespace MWGui
|
||||||
getWidget(avatar, "Avatar");
|
getWidget(avatar, "Avatar");
|
||||||
|
|
||||||
// Adjust armor rating text to bottom of avatar widget
|
// Adjust armor rating text to bottom of avatar widget
|
||||||
MyGUI::StaticTextPtr armor_rating;
|
MyGUI::TextBox* armor_rating;
|
||||||
getWidget(armor_rating, "ArmorRating");
|
getWidget(armor_rating, "ArmorRating");
|
||||||
armor_rating->setCaption("Armor: 11");
|
armor_rating->setCaption("Armor: 11");
|
||||||
MyGUI::IntCoord coord = armor_rating->getCoord();
|
MyGUI::IntCoord coord = armor_rating->getCoord();
|
||||||
|
@ -165,7 +190,7 @@ namespace MWGui
|
||||||
last_x += coord.width + margin;
|
last_x += coord.width + margin;
|
||||||
button_pt->setCoord(coord);
|
button_pt->setCoord(coord);
|
||||||
|
|
||||||
button_pt->eventMouseButtonClick = MyGUI::newDelegate(this, &InventoryWindow::onCategorySelected);
|
button_pt->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onCategorySelected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
if(it->current >= it->max)
|
if(it->current >= it->max)
|
||||||
{
|
{
|
||||||
it->messageBox->mMarkedToDelete = true;
|
it->messageBox->mMarkedToDelete = true;
|
||||||
|
|
||||||
if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one
|
if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one
|
||||||
{
|
{
|
||||||
// collect all with mMarkedToDelete and delete them.
|
// collect all with mMarkedToDelete and delete them.
|
||||||
|
@ -47,7 +47,7 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
|
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
|
||||||
delete mInterMessageBoxe;
|
delete mInterMessageBoxe;
|
||||||
mInterMessageBoxe = NULL;
|
mInterMessageBoxe = NULL;
|
||||||
|
@ -57,20 +57,18 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
|
|
||||||
void MessageBoxManager::createMessageBox (const std::string& message)
|
void MessageBoxManager::createMessageBox (const std::string& message)
|
||||||
{
|
{
|
||||||
std::cout << "MessageBox: " << message << std::endl;
|
|
||||||
|
|
||||||
MessageBox *box = new MessageBox(*this, message);
|
MessageBox *box = new MessageBox(*this, message);
|
||||||
|
|
||||||
removeMessageBox(message.length()*mMessageBoxSpeed, box);
|
removeMessageBox(message.length()*mMessageBoxSpeed, box);
|
||||||
|
|
||||||
mMessageBoxes.push_back(box);
|
mMessageBoxes.push_back(box);
|
||||||
std::vector<MessageBox*>::iterator it;
|
std::vector<MessageBox*>::iterator it;
|
||||||
|
|
||||||
if(mMessageBoxes.size() > 3) {
|
if(mMessageBoxes.size() > 3) {
|
||||||
delete *mMessageBoxes.begin();
|
delete *mMessageBoxes.begin();
|
||||||
mMessageBoxes.erase(mMessageBoxes.begin());
|
mMessageBoxes.erase(mMessageBoxes.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
int height = 0;
|
int height = 0;
|
||||||
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
|
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -88,9 +86,9 @@ bool MessageBoxManager::createInteractiveMessageBox (const std::string& message,
|
||||||
std::cout << "interactive MessageBox: " << message << " - ";
|
std::cout << "interactive MessageBox: " << message << " - ";
|
||||||
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
|
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
|
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +103,7 @@ void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox)
|
||||||
timer.current = 0;
|
timer.current = 0;
|
||||||
timer.max = time;
|
timer.max = time;
|
||||||
timer.messageBox = msgbox;
|
timer.messageBox = msgbox;
|
||||||
|
|
||||||
mTimers.insert(mTimers.end(), timer);
|
mTimers.insert(mTimers.end(), timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,25 +150,26 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin
|
||||||
mBottomPadding = 20;
|
mBottomPadding = 20;
|
||||||
mNextBoxPadding = 20;
|
mNextBoxPadding = 20;
|
||||||
mMarkedToDelete = false;
|
mMarkedToDelete = false;
|
||||||
|
|
||||||
getWidget(mMessageWidget, "message");
|
getWidget(mMessageWidget, "message");
|
||||||
|
|
||||||
mMessageWidget->setOverflowToTheLeft(true);
|
mMessageWidget->setOverflowToTheLeft(true);
|
||||||
mMessageWidget->addText(cMessage);
|
mMessageWidget->addText(cMessage);
|
||||||
|
|
||||||
MyGUI::IntSize size;
|
MyGUI::IntSize size;
|
||||||
size.width = mFixedWidth;
|
size.width = mFixedWidth;
|
||||||
size.height = 100; // dummy
|
size.height = 100; // dummy
|
||||||
|
|
||||||
MyGUI::IntCoord coord;
|
MyGUI::IntCoord coord;
|
||||||
coord.left = 10; // dummy
|
coord.left = 10; // dummy
|
||||||
coord.top = 10; // dummy
|
coord.top = 10; // dummy
|
||||||
|
|
||||||
mMessageWidget->setSize(size);
|
mMessageWidget->setSize(size);
|
||||||
|
|
||||||
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
MyGUI::IntSize textSize = mMessageWidget->getTextSize();
|
||||||
|
|
||||||
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
|
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
|
||||||
|
|
||||||
mMainWidget->setSize(size);
|
mMainWidget->setSize(size);
|
||||||
size.width -= 15; // this is to center the text (see messagebox_layout.xml, Widget type="Edit" position="-2 -3 0 0")
|
size.width -= 15; // this is to center the text (see messagebox_layout.xml, Widget type="Edit" position="-2 -3 0 0")
|
||||||
mMessageWidget->setSize(size);
|
mMessageWidget->setSize(size);
|
||||||
|
@ -178,15 +177,15 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin
|
||||||
|
|
||||||
void MessageBox::update (int height)
|
void MessageBox::update (int height)
|
||||||
{
|
{
|
||||||
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
|
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
MyGUI::IntCoord coord;
|
MyGUI::IntCoord coord;
|
||||||
coord.left = (gameWindowSize.width - mFixedWidth)/2;
|
coord.left = (gameWindowSize.width - mFixedWidth)/2;
|
||||||
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
|
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
|
||||||
|
|
||||||
MyGUI::IntSize size;
|
MyGUI::IntSize size;
|
||||||
size.width = mFixedWidth;
|
size.width = mFixedWidth;
|
||||||
size.height = mHeight;
|
size.height = mHeight;
|
||||||
|
|
||||||
mMainWidget->setCoord(coord);
|
mMainWidget->setCoord(coord);
|
||||||
mMainWidget->setSize(size);
|
mMainWidget->setSize(size);
|
||||||
mMainWidget->setVisible(true);
|
mMainWidget->setVisible(true);
|
||||||
|
@ -211,26 +210,26 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
int buttonTopPadding = 5; // ^-- if vertical
|
int buttonTopPadding = 5; // ^-- if vertical
|
||||||
int buttonPadding = 5; // padding between button label and button itself
|
int buttonPadding = 5; // padding between button label and button itself
|
||||||
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
|
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
|
||||||
|
|
||||||
mMarkedToDelete = false;
|
mMarkedToDelete = false;
|
||||||
|
|
||||||
|
|
||||||
getWidget(mMessageWidget, "message");
|
getWidget(mMessageWidget, "message");
|
||||||
getWidget(mButtonsWidget, "buttons");
|
getWidget(mButtonsWidget, "buttons");
|
||||||
|
|
||||||
mMessageWidget->setOverflowToTheLeft(true);
|
mMessageWidget->setOverflowToTheLeft(true);
|
||||||
mMessageWidget->addText(message);
|
mMessageWidget->addText(message);
|
||||||
|
|
||||||
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
MyGUI::IntSize textSize = mMessageWidget->getTextSize();
|
||||||
|
|
||||||
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
|
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
|
|
||||||
int biggestButtonWidth = 0;
|
int biggestButtonWidth = 0;
|
||||||
int buttonWidth = 0;
|
int buttonWidth = 0;
|
||||||
int buttonsWidth = 0;
|
int buttonsWidth = 0;
|
||||||
int buttonHeight = 0;
|
int buttonHeight = 0;
|
||||||
MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
|
MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
|
||||||
|
|
||||||
std::vector<std::string>::const_iterator it;
|
std::vector<std::string>::const_iterator it;
|
||||||
for(it = buttons.begin(); it != buttons.end(); ++it)
|
for(it = buttons.begin(); it != buttons.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -240,28 +239,28 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
dummyCoord,
|
dummyCoord,
|
||||||
MyGUI::Align::Default);
|
MyGUI::Align::Default);
|
||||||
button->setCaption(*it);
|
button->setCaption(*it);
|
||||||
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed);
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed);
|
||||||
|
|
||||||
mButtons.push_back(button);
|
mButtons.push_back(button);
|
||||||
|
|
||||||
buttonWidth = button->_getTextSize().width + 2*buttonPadding + buttonLeftPadding;
|
buttonWidth = button->getTextSize().width + 2*buttonPadding + buttonLeftPadding;
|
||||||
buttonsWidth += buttonWidth;
|
buttonsWidth += buttonWidth;
|
||||||
buttonHeight = button->_getTextSize().height + 2*buttonPadding + buttonTopPadding;
|
buttonHeight = button->getTextSize().height + 2*buttonPadding + buttonTopPadding;
|
||||||
|
|
||||||
if(buttonWidth > biggestButtonWidth)
|
if(buttonWidth > biggestButtonWidth)
|
||||||
{
|
{
|
||||||
biggestButtonWidth = buttonWidth;
|
biggestButtonWidth = buttonWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buttonsWidth += buttonLeftPadding;
|
buttonsWidth += buttonLeftPadding;
|
||||||
|
|
||||||
MyGUI::IntSize mainWidgetSize;
|
MyGUI::IntSize mainWidgetSize;
|
||||||
if(buttonsWidth < fixedWidth)
|
if(buttonsWidth < fixedWidth)
|
||||||
{
|
{
|
||||||
// on one line
|
// on one line
|
||||||
std::cout << "on one line" << std::endl;
|
std::cout << "on one line" << std::endl;
|
||||||
|
|
||||||
if(textSize.width + 2*textPadding < buttonsWidth)
|
if(textSize.width + 2*textPadding < buttonsWidth)
|
||||||
{
|
{
|
||||||
std::cout << "width = buttonsWidth" << std::endl;
|
std::cout << "width = buttonsWidth" << std::endl;
|
||||||
|
@ -272,48 +271,48 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
mainWidgetSize.width = textSize.width + 3*textPadding;
|
mainWidgetSize.width = textSize.width + 3*textPadding;
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
MyGUI::IntCoord absCoord;
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
||||||
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
|
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
mMainWidget->setCoord(absCoord);
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
||||||
messageWidgetCoord.top = textPadding;
|
messageWidgetCoord.top = textPadding;
|
||||||
mMessageWidget->setCoord(messageWidgetCoord);
|
mMessageWidget->setCoord(messageWidgetCoord);
|
||||||
|
|
||||||
mMessageWidget->setSize(textSize);
|
mMessageWidget->setSize(textSize);
|
||||||
|
|
||||||
MyGUI::IntCoord buttonCord;
|
MyGUI::IntCoord buttonCord;
|
||||||
MyGUI::IntSize buttonSize(0, buttonHeight);
|
MyGUI::IntSize buttonSize(0, buttonHeight);
|
||||||
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
|
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
|
||||||
|
|
||||||
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
||||||
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
||||||
{
|
{
|
||||||
buttonCord.left = left;
|
buttonCord.left = left;
|
||||||
buttonCord.top = textSize.height + textButtonPadding;
|
buttonCord.top = textSize.height + textButtonPadding;
|
||||||
|
|
||||||
buttonSize.width = (*button)->_getTextSize().width + 2*buttonPadding;
|
buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding;
|
||||||
buttonSize.height = (*button)->_getTextSize().height + 2*buttonPadding;
|
buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding;
|
||||||
|
|
||||||
(*button)->setCoord(buttonCord);
|
(*button)->setCoord(buttonCord);
|
||||||
(*button)->setSize(buttonSize);
|
(*button)->setSize(buttonSize);
|
||||||
|
|
||||||
left += buttonSize.width + buttonLeftPadding;
|
left += buttonSize.width + buttonLeftPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// among each other
|
// among each other
|
||||||
|
|
||||||
if(biggestButtonWidth > textSize.width) {
|
if(biggestButtonWidth > textSize.width) {
|
||||||
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
|
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
|
||||||
}
|
}
|
||||||
|
@ -321,46 +320,46 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
mainWidgetSize.width = textSize.width + 3*textPadding;
|
mainWidgetSize.width = textSize.width + 3*textPadding;
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
|
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
|
||||||
|
|
||||||
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
|
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
|
||||||
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
MyGUI::IntCoord absCoord;
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
mMainWidget->setCoord(absCoord);
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
||||||
messageWidgetCoord.top = textPadding;
|
messageWidgetCoord.top = textPadding;
|
||||||
mMessageWidget->setCoord(messageWidgetCoord);
|
mMessageWidget->setCoord(messageWidgetCoord);
|
||||||
|
|
||||||
mMessageWidget->setSize(textSize);
|
mMessageWidget->setSize(textSize);
|
||||||
|
|
||||||
MyGUI::IntCoord buttonCord;
|
MyGUI::IntCoord buttonCord;
|
||||||
MyGUI::IntSize buttonSize(0, buttonHeight);
|
MyGUI::IntSize buttonSize(0, buttonHeight);
|
||||||
|
|
||||||
int top = textButtonPadding + buttonTopPadding + textSize.height;
|
int top = textButtonPadding + buttonTopPadding + textSize.height;
|
||||||
|
|
||||||
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
||||||
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
||||||
{
|
{
|
||||||
buttonSize.width = (*button)->_getTextSize().width + buttonPadding*2;
|
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2;
|
||||||
buttonSize.height = (*button)->_getTextSize().height + buttonPadding*2;
|
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2;
|
||||||
|
|
||||||
buttonCord.top = top;
|
buttonCord.top = top;
|
||||||
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
|
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
|
||||||
|
|
||||||
(*button)->setCoord(buttonCord);
|
(*button)->setCoord(buttonCord);
|
||||||
(*button)->setSize(buttonSize);
|
(*button)->setSize(buttonSize);
|
||||||
|
|
||||||
top += buttonSize.height + 2*buttonTopPadding;
|
top += buttonSize.height + 2*buttonTopPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,8 +386,3 @@ int InteractiveMessageBox::readPressedButton ()
|
||||||
mButtonPressed = -1;
|
mButtonPressed = -1;
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "window_base.hpp"
|
#include "window_base.hpp"
|
||||||
#include "window_manager.hpp"
|
#include "window_manager.hpp"
|
||||||
|
|
||||||
|
#undef MessageBox
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
|
||||||
headRotate->setScrollRange(50);
|
headRotate->setScrollRange(50);
|
||||||
headRotate->setScrollPosition(20);
|
headRotate->setScrollPosition(20);
|
||||||
headRotate->setScrollViewPage(10);
|
headRotate->setScrollViewPage(10);
|
||||||
headRotate->eventScrollChangePosition = MyGUI::newDelegate(this, &RaceDialog::onHeadRotate);
|
headRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate);
|
||||||
|
|
||||||
// Set up next/previous buttons
|
// Set up next/previous buttons
|
||||||
MyGUI::ButtonPtr prevButton, nextButton;
|
MyGUI::ButtonPtr prevButton, nextButton;
|
||||||
|
@ -42,27 +42,27 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
|
||||||
setText("GenderChoiceT", mWindowManager.getGameSettingString("sRaceMenu2", "Change Sex"));
|
setText("GenderChoiceT", mWindowManager.getGameSettingString("sRaceMenu2", "Change Sex"));
|
||||||
getWidget(prevButton, "PrevGenderButton");
|
getWidget(prevButton, "PrevGenderButton");
|
||||||
getWidget(nextButton, "NextGenderButton");
|
getWidget(nextButton, "NextGenderButton");
|
||||||
prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousGender);
|
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousGender);
|
||||||
nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextGender);
|
nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextGender);
|
||||||
|
|
||||||
setText("FaceChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Face"));
|
setText("FaceChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Face"));
|
||||||
getWidget(prevButton, "PrevFaceButton");
|
getWidget(prevButton, "PrevFaceButton");
|
||||||
getWidget(nextButton, "NextFaceButton");
|
getWidget(nextButton, "NextFaceButton");
|
||||||
prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace);
|
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace);
|
||||||
nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace);
|
nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace);
|
||||||
|
|
||||||
setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair"));
|
setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair"));
|
||||||
getWidget(prevButton, "PrevHairButton");
|
getWidget(prevButton, "PrevHairButton");
|
||||||
getWidget(nextButton, "NextHairButton");
|
getWidget(nextButton, "NextHairButton");
|
||||||
prevButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair);
|
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair);
|
||||||
nextButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onSelectNextHair);
|
nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextHair);
|
||||||
|
|
||||||
setText("RaceT", mWindowManager.getGameSettingString("sRaceMenu4", "Race"));
|
setText("RaceT", mWindowManager.getGameSettingString("sRaceMenu4", "Race"));
|
||||||
getWidget(raceList, "RaceList");
|
getWidget(raceList, "RaceList");
|
||||||
raceList->setScrollVisible(true);
|
raceList->setScrollVisible(true);
|
||||||
raceList->eventListSelectAccept = MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
raceList->eventListSelectAccept += MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
||||||
raceList->eventListMouseItemActivate = MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
raceList->eventListMouseItemActivate += MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
||||||
raceList->eventListChangePosition = MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
raceList->eventListChangePosition += MyGUI::newDelegate(this, &RaceDialog::onSelectRace);
|
||||||
|
|
||||||
setText("SkillsT", mWindowManager.getGameSettingString("sBonusSkillTitle", "Skill Bonus"));
|
setText("SkillsT", mWindowManager.getGameSettingString("sBonusSkillTitle", "Skill Bonus"));
|
||||||
getWidget(skillList, "SkillList");
|
getWidget(skillList, "SkillList");
|
||||||
|
@ -72,11 +72,11 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
|
||||||
|
|
||||||
updateRaces();
|
updateRaces();
|
||||||
updateSkills();
|
updateSkills();
|
||||||
|
@ -157,7 +157,7 @@ void RaceDialog::onBackClicked(MyGUI::Widget* _sender)
|
||||||
eventBack();
|
eventBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onHeadRotate(MyGUI::VScroll*, size_t _position)
|
void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position)
|
||||||
{
|
{
|
||||||
// TODO: Rotate head
|
// TODO: Rotate head
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
||||||
hairIndex = wrap(hairIndex - 1, hairCount);
|
hairIndex = wrap(hairIndex - 1, hairCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectRace(MyGUI::List* _sender, size_t _index)
|
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -54,7 +54,7 @@ namespace MWGui
|
||||||
EventHandle_Void eventBack;
|
EventHandle_Void eventBack;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onHeadRotate(MyGUI::VScroll* _sender, size_t _position);
|
void onHeadRotate(MyGUI::ScrollBar* _sender, size_t _position);
|
||||||
|
|
||||||
void onSelectPreviousGender(MyGUI::Widget* _sender);
|
void onSelectPreviousGender(MyGUI::Widget* _sender);
|
||||||
void onSelectNextGender(MyGUI::Widget* _sender);
|
void onSelectNextGender(MyGUI::Widget* _sender);
|
||||||
|
@ -65,7 +65,7 @@ namespace MWGui
|
||||||
void onSelectPreviousHair(MyGUI::Widget* _sender);
|
void onSelectPreviousHair(MyGUI::Widget* _sender);
|
||||||
void onSelectNextHair(MyGUI::Widget* _sender);
|
void onSelectNextHair(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
void onSelectRace(MyGUI::List* _sender, size_t _index);
|
void onSelectRace(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
@ -76,8 +76,8 @@ namespace MWGui
|
||||||
void updateSpellPowers();
|
void updateSpellPowers();
|
||||||
|
|
||||||
MyGUI::CanvasPtr appearanceBox;
|
MyGUI::CanvasPtr appearanceBox;
|
||||||
MyGUI::ListPtr raceList;
|
MyGUI::ListBox* raceList;
|
||||||
MyGUI::HScrollPtr headRotate;
|
MyGUI::ScrollBar* headRotate;
|
||||||
|
|
||||||
MyGUI::WidgetPtr skillList;
|
MyGUI::WidgetPtr skillList;
|
||||||
std::vector<MyGUI::WidgetPtr> skillItems;
|
std::vector<MyGUI::WidgetPtr> skillItems;
|
||||||
|
|
|
@ -28,22 +28,22 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
|
||||||
getWidget(nameWidget, "NameText");
|
getWidget(nameWidget, "NameText");
|
||||||
getWidget(button, "NameButton");
|
getWidget(button, "NameButton");
|
||||||
button->setCaption(mWindowManager.getGameSettingString("sName", ""));
|
button->setCaption(mWindowManager.getGameSettingString("sName", ""));
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);;
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);;
|
||||||
|
|
||||||
getWidget(raceWidget, "RaceText");
|
getWidget(raceWidget, "RaceText");
|
||||||
getWidget(button, "RaceButton");
|
getWidget(button, "RaceButton");
|
||||||
button->setCaption(mWindowManager.getGameSettingString("sRace", ""));
|
button->setCaption(mWindowManager.getGameSettingString("sRace", ""));
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);;
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);;
|
||||||
|
|
||||||
getWidget(classWidget, "ClassText");
|
getWidget(classWidget, "ClassText");
|
||||||
getWidget(button, "ClassButton");
|
getWidget(button, "ClassButton");
|
||||||
button->setCaption(mWindowManager.getGameSettingString("sClass", ""));
|
button->setCaption(mWindowManager.getGameSettingString("sClass", ""));
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);;
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);;
|
||||||
|
|
||||||
getWidget(birthSignWidget, "SignText");
|
getWidget(birthSignWidget, "SignText");
|
||||||
getWidget(button, "SignButton");
|
getWidget(button, "SignButton");
|
||||||
button->setCaption(mWindowManager.getGameSettingString("sBirthSign", ""));
|
button->setCaption(mWindowManager.getGameSettingString("sBirthSign", ""));
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);;
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);;
|
||||||
|
|
||||||
// Setup dynamic stats
|
// Setup dynamic stats
|
||||||
getWidget(health, "Health");
|
getWidget(health, "Health");
|
||||||
|
@ -75,25 +75,25 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
|
||||||
getWidget(skillClientWidget, "SkillClient");
|
getWidget(skillClientWidget, "SkillClient");
|
||||||
getWidget(skillScrollerWidget, "SkillScroller");
|
getWidget(skillScrollerWidget, "SkillScroller");
|
||||||
|
|
||||||
skillScrollerWidget->eventScrollChangePosition = MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition);
|
skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition);
|
||||||
updateScroller();
|
updateScroller();
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
skillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
|
skillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
|
||||||
skillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::StaticText*> (0)));
|
skillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<MyGUI::WindowPtr>(mMainWidget)->eventWindowChangeCoord = MyGUI::newDelegate(this, &ReviewDialog::onWindowResize);
|
static_cast<MyGUI::WindowPtr>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ReviewDialog::onWindowResize);
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr backButton;
|
MyGUI::ButtonPtr backButton;
|
||||||
getWidget(backButton, "BackButton");
|
getWidget(backButton, "BackButton");
|
||||||
backButton->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onBackClicked);
|
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked);
|
||||||
|
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReviewDialog::open()
|
void ReviewDialog::open()
|
||||||
|
@ -102,7 +102,7 @@ void ReviewDialog::open()
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReviewDialog::onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos)
|
void ReviewDialog::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
|
||||||
{
|
{
|
||||||
int diff = lastPos - pos;
|
int diff = lastPos - pos;
|
||||||
// Adjust position of all widget according to difference
|
// Adjust position of all widget according to difference
|
||||||
|
@ -176,7 +176,7 @@ void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const M
|
||||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
|
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
|
||||||
{
|
{
|
||||||
skillValues[skillId] = value;
|
skillValues[skillId] = value;
|
||||||
MyGUI::StaticTextPtr widget = skillWidgetMap[skillId];
|
MyGUI::TextBox* widget = skillWidgetMap[skillId];
|
||||||
if (widget)
|
if (widget)
|
||||||
{
|
{
|
||||||
float modified = value.getModified(), base = value.getBase();
|
float modified = value.getModified(), base = value.getBase();
|
||||||
|
@ -210,7 +210,7 @@ void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReviewDialog::setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value)
|
void ReviewDialog::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value)
|
||||||
{
|
{
|
||||||
widget->setCaption(value);
|
widget->setCaption(value);
|
||||||
if (style == CS_Super)
|
if (style == CS_Super)
|
||||||
|
@ -223,7 +223,7 @@ void ReviewDialog::setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style,
|
||||||
|
|
||||||
void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticImagePtr separator = skillClientWidget->createWidget<MyGUI::StaticImage>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
|
MyGUI::ImageBox* separator = skillClientWidget->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
|
||||||
skillWidgets.push_back(separator);
|
skillWidgets.push_back(separator);
|
||||||
|
|
||||||
coord1.top += separator->getHeight();
|
coord1.top += separator->getHeight();
|
||||||
|
@ -232,7 +232,7 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2
|
||||||
|
|
||||||
void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr groupWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
|
MyGUI::TextBox* groupWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
|
||||||
groupWidget->setCaption(label);
|
groupWidget->setCaption(label);
|
||||||
skillWidgets.push_back(groupWidget);
|
skillWidgets.push_back(groupWidget);
|
||||||
|
|
||||||
|
@ -240,14 +240,15 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M
|
||||||
coord2.top += lineHeight;
|
coord2.top += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::StaticTextPtr ReviewDialog::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr skillNameWidget, skillValueWidget;
|
MyGUI::TextBox* skillNameWidget;
|
||||||
|
MyGUI::TextBox* skillValueWidget;
|
||||||
|
|
||||||
skillNameWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandText", coord1, MyGUI::Align::Default);
|
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default);
|
||||||
skillNameWidget->setCaption(text);
|
skillNameWidget->setCaption(text);
|
||||||
|
|
||||||
skillValueWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandTextRight", coord2, MyGUI::Align::Default);
|
skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Default);
|
||||||
setStyledText(skillValueWidget, style, value);
|
setStyledText(skillValueWidget, style, value);
|
||||||
|
|
||||||
skillWidgets.push_back(skillNameWidget);
|
skillWidgets.push_back(skillNameWidget);
|
||||||
|
@ -261,9 +262,9 @@ MyGUI::StaticTextPtr ReviewDialog::addValueItem(const std::string text, const st
|
||||||
|
|
||||||
void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr skillNameWidget;
|
MyGUI::TextBox* skillNameWidget;
|
||||||
|
|
||||||
skillNameWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
|
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
|
||||||
skillNameWidget->setCaption(text);
|
skillNameWidget->setCaption(text);
|
||||||
|
|
||||||
skillWidgets.push_back(skillNameWidget);
|
skillWidgets.push_back(skillNameWidget);
|
||||||
|
@ -299,7 +300,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId
|
||||||
style = CS_Super;
|
style = CS_Super;
|
||||||
else if (modified < base)
|
else if (modified < base)
|
||||||
style = CS_Sub;
|
style = CS_Sub;
|
||||||
MyGUI::StaticTextPtr widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
|
MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
|
||||||
skillWidgetMap[skillId] = widget;
|
skillWidgetMap[skillId] = widget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ namespace MWGui
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate0 EventHandle_Void;
|
typedef delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
typedef delegates::CDelegate1<int> EventHandle_Int;
|
typedef delegates::CMultiDelegate1<int> EventHandle_Int;
|
||||||
|
|
||||||
/** Event : Back button clicked.\n
|
/** Event : Back button clicked.\n
|
||||||
signature : void method()\n
|
signature : void method()\n
|
||||||
|
@ -75,23 +75,23 @@ namespace MWGui
|
||||||
CS_Normal,
|
CS_Normal,
|
||||||
CS_Super
|
CS_Super
|
||||||
};
|
};
|
||||||
void setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value);
|
void setStyledText(MyGUI::TextBox* 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 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 addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
|
||||||
void addGroup(const std::string &label, 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);
|
MyGUI::TextBox* 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 addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
|
||||||
void updateScroller();
|
void updateScroller();
|
||||||
void updateSkillArea();
|
void updateSkillArea();
|
||||||
|
|
||||||
void onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos);
|
void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
|
||||||
void onWindowResize(MyGUI::Window* window);
|
void onWindowResize(MyGUI::Window* window);
|
||||||
|
|
||||||
static const int lineHeight;
|
static const int lineHeight;
|
||||||
|
|
||||||
MyGUI::StaticTextPtr nameWidget, raceWidget, classWidget, birthSignWidget;
|
MyGUI::TextBox *nameWidget, *raceWidget, *classWidget, *birthSignWidget;
|
||||||
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
||||||
MyGUI::VScrollPtr skillScrollerWidget;
|
MyGUI::ScrollBar* skillScrollerWidget;
|
||||||
int lastPos, clientHeight;
|
int lastPos, clientHeight;
|
||||||
|
|
||||||
Widgets::MWDynamicStatPtr health, magicka, fatigue;
|
Widgets::MWDynamicStatPtr health, magicka, fatigue;
|
||||||
|
@ -100,7 +100,7 @@ namespace MWGui
|
||||||
|
|
||||||
SkillList majorSkills, minorSkills, miscSkills;
|
SkillList majorSkills, minorSkills, miscSkills;
|
||||||
std::map<int, MWMechanics::Stat<float> > skillValues;
|
std::map<int, MWMechanics::Stat<float> > skillValues;
|
||||||
std::map<int, MyGUI::StaticTextPtr> skillWidgetMap;
|
std::map<int, MyGUI::TextBox*> skillWidgetMap;
|
||||||
std::string name, raceId, birthSignId;
|
std::string name, raceId, birthSignId;
|
||||||
ESM::Class klass;
|
ESM::Class klass;
|
||||||
std::vector<MyGUI::WidgetPtr> skillWidgets; //< Skills and other information
|
std::vector<MyGUI::WidgetPtr> skillWidgets; //< Skills and other information
|
||||||
|
|
|
@ -13,9 +13,22 @@ const int StatsWindow::lineHeight = 18;
|
||||||
|
|
||||||
StatsWindow::StatsWindow (WindowManager& parWindowManager)
|
StatsWindow::StatsWindow (WindowManager& parWindowManager)
|
||||||
: WindowBase("openmw_stats_window_layout.xml", parWindowManager)
|
: WindowBase("openmw_stats_window_layout.xml", parWindowManager)
|
||||||
|
, skillAreaWidget(NULL)
|
||||||
|
, skillClientWidget(NULL)
|
||||||
|
, skillScrollerWidget(NULL)
|
||||||
, lastPos(0)
|
, lastPos(0)
|
||||||
|
, clientHeight(0)
|
||||||
|
, majorSkills()
|
||||||
|
, minorSkills()
|
||||||
|
, miscSkills()
|
||||||
|
, skillValues()
|
||||||
|
, skillWidgetMap()
|
||||||
|
, factionWidgetMap()
|
||||||
|
, factions()
|
||||||
|
, birthSignId()
|
||||||
, reputation(0)
|
, reputation(0)
|
||||||
, bounty(0)
|
, bounty(0)
|
||||||
|
, skillWidgets()
|
||||||
{
|
{
|
||||||
setCoord(0,0,498, 342);
|
setCoord(0,0,498, 342);
|
||||||
|
|
||||||
|
@ -48,20 +61,20 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
|
||||||
getWidget(skillClientWidget, "SkillClient");
|
getWidget(skillClientWidget, "SkillClient");
|
||||||
getWidget(skillScrollerWidget, "SkillScroller");
|
getWidget(skillScrollerWidget, "SkillScroller");
|
||||||
|
|
||||||
skillScrollerWidget->eventScrollChangePosition = MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition);
|
skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition);
|
||||||
updateScroller();
|
updateScroller();
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
skillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
|
skillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
|
||||||
skillWidgetMap.insert(std::pair<int, MyGUI::StaticTextPtr>(i, nullptr));
|
skillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
||||||
t->eventWindowChangeCoord = MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
|
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos)
|
void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
|
||||||
{
|
{
|
||||||
int diff = lastPos - pos;
|
int diff = lastPos - pos;
|
||||||
// Adjust position of all widget according to difference
|
// Adjust position of all widget according to difference
|
||||||
|
@ -95,10 +108,10 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int
|
||||||
|
|
||||||
void StatsWindow::setPlayerName(const std::string& playerName)
|
void StatsWindow::setPlayerName(const std::string& playerName)
|
||||||
{
|
{
|
||||||
mMainWidget->setCaption(playerName);
|
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value)
|
void StatsWindow::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value)
|
||||||
{
|
{
|
||||||
widget->setCaption(value);
|
widget->setCaption(value);
|
||||||
if (style == CS_Super)
|
if (style == CS_Super)
|
||||||
|
@ -175,7 +188,7 @@ void StatsWindow::setValue (const std::string& id, int value)
|
||||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
||||||
{
|
{
|
||||||
skillValues[parSkill] = value;
|
skillValues[parSkill] = value;
|
||||||
MyGUI::StaticTextPtr widget = skillWidgetMap[(int)parSkill];
|
MyGUI::TextBox* widget = skillWidgetMap[(int)parSkill];
|
||||||
if (widget)
|
if (widget)
|
||||||
{
|
{
|
||||||
float modified = value.getModified(), base = value.getBase();
|
float modified = value.getModified(), base = value.getBase();
|
||||||
|
@ -221,7 +234,7 @@ void StatsWindow::setBirthSign (const std::string& signId)
|
||||||
|
|
||||||
void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticImagePtr separator = skillClientWidget->createWidget<MyGUI::StaticImage>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
|
MyGUI::ImageBox* separator = skillClientWidget->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
|
||||||
skillWidgets.push_back(separator);
|
skillWidgets.push_back(separator);
|
||||||
|
|
||||||
coord1.top += separator->getHeight();
|
coord1.top += separator->getHeight();
|
||||||
|
@ -230,7 +243,7 @@ void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
|
|
||||||
void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr groupWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
|
MyGUI::TextBox* groupWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
|
||||||
groupWidget->setCaption(label);
|
groupWidget->setCaption(label);
|
||||||
skillWidgets.push_back(groupWidget);
|
skillWidgets.push_back(groupWidget);
|
||||||
|
|
||||||
|
@ -238,14 +251,14 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
|
||||||
coord2.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::TextBox* StatsWindow::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr skillNameWidget, skillValueWidget;
|
MyGUI::TextBox *skillNameWidget, *skillValueWidget;
|
||||||
|
|
||||||
skillNameWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandText", coord1, MyGUI::Align::Default);
|
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default);
|
||||||
skillNameWidget->setCaption(text);
|
skillNameWidget->setCaption(text);
|
||||||
|
|
||||||
skillValueWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandTextRight", coord2, MyGUI::Align::Default);
|
skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Default);
|
||||||
setStyledText(skillValueWidget, style, value);
|
setStyledText(skillValueWidget, style, value);
|
||||||
|
|
||||||
skillWidgets.push_back(skillNameWidget);
|
skillWidgets.push_back(skillNameWidget);
|
||||||
|
@ -259,9 +272,9 @@ MyGUI::StaticTextPtr StatsWindow::addValueItem(const std::string text, const std
|
||||||
|
|
||||||
void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
|
||||||
{
|
{
|
||||||
MyGUI::StaticTextPtr skillNameWidget;
|
MyGUI::TextBox* skillNameWidget;
|
||||||
|
|
||||||
skillNameWidget = skillClientWidget->createWidget<MyGUI::StaticText>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
|
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
|
||||||
skillNameWidget->setCaption(text);
|
skillNameWidget->setCaption(text);
|
||||||
|
|
||||||
skillWidgets.push_back(skillNameWidget);
|
skillWidgets.push_back(skillNameWidget);
|
||||||
|
@ -297,7 +310,7 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId,
|
||||||
style = CS_Super;
|
style = CS_Super;
|
||||||
else if (modified < base)
|
else if (modified < base)
|
||||||
style = CS_Sub;
|
style = CS_Sub;
|
||||||
MyGUI::StaticTextPtr widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
|
MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
|
||||||
skillWidgetMap[skillId] = widget;
|
skillWidgetMap[skillId] = widget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,26 +49,26 @@ namespace MWGui
|
||||||
CS_Normal,
|
CS_Normal,
|
||||||
CS_Super
|
CS_Super
|
||||||
};
|
};
|
||||||
void setStyledText(MyGUI::StaticTextPtr widget, ColorStyle style, const std::string &value);
|
void setStyledText(MyGUI::TextBox* 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 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 addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
|
||||||
void addGroup(const std::string &label, 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);
|
MyGUI::TextBox* 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 addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
|
||||||
void updateScroller();
|
void updateScroller();
|
||||||
|
|
||||||
void onScrollChangePosition(MyGUI::VScrollPtr scroller, size_t pos);
|
void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
|
||||||
void onWindowResize(MyGUI::Window* window);
|
void onWindowResize(MyGUI::Window* window);
|
||||||
|
|
||||||
static const int lineHeight;
|
static const int lineHeight;
|
||||||
|
|
||||||
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
||||||
MyGUI::VScrollPtr skillScrollerWidget;
|
MyGUI::ScrollBar* skillScrollerWidget;
|
||||||
int lastPos, clientHeight;
|
int lastPos, clientHeight;
|
||||||
|
|
||||||
SkillList majorSkills, minorSkills, miscSkills;
|
SkillList majorSkills, minorSkills, miscSkills;
|
||||||
std::map<int, MWMechanics::Stat<float> > skillValues;
|
std::map<int, MWMechanics::Stat<float> > skillValues;
|
||||||
std::map<int, MyGUI::StaticTextPtr> skillWidgetMap;
|
std::map<int, MyGUI::TextBox*> skillWidgetMap;
|
||||||
std::map<std::string, MyGUI::WidgetPtr> factionWidgetMap;
|
std::map<std::string, MyGUI::WidgetPtr> factionWidgetMap;
|
||||||
FactionList factions; ///< Stores a list of factions and the current rank
|
FactionList factions; ///< Stores a list of factions and the current rank
|
||||||
std::string birthSignId;
|
std::string birthSignId;
|
||||||
|
|
|
@ -10,12 +10,12 @@ TextInputDialog::TextInputDialog(WindowManager& parWindowManager)
|
||||||
center();
|
center();
|
||||||
|
|
||||||
getWidget(textEdit, "TextEdit");
|
getWidget(textEdit, "TextEdit");
|
||||||
textEdit->eventEditSelectAccept = newDelegate(this, &TextInputDialog::onTextAccepted);
|
textEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted);
|
||||||
|
|
||||||
// TODO: These buttons should be managed by a Dialog class
|
// TODO: These buttons should be managed by a Dialog class
|
||||||
MyGUI::ButtonPtr okButton;
|
MyGUI::ButtonPtr okButton;
|
||||||
getWidget(okButton, "OKButton");
|
getWidget(okButton, "OKButton");
|
||||||
okButton->eventMouseButtonClick = MyGUI::newDelegate(this, &TextInputDialog::onOkClicked);
|
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked);
|
||||||
|
|
||||||
// Make sure the edit box has focus
|
// Make sure the edit box has focus
|
||||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit);
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit);
|
||||||
|
|
|
@ -62,24 +62,24 @@ void MWSkill::updateWidgets()
|
||||||
{
|
{
|
||||||
if (skillId == ESM::Skill::Length)
|
if (skillId == ESM::Skill::Length)
|
||||||
{
|
{
|
||||||
skillNameWidget->setCaption("");
|
static_cast<MyGUI::TextBox*>(skillNameWidget)->setCaption("");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const std::string &name = manager->getGameSettingString(ESM::Skill::sSkillNameIds[skillId], "");
|
const std::string &name = manager->getGameSettingString(ESM::Skill::sSkillNameIds[skillId], "");
|
||||||
skillNameWidget->setCaption(name);
|
static_cast<MyGUI::TextBox*>(skillNameWidget)->setCaption(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (skillValueWidget)
|
if (skillValueWidget)
|
||||||
{
|
{
|
||||||
SkillValue::Type modified = value.getModified(), base = value.getBase();
|
SkillValue::Type modified = value.getModified(), base = value.getBase();
|
||||||
skillValueWidget->setCaption(boost::lexical_cast<std::string>(modified));
|
static_cast<MyGUI::TextBox*>(skillValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
||||||
if (modified > base)
|
if (modified > base)
|
||||||
skillValueWidget->setState("increased");
|
skillValueWidget->_setWidgetState("increased");
|
||||||
else if (modified < base)
|
else if (modified < base)
|
||||||
skillValueWidget->setState("decreased");
|
skillValueWidget->_setWidgetState("decreased");
|
||||||
else
|
else
|
||||||
skillValueWidget->setState("normal");
|
skillValueWidget->_setWidgetState("normal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,59 +88,32 @@ void MWSkill::onClicked(MyGUI::Widget* _sender)
|
||||||
eventClicked(this);
|
eventClicked(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
MWSkill::~MWSkill()
|
MWSkill::~MWSkill()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWSkill::baseChangeWidgetSkin(ResourceSkin* _info)
|
void MWSkill::initialiseOverride()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
Base::initialiseOverride();
|
||||||
Base::baseChangeWidgetSkin(_info);
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSkill::initialiseWidgetSkin(ResourceSkin* _info)
|
assignWidget(skillNameWidget, "StatName");
|
||||||
{
|
assignWidget(skillValueWidget, "StatValue");
|
||||||
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
||||||
|
MyGUI::ButtonPtr button;
|
||||||
|
assignWidget(button, "StatNameButton");
|
||||||
|
if (button)
|
||||||
{
|
{
|
||||||
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
skillNameWidget = button;
|
||||||
if (name == "StatName")
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWSkill::onClicked);
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned");
|
|
||||||
skillNameWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "StatValue")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned");
|
|
||||||
skillValueWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "StatNameButton")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned");
|
|
||||||
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
||||||
skillNameWidget = button;
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWSkill::onClicked);
|
|
||||||
}
|
|
||||||
else if (name == "StatValueButton")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned");
|
|
||||||
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
||||||
skillNameWidget = button;
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWSkill::onClicked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MWSkill::shutdownWidgetSkin()
|
button = 0;
|
||||||
{
|
assignWidget(button, "StatValueButton");
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
skillNameWidget = button;
|
||||||
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWSkill::onClicked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MWAttribute */
|
/* MWAttribute */
|
||||||
|
@ -176,7 +149,7 @@ void MWAttribute::updateWidgets()
|
||||||
{
|
{
|
||||||
if (id < 0 || id >= 8)
|
if (id < 0 || id >= 8)
|
||||||
{
|
{
|
||||||
attributeNameWidget->setCaption("");
|
static_cast<MyGUI::TextBox*>(attributeNameWidget)->setCaption("");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -191,75 +164,48 @@ void MWAttribute::updateWidgets()
|
||||||
"sAttributeLuck"
|
"sAttributeLuck"
|
||||||
};
|
};
|
||||||
const std::string &name = manager->getGameSettingString(attributes[id], "");
|
const std::string &name = manager->getGameSettingString(attributes[id], "");
|
||||||
attributeNameWidget->setCaption(name);
|
static_cast<MyGUI::TextBox*>(attributeNameWidget)->setCaption(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attributeValueWidget)
|
if (attributeValueWidget)
|
||||||
{
|
{
|
||||||
AttributeValue::Type modified = value.getModified(), base = value.getBase();
|
AttributeValue::Type modified = value.getModified(), base = value.getBase();
|
||||||
attributeValueWidget->setCaption(boost::lexical_cast<std::string>(modified));
|
static_cast<MyGUI::TextBox*>(attributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
||||||
if (modified > base)
|
if (modified > base)
|
||||||
attributeValueWidget->setState("increased");
|
attributeValueWidget->_setWidgetState("increased");
|
||||||
else if (modified < base)
|
else if (modified < base)
|
||||||
attributeValueWidget->setState("decreased");
|
attributeValueWidget->_setWidgetState("decreased");
|
||||||
else
|
else
|
||||||
attributeValueWidget->setState("normal");
|
attributeValueWidget->_setWidgetState("normal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWAttribute::_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);
|
|
||||||
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
MWAttribute::~MWAttribute()
|
MWAttribute::~MWAttribute()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWAttribute::baseChangeWidgetSkin(ResourceSkin* _info)
|
void MWAttribute::initialiseOverride()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
Base::initialiseOverride();
|
||||||
Base::baseChangeWidgetSkin(_info);
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWAttribute::initialiseWidgetSkin(ResourceSkin* _info)
|
assignWidget(attributeNameWidget, "StatName");
|
||||||
{
|
assignWidget(attributeValueWidget, "StatValue");
|
||||||
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
||||||
|
MyGUI::ButtonPtr button;
|
||||||
|
assignWidget(button, "StatNameButton");
|
||||||
|
if (button)
|
||||||
{
|
{
|
||||||
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
attributeNameWidget = button;
|
||||||
if (name == "StatName")
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! attributeNameWidget, "widget already assigned");
|
|
||||||
attributeNameWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "StatValue")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! attributeValueWidget, "widget already assigned");
|
|
||||||
attributeValueWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "StatNameButton")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! attributeNameWidget, "widget already assigned");
|
|
||||||
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
||||||
attributeNameWidget = button;
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
|
||||||
}
|
|
||||||
else if (name == "StatValue")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! attributeValueWidget, "widget already assigned");
|
|
||||||
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
||||||
attributeNameWidget = button;
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MWAttribute::shutdownWidgetSkin()
|
button = 0;
|
||||||
{
|
assignWidget(button, "StatValueButton");
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
attributeValueWidget = button;
|
||||||
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MWSpell */
|
/* MWSpell */
|
||||||
|
@ -301,45 +247,20 @@ void MWSpell::updateWidgets()
|
||||||
const ESMS::ESMStore &store = mWindowManager->getStore();
|
const ESMS::ESMStore &store = mWindowManager->getStore();
|
||||||
const ESM::Spell *spell = store.spells.search(id);
|
const ESM::Spell *spell = store.spells.search(id);
|
||||||
if (spell)
|
if (spell)
|
||||||
spellNameWidget->setCaption(spell->name);
|
static_cast<MyGUI::TextBox*>(spellNameWidget)->setCaption(spell->name);
|
||||||
else
|
else
|
||||||
spellNameWidget->setCaption("");
|
static_cast<MyGUI::TextBox*>(spellNameWidget)->setCaption("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWSpell::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
void MWSpell::initialiseOverride()
|
||||||
{
|
{
|
||||||
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
Base::initialiseOverride();
|
||||||
|
|
||||||
initialiseWidgetSkin(_info);
|
assignWidget(spellNameWidget, "StatName");
|
||||||
}
|
}
|
||||||
|
|
||||||
MWSpell::~MWSpell()
|
MWSpell::~MWSpell()
|
||||||
{
|
|
||||||
shutdownWidgetSkin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSpell::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
||||||
{
|
|
||||||
shutdownWidgetSkin();
|
|
||||||
Base::baseChangeWidgetSkin(_info);
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSpell::initialiseWidgetSkin(ResourceSkin* _info)
|
|
||||||
{
|
|
||||||
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
||||||
{
|
|
||||||
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
||||||
if (name == "StatName")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! spellNameWidget, "widget already assigned");
|
|
||||||
spellNameWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSpell::shutdownWidgetSkin()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,10 +329,10 @@ void MWSpellEffect::updateWidgets()
|
||||||
spellLine += " on Touch";
|
spellLine += " on Touch";
|
||||||
else if (effect.range == ESM::RT_Target)
|
else if (effect.range == ESM::RT_Target)
|
||||||
spellLine += " on Target";
|
spellLine += " on Target";
|
||||||
textWidget->setCaption(spellLine);
|
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
textWidget->setCaption("");
|
static_cast<MyGUI::TextBox*>(textWidget)->setCaption("");
|
||||||
}
|
}
|
||||||
if (imageWidget)
|
if (imageWidget)
|
||||||
{
|
{
|
||||||
|
@ -421,45 +342,16 @@ void MWSpellEffect::updateWidgets()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWSpellEffect::_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);
|
|
||||||
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
MWSpellEffect::~MWSpellEffect()
|
MWSpellEffect::~MWSpellEffect()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWSpellEffect::baseChangeWidgetSkin(ResourceSkin* _info)
|
void MWSpellEffect::initialiseOverride()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
Base::initialiseOverride();
|
||||||
Base::baseChangeWidgetSkin(_info);
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSpellEffect::initialiseWidgetSkin(ResourceSkin* _info)
|
assignWidget(textWidget, "Text");
|
||||||
{
|
assignWidget(imageWidget, "Image");
|
||||||
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
||||||
{
|
|
||||||
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
||||||
if (name == "Text")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! textWidget, "widget already assigned");
|
|
||||||
textWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "Image")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! imageWidget, "widget already assigned");
|
|
||||||
imageWidget = (*iter)->castType<StaticImage>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWSpellEffect::shutdownWidgetSkin()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MWDynamicStat */
|
/* MWDynamicStat */
|
||||||
|
@ -491,60 +383,27 @@ void MWDynamicStat::setValue(int cur, int max_)
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
out << value << "/" << max;
|
out << value << "/" << max;
|
||||||
barTextWidget->setCaption(out.str().c_str());
|
static_cast<MyGUI::TextBox*>(barTextWidget)->setCaption(out.str().c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
barTextWidget->setCaption("");
|
static_cast<MyGUI::TextBox*>(barTextWidget)->setCaption("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MWDynamicStat::setTitle(const std::string text)
|
void MWDynamicStat::setTitle(const std::string text)
|
||||||
{
|
{
|
||||||
if (textWidget)
|
if (textWidget)
|
||||||
textWidget->setCaption(text);
|
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(text);
|
||||||
}
|
|
||||||
|
|
||||||
void MWDynamicStat::_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);
|
|
||||||
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWDynamicStat::~MWDynamicStat()
|
MWDynamicStat::~MWDynamicStat()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWDynamicStat::baseChangeWidgetSkin(ResourceSkin* _info)
|
void MWDynamicStat::initialiseOverride()
|
||||||
{
|
{
|
||||||
shutdownWidgetSkin();
|
Base::initialiseOverride();
|
||||||
Base::baseChangeWidgetSkin(_info);
|
|
||||||
initialiseWidgetSkin(_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWDynamicStat::initialiseWidgetSkin(ResourceSkin* _info)
|
assignWidget(textWidget, "Text");
|
||||||
{
|
assignWidget(barWidget, "Bar");
|
||||||
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
assignWidget(barTextWidget, "BarText");
|
||||||
{
|
|
||||||
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
||||||
if (name == "Text")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! textWidget, "widget already assigned");
|
|
||||||
textWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
else if (name == "Bar")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! barWidget, "widget already assigned");
|
|
||||||
barWidget = (*iter)->castType<Progress>();
|
|
||||||
}
|
|
||||||
else if (name == "BarText")
|
|
||||||
{
|
|
||||||
MYGUI_DEBUG_ASSERT( ! barTextWidget, "widget already assigned");
|
|
||||||
barTextWidget = (*iter)->castType<StaticText>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWDynamicStat::shutdownWidgetSkin()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
#include "../mwmechanics/stat.hpp"
|
#include "../mwmechanics/stat.hpp"
|
||||||
|
|
||||||
|
#undef MYGUI_EXPORT
|
||||||
|
#define MYGUI_EXPORT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file contains various custom widgets used in OpenMW.
|
This file contains various custom widgets used in OpenMW.
|
||||||
*/
|
*/
|
||||||
|
@ -38,26 +41,21 @@ namespace MWGui
|
||||||
const SkillValue& getSkillValue() const { return value; }
|
const SkillValue& getSkillValue() const { return value; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate1<MWSkill*> EventHandle_SkillVoid;
|
typedef delegates::CMultiDelegate1<MWSkill*> EventHandle_SkillVoid;
|
||||||
|
|
||||||
/** Event : Skill clicked.\n
|
/** Event : Skill clicked.\n
|
||||||
signature : void method(MWSkill* _sender)\n
|
signature : void method(MWSkill* _sender)\n
|
||||||
*/
|
*/
|
||||||
EventHandle_SkillVoid eventClicked;
|
EventHandle_SkillVoid eventClicked;
|
||||||
|
|
||||||
/*internal:*/
|
|
||||||
virtual void _initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSkill();
|
virtual ~MWSkill();
|
||||||
|
|
||||||
void baseChangeWidgetSkin(ResourceSkin* _info);
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
void onClicked(MyGUI::Widget* _sender);
|
void onClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseWidgetSkin(ResourceSkin* _info);
|
|
||||||
void shutdownWidgetSkin();
|
|
||||||
|
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
|
@ -85,26 +83,21 @@ namespace MWGui
|
||||||
const AttributeValue& getAttributeValue() const { return value; }
|
const AttributeValue& getAttributeValue() const { return value; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef delegates::CDelegate1<MWAttribute*> EventHandle_AttributeVoid;
|
typedef delegates::CMultiDelegate1<MWAttribute*> EventHandle_AttributeVoid;
|
||||||
|
|
||||||
/** Event : Attribute clicked.\n
|
/** Event : Attribute clicked.\n
|
||||||
signature : void method(MWAttribute* _sender)\n
|
signature : void method(MWAttribute* _sender)\n
|
||||||
*/
|
*/
|
||||||
EventHandle_AttributeVoid eventClicked;
|
EventHandle_AttributeVoid eventClicked;
|
||||||
|
|
||||||
/*internal:*/
|
|
||||||
virtual void _initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWAttribute();
|
virtual ~MWAttribute();
|
||||||
|
|
||||||
void baseChangeWidgetSkin(ResourceSkin* _info);
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
void onClicked(MyGUI::Widget* _sender);
|
void onClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseWidgetSkin(ResourceSkin* _info);
|
|
||||||
void shutdownWidgetSkin();
|
|
||||||
|
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
|
@ -130,23 +123,17 @@ namespace MWGui
|
||||||
|
|
||||||
const std::string &getSpellId() const { return id; }
|
const std::string &getSpellId() const { return id; }
|
||||||
|
|
||||||
/*internal:*/
|
|
||||||
virtual void _initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSpell();
|
virtual ~MWSpell();
|
||||||
|
|
||||||
void baseChangeWidgetSkin(ResourceSkin* _info);
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseWidgetSkin(ResourceSkin* _info);
|
|
||||||
void shutdownWidgetSkin();
|
|
||||||
|
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
WindowManager* mWindowManager;
|
WindowManager* mWindowManager;
|
||||||
std::string id;
|
std::string id;
|
||||||
MyGUI::StaticTextPtr spellNameWidget;
|
MyGUI::TextBox* spellNameWidget;
|
||||||
};
|
};
|
||||||
typedef MWSpell* MWSpellPtr;
|
typedef MWSpell* MWSpellPtr;
|
||||||
|
|
||||||
|
@ -163,24 +150,19 @@ namespace MWGui
|
||||||
|
|
||||||
const SpellEffectValue &getSpellEffect() const { return effect; }
|
const SpellEffectValue &getSpellEffect() const { return effect; }
|
||||||
|
|
||||||
/*internal:*/
|
|
||||||
virtual void _initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWSpellEffect();
|
virtual ~MWSpellEffect();
|
||||||
|
|
||||||
void baseChangeWidgetSkin(ResourceSkin* _info);
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseWidgetSkin(ResourceSkin* _info);
|
|
||||||
void shutdownWidgetSkin();
|
|
||||||
|
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
WindowManager* mWindowManager;
|
WindowManager* mWindowManager;
|
||||||
SpellEffectValue effect;
|
SpellEffectValue effect;
|
||||||
MyGUI::StaticImagePtr imageWidget;
|
MyGUI::ImageBox* imageWidget;
|
||||||
MyGUI::StaticTextPtr textWidget;
|
MyGUI::TextBox* textWidget;
|
||||||
};
|
};
|
||||||
typedef MWSpellEffect* MWSpellEffectPtr;
|
typedef MWSpellEffect* MWSpellEffectPtr;
|
||||||
|
|
||||||
|
@ -196,22 +178,17 @@ namespace MWGui
|
||||||
int getValue() const { return value; }
|
int getValue() const { return value; }
|
||||||
int getMax() const { return max; }
|
int getMax() const { return max; }
|
||||||
|
|
||||||
/*internal:*/
|
|
||||||
virtual void _initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWDynamicStat();
|
virtual ~MWDynamicStat();
|
||||||
|
|
||||||
void baseChangeWidgetSkin(ResourceSkin* _info);
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseWidgetSkin(ResourceSkin* _info);
|
|
||||||
void shutdownWidgetSkin();
|
|
||||||
|
|
||||||
int value, max;
|
int value, max;
|
||||||
MyGUI::StaticTextPtr textWidget;
|
MyGUI::TextBox* textWidget;
|
||||||
MyGUI::ProgressPtr barWidget;
|
MyGUI::ProgressPtr barWidget;
|
||||||
MyGUI::StaticTextPtr barTextWidget;
|
MyGUI::TextBox* barTextWidget;
|
||||||
};
|
};
|
||||||
typedef MWDynamicStat* MWDynamicStatPtr;
|
typedef MWDynamicStat* MWDynamicStatPtr;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ void WindowBase::open()
|
||||||
void WindowBase::center()
|
void WindowBase::center()
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
MyGUI::IntSize gameWindowSize = mWindowManager.getGui()->getViewSize();
|
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
MyGUI::IntCoord coord = mMainWidget->getCoord();
|
MyGUI::IntCoord coord = mMainWidget->getCoord();
|
||||||
coord.left = (gameWindowSize.width - coord.width)/2;
|
coord.left = (gameWindowSize.width - coord.width)/2;
|
||||||
coord.top = (gameWindowSize.height - coord.height)/2;
|
coord.top = (gameWindowSize.height - coord.height)/2;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace MWGui
|
||||||
WindowBase(const std::string& parLayout, WindowManager& parWindowManager);
|
WindowBase(const std::string& parLayout, WindowManager& parWindowManager);
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CDelegate1<WindowBase*> EventHandle_WindowBase;
|
typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase;
|
||||||
|
|
||||||
virtual void open();
|
virtual void open();
|
||||||
void center();
|
void center();
|
||||||
|
|
|
@ -22,27 +22,52 @@ using namespace MWGui;
|
||||||
|
|
||||||
WindowManager::WindowManager(MWWorld::Environment& environment,
|
WindowManager::WindowManager(MWWorld::Environment& environment,
|
||||||
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath)
|
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath)
|
||||||
: environment(environment)
|
: mGuiManager(NULL)
|
||||||
|
, environment(environment)
|
||||||
|
, hud(NULL)
|
||||||
|
, map(NULL)
|
||||||
|
, menu(NULL)
|
||||||
|
, stats(NULL)
|
||||||
|
, mMessageBoxManager(NULL)
|
||||||
|
, console(NULL)
|
||||||
|
, mJournal(NULL)
|
||||||
, dialogueWindow(nullptr)
|
, dialogueWindow(nullptr)
|
||||||
|
, mCharGen(NULL)
|
||||||
|
, playerClass()
|
||||||
|
, playerName()
|
||||||
|
, playerRaceId()
|
||||||
|
, playerBirthSignId()
|
||||||
|
, playerAttributes()
|
||||||
|
, playerMajorSkills()
|
||||||
|
, playerMinorSkills()
|
||||||
|
, playerSkillValues()
|
||||||
|
, playerHealth()
|
||||||
|
, playerMagicka()
|
||||||
|
, playerFatigue()
|
||||||
|
, gui(NULL)
|
||||||
, mode(GM_Game)
|
, mode(GM_Game)
|
||||||
, nextMode(GM_Game)
|
, nextMode(GM_Game)
|
||||||
, needModeChange(false)
|
, needModeChange(false)
|
||||||
|
, garbageDialogs()
|
||||||
, shown(GW_ALL)
|
, shown(GW_ALL)
|
||||||
, allowed(newGame ? GW_None : GW_ALL)
|
, allowed(newGame ? GW_None : GW_ALL)
|
||||||
|
, showFPSLevel(fpsLevel)
|
||||||
|
, mFPS(0.0f)
|
||||||
|
, mTriangleCount(0)
|
||||||
|
, mBatchCount(0)
|
||||||
{
|
{
|
||||||
showFPSLevel = fpsLevel;
|
|
||||||
|
|
||||||
// Set up the GUI system
|
// Set up the GUI system
|
||||||
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath);
|
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath);
|
||||||
gui = mGuiManager->getGui();
|
gui = mGuiManager->getGui();
|
||||||
|
|
||||||
//Register own widgets with MyGUI
|
//Register own widgets with MyGUI
|
||||||
MyGUI::FactoryManager::getInstance().registerFactory<DialogeHistory>("Widget");
|
MyGUI::FactoryManager::getInstance().registerFactory<DialogueHistory>("Widget");
|
||||||
|
|
||||||
// Get size info from the Gui object
|
// Get size info from the Gui object
|
||||||
assert(gui);
|
assert(gui);
|
||||||
int w = gui->getViewSize().width;
|
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
|
||||||
int h = gui->getViewSize().height;
|
int h = MyGUI::RenderManager::getInstance().getViewSize().height;
|
||||||
|
|
||||||
hud = new HUD(w,h, showFPSLevel);
|
hud = new HUD(w,h, showFPSLevel);
|
||||||
menu = new MainMenu(w,h);
|
menu = new MainMenu(w,h);
|
||||||
|
@ -51,6 +76,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
|
||||||
console = new Console(w,h, environment, extensions);
|
console = new Console(w,h, environment, extensions);
|
||||||
mJournal = new JournalWindow(*this);
|
mJournal = new JournalWindow(*this);
|
||||||
mMessageBoxManager = new MessageBoxManager(this);
|
mMessageBoxManager = new MessageBoxManager(this);
|
||||||
|
dialogueWindow = new DialogueWindow(*this,environment);
|
||||||
|
|
||||||
// The HUD is always on
|
// The HUD is always on
|
||||||
hud->setVisible(true);
|
hud->setVisible(true);
|
||||||
|
@ -149,9 +175,10 @@ void WindowManager::updateVisible()
|
||||||
stats->setVisible(false);
|
stats->setVisible(false);
|
||||||
console->disable();
|
console->disable();
|
||||||
mJournal->setVisible(false);
|
mJournal->setVisible(false);
|
||||||
|
dialogueWindow->setVisible(false);
|
||||||
|
|
||||||
// Mouse is visible whenever we're not in game mode
|
// Mouse is visible whenever we're not in game mode
|
||||||
gui->setVisiblePointer(isGuiMode());
|
MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
|
||||||
|
|
||||||
// If in game mode, don't show anything.
|
// If in game mode, don't show anything.
|
||||||
if(mode == GM_Game) //Use a switch/case structure
|
if(mode == GM_Game) //Use a switch/case structure
|
||||||
|
@ -195,11 +222,6 @@ void WindowManager::updateVisible()
|
||||||
|
|
||||||
if (mode == GM_Dialogue)
|
if (mode == GM_Dialogue)
|
||||||
{
|
{
|
||||||
if (!dialogueWindow)
|
|
||||||
{
|
|
||||||
dialogueWindow = new DialogueWindow(*this);
|
|
||||||
dialogueWindow->eventBye = MyGUI::newDelegate(this, &WindowManager::onDialogueWindowBye);
|
|
||||||
}
|
|
||||||
dialogueWindow->open();
|
dialogueWindow->open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -349,6 +371,7 @@ void WindowManager::updateSkillArea()
|
||||||
|
|
||||||
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
|
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
|
||||||
{
|
{
|
||||||
|
std::cout << "dialogue a la poubelle";
|
||||||
assert(dialog);
|
assert(dialog);
|
||||||
if (!dialog)
|
if (!dialog)
|
||||||
return;
|
return;
|
||||||
|
@ -387,7 +410,8 @@ void WindowManager::onDialogueWindowBye()
|
||||||
if (dialogueWindow)
|
if (dialogueWindow)
|
||||||
{
|
{
|
||||||
//FIXME set some state and stuff?
|
//FIXME set some state and stuff?
|
||||||
removeDialog(dialogueWindow);
|
//removeDialog(dialogueWindow);
|
||||||
|
dialogueWindow->setVisible(false);
|
||||||
}
|
}
|
||||||
setGuiMode(GM_Game);
|
setGuiMode(GM_Game);
|
||||||
}
|
}
|
||||||
|
@ -401,3 +425,47 @@ const ESMS::ESMStore& WindowManager::getStore() const
|
||||||
{
|
{
|
||||||
return environment.mWorld->getStore();
|
return environment.mWorld->getStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
if (!(cell->cell->data.flags & ESM::Cell::Interior))
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
if (cell->cell->name != "")
|
||||||
|
name = cell->cell->name;
|
||||||
|
else
|
||||||
|
name = cell->cell->region;
|
||||||
|
|
||||||
|
map->setCellName( name );
|
||||||
|
|
||||||
|
map->setCellPrefix("Cell");
|
||||||
|
hud->setCellPrefix("Cell");
|
||||||
|
map->setActiveCell( cell->cell->data.gridX, cell->cell->data.gridY );
|
||||||
|
hud->setActiveCell( cell->cell->data.gridX, cell->cell->data.gridY );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map->setCellName( cell->cell->name );
|
||||||
|
map->setCellPrefix( cell->cell->name );
|
||||||
|
hud->setCellPrefix( cell->cell->name );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::setInteriorMapTexture(const int x, const int y)
|
||||||
|
{
|
||||||
|
map->setActiveCell(x,y, true);
|
||||||
|
hud->setActiveCell(x,y, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::setPlayerPos(const float x, const float y)
|
||||||
|
{
|
||||||
|
map->setPlayerPos(x,y);
|
||||||
|
hud->setPlayerPos(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::setPlayerDir(const float x, const float y)
|
||||||
|
{
|
||||||
|
map->setPlayerDir(x,y);
|
||||||
|
hud->setPlayerDir(x,y);
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <openengine/ogre/renderer.hpp>
|
#include <openengine/ogre/renderer.hpp>
|
||||||
#include <openengine/gui/manager.hpp>
|
#include <openengine/gui/manager.hpp>
|
||||||
#include "../mwmechanics/stat.hpp"
|
#include "../mwmechanics/stat.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "mode.hpp"
|
#include "mode.hpp"
|
||||||
|
|
||||||
namespace MyGUI
|
namespace MyGUI
|
||||||
|
@ -124,6 +125,8 @@ namespace MWGui
|
||||||
updateVisible();
|
updateVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWGui::DialogueWindow* getDialogueWindow() {return dialogueWindow;}
|
||||||
|
|
||||||
MyGUI::Gui* getGui() const { return gui; }
|
MyGUI::Gui* getGui() const { return gui; }
|
||||||
|
|
||||||
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)
|
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)
|
||||||
|
@ -150,6 +153,12 @@ namespace MWGui
|
||||||
void setBounty (int bounty); ///< set the current bounty value
|
void setBounty (int bounty); ///< set the current bounty value
|
||||||
void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
|
void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
|
||||||
|
|
||||||
|
void changeCell(MWWorld::Ptr::CellStore* cell); ///< change the active cell
|
||||||
|
void setPlayerPos(const float x, const float y); ///< set player position in map space
|
||||||
|
void setPlayerDir(const float x, const float y); ///< set player view direction in map space
|
||||||
|
|
||||||
|
void setInteriorMapTexture(const int x, const int y);
|
||||||
|
///< set the index of the map texture that should be used (for interiors)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
|
void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
|
||||||
|
|
|
@ -8,6 +8,15 @@ using namespace Ogre;
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace NifOgre;
|
using namespace NifOgre;
|
||||||
|
|
||||||
|
Actors::~Actors(){
|
||||||
|
|
||||||
|
std::map<MWWorld::Ptr, Animation*>::iterator it = mAllActors.begin();
|
||||||
|
for (; it != mAllActors.end(); ++it) {
|
||||||
|
delete it->second;
|
||||||
|
it->second = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::setMwRoot(Ogre::SceneNode* root){
|
void Actors::setMwRoot(Ogre::SceneNode* root){
|
||||||
mMwRoot = root;
|
mMwRoot = root;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +70,7 @@ void Actors::insertCreature (const MWWorld::Ptr& ptr){
|
||||||
insertBegin(ptr, true, true);
|
insertBegin(ptr, true, true);
|
||||||
CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend);
|
CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend);
|
||||||
//mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim));
|
//mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim));
|
||||||
|
delete mAllActors[ptr];
|
||||||
mAllActors[ptr] = anim;
|
mAllActors[ptr] = anim;
|
||||||
//mAllActors.push_back(&anim);*/
|
//mAllActors.push_back(&anim);*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace MWRender{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){}
|
Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){}
|
||||||
~Actors(){}
|
~Actors();
|
||||||
void setMwRoot(Ogre::SceneNode* root);
|
void setMwRoot(Ogre::SceneNode* root);
|
||||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||||
void insertCreature (const MWWorld::Ptr& ptr);
|
void insertCreature (const MWWorld::Ptr& ptr);
|
||||||
|
|
|
@ -4,7 +4,30 @@
|
||||||
namespace MWRender{
|
namespace MWRender{
|
||||||
std::map<std::string, int> Animation::mUniqueIDs;
|
std::map<std::string, int> Animation::mUniqueIDs;
|
||||||
|
|
||||||
Animation::~Animation(){
|
Animation::Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend)
|
||||||
|
: insert(NULL)
|
||||||
|
, mRend(_rend)
|
||||||
|
, mEnvironment(_env)
|
||||||
|
, vecRotPos()
|
||||||
|
, shapeparts()
|
||||||
|
, time(0.0f)
|
||||||
|
, startTime(0.0f)
|
||||||
|
, stopTime(0.0f)
|
||||||
|
, animate(0)
|
||||||
|
, rindexI()
|
||||||
|
, tindexI()
|
||||||
|
, shapeNumber(0)
|
||||||
|
, shapeIndexI()
|
||||||
|
, shapes(NULL)
|
||||||
|
, entityparts()
|
||||||
|
, transformations(NULL)
|
||||||
|
, textmappings(NULL)
|
||||||
|
, base(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation::~Animation()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Animation::getUniqueID(std::string mesh){
|
std::string Animation::getUniqueID(std::string mesh){
|
||||||
|
@ -111,7 +134,6 @@ namespace MWRender{
|
||||||
|
|
||||||
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
||||||
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
||||||
std::vector<Ogre::Vector3>* allnormals = ©.normals;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +204,6 @@ namespace MWRender{
|
||||||
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
|
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
|
||||||
int verIndex = iter->first;
|
int verIndex = iter->first;
|
||||||
Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
|
Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
|
||||||
Ogre::Vector3 currentNormal = (*allnormals)[verIndex];
|
|
||||||
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
|
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
|
||||||
Ogre::Bone *bonePtr = 0;
|
Ogre::Bone *bonePtr = 0;
|
||||||
|
|
||||||
|
@ -276,7 +297,7 @@ namespace MWRender{
|
||||||
rotmult = bonePtr->getOrientation();
|
rotmult = bonePtr->getOrientation();
|
||||||
scale = bonePtr->getScale().x;
|
scale = bonePtr->getScale().x;
|
||||||
boneSequenceIter++;
|
boneSequenceIter++;
|
||||||
|
|
||||||
for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++)
|
for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++)
|
||||||
{
|
{
|
||||||
if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){
|
if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){
|
||||||
|
@ -390,7 +411,7 @@ namespace MWRender{
|
||||||
|
|
||||||
void Animation::handleAnimationTransforms(){
|
void Animation::handleAnimationTransforms(){
|
||||||
|
|
||||||
|
|
||||||
Ogre::SkeletonInstance* skel = base->getSkeleton();
|
Ogre::SkeletonInstance* skel = base->getSkeleton();
|
||||||
|
|
||||||
|
|
||||||
|
@ -430,11 +451,11 @@ namespace MWRender{
|
||||||
const std::vector<Ogre::Quaternion> & quats = iter->getQuat();
|
const std::vector<Ogre::Quaternion> & quats = iter->getQuat();
|
||||||
|
|
||||||
const std::vector<float> & ttime = iter->gettTime();
|
const std::vector<float> & ttime = iter->gettTime();
|
||||||
|
|
||||||
|
|
||||||
const std::vector<float> & rtime = iter->getrTime();
|
const std::vector<float> & rtime = iter->getrTime();
|
||||||
int rindexJ = rindexI[slot];
|
int rindexJ = rindexI[slot];
|
||||||
|
|
||||||
timeIndex(time, rtime, rindexI[slot], rindexJ, x2);
|
timeIndex(time, rtime, rindexI[slot], rindexJ, x2);
|
||||||
int tindexJ = tindexI[slot];
|
int tindexJ = tindexI[slot];
|
||||||
|
|
||||||
|
@ -447,10 +468,10 @@ namespace MWRender{
|
||||||
Ogre::Quaternion r;
|
Ogre::Quaternion r;
|
||||||
|
|
||||||
bool bTrans = translist1.size() > 0;
|
bool bTrans = translist1.size() > 0;
|
||||||
|
|
||||||
|
|
||||||
bool bQuats = quats.size() > 0;
|
bool bQuats = quats.size() > 0;
|
||||||
|
|
||||||
if(skel->hasBone(iter->getBonename())){
|
if(skel->hasBone(iter->getBonename())){
|
||||||
Ogre::Bone* bone = skel->getBone(iter->getBonename());
|
Ogre::Bone* bone = skel->getBone(iter->getBonename());
|
||||||
if(bTrans){
|
if(bTrans){
|
||||||
|
@ -467,10 +488,10 @@ namespace MWRender{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
slot++;
|
slot++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,14 +60,14 @@ class Animation{
|
||||||
std::string getUniqueID(std::string mesh);
|
std::string getUniqueID(std::string mesh);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend): mRend(_rend), mEnvironment(_env), animate(0){};
|
Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||||
virtual void runAnimation(float timepassed) = 0;
|
virtual void runAnimation(float timepassed) = 0;
|
||||||
void startScript(std::string groupname, int mode, int loops);
|
void startScript(std::string groupname, int mode, int loops);
|
||||||
void stopScript();
|
void stopScript();
|
||||||
|
|
||||||
|
|
||||||
~Animation();
|
virtual ~Animation();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace MWRender{
|
||||||
class CreatureAnimation: public Animation{
|
class CreatureAnimation: public Animation{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~CreatureAnimation();
|
virtual ~CreatureAnimation();
|
||||||
CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||||
virtual void runAnimation(float timepassed);
|
virtual void runAnimation(float timepassed);
|
||||||
|
|
||||||
|
|
305
apps/openmw/mwrender/localmap.cpp
Normal file
305
apps/openmw/mwrender/localmap.cpp
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
#include "localmap.hpp"
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
|
||||||
|
#include <OgreOverlayManager.h>
|
||||||
|
#include <OgreMaterialManager.h>
|
||||||
|
|
||||||
|
using namespace MWRender;
|
||||||
|
using namespace Ogre;
|
||||||
|
|
||||||
|
LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWWorld::Environment* env)
|
||||||
|
{
|
||||||
|
mRendering = rend;
|
||||||
|
mEnvironment = env;
|
||||||
|
|
||||||
|
mCellCamera = mRendering->getScene()->createCamera("CellCamera");
|
||||||
|
mCellCamera->setProjectionType(PT_ORTHOGRAPHIC);
|
||||||
|
// look down -y
|
||||||
|
const float sqrt0pt5 = 0.707106781;
|
||||||
|
mCellCamera->setOrientation(Quaternion(sqrt0pt5, -sqrt0pt5, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalMap::~LocalMap()
|
||||||
|
{
|
||||||
|
deleteBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::deleteBuffers()
|
||||||
|
{
|
||||||
|
mBuffers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::saveTexture(const std::string& texname, const std::string& filename)
|
||||||
|
{
|
||||||
|
TexturePtr tex = TextureManager::getSingleton().getByName(texname);
|
||||||
|
if (tex.isNull()) return;
|
||||||
|
HardwarePixelBufferSharedPtr readbuffer = tex->getBuffer();
|
||||||
|
readbuffer->lock(HardwareBuffer::HBL_NORMAL );
|
||||||
|
const PixelBox &readrefpb = readbuffer->getCurrentLock();
|
||||||
|
uchar *readrefdata = static_cast<uchar*>(readrefpb.data);
|
||||||
|
|
||||||
|
Image img;
|
||||||
|
img = img.loadDynamicImage (readrefdata, tex->getWidth(),
|
||||||
|
tex->getHeight(), tex->getFormat());
|
||||||
|
img.save("./" + filename);
|
||||||
|
|
||||||
|
readbuffer->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LocalMap::coordStr(const int x, const int y)
|
||||||
|
{
|
||||||
|
return StringConverter::toString(x) + "_" + StringConverter::toString(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::saveFogOfWar(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
if (!mInterior)
|
||||||
|
{
|
||||||
|
/*saveTexture("Cell_"+coordStr(mCellX, mCellY)+"_fog",
|
||||||
|
"Cell_"+coordStr(mCellX, mCellY)+"_fog.png");*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||||
|
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
|
||||||
|
/// \todo why is this workaround needed?
|
||||||
|
min *= 1.3;
|
||||||
|
max *= 1.3;
|
||||||
|
Vector2 length = max-min;
|
||||||
|
|
||||||
|
// divide into segments
|
||||||
|
const int segsX = std::ceil( length.x / sSize );
|
||||||
|
const int segsY = std::ceil( length.y / sSize );
|
||||||
|
|
||||||
|
for (int x=0; x<segsX; ++x)
|
||||||
|
{
|
||||||
|
for (int y=0; y<segsY; ++y)
|
||||||
|
{
|
||||||
|
/*saveTexture(
|
||||||
|
mInteriorName + "_" + coordStr(x,y) + "_fog",
|
||||||
|
mInteriorName + "_" + coordStr(x,y) + "_fog.png");*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
mInterior = false;
|
||||||
|
|
||||||
|
std::string name = "Cell_"+coordStr(cell->cell->data.gridX, cell->cell->data.gridY);
|
||||||
|
|
||||||
|
int x = cell->cell->data.gridX;
|
||||||
|
int y = cell->cell->data.gridY;
|
||||||
|
|
||||||
|
render((x+0.5)*sSize, (-y-0.5)*sSize, -10000, 10000, sSize, sSize, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
|
||||||
|
AxisAlignedBox bounds)
|
||||||
|
{
|
||||||
|
mInterior = true;
|
||||||
|
mBounds = bounds;
|
||||||
|
|
||||||
|
Vector2 z(bounds.getMaximum().y, bounds.getMinimum().y);
|
||||||
|
Vector2 min(bounds.getMinimum().x, bounds.getMinimum().z);
|
||||||
|
Vector2 max(bounds.getMaximum().x, bounds.getMaximum().z);
|
||||||
|
|
||||||
|
/// \todo why is this workaround needed?
|
||||||
|
min *= 1.3;
|
||||||
|
max *= 1.3;
|
||||||
|
|
||||||
|
Vector2 length = max-min;
|
||||||
|
Vector2 center(bounds.getCenter().x, bounds.getCenter().z);
|
||||||
|
|
||||||
|
// divide into segments
|
||||||
|
const int segsX = std::ceil( length.x / sSize );
|
||||||
|
const int segsY = std::ceil( length.y / sSize );
|
||||||
|
|
||||||
|
mInteriorName = cell->cell->name;
|
||||||
|
|
||||||
|
for (int x=0; x<segsX; ++x)
|
||||||
|
{
|
||||||
|
for (int y=0; y<segsY; ++y)
|
||||||
|
{
|
||||||
|
Vector2 start = min + Vector2(sSize*x,sSize*y);
|
||||||
|
Vector2 newcenter = start + 4096;
|
||||||
|
|
||||||
|
render(newcenter.x, newcenter.y, z.y, z.x, sSize, sSize,
|
||||||
|
cell->cell->name + "_" + coordStr(x,y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::render(const float x, const float y,
|
||||||
|
const float zlow, const float zhigh,
|
||||||
|
const float xw, const float yw, const std::string& texture)
|
||||||
|
{
|
||||||
|
// disable fog
|
||||||
|
// changing FOG_MODE is not a solution when using shaders, thus we have to push linear start/end
|
||||||
|
const float fStart = mRendering->getScene()->getFogStart();
|
||||||
|
const float fEnd = mRendering->getScene()->getFogEnd();
|
||||||
|
const ColourValue& clr = mRendering->getScene()->getFogColour();
|
||||||
|
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, 1000000, 10000000);
|
||||||
|
|
||||||
|
// make everything visible
|
||||||
|
mRendering->getScene()->setAmbientLight(ColourValue(1,1,1));
|
||||||
|
|
||||||
|
mCellCamera->setPosition(Vector3(x, zhigh+100000, y));
|
||||||
|
//mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 );
|
||||||
|
mCellCamera->setFarClipDistance(0); // infinite
|
||||||
|
|
||||||
|
mCellCamera->setOrthoWindow(xw, yw);
|
||||||
|
|
||||||
|
TexturePtr tex;
|
||||||
|
// try loading from memory
|
||||||
|
tex = TextureManager::getSingleton().getByName(texture);
|
||||||
|
if (tex.isNull())
|
||||||
|
{
|
||||||
|
// try loading from disk
|
||||||
|
//if (boost::filesystem::exists(texture+".jpg"))
|
||||||
|
//{
|
||||||
|
/// \todo
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
// render
|
||||||
|
tex = TextureManager::getSingleton().createManual(
|
||||||
|
texture,
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
TEX_TYPE_2D,
|
||||||
|
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
||||||
|
0,
|
||||||
|
PF_R8G8B8,
|
||||||
|
TU_RENDERTARGET);
|
||||||
|
|
||||||
|
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||||
|
rtt->setAutoUpdated(false);
|
||||||
|
Viewport* vp = rtt->addViewport(mCellCamera);
|
||||||
|
vp->setOverlaysEnabled(false);
|
||||||
|
vp->setShadowsEnabled(false);
|
||||||
|
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||||
|
//vp->setVisibilityMask( ... );
|
||||||
|
|
||||||
|
rtt->update();
|
||||||
|
|
||||||
|
// create "fog of war" texture
|
||||||
|
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
||||||
|
texture + "_fog",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
TEX_TYPE_2D,
|
||||||
|
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
||||||
|
0,
|
||||||
|
PF_A8R8G8B8,
|
||||||
|
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||||
|
|
||||||
|
// create a buffer to use for dynamic operations
|
||||||
|
std::vector<uint32> buffer;
|
||||||
|
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
||||||
|
|
||||||
|
// initialize to (0, 0, 0, 1)
|
||||||
|
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
||||||
|
{
|
||||||
|
buffer[p] = (255 << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||||
|
tex2->getBuffer()->unlock();
|
||||||
|
|
||||||
|
mBuffers[texture] = buffer;
|
||||||
|
|
||||||
|
// save to cache for next time
|
||||||
|
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// re-enable fog
|
||||||
|
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction)
|
||||||
|
{
|
||||||
|
if (sFogOfWarSkip != 0)
|
||||||
|
{
|
||||||
|
static int count=0;
|
||||||
|
if (++count % sFogOfWarSkip != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve the x,y grid coordinates the player is in
|
||||||
|
int x,y;
|
||||||
|
Vector2 pos(position.x, position.z);
|
||||||
|
if (!mInterior)
|
||||||
|
{
|
||||||
|
x = std::ceil(pos.x / sSize)-1;
|
||||||
|
y = std::ceil(-pos.y / sSize)-1;
|
||||||
|
mCellX = x;
|
||||||
|
mCellY = y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||||
|
min *= 1.3;
|
||||||
|
|
||||||
|
x = std::ceil((pos.x - min.x)/sSize)-1;
|
||||||
|
y = std::ceil((pos.y - min.y)/sSize)-1;
|
||||||
|
|
||||||
|
mEnvironment->mWindowManager->setInteriorMapTexture(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert from world coordinates to texture UV coordinates
|
||||||
|
float u,v;
|
||||||
|
std::string texName;
|
||||||
|
if (!mInterior)
|
||||||
|
{
|
||||||
|
u = std::abs((pos.x - (sSize*x))/sSize);
|
||||||
|
v = 1-std::abs((pos.y + (sSize*y))/sSize);
|
||||||
|
texName = "Cell_"+coordStr(x,y);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||||
|
min *= 1.3;
|
||||||
|
|
||||||
|
u = (pos.x - min.x - sSize*x)/sSize;
|
||||||
|
v = (pos.y - min.y - sSize*y)/sSize;
|
||||||
|
|
||||||
|
texName = mInteriorName + "_" + coordStr(x,y);
|
||||||
|
}
|
||||||
|
mEnvironment->mWindowManager->setPlayerPos(u, v);
|
||||||
|
mEnvironment->mWindowManager->setPlayerDir(direction.x, -direction.z);
|
||||||
|
|
||||||
|
// explore radius (squared)
|
||||||
|
const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution;
|
||||||
|
|
||||||
|
// get the appropriate fog of war texture
|
||||||
|
TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog");
|
||||||
|
if (!tex.isNull())
|
||||||
|
{
|
||||||
|
// get its buffer
|
||||||
|
if (mBuffers.find(texName) == mBuffers.end()) return;
|
||||||
|
int i=0;
|
||||||
|
for (int texV = 0; texV<sFogOfWarResolution; ++texV)
|
||||||
|
{
|
||||||
|
for (int texU = 0; texU<sFogOfWarResolution; ++texU)
|
||||||
|
{
|
||||||
|
float sqrDist = Math::Sqr(texU - u*sFogOfWarResolution) + Math::Sqr(texV - v*sFogOfWarResolution);
|
||||||
|
uint32 clr = mBuffers[texName][i];
|
||||||
|
uint8 alpha = (clr >> 24);
|
||||||
|
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
|
||||||
|
mBuffers[texName][i] = (uint32) (alpha << 24);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy to the texture
|
||||||
|
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||||
|
tex->getBuffer()->unlock();
|
||||||
|
}
|
||||||
|
}
|
100
apps/openmw/mwrender/localmap.hpp
Normal file
100
apps/openmw/mwrender/localmap.hpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#ifndef _GAME_RENDER_LOCALMAP_H
|
||||||
|
#define _GAME_RENDER_LOCALMAP_H
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
///
|
||||||
|
/// \brief Local map rendering
|
||||||
|
///
|
||||||
|
class LocalMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LocalMap(OEngine::Render::OgreRenderer*, MWWorld::Environment* env);
|
||||||
|
~LocalMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the local map for an exterior cell.
|
||||||
|
* @remarks It will either be loaded from a disk cache,
|
||||||
|
* or rendered if it is not already cached.
|
||||||
|
* @param exterior cell
|
||||||
|
*/
|
||||||
|
void requestMap (MWWorld::Ptr::CellStore* cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the local map for an interior cell.
|
||||||
|
* @remarks It will either be loaded from a disk cache,
|
||||||
|
* or rendered if it is not already cached.
|
||||||
|
* @param interior cell
|
||||||
|
* @param bounding box of the cell
|
||||||
|
*/
|
||||||
|
void requestMap (MWWorld::Ptr::CellStore* cell,
|
||||||
|
Ogre::AxisAlignedBox bounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the position & direction of the player.
|
||||||
|
* @remarks This is used to draw a "fog of war" effect
|
||||||
|
* to hide areas on the map the player has not discovered yet.
|
||||||
|
* @param position (OGRE coordinates)
|
||||||
|
* @param view direction (OGRE coordinates)
|
||||||
|
*/
|
||||||
|
void updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the fog of war for the current cell to disk.
|
||||||
|
* @remarks This should be called before loading a
|
||||||
|
* new cell, as well as when the game is quit.
|
||||||
|
* @param current cell
|
||||||
|
*/
|
||||||
|
void saveFogOfWar(MWWorld::Ptr::CellStore* cell);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OEngine::Render::OgreRenderer* mRendering;
|
||||||
|
MWWorld::Environment* mEnvironment;
|
||||||
|
|
||||||
|
// 1024*1024 pixels for a cell
|
||||||
|
static const int sMapResolution = 1024;
|
||||||
|
|
||||||
|
// the dynamic texture is a bottleneck, so don't set this too high
|
||||||
|
static const int sFogOfWarResolution = 32;
|
||||||
|
|
||||||
|
// frames to skip before rendering fog of war
|
||||||
|
static const int sFogOfWarSkip = 2;
|
||||||
|
|
||||||
|
// size of a map segment (for exteriors, 1 cell)
|
||||||
|
static const int sSize = 8192;
|
||||||
|
|
||||||
|
Ogre::Camera* mCellCamera;
|
||||||
|
|
||||||
|
void render(const float x, const float y,
|
||||||
|
const float zlow, const float zhigh,
|
||||||
|
const float xw, const float yw,
|
||||||
|
const std::string& texture);
|
||||||
|
|
||||||
|
void saveTexture(const std::string& texname, const std::string& filename);
|
||||||
|
|
||||||
|
std::string coordStr(const int x, const int y);
|
||||||
|
|
||||||
|
// a buffer for the "fog of war" texture of the current cell.
|
||||||
|
// interior cells could be divided into multiple textures,
|
||||||
|
// so we store in a map.
|
||||||
|
std::map <std::string, std::vector<Ogre::uint32> > mBuffers;
|
||||||
|
|
||||||
|
void deleteBuffers();
|
||||||
|
|
||||||
|
bool mInterior;
|
||||||
|
int mCellX, mCellY;
|
||||||
|
Ogre::AxisAlignedBox mBounds;
|
||||||
|
std::string mInteriorName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -20,7 +20,7 @@ class NpcAnimation: public Animation{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||||
~NpcAnimation();
|
virtual ~NpcAnimation();
|
||||||
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
|
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
|
||||||
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
|
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
|
||||||
virtual void runAnimation(float timepassed);
|
virtual void runAnimation(float timepassed);
|
||||||
|
|
|
@ -109,6 +109,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
// If it is set too low:
|
// If it is set too low:
|
||||||
// - there will be too many batches.
|
// - there will be too many batches.
|
||||||
sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500));
|
sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500));
|
||||||
|
|
||||||
|
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
|
||||||
|
mBounds[ptr.getCell()].merge(ent->getBoundingBox());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -116,6 +119,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||||
|
mBounds[ptr.getCell()].merge(insert->_getDerivedPosition());
|
||||||
|
|
||||||
mRenderer.getScene()->destroyEntity(ent);
|
mRenderer.getScene()->destroyEntity(ent);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +206,9 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
|
||||||
mRenderer.getScene()->destroyStaticGeometry (sg);
|
mRenderer.getScene()->destroyStaticGeometry (sg);
|
||||||
sg = 0;
|
sg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mBounds.find(store) != mBounds.end())
|
||||||
|
mBounds.erase(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
||||||
|
@ -212,3 +219,8 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
||||||
sg->build();
|
sg->build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
return mBounds[cell];
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Objects{
|
||||||
OEngine::Render::OgreRenderer &mRenderer;
|
OEngine::Render::OgreRenderer &mRenderer;
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
||||||
|
std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
|
||||||
Ogre::SceneNode* mMwRoot;
|
Ogre::SceneNode* mMwRoot;
|
||||||
bool mIsStatic;
|
bool mIsStatic;
|
||||||
static int uniqueID;
|
static int uniqueID;
|
||||||
|
@ -42,6 +43,9 @@ public:
|
||||||
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||||
void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius);
|
void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius);
|
||||||
|
|
||||||
|
Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
|
||||||
|
///< get a bounding box that encloses all objects in the specified cell
|
||||||
|
|
||||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||||
///< \return found?
|
///< \return found?
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
|
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
|
||||||
{
|
{
|
||||||
mRendering.createScene("PlayerCam", 55, 5);
|
mRendering.createScene("PlayerCam", 55, 5);
|
||||||
mTerrainManager = new TerrainManager(mRendering.getScene());
|
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
||||||
|
environment);
|
||||||
|
|
||||||
//The fog type must be set before any terrain objects are created as if the
|
//The fog type must be set before any terrain objects are created as if the
|
||||||
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
||||||
|
@ -56,10 +57,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||||
|
|
||||||
//mSkyManager = 0;
|
//mSkyManager = 0;
|
||||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
|
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||||
|
|
||||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||||
mSun = 0;
|
mSun = 0;
|
||||||
|
|
||||||
|
mLocalMap = new MWRender::LocalMap(&mRendering, &environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderingManager::~RenderingManager ()
|
RenderingManager::~RenderingManager ()
|
||||||
|
@ -68,6 +71,7 @@ RenderingManager::~RenderingManager ()
|
||||||
delete mPlayer;
|
delete mPlayer;
|
||||||
delete mSkyManager;
|
delete mSkyManager;
|
||||||
delete mTerrainManager;
|
delete mTerrainManager;
|
||||||
|
delete mLocalMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWRender::SkyManager* RenderingManager::getSkyManager()
|
MWRender::SkyManager* RenderingManager::getSkyManager()
|
||||||
|
@ -147,6 +151,8 @@ void RenderingManager::update (float duration){
|
||||||
mSkyManager->update(duration);
|
mSkyManager->update(duration);
|
||||||
|
|
||||||
mRendering.update(duration);
|
mRendering.update(duration);
|
||||||
|
|
||||||
|
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::skyEnable ()
|
void RenderingManager::skyEnable ()
|
||||||
|
@ -220,9 +226,14 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
|
||||||
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
|
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
|
||||||
{
|
{
|
||||||
/// \todo make the viewing distance and fog start/end configurable
|
/// \todo make the viewing distance and fog start/end configurable
|
||||||
float low = 3000 / density;
|
|
||||||
float high = 6200 / density;
|
// right now we load 3x3 cells, so the maximum viewing distance we
|
||||||
|
// can allow (to prevent objects suddenly popping up) equals:
|
||||||
|
// 8192 * 0.69
|
||||||
|
// ^ cell size ^ minimum density value used (clear weather)
|
||||||
|
float low = 5652.48 / density / 2.f;
|
||||||
|
float high = 5652.48 / density;
|
||||||
|
|
||||||
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);
|
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);
|
||||||
|
|
||||||
mRendering.getCamera()->setFarClipDistance ( high );
|
mRendering.getCamera()->setFarClipDistance ( high );
|
||||||
|
@ -334,4 +345,17 @@ void RenderingManager::setGlare(bool glare)
|
||||||
mSkyManager->setGlare(glare);
|
mSkyManager->setGlare(glare);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
if (!(cell->cell->data.flags & ESM::Cell::Interior))
|
||||||
|
mLocalMap->requestMap(cell);
|
||||||
|
else
|
||||||
|
mLocalMap->requestMap(cell, mObjects.getDimensions(cell));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
|
||||||
|
{
|
||||||
|
mLocalMap->saveFogOfWar(cell);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "objects.hpp"
|
#include "objects.hpp"
|
||||||
#include "actors.hpp"
|
#include "actors.hpp"
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
|
#include "localmap.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -76,6 +77,9 @@ class RenderingManager: private RenderingInterface {
|
||||||
/// when rebatching is needed and update automatically at the end of each frame.
|
/// when rebatching is needed and update automatically at the end of each frame.
|
||||||
void cellAdded (MWWorld::Ptr::CellStore *store);
|
void cellAdded (MWWorld::Ptr::CellStore *store);
|
||||||
|
|
||||||
|
void preCellChange (MWWorld::Ptr::CellStore* store);
|
||||||
|
///< this event is fired immediately before changing cell
|
||||||
|
|
||||||
void addObject (const MWWorld::Ptr& ptr);
|
void addObject (const MWWorld::Ptr& ptr);
|
||||||
void removeObject (const MWWorld::Ptr& ptr);
|
void removeObject (const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
@ -103,6 +107,9 @@ class RenderingManager: private RenderingInterface {
|
||||||
int skyGetSecundaPhase() const;
|
int skyGetSecundaPhase() const;
|
||||||
void skySetMoonColour (bool red);
|
void skySetMoonColour (bool red);
|
||||||
void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell);
|
void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||||
|
|
||||||
|
void requestMap (MWWorld::Ptr::CellStore* cell);
|
||||||
|
///< request the local map for a cell
|
||||||
|
|
||||||
/// configure fog according to cell
|
/// configure fog according to cell
|
||||||
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
|
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||||
|
@ -150,6 +157,8 @@ class RenderingManager: private RenderingInterface {
|
||||||
|
|
||||||
MWRender::Player *mPlayer;
|
MWRender::Player *mPlayer;
|
||||||
MWRender::Debugging mDebugging;
|
MWRender::Debugging mDebugging;
|
||||||
|
|
||||||
|
MWRender::LocalMap* mLocalMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,12 @@
|
||||||
|
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
// the speed at which the clouds are animated
|
|
||||||
#define CLOUD_SPEED 0.001
|
|
||||||
|
|
||||||
// this distance has to be set accordingly so that the
|
|
||||||
// celestial bodies are behind the clouds, but in front of the atmosphere
|
|
||||||
#define CELESTIAL_BODY_DISTANCE 1000.f
|
|
||||||
|
|
||||||
BillboardObject::BillboardObject( const String& textureName,
|
BillboardObject::BillboardObject( const String& textureName,
|
||||||
const float initialSize,
|
const float initialSize,
|
||||||
const Vector3& position,
|
const Vector3& position,
|
||||||
|
@ -50,7 +46,7 @@ void BillboardObject::setVisibility(const float visibility)
|
||||||
void BillboardObject::setPosition(const Vector3& pPosition)
|
void BillboardObject::setPosition(const Vector3& pPosition)
|
||||||
{
|
{
|
||||||
Vector3 normalised = pPosition.normalisedCopy();
|
Vector3 normalised = pPosition.normalisedCopy();
|
||||||
Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE;
|
Vector3 finalPosition = normalised * 1000.f;
|
||||||
|
|
||||||
mBBSet->setCommonDirection( -normalised );
|
mBBSet->setCommonDirection( -normalised );
|
||||||
|
|
||||||
|
@ -59,7 +55,8 @@ void BillboardObject::setPosition(const Vector3& pPosition)
|
||||||
|
|
||||||
Vector3 BillboardObject::getPosition() const
|
Vector3 BillboardObject::getPosition() const
|
||||||
{
|
{
|
||||||
return mNode->getPosition();
|
Vector3 p = mNode->_getDerivedPosition() - mNode->getParentSceneNode()->_getDerivedPosition();
|
||||||
|
return Vector3(p.x, -p.z, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BillboardObject::setColour(const ColourValue& pColour)
|
void BillboardObject::setColour(const ColourValue& pColour)
|
||||||
|
@ -84,7 +81,7 @@ void BillboardObject::init(const String& textureName,
|
||||||
{
|
{
|
||||||
SceneManager* sceneMgr = rootNode->getCreator();
|
SceneManager* sceneMgr = rootNode->getCreator();
|
||||||
|
|
||||||
Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
Vector3 finalPosition = position.normalisedCopy() * 1000.f;
|
||||||
|
|
||||||
static unsigned int bodyCount=0;
|
static unsigned int bodyCount=0;
|
||||||
|
|
||||||
|
@ -161,14 +158,20 @@ Moon::Moon( const String& textureName,
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
" out float4 oColor : COLOR, \n"
|
" out float4 oColor : COLOR, \n"
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform float4 skyColour, \n"
|
||||||
" uniform float4 diffuse, \n"
|
" uniform float4 diffuse, \n"
|
||||||
" uniform float4 emissive \n"
|
" uniform float4 emissive \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" float4 tex = tex2D(texture, uv); \n"
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
" oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n"
|
" oColor = float4(emissive.xyz,1) * tex; \n"
|
||||||
" float bump = pow((1-diffuse.a),4); \n"
|
// use a circle for the alpha (compute UV distance to center)
|
||||||
" oColor.rgb += float3(bump, bump, bump)*0.5; \n"
|
// looks a bit bad because its not filtered on the edges,
|
||||||
|
// but it's cheaper than a seperate alpha texture.
|
||||||
|
" float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n"
|
||||||
|
" oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n"
|
||||||
|
" oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour
|
||||||
|
" oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump
|
||||||
"}";
|
"}";
|
||||||
fshader->setSource(outStream2.str());
|
fshader->setSource(outStream2.str());
|
||||||
fshader->load();
|
fshader->load();
|
||||||
|
@ -186,15 +189,19 @@ void Moon::setType(const Moon::Type& type)
|
||||||
mType = type;
|
mType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Moon::setSkyColour(const Ogre::ColourValue& colour)
|
||||||
|
{
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("skyColour", colour);
|
||||||
|
}
|
||||||
|
|
||||||
/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
|
|
||||||
void Moon::setPhase(const Moon::Phase& phase)
|
void Moon::setPhase(const Moon::Phase& phase)
|
||||||
{
|
{
|
||||||
|
// Colour texture
|
||||||
Ogre::String textureName = "textures\\tx_";
|
Ogre::String textureName = "textures\\tx_";
|
||||||
|
|
||||||
if (mType == Moon::Type_Secunda) textureName += "secunda_";
|
if (mType == Moon::Type_Secunda) textureName += "secunda_";
|
||||||
else textureName += "masser_";
|
else textureName += "masser_";
|
||||||
|
|
||||||
if (phase == Moon::Phase_New) textureName += "new";
|
if (phase == Moon::Phase_New) textureName += "new";
|
||||||
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
|
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
|
||||||
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
|
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
|
||||||
|
@ -203,9 +210,9 @@ void Moon::setPhase(const Moon::Phase& phase)
|
||||||
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
|
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
|
||||||
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
|
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
|
||||||
else if (phase == Moon::Phase_Full) textureName += "full";
|
else if (phase == Moon::Phase_Full) textureName += "full";
|
||||||
|
|
||||||
textureName += ".dds";
|
textureName += ".dds";
|
||||||
|
|
||||||
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);
|
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);
|
||||||
|
|
||||||
mPhase = phase;
|
mPhase = phase;
|
||||||
|
@ -247,7 +254,7 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||||
// Get a pointer to the vertex colour
|
// Get a pointer to the vertex colour
|
||||||
ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex );
|
ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex );
|
||||||
|
|
||||||
unsigned char alpha;
|
unsigned char alpha=0;
|
||||||
if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
||||||
else if (meshType == 1)
|
else if (meshType == 1)
|
||||||
{
|
{
|
||||||
|
@ -285,9 +292,40 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||||
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env)
|
||||||
mGlareFade(0), mGlareEnabled(false)
|
: mEnvironment(env)
|
||||||
|
, mHour(0.0f)
|
||||||
|
, mDay(0)
|
||||||
|
, mMonth(0)
|
||||||
|
, mSun(NULL)
|
||||||
|
, mSunGlare(NULL)
|
||||||
|
, mMasser(NULL)
|
||||||
|
, mSecunda(NULL)
|
||||||
|
, mViewport(NULL)
|
||||||
|
, mRootNode(NULL)
|
||||||
|
, mSceneMgr(NULL)
|
||||||
|
, mAtmosphereDay(NULL)
|
||||||
|
, mAtmosphereNight(NULL)
|
||||||
|
, mCloudMaterial()
|
||||||
|
, mAtmosphereMaterial()
|
||||||
|
, mCloudFragmentShader()
|
||||||
|
, mClouds()
|
||||||
|
, mNextClouds()
|
||||||
|
, mCloudBlendFactor(0.0f)
|
||||||
|
, mCloudOpacity(0.0f)
|
||||||
|
, mCloudSpeed(0.0f)
|
||||||
|
, mStarsOpacity(0.0f)
|
||||||
|
, mThunderOverlay(NULL)
|
||||||
|
, mThunderTextureUnit(NULL)
|
||||||
|
, mRemainingTransitionTime(0.0f)
|
||||||
|
, mGlareFade(0.0f)
|
||||||
|
, mEnabled(true)
|
||||||
|
, mGlareEnabled(true)
|
||||||
|
, mSunEnabled(true)
|
||||||
|
, mMasserEnabled(true)
|
||||||
|
, mSecundaEnabled(true)
|
||||||
{
|
{
|
||||||
|
|
||||||
mViewport = pCamera->getViewport();
|
mViewport = pCamera->getViewport();
|
||||||
mSceneMgr = pMwRoot->getCreator();
|
mSceneMgr = pMwRoot->getCreator();
|
||||||
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
||||||
|
@ -301,7 +339,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
Pass* pass = material->getTechnique(0)->getPass(0);
|
Pass* pass = material->getTechnique(0)->getPass(0);
|
||||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
mThunderTextureUnit = pass->createTextureUnitState();
|
mThunderTextureUnit = pass->createTextureUnitState();
|
||||||
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour
|
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f));
|
||||||
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
||||||
OverlayManager& ovm = OverlayManager::getSingleton();
|
OverlayManager& ovm = OverlayManager::getSingleton();
|
||||||
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
||||||
|
@ -338,24 +376,11 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||||
mAtmosphereNight->attachObject(night1_ent);
|
mAtmosphereNight->attachObject(night1_ent);
|
||||||
|
|
||||||
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
|
|
||||||
{
|
|
||||||
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
|
|
||||||
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
|
||||||
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
|
|
||||||
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
|
|
||||||
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
|
||||||
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
|
|
||||||
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
|
||||||
|
|
||||||
mStarsMaterials[i] = mp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stars vertex shader
|
// Stars vertex shader
|
||||||
HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
"cg", GPT_VERTEX_PROGRAM);
|
"cg", GPT_VERTEX_PROGRAM);
|
||||||
vshader3->setParameter("profiles", "vs_2_x arbvp1");
|
stars_vp->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
vshader3->setParameter("entry_point", "main_vp");
|
stars_vp->setParameter("entry_point", "main_vp");
|
||||||
StringUtil::StrStreamType outStream4;
|
StringUtil::StrStreamType outStream4;
|
||||||
outStream4 <<
|
outStream4 <<
|
||||||
"void main_vp( \n"
|
"void main_vp( \n"
|
||||||
|
@ -371,10 +396,9 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
" oFade = (position.z > 50) ? 1.f : 0.f; \n"
|
" oFade = (position.z > 50) ? 1.f : 0.f; \n"
|
||||||
" oPosition = mul( worldViewProj, position ); \n"
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
"}";
|
"}";
|
||||||
vshader3->setSource(outStream4.str());
|
stars_vp->setSource(outStream4.str());
|
||||||
vshader3->load();
|
stars_vp->load();
|
||||||
vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName());
|
|
||||||
|
|
||||||
// Stars fragment shader
|
// Stars fragment shader
|
||||||
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
@ -399,7 +423,20 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
stars_fp->load();
|
stars_fp->load();
|
||||||
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||||
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
|
|
||||||
|
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
|
||||||
|
{
|
||||||
|
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
|
||||||
|
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName());
|
||||||
|
mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
|
||||||
|
mStarsMaterials[i] = mp;
|
||||||
|
}
|
||||||
|
|
||||||
// Atmosphere (day)
|
// Atmosphere (day)
|
||||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||||
|
@ -439,6 +476,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram("");
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||||
|
@ -494,7 +532,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
" uniform float4 emissive \n"
|
" uniform float4 emissive \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" uv += float2(1,1) * time * speed * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
" uv += float2(1,0) * time * speed * 0.003; \n" // Scroll in x direction
|
||||||
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||||
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
||||||
"}";
|
"}";
|
||||||
|
@ -548,7 +586,7 @@ void SkyManager::update(float duration)
|
||||||
if (!mEnabled) return;
|
if (!mEnabled) return;
|
||||||
|
|
||||||
// UV Scroll the clouds
|
// UV Scroll the clouds
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1);
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", mEnvironment->mWorld->getTimeScaleFactor()/30.f);
|
||||||
|
|
||||||
/// \todo improve this
|
/// \todo improve this
|
||||||
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
|
@ -583,6 +621,9 @@ void SkyManager::update(float duration)
|
||||||
mSun->setVisible(mSunEnabled);
|
mSun->setVisible(mSunEnabled);
|
||||||
mMasser->setVisible(mMasserEnabled);
|
mMasser->setVisible(mMasserEnabled);
|
||||||
mSecunda->setVisible(mSecundaEnabled);
|
mSecunda->setVisible(mSecundaEnabled);
|
||||||
|
|
||||||
|
// rotate the stars by 360 degrees every 4 days
|
||||||
|
mAtmosphereNight->roll(Degree(mEnvironment->mWorld->getTimeScaleFactor()*duration*360 / (3600*96.f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::enable()
|
void SkyManager::enable()
|
||||||
|
@ -647,6 +688,8 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
if (mSkyColour != weather.mSkyColor)
|
if (mSkyColour != weather.mSkyColor)
|
||||||
{
|
{
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
|
||||||
|
mMasser->setSkyColour(weather.mSkyColor);
|
||||||
|
mSecunda->setSkyColour(weather.mSkyColor);
|
||||||
mSkyColour = weather.mSkyColor;
|
mSkyColour = weather.mSkyColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,6 +720,7 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
strength = 1.f;
|
strength = 1.f;
|
||||||
|
|
||||||
mSunGlare->setVisibility(weather.mGlareView * strength);
|
mSunGlare->setVisibility(weather.mGlareView * strength);
|
||||||
|
mSun->setVisibility(strength);
|
||||||
|
|
||||||
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace MWRender
|
||||||
Ogre::SceneNode* rootNode
|
Ogre::SceneNode* rootNode
|
||||||
);
|
);
|
||||||
BillboardObject();
|
BillboardObject();
|
||||||
|
|
||||||
|
virtual ~BillboardObject() {}
|
||||||
|
|
||||||
void setColour(const Ogre::ColourValue& pColour);
|
void setColour(const Ogre::ColourValue& pColour);
|
||||||
void setPosition(const Ogre::Vector3& pPosition);
|
void setPosition(const Ogre::Vector3& pPosition);
|
||||||
|
@ -69,6 +71,8 @@ namespace MWRender
|
||||||
const Ogre::Vector3& position,
|
const Ogre::Vector3& position,
|
||||||
Ogre::SceneNode* rootNode
|
Ogre::SceneNode* rootNode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
virtual ~Moon() {}
|
||||||
|
|
||||||
enum Phase
|
enum Phase
|
||||||
{
|
{
|
||||||
|
@ -90,6 +94,7 @@ namespace MWRender
|
||||||
|
|
||||||
void setPhase(const Phase& phase);
|
void setPhase(const Phase& phase);
|
||||||
void setType(const Type& type);
|
void setType(const Type& type);
|
||||||
|
void setSkyColour(const Ogre::ColourValue& colour);
|
||||||
|
|
||||||
Phase getPhase() const;
|
Phase getPhase() const;
|
||||||
unsigned int getPhaseInt() const;
|
unsigned int getPhaseInt() const;
|
||||||
|
@ -102,7 +107,7 @@ namespace MWRender
|
||||||
class SkyManager
|
class SkyManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera);
|
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env);
|
||||||
~SkyManager();
|
~SkyManager();
|
||||||
|
|
||||||
void update(float duration);
|
void update(float duration);
|
||||||
|
@ -159,10 +164,11 @@ namespace MWRender
|
||||||
Ogre::Vector3 getRealSunPos();
|
Ogre::Vector3 getRealSunPos();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MWWorld::Environment* mEnvironment;
|
||||||
float mHour;
|
float mHour;
|
||||||
int mDay;
|
int mDay;
|
||||||
int mMonth;
|
int mMonth;
|
||||||
|
|
||||||
BillboardObject* mSun;
|
BillboardObject* mSun;
|
||||||
BillboardObject* mSunGlare;
|
BillboardObject* mSunGlare;
|
||||||
Moon* mMasser;
|
Moon* mMasser;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include <OgreTerrain.h>
|
#include <OgreTerrain.h>
|
||||||
#include <OgreTerrainGroup.h>
|
#include <OgreTerrainGroup.h>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
#include "terrainmaterial.hpp"
|
#include "terrainmaterial.hpp"
|
||||||
#include "terrain.hpp"
|
#include "terrain.hpp"
|
||||||
|
|
||||||
#include "components/esm/loadland.hpp"
|
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
|
@ -15,33 +15,33 @@ namespace MWRender
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
TerrainManager::TerrainManager(SceneManager* mgr)
|
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
|
||||||
|
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize))
|
||||||
{
|
{
|
||||||
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
|
|
||||||
|
|
||||||
TerrainMaterialGeneratorPtr matGen;
|
TerrainMaterialGeneratorPtr matGen;
|
||||||
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
|
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
|
||||||
matGen.bind(matGenP);
|
matGen.bind(matGenP);
|
||||||
mTerrainGlobals->setDefaultMaterialGenerator(matGen);
|
mTerrainGlobals.setDefaultMaterialGenerator(matGen);
|
||||||
|
|
||||||
TerrainMaterialGenerator::Profile* const activeProfile =
|
TerrainMaterialGenerator::Profile* const activeProfile =
|
||||||
mTerrainGlobals->getDefaultMaterialGenerator()
|
mTerrainGlobals.getDefaultMaterialGenerator()
|
||||||
->getActiveProfile();
|
->getActiveProfile();
|
||||||
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
|
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
|
||||||
|
|
||||||
//The pixel error should be as high as possible without it being noticed
|
//The pixel error should be as high as possible without it being noticed
|
||||||
//as it governs how fast mesh quality decreases.
|
//as it governs how fast mesh quality decreases.
|
||||||
mTerrainGlobals->setMaxPixelError(8);
|
mTerrainGlobals.setMaxPixelError(8);
|
||||||
|
|
||||||
mTerrainGlobals->setLayerBlendMapSize(32);
|
mTerrainGlobals.setLayerBlendMapSize(32);
|
||||||
mTerrainGlobals->setDefaultGlobalColourMapSize(65);
|
mTerrainGlobals.setDefaultGlobalColourMapSize(65);
|
||||||
|
|
||||||
//10 (default) didn't seem to be quite enough
|
//10 (default) didn't seem to be quite enough
|
||||||
mTerrainGlobals->setSkirtSize(128);
|
mTerrainGlobals.setSkirtSize(128);
|
||||||
|
|
||||||
//due to the sudden flick between composite and non composite textures,
|
//due to the sudden flick between composite and non composite textures,
|
||||||
//this seemed the distance where it wasn't too noticeable
|
//this seemed the distance where it wasn't too noticeable
|
||||||
mTerrainGlobals->setCompositeMapDistance(mWorldSize*2);
|
mTerrainGlobals.setCompositeMapDistance(mWorldSize*2);
|
||||||
|
|
||||||
mActiveProfile->setLightmapEnabled(false);
|
mActiveProfile->setLightmapEnabled(false);
|
||||||
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
||||||
|
@ -53,16 +53,11 @@ namespace MWRender
|
||||||
//disabled
|
//disabled
|
||||||
mActiveProfile->setCompositeMapEnabled(false);
|
mActiveProfile->setCompositeMapEnabled(false);
|
||||||
|
|
||||||
mTerrainGroup = OGRE_NEW TerrainGroup(mgr,
|
mTerrainGroup.setOrigin(Vector3(mWorldSize/2,
|
||||||
Terrain::ALIGN_X_Z,
|
|
||||||
mLandSize,
|
|
||||||
mWorldSize);
|
|
||||||
|
|
||||||
mTerrainGroup->setOrigin(Vector3(mWorldSize/2,
|
|
||||||
0,
|
0,
|
||||||
-mWorldSize/2));
|
-mWorldSize/2));
|
||||||
|
|
||||||
Terrain::ImportData& importSettings = mTerrainGroup->getDefaultImportSettings();
|
Terrain::ImportData& importSettings = mTerrainGroup.getDefaultImportSettings();
|
||||||
|
|
||||||
importSettings.inputBias = 0;
|
importSettings.inputBias = 0;
|
||||||
importSettings.terrainSize = mLandSize;
|
importSettings.terrainSize = mLandSize;
|
||||||
|
@ -77,22 +72,20 @@ namespace MWRender
|
||||||
|
|
||||||
TerrainManager::~TerrainManager()
|
TerrainManager::~TerrainManager()
|
||||||
{
|
{
|
||||||
OGRE_DELETE mTerrainGroup;
|
|
||||||
OGRE_DELETE mTerrainGlobals;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::setDiffuse(const ColourValue& diffuse)
|
void TerrainManager::setDiffuse(const ColourValue& diffuse)
|
||||||
{
|
{
|
||||||
mTerrainGlobals->setCompositeMapDiffuse(diffuse);
|
mTerrainGlobals.setCompositeMapDiffuse(diffuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::setAmbient(const ColourValue& ambient)
|
void TerrainManager::setAmbient(const ColourValue& ambient)
|
||||||
{
|
{
|
||||||
mTerrainGlobals->setCompositeMapAmbient(ambient);
|
mTerrainGlobals.setCompositeMapAmbient(ambient);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
@ -102,6 +95,12 @@ namespace MWRender
|
||||||
const int cellX = store->cell->getGridX();
|
const int cellX = store->cell->getGridX();
|
||||||
const int cellY = store->cell->getGridY();
|
const int cellY = store->cell->getGridY();
|
||||||
|
|
||||||
|
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
|
||||||
|
if ( land != NULL )
|
||||||
|
{
|
||||||
|
land->loadData();
|
||||||
|
}
|
||||||
|
|
||||||
//split the cell terrain into four segments
|
//split the cell terrain into four segments
|
||||||
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
|
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
|
||||||
|
|
||||||
|
@ -110,7 +109,7 @@ namespace MWRender
|
||||||
for ( int y = 0; y < 2; y++ )
|
for ( int y = 0; y < 2; y++ )
|
||||||
{
|
{
|
||||||
Terrain::ImportData terrainData =
|
Terrain::ImportData terrainData =
|
||||||
mTerrainGroup->getDefaultImportSettings();
|
mTerrainGroup.getDefaultImportSettings();
|
||||||
|
|
||||||
const int terrainX = cellX * 2 + x;
|
const int terrainX = cellX * 2 + x;
|
||||||
const int terrainY = cellY * 2 + y;
|
const int terrainY = cellY * 2 + y;
|
||||||
|
@ -122,42 +121,51 @@ namespace MWRender
|
||||||
mLandSize*mLandSize,
|
mLandSize*mLandSize,
|
||||||
MEMCATEGORY_GEOMETRY);
|
MEMCATEGORY_GEOMETRY);
|
||||||
|
|
||||||
//copy the height data row by row
|
if ( land != NULL )
|
||||||
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
|
|
||||||
{
|
{
|
||||||
//the offset of the current segment
|
//copy the height data row by row
|
||||||
const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
|
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
|
||||||
//offset of the row
|
{
|
||||||
terrainCopyY * ESM::Land::LAND_SIZE;
|
//the offset of the current segment
|
||||||
const size_t xOffset = x * (mLandSize-1);
|
const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
|
||||||
|
//offset of the row
|
||||||
|
terrainCopyY * ESM::Land::LAND_SIZE;
|
||||||
|
const size_t xOffset = x * (mLandSize-1);
|
||||||
|
|
||||||
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
|
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
|
||||||
&store->land[1][1]->landData->heights[yOffset + xOffset],
|
&land->landData->heights[yOffset + xOffset],
|
||||||
mLandSize*sizeof(float));
|
mLandSize*sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(terrainData.inputFloat, 0, mLandSize*mLandSize*sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint16_t, int> indexes;
|
std::map<uint16_t, int> indexes;
|
||||||
initTerrainTextures(&terrainData, store,
|
initTerrainTextures(&terrainData, cellX, cellY,
|
||||||
x * numTextures, y * numTextures,
|
x * numTextures, y * numTextures,
|
||||||
numTextures, indexes);
|
numTextures, indexes);
|
||||||
|
|
||||||
if (mTerrainGroup->getTerrain(terrainX, terrainY) == NULL)
|
if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL)
|
||||||
{
|
{
|
||||||
mTerrainGroup->defineTerrain(terrainX, terrainY, &terrainData);
|
mTerrainGroup.defineTerrain(terrainX, terrainY, &terrainData);
|
||||||
|
|
||||||
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
|
mTerrainGroup.loadTerrain(terrainX, terrainY, true);
|
||||||
|
|
||||||
Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY);
|
Terrain* terrain = mTerrainGroup.getTerrain(terrainX, terrainY);
|
||||||
initTerrainBlendMaps(terrain, store,
|
initTerrainBlendMaps(terrain,
|
||||||
|
cellX, cellY,
|
||||||
x * numTextures, y * numTextures,
|
x * numTextures, y * numTextures,
|
||||||
numTextures,
|
numTextures,
|
||||||
indexes);
|
indexes);
|
||||||
|
|
||||||
if ( store->land[1][1]->landData->usingColours )
|
if ( land->landData->usingColours )
|
||||||
{
|
{
|
||||||
// disable or enable global colour map (depends on available vertex colours)
|
// disable or enable global colour map (depends on available vertex colours)
|
||||||
mActiveProfile->setGlobalColourMapEnabled(true);
|
mActiveProfile->setGlobalColourMapEnabled(true);
|
||||||
TexturePtr vertex = getVertexColours(store,
|
TexturePtr vertex = getVertexColours(land,
|
||||||
|
cellX, cellY,
|
||||||
x*(mLandSize-1),
|
x*(mLandSize-1),
|
||||||
y*(mLandSize-1),
|
y*(mLandSize-1),
|
||||||
mLandSize);
|
mLandSize);
|
||||||
|
@ -177,7 +185,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mTerrainGroup->freeTemporaryResources();
|
mTerrainGroup.freeTemporaryResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
@ -188,8 +196,8 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for ( int y = 0; y < 2; y++ )
|
for ( int y = 0; y < 2; y++ )
|
||||||
{
|
{
|
||||||
mTerrainGroup->unloadTerrain(store->cell->getGridX() * 2 + x,
|
mTerrainGroup.unloadTerrain(store->cell->getGridX() * 2 + x,
|
||||||
store->cell->getGridY() * 2 + y);
|
store->cell->getGridY() * 2 + y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,11 +205,10 @@ namespace MWRender
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData,
|
void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
std::map<uint16_t, int>& indexes)
|
std::map<uint16_t, int>& indexes)
|
||||||
{
|
{
|
||||||
assert(store != NULL && "store must be a valid pointer");
|
|
||||||
assert(terrainData != NULL && "Must have valid terrain data");
|
assert(terrainData != NULL && "Must have valid terrain data");
|
||||||
assert(fromX >= 0 && fromY >= 0 &&
|
assert(fromX >= 0 && fromY >= 0 &&
|
||||||
"Can't get a terrain texture on terrain outside the current cell");
|
"Can't get a terrain texture on terrain outside the current cell");
|
||||||
|
@ -219,7 +226,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for ( int x = fromX - 1; x < fromX + size + 1; x++ )
|
for ( int x = fromX - 1; x < fromX + size + 1; x++ )
|
||||||
{
|
{
|
||||||
ltexIndexes.insert(getLtexIndexAt(store, x, y));
|
ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +251,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
//NB: All vtex ids are +1 compared to the ltex ids
|
//NB: All vtex ids are +1 compared to the ltex ids
|
||||||
|
|
||||||
assert( (int)store->landTextures->ltex.size() >= (int)ltexIndex - 1 &&
|
assert( (int)mEnvironment.mWorld->getStore().landTexts.getSize() >= (int)ltexIndex - 1 &&
|
||||||
"LAND.VTEX must be within the bounds of the LTEX array");
|
"LAND.VTEX must be within the bounds of the LTEX array");
|
||||||
|
|
||||||
std::string texture;
|
std::string texture;
|
||||||
|
@ -254,7 +261,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
texture = store->landTextures->ltex[ltexIndex-1].texture;
|
texture = mEnvironment.mWorld->getStore().landTexts.search(ltexIndex-1)->texture;
|
||||||
//TODO this is needed due to MWs messed up texture handling
|
//TODO this is needed due to MWs messed up texture handling
|
||||||
texture = texture.substr(0, texture.rfind(".")) + ".dds";
|
texture = texture.substr(0, texture.rfind(".")) + ".dds";
|
||||||
}
|
}
|
||||||
|
@ -280,11 +287,10 @@ namespace MWRender
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::initTerrainBlendMaps(Terrain* terrain,
|
void TerrainManager::initTerrainBlendMaps(Terrain* terrain,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
const std::map<uint16_t, int>& indexes)
|
const std::map<uint16_t, int>& indexes)
|
||||||
{
|
{
|
||||||
assert(store != NULL && "store must be a valid pointer");
|
|
||||||
assert(terrain != NULL && "Must have valid terrain");
|
assert(terrain != NULL && "Must have valid terrain");
|
||||||
assert(fromX >= 0 && fromY >= 0 &&
|
assert(fromX >= 0 && fromY >= 0 &&
|
||||||
"Can't get a terrain texture on terrain outside the current cell");
|
"Can't get a terrain texture on terrain outside the current cell");
|
||||||
|
@ -313,7 +319,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for ( int texX = fromX - 1; texX < fromX + size + 1; texX++ )
|
for ( int texX = fromX - 1; texX < fromX + size + 1; texX++ )
|
||||||
{
|
{
|
||||||
const uint16_t ltexIndex = getLtexIndexAt(store, texX, texY);
|
const uint16_t ltexIndex = getLtexIndexAt(cellX, cellY, texX, texY);
|
||||||
|
|
||||||
//check if it is the base texture (which isn't in the map) and
|
//check if it is the base texture (which isn't in the map) and
|
||||||
//if it is don't bother altering the blend map for it
|
//if it is don't bother altering the blend map for it
|
||||||
|
@ -332,8 +338,10 @@ namespace MWRender
|
||||||
float* const pBlend = terrain->getLayerBlendMap(layerIndex)
|
float* const pBlend = terrain->getLayerBlendMap(layerIndex)
|
||||||
->getBlendPointer();
|
->getBlendPointer();
|
||||||
|
|
||||||
for ( int y = -1; y < splatSize + 1; y++ ){
|
for ( int y = -1; y < splatSize + 1; y++ )
|
||||||
for ( int x = -1; x < splatSize + 1; x++ ){
|
{
|
||||||
|
for ( int x = -1; x < splatSize + 1; x++ )
|
||||||
|
{
|
||||||
|
|
||||||
//Note: Y is reversed
|
//Note: Y is reversed
|
||||||
const int splatY = blendMapSize - 1 - relY * splatSize - y;
|
const int splatY = blendMapSize - 1 - relY * splatSize - y;
|
||||||
|
@ -373,7 +381,7 @@ namespace MWRender
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
int TerrainManager::getLtexIndexAt(MWWorld::Ptr::CellStore* store,
|
int TerrainManager::getLtexIndexAt(int cellX, int cellY,
|
||||||
int x, int y)
|
int x, int y)
|
||||||
{
|
{
|
||||||
//check texture index falls within the 9 cell bounds
|
//check texture index falls within the 9 cell bounds
|
||||||
|
@ -386,12 +394,6 @@ namespace MWRender
|
||||||
y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
|
y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
|
||||||
"Trying to get land textures that are out of bounds");
|
"Trying to get land textures that are out of bounds");
|
||||||
|
|
||||||
assert(store != NULL && "Store pointer must be valid");
|
|
||||||
|
|
||||||
//default center cell is indexed at (1,1)
|
|
||||||
int cellX = 1;
|
|
||||||
int cellY = 1;
|
|
||||||
|
|
||||||
if ( x < 0 )
|
if ( x < 0 )
|
||||||
{
|
{
|
||||||
cellX--;
|
cellX--;
|
||||||
|
@ -414,22 +416,32 @@ namespace MWRender
|
||||||
y -= ESM::Land::LAND_TEXTURE_SIZE;
|
y -= ESM::Land::LAND_TEXTURE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return store->land[cellX][cellY]
|
|
||||||
->landData
|
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
|
||||||
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
if ( land != NULL )
|
||||||
|
{
|
||||||
|
land->loadData();
|
||||||
|
return land->landData
|
||||||
|
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
TexturePtr TerrainManager::getVertexColours(MWWorld::Ptr::CellStore* store,
|
TexturePtr TerrainManager::getVertexColours(ESM::Land* land,
|
||||||
int fromX, int fromY, int size)
|
int cellX, int cellY,
|
||||||
|
int fromX, int fromY, int size)
|
||||||
{
|
{
|
||||||
TextureManager* const texMgr = TextureManager::getSingletonPtr();
|
TextureManager* const texMgr = TextureManager::getSingletonPtr();
|
||||||
|
|
||||||
const std::string colourTextureName = "VtexColours_" +
|
const std::string colourTextureName = "VtexColours_" +
|
||||||
boost::lexical_cast<std::string>(store->cell->getGridX()) +
|
boost::lexical_cast<std::string>(cellX) +
|
||||||
"_" +
|
"_" +
|
||||||
boost::lexical_cast<std::string>(store->cell->getGridY()) +
|
boost::lexical_cast<std::string>(cellY) +
|
||||||
"_" +
|
"_" +
|
||||||
boost::lexical_cast<std::string>(fromX) +
|
boost::lexical_cast<std::string>(fromX) +
|
||||||
"_" +
|
"_" +
|
||||||
|
@ -451,26 +463,42 @@ namespace MWRender
|
||||||
const PixelBox& pixelBox = pixelBuffer->getCurrentLock();
|
const PixelBox& pixelBox = pixelBuffer->getCurrentLock();
|
||||||
|
|
||||||
uint8* pDest = static_cast<uint8*>(pixelBox.data);
|
uint8* pDest = static_cast<uint8*>(pixelBox.data);
|
||||||
|
|
||||||
const char* const colours = store->land[1][1]->landData->colours;
|
if ( land != NULL )
|
||||||
for ( int y = 0; y < size; y++ )
|
|
||||||
{
|
{
|
||||||
for ( int x = 0; x < size; x++ )
|
const char* const colours = land->landData->colours;
|
||||||
|
for ( int y = 0; y < size; y++ )
|
||||||
{
|
{
|
||||||
const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3;
|
for ( int x = 0; x < size; x++ )
|
||||||
|
{
|
||||||
|
const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3;
|
||||||
|
|
||||||
assert( colourOffset >= 0 && colourOffset < 65*65*3 &&
|
assert( colourOffset < 65*65*3 &&
|
||||||
"Colour offset is out of the expected bounds of record" );
|
"Colour offset is out of the expected bounds of record" );
|
||||||
|
|
||||||
const unsigned char r = colours[colourOffset + 0];
|
const unsigned char r = colours[colourOffset + 0];
|
||||||
const unsigned char g = colours[colourOffset + 1];
|
const unsigned char g = colours[colourOffset + 1];
|
||||||
const unsigned char b = colours[colourOffset + 2];
|
const unsigned char b = colours[colourOffset + 2];
|
||||||
|
|
||||||
//as is the case elsewhere we need to flip the y
|
//as is the case elsewhere we need to flip the y
|
||||||
const size_t imageOffset = (size - 1 - y)*size*4 + x*4;
|
const size_t imageOffset = (size - 1 - y)*size*4 + x*4;
|
||||||
pDest[imageOffset + 0] = b;
|
pDest[imageOffset + 0] = b;
|
||||||
pDest[imageOffset + 1] = g;
|
pDest[imageOffset + 1] = g;
|
||||||
pDest[imageOffset + 2] = r;
|
pDest[imageOffset + 2] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( int y = 0; y < size; y++ )
|
||||||
|
{
|
||||||
|
for ( int x = 0; x < size; x++ )
|
||||||
|
{
|
||||||
|
for ( int k = 0; k < 3; k++ )
|
||||||
|
{
|
||||||
|
*pDest++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define _GAME_RENDER_TERRAIN_H
|
#define _GAME_RENDER_TERRAIN_H
|
||||||
|
|
||||||
#include <OgreTerrain.h>
|
#include <OgreTerrain.h>
|
||||||
|
#include <OgreTerrainGroup.h>
|
||||||
#include "terrainmaterial.hpp"
|
#include "terrainmaterial.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -23,7 +24,7 @@ namespace MWRender{
|
||||||
*/
|
*/
|
||||||
class TerrainManager{
|
class TerrainManager{
|
||||||
public:
|
public:
|
||||||
TerrainManager(Ogre::SceneManager*);
|
TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
|
||||||
virtual ~TerrainManager();
|
virtual ~TerrainManager();
|
||||||
|
|
||||||
void setDiffuse(const Ogre::ColourValue& diffuse);
|
void setDiffuse(const Ogre::ColourValue& diffuse);
|
||||||
|
@ -32,8 +33,10 @@ namespace MWRender{
|
||||||
void cellAdded(MWWorld::Ptr::CellStore* store);
|
void cellAdded(MWWorld::Ptr::CellStore* store);
|
||||||
void cellRemoved(MWWorld::Ptr::CellStore* store);
|
void cellRemoved(MWWorld::Ptr::CellStore* store);
|
||||||
private:
|
private:
|
||||||
Ogre::TerrainGlobalOptions* mTerrainGlobals;
|
Ogre::TerrainGlobalOptions mTerrainGlobals;
|
||||||
Ogre::TerrainGroup* mTerrainGroup;
|
Ogre::TerrainGroup mTerrainGroup;
|
||||||
|
|
||||||
|
const MWWorld::Environment& mEnvironment;
|
||||||
|
|
||||||
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
||||||
|
|
||||||
|
@ -53,7 +56,8 @@ namespace MWRender{
|
||||||
* layer
|
* layer
|
||||||
*
|
*
|
||||||
* @param terrainData the terrain data to setup the textures for
|
* @param terrainData the terrain data to setup the textures for
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the ltex index in the current cell to start making the texture from
|
* @param fromX the ltex index in the current cell to start making the texture from
|
||||||
* @param fromY the ltex index in the current cell to start making the texture from
|
* @param fromY the ltex index in the current cell to start making the texture from
|
||||||
* @param size the size (number of splats) to get
|
* @param size the size (number of splats) to get
|
||||||
|
@ -61,7 +65,7 @@ namespace MWRender{
|
||||||
* can be used by initTerrainBlendMaps
|
* can be used by initTerrainBlendMaps
|
||||||
*/
|
*/
|
||||||
void initTerrainTextures(Ogre::Terrain::ImportData* terrainData,
|
void initTerrainTextures(Ogre::Terrain::ImportData* terrainData,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
std::map<uint16_t, int>& indexes);
|
std::map<uint16_t, int>& indexes);
|
||||||
|
|
||||||
|
@ -69,14 +73,15 @@ namespace MWRender{
|
||||||
* Creates the blend (splatting maps) for the given terrain from the ltex data.
|
* Creates the blend (splatting maps) for the given terrain from the ltex data.
|
||||||
*
|
*
|
||||||
* @param terrain the terrain object for the current cell
|
* @param terrain the terrain object for the current cell
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the ltex index in the current cell to start making the texture from
|
* @param fromX the ltex index in the current cell to start making the texture from
|
||||||
* @param fromY the ltex index in the current cell to start making the texture from
|
* @param fromY the ltex index in the current cell to start making the texture from
|
||||||
* @param size the size (number of splats) to get
|
* @param size the size (number of splats) to get
|
||||||
* @param indexes the mapping of ltex to blend map produced by initTerrainTextures
|
* @param indexes the mapping of ltex to blend map produced by initTerrainTextures
|
||||||
*/
|
*/
|
||||||
void initTerrainBlendMaps(Ogre::Terrain* terrain,
|
void initTerrainBlendMaps(Ogre::Terrain* terrain,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
const std::map<uint16_t, int>& indexes);
|
const std::map<uint16_t, int>& indexes);
|
||||||
|
|
||||||
|
@ -85,22 +90,25 @@ namespace MWRender{
|
||||||
* starts at (0,0). This supports getting values from the surrounding
|
* starts at (0,0). This supports getting values from the surrounding
|
||||||
* cells so negative x, y is acceptable
|
* cells so negative x, y is acceptable
|
||||||
*
|
*
|
||||||
* @param store the cell store for the current cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param x, y the splat position of the ltex index to get relative to the
|
* @param x, y the splat position of the ltex index to get relative to the
|
||||||
* first splat of the current cell
|
* first splat of the current cell
|
||||||
*/
|
*/
|
||||||
int getLtexIndexAt(MWWorld::Ptr::CellStore* store, int x, int y);
|
int getLtexIndexAt(int cellX, int cellY, int x, int y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Due to the fact that Ogre terrain doesn't support vertex colours
|
* Due to the fact that Ogre terrain doesn't support vertex colours
|
||||||
* we have to generate them manually
|
* we have to generate them manually
|
||||||
*
|
*
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the *vertex* index in the current cell to start making texture from
|
* @param fromX the *vertex* index in the current cell to start making texture from
|
||||||
* @param fromY the *vertex* index in the current cell to start making the texture from
|
* @param fromY the *vertex* index in the current cell to start making the texture from
|
||||||
* @param size the size (number of vertexes) to get
|
* @param size the size (number of vertexes) to get
|
||||||
*/
|
*/
|
||||||
Ogre::TexturePtr getVertexColours(MWWorld::Ptr::CellStore* store,
|
Ogre::TexturePtr getVertexColours(ESM::Land* land,
|
||||||
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size);
|
int fromX, int fromY, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,9 @@ namespace Ogre
|
||||||
public:
|
public:
|
||||||
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
|
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
|
||||||
~SM2Profile();
|
~SM2Profile();
|
||||||
|
|
||||||
|
bool isVertexCompressionSupported() const {return false;}
|
||||||
|
|
||||||
MaterialPtr generate(const Terrain* terrain);
|
MaterialPtr generate(const Terrain* terrain);
|
||||||
MaterialPtr generateForCompositeMap(const Terrain* terrain);
|
MaterialPtr generateForCompositeMap(const Terrain* terrain);
|
||||||
uint8 getMaxLayers(const Terrain* terrain) const;
|
uint8 getMaxLayers(const Terrain* terrain) const;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <components/interpreter/opcodes.hpp>
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
#include "../mwdialogue/journal.hpp"
|
#include "../mwdialogue/journal.hpp"
|
||||||
|
#include "../mwdialogue/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
|
|
||||||
|
@ -72,15 +73,62 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpAddTopic : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext& context
|
||||||
|
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
|
std::string topic = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
context.getEnvironment().mDialogueManager->addTopic(topic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpChoice : public Interpreter::Opcode1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext& context
|
||||||
|
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||||
|
MWDialogue::DialogueManager* dialogue = context.getEnvironment().mDialogueManager;
|
||||||
|
while(arg0>0)
|
||||||
|
{
|
||||||
|
std::string question = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
arg0 = arg0 -1;
|
||||||
|
Interpreter::Type_Integer choice = 1;
|
||||||
|
if(arg0>0)
|
||||||
|
{
|
||||||
|
choice = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
arg0 = arg0 -1;
|
||||||
|
}
|
||||||
|
dialogue->askQuestion(question,choice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const int opcodeJournal = 0x2000133;
|
const int opcodeJournal = 0x2000133;
|
||||||
const int opcodeSetJournalIndex = 0x2000134;
|
const int opcodeSetJournalIndex = 0x2000134;
|
||||||
const int opcodeGetJournalIndex = 0x2000135;
|
const int opcodeGetJournalIndex = 0x2000135;
|
||||||
|
const int opcodeAddTopic = 0x200013a;
|
||||||
|
const int opcodeChoice = 0x2000a;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
extensions.registerInstruction ("journal", "cl", opcodeJournal);
|
extensions.registerInstruction ("journal", "cl", opcodeJournal);
|
||||||
extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex);
|
extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex);
|
||||||
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
|
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
|
||||||
|
extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic);
|
||||||
|
extensions.registerInstruction ("choice", "/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -88,6 +136,8 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (opcodeJournal, new OpJournal);
|
interpreter.installSegment5 (opcodeJournal, new OpJournal);
|
||||||
interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex);
|
interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex);
|
||||||
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
|
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
|
||||||
|
interpreter.installSegment5 (opcodeAddTopic, new OpAddTopic);
|
||||||
|
interpreter.installSegment3 (opcodeChoice,new OpChoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ op 0x20006: PlayAnim
|
||||||
op 0x20007: PlayAnim, explicit reference
|
op 0x20007: PlayAnim, explicit reference
|
||||||
op 0x20008: LoopAnim
|
op 0x20008: LoopAnim
|
||||||
op 0x20009: LoopAnim, explicit reference
|
op 0x20009: LoopAnim, explicit reference
|
||||||
opcodes 0x2000a-0x3ffff unused
|
op 0x2000a: Choice
|
||||||
|
opcodes 0x2000b-0x3ffff unused
|
||||||
|
|
||||||
Segment 4:
|
Segment 4:
|
||||||
(not implemented yet)
|
(not implemented yet)
|
||||||
|
@ -115,6 +116,7 @@ op 0x2000136: GetPCCell
|
||||||
op 0x2000137: GetButtonPressed
|
op 0x2000137: GetButtonPressed
|
||||||
op 0x2000138: SkipAnim
|
op 0x2000138: SkipAnim
|
||||||
op 0x2000139: SkipAnim, expplicit reference
|
op 0x2000139: SkipAnim, expplicit reference
|
||||||
|
op 0x200013a: AddTopic
|
||||||
op 0x200013b: twf
|
op 0x200013b: twf
|
||||||
op 0x200013c: FadeIn
|
op 0x200013c: FadeIn
|
||||||
op 0x200013d: FadeOut
|
op 0x200013d: FadeOut
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
std::vector<Interpreter::Type_Code> code;
|
std::vector<Interpreter::Type_Code> code;
|
||||||
mParser.getCode (code);
|
mParser.getCode (code);
|
||||||
mScripts.insert (std::make_pair (name, code));
|
mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals())));
|
||||||
|
|
||||||
// TODO sanity check on generated locals
|
// TODO sanity check on generated locals
|
||||||
|
|
||||||
|
@ -77,8 +77,7 @@ namespace MWScript
|
||||||
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
||||||
{
|
{
|
||||||
// compile script
|
// compile script
|
||||||
std::map<std::string, std::vector<Interpreter::Type_Code> >::iterator iter =
|
ScriptCollection::iterator iter = mScripts.find (name);
|
||||||
mScripts.find (name);
|
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
|
@ -86,7 +85,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
// failed -> ignore script from now on.
|
// failed -> ignore script from now on.
|
||||||
std::vector<Interpreter::Type_Code> empty;
|
std::vector<Interpreter::Type_Code> empty;
|
||||||
mScripts.insert (std::make_pair (name, empty));
|
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +94,7 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute script
|
// execute script
|
||||||
if (!iter->second.empty())
|
if (!iter->second.first.empty())
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!mOpcodesInstalled)
|
if (!mOpcodesInstalled)
|
||||||
|
@ -104,7 +103,7 @@ namespace MWScript
|
||||||
mOpcodesInstalled = true;
|
mOpcodesInstalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mInterpreter.run (&iter->second[0], iter->second.size(), interpreterContext);
|
mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +112,7 @@ namespace MWScript
|
||||||
if (mVerbose)
|
if (mVerbose)
|
||||||
std::cerr << "(" << e.what() << ")" << std::endl;
|
std::cerr << "(" << e.what() << ")" << std::endl;
|
||||||
|
|
||||||
iter->second.clear(); // don't execute again.
|
iter->second.first.clear(); // don't execute again.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,4 +131,24 @@ namespace MWScript
|
||||||
|
|
||||||
return std::make_pair (count, success);
|
return std::make_pair (count, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Compiler::Locals& ScriptManager::getLocals (const std::string& name)
|
||||||
|
{
|
||||||
|
ScriptCollection::iterator iter = mScripts.find (name);
|
||||||
|
|
||||||
|
if (iter==mScripts.end())
|
||||||
|
{
|
||||||
|
if (!compile (name))
|
||||||
|
{
|
||||||
|
// failed -> ignore script from now on.
|
||||||
|
std::vector<Interpreter::Type_Code> empty;
|
||||||
|
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||||
|
throw std::runtime_error ("failed to compile script " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = mScripts.find (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter->second.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,11 @@ namespace MWScript
|
||||||
Interpreter::Interpreter mInterpreter;
|
Interpreter::Interpreter mInterpreter;
|
||||||
bool mOpcodesInstalled;
|
bool mOpcodesInstalled;
|
||||||
|
|
||||||
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts;
|
typedef std::pair<std::vector<Interpreter::Type_Code>, Compiler::Locals> CompiledScript;
|
||||||
|
typedef std::map<std::string, CompiledScript> ScriptCollection;
|
||||||
|
|
||||||
|
|
||||||
|
ScriptCollection mScripts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -56,6 +60,9 @@ namespace MWScript
|
||||||
std::pair<int, int> compileAll();
|
std::pair<int, int> compileAll();
|
||||||
///< Compile all scripts
|
///< Compile all scripts
|
||||||
/// \return count, success
|
/// \return count, success
|
||||||
|
|
||||||
|
Compiler::Locals& getLocals (const std::string& name);
|
||||||
|
///< Return locals for script \a name.
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
407
apps/openmw/mwsound/ffmpeg_decoder.cpp
Normal file
407
apps/openmw/mwsound/ffmpeg_decoder.cpp
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
#ifdef OPENMW_USE_FFMPEG
|
||||||
|
|
||||||
|
#include "ffmpeg_decoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
|
||||||
|
static void fail(const std::string &msg)
|
||||||
|
{ throw std::runtime_error("FFmpeg exception: "+msg); }
|
||||||
|
|
||||||
|
|
||||||
|
struct PacketList {
|
||||||
|
AVPacket pkt;
|
||||||
|
PacketList *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FFmpeg_Decoder::MyStream {
|
||||||
|
AVCodecContext *mCodecCtx;
|
||||||
|
int mStreamIdx;
|
||||||
|
|
||||||
|
PacketList *mPackets;
|
||||||
|
|
||||||
|
char *mDecodedData;
|
||||||
|
size_t mDecodedDataSize;
|
||||||
|
|
||||||
|
FFmpeg_Decoder *mParent;
|
||||||
|
|
||||||
|
void clearPackets();
|
||||||
|
void *getAVAudioData(size_t *length);
|
||||||
|
size_t readAVAudioData(void *data, size_t length);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->read(buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FFmpeg_Decoder::writePacket(void *user_data, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->write(buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t FFmpeg_Decoder::seek(void *user_data, int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||||
|
|
||||||
|
whence &= ~AVSEEK_FORCE;
|
||||||
|
if(whence == AVSEEK_SIZE)
|
||||||
|
return stream->size();
|
||||||
|
if(whence == SEEK_SET)
|
||||||
|
stream->seek(offset);
|
||||||
|
else if(whence == SEEK_CUR)
|
||||||
|
stream->seek(stream->tell()+offset);
|
||||||
|
else if(whence == SEEK_END)
|
||||||
|
stream->seek(stream->size()+offset);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return stream->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
||||||
|
* correct stream. It won't buffer data for streams that the app doesn't have a
|
||||||
|
* handle for. */
|
||||||
|
bool FFmpeg_Decoder::getNextPacket(int streamidx)
|
||||||
|
{
|
||||||
|
PacketList *packet;
|
||||||
|
|
||||||
|
packet = (PacketList*)av_malloc(sizeof(*packet));
|
||||||
|
packet->next = NULL;
|
||||||
|
|
||||||
|
next_packet:
|
||||||
|
while(av_read_frame(mFormatCtx, &packet->pkt) >= 0)
|
||||||
|
{
|
||||||
|
std::vector<MyStream*>::iterator iter = mStreams.begin();
|
||||||
|
|
||||||
|
/* Check each stream the user has a handle for, looking for the one
|
||||||
|
* this packet belongs to */
|
||||||
|
while(iter != mStreams.end())
|
||||||
|
{
|
||||||
|
if((*iter)->mStreamIdx == packet->pkt.stream_index)
|
||||||
|
{
|
||||||
|
PacketList **last;
|
||||||
|
|
||||||
|
last = &(*iter)->mPackets;
|
||||||
|
while(*last != NULL)
|
||||||
|
last = &(*last)->next;
|
||||||
|
|
||||||
|
*last = packet;
|
||||||
|
if((*iter)->mStreamIdx == streamidx)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
packet = (PacketList*)av_malloc(sizeof(*packet));
|
||||||
|
packet->next = NULL;
|
||||||
|
goto next_packet;
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
/* Free the packet and look for another */
|
||||||
|
av_free_packet(&packet->pkt);
|
||||||
|
}
|
||||||
|
av_free(packet);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::MyStream::clearPackets()
|
||||||
|
{
|
||||||
|
while(mPackets)
|
||||||
|
{
|
||||||
|
PacketList *self = mPackets;
|
||||||
|
mPackets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(length) *length = 0;
|
||||||
|
if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mDecodedDataSize = 0;
|
||||||
|
|
||||||
|
next_packet:
|
||||||
|
if(!mPackets && !mParent->getNextPacket(mStreamIdx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Decode some data, and check for errors */
|
||||||
|
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
|
while((len=avcodec_decode_audio3(mCodecCtx, (int16_t*)mDecodedData, &size,
|
||||||
|
&mPackets->pkt)) == 0)
|
||||||
|
{
|
||||||
|
PacketList *self;
|
||||||
|
|
||||||
|
if(size > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Packet went unread and no data was given? Drop it and try the next,
|
||||||
|
* I guess... */
|
||||||
|
self = mPackets;
|
||||||
|
mPackets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
|
||||||
|
if(!mPackets)
|
||||||
|
goto next_packet;
|
||||||
|
|
||||||
|
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(len < mPackets->pkt.size)
|
||||||
|
{
|
||||||
|
/* Move the unread data to the front and clear the end bits */
|
||||||
|
int remaining = mPackets->pkt.size - len;
|
||||||
|
memmove(mPackets->pkt.data, &mPackets->pkt.data[len], remaining);
|
||||||
|
memset(&mPackets->pkt.data[remaining], 0, mPackets->pkt.size - remaining);
|
||||||
|
mPackets->pkt.size -= len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PacketList *self;
|
||||||
|
|
||||||
|
self = mPackets;
|
||||||
|
mPackets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size == 0)
|
||||||
|
goto next_packet;
|
||||||
|
|
||||||
|
/* Set the output buffer size */
|
||||||
|
mDecodedDataSize = size;
|
||||||
|
if(length) *length = mDecodedDataSize;
|
||||||
|
|
||||||
|
return mDecodedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
||||||
|
{
|
||||||
|
size_t dec = 0;
|
||||||
|
|
||||||
|
while(dec < length)
|
||||||
|
{
|
||||||
|
/* If there's no decoded data, find some */
|
||||||
|
if(mDecodedDataSize == 0)
|
||||||
|
{
|
||||||
|
if(getAVAudioData(NULL) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mDecodedDataSize > 0)
|
||||||
|
{
|
||||||
|
/* Get the amount of bytes remaining to be written, and clamp to
|
||||||
|
* the amount of decoded data we have */
|
||||||
|
size_t rem = length-dec;
|
||||||
|
if(rem > mDecodedDataSize)
|
||||||
|
rem = mDecodedDataSize;
|
||||||
|
|
||||||
|
/* Copy the data to the app's buffer and increment */
|
||||||
|
if(data != NULL)
|
||||||
|
{
|
||||||
|
memcpy(data, mDecodedData, rem);
|
||||||
|
data = (char*)data + rem;
|
||||||
|
}
|
||||||
|
dec += rem;
|
||||||
|
|
||||||
|
/* If there's any decoded data left, move it to the front of the
|
||||||
|
* buffer for next time */
|
||||||
|
if(rem < mDecodedDataSize)
|
||||||
|
memmove(mDecodedData, &mDecodedData[rem], mDecodedDataSize - rem);
|
||||||
|
mDecodedDataSize -= rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of bytes we were able to get */
|
||||||
|
return dec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
mDataStream = mResourceMgr.openResource(fname);
|
||||||
|
|
||||||
|
if((mFormatCtx=avformat_alloc_context()) == NULL)
|
||||||
|
fail("Failed to allocate context");
|
||||||
|
|
||||||
|
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
||||||
|
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
||||||
|
{
|
||||||
|
avformat_free_context(mFormatCtx);
|
||||||
|
mFormatCtx = NULL;
|
||||||
|
fail("Failed to allocate input stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(avformat_find_stream_info(mFormatCtx, NULL) < 0)
|
||||||
|
fail("Failed to find stream info in "+fname);
|
||||||
|
|
||||||
|
for(size_t j = 0;j < mFormatCtx->nb_streams;j++)
|
||||||
|
{
|
||||||
|
if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||||
|
{
|
||||||
|
std::auto_ptr<MyStream> stream(new MyStream);
|
||||||
|
stream->mCodecCtx = mFormatCtx->streams[j]->codec;
|
||||||
|
stream->mStreamIdx = j;
|
||||||
|
stream->mPackets = NULL;
|
||||||
|
|
||||||
|
AVCodec *codec = avcodec_find_decoder(stream->mCodecCtx->codec_id);
|
||||||
|
if(!codec)
|
||||||
|
{
|
||||||
|
std::stringstream ss("No codec found for id ");
|
||||||
|
ss << stream->mCodecCtx->codec_id;
|
||||||
|
fail(ss.str());
|
||||||
|
}
|
||||||
|
if(avcodec_open(stream->mCodecCtx, codec) < 0)
|
||||||
|
fail("Failed to open audio codec " + std::string(codec->long_name));
|
||||||
|
|
||||||
|
stream->mDecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
||||||
|
stream->mDecodedDataSize = 0;
|
||||||
|
|
||||||
|
stream->mParent = this;
|
||||||
|
mStreams.push_back(stream.release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mStreams.empty())
|
||||||
|
fail("No audio streams in "+fname);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
av_close_input_file(mFormatCtx);
|
||||||
|
mFormatCtx = NULL;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::close()
|
||||||
|
{
|
||||||
|
while(!mStreams.empty())
|
||||||
|
{
|
||||||
|
MyStream *stream = mStreams.front();
|
||||||
|
|
||||||
|
stream->clearPackets();
|
||||||
|
avcodec_close(stream->mCodecCtx);
|
||||||
|
av_free(stream->mDecodedData);
|
||||||
|
delete stream;
|
||||||
|
|
||||||
|
mStreams.erase(mStreams.begin());
|
||||||
|
}
|
||||||
|
if(mFormatCtx)
|
||||||
|
av_close_input_file(mFormatCtx);
|
||||||
|
mFormatCtx = NULL;
|
||||||
|
|
||||||
|
mDataStream.setNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
|
{
|
||||||
|
if(mStreams.empty())
|
||||||
|
fail("No audio stream info");
|
||||||
|
|
||||||
|
MyStream *stream = mStreams[0];
|
||||||
|
if(stream->mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
|
||||||
|
*type = SampleType_UInt8;
|
||||||
|
else if(stream->mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
|
||||||
|
*type = SampleType_Int16;
|
||||||
|
else
|
||||||
|
fail(std::string("Unsupported sample format: ")+
|
||||||
|
av_get_sample_fmt_name(stream->mCodecCtx->sample_fmt));
|
||||||
|
|
||||||
|
if(stream->mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
|
||||||
|
*chans = ChannelConfig_Mono;
|
||||||
|
else if(stream->mCodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
|
||||||
|
*chans = ChannelConfig_Stereo;
|
||||||
|
else if(stream->mCodecCtx->channel_layout == 0)
|
||||||
|
{
|
||||||
|
/* Unknown channel layout. Try to guess. */
|
||||||
|
if(stream->mCodecCtx->channels == 1)
|
||||||
|
*chans = ChannelConfig_Mono;
|
||||||
|
else if(stream->mCodecCtx->channels == 2)
|
||||||
|
*chans = ChannelConfig_Stereo;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::stringstream sstr("Unsupported raw channel count: ");
|
||||||
|
sstr << stream->mCodecCtx->channels;
|
||||||
|
fail(sstr.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char str[1024];
|
||||||
|
av_get_channel_layout_string(str, sizeof(str), stream->mCodecCtx->channels,
|
||||||
|
stream->mCodecCtx->channel_layout);
|
||||||
|
fail(std::string("Unsupported channel layout: ")+str);
|
||||||
|
}
|
||||||
|
|
||||||
|
*samplerate = stream->mCodecCtx->sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
||||||
|
{
|
||||||
|
if(mStreams.empty())
|
||||||
|
fail("No audio streams");
|
||||||
|
|
||||||
|
return mStreams.front()->readAVAudioData(buffer, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
||||||
|
{
|
||||||
|
if(mStreams.empty())
|
||||||
|
fail("No audio streams");
|
||||||
|
MyStream *stream = mStreams.front();
|
||||||
|
char *inbuf;
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
while((inbuf=(char*)stream->getAVAudioData(&got)) != NULL && got > 0)
|
||||||
|
output.insert(output.end(), inbuf, inbuf+got);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpeg_Decoder::rewind()
|
||||||
|
{
|
||||||
|
av_seek_frame(mFormatCtx, -1, 0, 0);
|
||||||
|
std::for_each(mStreams.begin(), mStreams.end(), std::mem_fun(&MyStream::clearPackets));
|
||||||
|
}
|
||||||
|
|
||||||
|
FFmpeg_Decoder::FFmpeg_Decoder() : mFormatCtx(NULL)
|
||||||
|
{
|
||||||
|
static bool done_init = false;
|
||||||
|
|
||||||
|
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
||||||
|
* output from the lib */
|
||||||
|
if(!done_init)
|
||||||
|
{
|
||||||
|
av_register_all();
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
done_init = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FFmpeg_Decoder::~FFmpeg_Decoder()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
59
apps/openmw/mwsound/ffmpeg_decoder.hpp
Normal file
59
apps/openmw/mwsound/ffmpeg_decoder.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef GAME_SOUND_FFMPEG_DECODER_H
|
||||||
|
#define GAME_SOUND_FFMPEG_DECODER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// FIXME: This can't be right? The headers refuse to build without UINT64_C,
|
||||||
|
// which only gets defined in stdint.h in either C99 mode or with this macro
|
||||||
|
// defined...
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
#include <stdint.h>
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <avcodec.h>
|
||||||
|
#include <avformat.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "sound_decoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
class FFmpeg_Decoder : public Sound_Decoder
|
||||||
|
{
|
||||||
|
AVFormatContext *mFormatCtx;
|
||||||
|
|
||||||
|
struct MyStream;
|
||||||
|
std::vector<MyStream*> mStreams;
|
||||||
|
|
||||||
|
bool getNextPacket(int streamidx);
|
||||||
|
|
||||||
|
Ogre::DataStreamPtr mDataStream;
|
||||||
|
static int readPacket(void *user_data, uint8_t *buf, int buf_size);
|
||||||
|
static int writePacket(void *user_data, uint8_t *buf, int buf_size);
|
||||||
|
static int64_t seek(void *user_data, int64_t offset, int whence);
|
||||||
|
|
||||||
|
virtual void open(const std::string &fname);
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||||
|
|
||||||
|
virtual size_t read(char *buffer, size_t bytes);
|
||||||
|
virtual void readAll(std::vector<char> &output);
|
||||||
|
virtual void rewind();
|
||||||
|
|
||||||
|
FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs);
|
||||||
|
FFmpeg_Decoder(const FFmpeg_Decoder &rhs);
|
||||||
|
|
||||||
|
FFmpeg_Decoder();
|
||||||
|
public:
|
||||||
|
virtual ~FFmpeg_Decoder();
|
||||||
|
|
||||||
|
friend class SoundManager;
|
||||||
|
};
|
||||||
|
#ifndef DEFAULT_DECODER
|
||||||
|
#define DEFAULT_DECODER (::MWSound::FFmpeg_Decoder)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
237
apps/openmw/mwsound/mpgsnd_decoder.cpp
Normal file
237
apps/openmw/mwsound/mpgsnd_decoder.cpp
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#ifdef OPENMW_USE_MPG123
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "mpgsnd_decoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
static void fail(const std::string &msg)
|
||||||
|
{ throw std::runtime_error("MpgSnd exception: "+msg); }
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// libSndFile io callbacks
|
||||||
|
//
|
||||||
|
sf_count_t MpgSnd_Decoder::ogresf_get_filelen(void *user_data)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf_count_t MpgSnd_Decoder::ogresf_seek(sf_count_t offset, int whence, void *user_data)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
|
||||||
|
if(whence == SEEK_CUR)
|
||||||
|
stream->seek(stream->tell()+offset);
|
||||||
|
else if(whence == SEEK_SET)
|
||||||
|
stream->seek(offset);
|
||||||
|
else if(whence == SEEK_END)
|
||||||
|
stream->seek(stream->size()+offset);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return stream->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf_count_t MpgSnd_Decoder::ogresf_read(void *ptr, sf_count_t count, void *user_data)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->read(ptr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
sf_count_t MpgSnd_Decoder::ogresf_write(const void*, sf_count_t, void*)
|
||||||
|
{ return -1; }
|
||||||
|
|
||||||
|
sf_count_t MpgSnd_Decoder::ogresf_tell(void *user_data)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// libmpg13 io callbacks
|
||||||
|
//
|
||||||
|
ssize_t MpgSnd_Decoder::ogrempg_read(void *user_data, void *ptr, size_t count)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
return stream->read(ptr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t MpgSnd_Decoder::ogrempg_lseek(void *user_data, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||||
|
|
||||||
|
if(whence == SEEK_CUR)
|
||||||
|
stream->seek(stream->tell()+offset);
|
||||||
|
else if(whence == SEEK_SET)
|
||||||
|
stream->seek(offset);
|
||||||
|
else if(whence == SEEK_END)
|
||||||
|
stream->seek(stream->size()+offset);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return stream->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MpgSnd_Decoder::open(const std::string &fname)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
mDataStream = mResourceMgr.openResource(fname);
|
||||||
|
|
||||||
|
SF_VIRTUAL_IO streamIO = {
|
||||||
|
ogresf_get_filelen, ogresf_seek,
|
||||||
|
ogresf_read, ogresf_write, ogresf_tell
|
||||||
|
};
|
||||||
|
mSndFile = sf_open_virtual(&streamIO, SFM_READ, &mSndInfo, this);
|
||||||
|
if(mSndFile)
|
||||||
|
{
|
||||||
|
if(mSndInfo.channels == 1)
|
||||||
|
mChanConfig = ChannelConfig_Mono;
|
||||||
|
else if(mSndInfo.channels == 2)
|
||||||
|
mChanConfig = ChannelConfig_Stereo;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sf_close(mSndFile);
|
||||||
|
mSndFile = NULL;
|
||||||
|
fail("Unsupported channel count in "+fname);
|
||||||
|
}
|
||||||
|
mSampleRate = mSndInfo.samplerate;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mDataStream->seek(0);
|
||||||
|
|
||||||
|
mMpgFile = mpg123_new(NULL, NULL);
|
||||||
|
if(mMpgFile && mpg123_replace_reader_handle(mMpgFile, ogrempg_read, ogrempg_lseek, NULL) == MPG123_OK &&
|
||||||
|
mpg123_open_handle(mMpgFile, this) == MPG123_OK)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int encoding, channels;
|
||||||
|
long rate;
|
||||||
|
if(mpg123_getformat(mMpgFile, &rate, &channels, &encoding) != MPG123_OK)
|
||||||
|
fail("Failed to get audio format");
|
||||||
|
if(encoding != MPG123_ENC_SIGNED_16)
|
||||||
|
fail("Unsupported encoding in "+fname);
|
||||||
|
if(channels != 1 && channels != 2)
|
||||||
|
fail("Unsupported channel count in "+fname);
|
||||||
|
mChanConfig = ((channels==2)?ChannelConfig_Stereo:ChannelConfig_Mono);
|
||||||
|
mSampleRate = rate;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mpg123_close(mMpgFile);
|
||||||
|
mpg123_delete(mMpgFile);
|
||||||
|
mMpgFile = NULL;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
mpg123_close(mMpgFile);
|
||||||
|
}
|
||||||
|
if(mMpgFile)
|
||||||
|
mpg123_delete(mMpgFile);
|
||||||
|
mMpgFile = NULL;
|
||||||
|
|
||||||
|
fail("Unsupported file type: "+fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MpgSnd_Decoder::close()
|
||||||
|
{
|
||||||
|
if(mSndFile)
|
||||||
|
sf_close(mSndFile);
|
||||||
|
mSndFile = NULL;
|
||||||
|
|
||||||
|
if(mMpgFile)
|
||||||
|
{
|
||||||
|
mpg123_close(mMpgFile);
|
||||||
|
mpg123_delete(mMpgFile);
|
||||||
|
mMpgFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDataStream.setNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
|
{
|
||||||
|
if(!mSndFile && !mMpgFile)
|
||||||
|
fail("No open file");
|
||||||
|
|
||||||
|
*samplerate = mSampleRate;
|
||||||
|
*chans = mChanConfig;
|
||||||
|
*type = SampleType_Int16;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MpgSnd_Decoder::read(char *buffer, size_t bytes)
|
||||||
|
{
|
||||||
|
size_t got = 0;
|
||||||
|
|
||||||
|
if(mSndFile)
|
||||||
|
{
|
||||||
|
got = sf_read_short(mSndFile, (short*)buffer, bytes/2)*2;
|
||||||
|
}
|
||||||
|
else if(mMpgFile)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
err = mpg123_read(mMpgFile, (unsigned char*)buffer, bytes, &got);
|
||||||
|
if(err != MPG123_OK && err != MPG123_DONE)
|
||||||
|
fail("Failed to read from file");
|
||||||
|
}
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MpgSnd_Decoder::readAll(std::vector<char> &output)
|
||||||
|
{
|
||||||
|
if(mSndFile && mSndInfo.frames > 0)
|
||||||
|
{
|
||||||
|
size_t pos = output.size();
|
||||||
|
output.resize(pos + mSndInfo.frames*mSndInfo.channels*2);
|
||||||
|
sf_readf_short(mSndFile, (short*)(output.data()+pos), mSndInfo.frames);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fallback in case we don't know the total already
|
||||||
|
Sound_Decoder::readAll(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MpgSnd_Decoder::rewind()
|
||||||
|
{
|
||||||
|
if(!mSndFile && !mMpgFile)
|
||||||
|
fail("No open file");
|
||||||
|
|
||||||
|
if(mSndFile)
|
||||||
|
{
|
||||||
|
if(sf_seek(mSndFile, 0, SEEK_SET) == -1)
|
||||||
|
fail("seek failed");
|
||||||
|
}
|
||||||
|
else if(mMpgFile)
|
||||||
|
{
|
||||||
|
if(mpg123_seek(mMpgFile, 0, SEEK_SET) < 0)
|
||||||
|
fail("seek failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MpgSnd_Decoder::MpgSnd_Decoder()
|
||||||
|
: mSndInfo()
|
||||||
|
, mSndFile(NULL)
|
||||||
|
, mMpgFile(NULL)
|
||||||
|
, mDataStream()
|
||||||
|
, mChanConfig(ChannelConfig_Stereo)
|
||||||
|
, mSampleRate(0)
|
||||||
|
{
|
||||||
|
static bool initdone = false;
|
||||||
|
if(!initdone)
|
||||||
|
mpg123_init();
|
||||||
|
initdone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MpgSnd_Decoder::~MpgSnd_Decoder()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
57
apps/openmw/mwsound/mpgsnd_decoder.hpp
Normal file
57
apps/openmw/mwsound/mpgsnd_decoder.hpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#ifndef GAME_SOUND_MPGSND_DECODER_H
|
||||||
|
#define GAME_SOUND_MPGSND_DECODER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <OgreDataStream.h>
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
#include "sndfile.h"
|
||||||
|
|
||||||
|
#include "sound_decoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
class MpgSnd_Decoder : public Sound_Decoder
|
||||||
|
{
|
||||||
|
SF_INFO mSndInfo;
|
||||||
|
SNDFILE *mSndFile;
|
||||||
|
mpg123_handle *mMpgFile;
|
||||||
|
|
||||||
|
Ogre::DataStreamPtr mDataStream;
|
||||||
|
static sf_count_t ogresf_get_filelen(void *user_data);
|
||||||
|
static sf_count_t ogresf_seek(sf_count_t offset, int whence, void *user_data);
|
||||||
|
static sf_count_t ogresf_read(void *ptr, sf_count_t count, void *user_data);
|
||||||
|
static sf_count_t ogresf_write(const void*, sf_count_t, void*);
|
||||||
|
static sf_count_t ogresf_tell(void *user_data);
|
||||||
|
static ssize_t ogrempg_read(void*, void*, size_t);
|
||||||
|
static off_t ogrempg_lseek(void*, off_t, int);
|
||||||
|
|
||||||
|
ChannelConfig mChanConfig;
|
||||||
|
int mSampleRate;
|
||||||
|
|
||||||
|
virtual void open(const std::string &fname);
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||||
|
|
||||||
|
virtual size_t read(char *buffer, size_t bytes);
|
||||||
|
virtual void readAll(std::vector<char> &output);
|
||||||
|
virtual void rewind();
|
||||||
|
|
||||||
|
MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs);
|
||||||
|
MpgSnd_Decoder(const MpgSnd_Decoder &rhs);
|
||||||
|
|
||||||
|
MpgSnd_Decoder();
|
||||||
|
public:
|
||||||
|
virtual ~MpgSnd_Decoder();
|
||||||
|
|
||||||
|
friend class SoundManager;
|
||||||
|
};
|
||||||
|
#ifndef DEFAULT_DECODER
|
||||||
|
#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
793
apps/openmw/mwsound/openal_output.cpp
Normal file
793
apps/openmw/mwsound/openal_output.cpp
Normal file
|
@ -0,0 +1,793 @@
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include "openal_output.hpp"
|
||||||
|
#include "sound_decoder.hpp"
|
||||||
|
#include "sound.hpp"
|
||||||
|
#include "soundmanager.hpp"
|
||||||
|
|
||||||
|
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||||
|
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
|
||||||
|
static void fail(const std::string &msg)
|
||||||
|
{ throw std::runtime_error("OpenAL exception: " + msg); }
|
||||||
|
|
||||||
|
static void throwALCerror(ALCdevice *device)
|
||||||
|
{
|
||||||
|
ALCenum err = alcGetError(device);
|
||||||
|
if(err != ALC_NO_ERROR)
|
||||||
|
fail(alcGetString(device, err));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void throwALerror()
|
||||||
|
{
|
||||||
|
ALenum err = alGetError();
|
||||||
|
if(err != AL_NO_ERROR)
|
||||||
|
fail(alGetString(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ALenum getALFormat(ChannelConfig chans, SampleType type)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
ALenum format;
|
||||||
|
ChannelConfig chans;
|
||||||
|
SampleType type;
|
||||||
|
} fmtlist[] = {
|
||||||
|
{ AL_FORMAT_MONO16, ChannelConfig_Mono, SampleType_Int16 },
|
||||||
|
{ AL_FORMAT_MONO8, ChannelConfig_Mono, SampleType_UInt8 },
|
||||||
|
{ AL_FORMAT_STEREO16, ChannelConfig_Stereo, SampleType_Int16 },
|
||||||
|
{ AL_FORMAT_STEREO8, ChannelConfig_Stereo, SampleType_UInt8 },
|
||||||
|
};
|
||||||
|
static const size_t fmtlistsize = sizeof(fmtlist)/sizeof(fmtlist[0]);
|
||||||
|
|
||||||
|
for(size_t i = 0;i < fmtlistsize;i++)
|
||||||
|
{
|
||||||
|
if(fmtlist[i].chans == chans && fmtlist[i].type == type)
|
||||||
|
return fmtlist[i].format;
|
||||||
|
}
|
||||||
|
fail(std::string("Unsupported sound format (")+getChannelConfigName(chans)+", "+getSampleTypeName(type)+")");
|
||||||
|
return AL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A streaming OpenAL sound.
|
||||||
|
//
|
||||||
|
class OpenAL_SoundStream : public Sound
|
||||||
|
{
|
||||||
|
static const ALuint sNumBuffers = 6;
|
||||||
|
static const ALfloat sBufferLength;
|
||||||
|
|
||||||
|
OpenAL_Output &mOutput;
|
||||||
|
|
||||||
|
ALuint mSource;
|
||||||
|
ALuint mBuffers[sNumBuffers];
|
||||||
|
|
||||||
|
ALenum mFormat;
|
||||||
|
ALsizei mSampleRate;
|
||||||
|
ALuint mBufferSize;
|
||||||
|
|
||||||
|
DecoderPtr mDecoder;
|
||||||
|
|
||||||
|
volatile bool mIsFinished;
|
||||||
|
|
||||||
|
OpenAL_SoundStream(const OpenAL_SoundStream &rhs);
|
||||||
|
OpenAL_SoundStream& operator=(const OpenAL_SoundStream &rhs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder);
|
||||||
|
virtual ~OpenAL_SoundStream();
|
||||||
|
|
||||||
|
virtual void stop();
|
||||||
|
virtual bool isPlaying();
|
||||||
|
virtual void setVolume(float volume);
|
||||||
|
virtual void update(const float *pos);
|
||||||
|
|
||||||
|
void play();
|
||||||
|
bool process();
|
||||||
|
};
|
||||||
|
|
||||||
|
const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f;
|
||||||
|
|
||||||
|
//
|
||||||
|
// A background streaming thread (keeps active streams processed)
|
||||||
|
//
|
||||||
|
struct OpenAL_Output::StreamThread {
|
||||||
|
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
||||||
|
StreamVec mStreams;
|
||||||
|
boost::mutex mMutex;
|
||||||
|
boost::thread mThread;
|
||||||
|
|
||||||
|
StreamThread()
|
||||||
|
: mThread(boost::ref(*this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~StreamThread()
|
||||||
|
{
|
||||||
|
mThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// boost::thread entry point
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
mMutex.lock();
|
||||||
|
StreamVec::iterator iter = mStreams.begin();
|
||||||
|
while(iter != mStreams.end())
|
||||||
|
{
|
||||||
|
if((*iter)->process() == false)
|
||||||
|
iter = mStreams.erase(iter);
|
||||||
|
else
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
mMutex.unlock();
|
||||||
|
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(OpenAL_SoundStream *stream)
|
||||||
|
{
|
||||||
|
mMutex.lock();
|
||||||
|
if(std::find(mStreams.begin(), mStreams.end(), stream) == mStreams.end())
|
||||||
|
mStreams.push_back(stream);
|
||||||
|
mMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(OpenAL_SoundStream *stream)
|
||||||
|
{
|
||||||
|
mMutex.lock();
|
||||||
|
StreamVec::iterator iter = std::find(mStreams.begin(), mStreams.end(), stream);
|
||||||
|
if(iter != mStreams.end())
|
||||||
|
mStreams.erase(iter);
|
||||||
|
mMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeAll()
|
||||||
|
{
|
||||||
|
mMutex.lock();
|
||||||
|
mStreams.clear();
|
||||||
|
mMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StreamThread(const StreamThread &rhs);
|
||||||
|
StreamThread& operator=(const StreamThread &rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder)
|
||||||
|
: mOutput(output), mSource(src), mDecoder(decoder), mIsFinished(true)
|
||||||
|
{
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
alGenBuffers(sNumBuffers, mBuffers);
|
||||||
|
throwALerror();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int srate;
|
||||||
|
ChannelConfig chans;
|
||||||
|
SampleType type;
|
||||||
|
|
||||||
|
mDecoder->getInfo(&srate, &chans, &type);
|
||||||
|
mFormat = getALFormat(chans, type);
|
||||||
|
mSampleRate = srate;
|
||||||
|
|
||||||
|
mBufferSize = static_cast<ALuint>(sBufferLength*srate);
|
||||||
|
mBufferSize = framesToBytes(mBufferSize, chans, type);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mOutput.mFreeSources.push_back(mSource);
|
||||||
|
alDeleteBuffers(sNumBuffers, mBuffers);
|
||||||
|
alGetError();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpenAL_SoundStream::~OpenAL_SoundStream()
|
||||||
|
{
|
||||||
|
mOutput.mStreamThread->remove(this);
|
||||||
|
|
||||||
|
alSourceStop(mSource);
|
||||||
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
|
|
||||||
|
mOutput.mFreeSources.push_back(mSource);
|
||||||
|
alDeleteBuffers(sNumBuffers, mBuffers);
|
||||||
|
alGetError();
|
||||||
|
|
||||||
|
mDecoder->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_SoundStream::play()
|
||||||
|
{
|
||||||
|
std::vector<char> data(mBufferSize);
|
||||||
|
|
||||||
|
alSourceStop(mSource);
|
||||||
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
for(ALuint i = 0;i < sNumBuffers;i++)
|
||||||
|
{
|
||||||
|
size_t got;
|
||||||
|
got = mDecoder->read(data.data(), data.size());
|
||||||
|
alBufferData(mBuffers[i], mFormat, data.data(), got, mSampleRate);
|
||||||
|
}
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
alSourceQueueBuffers(mSource, sNumBuffers, mBuffers);
|
||||||
|
alSourcePlay(mSource);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
mIsFinished = false;
|
||||||
|
mOutput.mStreamThread->add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_SoundStream::stop()
|
||||||
|
{
|
||||||
|
mOutput.mStreamThread->remove(this);
|
||||||
|
mIsFinished = true;
|
||||||
|
|
||||||
|
alSourceStop(mSource);
|
||||||
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
mDecoder->rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenAL_SoundStream::isPlaying()
|
||||||
|
{
|
||||||
|
ALint state;
|
||||||
|
|
||||||
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
if(state == AL_PLAYING)
|
||||||
|
return true;
|
||||||
|
return !mIsFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_SoundStream::setVolume(float volume)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_GAIN, volume*mBaseVolume);
|
||||||
|
throwALerror();
|
||||||
|
mVolume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_SoundStream::update(const float *pos)
|
||||||
|
{
|
||||||
|
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]);
|
||||||
|
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenAL_SoundStream::process()
|
||||||
|
{
|
||||||
|
bool finished = mIsFinished;
|
||||||
|
ALint processed, state;
|
||||||
|
|
||||||
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
|
alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
if(processed > 0)
|
||||||
|
{
|
||||||
|
std::vector<char> data(mBufferSize);
|
||||||
|
do {
|
||||||
|
ALuint bufid;
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(mSource, 1, &bufid);
|
||||||
|
processed--;
|
||||||
|
|
||||||
|
if(finished)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
got = mDecoder->read(data.data(), data.size());
|
||||||
|
finished = (got < data.size());
|
||||||
|
if(got > 0)
|
||||||
|
{
|
||||||
|
alBufferData(bufid, mFormat, data.data(), got, mSampleRate);
|
||||||
|
alSourceQueueBuffers(mSource, 1, &bufid);
|
||||||
|
}
|
||||||
|
} while(processed > 0);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state != AL_PLAYING && state != AL_PAUSED)
|
||||||
|
{
|
||||||
|
ALint queued;
|
||||||
|
|
||||||
|
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
throwALerror();
|
||||||
|
if(queued > 0)
|
||||||
|
{
|
||||||
|
alSourcePlay(mSource);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsFinished = finished;
|
||||||
|
return !finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A regular OpenAL sound
|
||||||
|
//
|
||||||
|
class OpenAL_Sound : public Sound
|
||||||
|
{
|
||||||
|
OpenAL_Output &mOutput;
|
||||||
|
|
||||||
|
ALuint mSource;
|
||||||
|
ALuint mBuffer;
|
||||||
|
|
||||||
|
OpenAL_Sound(const OpenAL_Sound &rhs);
|
||||||
|
OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf);
|
||||||
|
virtual ~OpenAL_Sound();
|
||||||
|
|
||||||
|
virtual void stop();
|
||||||
|
virtual bool isPlaying();
|
||||||
|
virtual void setVolume(float volume);
|
||||||
|
virtual void update(const float *pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf)
|
||||||
|
: mOutput(output), mSource(src), mBuffer(buf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
OpenAL_Sound::~OpenAL_Sound()
|
||||||
|
{
|
||||||
|
alSourceStop(mSource);
|
||||||
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
|
|
||||||
|
mOutput.mFreeSources.push_back(mSource);
|
||||||
|
mOutput.bufferFinished(mBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Sound::stop()
|
||||||
|
{
|
||||||
|
alSourceStop(mSource);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenAL_Sound::isPlaying()
|
||||||
|
{
|
||||||
|
ALint state;
|
||||||
|
|
||||||
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
return state==AL_PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Sound::setVolume(float volume)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_GAIN, volume*mBaseVolume);
|
||||||
|
throwALerror();
|
||||||
|
mVolume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Sound::update(const float *pos)
|
||||||
|
{
|
||||||
|
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]);
|
||||||
|
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// An OpenAL output device
|
||||||
|
//
|
||||||
|
std::vector<std::string> OpenAL_Output::enumerate()
|
||||||
|
{
|
||||||
|
std::vector<std::string> devlist;
|
||||||
|
const ALCchar *devnames;
|
||||||
|
|
||||||
|
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
|
||||||
|
devnames = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
|
else
|
||||||
|
devnames = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||||
|
while(devnames && *devnames)
|
||||||
|
{
|
||||||
|
devlist.push_back(devnames);
|
||||||
|
devnames += strlen(devnames)+1;
|
||||||
|
}
|
||||||
|
return devlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Output::init(const std::string &devname)
|
||||||
|
{
|
||||||
|
if(mDevice || mContext)
|
||||||
|
fail("Device already open");
|
||||||
|
|
||||||
|
mDevice = alcOpenDevice(devname.c_str());
|
||||||
|
if(!mDevice)
|
||||||
|
{
|
||||||
|
if(devname.empty())
|
||||||
|
fail("Failed to open default device");
|
||||||
|
else
|
||||||
|
fail("Failed to open \""+devname+"\"");
|
||||||
|
}
|
||||||
|
if(alcIsExtensionPresent(mDevice, "ALC_ENUMERATE_ALL_EXT"))
|
||||||
|
std::cout << "Opened \""<<alcGetString(mDevice, ALC_ALL_DEVICES_SPECIFIER)<<"\"" << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "Opened \""<<alcGetString(mDevice, ALC_DEVICE_SPECIFIER)<<"\"" << std::endl;
|
||||||
|
|
||||||
|
mContext = alcCreateContext(mDevice, NULL);
|
||||||
|
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
||||||
|
fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice)));
|
||||||
|
|
||||||
|
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
ALCint maxmono=0, maxstereo=0;
|
||||||
|
alcGetIntegerv(mDevice, ALC_MONO_SOURCES, 1, &maxmono);
|
||||||
|
alcGetIntegerv(mDevice, ALC_STEREO_SOURCES, 1, &maxstereo);
|
||||||
|
throwALCerror(mDevice);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256);
|
||||||
|
for(size_t i = 0;i < maxtotal;i++)
|
||||||
|
{
|
||||||
|
ALuint src = 0;
|
||||||
|
alGenSources(1, &src);
|
||||||
|
throwALerror();
|
||||||
|
mFreeSources.push_back(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
std::cout <<"Error: "<<e.what()<<", trying to continue"<< std::endl;
|
||||||
|
}
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("Could not allocate any sources");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Output::deinit()
|
||||||
|
{
|
||||||
|
mStreamThread->removeAll();
|
||||||
|
|
||||||
|
while(!mFreeSources.empty())
|
||||||
|
{
|
||||||
|
alDeleteSources(1, &mFreeSources.front());
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
mBufferRefs.clear();
|
||||||
|
mUnusedBuffers.clear();
|
||||||
|
while(!mBufferCache.empty())
|
||||||
|
{
|
||||||
|
alDeleteBuffers(1, &mBufferCache.begin()->second);
|
||||||
|
mBufferCache.erase(mBufferCache.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
alcMakeContextCurrent(0);
|
||||||
|
if(mContext)
|
||||||
|
alcDestroyContext(mContext);
|
||||||
|
mContext = 0;
|
||||||
|
if(mDevice)
|
||||||
|
alcCloseDevice(mDevice);
|
||||||
|
mDevice = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALuint OpenAL_Output::getBuffer(const std::string &fname)
|
||||||
|
{
|
||||||
|
ALuint buf = 0;
|
||||||
|
|
||||||
|
NameMap::iterator iditer = mBufferCache.find(fname);
|
||||||
|
if(iditer != mBufferCache.end())
|
||||||
|
{
|
||||||
|
buf = iditer->second;
|
||||||
|
if(mBufferRefs[buf]++ == 0)
|
||||||
|
{
|
||||||
|
IDDq::iterator iter = std::find(mUnusedBuffers.begin(),
|
||||||
|
mUnusedBuffers.end(), buf);
|
||||||
|
if(iter != mUnusedBuffers.end())
|
||||||
|
mUnusedBuffers.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
std::vector<char> data;
|
||||||
|
ChannelConfig chans;
|
||||||
|
SampleType type;
|
||||||
|
ALenum format;
|
||||||
|
int srate;
|
||||||
|
|
||||||
|
DecoderPtr decoder = mManager.getDecoder();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decoder->open(fname);
|
||||||
|
}
|
||||||
|
catch(Ogre::FileNotFoundException &e)
|
||||||
|
{
|
||||||
|
std::string::size_type pos = fname.rfind('.');
|
||||||
|
if(pos == std::string::npos)
|
||||||
|
throw;
|
||||||
|
decoder->open(fname.substr(0, pos)+".mp3");
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder->getInfo(&srate, &chans, &type);
|
||||||
|
format = getALFormat(chans, type);
|
||||||
|
|
||||||
|
decoder->readAll(data);
|
||||||
|
decoder->close();
|
||||||
|
|
||||||
|
alGenBuffers(1, &buf);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
alBufferData(buf, format, data.data(), data.size(), srate);
|
||||||
|
mBufferCache[fname] = buf;
|
||||||
|
mBufferRefs[buf] = 1;
|
||||||
|
|
||||||
|
ALint bufsize = 0;
|
||||||
|
alGetBufferi(buf, AL_SIZE, &bufsize);
|
||||||
|
mBufferCacheMemSize += bufsize;
|
||||||
|
|
||||||
|
// NOTE: Max buffer cache: 15MB
|
||||||
|
while(mBufferCacheMemSize > 15*1024*1024)
|
||||||
|
{
|
||||||
|
if(mUnusedBuffers.empty())
|
||||||
|
{
|
||||||
|
std::cout <<"No more unused buffers to clear!"<< std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALuint oldbuf = mUnusedBuffers.front();
|
||||||
|
mUnusedBuffers.pop_front();
|
||||||
|
|
||||||
|
NameMap::iterator nameiter = mBufferCache.begin();
|
||||||
|
while(nameiter != mBufferCache.end())
|
||||||
|
{
|
||||||
|
if(nameiter->second == oldbuf)
|
||||||
|
mBufferCache.erase(nameiter++);
|
||||||
|
else
|
||||||
|
nameiter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufsize = 0;
|
||||||
|
alGetBufferi(oldbuf, AL_SIZE, &bufsize);
|
||||||
|
alDeleteBuffers(1, &oldbuf);
|
||||||
|
mBufferCacheMemSize -= bufsize;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Output::bufferFinished(ALuint buf)
|
||||||
|
{
|
||||||
|
if(mBufferRefs.at(buf)-- == 1)
|
||||||
|
{
|
||||||
|
mBufferRefs.erase(mBufferRefs.find(buf));
|
||||||
|
mUnusedBuffers.push_back(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, bool loop)
|
||||||
|
{
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
|
ALuint src=0, buf=0;
|
||||||
|
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("No free sources");
|
||||||
|
src = mFreeSources.front();
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
buf = getBuffer(fname);
|
||||||
|
sound.reset(new OpenAL_Sound(*this, src, buf));
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mFreeSources.push_back(src);
|
||||||
|
if(buf && alIsBuffer(buf))
|
||||||
|
bufferFinished(buf);
|
||||||
|
alGetError();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f);
|
||||||
|
alSourcef(src, AL_MAX_DISTANCE, 1000.0f);
|
||||||
|
alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_GAIN, volume);
|
||||||
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
|
alSourcePlay(src);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
||||||
|
float min, float max, bool loop)
|
||||||
|
{
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
|
ALuint src=0, buf=0;
|
||||||
|
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("No free sources");
|
||||||
|
src = mFreeSources.front();
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
buf = getBuffer(fname);
|
||||||
|
sound.reset(new OpenAL_Sound(*this, src, buf));
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mFreeSources.push_back(src);
|
||||||
|
if(buf && alIsBuffer(buf))
|
||||||
|
bufferFinished(buf);
|
||||||
|
alGetError();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
|
||||||
|
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_REFERENCE_DISTANCE, min);
|
||||||
|
alSourcef(src, AL_MAX_DISTANCE, max);
|
||||||
|
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_GAIN, volume);
|
||||||
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
|
alSourcePlay(src);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch)
|
||||||
|
{
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
boost::shared_ptr<OpenAL_SoundStream> sound;
|
||||||
|
ALuint src;
|
||||||
|
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("No free sources");
|
||||||
|
src = mFreeSources.front();
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DecoderPtr decoder = mManager.getDecoder();
|
||||||
|
decoder->open(fname);
|
||||||
|
sound.reset(new OpenAL_SoundStream(*this, src, decoder));
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mFreeSources.push_back(src);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f);
|
||||||
|
alSourcef(src, AL_MAX_DISTANCE, 1000.0f);
|
||||||
|
alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_GAIN, volume);
|
||||||
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSourcei(src, AL_LOOPING, AL_FALSE);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
sound->play();
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundPtr OpenAL_Output::streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
||||||
|
float min, float max)
|
||||||
|
{
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
boost::shared_ptr<OpenAL_SoundStream> sound;
|
||||||
|
ALuint src;
|
||||||
|
|
||||||
|
if(mFreeSources.empty())
|
||||||
|
fail("No free sources");
|
||||||
|
src = mFreeSources.front();
|
||||||
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DecoderPtr decoder = mManager.getDecoder();
|
||||||
|
decoder->open(fname);
|
||||||
|
sound.reset(new OpenAL_SoundStream(*this, src, decoder));
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
mFreeSources.push_back(src);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
|
||||||
|
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_REFERENCE_DISTANCE, min);
|
||||||
|
alSourcef(src, AL_MAX_DISTANCE, max);
|
||||||
|
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
|
||||||
|
alSourcef(src, AL_GAIN, volume);
|
||||||
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
alSourcei(src, AL_LOOPING, AL_FALSE);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
sound->play();
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenAL_Output::updateListener(const float *pos, const float *atdir, const float *updir)
|
||||||
|
{
|
||||||
|
float orient[6] = {
|
||||||
|
atdir[0], atdir[2], -atdir[1],
|
||||||
|
updir[0], updir[2], -updir[1]
|
||||||
|
};
|
||||||
|
|
||||||
|
alListener3f(AL_POSITION, pos[0], pos[2], -pos[1]);
|
||||||
|
alListenerfv(AL_ORIENTATION, orient);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenAL_Output::OpenAL_Output(SoundManager &mgr)
|
||||||
|
: Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0),
|
||||||
|
mStreamThread(new StreamThread)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenAL_Output::~OpenAL_Output()
|
||||||
|
{
|
||||||
|
deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
apps/openmw/mwsound/openal_output.hpp
Normal file
71
apps/openmw/mwsound/openal_output.hpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef GAME_SOUND_OPENAL_OUTPUT_H
|
||||||
|
#define GAME_SOUND_OPENAL_OUTPUT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include "alc.h"
|
||||||
|
#include "al.h"
|
||||||
|
|
||||||
|
#include "sound_output.hpp"
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
class SoundManager;
|
||||||
|
class Sound;
|
||||||
|
|
||||||
|
class OpenAL_Output : public Sound_Output
|
||||||
|
{
|
||||||
|
ALCdevice *mDevice;
|
||||||
|
ALCcontext *mContext;
|
||||||
|
|
||||||
|
typedef std::deque<ALuint> IDDq;
|
||||||
|
IDDq mFreeSources;
|
||||||
|
IDDq mUnusedBuffers;
|
||||||
|
|
||||||
|
typedef std::map<std::string,ALuint> NameMap;
|
||||||
|
NameMap mBufferCache;
|
||||||
|
|
||||||
|
typedef std::map<ALuint,ALuint> IDRefMap;
|
||||||
|
IDRefMap mBufferRefs;
|
||||||
|
|
||||||
|
uint64_t mBufferCacheMemSize;
|
||||||
|
|
||||||
|
ALuint getBuffer(const std::string &fname);
|
||||||
|
void bufferFinished(ALuint buffer);
|
||||||
|
|
||||||
|
virtual std::vector<std::string> enumerate();
|
||||||
|
virtual void init(const std::string &devname="");
|
||||||
|
virtual void deinit();
|
||||||
|
|
||||||
|
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, bool loop);
|
||||||
|
virtual SoundPtr playSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
||||||
|
float min, float max, bool loop);
|
||||||
|
|
||||||
|
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch);
|
||||||
|
virtual SoundPtr streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
||||||
|
float min, float max);
|
||||||
|
|
||||||
|
virtual void updateListener(const float *pos, const float *atdir, const float *updir);
|
||||||
|
|
||||||
|
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
||||||
|
OpenAL_Output(const OpenAL_Output &rhs);
|
||||||
|
|
||||||
|
OpenAL_Output(SoundManager &mgr);
|
||||||
|
virtual ~OpenAL_Output();
|
||||||
|
|
||||||
|
class StreamThread;
|
||||||
|
std::auto_ptr<StreamThread> mStreamThread;
|
||||||
|
|
||||||
|
friend class OpenAL_Sound;
|
||||||
|
friend class OpenAL_SoundStream;
|
||||||
|
friend class SoundManager;
|
||||||
|
};
|
||||||
|
#ifndef DEFAULT_OUTPUT
|
||||||
|
#define DEFAULT_OUTPUT (::MWSound::OpenAL_Output)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
36
apps/openmw/mwsound/sound.hpp
Normal file
36
apps/openmw/mwsound/sound.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef GAME_SOUND_SOUND_H
|
||||||
|
#define GAME_SOUND_SOUND_H
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
class Sound
|
||||||
|
{
|
||||||
|
virtual void update(const float *pos) = 0;
|
||||||
|
|
||||||
|
Sound& operator=(const Sound &rhs);
|
||||||
|
Sound(const Sound &rhs);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
|
||||||
|
float mBaseVolume;
|
||||||
|
float mMinDistance;
|
||||||
|
float mMaxDistance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void stop() = 0;
|
||||||
|
virtual bool isPlaying() = 0;
|
||||||
|
virtual void setVolume(float volume) = 0;
|
||||||
|
|
||||||
|
Sound() : mVolume(1.0f)
|
||||||
|
, mBaseVolume(1.0f)
|
||||||
|
, mMinDistance(20.0f) /* 1 * min_range_scale */
|
||||||
|
, mMaxDistance(12750.0f) /* 255 * max_range_scale */
|
||||||
|
{ }
|
||||||
|
virtual ~Sound() { }
|
||||||
|
|
||||||
|
friend class OpenAL_Output;
|
||||||
|
friend class SoundManager;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
48
apps/openmw/mwsound/sound_decoder.hpp
Normal file
48
apps/openmw/mwsound/sound_decoder.hpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef GAME_SOUND_SOUND_DECODER_H
|
||||||
|
#define GAME_SOUND_SOUND_DECODER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <OgreResourceGroupManager.h>
|
||||||
|
|
||||||
|
namespace MWSound
|
||||||
|
{
|
||||||
|
enum SampleType {
|
||||||
|
SampleType_UInt8,
|
||||||
|
SampleType_Int16
|
||||||
|
};
|
||||||
|
const char *getSampleTypeName(SampleType type);
|
||||||
|
|
||||||
|
enum ChannelConfig {
|
||||||
|
ChannelConfig_Mono,
|
||||||
|
ChannelConfig_Stereo
|
||||||
|
};
|
||||||
|
const char *getChannelConfigName(ChannelConfig config);
|
||||||
|
|
||||||
|
size_t framesToBytes(size_t frames, ChannelConfig config, SampleType type);
|
||||||
|
size_t bytesToFrames(size_t bytes, ChannelConfig config, SampleType type);
|
||||||
|
|
||||||
|
struct Sound_Decoder
|
||||||
|
{
|
||||||
|
Ogre::ResourceGroupManager &mResourceMgr;
|
||||||
|
|
||||||
|
virtual void open(const std::string &fname) = 0;
|
||||||
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
||||||
|
|
||||||
|
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||||
|
virtual void readAll(std::vector<char> &output);
|
||||||
|
virtual void rewind() = 0;
|
||||||
|
|
||||||
|
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
||||||
|
{ }
|
||||||
|
virtual ~Sound_Decoder() { }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Sound_Decoder(const Sound_Decoder &rhs);
|
||||||
|
Sound_Decoder& operator=(const Sound_Decoder &rhs);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue