mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 05:09:43 +00:00
Merge branch 'next' into terrain_next
Conflicts: CMakeLists.txt apps/openmw/CMakeLists.txt apps/openmw/mwrender/renderingmanager.cpp apps/openmw/mwrender/renderingmanager.hpp cmake/FindOGRE.cmake
This commit is contained in:
commit
f2c3616638
254 changed files with 8103 additions and 33876 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -7,3 +7,6 @@ Docs/mainpage.hpp
|
|||
CMakeFiles
|
||||
*/CMakeFiles
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
makefile
|
||||
data
|
||||
|
|
202
CMakeLists.txt
202
CMakeLists.txt
|
@ -1,11 +1,13 @@
|
|||
project(OpenMW)
|
||||
|
||||
IF (APPLE)
|
||||
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/OpenMW.app")
|
||||
if (APPLE)
|
||||
set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
||||
|
||||
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
|
||||
|
||||
# using 10.6 sdk
|
||||
set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk")
|
||||
ENDIF (APPLE)
|
||||
endif (APPLE)
|
||||
|
||||
# Macros
|
||||
|
||||
|
@ -94,6 +96,7 @@ source_group(libs\\mangle FILES ${MANGLE_ALL})
|
|||
set(OENGINE_OGRE
|
||||
${LIBDIR}/openengine/ogre/renderer.cpp
|
||||
${LIBDIR}/openengine/ogre/mouselook.cpp
|
||||
${LIBDIR}/openengine/ogre/fader.cpp
|
||||
)
|
||||
set(OENGINE_GUI
|
||||
${LIBDIR}/openengine/gui/events.cpp
|
||||
|
@ -191,7 +194,6 @@ include_directories("."
|
|||
${OGRE_Terrain_INCLUDE_DIR}
|
||||
${OIS_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
|
||||
${PLATFORM_INCLUDE_DIR}
|
||||
${CMAKE_HOME_DIRECTORY}/extern/caelum/include
|
||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include
|
||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/OgrePlatform/include
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
|
@ -201,7 +203,14 @@ include_directories("."
|
|||
|
||||
link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR})
|
||||
|
||||
add_subdirectory( extern/caelum )
|
||||
if(APPLE)
|
||||
# List used Ogre plugins
|
||||
SET(USED_OGRE_PLUGINS "RenderSystem_GL"
|
||||
"Plugin_OctreeSceneManager"
|
||||
"Plugin_CgProgramManager"
|
||||
"Plugin_ParticleFX")
|
||||
endif(APPLE)
|
||||
|
||||
add_subdirectory( extern/mygui_3.0.1 )
|
||||
|
||||
# Make sure that certain libraries are used as static libraries
|
||||
|
@ -211,9 +220,6 @@ add_subdirectory( extern/mygui_3.0.1 )
|
|||
# MyGUI: extern/mygui_3.0.0/
|
||||
add_definitions(-DMYGUI_STATIC)
|
||||
|
||||
# Caelum: extern/caelum/
|
||||
add_definitions(-DCAELUM_STATIC)
|
||||
|
||||
# Specify build paths
|
||||
|
||||
if (APPLE)
|
||||
|
@ -244,32 +250,16 @@ if (APPLE)
|
|||
"${OpenMW_BINARY_DIR}/plugins.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
|
||||
"${APP_BUNDLE_DIR}/Contents/Info.plist" COPYONLY)
|
||||
"${APP_BUNDLE_DIR}/Contents/Info.plist")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns
|
||||
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
|
||||
|
||||
|
||||
# prepare plugins
|
||||
configure_file(${OGRE_PLUGIN_DIR}/RenderSystem_GL.dylib
|
||||
"${APP_BUNDLE_DIR}/Contents/Plugins/RenderSystem_GL.dylib" COPYONLY)
|
||||
|
||||
configure_file(${OGRE_PLUGIN_DIR}/Plugin_OctreeSceneManager.dylib
|
||||
"${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_OctreeSceneManager.dylib" COPYONLY)
|
||||
|
||||
configure_file(${OGRE_PLUGIN_DIR}/Plugin_ParticleFX.dylib
|
||||
"${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_ParticleFX.dylib" COPYONLY)
|
||||
|
||||
# prepare components
|
||||
configure_file(${OGRE_LIB_DIR}/libOgrePaging.dylib
|
||||
"${APP_BUNDLE_DIR}/Contents/Components/libOgrePaging.dylib" COPYONLY)
|
||||
|
||||
configure_file(${OGRE_LIB_DIR}/libOgreTerrain.dylib
|
||||
"${APP_BUNDLE_DIR}/Contents/Components/libOgreTerrain.dylib" COPYONLY)
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||
"${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg")
|
||||
|
||||
foreach(plugin ${USED_OGRE_PLUGINS})
|
||||
configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib"
|
||||
"${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib"
|
||||
COPYONLY)
|
||||
endforeach()
|
||||
endif (APPLE)
|
||||
|
||||
|
||||
|
@ -279,36 +269,6 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
|||
add_definitions (-Wall)
|
||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# Apple bundling
|
||||
# TODO REWRITE!
|
||||
if (APPLE)
|
||||
set(MISC_FILES
|
||||
${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg
|
||||
${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg)
|
||||
|
||||
set(OGRE_PLUGINS
|
||||
${APP_BUNDLE_DIR}/Contents/Plugins/*)
|
||||
|
||||
install(FILES ${MISC_FILES} DESTINATION ../MacOS)
|
||||
install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..)
|
||||
install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources)
|
||||
set(CPACK_GENERATOR "Bundle")
|
||||
set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist")
|
||||
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns")
|
||||
set(CPACK_BUNDLE_NAME "OpenMW")
|
||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
|
||||
include(CPack)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-arch i386")
|
||||
set(CMAKE_CXX_FLAGS "-arch i386")
|
||||
|
||||
endif (APPLE)
|
||||
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
SET(CMAKE_INSTALL_PREFIX "/usr")
|
||||
|
||||
|
@ -362,6 +322,45 @@ if(DPKG_PROGRAM)
|
|||
include(CPack)
|
||||
endif(DPKG_PROGRAM)
|
||||
|
||||
if(WIN32)
|
||||
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
|
||||
INSTALL(FILES ${files} DESTINATION ".")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.cfg" "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION ".")
|
||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||
|
||||
SET(CPACK_GENERATOR "NSIS")
|
||||
SET(CPACK_PACKAGE_NAME "OpenMW")
|
||||
SET(CPACK_PACKAGE_VENDOR "OpenMW.org")
|
||||
SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
|
||||
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW")
|
||||
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
|
||||
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
|
||||
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
|
||||
|
||||
SET(VCREDIST "${OpenMW_BINARY_DIR}/vcredist_x86.exe")
|
||||
if(EXISTS ${VCREDIST})
|
||||
INSTALL(FILES ${VCREDIST} DESTINATION "redist")
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" )
|
||||
endif(EXISTS ${VCREDIST})
|
||||
|
||||
SET(OALREDIST "${OpenMW_BINARY_DIR}/oalinst.exe")
|
||||
if(EXISTS ${OALREDIST})
|
||||
INSTALL(FILES ${OALREDIST} DESTINATION "redist")
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
|
||||
ExecWait '\\\"$INSTDIR\\\\redist\\\\oalinst.exe\\\" /s'" )
|
||||
endif(EXISTS ${OALREDIST})
|
||||
|
||||
include(CPack)
|
||||
endif(WIN32)
|
||||
|
||||
# Components
|
||||
add_subdirectory (components)
|
||||
|
||||
|
@ -416,3 +415,86 @@ if (WIN32)
|
|||
#set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
endif()
|
||||
|
||||
# Apple bundling
|
||||
if (APPLE)
|
||||
set(INSTALL_SUBDIR OpenMW)
|
||||
|
||||
#install(FILES ${MISC_FILES} DESTINATION ../MacOS)
|
||||
#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..)
|
||||
#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources)
|
||||
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
|
||||
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
# set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist")
|
||||
# set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns")
|
||||
# set(CPACK_BUNDLE_NAME "OpenMW")
|
||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
|
||||
set(PLUGINS "")
|
||||
|
||||
# Scan Plugins dir for *.dylibs
|
||||
file(GLOB ALL_PLUGINS "${APP_BUNDLE_DIR}/Contents/Plugins/*.dylib")
|
||||
|
||||
foreach(PLUGIN ${ALL_PLUGINS})
|
||||
get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME)
|
||||
set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins/${PLUGIN_FILENAME}")
|
||||
endforeach()
|
||||
|
||||
#For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail
|
||||
set(DIRS "")
|
||||
|
||||
# Overriding item resolving during installation, it needed if
|
||||
# some library already has be "fixed up", i.e. its id name contains @executable_path,
|
||||
# but library is not embedded in bundle. For example, it's Ogre.framework from Ogre SDK.
|
||||
# Current implementation of GetPrerequsities/BundleUtilities doesn't handle that case.
|
||||
#
|
||||
# Current limitations:
|
||||
# 1. Handles only frameworks, not simple libs
|
||||
INSTALL(CODE "
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH})
|
||||
|
||||
set(OPENMW_RESOLVED_ITEMS \"\")
|
||||
|
||||
function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var)
|
||||
if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}})
|
||||
if (item MATCHES \"Frameworks\") # if it is a framework
|
||||
# get last segment of path
|
||||
get_filename_component(fname \"\${item}\" NAME_WE)
|
||||
find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks)
|
||||
if (ri)
|
||||
message(STATUS \"found \${ri} for \${item}\")
|
||||
string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item})
|
||||
set(ri \"\${ri}\${item_part}\")
|
||||
set(\${resolved_item_var} \${ri} PARENT_SCOPE)
|
||||
set(\${resolved_var} 1 PARENT_SCOPE)
|
||||
set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri})
|
||||
endif()
|
||||
else()
|
||||
# code path for standard (non-framework) libs (ogre & qt pugins)
|
||||
endif()
|
||||
endif()
|
||||
endfunction(gp_resolve_item_override)
|
||||
|
||||
cmake_policy(SET CMP0009 OLD)
|
||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||
include(BundleUtilities)
|
||||
fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
include(CPack)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-arch i386")
|
||||
set(CMAKE_CXX_FLAGS "-arch i386")
|
||||
|
||||
endif (APPLE)
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
esmtool_cmd.c: esmtool.ggo
|
||||
gengetopt < esmtool.ggo
|
||||
|
||||
clean:
|
||||
rm esmtool_cmd.c esmtool_cmd.h
|
|
@ -926,13 +926,13 @@ int update_arg(void *field, char **orig_field,
|
|||
const char *long_opt, char short_opt,
|
||||
const char *additional_error)
|
||||
{
|
||||
char *stop_char = 0;
|
||||
const char *val = value;
|
||||
int found;
|
||||
//char *stop_char = 0;
|
||||
//const char *val = value;
|
||||
//int found;
|
||||
FIX_UNUSED (field);
|
||||
|
||||
stop_char = 0;
|
||||
found = 0;
|
||||
//stop_char = 0;
|
||||
//found = 0;
|
||||
|
||||
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
|
||||
{
|
||||
|
@ -955,8 +955,8 @@ int update_arg(void *field, char **orig_field,
|
|||
(*prev_given)++;
|
||||
if (field_given)
|
||||
(*field_given)++;
|
||||
if (possible_values)
|
||||
val = possible_values[found];
|
||||
//if (possible_values)
|
||||
//val = possible_values[found];
|
||||
|
||||
switch(arg_type) {
|
||||
default:
|
||||
|
@ -996,7 +996,7 @@ cmdline_parser_internal (
|
|||
|
||||
int override;
|
||||
int initialize;
|
||||
int check_required;
|
||||
//int check_required;
|
||||
int check_ambiguity;
|
||||
|
||||
char *optarg;
|
||||
|
@ -1008,7 +1008,7 @@ cmdline_parser_internal (
|
|||
|
||||
override = params->override;
|
||||
initialize = params->initialize;
|
||||
check_required = params->check_required;
|
||||
//check_required = params->check_required;
|
||||
check_ambiguity = params->check_ambiguity;
|
||||
|
||||
if (initialize)
|
||||
|
|
|
@ -41,14 +41,25 @@ source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC
|
|||
find_package(Qt4 REQUIRED)
|
||||
set(QT_USE_QTGUI 1)
|
||||
|
||||
find_package(PNG REQUIRED)
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
#find_package(PNG REQUIRED)
|
||||
#include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
QT4_ADD_RESOURCES(RCC_SRCS resources.qrc)
|
||||
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
# list here plugins that can't be detected statically, but loaded in runtime
|
||||
# it needed for packaging automatisation
|
||||
#set(USED_QT_PLUGINS imageformats/libqgif
|
||||
# imageformats/libqico
|
||||
# imageformats/libqjpeg
|
||||
# imageformats/libqmng
|
||||
# imageformats/libqsvg
|
||||
# imageformats/libqtga
|
||||
# imageformats/libqtiff)
|
||||
# It seems that launcher works without this plugins, but it loads them into memory if they exists
|
||||
|
||||
# Main executable
|
||||
add_executable(omwlauncher
|
||||
${LAUNCHER}
|
||||
|
@ -60,7 +71,7 @@ target_link_libraries(omwlauncher
|
|||
${Boost_LIBRARIES}
|
||||
${OGRE_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
${PNG_LIBRARY}
|
||||
# ${PNG_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
@ -73,6 +84,13 @@ if (APPLE)
|
|||
"${APP_BUNDLE_DIR}/../launcher.qss")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
|
||||
"${APP_BUNDLE_DIR}/../launcher.cfg")
|
||||
|
||||
# copy used QT plugins into ${APP_BUNDLE_DIR}/Contents/Plugins
|
||||
#foreach(PLUGIN ${USED_QT_PLUGINS})
|
||||
# get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME)
|
||||
# configure_file("${QT_PLUGINS_DIR}/${PLUGIN}.dylib" "${APP_BUNDLE_DIR}/Contents/Plugins/${PLUGIN_FILENAME}.dylib" COPYONLY)
|
||||
#endforeach()
|
||||
|
||||
else()
|
||||
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
|
||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss")
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
project(OpenMW)
|
||||
|
||||
# config file
|
||||
|
||||
configure_file ("${OpenMW_SOURCE_DIR}/config.hpp.cmake" "${OpenMW_SOURCE_DIR}/config.hpp")
|
||||
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/config.hpp")
|
||||
|
||||
# local files
|
||||
|
||||
set(GAME
|
||||
main.cpp
|
||||
engine.cpp
|
||||
)
|
||||
)
|
||||
set(GAME_HEADER
|
||||
engine.hpp
|
||||
config.hpp)
|
||||
config.hpp
|
||||
)
|
||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||
|
||||
add_openmw_dir (mwrender
|
||||
renderingmanager debugging sky terrain terrainmaterial player npcs creatures objects renderinginterface
|
||||
renderingmanager debugging sky terrain terrainmaterial player animation npcanimation creatureanimation actors objects renderinginterface
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -25,7 +23,7 @@ add_openmw_dir (mwinput
|
|||
|
||||
add_openmw_dir (mwgui
|
||||
layouts text_input widgets race class birth review window_manager console dialogue
|
||||
dialogue_history window_base stats_window messagebox
|
||||
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
||||
)
|
||||
|
||||
add_openmw_dir (mwdialogue
|
||||
|
@ -36,6 +34,7 @@ add_openmw_dir (mwscript
|
|||
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
|
||||
guiextensions soundextensions skyextensions statsextensions containerextensions
|
||||
aiextensions controlextensions extensions globalscripts ref dialogueextensions
|
||||
animationextensions
|
||||
)
|
||||
|
||||
add_openmw_dir (mwsound
|
||||
|
@ -44,8 +43,8 @@ add_openmw_dir (mwsound
|
|||
|
||||
add_openmw_dir (mwworld
|
||||
refdata world physicssystem scene environment globals class action nullaction actionteleport
|
||||
containerstore actiontalk actiontake containerstore manualref containerutil player cellfunctors
|
||||
cells localscripts
|
||||
containerstore actiontalk actiontake manualref player cellfunctors
|
||||
cells localscripts customdata weather
|
||||
)
|
||||
|
||||
add_openmw_dir (mwclass
|
||||
|
@ -60,13 +59,11 @@ add_openmw_dir (mwmechanics
|
|||
# Main executable
|
||||
add_executable(openmw
|
||||
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
|
||||
${CONPONENT_FILES}
|
||||
${COMPONENT_FILES}
|
||||
${OPENMW_FILES}
|
||||
${GAME} ${GAME_HEADER}
|
||||
${APPLE_BUNDLE_RESOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries (openmw components)
|
||||
)
|
||||
|
||||
# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
|
||||
# when we change the backend.
|
||||
|
@ -74,27 +71,23 @@ include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS})
|
|||
add_definitions(${SOUND_DEFINE})
|
||||
|
||||
target_link_libraries(openmw
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_Terrain_LIBRARY}
|
||||
${OIS_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${SOUND_INPUT_LIBRARY}
|
||||
${BULLET_LIBRARIES}
|
||||
caelum
|
||||
MyGUIEngine
|
||||
MyGUIOgrePlatform
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_Terrain_LIBRARY}
|
||||
${OIS_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${SOUND_INPUT_LIBRARY}
|
||||
${BULLET_LIBRARIES}
|
||||
components
|
||||
MyGUIEngine
|
||||
MyGUIOgrePlatform
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
if(APPLE)
|
||||
find_library(CARBON_FRAMEWORK Carbon)
|
||||
target_link_libraries(openmw ${CARBON_FRAMEWORK})
|
||||
install(TARGETS openmw
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ../MacOS
|
||||
COMPONENT Runtime)
|
||||
endif (APPLE)
|
||||
endif(APPLE)
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw)
|
||||
endif()
|
||||
endif(DPKG_PROGRAM)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderWindow.h>
|
||||
|
||||
#include <MyGUI_WidgetManager.h>
|
||||
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include <components/esm/esm_reader.hpp>
|
||||
#include <components/files/path.hpp>
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
||||
#include "mwinput/inputmanager.hpp"
|
||||
|
||||
|
@ -33,8 +35,6 @@
|
|||
#include "mwsound/soundmanager.hpp"
|
||||
|
||||
#include "mwworld/world.hpp"
|
||||
#include "mwworld/ptr.hpp"
|
||||
#include "mwworld/environment.hpp"
|
||||
#include "mwworld/class.hpp"
|
||||
#include "mwworld/player.hpp"
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include "mwmechanics/mechanicsmanager.hpp"
|
||||
|
||||
|
||||
void OMW::Engine::executeLocalScripts()
|
||||
{
|
||||
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
|
||||
|
@ -99,6 +100,13 @@ void OMW::Engine::updateFocusReport (float duration)
|
|||
}
|
||||
}
|
||||
|
||||
void OMW::Engine::setAnimationVerbose(bool animverbose){
|
||||
if(animverbose){
|
||||
NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true);
|
||||
NifOgre::NIFLoader::getSingletonPtr()->setVerbosePath(mCfgMgr.getLogPath().string());
|
||||
}
|
||||
}
|
||||
|
||||
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||
{
|
||||
try
|
||||
|
@ -115,8 +123,10 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
}
|
||||
|
||||
// update GUI
|
||||
if(mShowFPS)
|
||||
mEnvironment.mWindowManager->wmSetFPS(mOgre->getFPS());
|
||||
Ogre::RenderWindow* window = mOgre->getWindow();
|
||||
mEnvironment.mWindowManager->wmUpdateFps(window->getLastFPS(),
|
||||
window->getTriangleCount(),
|
||||
window->getBatchCount());
|
||||
|
||||
mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration);
|
||||
|
||||
|
@ -135,6 +145,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
mEnvironment.mWorld->advanceTime (
|
||||
mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600);
|
||||
|
||||
|
||||
if (changed) // keep change flag for another frame, if cell changed happend in local script
|
||||
mEnvironment.mWorld->markCellAsUnchanged();
|
||||
|
||||
|
@ -145,6 +156,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game)
|
||||
mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration);
|
||||
|
||||
// update world
|
||||
mEnvironment.mWorld->update (evt.timeSinceLastFrame);
|
||||
|
||||
// report focus object (for debugging)
|
||||
if (mReportFocus)
|
||||
updateFocusReport (mEnvironment.mFrameDuration);
|
||||
|
@ -159,8 +173,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
|
||||
OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager)
|
||||
: mOgre (0)
|
||||
, mPhysicEngine (0)
|
||||
, mShowFPS (false)
|
||||
, mFpsLevel(0)
|
||||
, mDebug (false)
|
||||
, mVerboseScripts (false)
|
||||
, mNewGame (false)
|
||||
|
@ -170,7 +183,6 @@ OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager)
|
|||
, mFocusTDiff (0)
|
||||
, mScriptManager (0)
|
||||
, mScriptContext (0)
|
||||
, mGuiManager (0)
|
||||
, mFSStrict (false)
|
||||
, mCfgMgr(configurationManager)
|
||||
{
|
||||
|
@ -180,7 +192,6 @@ OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager)
|
|||
|
||||
OMW::Engine::~Engine()
|
||||
{
|
||||
delete mGuiManager;
|
||||
delete mEnvironment.mWorld;
|
||||
delete mEnvironment.mSoundManager;
|
||||
delete mEnvironment.mGlobalScripts;
|
||||
|
@ -189,7 +200,6 @@ OMW::Engine::~Engine()
|
|||
delete mEnvironment.mJournal;
|
||||
delete mScriptManager;
|
||||
delete mScriptContext;
|
||||
delete mPhysicEngine;
|
||||
delete mOgre;
|
||||
}
|
||||
|
||||
|
@ -317,25 +327,15 @@ void OMW::Engine::go()
|
|||
|
||||
loadBSA();
|
||||
|
||||
/// \todo move this into the physics manager
|
||||
// Create physics. shapeLoader is deleted by the physic engine
|
||||
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
|
||||
mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
|
||||
|
||||
// Create the world
|
||||
mEnvironment.mWorld = new MWWorld::World (*mOgre, mPhysicEngine, mFileCollections, mMaster,
|
||||
mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
||||
mResDir, mNewGame, mEnvironment, mEncoding);
|
||||
|
||||
/// \todo move this into the GUI manager (a.k.a WindowManager)
|
||||
// Set up the GUI system
|
||||
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false,
|
||||
mCfgMgr.getLogPath().string() + std::string("/"));
|
||||
|
||||
// Create window manager - this manages all the MW-specific GUI windows
|
||||
MWScript::registerExtensions (mExtensions);
|
||||
|
||||
mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui(), mEnvironment,
|
||||
mExtensions, mShowFPS, mNewGame);
|
||||
mEnvironment.mWindowManager = new MWGui::WindowManager(mEnvironment,
|
||||
mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"));
|
||||
|
||||
// Create sound system
|
||||
mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(),
|
||||
|
@ -445,6 +445,28 @@ void OMW::Engine::activate()
|
|||
}
|
||||
}
|
||||
|
||||
void OMW::Engine::screenshot()
|
||||
{
|
||||
// Count screenshots.
|
||||
int shotCount = 0;
|
||||
|
||||
const std::string screenshotPath = mCfgMgr.getLocalConfigPath().string();
|
||||
|
||||
// Find the first unused filename with a do-while
|
||||
std::ostringstream stream;
|
||||
do
|
||||
{
|
||||
// Reset the stream
|
||||
stream.str("");
|
||||
stream.clear();
|
||||
|
||||
stream << screenshotPath << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << ".png";
|
||||
|
||||
} while (boost::filesystem::exists(stream.str()));
|
||||
|
||||
mOgre->screenshot(stream.str());
|
||||
}
|
||||
|
||||
void OMW::Engine::setCompileAll (bool all)
|
||||
{
|
||||
mCompileAll = all;
|
||||
|
@ -455,9 +477,9 @@ void OMW::Engine::setSoundUsage(bool soundUsage)
|
|||
mUseSound = soundUsage;
|
||||
}
|
||||
|
||||
void OMW::Engine::showFPS(bool showFps)
|
||||
void OMW::Engine::showFPS(int level)
|
||||
{
|
||||
mShowFPS = showFps;
|
||||
mFpsLevel = level;
|
||||
}
|
||||
|
||||
void OMW::Engine::setEncoding(const std::string& encoding)
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <OgreFrameListener.h>
|
||||
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
#include <components/files/collections.hpp>
|
||||
#include <components/cfg/configurationmanager.hpp>
|
||||
|
@ -63,10 +61,9 @@ namespace OMW
|
|||
boost::filesystem::path mDataDir;
|
||||
boost::filesystem::path mResDir;
|
||||
OEngine::Render::OgreRenderer *mOgre;
|
||||
OEngine::Physic::PhysicEngine* mPhysicEngine;
|
||||
std::string mCellName;
|
||||
std::string mMaster;
|
||||
bool mShowFPS;
|
||||
int mFpsLevel;
|
||||
bool mDebug;
|
||||
bool mVerboseScripts;
|
||||
bool mNewGame;
|
||||
|
@ -80,7 +77,7 @@ namespace OMW
|
|||
MWScript::ScriptManager *mScriptManager;
|
||||
Compiler::Extensions mExtensions;
|
||||
Compiler::Context *mScriptContext;
|
||||
OEngine::GUI::MyGUIManager *mGuiManager;
|
||||
|
||||
|
||||
Files::Collections mFileCollections;
|
||||
bool mFSStrict;
|
||||
|
@ -128,7 +125,7 @@ namespace OMW
|
|||
void addMaster(const std::string& master);
|
||||
|
||||
/// Enable fps counter
|
||||
void showFPS(bool showFps);
|
||||
void showFPS(int level);
|
||||
|
||||
/// Enable debug mode:
|
||||
/// - non-exclusive input
|
||||
|
@ -152,12 +149,17 @@ namespace OMW
|
|||
/// Activate the focussed object.
|
||||
void activate();
|
||||
|
||||
/// Write screenshot to file.
|
||||
void screenshot();
|
||||
|
||||
/// Compile all scripts (excludign dialogue scripts) at startup?
|
||||
void setCompileAll (bool all);
|
||||
|
||||
/// Font encoding
|
||||
void setEncoding(const std::string& encoding);
|
||||
|
||||
void setAnimationVerbose(bool animverbose);
|
||||
|
||||
private:
|
||||
Cfg::ConfigurationManager& mCfgMgr;
|
||||
};
|
||||
|
|
|
@ -75,8 +75,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio
|
|||
("plugin", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
||||
->multitoken(), "plugin file(s)")
|
||||
|
||||
("fps", boost::program_options::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "show fps counter")
|
||||
("fps", boost::program_options::value<int>()->implicit_value(1)
|
||||
->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)")
|
||||
|
||||
("anim-verbose", boost::program_options::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "output animation indices files")
|
||||
|
||||
("debug", boost::program_options::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "debug mode")
|
||||
|
@ -200,12 +203,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio
|
|||
engine.setNewGame(variables["new-game"].as<bool>());
|
||||
|
||||
// other settings
|
||||
engine.showFPS(variables["fps"].as<bool>());
|
||||
engine.showFPS(variables["fps"].as<int>());
|
||||
engine.setDebugMode(variables["debug"].as<bool>());
|
||||
engine.setSoundUsage(!variables["nosound"].as<bool>());
|
||||
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
|
||||
engine.setCompileAll(variables["script-all"].as<bool>());
|
||||
engine.setReportFocus(variables["report-focus"].as<bool>());
|
||||
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -58,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Apparatus::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.appas);
|
||||
}
|
||||
|
||||
std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_APPARATUS_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -70,12 +69,6 @@ namespace MWClass
|
|||
return ref->base->data.health;
|
||||
}
|
||||
|
||||
void Armor::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.armors);
|
||||
}
|
||||
|
||||
std::string Armor::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_ARMOR_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -29,10 +28,6 @@ namespace MWClass
|
|||
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
|
||||
///< Return item max health or throw an exception, if class does not have item health
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -60,12 +59,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Book::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.books);
|
||||
}
|
||||
|
||||
std::string Book::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_BOOK_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -58,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Clothing::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.clothes);
|
||||
}
|
||||
|
||||
std::string Clothing::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_CLOTHING_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -6,9 +6,45 @@
|
|||
#include <components/esm_store/cell_store.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/nullaction.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/customdata.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct CustomData : public MWWorld::CustomData
|
||||
{
|
||||
MWWorld::ContainerStore mContainerStore;
|
||||
|
||||
virtual MWWorld::CustomData *clone() const;
|
||||
};
|
||||
|
||||
MWWorld::CustomData *CustomData::clone() const
|
||||
{
|
||||
return new CustomData (*this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
void Container::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
std::auto_ptr<CustomData> data (new CustomData);
|
||||
|
||||
// \todo add initial container content
|
||||
|
||||
// store
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
}
|
||||
|
||||
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
||||
|
@ -16,7 +52,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -39,6 +75,38 @@ namespace MWClass
|
|||
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Container::activate (const MWWorld::Ptr& ptr,
|
||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||
{
|
||||
const std::string lockedSound = "LockedChest";
|
||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||
|
||||
if (ptr.getCellRef().lockLevel>0)
|
||||
{
|
||||
// TODO check for key
|
||||
std::cout << "Locked container" << std::endl;
|
||||
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unlocked container" << std::endl;
|
||||
if(ptr.getCellRef().trap.empty())
|
||||
{
|
||||
// Not trapped, Inventory GUI goes here
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trap activation goes here
|
||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
|
||||
ptr.getCellRef().trap = "";
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Container::getName (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
||||
|
@ -47,20 +115,12 @@ namespace MWClass
|
|||
return ref->base->name;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& Container::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
const
|
||||
{
|
||||
if (!ptr.getRefData().getContainerStore().get())
|
||||
{
|
||||
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
|
||||
new MWWorld::ContainerStore<MWWorld::RefData>);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
// TODO add initial content
|
||||
|
||||
ptr.getRefData().getContainerStore() = store;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getContainerStore();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
|
||||
}
|
||||
|
||||
std::string Container::getScript (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#define GAME_MWCLASS_CONTAINER_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
class Container : public MWWorld::Class
|
||||
{
|
||||
void ensureCustomData (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
public:
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
|
@ -19,8 +20,11 @@ namespace MWClass
|
|||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
||||
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore (
|
||||
const MWWorld::Ptr& ptr) const;
|
||||
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
|
||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
|
||||
///< Return container store
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef GAME_MWCLASS_CONTAINERUTIL_H
|
||||
#define GAME_MWCLASS_CONTAINERUTIL_H
|
||||
|
||||
#include <components/esm_store/cell_store.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
template<typename T>
|
||||
void insertIntoContainerStore (const MWWorld::Ptr& ptr,
|
||||
ESMS::CellRefList<T, MWWorld::RefData>& containerStore)
|
||||
{
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
// TODO check stacking
|
||||
|
||||
ESMS::LiveCellRef<T, MWWorld::RefData> cellRef(ptr.getCellRef(), ptr.get<T>()->base);
|
||||
cellRef.mData = ptr.getRefData();
|
||||
|
||||
containerStore.list.push_back (cellRef);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -4,16 +4,62 @@
|
|||
#include <components/esm/loadcrea.hpp>
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/customdata.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct CustomData : public MWWorld::CustomData
|
||||
{
|
||||
MWMechanics::CreatureStats mCreatureStats;
|
||||
MWWorld::ContainerStore mContainerStore;
|
||||
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
virtual MWWorld::CustomData *clone() const;
|
||||
};
|
||||
|
||||
MWWorld::CustomData *CustomData::clone() const
|
||||
{
|
||||
return new CustomData (*this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
void Creature::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
std::auto_ptr<CustomData> data (new CustomData);
|
||||
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ptr.get<ESM::Creature>();
|
||||
|
||||
// creature stats
|
||||
data->mCreatureStats.mAttributes[0].set (ref->base->data.strength);
|
||||
data->mCreatureStats.mAttributes[1].set (ref->base->data.intelligence);
|
||||
data->mCreatureStats.mAttributes[2].set (ref->base->data.willpower);
|
||||
data->mCreatureStats.mAttributes[3].set (ref->base->data.agility);
|
||||
data->mCreatureStats.mAttributes[4].set (ref->base->data.speed);
|
||||
data->mCreatureStats.mAttributes[5].set (ref->base->data.endurance);
|
||||
data->mCreatureStats.mAttributes[6].set (ref->base->data.personality);
|
||||
data->mCreatureStats.mAttributes[7].set (ref->base->data.luck);
|
||||
data->mCreatureStats.mDynamic[0].set (ref->base->data.health);
|
||||
data->mCreatureStats.mDynamic[1].set (ref->base->data.mana);
|
||||
data->mCreatureStats.mDynamic[2].set (ref->base->data.fatigue);
|
||||
|
||||
data->mCreatureStats.mLevel = ref->base->data.level;
|
||||
|
||||
// \todo add initial container content
|
||||
|
||||
// store
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
}
|
||||
|
||||
std::string Creature::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||
|
@ -24,24 +70,12 @@ namespace MWClass
|
|||
|
||||
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
/*
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Creatures& creatures = renderingInterface.getCreatures();
|
||||
//creatures.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||
//creatures.insertMesh(ptr, "meshes\\" + model);
|
||||
}*/
|
||||
MWRender::Actors& actors = renderingInterface.getActors();
|
||||
actors.insertCreature(ptr);
|
||||
}
|
||||
|
||||
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||
{
|
||||
/*
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
|
@ -50,8 +84,7 @@ namespace MWClass
|
|||
assert (ref->base != NULL);
|
||||
if(!model.empty()){
|
||||
physics.insertActorPhysics(ptr, "meshes\\" + model);
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||
|
@ -74,31 +107,9 @@ namespace MWClass
|
|||
|
||||
MWMechanics::CreatureStats& Creature::getCreatureStats (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCreatureStats().get())
|
||||
{
|
||||
boost::shared_ptr<MWMechanics::CreatureStats> stats (
|
||||
new MWMechanics::CreatureStats);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ptr.get<ESM::Creature>();
|
||||
|
||||
stats->mAttributes[0].set (ref->base->data.strength);
|
||||
stats->mAttributes[1].set (ref->base->data.intelligence);
|
||||
stats->mAttributes[2].set (ref->base->data.willpower);
|
||||
stats->mAttributes[3].set (ref->base->data.agility);
|
||||
stats->mAttributes[4].set (ref->base->data.speed);
|
||||
stats->mAttributes[5].set (ref->base->data.endurance);
|
||||
stats->mAttributes[6].set (ref->base->data.personality);
|
||||
stats->mAttributes[7].set (ref->base->data.luck);
|
||||
stats->mDynamic[0].set (ref->base->data.health);
|
||||
stats->mDynamic[1].set (ref->base->data.mana);
|
||||
stats->mDynamic[2].set (ref->base->data.fatigue);
|
||||
|
||||
stats->mLevel = ref->base->data.level;
|
||||
|
||||
ptr.getRefData().getCreatureStats() = stats;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getCreatureStats();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr,
|
||||
|
@ -107,20 +118,12 @@ namespace MWClass
|
|||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
||||
}
|
||||
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& Creature::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
const
|
||||
{
|
||||
if (!ptr.getRefData().getContainerStore().get())
|
||||
{
|
||||
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
|
||||
new MWWorld::ContainerStore<MWWorld::RefData>);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
// TODO add initial content
|
||||
|
||||
ptr.getRefData().getContainerStore() = store;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getContainerStore();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
|
||||
}
|
||||
|
||||
std::string Creature::getScript (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
#define GAME_MWCLASS_CREATURE_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/creatures.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
#include "../mwrender/actors.hpp"
|
||||
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
class Creature : public MWWorld::Class
|
||||
{
|
||||
void ensureCustomData (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
public:
|
||||
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
@ -35,7 +39,7 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore (
|
||||
virtual MWWorld::ContainerStore& getContainerStore (
|
||||
const MWWorld::Ptr& ptr) const;
|
||||
///< Return container store
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -39,13 +39,11 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Door>();
|
||||
|
||||
|
||||
const std::string &model = ref->base->model;
|
||||
assert (ref->base != NULL);
|
||||
if(!model.empty()){
|
||||
physics.insertObjectPhysics(ptr, "meshes\\" + model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string Door::getName (const MWWorld::Ptr& ptr) const
|
||||
|
@ -65,15 +63,28 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Door>();
|
||||
|
||||
const std::string &openSound = ref->base->openSound;
|
||||
//const std::string &closeSound = ref->base->closeSound;
|
||||
const std::string lockedSound = "LockedDoor";
|
||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||
|
||||
if (ptr.getCellRef().lockLevel>0)
|
||||
{
|
||||
// TODO check for key
|
||||
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
||||
std::cout << "Locked!" << std::endl;
|
||||
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0);
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
|
||||
// TODO check trap
|
||||
if(!ptr.getCellRef().trap.empty())
|
||||
{
|
||||
// Trap activation
|
||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0);
|
||||
ptr.getCellRef().trap = "";
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
|
||||
if (ref->ref.teleport)
|
||||
{
|
||||
|
@ -81,12 +92,13 @@ namespace MWClass
|
|||
if (environment.mWorld->getPlayer().getPlayer()==actor)
|
||||
{
|
||||
// the player is using the door
|
||||
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
|
||||
return boost::shared_ptr<MWWorld::Action> (
|
||||
new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest));
|
||||
}
|
||||
else
|
||||
{
|
||||
// another NPC or a create is using the door
|
||||
// another NPC or a creature is using the door
|
||||
// TODO return action for teleporting other NPC/creature
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
|
@ -95,6 +107,9 @@ namespace MWClass
|
|||
{
|
||||
// animated door
|
||||
// TODO return action for rotating the door
|
||||
|
||||
// This is a little pointless, but helps with testing
|
||||
environment.mSoundManager->playSound(openSound, 1.0, 1.0);
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_DOOR_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -34,14 +33,11 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Ingredient>();
|
||||
|
||||
|
||||
|
||||
const std::string &model = ref->base->model;
|
||||
assert (ref->base != NULL);
|
||||
if(!model.empty()){
|
||||
physics.insertObjectPhysics(ptr, "meshes\\" + model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string Ingredient::getName (const MWWorld::Ptr& ptr) const
|
||||
|
@ -59,12 +55,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Ingredient::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.ingreds);
|
||||
}
|
||||
|
||||
std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_INGREDIENT_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,19 +23,19 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||
objects.insertMesh(ptr, "meshes\\" + model);
|
||||
const int color = ref->base->data.color;
|
||||
const float r = ((color >> 0) & 0xFF) / 255.0f;
|
||||
const float g = ((color >> 8) & 0xFF) / 255.0f;
|
||||
const float b = ((color >> 16) & 0xFF) / 255.0f;
|
||||
const float radius = float (ref->base->data.radius);
|
||||
objects.insertLight (ptr, r, g, b, radius);
|
||||
}
|
||||
|
||||
const int color = ref->base->data.color;
|
||||
const float r = ((color >> 0) & 0xFF) / 255.0f;
|
||||
const float g = ((color >> 8) & 0xFF) / 255.0f;
|
||||
const float b = ((color >> 16) & 0xFF) / 255.0f;
|
||||
const float radius = float (ref->base->data.radius);
|
||||
objects.insertLight (ptr, r, g, b, radius);
|
||||
}
|
||||
|
||||
void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||
|
@ -43,13 +43,12 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Light>();
|
||||
|
||||
|
||||
const std::string &model = ref->base->model;
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
if(!model.empty()){
|
||||
physics.insertObjectPhysics(ptr, "meshes\\" + model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||
|
@ -87,12 +86,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Light::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.lights);
|
||||
}
|
||||
|
||||
std::string Light::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_LIGHT_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -28,10 +27,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -58,12 +58,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Lockpick::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.lockpicks);
|
||||
}
|
||||
|
||||
std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_LOCKPICK_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -57,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Miscellaneous::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.miscItems);
|
||||
}
|
||||
|
||||
std::string Miscellaneous::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_MISC_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -1,27 +1,88 @@
|
|||
|
||||
#include "npc.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
#include <OgreSceneNode.h>
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/customdata.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
const Ogre::Radian kOgrePi (Ogre::Math::PI);
|
||||
const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0));
|
||||
|
||||
struct CustomData : public MWWorld::CustomData
|
||||
{
|
||||
MWMechanics::NpcStats mNpcStats;
|
||||
MWMechanics::CreatureStats mCreatureStats;
|
||||
MWMechanics::Movement mMovement;
|
||||
MWWorld::ContainerStore mContainerStore;
|
||||
|
||||
virtual MWWorld::CustomData *clone() const;
|
||||
};
|
||||
|
||||
MWWorld::CustomData *CustomData::clone() const
|
||||
{
|
||||
return new CustomData (*this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
std::auto_ptr<CustomData> data (new CustomData);
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
// NPC stats
|
||||
if (!ref->base->faction.empty())
|
||||
{
|
||||
// TODO research how initial rank is stored. The information in loadnpc.hpp are at
|
||||
// best very unclear.
|
||||
data->mNpcStats.mFactionRank[ref->base->faction] = 0;
|
||||
}
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||
|
||||
// creature stats
|
||||
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
||||
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||
data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower);
|
||||
data->mCreatureStats.mAttributes[3].set (ref->base->npdt52.agility);
|
||||
data->mCreatureStats.mAttributes[4].set (ref->base->npdt52.speed);
|
||||
data->mCreatureStats.mAttributes[5].set (ref->base->npdt52.endurance);
|
||||
data->mCreatureStats.mAttributes[6].set (ref->base->npdt52.personality);
|
||||
data->mCreatureStats.mAttributes[7].set (ref->base->npdt52.luck);
|
||||
data->mCreatureStats.mDynamic[0].set (ref->base->npdt52.health);
|
||||
data->mCreatureStats.mDynamic[1].set (ref->base->npdt52.mana);
|
||||
data->mCreatureStats.mDynamic[2].set (ref->base->npdt52.fatigue);
|
||||
|
||||
data->mCreatureStats.mLevel = ref->base->npdt52.level;
|
||||
|
||||
// \todo add initial container content
|
||||
|
||||
// store
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
}
|
||||
|
||||
std::string Npc::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
|
@ -32,34 +93,28 @@ namespace MWClass
|
|||
|
||||
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
/*
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::NPC>();
|
||||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Npcs& npcs = renderingInterface.getNPCs();
|
||||
//npcs.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||
//npcs.insertMesh(ptr, "meshes\\" + model);
|
||||
}*/
|
||||
renderingInterface.getActors().insertNPC(ptr);
|
||||
}
|
||||
|
||||
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||
{
|
||||
|
||||
/*
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::NPC>();
|
||||
|
||||
|
||||
const std::string &model = ref->base->model;
|
||||
assert (ref->base != NULL);
|
||||
if(!model.empty()){
|
||||
physics.insertActorPhysics(ptr, "meshes\\" + model);
|
||||
}*/
|
||||
std::string headID = ref->base->head;
|
||||
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||
|
||||
|
||||
std::string smodel = "meshes\\base_anim.nif";
|
||||
if(beast)
|
||||
smodel = "meshes\\base_animkna.nif";
|
||||
physics.insertActorPhysics(ptr, smodel);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -83,56 +138,16 @@ namespace MWClass
|
|||
|
||||
MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCreatureStats().get())
|
||||
{
|
||||
boost::shared_ptr<MWMechanics::CreatureStats> stats (
|
||||
new MWMechanics::CreatureStats);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
stats->mAttributes[0].set (ref->base->npdt52.strength);
|
||||
stats->mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||
stats->mAttributes[2].set (ref->base->npdt52.willpower);
|
||||
stats->mAttributes[3].set (ref->base->npdt52.agility);
|
||||
stats->mAttributes[4].set (ref->base->npdt52.speed);
|
||||
stats->mAttributes[5].set (ref->base->npdt52.endurance);
|
||||
stats->mAttributes[6].set (ref->base->npdt52.personality);
|
||||
stats->mAttributes[7].set (ref->base->npdt52.luck);
|
||||
stats->mDynamic[0].set (ref->base->npdt52.health);
|
||||
stats->mDynamic[1].set (ref->base->npdt52.mana);
|
||||
stats->mDynamic[2].set (ref->base->npdt52.fatigue);
|
||||
|
||||
stats->mLevel = ref->base->npdt52.level;
|
||||
|
||||
ptr.getRefData().getCreatureStats() = stats;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getCreatureStats();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
|
||||
}
|
||||
|
||||
MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getNpcStats().get())
|
||||
{
|
||||
boost::shared_ptr<MWMechanics::NpcStats> stats (
|
||||
new MWMechanics::NpcStats);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
if (!ref->base->faction.empty())
|
||||
{
|
||||
// TODO research how initial rank is stored. The information in loadnpc.hpp are at
|
||||
// best very unclear.
|
||||
stats->mFactionRank[ref->base->faction] = 0;
|
||||
}
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
stats->mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||
|
||||
ptr.getRefData().getNpcStats() = stats;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getNpcStats();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr,
|
||||
|
@ -141,20 +156,12 @@ namespace MWClass
|
|||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
|
||||
}
|
||||
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& Npc::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr)
|
||||
const
|
||||
{
|
||||
if (!ptr.getRefData().getContainerStore().get())
|
||||
{
|
||||
boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
|
||||
new MWWorld::ContainerStore<MWWorld::RefData>);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
// TODO add initial content
|
||||
|
||||
ptr.getRefData().getContainerStore() = store;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getContainerStore();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
|
||||
}
|
||||
|
||||
std::string Npc::getScript (const MWWorld::Ptr& ptr) const
|
||||
|
@ -245,29 +252,20 @@ namespace MWClass
|
|||
|
||||
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getMovement().get())
|
||||
{
|
||||
boost::shared_ptr<MWMechanics::Movement> movement (
|
||||
new MWMechanics::Movement);
|
||||
ensureCustomData (ptr);
|
||||
|
||||
ptr.getRefData().getMovement() = movement;
|
||||
}
|
||||
|
||||
return *ptr.getRefData().getMovement();
|
||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mMovement;
|
||||
}
|
||||
|
||||
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
Ogre::Vector3 vector (0, 0, 0);
|
||||
|
||||
if (ptr.getRefData().getMovement().get())
|
||||
{
|
||||
vector.x = - ptr.getRefData().getMovement()->mLeftRight * 200;
|
||||
vector.y = ptr.getRefData().getMovement()->mForwardBackward * 200;
|
||||
vector.x = - getMovementSettings (ptr).mLeftRight * 200;
|
||||
vector.y = getMovementSettings (ptr).mForwardBackward * 200;
|
||||
|
||||
if (getStance (ptr, Run, false))
|
||||
vector *= 2;
|
||||
}
|
||||
if (getStance (ptr, Run, false))
|
||||
vector *= 2;
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#define GAME_MWCLASS_NPC_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/npcs.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
class Npc : public MWWorld::Class
|
||||
{
|
||||
void ensureCustomData (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
public:
|
||||
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
@ -34,8 +35,7 @@ namespace MWClass
|
|||
virtual MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const;
|
||||
///< Return NPC stats
|
||||
|
||||
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore (
|
||||
const MWWorld::Ptr& ptr) const;
|
||||
virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
|
||||
///< Return container store
|
||||
|
||||
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -58,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Potion::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.potions);
|
||||
}
|
||||
|
||||
std::string Potion::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_POTION_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -58,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Probe::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.probes);
|
||||
}
|
||||
|
||||
std::string Probe::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
class Probe : public MWWorld::Class
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -57,12 +57,6 @@ namespace MWClass
|
|||
new MWWorld::ActionTake (ptr));
|
||||
}
|
||||
|
||||
void Repair::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.repairs);
|
||||
}
|
||||
|
||||
std::string Repair::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_REPAIR_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -23,10 +22,6 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -15,11 +16,11 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), true);
|
||||
objects.insertMesh(ptr, "meshes\\" + model);
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +30,12 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Static>();
|
||||
|
||||
|
||||
const std::string &model = ref->base->model;
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
if(!model.empty()){
|
||||
physics.insertObjectPhysics(ptr, "meshes\\" + model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string Static::getName (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_STATIC_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
|
||||
#include "containerutil.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -20,7 +19,7 @@ namespace MWClass
|
|||
|
||||
assert (ref->base != NULL);
|
||||
const std::string &model = ref->base->model;
|
||||
|
||||
|
||||
if (!model.empty())
|
||||
{
|
||||
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||
|
@ -71,12 +70,6 @@ namespace MWClass
|
|||
return ref->base->data.health;
|
||||
}
|
||||
|
||||
void Weapon::insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const
|
||||
{
|
||||
insertIntoContainerStore (ptr, containerStore.weapons);
|
||||
}
|
||||
|
||||
std::string Weapon::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define GAME_MWCLASS_WEAPON_H
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwrender/objects.hpp"
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
|
@ -29,10 +28,6 @@ namespace MWClass
|
|||
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
|
||||
///< Return item max health or throw an exception, if class does not have item health
|
||||
|
||||
virtual void insertIntoContainer (const MWWorld::Ptr& ptr,
|
||||
MWWorld::ContainerStore<MWWorld::RefData>& containerStore) const;
|
||||
///< Insert into a containe
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace MWDialogue
|
|||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->data.disposition==index) /// \todo cleanup info structure
|
||||
{
|
||||
iter->id;
|
||||
return iter->id;
|
||||
}
|
||||
|
||||
throw std::runtime_error ("unknown journal index for topic " + topic);
|
||||
|
|
629
apps/openmw/mwgui/charactercreation.cpp
Normal file
629
apps/openmw/mwgui/charactercreation.cpp
Normal file
|
@ -0,0 +1,629 @@
|
|||
#include "charactercreation.hpp"
|
||||
|
||||
#include "text_input.hpp"
|
||||
#include "race.hpp"
|
||||
#include "class.hpp"
|
||||
#include "birth.hpp"
|
||||
#include "review.hpp"
|
||||
#include "dialogue.hpp"
|
||||
#include "mode.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Step
|
||||
{
|
||||
const char* mText;
|
||||
const char* mButtons[3];
|
||||
ESM::Class::Specialization mSpecializations[3]; // The specialization for each answer
|
||||
};
|
||||
|
||||
static boost::array<Step, 10> sGenerateClassSteps = { {
|
||||
// Question 1
|
||||
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
|
||||
{"Draw your dagger, mercifully endings its life with a single thrust.",
|
||||
"Use herbs from your pack to put it to sleep.",
|
||||
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 2
|
||||
{"One Summer afternoon your father gives you a choice of chores.",
|
||||
{"Work in the forge with him casting iron for a new plow.",
|
||||
"Gather herbs for your mother who is preparing dinner.",
|
||||
"Go catch fish at the stream using a net and line."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 3
|
||||
{"Your cousin has given you a very embarrassing nickname and, even worse, likes to call you it in front of your friends. You asked him to stop, but he finds it very amusing to watch you blush.",
|
||||
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
|
||||
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
|
||||
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 4
|
||||
{"There is a lot of heated discussion at the local tavern over a grouped of people called 'Telepaths'. They have been hired by certain City-State kings. Rumor has it these Telepaths read a person's mind and tell their lord whether a follower is telling the truth or not.",
|
||||
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
|
||||
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
|
||||
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 5
|
||||
{"Your mother sends you to the market with a list of goods to buy. After you finish you find that by mistake a shopkeeper has given you too much money back in exchange for one of the items.",
|
||||
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
|
||||
"Decide to put the extra money to good use and purchase items that would help your family?",
|
||||
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 6
|
||||
{"While in the market place you witness a thief cut a purse from a noble. Even as he does so, the noble notices and calls for the city guards. In his haste to get away, the thief drops the purse near you. Surprisingly no one seems to notice the bag of coins at your feet.",
|
||||
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
|
||||
"Leave the bag there, knowing that it is better not to get involved.",
|
||||
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 7
|
||||
{"Your father sends you on a task which you loathe, cleaning the stables. On the way there, pitchfork in hand, you run into your friend from the homestead near your own. He offers to do it for you, in return for a future favor of his choosing.",
|
||||
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
|
||||
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
|
||||
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 8
|
||||
{"Your mother asks you to help fix the stove. While you are working, a very hot pipe slips its mooring and falls towards her.",
|
||||
{"Position yourself between the pipe and your mother.",
|
||||
"Grab the hot pipe and try to push it away.",
|
||||
"Push your mother out of the way."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 9
|
||||
{"While in town the baker gives you a sweetroll. Delighted, you take it into an alley to enjoy only to be intercepted by a gang of three other kids your age. The leader demands the sweetroll, or else he and his friends will beat you and take it.",
|
||||
{"Drop the sweetroll and step on it, then get ready for the fight.",
|
||||
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
|
||||
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 10
|
||||
{"Entering town you find that you are witness to a very well-dressed man running from a crowd. He screams to you for help. The crowd behind him seem very angry.",
|
||||
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
|
||||
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
|
||||
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
}
|
||||
} };
|
||||
}
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
CharacterCreation::CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment)
|
||||
: mNameDialog(0)
|
||||
, mRaceDialog(0)
|
||||
, mDialogueWindow(0)
|
||||
, mClassChoiceDialog(0)
|
||||
, mGenerateClassQuestionDialog(0)
|
||||
, mGenerateClassResultDialog(0)
|
||||
, mPickClassDialog(0)
|
||||
, mCreateClassDialog(0)
|
||||
, mBirthSignDialog(0)
|
||||
, mReviewDialog(0)
|
||||
, mWM(_wm)
|
||||
, mEnvironment(_environment)
|
||||
{
|
||||
mCreationStage = CSE_NotStarted;
|
||||
}
|
||||
|
||||
void CharacterCreation::spawnDialog(const char id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case GM_Name:
|
||||
if(mNameDialog)
|
||||
mWM->removeDialog(mNameDialog);
|
||||
mNameDialog = new TextInputDialog(*mWM);
|
||||
mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name"));
|
||||
mNameDialog->setTextInput(mPlayerName);
|
||||
mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
|
||||
mNameDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
|
||||
mNameDialog->open();
|
||||
break;
|
||||
|
||||
case GM_Race:
|
||||
if (mRaceDialog)
|
||||
mWM->removeDialog(mRaceDialog);
|
||||
mRaceDialog = new RaceDialog(*mWM);
|
||||
mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
|
||||
mRaceDialog->setRaceId(mPlayerRaceId);
|
||||
mRaceDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
|
||||
mRaceDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
|
||||
mRaceDialog->open();
|
||||
break;
|
||||
|
||||
case GM_Class:
|
||||
if (mClassChoiceDialog)
|
||||
mWM->removeDialog(mClassChoiceDialog);
|
||||
mClassChoiceDialog = new ClassChoiceDialog(*mWM);
|
||||
mClassChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
|
||||
mClassChoiceDialog->open();
|
||||
break;
|
||||
|
||||
case GM_ClassPick:
|
||||
if (mPickClassDialog)
|
||||
mWM->removeDialog(mPickClassDialog);
|
||||
mPickClassDialog = new PickClassDialog(*mWM);
|
||||
mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
||||
mPickClassDialog->setClassId(mPlayerClass.name);
|
||||
mPickClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
|
||||
mPickClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
|
||||
mPickClassDialog->open();
|
||||
break;
|
||||
|
||||
case GM_Birth:
|
||||
if (mBirthSignDialog)
|
||||
mWM->removeDialog(mBirthSignDialog);
|
||||
mBirthSignDialog = new BirthDialog(*mWM);
|
||||
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
|
||||
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
|
||||
mBirthSignDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
|
||||
mBirthSignDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
|
||||
mBirthSignDialog->open();
|
||||
break;
|
||||
|
||||
case GM_ClassCreate:
|
||||
if (mCreateClassDialog)
|
||||
mWM->removeDialog(mCreateClassDialog);
|
||||
mCreateClassDialog = new CreateClassDialog(*mWM);
|
||||
mCreateClassDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||
mCreateClassDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||
mCreateClassDialog->open();
|
||||
break;
|
||||
case GM_ClassGenerate:
|
||||
mGenerateClassStep = 0;
|
||||
mGenerateClass = "";
|
||||
mGenerateClassSpecializations[0] = 0;
|
||||
mGenerateClassSpecializations[1] = 0;
|
||||
mGenerateClassSpecializations[2] = 0;
|
||||
showClassQuestionDialog();
|
||||
break;
|
||||
case GM_Review:
|
||||
if (mReviewDialog)
|
||||
mWM->removeDialog(mReviewDialog);
|
||||
mReviewDialog = new ReviewDialog(*mWM);
|
||||
mReviewDialog->setPlayerName(mPlayerName);
|
||||
mReviewDialog->setRace(mPlayerRaceId);
|
||||
mReviewDialog->setClass(mPlayerClass);
|
||||
mReviewDialog->setBirthSign(mPlayerBirthSignId);
|
||||
|
||||
mReviewDialog->setHealth(mPlayerHealth);
|
||||
mReviewDialog->setMagicka(mPlayerMagicka);
|
||||
mReviewDialog->setFatigue(mPlayerFatigue);
|
||||
|
||||
{
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator end = mPlayerAttributes.end();
|
||||
for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = mPlayerAttributes.begin(); it != end; ++it)
|
||||
{
|
||||
mReviewDialog->setAttribute(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator end = mPlayerSkillValues.end();
|
||||
for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = mPlayerSkillValues.begin(); it != end; ++it)
|
||||
{
|
||||
mReviewDialog->setSkillValue(it->first, it->second);
|
||||
}
|
||||
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
|
||||
}
|
||||
|
||||
mReviewDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
|
||||
mReviewDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
||||
mReviewDialog->eventActivateDialog = MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
|
||||
mReviewDialog->open();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<int>& value)
|
||||
{
|
||||
mPlayerHealth = value;
|
||||
}
|
||||
|
||||
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<int>& value)
|
||||
{
|
||||
mPlayerMagicka = value;
|
||||
}
|
||||
|
||||
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<int>& value)
|
||||
{
|
||||
mPlayerFatigue = value;
|
||||
}
|
||||
|
||||
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
mWM->removeDialog(mReviewDialog);
|
||||
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
|
||||
void CharacterCreation::onReviewDialogBack()
|
||||
{
|
||||
if (mReviewDialog)
|
||||
mWM->removeDialog(mReviewDialog);
|
||||
|
||||
mWM->setGuiMode(GM_Birth);
|
||||
}
|
||||
|
||||
void CharacterCreation::onReviewActivateDialog(int parDialog)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
mWM->removeDialog(mReviewDialog);
|
||||
mCreationStage = CSE_ReviewNext;
|
||||
|
||||
switch(parDialog)
|
||||
{
|
||||
case ReviewDialog::NAME_DIALOG:
|
||||
mWM->setGuiMode(GM_Name);
|
||||
break;
|
||||
case ReviewDialog::RACE_DIALOG:
|
||||
mWM->setGuiMode(GM_Race);
|
||||
break;
|
||||
case ReviewDialog::CLASS_DIALOG:
|
||||
mWM->setGuiMode(GM_Class);
|
||||
break;
|
||||
case ReviewDialog::BIRTHSIGN_DIALOG:
|
||||
mWM->setGuiMode(GM_Birth);
|
||||
};
|
||||
}
|
||||
|
||||
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mPickClassDialog)
|
||||
{
|
||||
const std::string &classId = mPickClassDialog->getClassId();
|
||||
if (!classId.empty())
|
||||
mEnvironment->mMechanicsManager->setPlayerClass(classId);
|
||||
const ESM::Class *klass = mEnvironment->mWorld->getStore().classes.find(classId);
|
||||
if (klass)
|
||||
{
|
||||
mPlayerClass = *klass;
|
||||
mWM->setPlayerClass(mPlayerClass);
|
||||
}
|
||||
mWM->removeDialog(mPickClassDialog);
|
||||
}
|
||||
|
||||
//TODO This bit gets repeated a few times; wrap it in a function
|
||||
if (mCreationStage == CSE_ReviewNext)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else if (mCreationStage >= CSE_ClassChosen)
|
||||
mWM->setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_ClassChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::onPickClassDialogBack()
|
||||
{
|
||||
if (mPickClassDialog)
|
||||
{
|
||||
const std::string classId = mPickClassDialog->getClassId();
|
||||
if (!classId.empty())
|
||||
mEnvironment->mMechanicsManager->setPlayerClass(classId);
|
||||
mWM->removeDialog(mPickClassDialog);
|
||||
}
|
||||
|
||||
mWM->setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onClassChoice(int _index)
|
||||
{
|
||||
if (mClassChoiceDialog)
|
||||
{
|
||||
mWM->removeDialog(mClassChoiceDialog);
|
||||
}
|
||||
|
||||
switch(_index)
|
||||
{
|
||||
case ClassChoiceDialog::Class_Generate:
|
||||
mWM->setGuiMode(GM_ClassGenerate);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Pick:
|
||||
mWM->setGuiMode(GM_ClassPick);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Create:
|
||||
mWM->setGuiMode(GM_ClassCreate);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Back:
|
||||
mWM->setGuiMode(GM_Race);
|
||||
break;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mNameDialog)
|
||||
{
|
||||
mPlayerName = mNameDialog->getTextInput();
|
||||
mWM->setValue("name", mPlayerName);
|
||||
mEnvironment->mMechanicsManager->setPlayerName(mPlayerName);
|
||||
mWM->removeDialog(mNameDialog);
|
||||
}
|
||||
|
||||
if (mCreationStage == CSE_ReviewNext)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else if (mCreationStage >= CSE_NameChosen)
|
||||
mWM->setGuiMode(GM_Race);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_NameChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogBack()
|
||||
{
|
||||
if (mRaceDialog)
|
||||
{
|
||||
mPlayerRaceId = mRaceDialog->getRaceId();
|
||||
if (!mPlayerRaceId.empty())
|
||||
mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male);
|
||||
mWM->removeDialog(mRaceDialog);
|
||||
}
|
||||
|
||||
mWM->setGuiMode(GM_Name);
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mRaceDialog)
|
||||
{
|
||||
mPlayerRaceId = mRaceDialog->getRaceId();
|
||||
mWM->setValue("race", mPlayerRaceId);
|
||||
if (!mPlayerRaceId.empty())
|
||||
mEnvironment->mMechanicsManager->setPlayerRace(mPlayerRaceId, mRaceDialog->getGender() == RaceDialog::GM_Male);
|
||||
mWM->removeDialog(mRaceDialog);
|
||||
}
|
||||
|
||||
if (mCreationStage == CSE_ReviewNext)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else if(mCreationStage >= CSE_RaceChosen)
|
||||
mWM->setGuiMode(GM_Class);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_RaceChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mBirthSignDialog)
|
||||
{
|
||||
mPlayerBirthSignId = mBirthSignDialog->getBirthId();
|
||||
mWM->setBirthSign(mPlayerBirthSignId);
|
||||
if (!mPlayerBirthSignId.empty())
|
||||
mEnvironment->mMechanicsManager->setPlayerBirthsign(mPlayerBirthSignId);
|
||||
mWM->removeDialog(mBirthSignDialog);
|
||||
}
|
||||
|
||||
if (mCreationStage >= CSE_BirthSignChosen)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_BirthSignChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::onBirthSignDialogBack()
|
||||
{
|
||||
if (mBirthSignDialog)
|
||||
{
|
||||
mEnvironment->mMechanicsManager->setPlayerBirthsign(mBirthSignDialog->getBirthId());
|
||||
mWM->removeDialog(mBirthSignDialog);
|
||||
}
|
||||
|
||||
mWM->setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mCreateClassDialog)
|
||||
{
|
||||
ESM::Class klass;
|
||||
klass.name = mCreateClassDialog->getName();
|
||||
klass.description = mCreateClassDialog->getDescription();
|
||||
klass.data.specialization = mCreateClassDialog->getSpecializationId();
|
||||
klass.data.isPlayable = 0x1;
|
||||
|
||||
std::vector<int> attributes = mCreateClassDialog->getFavoriteAttributes();
|
||||
assert(attributes.size() == 2);
|
||||
klass.data.attribute[0] = attributes[0];
|
||||
klass.data.attribute[1] = attributes[1];
|
||||
|
||||
std::vector<ESM::Skill::SkillEnum> majorSkills = mCreateClassDialog->getMajorSkills();
|
||||
std::vector<ESM::Skill::SkillEnum> minorSkills = mCreateClassDialog->getMinorSkills();
|
||||
assert(majorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
|
||||
assert(minorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
|
||||
for (size_t i = 0; i < sizeof(klass.data.skills)/sizeof(klass.data.skills[0]); ++i)
|
||||
{
|
||||
klass.data.skills[i][1] = majorSkills[i];
|
||||
klass.data.skills[i][0] = minorSkills[i];
|
||||
}
|
||||
mEnvironment->mMechanicsManager->setPlayerClass(klass);
|
||||
mPlayerClass = klass;
|
||||
mWM->setPlayerClass(klass);
|
||||
|
||||
mWM->removeDialog(mCreateClassDialog);
|
||||
}
|
||||
|
||||
if (mCreationStage == CSE_ReviewNext)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else if (mCreationStage >= CSE_ClassChosen)
|
||||
mWM->setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_ClassChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::onCreateClassDialogBack()
|
||||
{
|
||||
if (mCreateClassDialog)
|
||||
mWM->removeDialog(mCreateClassDialog);
|
||||
|
||||
mWM->setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onClassQuestionChosen(int _index)
|
||||
{
|
||||
if (mGenerateClassQuestionDialog)
|
||||
mWM->removeDialog(mGenerateClassQuestionDialog);
|
||||
if (_index < 0 || _index >= 3)
|
||||
{
|
||||
mWM->setGuiMode(GM_Class);
|
||||
return;
|
||||
}
|
||||
|
||||
ESM::Class::Specialization specialization = sGenerateClassSteps[mGenerateClassStep].mSpecializations[_index];
|
||||
if (specialization == ESM::Class::Stealth)
|
||||
++mGenerateClassSpecializations[0];
|
||||
else if (specialization == ESM::Class::Combat)
|
||||
++mGenerateClassSpecializations[1];
|
||||
else if (specialization == ESM::Class::Magic)
|
||||
++mGenerateClassSpecializations[2];
|
||||
++mGenerateClassStep;
|
||||
showClassQuestionDialog();
|
||||
}
|
||||
|
||||
void CharacterCreation::showClassQuestionDialog()
|
||||
{
|
||||
if (mGenerateClassStep == sGenerateClassSteps.size())
|
||||
{
|
||||
static boost::array<ClassPoint, 23> classes = { {
|
||||
{"Acrobat", {6, 2, 2}},
|
||||
{"Agent", {6, 1, 3}},
|
||||
{"Archer", {3, 5, 2}},
|
||||
{"Archer", {5, 5, 0}},
|
||||
{"Assassin", {6, 3, 1}},
|
||||
{"Barbarian", {3, 6, 1}},
|
||||
{"Bard", {3, 3, 3}},
|
||||
{"Battlemage", {1, 3, 6}},
|
||||
{"Crusader", {1, 6, 3}},
|
||||
{"Healer", {3, 1, 6}},
|
||||
{"Knight", {2, 6, 2}},
|
||||
{"Monk", {5, 3, 2}},
|
||||
{"Nightblade", {4, 2, 4}},
|
||||
{"Pilgrim", {5, 2, 3}},
|
||||
{"Rogue", {3, 4, 3}},
|
||||
{"Rogue", {4, 4, 2}},
|
||||
{"Rogue", {5, 4, 1}},
|
||||
{"Scout", {2, 5, 3}},
|
||||
{"Sorcerer", {2, 2, 6}},
|
||||
{"Spellsword", {2, 4, 4}},
|
||||
{"Spellsword", {5, 1, 4}},
|
||||
{"Witchhunter", {2, 3, 5}},
|
||||
{"Witchhunter", {5, 0, 5}}
|
||||
} };
|
||||
|
||||
int match = -1;
|
||||
for (unsigned i = 0; i < classes.size(); ++i)
|
||||
{
|
||||
if (mGenerateClassSpecializations[0] == classes[i].points[0] &&
|
||||
mGenerateClassSpecializations[1] == classes[i].points[1] &&
|
||||
mGenerateClassSpecializations[2] == classes[i].points[2])
|
||||
{
|
||||
match = i;
|
||||
mGenerateClass = classes[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match == -1)
|
||||
{
|
||||
if (mGenerateClassSpecializations[0] >= 7)
|
||||
mGenerateClass = "Thief";
|
||||
else if (mGenerateClassSpecializations[1] >= 7)
|
||||
mGenerateClass = "Warrior";
|
||||
else if (mGenerateClassSpecializations[2] >= 7)
|
||||
mGenerateClass = "Mage";
|
||||
else
|
||||
{
|
||||
std::cerr << "Failed to deduce class from chosen answers in generate class dialog" << std::endl;
|
||||
mGenerateClass = "Thief";
|
||||
}
|
||||
}
|
||||
|
||||
if (mGenerateClassResultDialog)
|
||||
mWM->removeDialog(mGenerateClassResultDialog);
|
||||
mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM);
|
||||
mGenerateClassResultDialog->setClassId(mGenerateClass);
|
||||
mGenerateClassResultDialog->eventBack = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack);
|
||||
mGenerateClassResultDialog->eventDone = MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone);
|
||||
mGenerateClassResultDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGenerateClassStep > sGenerateClassSteps.size())
|
||||
{
|
||||
mWM->setGuiMode(GM_Class);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGenerateClassQuestionDialog)
|
||||
mWM->removeDialog(mGenerateClassQuestionDialog);
|
||||
mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM);
|
||||
|
||||
InfoBoxDialog::ButtonList buttons;
|
||||
mGenerateClassQuestionDialog->setText(sGenerateClassSteps[mGenerateClassStep].mText);
|
||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[0]);
|
||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[1]);
|
||||
buttons.push_back(sGenerateClassSteps[mGenerateClassStep].mButtons[2]);
|
||||
mGenerateClassQuestionDialog->setButtons(buttons);
|
||||
mGenerateClassQuestionDialog->eventButtonSelected = MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
||||
mGenerateClassQuestionDialog->open();
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassBack()
|
||||
{
|
||||
if(mCreationStage < CSE_ClassChosen)
|
||||
mCreationStage = CSE_ClassChosen;
|
||||
|
||||
if (mGenerateClassResultDialog)
|
||||
mWM->removeDialog(mGenerateClassResultDialog);
|
||||
mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass);
|
||||
|
||||
mWM->setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
|
||||
{
|
||||
if (mGenerateClassResultDialog)
|
||||
mWM->removeDialog(mGenerateClassResultDialog);
|
||||
mEnvironment->mMechanicsManager->setPlayerClass(mGenerateClass);
|
||||
|
||||
if (mCreationStage == CSE_ReviewNext)
|
||||
mWM->setGuiMode(GM_Review);
|
||||
else if (mCreationStage >= CSE_ClassChosen)
|
||||
mWM->setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
mCreationStage = CSE_ClassChosen;
|
||||
mWM->setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
CharacterCreation::~CharacterCreation()
|
||||
{
|
||||
delete mNameDialog;
|
||||
delete mRaceDialog;
|
||||
delete mDialogueWindow;
|
||||
delete mClassChoiceDialog;
|
||||
delete mGenerateClassQuestionDialog;
|
||||
delete mGenerateClassResultDialog;
|
||||
delete mPickClassDialog;
|
||||
delete mCreateClassDialog;
|
||||
delete mBirthSignDialog;
|
||||
delete mReviewDialog;
|
||||
}
|
120
apps/openmw/mwgui/charactercreation.hpp
Normal file
120
apps/openmw/mwgui/charactercreation.hpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#ifndef CHARACTER_CREATION_HPP
|
||||
#define CHARACTER_CREATION_HPP
|
||||
|
||||
#include "window_manager.hpp"
|
||||
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include <components/esm_store/store.hpp>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowManager;
|
||||
class WindowBase;
|
||||
|
||||
class TextInputDialog;
|
||||
class InfoBoxDialog;
|
||||
class RaceDialog;
|
||||
class DialogueWindow;
|
||||
class ClassChoiceDialog;
|
||||
class GenerateClassResultDialog;
|
||||
class PickClassDialog;
|
||||
class CreateClassDialog;
|
||||
class BirthDialog;
|
||||
class ReviewDialog;
|
||||
class MessageBoxManager;
|
||||
|
||||
class CharacterCreation
|
||||
{
|
||||
public:
|
||||
typedef std::vector<int> SkillList;
|
||||
|
||||
CharacterCreation(WindowManager* _wm, MWWorld::Environment* _environment);
|
||||
~CharacterCreation();
|
||||
|
||||
//Show a dialog
|
||||
void spawnDialog(const char id);
|
||||
|
||||
void setPlayerHealth (const MWMechanics::DynamicStat<int>& value);
|
||||
|
||||
void setPlayerMagicka (const MWMechanics::DynamicStat<int>& value);
|
||||
|
||||
void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value);
|
||||
|
||||
private:
|
||||
//Dialogs
|
||||
TextInputDialog* mNameDialog;
|
||||
RaceDialog* mRaceDialog;
|
||||
DialogueWindow* mDialogueWindow;
|
||||
ClassChoiceDialog* mClassChoiceDialog;
|
||||
InfoBoxDialog* mGenerateClassQuestionDialog;
|
||||
GenerateClassResultDialog* mGenerateClassResultDialog;
|
||||
PickClassDialog* mPickClassDialog;
|
||||
CreateClassDialog* mCreateClassDialog;
|
||||
BirthDialog* mBirthSignDialog;
|
||||
ReviewDialog* mReviewDialog;
|
||||
|
||||
WindowManager* mWM;
|
||||
MWWorld::Environment* mEnvironment;
|
||||
|
||||
//Player data
|
||||
std::string mPlayerName;
|
||||
std::string mPlayerRaceId;
|
||||
std::string mPlayerBirthSignId;
|
||||
ESM::Class mPlayerClass;
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > mPlayerAttributes;
|
||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > mPlayerSkillValues;
|
||||
MWMechanics::DynamicStat<int> mPlayerHealth;
|
||||
MWMechanics::DynamicStat<int> mPlayerMagicka;
|
||||
MWMechanics::DynamicStat<int> mPlayerFatigue;
|
||||
|
||||
//Class generation vars
|
||||
unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog
|
||||
unsigned mGenerateClassSpecializations[3]; // A counter for each specialization which is increased when an answer is chosen
|
||||
std::string mGenerateClass; // In order: Stealth, Combat, Magic
|
||||
|
||||
////Dialog events
|
||||
//Name dialog
|
||||
void onNameDialogDone(WindowBase* parWindow);
|
||||
|
||||
//Race dialog
|
||||
void onRaceDialogDone(WindowBase* parWindow);
|
||||
void onRaceDialogBack();
|
||||
|
||||
//Class dialogs
|
||||
void onClassChoice(int _index);
|
||||
void onPickClassDialogDone(WindowBase* parWindow);
|
||||
void onPickClassDialogBack();
|
||||
void onCreateClassDialogDone(WindowBase* parWindow);
|
||||
void onCreateClassDialogBack();
|
||||
void showClassQuestionDialog();
|
||||
void onClassQuestionChosen(int _index);
|
||||
void onGenerateClassBack();
|
||||
void onGenerateClassDone(WindowBase* parWindow);
|
||||
|
||||
//Birthsign dialog
|
||||
void onBirthSignDialogDone(WindowBase* parWindow);
|
||||
void onBirthSignDialogBack();
|
||||
|
||||
//Review dialog
|
||||
void onReviewDialogDone(WindowBase* parWindow);
|
||||
void onReviewDialogBack();
|
||||
void onReviewActivateDialog(int parDialog);
|
||||
|
||||
enum CSE //Creation Stage Enum
|
||||
{
|
||||
CSE_NotStarted,
|
||||
CSE_NameChosen,
|
||||
CSE_RaceChosen,
|
||||
CSE_ClassChosen,
|
||||
CSE_BirthSignChosen,
|
||||
CSE_ReviewNext
|
||||
};
|
||||
|
||||
CSE mCreationStage; // Which state the character creating is in, controls back/next/ok buttons
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
193
apps/openmw/mwgui/journalwindow.cpp
Normal file
193
apps/openmw/mwgui/journalwindow.cpp
Normal file
|
@ -0,0 +1,193 @@
|
|||
#include "journalwindow.hpp"
|
||||
#include "window_manager.hpp"
|
||||
#include "../mwdialogue/journal.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct book
|
||||
{
|
||||
int endLine;
|
||||
std::list<std::string> pages;
|
||||
};
|
||||
}
|
||||
|
||||
book formatText(std::string text,book mBook,int maxLine, int lineSize)
|
||||
{
|
||||
//stringList.push_back("");
|
||||
|
||||
int cLineSize = 0;
|
||||
int cLine = mBook.endLine +1;
|
||||
std::string cString;
|
||||
|
||||
if(mBook.pages.empty())
|
||||
{
|
||||
cString = "";
|
||||
cLine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cString = mBook.pages.back() + std::string("\n");
|
||||
mBook.pages.pop_back();
|
||||
}
|
||||
|
||||
//std::string::iterator wordBegin = text.begin();
|
||||
//std::string::iterator wordEnd;
|
||||
|
||||
std::string cText = text;
|
||||
|
||||
while(cText.length() != 0)
|
||||
{
|
||||
size_t firstSpace = cText.find_first_of(' ');
|
||||
if(firstSpace == std::string::npos)
|
||||
{
|
||||
cString = cString + cText;
|
||||
mBook.pages.push_back(cString);
|
||||
//TODO:finnish this
|
||||
break;
|
||||
}
|
||||
if(static_cast<int> (firstSpace) + cLineSize <= lineSize)
|
||||
{
|
||||
cLineSize = firstSpace + cLineSize;
|
||||
cString = cString + cText.substr(0,firstSpace +1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLineSize = firstSpace;
|
||||
if(cLine +1 <= maxLine)
|
||||
{
|
||||
cLine = cLine + 1;
|
||||
cString = cString + std::string("\n") + cText.substr(0,firstSpace +1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLine = 0;
|
||||
mBook.pages.push_back(cString);
|
||||
cString = cText.substr(0,firstSpace +1);
|
||||
}
|
||||
}
|
||||
//std::cout << cText << "\n";
|
||||
//std::cout << cText.length();
|
||||
cText = cText.substr(firstSpace +1,cText.length() - firstSpace -1);
|
||||
}
|
||||
mBook.endLine = cLine;
|
||||
return mBook;
|
||||
//std::string
|
||||
}
|
||||
|
||||
|
||||
MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager)
|
||||
: WindowBase("openmw_journal_layout.xml", parWindowManager)
|
||||
, lastPos(0)
|
||||
{
|
||||
//setCoord(0,0,498, 342);
|
||||
center();
|
||||
|
||||
getWidget(mLeftTextWidget, "LeftText");
|
||||
getWidget(mRightTextWidget, "RightText");
|
||||
getWidget(mPrevBtn, "PrevPageBTN");
|
||||
mPrevBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyPrevPage);
|
||||
getWidget(mNextBtn, "NextPageBTN");
|
||||
mNextBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyNextPage);
|
||||
//MyGUI::ItemBox* list = new MyGUI::ItemBox();
|
||||
//list->addItem("qaq","aqzazaz");
|
||||
//mScrollerWidget->addChildItem(list);
|
||||
//mScrollerWidget->addItem("dserzt",MyGUI::UString("fedgdfg"));
|
||||
//mEditWidget->addText("ljblsxdvdsfvgedfvdfvdkjfghldfjgn sdv,nhsxl;vvn lklksbvlksb lbsdflkbdSLKJGBLskdhbvl<kbvlqksbgkqsjhdvb");
|
||||
//mEditWidget->show();
|
||||
//mEditWidget->setEditStatic(true);
|
||||
mLeftTextWidget->addText("left texxxt ");
|
||||
mLeftTextWidget->setEditReadOnly(true);
|
||||
mRightTextWidget->setEditReadOnly(true);
|
||||
mRightTextWidget->setEditStatic(true);
|
||||
mLeftTextWidget->setEditStatic(true);
|
||||
mRightTextWidget->addText("Right texxt ");
|
||||
|
||||
//std::list<std::string> list = formatText("OpenMW rgh dsfg sqef srg ZT uzql n ZLIEHRF LQSJH GLOIjf qjfmj hslkdgn jlkdjhg qlr isgli shli uhs fiuh qksf cg ksjnf lkqsnbf ksbf sbfkl zbf kuyzflkj sbgdfkj zlfh ozhjfmo hzmfh lizuf rty qzt ezy tkyEZT RYYJ DG fgh is an open-source implementation of the game engine found in the game Morrowind. This is a dumb test text msodjbg smojg smoig fiiinnn");
|
||||
//std::list<std::string> list = formatText();
|
||||
//displayLeftText(list.front());
|
||||
|
||||
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
||||
t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize);
|
||||
}
|
||||
|
||||
void MWGui::JournalWindow::open()
|
||||
{
|
||||
mPageNumber = 0;
|
||||
if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end())
|
||||
{
|
||||
book journal;
|
||||
journal.endLine = 0;
|
||||
|
||||
for(std::deque<MWDialogue::StampedJournalEntry>::const_iterator it = mWindowManager.getEnvironment().mJournal->begin();it!=mWindowManager.getEnvironment().mJournal->end();it++)
|
||||
{
|
||||
std::string a = it->getText(mWindowManager.getEnvironment().mWorld->getStore());
|
||||
journal = formatText(a,journal,10,17);
|
||||
journal.endLine = journal.endLine +1;
|
||||
journal.pages.back() = journal.pages.back() + std::string("\n");
|
||||
}
|
||||
//std::string a = mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore());
|
||||
//std::list<std::string> journal = formatText(a,10,20,1);
|
||||
bool left = true;
|
||||
for(std::list<std::string>::iterator it = journal.pages.begin(); it != journal.pages.end();it++)
|
||||
{
|
||||
if(left)
|
||||
{
|
||||
leftPages.push_back(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
rightPages.push_back(*it);
|
||||
}
|
||||
left = !left;
|
||||
}
|
||||
if(!left) rightPages.push_back("");
|
||||
|
||||
mPageNumber = leftPages.size()-1;
|
||||
displayLeftText(leftPages[mPageNumber]);
|
||||
displayRightText(rightPages[mPageNumber]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout << mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore());
|
||||
}
|
||||
}
|
||||
|
||||
void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window)
|
||||
{
|
||||
}
|
||||
|
||||
void MWGui::JournalWindow::displayLeftText(std::string text)
|
||||
{
|
||||
mLeftTextWidget->eraseText(0,mLeftTextWidget->getTextLength());
|
||||
mLeftTextWidget->addText(text);
|
||||
}
|
||||
|
||||
void MWGui::JournalWindow::displayRightText(std::string text)
|
||||
{
|
||||
mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength());
|
||||
mRightTextWidget->addText(text);
|
||||
}
|
||||
|
||||
|
||||
void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender)
|
||||
{
|
||||
if(mPageNumber < int(leftPages.size())-1)
|
||||
{
|
||||
mPageNumber = mPageNumber + 1;
|
||||
displayLeftText(leftPages[mPageNumber]);
|
||||
displayRightText(rightPages[mPageNumber]);
|
||||
}
|
||||
}
|
||||
|
||||
void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender)
|
||||
{
|
||||
if(mPageNumber > 0)
|
||||
{
|
||||
mPageNumber = mPageNumber - 1;
|
||||
displayLeftText(leftPages[mPageNumber]);
|
||||
displayRightText(rightPages[mPageNumber]);
|
||||
}
|
||||
}
|
57
apps/openmw/mwgui/journalwindow.hpp
Normal file
57
apps/openmw/mwgui/journalwindow.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef MWGUI_JOURNAL_H
|
||||
#define MWGUI_JOURNAL_H
|
||||
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowManager;
|
||||
|
||||
class JournalWindow : public WindowBase
|
||||
{
|
||||
public:
|
||||
JournalWindow(WindowManager& parWindowManager);
|
||||
void open();
|
||||
|
||||
private:
|
||||
enum ColorStyle
|
||||
{
|
||||
CS_Sub,
|
||||
CS_Normal,
|
||||
CS_Super
|
||||
};
|
||||
|
||||
void onWindowResize(MyGUI::Window* window);
|
||||
|
||||
void displayLeftText(std::string text);
|
||||
void displayRightText(std::string text);
|
||||
|
||||
|
||||
/**
|
||||
*Called when next/prev button is used.
|
||||
*/
|
||||
void notifyNextPage(MyGUI::WidgetPtr _sender);
|
||||
void notifyPrevPage(MyGUI::WidgetPtr _sender);
|
||||
|
||||
static const int lineHeight;
|
||||
|
||||
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
|
||||
MyGUI::VScrollPtr skillScrollerWidget;
|
||||
int lastPos, clientHeight;
|
||||
MyGUI::EditPtr mLeftTextWidget;
|
||||
MyGUI::EditPtr mRightTextWidget;
|
||||
MyGUI::ButtonPtr mPrevBtn;
|
||||
MyGUI::ButtonPtr mNextBtn;
|
||||
std::vector<std::string> leftPages;
|
||||
std::vector<std::string> rightPages;
|
||||
int mPageNumber; //store the number of the current left page
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,7 +13,7 @@
|
|||
using namespace MWGui;
|
||||
|
||||
|
||||
HUD::HUD(int width, int height, bool fpsSwitch)
|
||||
HUD::HUD(int width, int height, int fpsLevel)
|
||||
: Layout("openmw_hud_layout.xml")
|
||||
{
|
||||
setCoord(0,0, width, height);
|
||||
|
@ -37,10 +37,19 @@ HUD::HUD(int width, int height, bool fpsSwitch)
|
|||
|
||||
getWidget(crosshair, "Crosshair");
|
||||
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
|
||||
fpsbox->setVisible(fpsSwitch);
|
||||
if ( fpsLevel == 2 ){
|
||||
getWidget(fpsbox, "FPSBoxAdv");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounterAdv");
|
||||
}else if ( fpsLevel == 1 ){
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}else{
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}
|
||||
getWidget(trianglecounter, "TriangleCounter");
|
||||
getWidget(batchcounter, "BatchCounter");
|
||||
|
||||
compass->setImageTexture("textures\\compass.dds");
|
||||
crosshair->setImageTexture("textures\\target.dds");
|
||||
|
@ -59,6 +68,15 @@ void HUD::setFPS(float fps)
|
|||
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
|
||||
}
|
||||
|
||||
void HUD::setTriangleCount(size_t count)
|
||||
{
|
||||
trianglecounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setBatchCount(size_t count)
|
||||
{
|
||||
batchcounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace MWGui
|
|||
class HUD : public OEngine::GUI::Layout
|
||||
{
|
||||
public:
|
||||
HUD(int width, int height, bool fpsSwitch);
|
||||
HUD(int width, int height, int fpsLevel);
|
||||
void setStats(int h, int hmax, int m, int mmax, int s, int smax);
|
||||
void setWeapIcon(const char *str);
|
||||
void setSpellIcon(const char *str);
|
||||
|
@ -41,6 +41,8 @@ namespace MWGui
|
|||
void setEffect(const char *img);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
|
||||
void setFPS(float fps);
|
||||
void setTriangleCount(size_t count);
|
||||
void setBatchCount(size_t count);
|
||||
|
||||
MyGUI::ProgressPtr health, magicka, stamina;
|
||||
MyGUI::StaticImagePtr weapImage, spellImage;
|
||||
|
@ -53,6 +55,8 @@ namespace MWGui
|
|||
|
||||
MyGUI::WidgetPtr fpsbox;
|
||||
MyGUI::StaticTextPtr fpscounter;
|
||||
MyGUI::StaticTextPtr trianglecounter;
|
||||
MyGUI::StaticTextPtr batchcounter;
|
||||
};
|
||||
|
||||
class MapWindow : public OEngine::GUI::Layout
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace MWGui
|
|||
GM_MainMenu, // Main menu mode
|
||||
|
||||
GM_Console, // Console mode
|
||||
GM_Journal, // Journal mode
|
||||
|
||||
// None of the following are implemented yet
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#include "window_manager.hpp"
|
||||
#include "layouts.hpp"
|
||||
#include "text_input.hpp"
|
||||
#include "race.hpp"
|
||||
#include "class.hpp"
|
||||
#include "birth.hpp"
|
||||
#include "review.hpp"
|
||||
#include "dialogue.hpp"
|
||||
#include "dialogue_history.hpp"
|
||||
|
@ -14,6 +11,8 @@
|
|||
#include "../mwinput/inputmanager.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
#include "journalwindow.hpp"
|
||||
#include "charactercreation.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
@ -21,29 +20,21 @@
|
|||
|
||||
using namespace MWGui;
|
||||
|
||||
WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment,
|
||||
const Compiler::Extensions& extensions, bool fpsSwitch, bool newGame)
|
||||
WindowManager::WindowManager(MWWorld::Environment& environment,
|
||||
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath)
|
||||
: environment(environment)
|
||||
, nameDialog(nullptr)
|
||||
, raceDialog(nullptr)
|
||||
, dialogueWindow(nullptr)
|
||||
, classChoiceDialog(nullptr)
|
||||
, generateClassQuestionDialog(nullptr)
|
||||
, generateClassResultDialog(nullptr)
|
||||
, pickClassDialog(nullptr)
|
||||
, createClassDialog(nullptr)
|
||||
, birthSignDialog(nullptr)
|
||||
, reviewDialog(nullptr)
|
||||
, gui(_gui)
|
||||
, mode(GM_Game)
|
||||
, nextMode(GM_Game)
|
||||
, needModeChange(false)
|
||||
, shown(GW_ALL)
|
||||
, allowed(newGame ? GW_None : GW_ALL)
|
||||
{
|
||||
showFPSCounter = fpsSwitch;
|
||||
showFPSLevel = fpsLevel;
|
||||
|
||||
creationStage = NotStarted;
|
||||
// Set up the GUI system
|
||||
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath);
|
||||
gui = mGuiManager->getGui();
|
||||
|
||||
//Register own widgets with MyGUI
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<DialogeHistory>("Widget");
|
||||
|
@ -53,19 +44,19 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
|
|||
int w = gui->getViewSize().width;
|
||||
int h = gui->getViewSize().height;
|
||||
|
||||
hud = new HUD(w,h, showFPSCounter);
|
||||
hud = new HUD(w,h, showFPSLevel);
|
||||
menu = new MainMenu(w,h);
|
||||
map = new MapWindow();
|
||||
stats = new StatsWindow(*this);
|
||||
#if 0
|
||||
inventory = new InventoryWindow ();
|
||||
#endif
|
||||
console = new Console(w,h, environment, extensions);
|
||||
mJournal = new JournalWindow(*this);
|
||||
mMessageBoxManager = new MessageBoxManager(this);
|
||||
|
||||
// The HUD is always on
|
||||
hud->setVisible(true);
|
||||
|
||||
mCharGen = new CharacterCreation(this, &environment);
|
||||
|
||||
// Setup player stats
|
||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||
{
|
||||
|
@ -89,26 +80,17 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
|
|||
|
||||
WindowManager::~WindowManager()
|
||||
{
|
||||
delete mGuiManager;
|
||||
delete console;
|
||||
delete mMessageBoxManager;
|
||||
delete hud;
|
||||
delete map;
|
||||
delete menu;
|
||||
delete stats;
|
||||
#if 0
|
||||
delete inventory;
|
||||
#endif
|
||||
|
||||
delete nameDialog;
|
||||
delete raceDialog;
|
||||
delete mJournal;
|
||||
delete dialogueWindow;
|
||||
delete classChoiceDialog;
|
||||
delete generateClassQuestionDialog;
|
||||
delete generateClassResultDialog;
|
||||
delete pickClassDialog;
|
||||
delete createClassDialog;
|
||||
delete birthSignDialog;
|
||||
delete reviewDialog;
|
||||
|
||||
delete mCharGen;
|
||||
|
||||
cleanupGarbage();
|
||||
}
|
||||
|
@ -135,12 +117,19 @@ void WindowManager::update()
|
|||
environment.mInputManager->setGuiMode(nextMode);
|
||||
nextMode = GM_Game;
|
||||
}
|
||||
if (showFPSCounter)
|
||||
if (showFPSLevel > 0)
|
||||
{
|
||||
hud->setFPS(mFPS);
|
||||
hud->setTriangleCount(mTriangleCount);
|
||||
hud->setBatchCount(mBatchCount);
|
||||
}
|
||||
}
|
||||
|
||||
MWWorld::Environment& WindowManager::getEnvironment()
|
||||
{
|
||||
return environment;
|
||||
}
|
||||
|
||||
void WindowManager::setNextMode(GuiMode newMode)
|
||||
{
|
||||
nextMode = newMode;
|
||||
|
@ -158,16 +147,14 @@ void WindowManager::updateVisible()
|
|||
map->setVisible(false);
|
||||
menu->setVisible(false);
|
||||
stats->setVisible(false);
|
||||
#if 0
|
||||
inventory->setVisible(false);
|
||||
#endif
|
||||
console->disable();
|
||||
mJournal->setVisible(false);
|
||||
|
||||
// Mouse is visible whenever we're not in game mode
|
||||
gui->setVisiblePointer(isGuiMode());
|
||||
|
||||
// If in game mode, don't show anything.
|
||||
if(mode == GM_Game)
|
||||
if(mode == GM_Game) //Use a switch/case structure
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -185,126 +172,10 @@ void WindowManager::updateVisible()
|
|||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Name)
|
||||
//There must be a more elegant solution
|
||||
if (mode == GM_Name || mode == GM_Race || mode == GM_Class || mode == GM_ClassPick || mode == GM_ClassCreate || mode == GM_Birth || mode == GM_ClassGenerate || mode == GM_Review)
|
||||
{
|
||||
if (nameDialog)
|
||||
removeDialog(nameDialog);
|
||||
nameDialog = new TextInputDialog(*this);
|
||||
std::string sName = getGameSettingString("sName", "Name");
|
||||
nameDialog->setTextLabel(sName);
|
||||
nameDialog->setTextInput(playerName);
|
||||
nameDialog->setNextButtonShow(creationStage >= NameChosen);
|
||||
nameDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onNameDialogDone);
|
||||
nameDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Race)
|
||||
{
|
||||
if (raceDialog)
|
||||
removeDialog(raceDialog);
|
||||
raceDialog = new RaceDialog(*this);
|
||||
raceDialog->setNextButtonShow(creationStage >= RaceChosen);
|
||||
raceDialog->setRaceId(playerRaceId);
|
||||
raceDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onRaceDialogDone);
|
||||
raceDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onRaceDialogBack);
|
||||
raceDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Class)
|
||||
{
|
||||
if (classChoiceDialog)
|
||||
removeDialog(classChoiceDialog);
|
||||
classChoiceDialog = new ClassChoiceDialog(*this);
|
||||
classChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &WindowManager::onClassChoice);
|
||||
classChoiceDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_ClassGenerate)
|
||||
{
|
||||
generateClassStep = 0;
|
||||
generateClass = "";
|
||||
generateClassSpecializations[0] = 0;
|
||||
generateClassSpecializations[1] = 0;
|
||||
generateClassSpecializations[2] = 0;
|
||||
showClassQuestionDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_ClassPick)
|
||||
{
|
||||
if (pickClassDialog)
|
||||
removeDialog(pickClassDialog);
|
||||
pickClassDialog = new PickClassDialog(*this);
|
||||
pickClassDialog->setNextButtonShow(creationStage >= ClassChosen);
|
||||
pickClassDialog->setClassId(playerClass.name);
|
||||
pickClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogDone);
|
||||
pickClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogBack);
|
||||
pickClassDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_ClassCreate)
|
||||
{
|
||||
if (createClassDialog)
|
||||
removeDialog(createClassDialog);
|
||||
createClassDialog = new CreateClassDialog(*this);
|
||||
createClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogDone);
|
||||
createClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogBack);
|
||||
createClassDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Birth)
|
||||
{
|
||||
if (birthSignDialog)
|
||||
removeDialog(birthSignDialog);
|
||||
birthSignDialog = new BirthDialog(*this);
|
||||
birthSignDialog->setNextButtonShow(creationStage >= BirthSignChosen);
|
||||
birthSignDialog->setBirthId(playerBirthSignId);
|
||||
birthSignDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogDone);
|
||||
birthSignDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogBack);
|
||||
birthSignDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Review)
|
||||
{
|
||||
if (reviewDialog)
|
||||
removeDialog(reviewDialog);
|
||||
reviewDialog = new ReviewDialog(*this);
|
||||
reviewDialog->setPlayerName(playerName);
|
||||
reviewDialog->setRace(playerRaceId);
|
||||
reviewDialog->setClass(playerClass);
|
||||
reviewDialog->setBirthSign(playerBirthSignId);
|
||||
|
||||
reviewDialog->setHealth(playerHealth);
|
||||
reviewDialog->setMagicka(playerMagicka);
|
||||
reviewDialog->setFatigue(playerFatigue);
|
||||
|
||||
{
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator end = playerAttributes.end();
|
||||
for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = playerAttributes.begin(); it != end; ++it)
|
||||
{
|
||||
reviewDialog->setAttribute(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator end = playerSkillValues.end();
|
||||
for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = playerSkillValues.begin(); it != end; ++it)
|
||||
{
|
||||
reviewDialog->setSkillValue(it->first, it->second);
|
||||
}
|
||||
reviewDialog->configureSkills(playerMajorSkills, playerMinorSkills);
|
||||
}
|
||||
|
||||
reviewDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onReviewDialogDone);
|
||||
reviewDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onReviewDialogBack);
|
||||
reviewDialog->eventActivateDialog = MyGUI::newDelegate(this, &WindowManager::onReviewActivateDialog);
|
||||
reviewDialog->open();
|
||||
mCharGen->spawnDialog(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -319,9 +190,6 @@ void WindowManager::updateVisible()
|
|||
// Show the windows we want
|
||||
map -> setVisible( (eff & GW_Map) != 0 );
|
||||
stats -> setVisible( (eff & GW_Stats) != 0 );
|
||||
#if 0
|
||||
// inventory -> setVisible( eff & GW_Inventory );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -344,6 +212,12 @@ void WindowManager::updateVisible()
|
|||
return;
|
||||
}
|
||||
|
||||
if(mode == GM_Journal)
|
||||
{
|
||||
mJournal->setVisible(true);
|
||||
mJournal->open();
|
||||
return;
|
||||
}
|
||||
|
||||
// Unsupported mode, switch back to game
|
||||
// Note: The call will eventually end up this method again but
|
||||
|
@ -392,13 +266,34 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
|
|||
stats->setValue (id, value);
|
||||
hud->setValue (id, value);
|
||||
if (id == "HBar")
|
||||
{
|
||||
playerHealth = value;
|
||||
mCharGen->setPlayerHealth (value);
|
||||
}
|
||||
else if (id == "MBar")
|
||||
{
|
||||
playerMagicka = value;
|
||||
mCharGen->setPlayerMagicka (value);
|
||||
}
|
||||
else if (id == "FBar")
|
||||
{
|
||||
playerFatigue = value;
|
||||
mCharGen->setPlayerFatigue (value);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id)
|
||||
{
|
||||
if(id == "HBar")
|
||||
return playerHealth;
|
||||
else if (id == "MBar")
|
||||
return playerMagicka;
|
||||
else if (id == "FBar")
|
||||
return playerFatigue;
|
||||
}
|
||||
#endif
|
||||
|
||||
void WindowManager::setValue (const std::string& id, const std::string& value)
|
||||
{
|
||||
stats->setValue (id, value);
|
||||
|
@ -487,49 +382,6 @@ const std::string &WindowManager::getGameSettingString(const std::string &id, co
|
|||
return default_;
|
||||
}
|
||||
|
||||
void WindowManager::onNameDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (nameDialog)
|
||||
{
|
||||
playerName = nameDialog->getTextInput();
|
||||
environment.mMechanicsManager->setPlayerName(playerName);
|
||||
removeDialog(nameDialog);
|
||||
}
|
||||
|
||||
// Go to next dialog if name was previously chosen
|
||||
if (creationStage == ReviewNext)
|
||||
setGuiMode(GM_Review);
|
||||
else if (creationStage >= NameChosen)
|
||||
setGuiMode(GM_Race);
|
||||
else
|
||||
{
|
||||
creationStage = NameChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::onRaceDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (raceDialog)
|
||||
{
|
||||
playerRaceId = raceDialog->getRaceId();
|
||||
if (!playerRaceId.empty())
|
||||
environment.mMechanicsManager->setPlayerRace(playerRaceId, raceDialog->getGender() == RaceDialog::GM_Male);
|
||||
removeDialog(raceDialog);
|
||||
}
|
||||
|
||||
// Go to next dialog if race was previously chosen
|
||||
if (creationStage == ReviewNext)
|
||||
setGuiMode(GM_Review);
|
||||
else if(creationStage >= RaceChosen)
|
||||
setGuiMode(GM_Class);
|
||||
else
|
||||
{
|
||||
creationStage = RaceChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::onDialogueWindowBye()
|
||||
{
|
||||
if (dialogueWindow)
|
||||
|
@ -540,434 +392,11 @@ void WindowManager::onDialogueWindowBye()
|
|||
setGuiMode(GM_Game);
|
||||
}
|
||||
|
||||
void WindowManager::onRaceDialogBack()
|
||||
{
|
||||
if (raceDialog)
|
||||
{
|
||||
playerRaceId = raceDialog->getRaceId();
|
||||
if (!playerRaceId.empty())
|
||||
environment.mMechanicsManager->setPlayerRace(playerRaceId, raceDialog->getGender() == RaceDialog::GM_Male);
|
||||
removeDialog(raceDialog);
|
||||
}
|
||||
|
||||
setGuiMode(GM_Name);
|
||||
}
|
||||
|
||||
void WindowManager::onClassChoice(int _index)
|
||||
{
|
||||
if (classChoiceDialog)
|
||||
{
|
||||
removeDialog(classChoiceDialog);
|
||||
}
|
||||
|
||||
switch(_index)
|
||||
{
|
||||
case ClassChoiceDialog::Class_Generate:
|
||||
setGuiMode(GM_ClassGenerate);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Pick:
|
||||
setGuiMode(GM_ClassPick);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Create:
|
||||
setGuiMode(GM_ClassCreate);
|
||||
break;
|
||||
case ClassChoiceDialog::Class_Back:
|
||||
setGuiMode(GM_Race);
|
||||
break;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void WindowManager::onFrame (float frameDuration)
|
||||
{
|
||||
mMessageBoxManager->onFrame(frameDuration);
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
struct Step
|
||||
{
|
||||
const char* text;
|
||||
const char* buttons[3];
|
||||
// The specialization for each answer
|
||||
ESM::Class::Specialization specializations[3];
|
||||
};
|
||||
|
||||
static boost::array<Step, 10> generateClassSteps = { {
|
||||
// Question 1
|
||||
{"On a clear day you chance upon a strange animal, its legs trapped in a hunter's clawsnare. Judging from the bleeding, it will not survive long.",
|
||||
{"Draw your dagger, mercifully endings its life with a single thrust.",
|
||||
"Use herbs from your pack to put it to sleep.",
|
||||
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 2
|
||||
{"One Summer afternoon your father gives you a choice of chores.",
|
||||
{"Work in the forge with him casting iron for a new plow.",
|
||||
"Gather herbs for your mother who is preparing dinner.",
|
||||
"Go catch fish at the stream using a net and line."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 3
|
||||
{"Your cousin has given you a very embarrassing nickname and, even worse, likes to call you it in front of your friends. You asked him to stop, but he finds it very amusing to watch you blush.",
|
||||
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
|
||||
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
|
||||
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 4
|
||||
{"There is a lot of heated discussion at the local tavern over a grouped of people called 'Telepaths'. They have been hired by certain City-State kings. Rumor has it these Telepaths read a person's mind and tell their lord whether a follower is telling the truth or not.",
|
||||
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
|
||||
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
|
||||
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 5
|
||||
{"Your mother sends you to the market with a list of goods to buy. After you finish you find that by mistake a shopkeeper has given you too much money back in exchange for one of the items.",
|
||||
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
|
||||
"Decide to put the extra money to good use and purchase items that would help your family?",
|
||||
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 6
|
||||
{"While in the market place you witness a thief cut a purse from a noble. Even as he does so, the noble notices and calls for the city guards. In his haste to get away, the thief drops the purse near you. Surprisingly no one seems to notice the bag of coins at your feet.",
|
||||
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
|
||||
"Leave the bag there, knowing that it is better not to get involved.",
|
||||
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 7
|
||||
{"Your father sends you on a task which you loathe, cleaning the stables. On the way there, pitchfork in hand, you run into your friend from the homestead near your own. He offers to do it for you, in return for a future favor of his choosing.",
|
||||
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
|
||||
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
|
||||
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 8
|
||||
{"Your mother asks you to help fix the stove. While you are working, a very hot pipe slips its mooring and falls towards her.",
|
||||
{"Position yourself between the pipe and your mother.",
|
||||
"Grab the hot pipe and try to push it away.",
|
||||
"Push your mother out of the way."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 9
|
||||
{"While in town the baker gives you a sweetroll. Delighted, you take it into an alley to enjoy only to be intercepted by a gang of three other kids your age. The leader demands the sweetroll, or else he and his friends will beat you and take it.",
|
||||
{"Drop the sweetroll and step on it, then get ready for the fight.",
|
||||
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
|
||||
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 10
|
||||
{"Entering town you find that you are witness to a very well-dressed man running from a crowd. He screams to you for help. The crowd behind him seem very angry.",
|
||||
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
|
||||
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
|
||||
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
}
|
||||
} };
|
||||
}
|
||||
|
||||
void WindowManager::showClassQuestionDialog()
|
||||
{
|
||||
if (generateClassStep == generateClassSteps.size())
|
||||
{
|
||||
|
||||
static boost::array<ClassPoint, 23> classes = { {
|
||||
{"Acrobat", {6, 2, 2}},
|
||||
{"Agent", {6, 1, 3}},
|
||||
{"Archer", {3, 5, 2}},
|
||||
{"Archer", {5, 5, 0}},
|
||||
{"Assassin", {6, 3, 1}},
|
||||
{"Barbarian", {3, 6, 1}},
|
||||
{"Bard", {3, 3, 3}},
|
||||
{"Battlemage", {1, 3, 6}},
|
||||
{"Crusader", {1, 6, 3}},
|
||||
{"Healer", {3, 1, 6}},
|
||||
{"Knight", {2, 6, 2}},
|
||||
{"Monk", {5, 3, 2}},
|
||||
{"Nightblade", {4, 2, 4}},
|
||||
{"Pilgrim", {5, 2, 3}},
|
||||
{"Rogue", {3, 4, 3}},
|
||||
{"Rogue", {4, 4, 2}},
|
||||
{"Rogue", {5, 4, 1}},
|
||||
{"Scout", {2, 5, 3}},
|
||||
{"Sorcerer", {2, 2, 6}},
|
||||
{"Spellsword", {2, 4, 4}},
|
||||
{"Spellsword", {5, 1, 4}},
|
||||
{"Witchhunter", {2, 3, 5}},
|
||||
{"Witchhunter", {5, 0, 5}}
|
||||
} };
|
||||
|
||||
int match = -1;
|
||||
for (unsigned i = 0; i < classes.size(); ++i)
|
||||
{
|
||||
if (generateClassSpecializations[0] == classes[i].points[0] &&
|
||||
generateClassSpecializations[1] == classes[i].points[1] &&
|
||||
generateClassSpecializations[2] == classes[i].points[2])
|
||||
{
|
||||
match = i;
|
||||
generateClass = classes[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match == -1)
|
||||
{
|
||||
if (generateClassSpecializations[0] >= 7)
|
||||
generateClass = "Thief";
|
||||
else if (generateClassSpecializations[1] >= 7)
|
||||
generateClass = "Warrior";
|
||||
else if (generateClassSpecializations[2] >= 7)
|
||||
generateClass = "Mage";
|
||||
else
|
||||
{
|
||||
std::cerr
|
||||
<< "Failed to deduce class from chosen answers in generate class dialog"
|
||||
<< std::endl;
|
||||
generateClass = "Thief";
|
||||
}
|
||||
}
|
||||
|
||||
if (generateClassResultDialog)
|
||||
removeDialog(generateClassResultDialog);
|
||||
generateClassResultDialog = new GenerateClassResultDialog(*this);
|
||||
generateClassResultDialog->setClassId(generateClass);
|
||||
generateClassResultDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onGenerateClassBack);
|
||||
generateClassResultDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onGenerateClassDone);
|
||||
generateClassResultDialog->open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (generateClassStep > generateClassSteps.size())
|
||||
{
|
||||
setGuiMode(GM_Class);
|
||||
return;
|
||||
}
|
||||
|
||||
if (generateClassQuestionDialog)
|
||||
removeDialog(generateClassQuestionDialog);
|
||||
generateClassQuestionDialog = new InfoBoxDialog(*this);
|
||||
|
||||
InfoBoxDialog::ButtonList buttons;
|
||||
generateClassQuestionDialog->setText(generateClassSteps[generateClassStep].text);
|
||||
buttons.push_back(generateClassSteps[generateClassStep].buttons[0]);
|
||||
buttons.push_back(generateClassSteps[generateClassStep].buttons[1]);
|
||||
buttons.push_back(generateClassSteps[generateClassStep].buttons[2]);
|
||||
generateClassQuestionDialog->setButtons(buttons);
|
||||
generateClassQuestionDialog->eventButtonSelected = MyGUI::newDelegate(this, &WindowManager::onClassQuestionChosen);
|
||||
generateClassQuestionDialog->open();
|
||||
}
|
||||
|
||||
void WindowManager::onClassQuestionChosen(int _index)
|
||||
{
|
||||
if (generateClassQuestionDialog)
|
||||
removeDialog(generateClassQuestionDialog);
|
||||
if (_index < 0 || _index >= 3)
|
||||
{
|
||||
setGuiMode(GM_Class);
|
||||
return;
|
||||
}
|
||||
|
||||
ESM::Class::Specialization specialization = generateClassSteps[generateClassStep].specializations[_index];
|
||||
if (specialization == ESM::Class::Stealth)
|
||||
++generateClassSpecializations[0];
|
||||
else if (specialization == ESM::Class::Combat)
|
||||
++generateClassSpecializations[1];
|
||||
else if (specialization == ESM::Class::Magic)
|
||||
++generateClassSpecializations[2];
|
||||
++generateClassStep;
|
||||
showClassQuestionDialog();
|
||||
}
|
||||
|
||||
void WindowManager::onGenerateClassBack()
|
||||
{
|
||||
if(creationStage < ClassChosen)
|
||||
creationStage = ClassChosen;
|
||||
|
||||
if (generateClassResultDialog)
|
||||
removeDialog(generateClassResultDialog);
|
||||
environment.mMechanicsManager->setPlayerClass(generateClass);
|
||||
|
||||
setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void WindowManager::onGenerateClassDone(WindowBase* parWindow)
|
||||
{
|
||||
if (generateClassResultDialog)
|
||||
removeDialog(generateClassResultDialog);
|
||||
environment.mMechanicsManager->setPlayerClass(generateClass);
|
||||
|
||||
// Go to next dialog if class was previously chosen
|
||||
if (creationStage == ReviewNext)
|
||||
setGuiMode(GM_Review);
|
||||
else if (creationStage >= ClassChosen)
|
||||
setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
creationStage = ClassChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WindowManager::onPickClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (pickClassDialog)
|
||||
{
|
||||
const std::string &classId = pickClassDialog->getClassId();
|
||||
if (!classId.empty())
|
||||
environment.mMechanicsManager->setPlayerClass(classId);
|
||||
const ESM::Class *klass = environment.mWorld->getStore().classes.find(classId);
|
||||
if (klass)
|
||||
playerClass = *klass;
|
||||
removeDialog(pickClassDialog);
|
||||
}
|
||||
|
||||
// Go to next dialog if class was previously chosen
|
||||
if (creationStage == ReviewNext)
|
||||
setGuiMode(GM_Review);
|
||||
else if (creationStage >= ClassChosen)
|
||||
setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
creationStage = ClassChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::onPickClassDialogBack()
|
||||
{
|
||||
if (pickClassDialog)
|
||||
{
|
||||
const std::string classId = pickClassDialog->getClassId();
|
||||
if (!classId.empty())
|
||||
environment.mMechanicsManager->setPlayerClass(classId);
|
||||
removeDialog(pickClassDialog);
|
||||
}
|
||||
|
||||
setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void WindowManager::onCreateClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (createClassDialog)
|
||||
{
|
||||
ESM::Class klass;
|
||||
klass.name = createClassDialog->getName();
|
||||
klass.description = createClassDialog->getDescription();
|
||||
klass.data.specialization = createClassDialog->getSpecializationId();
|
||||
klass.data.isPlayable = 0x1;
|
||||
|
||||
std::vector<int> attributes = createClassDialog->getFavoriteAttributes();
|
||||
assert(attributes.size() == 2);
|
||||
klass.data.attribute[0] = attributes[0];
|
||||
klass.data.attribute[1] = attributes[1];
|
||||
|
||||
std::vector<ESM::Skill::SkillEnum> majorSkills = createClassDialog->getMajorSkills();
|
||||
std::vector<ESM::Skill::SkillEnum> minorSkills = createClassDialog->getMinorSkills();
|
||||
assert(majorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
|
||||
assert(minorSkills.size() >= sizeof(klass.data.skills)/sizeof(klass.data.skills[0]));
|
||||
for (size_t i = 0; i < sizeof(klass.data.skills)/sizeof(klass.data.skills[0]); ++i)
|
||||
{
|
||||
klass.data.skills[i][1] = majorSkills[i];
|
||||
klass.data.skills[i][0] = minorSkills[i];
|
||||
}
|
||||
environment.mMechanicsManager->setPlayerClass(klass);
|
||||
playerClass = klass;
|
||||
|
||||
removeDialog(createClassDialog);
|
||||
}
|
||||
|
||||
// Go to next dialog if class was previously chosen
|
||||
if (creationStage == ReviewNext)
|
||||
setGuiMode(GM_Review);
|
||||
else if (creationStage >= ClassChosen)
|
||||
setGuiMode(GM_Birth);
|
||||
else
|
||||
{
|
||||
creationStage = ClassChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::onCreateClassDialogBack()
|
||||
{
|
||||
if (createClassDialog)
|
||||
removeDialog(createClassDialog);
|
||||
|
||||
setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void WindowManager::onBirthSignDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (birthSignDialog)
|
||||
{
|
||||
playerBirthSignId = birthSignDialog->getBirthId();
|
||||
if (!playerBirthSignId.empty())
|
||||
environment.mMechanicsManager->setPlayerBirthsign(playerBirthSignId);
|
||||
removeDialog(birthSignDialog);
|
||||
}
|
||||
|
||||
// Go to next dialog if birth sign was previously chosen
|
||||
if (creationStage >= BirthSignChosen)
|
||||
setGuiMode(GM_Review);
|
||||
else
|
||||
{
|
||||
creationStage = BirthSignChosen;
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::onBirthSignDialogBack()
|
||||
{
|
||||
if (birthSignDialog)
|
||||
{
|
||||
environment.mMechanicsManager->setPlayerBirthsign(birthSignDialog->getBirthId());
|
||||
removeDialog(birthSignDialog);
|
||||
}
|
||||
|
||||
setGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void WindowManager::onReviewDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
if (reviewDialog)
|
||||
removeDialog(reviewDialog);
|
||||
|
||||
setGuiMode(GM_Game);
|
||||
}
|
||||
|
||||
void WindowManager::onReviewDialogBack()
|
||||
{
|
||||
if (reviewDialog)
|
||||
removeDialog(reviewDialog);
|
||||
|
||||
setGuiMode(GM_Birth);
|
||||
}
|
||||
|
||||
void WindowManager::onReviewActivateDialog(int parDialog)
|
||||
{
|
||||
if (reviewDialog)
|
||||
removeDialog(reviewDialog);
|
||||
creationStage = ReviewNext;
|
||||
|
||||
switch(parDialog)
|
||||
{
|
||||
case ReviewDialog::NAME_DIALOG:
|
||||
setGuiMode(GM_Name);
|
||||
break;
|
||||
case ReviewDialog::RACE_DIALOG:
|
||||
setGuiMode(GM_Race);
|
||||
break;
|
||||
case ReviewDialog::CLASS_DIALOG:
|
||||
setGuiMode(GM_Class);
|
||||
break;
|
||||
case ReviewDialog::BIRTHSIGN_DIALOG:
|
||||
setGuiMode(GM_Birth);
|
||||
};
|
||||
}
|
||||
|
||||
const ESMS::ESMStore& WindowManager::getStore() const
|
||||
{
|
||||
return environment.mWorld->getStore();
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
|
||||
MyGUI should be initialized separately before creating instances of
|
||||
this class.
|
||||
*/
|
||||
**/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <components/esm_store/store.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/gui/manager.hpp>
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
#include "mode.hpp"
|
||||
|
||||
|
@ -32,6 +34,12 @@ namespace Compiler
|
|||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class MechanicsManager;
|
||||
}
|
||||
|
||||
namespace OEngine
|
||||
|
@ -51,17 +59,12 @@ namespace MWGui
|
|||
class StatsWindow;
|
||||
class InventoryWindow;
|
||||
class Console;
|
||||
class JournalWindow;
|
||||
class CharacterCreation;
|
||||
|
||||
class TextInputDialog;
|
||||
class InfoBoxDialog;
|
||||
class RaceDialog;
|
||||
class DialogueWindow;
|
||||
class ClassChoiceDialog;
|
||||
class GenerateClassResultDialog;
|
||||
class PickClassDialog;
|
||||
class CreateClassDialog;
|
||||
class BirthDialog;
|
||||
class ReviewDialog;
|
||||
class MessageBoxManager;
|
||||
|
||||
struct ClassPoint
|
||||
|
@ -79,92 +82,11 @@ namespace MWGui
|
|||
typedef std::vector<Faction> FactionList;
|
||||
typedef std::vector<int> SkillList;
|
||||
|
||||
private:
|
||||
MWWorld::Environment& environment;
|
||||
HUD *hud;
|
||||
MapWindow *map;
|
||||
MainMenu *menu;
|
||||
StatsWindow *stats;
|
||||
MessageBoxManager *mMessageBoxManager;
|
||||
#if 0
|
||||
InventoryWindow *inventory;
|
||||
#endif
|
||||
Console *console;
|
||||
|
||||
// Character creation
|
||||
TextInputDialog *nameDialog;
|
||||
RaceDialog *raceDialog;
|
||||
DialogueWindow *dialogueWindow;
|
||||
ClassChoiceDialog *classChoiceDialog;
|
||||
InfoBoxDialog *generateClassQuestionDialog;
|
||||
GenerateClassResultDialog *generateClassResultDialog;
|
||||
PickClassDialog *pickClassDialog;
|
||||
CreateClassDialog *createClassDialog;
|
||||
BirthDialog *birthSignDialog;
|
||||
ReviewDialog *reviewDialog;
|
||||
|
||||
// Keeps track of current step in Generate Class dialogs
|
||||
unsigned generateClassStep;
|
||||
// A counter for each specialization which is increased when an answer is chosen, in order: Stealth, Combat, Magic
|
||||
unsigned generateClassSpecializations[3];
|
||||
std::string generateClass;
|
||||
|
||||
// Various stats about player as needed by window manager
|
||||
std::string playerName;
|
||||
ESM::Class playerClass;
|
||||
std::string playerRaceId, playerBirthSignId;
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > playerAttributes;
|
||||
SkillList playerMajorSkills, playerMinorSkills;
|
||||
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > playerSkillValues;
|
||||
MWMechanics::DynamicStat<int> playerHealth, playerMagicka, playerFatigue;
|
||||
|
||||
// Gui
|
||||
MyGUI::Gui *gui;
|
||||
|
||||
// Current gui mode
|
||||
GuiMode mode;
|
||||
|
||||
/**
|
||||
* Next mode to activate in update().
|
||||
*/
|
||||
GuiMode nextMode;
|
||||
/**
|
||||
* Whether a mode change is needed in update().
|
||||
* Will use @a nextMode as the new mode.
|
||||
*/
|
||||
bool needModeChange;
|
||||
|
||||
std::vector<OEngine::GUI::Layout*> garbageDialogs;
|
||||
void cleanupGarbage();
|
||||
|
||||
// Currently shown windows in inventory mode
|
||||
GuiWindow shown;
|
||||
|
||||
/* Currently ALLOWED windows in inventory mode. This is used at
|
||||
the start of the game, when windows are enabled one by one
|
||||
through script commands. You can manipulate this through using
|
||||
allow() and disableAll().
|
||||
|
||||
The setting should also affect visibility of certain HUD
|
||||
elements, but this is not done yet.
|
||||
*/
|
||||
GuiWindow allowed;
|
||||
|
||||
// Update visibility of all windows based on mode, shown and
|
||||
// allowed settings.
|
||||
void updateVisible();
|
||||
WindowManager(MWWorld::Environment& environment, const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath);
|
||||
virtual ~WindowManager();
|
||||
|
||||
void setGuiMode(GuiMode newMode);
|
||||
|
||||
bool showFPSCounter;
|
||||
float mFPS;
|
||||
|
||||
public:
|
||||
/// The constructor needs the main Gui object
|
||||
WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment,
|
||||
const Compiler::Extensions& extensions, bool fpsSwitch, bool newGame);
|
||||
virtual ~WindowManager();
|
||||
|
||||
/**
|
||||
* Should be called each frame to update windows/gui elements.
|
||||
* This could mean updating sizes of gui elements or opening
|
||||
|
@ -172,6 +94,8 @@ namespace MWGui
|
|||
*/
|
||||
void update();
|
||||
|
||||
MWWorld::Environment& getEnvironment();
|
||||
|
||||
void setMode(GuiMode newMode)
|
||||
{
|
||||
if (newMode==GM_Inventory && allowed==GW_None)
|
||||
|
@ -184,8 +108,7 @@ namespace MWGui
|
|||
|
||||
GuiMode getMode() const { return mode; }
|
||||
|
||||
// Everything that is not game mode is considered "gui mode"
|
||||
bool isGuiMode() const { return getMode() != GM_Game; }
|
||||
bool isGuiMode() const { return getMode() != GM_Game; } // Everything that is not game mode is considered "gui mode"
|
||||
|
||||
// Disallow all inventory mode windows
|
||||
void disallowAll()
|
||||
|
@ -203,56 +126,38 @@ namespace MWGui
|
|||
|
||||
MyGUI::Gui* getGui() const { return gui; }
|
||||
|
||||
void wmSetFPS(float fps) { mFPS = fps; }
|
||||
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)
|
||||
{
|
||||
mFPS = fps;
|
||||
mTriangleCount = triangleCount;
|
||||
mBatchCount = batchCount;
|
||||
}
|
||||
|
||||
// MWMechanics::DynamicStat<int> getValue(const std::string& id);
|
||||
|
||||
///< Set value for the given ID.
|
||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
///< Set value for the given ID.
|
||||
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
||||
///< Set value for the given ID.
|
||||
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
|
||||
///< Set value for the given ID.
|
||||
|
||||
void setValue (const std::string& id, const std::string& value);
|
||||
///< set value for the given ID.
|
||||
|
||||
void setValue (const std::string& id, int value);
|
||||
///< set value for the given ID.
|
||||
|
||||
void setPlayerClass (const ESM::Class &class_);
|
||||
///< set current class of player
|
||||
void setPlayerClass (const ESM::Class &class_); ///< set current class of player
|
||||
void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group.
|
||||
void setFactions (const FactionList& factions); ///< set faction and rank to display on stat window, use an empty vector to disable
|
||||
void setBirthSign (const std::string &signId); ///< set birth sign to display on stat window, use an empty string to disable.
|
||||
void setReputation (int reputation); ///< set the current reputation value
|
||||
void setBounty (int bounty); ///< set the current bounty value
|
||||
void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
|
||||
|
||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||
///< configure skill groups, each set contains the skill ID for that group.
|
||||
|
||||
void setFactions (const FactionList& factions);
|
||||
///< set faction and rank to display on stat window, use an empty vector to disable
|
||||
|
||||
void setBirthSign (const std::string &signId);
|
||||
///< set birth sign to display on stat window, use an empty string to disable.
|
||||
|
||||
void setReputation (int reputation);
|
||||
///< set the current reputation value
|
||||
|
||||
void setBounty (int bounty);
|
||||
///< set the current bounty value
|
||||
|
||||
void updateSkillArea();
|
||||
///< update display of skills, factions, birth sign, reputation and bounty
|
||||
|
||||
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.
|
||||
void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted.
|
||||
|
||||
void removeDialog(OEngine::GUI::Layout* dialog);
|
||||
///< Hides dialog and schedules dialog to be deleted.
|
||||
|
||||
void messageBox (const std::string& message, const std::vector<std::string>& buttons);
|
||||
|
||||
int readPressedButton ();
|
||||
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||
|
||||
int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||
|
||||
void onFrame (float frameDuration);
|
||||
|
||||
/**
|
||||
|
@ -267,54 +172,58 @@ namespace MWGui
|
|||
const ESMS::ESMStore& getStore() const;
|
||||
|
||||
private:
|
||||
OEngine::GUI::MyGUIManager *mGuiManager;
|
||||
MWWorld::Environment& environment;
|
||||
HUD *hud;
|
||||
MapWindow *map;
|
||||
MainMenu *menu;
|
||||
StatsWindow *stats;
|
||||
MessageBoxManager *mMessageBoxManager;
|
||||
Console *console;
|
||||
JournalWindow* mJournal;
|
||||
DialogueWindow *dialogueWindow;
|
||||
|
||||
CharacterCreation* mCharGen;
|
||||
|
||||
// Various stats about player as needed by window manager
|
||||
ESM::Class playerClass;
|
||||
std::string playerName;
|
||||
std::string playerRaceId;
|
||||
std::string playerBirthSignId;
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > playerAttributes;
|
||||
SkillList playerMajorSkills, playerMinorSkills;
|
||||
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > playerSkillValues;
|
||||
MWMechanics::DynamicStat<int> playerHealth, playerMagicka, playerFatigue;
|
||||
|
||||
|
||||
MyGUI::Gui *gui; // Gui
|
||||
GuiMode mode; // Current gui mode
|
||||
GuiMode nextMode; // Next mode to activate in update()
|
||||
bool needModeChange; //Whether a mode change is needed in update() [will use nextMode]
|
||||
|
||||
std::vector<OEngine::GUI::Layout*> garbageDialogs;
|
||||
void cleanupGarbage();
|
||||
|
||||
GuiWindow shown; // Currently shown windows in inventory mode
|
||||
|
||||
/* Currently ALLOWED windows in inventory mode. This is used at
|
||||
the start of the game, when windows are enabled one by one
|
||||
through script commands. You can manipulate this through using
|
||||
allow() and disableAll().
|
||||
|
||||
The setting should also affect visibility of certain HUD
|
||||
elements, but this is not done yet.
|
||||
*/
|
||||
GuiWindow allowed;
|
||||
|
||||
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
|
||||
|
||||
int showFPSLevel;
|
||||
float mFPS;
|
||||
size_t mTriangleCount;
|
||||
size_t mBatchCount;
|
||||
|
||||
void onDialogueWindowBye();
|
||||
|
||||
// Character generation: Name dialog
|
||||
void onNameDialogDone(WindowBase* parWindow);
|
||||
|
||||
// Character generation: Race dialog
|
||||
void onRaceDialogDone(WindowBase* parWindow);
|
||||
void onRaceDialogBack();
|
||||
|
||||
// Character generation: Choose class process
|
||||
void onClassChoice(int _index);
|
||||
|
||||
// Character generation: Generate Class
|
||||
void showClassQuestionDialog();
|
||||
void onClassQuestionChosen(int _index);
|
||||
void onGenerateClassBack();
|
||||
void onGenerateClassDone(WindowBase* parWindow);
|
||||
|
||||
// Character generation: Pick Class dialog
|
||||
void onPickClassDialogDone(WindowBase* parWindow);
|
||||
void onPickClassDialogBack();
|
||||
|
||||
// Character generation: Create Class dialog
|
||||
void onCreateClassDialogDone(WindowBase* parWindow);
|
||||
void onCreateClassDialogBack();
|
||||
|
||||
// Character generation: Birth sign dialog
|
||||
void onBirthSignDialogDone(WindowBase* parWindow);
|
||||
void onBirthSignDialogBack();
|
||||
|
||||
// Character generation: Review dialog
|
||||
void onReviewDialogDone(WindowBase* parWindow);
|
||||
void onReviewDialogBack();
|
||||
void onReviewActivateDialog(int parDialog);
|
||||
|
||||
enum CreationStageEnum
|
||||
{
|
||||
NotStarted,
|
||||
NameChosen,
|
||||
RaceChosen,
|
||||
ClassChosen,
|
||||
BirthSignChosen,
|
||||
ReviewNext
|
||||
};
|
||||
|
||||
// Which state the character creating is in, controls back/next/ok buttons
|
||||
CreationStageEnum creationStage;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -83,27 +83,14 @@ namespace MWInput
|
|||
MWGui::WindowManager &windows;
|
||||
OMW::Engine& mEngine;
|
||||
|
||||
// Count screenshots.
|
||||
int shotCount;
|
||||
|
||||
|
||||
/* InputImpl Methods */
|
||||
|
||||
// Write screenshot to file.
|
||||
void screenshot()
|
||||
{
|
||||
|
||||
// Find the first unused filename with a do-while
|
||||
char buf[50];
|
||||
do
|
||||
{
|
||||
snprintf(buf, 50, "screenshot%03d.png", shotCount++);
|
||||
} while (boost::filesystem::exists(buf));
|
||||
|
||||
ogre.screenshot(buf);
|
||||
mEngine.screenshot();
|
||||
}
|
||||
|
||||
|
||||
/* toggleInventory() is called when the user presses the button to toggle the inventory screen. */
|
||||
void toggleInventory()
|
||||
{
|
||||
|
@ -134,6 +121,21 @@ namespace MWInput
|
|||
else setGuiMode(GM_Console);
|
||||
}
|
||||
|
||||
void toggleJournal()
|
||||
{
|
||||
using namespace MWGui;
|
||||
|
||||
GuiMode mode = windows.getMode();
|
||||
|
||||
// Toggle between game mode and journal mode
|
||||
if(mode == GM_Game)
|
||||
setGuiMode(GM_Journal);
|
||||
else if(mode == GM_Journal)
|
||||
setGuiMode(GM_Game);
|
||||
|
||||
// .. but don't touch any other mode.
|
||||
}
|
||||
|
||||
void activate()
|
||||
{
|
||||
mEngine.activate();
|
||||
|
@ -168,8 +170,7 @@ namespace MWInput
|
|||
poller(input),
|
||||
player(_player),
|
||||
windows(_windows),
|
||||
mEngine (engine),
|
||||
shotCount(0)
|
||||
mEngine (engine)
|
||||
{
|
||||
using namespace OEngine::Input;
|
||||
using namespace OEngine::Render;
|
||||
|
@ -188,6 +189,8 @@ namespace MWInput
|
|||
"Toggle inventory screen");
|
||||
disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this),
|
||||
"Toggle console");
|
||||
disp->funcs.bind(A_Journal, boost::bind(&InputImpl::toggleJournal, this),
|
||||
"Toggle journal");
|
||||
disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this),
|
||||
"Activate");
|
||||
disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this),
|
||||
|
@ -236,6 +239,7 @@ namespace MWInput
|
|||
disp->bind(A_Screenshot, KC_SYSRQ);
|
||||
disp->bind(A_Inventory, KC_I);
|
||||
disp->bind(A_Console, KC_F1);
|
||||
disp->bind(A_Journal, KC_J);
|
||||
disp->bind(A_Activate, KC_SPACE);
|
||||
disp->bind(A_AutoMove, KC_Z);
|
||||
disp->bind(A_ToggleSneak, KC_X);
|
||||
|
|
|
@ -250,6 +250,7 @@ namespace MWMechanics
|
|||
while (iter!=mActors.end())
|
||||
if (iter->getCell()==cellStore)
|
||||
{
|
||||
//std::cout << "Erasing an actor";
|
||||
mActors.erase (iter++);
|
||||
}
|
||||
else
|
||||
|
|
125
apps/openmw/mwrender/actors.cpp
Normal file
125
apps/openmw/mwrender/actors.cpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include "actors.hpp"
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
using namespace NifOgre;
|
||||
|
||||
void Actors::setMwRoot(Ogre::SceneNode* root){
|
||||
mMwRoot = root;
|
||||
}
|
||||
void Actors::insertNPC(const MWWorld::Ptr& ptr){
|
||||
|
||||
insertBegin(ptr, true, true);
|
||||
NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend);
|
||||
|
||||
mAllActors[ptr] = anim;
|
||||
}
|
||||
void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
|
||||
Ogre::SceneNode* cellnode;
|
||||
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end())
|
||||
{
|
||||
//Create the scenenode and put it in the map
|
||||
cellnode = mMwRoot->createChildSceneNode();
|
||||
mCellSceneNodes[ptr.getCell()] = cellnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellnode = mCellSceneNodes[ptr.getCell()];
|
||||
}
|
||||
|
||||
Ogre::SceneNode* insert = cellnode->createChildSceneNode();
|
||||
const float *f = ptr.getRefData().getPosition().pos;
|
||||
insert->setPosition(f[0], f[1], f[2]);
|
||||
insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale);
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ptr.getCellRef().pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
insert->setOrientation(xr*yr*zr);
|
||||
if (!enabled)
|
||||
insert->setVisible (false);
|
||||
ptr.getRefData().setBaseNode(insert);
|
||||
|
||||
|
||||
}
|
||||
void Actors::insertCreature (const MWWorld::Ptr& ptr){
|
||||
|
||||
insertBegin(ptr, true, true);
|
||||
CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend);
|
||||
//mAllActors.insert(std::pair<MWWorld::Ptr, Animation*>(ptr,anim));
|
||||
mAllActors[ptr] = anim;
|
||||
//mAllActors.push_back(&anim);*/
|
||||
}
|
||||
|
||||
bool Actors::deleteObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
delete mAllActors[ptr];
|
||||
mAllActors.erase(ptr);
|
||||
if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode())
|
||||
{
|
||||
|
||||
Ogre::SceneNode *parent = base->getParentSceneNode();
|
||||
|
||||
for (std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::const_iterator iter (
|
||||
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
|
||||
if (iter->second==parent)
|
||||
{
|
||||
base->removeAndDestroyAllChildren();
|
||||
mRend.getScene()->destroySceneNode (base);
|
||||
ptr.getRefData().setBaseNode (0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Actors::removeCell(MWWorld::Ptr::CellStore* store){
|
||||
if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
|
||||
{
|
||||
Ogre::SceneNode* base = mCellSceneNodes[store];
|
||||
base->removeAndDestroyAllChildren();
|
||||
mCellSceneNodes.erase(store);
|
||||
mRend.getScene()->destroySceneNode(base);
|
||||
base = 0;
|
||||
}
|
||||
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||
{
|
||||
if(iter->first.getCell() == store){
|
||||
delete iter->second;
|
||||
mAllActors.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->startScript(groupName, mode, number);
|
||||
}
|
||||
void Actors::skipAnimation (const MWWorld::Ptr& ptr){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->stopScript();
|
||||
}
|
||||
void Actors::update (float duration){
|
||||
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||
{
|
||||
(iter->second)->runAnimation(duration);
|
||||
}
|
||||
}
|
59
apps/openmw/mwrender/actors.hpp
Normal file
59
apps/openmw/mwrender/actors.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef _GAME_RENDER_ACTORS_H
|
||||
#define _GAME_RENDER_ACTORS_H
|
||||
|
||||
#include "components/esm_store/cell_store.hpp"
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "npcanimation.hpp"
|
||||
#include "creatureanimation.hpp"
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
namespace MWRender{
|
||||
class Actors{
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||
Ogre::SceneNode* mMwRoot;
|
||||
MWWorld::Environment& mEnvironment;
|
||||
std::map<MWWorld::Ptr, Animation*> mAllActors;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){}
|
||||
~Actors(){}
|
||||
void setMwRoot(Ogre::SceneNode* root);
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertCreature (const MWWorld::Ptr& ptr);
|
||||
void insertNPC(const MWWorld::Ptr& ptr);
|
||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||
///< \return found?
|
||||
|
||||
void removeCell(MWWorld::Ptr::CellStore* store);
|
||||
|
||||
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
|
||||
int number = 1);
|
||||
///< Run animation for a MW-reference. Calls to this function for references that are currently not
|
||||
/// in the rendered scene should be ignored.
|
||||
///
|
||||
/// \param mode: 0 normal, 1 immediate start, 2 immediate loop
|
||||
/// \param number How offen the animation should be run
|
||||
|
||||
void skipAnimation (const MWWorld::Ptr& ptr);
|
||||
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
|
||||
/// references that are currently not in the rendered scene should be ignored.
|
||||
|
||||
void update (float duration);
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
477
apps/openmw/mwrender/animation.cpp
Normal file
477
apps/openmw/mwrender/animation.cpp
Normal file
|
@ -0,0 +1,477 @@
|
|||
#include "animation.hpp"
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
std::map<std::string, int> Animation::mUniqueIDs;
|
||||
|
||||
Animation::~Animation(){
|
||||
}
|
||||
|
||||
std::string Animation::getUniqueID(std::string mesh){
|
||||
int counter;
|
||||
std::string copy = mesh;
|
||||
std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
|
||||
if(mUniqueIDs.find(copy) == mUniqueIDs.end()){
|
||||
counter = mUniqueIDs[copy] = 0;
|
||||
}
|
||||
else{
|
||||
mUniqueIDs[copy] = mUniqueIDs[copy] + 1;
|
||||
counter = mUniqueIDs[copy];
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
if(counter > 99 && counter < 1000)
|
||||
out << "0";
|
||||
else if(counter > 9)
|
||||
out << "00";
|
||||
else
|
||||
out << "000";
|
||||
out << counter;
|
||||
return out.str();
|
||||
}
|
||||
void Animation::startScript(std::string groupname, int mode, int loops){
|
||||
//If groupname is recognized set animate to true
|
||||
//Set the start time and stop time
|
||||
//How many times to loop
|
||||
if(groupname == "all"){
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
}
|
||||
else if(textmappings){
|
||||
|
||||
std::string startName = groupname + ": loop start";
|
||||
std::string stopName = groupname + ": loop stop";
|
||||
|
||||
bool first = false;
|
||||
|
||||
if(loops > 1){
|
||||
startName = groupname + ": loop start";
|
||||
stopName = groupname + ": loop stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName){
|
||||
startTime = iter->second;
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName){
|
||||
stopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!first){
|
||||
startName = groupname + ": start";
|
||||
stopName = groupname + ": stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName){
|
||||
startTime = iter->second;
|
||||
animate = loops;
|
||||
time = startTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName){
|
||||
stopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void Animation::stopScript(){
|
||||
animate = 0;
|
||||
}
|
||||
|
||||
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
|
||||
shapeNumber = 0;
|
||||
|
||||
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
||||
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
||||
|
||||
{
|
||||
//std::map<unsigned short, PosAndRot> vecPosRot;
|
||||
|
||||
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
||||
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
||||
std::vector<Ogre::Vector3>* allnormals = ©.normals;
|
||||
|
||||
|
||||
|
||||
//std::set<unsigned int> vertices;
|
||||
//std::set<unsigned int> normals;
|
||||
//std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfovector = copy.boneinfo;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >* verticesToChange = ©.vertsToWeights;
|
||||
|
||||
//std::cout << "Name " << copy.sname << "\n";
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0);
|
||||
Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||
|
||||
|
||||
std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices();
|
||||
//Each shape has multiple indices
|
||||
if(initialVertices.size() )
|
||||
{
|
||||
|
||||
if(copy.vertices.size() == initialVertices.size())
|
||||
{
|
||||
//Create if it doesn't already exist
|
||||
if(shapeIndexI.size() == static_cast<std::size_t> (shapeNumber))
|
||||
{
|
||||
std::vector<int> vec;
|
||||
shapeIndexI.push_back(vec);
|
||||
}
|
||||
if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){
|
||||
float x;
|
||||
for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){
|
||||
int j = 0;
|
||||
if(shapeIndexI[shapeNumber].size() <= i)
|
||||
shapeIndexI[shapeNumber].push_back(0);
|
||||
|
||||
|
||||
if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){
|
||||
int indexI = (shapeIndexI[shapeNumber])[i];
|
||||
std::vector<Ogre::Vector3> relevantData = (copy.morph.getRelevantData()[i]);
|
||||
float v1 = relevantData[indexI].x;
|
||||
float v2 = relevantData[j].x;
|
||||
float t = v1 + (v2 - v1) * x;
|
||||
if ( t < 0 ) t = 0;
|
||||
if ( t > 1 ) t = 1;
|
||||
if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size())
|
||||
{
|
||||
for (unsigned int v = 0; v < initialVertices.size(); v++){
|
||||
initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
allvertices = &initialVertices;
|
||||
}
|
||||
shapeNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(verticesToChange->size() > 0){
|
||||
|
||||
for(std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >::iterator iter = verticesToChange->begin();
|
||||
iter != verticesToChange->end(); iter++)
|
||||
{
|
||||
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
|
||||
int verIndex = iter->first;
|
||||
Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
|
||||
Ogre::Vector3 currentNormal = (*allnormals)[verIndex];
|
||||
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
|
||||
Ogre::Bone *bonePtr = 0;
|
||||
|
||||
|
||||
|
||||
Ogre::Vector3 vecPos;
|
||||
Ogre::Quaternion vecRot;
|
||||
std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot>::iterator result = vecRotPos.find(boneinfocopy);
|
||||
|
||||
if(result == vecRotPos.end()){
|
||||
bonePtr = skel->getBone(boneinfocopy->bonename);
|
||||
|
||||
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
|
||||
PosAndRot both;
|
||||
both.vecPos = vecPos;
|
||||
both.vecRot = vecRot;
|
||||
vecRotPos[boneinfocopy] = both;
|
||||
|
||||
}
|
||||
else{
|
||||
PosAndRot both = result->second;
|
||||
vecPos = both.vecPos;
|
||||
vecRot = both.vecRot;
|
||||
}
|
||||
|
||||
Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight;
|
||||
|
||||
|
||||
|
||||
for(std::size_t i = 1; i < inds.size(); i++){
|
||||
boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]);
|
||||
result = vecRotPos.find(boneinfocopy);
|
||||
|
||||
|
||||
if(result == vecRotPos.end()){
|
||||
bonePtr = skel->getBone(boneinfocopy->bonename);
|
||||
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
|
||||
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
|
||||
|
||||
PosAndRot both;
|
||||
both.vecPos = vecPos;
|
||||
both.vecRot = vecRot;
|
||||
vecRotPos[boneinfocopy] = both;
|
||||
|
||||
}
|
||||
else{
|
||||
PosAndRot both = result->second;
|
||||
vecPos = both.vecPos;
|
||||
vecRot = both.vecRot;
|
||||
}
|
||||
|
||||
|
||||
absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight;
|
||||
|
||||
|
||||
}
|
||||
Ogre::Real* addr = (pReal + 3 * verIndex);
|
||||
*addr = absVertPos.x;
|
||||
*(addr+1) = absVertPos.y;
|
||||
*(addr+2) = absVertPos.z;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename);
|
||||
Ogre::Quaternion shaperot = copy.trafo.rotation;
|
||||
Ogre::Vector3 shapetrans = copy.trafo.trans;
|
||||
float shapescale = copy.trafo.scale;
|
||||
std::vector<std::string> boneSequence = copy.boneSequence;
|
||||
|
||||
Ogre::Vector3 transmult;
|
||||
Ogre::Quaternion rotmult;
|
||||
float scale;
|
||||
if(boneSequence.size() > 0){
|
||||
std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin();
|
||||
if(skel->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter);
|
||||
|
||||
|
||||
|
||||
|
||||
transmult = bonePtr->getPosition();
|
||||
rotmult = bonePtr->getOrientation();
|
||||
scale = bonePtr->getScale().x;
|
||||
boneSequenceIter++;
|
||||
for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++)
|
||||
{
|
||||
if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(*boneSequenceIter);
|
||||
// Computes C = B + AxC*scale
|
||||
transmult = transmult + rotmult * bonePtr->getPosition();
|
||||
rotmult = rotmult * bonePtr->getOrientation();
|
||||
scale = scale * bonePtr->getScale().x;
|
||||
}
|
||||
//std::cout << "Bone:" << *boneSequenceIter << " ";
|
||||
}
|
||||
transmult = transmult + rotmult * shapetrans;
|
||||
rotmult = rotmult * shaperot;
|
||||
scale = shapescale * scale;
|
||||
|
||||
//std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transmult = shapetrans;
|
||||
rotmult = shaperot;
|
||||
scale = shapescale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Computes C = B + AxC*scale
|
||||
// final_vector = old_vector + old_rotation*new_vector*old_scale/
|
||||
|
||||
for(unsigned int i = 0; i < allvertices->size(); i++){
|
||||
Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i];
|
||||
Ogre::Real* addr = pReal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}/*
|
||||
for(int i = 0; i < allnormals.size(); i++){
|
||||
Ogre::Vector3 current =rotmult * allnormals[i];
|
||||
Ogre::Real* addr = pRealNormal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}*/
|
||||
|
||||
}
|
||||
vbuf->unlock();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
bool Animation::timeIndex( float time, std::vector<float> times, int & i, int & j, float & x ){
|
||||
int count;
|
||||
if ( (count = times.size()) > 0 )
|
||||
{
|
||||
if ( time <= times[0] )
|
||||
{
|
||||
i = j = 0;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
if ( time >= times[count - 1] )
|
||||
{
|
||||
i = j = count - 1;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( i < 0 || i >= count )
|
||||
i = 0;
|
||||
|
||||
float tI = times[i];
|
||||
if ( time > tI )
|
||||
{
|
||||
j = i + 1;
|
||||
float tJ;
|
||||
while ( time >= ( tJ = times[j]) )
|
||||
{
|
||||
i = j++;
|
||||
tI = tJ;
|
||||
}
|
||||
x = ( time - tI ) / ( tJ - tI );
|
||||
return true;
|
||||
}
|
||||
else if ( time < tI )
|
||||
{
|
||||
j = i - 1;
|
||||
float tJ;
|
||||
while ( time <= ( tJ = times[j] ) )
|
||||
{
|
||||
i = j--;
|
||||
tI = tJ;
|
||||
}
|
||||
x = ( time - tI ) / ( tJ - tI );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = i;
|
||||
x = 0.0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void Animation::handleAnimationTransforms(){
|
||||
Ogre::SkeletonInstance* skel = base->getSkeleton();
|
||||
|
||||
|
||||
Ogre::Bone* b = skel->getRootBone();
|
||||
b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick
|
||||
|
||||
skel->_updateTransforms();
|
||||
//skel->_notifyManualBonesDirty();
|
||||
|
||||
base->getAllAnimationStates()->_notifyDirty();
|
||||
//base->_updateAnimation();
|
||||
//base->_notifyMoved();
|
||||
|
||||
for(unsigned int i = 0; i < entityparts.size(); i++){
|
||||
//Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton();
|
||||
|
||||
Ogre::Bone* b = skel->getRootBone();
|
||||
b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick
|
||||
|
||||
entityparts[i]->getAllAnimationStates()->_notifyDirty();
|
||||
}
|
||||
|
||||
|
||||
std::vector<Nif::NiKeyframeData>::iterator iter;
|
||||
int slot = 0;
|
||||
if(transformations){
|
||||
for(iter = transformations->begin(); iter != transformations->end(); iter++){
|
||||
if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime())
|
||||
{
|
||||
slot++;
|
||||
continue;
|
||||
}
|
||||
|
||||
float x;
|
||||
float x2;
|
||||
|
||||
std::vector<Ogre::Quaternion> quats = iter->getQuat();
|
||||
|
||||
std::vector<float> ttime = iter->gettTime();
|
||||
std::vector<float>::iterator ttimeiter = ttime.begin();
|
||||
|
||||
std::vector<float> rtime = iter->getrTime();
|
||||
int rindexJ = 0;
|
||||
timeIndex(time, rtime, rindexI[slot], rindexJ, x2);
|
||||
int tindexJ = 0;
|
||||
|
||||
|
||||
std::vector<Ogre::Vector3> translist1 = iter->getTranslist1();
|
||||
|
||||
timeIndex(time, ttime, tindexI[slot], tindexJ, x);
|
||||
|
||||
Ogre::Vector3 t;
|
||||
Ogre::Quaternion r;
|
||||
|
||||
bool bTrans = translist1.size() > 0;
|
||||
if(bTrans){
|
||||
Ogre::Vector3 v1 = translist1[tindexI[slot]];
|
||||
Ogre::Vector3 v2 = translist1[tindexJ];
|
||||
t = (v1 + (v2 - v1) * x);
|
||||
|
||||
}
|
||||
|
||||
bool bQuats = quats.size() > 0;
|
||||
if(bQuats){
|
||||
r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true);
|
||||
}
|
||||
skel = base->getSkeleton();
|
||||
if(skel->hasBone(iter->getBonename())){
|
||||
Ogre::Bone* bone = skel->getBone(iter->getBonename());
|
||||
if(bTrans)
|
||||
bone->setPosition(t);
|
||||
if(bQuats)
|
||||
bone->setOrientation(r);
|
||||
|
||||
|
||||
|
||||
skel->_updateTransforms();
|
||||
base->getAllAnimationStates()->_notifyDirty();
|
||||
|
||||
}
|
||||
|
||||
slot++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
72
apps/openmw/mwrender/animation.hpp
Normal file
72
apps/openmw/mwrender/animation.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef _GAME_RENDER_ANIMATION_H
|
||||
#define _GAME_RENDER_ANIMATION_H
|
||||
#include <components/nif/data.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
#include <map>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
struct PosAndRot{
|
||||
Ogre::Quaternion vecRot;
|
||||
Ogre::Vector3 vecPos;
|
||||
};
|
||||
|
||||
class Animation{
|
||||
|
||||
protected:
|
||||
Ogre::SceneNode* insert;
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
MWWorld::Environment& mEnvironment;
|
||||
std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot> vecRotPos;
|
||||
static std::map<std::string, int> mUniqueIDs;
|
||||
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>* > shapeparts; //All the NiTriShape data that we need for animating an npc
|
||||
|
||||
float time;
|
||||
float startTime;
|
||||
float stopTime;
|
||||
int animate;
|
||||
//Represents a rotation index for each bone
|
||||
std::vector<int>rindexI;
|
||||
//Represents a translation index for each bone
|
||||
std::vector<int>tindexI;
|
||||
|
||||
//Only shapes with morphing data will use a shape number
|
||||
int shapeNumber;
|
||||
std::vector<std::vector<int> > shapeIndexI;
|
||||
|
||||
//Ogre::SkeletonInstance* skel;
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes; //All the NiTriShapeData for a creature
|
||||
std::vector<Ogre::Entity*> entityparts;
|
||||
|
||||
|
||||
std::vector<Nif::NiKeyframeData>* transformations;
|
||||
std::map<std::string,float>* textmappings;
|
||||
Ogre::Entity* base;
|
||||
void handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel);
|
||||
void handleAnimationTransforms();
|
||||
bool timeIndex( float time, std::vector<float> times, int & i, int & j, float & x );
|
||||
std::string getUniqueID(std::string mesh);
|
||||
|
||||
public:
|
||||
Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend): mRend(_rend), mEnvironment(_env), animate(0){};
|
||||
virtual void runAnimation(float timepassed) = 0;
|
||||
void startScript(std::string groupname, int mode, int loops);
|
||||
void stopScript();
|
||||
|
||||
|
||||
~Animation();
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
63
apps/openmw/mwrender/creatureanimation.cpp
Normal file
63
apps/openmw/mwrender/creatureanimation.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include "creatureanimation.hpp"
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace NifOgre;
|
||||
namespace MWRender{
|
||||
|
||||
CreatureAnimation::~CreatureAnimation(){
|
||||
|
||||
}
|
||||
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){
|
||||
insert = ptr.getRefData().getBaseNode();
|
||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
assert (ref->base != NULL);
|
||||
if(!ref->base->model.empty()){
|
||||
const std::string &mesh = "meshes\\" + ref->base->model;
|
||||
std::string meshNumbered = mesh + getUniqueID(mesh) + ">|";
|
||||
NifOgre::NIFLoader::load(meshNumbered);
|
||||
base = mRend.getScene()->createEntity(meshNumbered);
|
||||
std::string meshZero = mesh + "0000>|";
|
||||
|
||||
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){
|
||||
|
||||
for(std::size_t init = 0; init < transformations->size(); init++){
|
||||
rindexI.push_back(0);
|
||||
tindexI.push_back(0);
|
||||
}
|
||||
stopTime = transformations->begin()->getStopTime();
|
||||
startTime = transformations->begin()->getStartTime();
|
||||
shapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero);
|
||||
}
|
||||
textmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero);
|
||||
insert->attachObject(base);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureAnimation::runAnimation(float timepassed){
|
||||
vecRotPos.clear();
|
||||
if(animate > 0){
|
||||
//Add the amount of time passed to time
|
||||
|
||||
//Handle the animation transforms dependent on time
|
||||
|
||||
//Handle the shapes dependent on animation transforms
|
||||
time += timepassed;
|
||||
if(time >= stopTime){
|
||||
animate--;
|
||||
//std::cout << "Stopping the animation\n";
|
||||
if(animate == 0)
|
||||
time = stopTime;
|
||||
else
|
||||
time = startTime + (time - stopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
handleShapes(shapes, base, base->getSkeleton());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
26
apps/openmw/mwrender/creatureanimation.hpp
Normal file
26
apps/openmw/mwrender/creatureanimation.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef _GAME_RENDER_CREATUREANIMATION_H
|
||||
#define _GAME_RENDER_CREATUREANIMATION_H
|
||||
|
||||
#include "animation.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class CreatureAnimation: public Animation{
|
||||
|
||||
public:
|
||||
~CreatureAnimation();
|
||||
CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||
virtual void runAnimation(float timepassed);
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
#include "creatures.hpp"
|
||||
using namespace MWRender;
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef _GAME_RENDER_CREATURES_H
|
||||
#define _GAME_RENDER_CREATURES_H
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
namespace MWRender{
|
||||
class Creatures{
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
282
apps/openmw/mwrender/npcanimation.cpp
Normal file
282
apps/openmw/mwrender/npcanimation.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
#include "npcanimation.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace NifOgre;
|
||||
namespace MWRender{
|
||||
NpcAnimation::~NpcAnimation(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::NPC>();
|
||||
|
||||
//Part selection on last character of the file string
|
||||
// " Tri Chest
|
||||
// * Tri Tail
|
||||
// : Tri Left Foot
|
||||
// < Tri Right Foot
|
||||
// > Tri Left Hand
|
||||
// ? Tri Right Hand
|
||||
// | Normal
|
||||
|
||||
//Mirroring Parts on second to last character
|
||||
//suffix == '*'
|
||||
// vector = Ogre::Vector3(-1,1,1);
|
||||
// suffix == '?'
|
||||
// vector = Ogre::Vector3(1,-1,1);
|
||||
// suffix == '<'
|
||||
// vector = Ogre::Vector3(1,1,-1);
|
||||
|
||||
|
||||
std::string hairID = ref->base->hair;
|
||||
std::string headID = ref->base->head;
|
||||
std::string npcName = ref->base->name;
|
||||
//ESMStore::Races r =
|
||||
const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race);
|
||||
|
||||
|
||||
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||
char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2);
|
||||
bool female = tolower(secondtolast) == 'f';
|
||||
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||
|
||||
/*std::cout << "Race: " << ref->base->race ;
|
||||
if(female){
|
||||
std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n";
|
||||
}
|
||||
else{
|
||||
std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n";
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
std::string smodel = "meshes\\base_anim.nif";
|
||||
if(beast)
|
||||
smodel = "meshes\\base_animkna.nif";
|
||||
|
||||
insert = ptr.getRefData().getBaseNode();
|
||||
assert(insert);
|
||||
|
||||
NifOgre::NIFLoader::load(smodel);
|
||||
|
||||
base = mRend.getScene()->createEntity(smodel);
|
||||
base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones
|
||||
//stay in the same place when we skipanim, or open a gui window
|
||||
|
||||
|
||||
|
||||
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){
|
||||
|
||||
for(unsigned int init = 0; init < transformations->size(); init++){
|
||||
rindexI.push_back(0);
|
||||
tindexI.push_back(0);
|
||||
}
|
||||
|
||||
stopTime = transformations->begin()->getStopTime();
|
||||
startTime = transformations->begin()->getStartTime();
|
||||
}
|
||||
textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel);
|
||||
insert->attachObject(base);
|
||||
|
||||
if(female)
|
||||
insert->scale(race->data.height.female, race->data.height.female, race->data.height.female);
|
||||
else
|
||||
insert->scale(race->data.height.male, race->data.height.male, race->data.height.male);
|
||||
std::string headModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(headID)->model;
|
||||
|
||||
std::string hairModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model;
|
||||
const ESM::BodyPart *chest = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
|
||||
const ESM::BodyPart *upperleg = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||
const ESM::BodyPart *groin = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
||||
const ESM::BodyPart *arml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); //We need two
|
||||
const ESM::BodyPart *neck = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck");
|
||||
const ESM::BodyPart *knee = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
|
||||
const ESM::BodyPart *ankle = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
|
||||
const ESM::BodyPart *foot = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
|
||||
const ESM::BodyPart *feet = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
|
||||
const ESM::BodyPart *tail = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail");
|
||||
const ESM::BodyPart *wristl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); //We need two
|
||||
const ESM::BodyPart *forearml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); //We need two
|
||||
const ESM::BodyPart *handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand"); //We need two
|
||||
const ESM::BodyPart *hair = mEnvironment.mWorld->getStore().bodyParts.search(hairID);
|
||||
const ESM::BodyPart *head = mEnvironment.mWorld->getStore().bodyParts.search(headID);
|
||||
if(bodyRaceID == "b_n_argonian_f_")
|
||||
forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two
|
||||
if(!handl)
|
||||
handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands");
|
||||
//const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle");
|
||||
//const ESM::BodyPart* clavicler = claviclel;
|
||||
const ESM::BodyPart* handr = handl;
|
||||
const ESM::BodyPart* forearmr = forearml;
|
||||
const ESM::BodyPart* wristr = wristl;
|
||||
const ESM::BodyPart* armr = arml;
|
||||
|
||||
|
||||
if(upperleg){
|
||||
insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg");
|
||||
insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg");
|
||||
|
||||
}
|
||||
if(foot){
|
||||
if(bodyRaceID.compare("b_n_khajiit_m_") == 0)
|
||||
{
|
||||
feet = foot;
|
||||
}
|
||||
else
|
||||
{
|
||||
insertBoundedPart("meshes\\" + foot->model, "Right Foot");
|
||||
insertBoundedPart("meshes\\" + foot->model + "*|", "Left Foot");
|
||||
}
|
||||
}
|
||||
if(groin){
|
||||
insertBoundedPart("meshes\\" + groin->model, "Groin");
|
||||
}
|
||||
if(knee)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e
|
||||
insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e
|
||||
|
||||
}
|
||||
if(ankle){
|
||||
|
||||
insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank);
|
||||
insertBoundedPart("meshes\\" + ankle->model, "Right Ankle");
|
||||
}
|
||||
if (armr){
|
||||
insertBoundedPart("meshes\\" + armr->model, "Right Upper Arm");
|
||||
}
|
||||
if(arml){
|
||||
insertBoundedPart("meshes\\" + arml->model + "*|", "Left Upper Arm");
|
||||
}
|
||||
|
||||
if (forearmr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + forearmr->model, "Right Forearm");
|
||||
}
|
||||
if(forearml)
|
||||
insertBoundedPart("meshes\\" + forearml->model + "*|", "Left Forearm");
|
||||
|
||||
if (wristr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + wristr->model, "Right Wrist");
|
||||
}
|
||||
|
||||
if(wristl)
|
||||
insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*if(claviclel)
|
||||
insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base);
|
||||
if(clavicler)
|
||||
insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/
|
||||
|
||||
if(neck)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + neck->model, "Neck");
|
||||
}
|
||||
if(head)
|
||||
insertBoundedPart("meshes\\" + head->model, "Head");
|
||||
if(hair)
|
||||
insertBoundedPart("meshes\\" + hair->model, "Head");
|
||||
|
||||
if (chest){
|
||||
insertFreePart("meshes\\" + chest->model, ">\"", insert);
|
||||
|
||||
|
||||
}
|
||||
if (handr){
|
||||
insertFreePart("meshes\\" + handr->model , ">?", insert);
|
||||
|
||||
}
|
||||
if (handl){
|
||||
insertFreePart("meshes\\" + handl->model, ">>", insert);
|
||||
|
||||
}
|
||||
if(tail){
|
||||
insertFreePart("meshes\\" + tail->model, ">*", insert);
|
||||
}
|
||||
if(feet){
|
||||
std::string num = getUniqueID(feet->model);
|
||||
insertFreePart("meshes\\" + feet->model,"><", insert);
|
||||
insertFreePart("meshes\\" + feet->model,">:", insert);
|
||||
}
|
||||
//originalpos = insert->_getWorldAABB().getCenter();
|
||||
//originalscenenode = insert->getPosition();
|
||||
}
|
||||
|
||||
Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){
|
||||
|
||||
NIFLoader::load(mesh);
|
||||
Entity* ent = mRend.getScene()->createEntity(mesh);
|
||||
|
||||
base->attachObjectToBone(bonename, ent);
|
||||
return ent;
|
||||
}
|
||||
void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){
|
||||
std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix;
|
||||
NIFLoader::load(meshNumbered);
|
||||
|
||||
Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered);
|
||||
|
||||
|
||||
|
||||
|
||||
insert->attachObject(ent);
|
||||
entityparts.push_back(ent);
|
||||
shapes = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix));
|
||||
if(shapes){
|
||||
shapeparts.push_back(shapes);
|
||||
handleShapes(shapes, ent, base->getSkeleton());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void NpcAnimation::runAnimation(float timepassed){
|
||||
|
||||
//1. Add the amount of time passed to time
|
||||
|
||||
//2. Handle the animation transforms dependent on time
|
||||
|
||||
//3. Handle the shapes dependent on animation transforms
|
||||
if(animate > 0){
|
||||
time += timepassed;
|
||||
|
||||
if(time > stopTime){
|
||||
animate--;
|
||||
|
||||
if(animate == 0)
|
||||
time = stopTime;
|
||||
else
|
||||
time = startTime + (time - stopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin();
|
||||
std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin();
|
||||
while(shapepartsiter != shapeparts.end())
|
||||
{
|
||||
vecRotPos.clear();
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter;
|
||||
Ogre::Entity* theentity = *entitypartsiter;
|
||||
|
||||
|
||||
handleShapes(shapes, theentity, base->getSkeleton());
|
||||
shapepartsiter++;
|
||||
entitypartsiter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
30
apps/openmw/mwrender/npcanimation.hpp
Normal file
30
apps/openmw/mwrender/npcanimation.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef _GAME_RENDER_NPCANIMATION_H
|
||||
#define _GAME_RENDER_NPCANIMATION_H
|
||||
#include "animation.hpp"
|
||||
#include <components/nif/data.hpp>
|
||||
#include <components/nif/node.hpp>
|
||||
#include <components/nif/property.hpp>
|
||||
#include <components/nif/controller.hpp>
|
||||
#include <components/nif/extra.hpp>
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class NpcAnimation: public Animation{
|
||||
|
||||
|
||||
|
||||
public:
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||
~NpcAnimation();
|
||||
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
|
||||
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
|
||||
virtual void runAnimation(float timepassed);
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
#include "npcs.hpp"
|
||||
using namespace MWRender;
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef _GAME_RENDER_NPCS_H
|
||||
#define _GAME_RENDER_NPCS_H
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
namespace MWRender{
|
||||
class Npcs{
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -1,11 +1,11 @@
|
|||
#include "objects.hpp"
|
||||
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
|
||||
bool Objects::lightConst = false;
|
||||
float Objects::lightConstValue = 0.0f;
|
||||
|
||||
|
@ -23,11 +23,25 @@ bool Objects::lightOutQuadInLin = false;
|
|||
|
||||
int Objects::uniqueID = 0;
|
||||
|
||||
void Objects::setMwRoot(Ogre::SceneNode* root){
|
||||
mwRoot = root;
|
||||
void Objects::clearSceneNode (Ogre::SceneNode *node)
|
||||
{
|
||||
/// \todo This should probably be moved into OpenEngine at some point.
|
||||
for (int i=node->numAttachedObjects()-1; i>=0; --i)
|
||||
{
|
||||
Ogre::MovableObject *object = node->getAttachedObject (i);
|
||||
node->detachObject (object);
|
||||
mRenderer.getScene()->destroyMovableObject (object);
|
||||
}
|
||||
}
|
||||
void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
|
||||
Ogre::SceneNode* root = mwRoot;
|
||||
|
||||
void Objects::setMwRoot(Ogre::SceneNode* root)
|
||||
{
|
||||
mMwRoot = root;
|
||||
}
|
||||
|
||||
void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_)
|
||||
{
|
||||
Ogre::SceneNode* root = mMwRoot;
|
||||
Ogre::SceneNode* cellnode;
|
||||
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end())
|
||||
{
|
||||
|
@ -49,90 +63,91 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
|
|||
f = ptr.getCellRef().pos.rot;
|
||||
|
||||
// Rotate around X axis
|
||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||
Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X);
|
||||
|
||||
// Rotate around Y axis
|
||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||
Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y);
|
||||
|
||||
// Rotate around Z axis
|
||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||
Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z);
|
||||
|
||||
// Rotates first around z, then y, then x
|
||||
// Rotates first around z, then y, then x
|
||||
insert->setOrientation(xr*yr*zr);
|
||||
|
||||
if (!enabled)
|
||||
insert->setVisible (false);
|
||||
ptr.getRefData().setBaseNode(insert);
|
||||
isStatic = static_;
|
||||
|
||||
|
||||
mIsStatic = static_;
|
||||
}
|
||||
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){
|
||||
|
||||
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||
{
|
||||
Ogre::SceneNode* insert = ptr.getRefData().getBaseNode();
|
||||
assert(insert);
|
||||
|
||||
NifOgre::NIFLoader::load(mesh);
|
||||
Entity *ent = mRend.getScene()->createEntity(mesh);
|
||||
Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh);
|
||||
|
||||
if(!isStatic)
|
||||
if(!mIsStatic)
|
||||
{
|
||||
insert->attachObject(ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::StaticGeometry* sg = 0;
|
||||
if(mSG.find(ptr.getCell()) == mSG.end())
|
||||
if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end())
|
||||
{
|
||||
uniqueID = uniqueID +1;
|
||||
sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||
sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||
//Create the scenenode and put it in the map
|
||||
mSG[ptr.getCell()] = sg;
|
||||
mStaticGeometry[ptr.getCell()] = sg;
|
||||
}
|
||||
else
|
||||
{
|
||||
sg = mSG[ptr.getCell()];
|
||||
sg = mStaticGeometry[ptr.getCell()];
|
||||
}
|
||||
|
||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||
sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000));
|
||||
|
||||
|
||||
mRend.getScene()->destroyEntity(ent);
|
||||
mRenderer.getScene()->destroyEntity(ent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){
|
||||
Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle());
|
||||
|
||||
void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius)
|
||||
{
|
||||
Ogre::SceneNode* insert = mRenderer.getScene()->getSceneNode(ptr.getRefData().getHandle());
|
||||
assert(insert);
|
||||
Ogre::Light *light = mRend.getScene()->createLight();
|
||||
Ogre::Light *light = mRenderer.getScene()->createLight();
|
||||
light->setDiffuseColour (r, g, b);
|
||||
|
||||
float cval=0.0f, lval=0.0f, qval=0.0f;
|
||||
|
||||
if(lightConst)
|
||||
cval = lightConstValue;
|
||||
if(!lightOutQuadInLin)
|
||||
{
|
||||
if(lightLinear)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
}
|
||||
if(!lightOutQuadInLin)
|
||||
{
|
||||
if(lightLinear)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
}
|
||||
|
||||
insert->attachObject(light);
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
|
||||
insert->attachObject(light);
|
||||
}
|
||||
|
||||
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
||||
|
@ -145,8 +160,9 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
|||
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
|
||||
if (iter->second==parent)
|
||||
{
|
||||
clearSceneNode (base);
|
||||
base->removeAndDestroyAllChildren();
|
||||
mRend.getScene()->destroySceneNode (base);
|
||||
mRenderer.getScene()->destroySceneNode (base);
|
||||
ptr.getRefData().setBaseNode (0);
|
||||
return true;
|
||||
}
|
||||
|
@ -157,29 +173,35 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Objects::removeCell(MWWorld::Ptr::CellStore* store){
|
||||
void Objects::removeCell(MWWorld::Ptr::CellStore* store)
|
||||
{
|
||||
if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
|
||||
{
|
||||
Ogre::SceneNode* base = mCellSceneNodes[store];
|
||||
|
||||
for (int i=0; i<base->numChildren(); ++i)
|
||||
clearSceneNode (static_cast<Ogre::SceneNode *> (base->getChild (i)));
|
||||
|
||||
base->removeAndDestroyAllChildren();
|
||||
mCellSceneNodes.erase(store);
|
||||
mRend.getScene()->destroySceneNode(base);
|
||||
mRenderer.getScene()->destroySceneNode(base);
|
||||
base = 0;
|
||||
}
|
||||
|
||||
|
||||
if(mSG.find(store) != mSG.end())
|
||||
if(mStaticGeometry.find(store) != mStaticGeometry.end())
|
||||
{
|
||||
Ogre::StaticGeometry* sg = mSG[store];
|
||||
mSG.erase(store);
|
||||
mRend.getScene()->destroyStaticGeometry (sg);
|
||||
Ogre::StaticGeometry* sg = mStaticGeometry[store];
|
||||
mStaticGeometry.erase(store);
|
||||
mRenderer.getScene()->destroyStaticGeometry (sg);
|
||||
sg = 0;
|
||||
}
|
||||
}
|
||||
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell){
|
||||
if(mSG.find(&cell) != mSG.end())
|
||||
|
||||
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
||||
{
|
||||
if(mStaticGeometry.find(&cell) != mStaticGeometry.end())
|
||||
{
|
||||
Ogre::StaticGeometry* sg = mSG[&cell];
|
||||
Ogre::StaticGeometry* sg = mStaticGeometry[&cell];
|
||||
sg->build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
#ifndef _GAME_RENDER_OBJECTS_H
|
||||
#define _GAME_RENDER_OBJECTS_H
|
||||
|
||||
#include "components/esm_store/cell_store.hpp"
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
#include <components/esm_store/cell_store.hpp>
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class Objects{
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
OEngine::Render::OgreRenderer &mRenderer;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mSG;
|
||||
Ogre::SceneNode* mwRoot;
|
||||
bool isStatic;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
||||
Ogre::SceneNode* mMwRoot;
|
||||
bool mIsStatic;
|
||||
static int uniqueID;
|
||||
static bool lightConst;
|
||||
static float lightConstValue;
|
||||
|
@ -30,8 +31,12 @@ class Objects{
|
|||
static float lightQuadraticRadiusMult;
|
||||
|
||||
static bool lightOutQuadInLin;
|
||||
|
||||
void clearSceneNode (Ogre::SceneNode *node);
|
||||
///< Remove all movable objects from \a node.
|
||||
|
||||
public:
|
||||
Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){}
|
||||
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){}
|
||||
~Objects(){}
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#ifndef _GAME_RENDERING_INTERFACE_H
|
||||
#define _GAME_RENDERING_INTERFACE_H
|
||||
namespace MWRender{
|
||||
class Npcs;
|
||||
class Creatures;
|
||||
class Objects;
|
||||
class Actors;
|
||||
class Player;
|
||||
|
||||
class RenderingInterface{
|
||||
public:
|
||||
virtual MWRender::Npcs& getNPCs() = 0;
|
||||
virtual MWRender::Creatures& getCreatures() = 0;
|
||||
virtual MWRender::Objects& getObjects() = 0;
|
||||
virtual MWRender::Player& getPlayer() = 0;
|
||||
virtual MWRender::Actors& getActors() = 0;
|
||||
virtual ~RenderingInterface(){};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,14 +19,11 @@ using namespace Ogre;
|
|||
|
||||
namespace MWRender {
|
||||
|
||||
|
||||
|
||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine)
|
||||
:rend(_rend), objects(rend), mDebugging(engine)
|
||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
|
||||
{
|
||||
rend.createScene("PlayerCam", 55, 5);
|
||||
mSkyManager = MWRender::SkyManager::create(rend.getWindow(), rend.getCamera(), resDir);
|
||||
mTerrainManager = new TerrainManager(rend.getScene());
|
||||
mRendering.createScene("PlayerCam", 55, 5);
|
||||
mTerrainManager = new TerrainManager(mRendering.getScene());
|
||||
|
||||
// Set default mipmap level (NB some APIs ignore this)
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(5);
|
||||
|
@ -39,52 +36,67 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
// the screen (when x is to the right.) This is the orientation that
|
||||
// Morrowind uses, and it automagically makes everything work as it
|
||||
// should.
|
||||
SceneNode *rt = rend.getScene()->getRootSceneNode();
|
||||
mwRoot = rt->createChildSceneNode();
|
||||
mwRoot->pitch(Degree(-90));
|
||||
objects.setMwRoot(mwRoot);
|
||||
|
||||
SceneNode *rt = mRendering.getScene()->getRootSceneNode();
|
||||
mMwRoot = rt->createChildSceneNode();
|
||||
mMwRoot->pitch(Degree(-90));
|
||||
mObjects.setMwRoot(mMwRoot);
|
||||
mActors.setMwRoot(mMwRoot);
|
||||
|
||||
//used to obtain ingame information of ogre objects (which are faced or selected)
|
||||
mRaySceneQuery = rend.getScene()->createRayQuery(Ray());
|
||||
mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray());
|
||||
|
||||
Ogre::SceneNode *playerNode = mwRoot->createChildSceneNode ("player");
|
||||
Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player");
|
||||
playerNode->pitch(Degree(90));
|
||||
Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode();
|
||||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||
cameraPitchNode->attachObject(rend.getCamera());
|
||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||
|
||||
//mSkyManager = 0;
|
||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
|
||||
|
||||
mPlayer = new MWRender::Player (rend.getCamera(), playerNode);
|
||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||
mSun = 0;
|
||||
}
|
||||
|
||||
RenderingManager::~RenderingManager ()
|
||||
{
|
||||
//TODO: destroy mSun?
|
||||
delete mPlayer;
|
||||
delete mSkyManager;
|
||||
delete mTerrainManager;
|
||||
}
|
||||
|
||||
MWRender::Npcs& RenderingManager::getNPCs(){
|
||||
return npcs;
|
||||
MWRender::SkyManager* RenderingManager::getSkyManager()
|
||||
{
|
||||
return mSkyManager;
|
||||
}
|
||||
|
||||
MWRender::Objects& RenderingManager::getObjects(){
|
||||
return objects;
|
||||
return mObjects;
|
||||
}
|
||||
MWRender::Creatures& RenderingManager::getCreatures(){
|
||||
return creatures;
|
||||
MWRender::Actors& RenderingManager::getActors(){
|
||||
return mActors;
|
||||
}
|
||||
|
||||
MWRender::Player& RenderingManager::getPlayer(){
|
||||
return (*mPlayer);
|
||||
}
|
||||
|
||||
OEngine::Render::Fader* RenderingManager::getFader()
|
||||
{
|
||||
return mRendering.getFader();
|
||||
}
|
||||
|
||||
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){
|
||||
objects.removeCell(store);
|
||||
mObjects.removeCell(store);
|
||||
mActors.removeCell(store);
|
||||
if (store->cell->isExterior())
|
||||
mTerrainManager->cellRemoved(store);
|
||||
}
|
||||
|
||||
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
|
||||
{
|
||||
objects.buildStaticGeometry (*store);
|
||||
mObjects.buildStaticGeometry (*store);
|
||||
if (store->cell->isExterior())
|
||||
mTerrainManager->cellAdded(store);
|
||||
}
|
||||
|
@ -97,7 +109,11 @@ void RenderingManager::addObject (const MWWorld::Ptr& ptr){
|
|||
}
|
||||
void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (!objects.deleteObject (ptr))
|
||||
if (!mObjects.deleteObject (ptr))
|
||||
{
|
||||
/// \todo delete non-object MW-references
|
||||
}
|
||||
if (!mActors.deleteObject (ptr))
|
||||
{
|
||||
/// \todo delete non-object MW-references
|
||||
}
|
||||
|
@ -106,7 +122,7 @@ void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
|
|||
void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position)
|
||||
{
|
||||
/// \todo move this to the rendering-subsystems
|
||||
rend.getScene()->getSceneNode (ptr.getRefData().getHandle())->
|
||||
mRendering.getScene()->getSceneNode (ptr.getRefData().getHandle())->
|
||||
setPosition (position);
|
||||
}
|
||||
|
||||
|
@ -122,32 +138,41 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve
|
|||
|
||||
void RenderingManager::update (float duration){
|
||||
|
||||
|
||||
mActors.update (duration);
|
||||
|
||||
mSkyManager->update(duration);
|
||||
|
||||
mRendering.update(duration);
|
||||
}
|
||||
|
||||
void RenderingManager::skyEnable ()
|
||||
{
|
||||
if(mSkyManager)
|
||||
mSkyManager->enable();
|
||||
}
|
||||
|
||||
void RenderingManager::skyDisable ()
|
||||
{
|
||||
mSkyManager->disable();
|
||||
if(mSkyManager)
|
||||
mSkyManager->disable();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetHour (double hour)
|
||||
{
|
||||
mSkyManager->setHour(hour);
|
||||
if(mSkyManager)
|
||||
mSkyManager->setHour(hour);
|
||||
}
|
||||
|
||||
|
||||
void RenderingManager::skySetDate (int day, int month)
|
||||
{
|
||||
mSkyManager->setDate(day, month);
|
||||
if(mSkyManager)
|
||||
mSkyManager->setDate(day, month);
|
||||
}
|
||||
|
||||
int RenderingManager::skyGetMasserPhase() const
|
||||
{
|
||||
|
||||
return mSkyManager->getMasserPhase();
|
||||
}
|
||||
|
||||
|
@ -156,12 +181,28 @@ int RenderingManager::skyGetSecundaPhase() const
|
|||
return mSkyManager->getSecundaPhase();
|
||||
}
|
||||
|
||||
void RenderingManager::skySetMoonColour (bool red)
|
||||
{
|
||||
mSkyManager->setMoonColour(red);
|
||||
void RenderingManager::skySetMoonColour (bool red){
|
||||
if(mSkyManager)
|
||||
mSkyManager->setMoonColour(red);
|
||||
}
|
||||
bool RenderingManager::toggleRenderMode(int mode){
|
||||
return mDebugging.toggleRenderMode(mode);
|
||||
|
||||
bool RenderingManager::toggleRenderMode(int mode)
|
||||
{
|
||||
if (mode == MWWorld::World::Render_CollisionDebug)
|
||||
return mDebugging.toggleRenderMode(mode);
|
||||
else // if (mode == MWWorld::World::Render_Wireframe)
|
||||
{
|
||||
if (mRendering.getCamera()->getPolygonMode() == PM_SOLID)
|
||||
{
|
||||
mRendering.getCamera()->setPolygonMode(PM_WIREFRAME);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRendering.getCamera()->setPolygonMode(PM_SOLID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
|
||||
|
@ -169,31 +210,39 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
|
|||
Ogre::ColourValue color;
|
||||
color.setAsABGR (mCell.cell->ambi.fog);
|
||||
|
||||
float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity);
|
||||
float low = 200;
|
||||
|
||||
rend.getScene()->setFog (FOG_LINEAR, color, 0, low, high);
|
||||
rend.getCamera()->setFarClipDistance (high + 10);
|
||||
rend.getViewport()->setBackgroundColour (color);
|
||||
configureFog(mCell.cell->ambi.fogDensity, color);
|
||||
}
|
||||
|
||||
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
|
||||
{
|
||||
/// \todo make the viewing distance and fog start/end configurable
|
||||
float low = 3000 / density;
|
||||
float high = 6200 / density;
|
||||
|
||||
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);
|
||||
|
||||
mRendering.getCamera()->setFarClipDistance ( high );
|
||||
mRendering.getViewport()->setBackgroundColour (colour);
|
||||
}
|
||||
|
||||
|
||||
void RenderingManager::setAmbientMode()
|
||||
{
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0:
|
||||
|
||||
rend.getScene()->setAmbientLight(mAmbientColor);
|
||||
mRendering.getScene()->setAmbientLight(mAmbientColor);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
rend.getScene()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
mRendering.getScene()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
rend.getScene()->setAmbientLight(ColourValue(1,1,1));
|
||||
mRendering.getScene()->setAmbientLight(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -205,12 +254,15 @@ void RenderingManager::configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell
|
|||
|
||||
// Create a "sun" that shines light downwards. It doesn't look
|
||||
// completely right, but leave it for now.
|
||||
Ogre::Light *light = rend.getScene()->createLight();
|
||||
if(!mSun)
|
||||
{
|
||||
mSun = mRendering.getScene()->createLight();
|
||||
}
|
||||
Ogre::ColourValue colour;
|
||||
colour.setAsABGR (mCell.cell->ambi.sunlight);
|
||||
light->setDiffuseColour (colour);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDirection(0,-1,0);
|
||||
mSun->setDiffuseColour (colour);
|
||||
mSun->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
mSun->setDirection(0,-1,0);
|
||||
}
|
||||
// Switch through lighting modes.
|
||||
|
||||
|
@ -231,6 +283,46 @@ void RenderingManager::toggleLight()
|
|||
setAmbientMode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RenderingManager::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName,
|
||||
int mode, int number)
|
||||
{
|
||||
mActors.playAnimationGroup(ptr, groupName, mode, number);
|
||||
}
|
||||
|
||||
void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mActors.skipAnimation(ptr);
|
||||
}
|
||||
|
||||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
||||
{
|
||||
mSun->setDiffuseColour(colour);
|
||||
}
|
||||
|
||||
void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
||||
{
|
||||
mRendering.getScene()->setAmbientLight(colour);
|
||||
}
|
||||
|
||||
void RenderingManager::sunEnable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(true);
|
||||
}
|
||||
|
||||
void RenderingManager::sunDisable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(false);
|
||||
}
|
||||
|
||||
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
|
||||
{
|
||||
if (mSun) mSun->setDirection(Vector3(direction.x, -direction.z, direction.y));
|
||||
mSkyManager->setSunDirection(direction);
|
||||
}
|
||||
|
||||
void RenderingManager::setGlare(bool glare)
|
||||
{
|
||||
mSkyManager->setGlare(glare);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <utility>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/ogre/fader.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
@ -20,9 +21,9 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "renderinginterface.hpp"
|
||||
#include "npcs.hpp"
|
||||
#include "creatures.hpp"
|
||||
|
||||
#include "objects.hpp"
|
||||
#include "actors.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
@ -50,20 +51,24 @@ class RenderingManager: private RenderingInterface {
|
|||
|
||||
private:
|
||||
|
||||
virtual MWRender::Npcs& getNPCs();
|
||||
virtual MWRender::Creatures& getCreatures();
|
||||
|
||||
virtual MWRender::Objects& getObjects();
|
||||
virtual MWRender::Actors& getActors();
|
||||
|
||||
public:
|
||||
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine);
|
||||
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment);
|
||||
virtual ~RenderingManager();
|
||||
|
||||
virtual MWRender::Player& getPlayer(); /// \todo move this to private again as soon as
|
||||
/// MWWorld::Player has been rewritten to not need access
|
||||
/// to internal details of the rendering system anymore
|
||||
|
||||
SkyManager* getSkyManager();
|
||||
|
||||
void toggleLight();
|
||||
bool toggleRenderMode(int mode);
|
||||
|
||||
OEngine::Render::Fader* getFader();
|
||||
|
||||
void removeCell (MWWorld::Ptr::CellStore *store);
|
||||
|
||||
|
@ -82,7 +87,14 @@ class RenderingManager: private RenderingInterface {
|
|||
void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store);
|
||||
|
||||
void update (float duration);
|
||||
|
||||
|
||||
void setAmbientColour(const Ogre::ColourValue& colour);
|
||||
void setSunColour(const Ogre::ColourValue& colour);
|
||||
void setSunDirection(const Ogre::Vector3& direction);
|
||||
void sunEnable();
|
||||
void sunDisable();
|
||||
|
||||
void setGlare(bool glare);
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
void skySetHour (double hour);
|
||||
|
@ -91,32 +103,50 @@ class RenderingManager: private RenderingInterface {
|
|||
int skyGetSecundaPhase() const;
|
||||
void skySetMoonColour (bool red);
|
||||
void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||
|
||||
/// configure fog according to cell
|
||||
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
|
||||
|
||||
/// configure fog manually
|
||||
void configureFog(const float density, const Ogre::ColourValue& colour);
|
||||
|
||||
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
|
||||
int number = 1);
|
||||
///< Run animation for a MW-reference. Calls to this function for references that are currently not
|
||||
/// in the rendered scene should be ignored.
|
||||
///
|
||||
/// \param mode: 0 normal, 1 immediate start, 2 immediate loop
|
||||
/// \param number How offen the animation should be run
|
||||
|
||||
void skipAnimation (const MWWorld::Ptr& ptr);
|
||||
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
|
||||
/// references that are currently not in the rendered scene should be ignored.
|
||||
|
||||
private:
|
||||
|
||||
void setAmbientMode();
|
||||
|
||||
SkyManager* mSkyManager;
|
||||
|
||||
TerrainManager* mTerrainManager;
|
||||
OEngine::Render::OgreRenderer &rend;
|
||||
Ogre::Camera* camera;
|
||||
MWRender::Npcs npcs;
|
||||
MWRender::Creatures creatures;
|
||||
MWRender::Objects objects;
|
||||
OEngine::Render::OgreRenderer &mRendering;
|
||||
|
||||
MWRender::Objects mObjects;
|
||||
MWRender::Actors mActors;
|
||||
|
||||
// 0 normal, 1 more bright, 2 max
|
||||
int mAmbientMode;
|
||||
|
||||
Ogre::ColourValue mAmbientColor;
|
||||
Ogre::Light* mSun;
|
||||
|
||||
/// Root node for all objects added to the scene. This is rotated so
|
||||
/// that the OGRE coordinate system matches that used internally in
|
||||
/// Morrowind.
|
||||
Ogre::SceneNode *mwRoot;
|
||||
Ogre::SceneNode *mMwRoot;
|
||||
Ogre::RaySceneQuery *mRaySceneQuery;
|
||||
|
||||
OEngine::Physic::PhysicEngine* eng;
|
||||
OEngine::Physic::PhysicEngine* mPhysicsEngine;
|
||||
|
||||
MWRender::Player *mPlayer;
|
||||
MWRender::Debugging mDebugging;
|
||||
|
|
|
@ -1,116 +1,762 @@
|
|||
#include "sky.hpp"
|
||||
#include "Caelum.h"
|
||||
|
||||
namespace MWRender
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreMesh.h>
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreHardwareVertexBuffer.h>
|
||||
#include <OgreHighLevelGpuProgramManager.h>
|
||||
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
||||
// the speed at which the clouds are animated
|
||||
#define CLOUD_SPEED 0.001
|
||||
|
||||
// this distance has to be set accordingly so that the
|
||||
// celestial bodies are behind the clouds, but in front of the atmosphere
|
||||
#define CELESTIAL_BODY_DISTANCE 1000.f
|
||||
|
||||
BillboardObject::BillboardObject( const String& textureName,
|
||||
const float initialSize,
|
||||
const Vector3& position,
|
||||
SceneNode* rootNode)
|
||||
{
|
||||
//
|
||||
// Implements a Caelum sky with default settings.
|
||||
//
|
||||
// Note: this is intended as a temporary solution to provide some form of
|
||||
// sky rendering. This code will obviously need significant tailoring to
|
||||
// support fidelity with Morrowind's rendering. Before doing major work
|
||||
// on this class, more research should be done to determine whether
|
||||
// Caelum or another plug-in such as SkyX would be best for the long-term.
|
||||
//
|
||||
class CaelumManager : public SkyManager
|
||||
init(textureName, initialSize, position, rootNode);
|
||||
}
|
||||
|
||||
BillboardObject::BillboardObject()
|
||||
{
|
||||
}
|
||||
|
||||
void BillboardObject::setVisible(const bool visible)
|
||||
{
|
||||
mNode->setVisible(visible);
|
||||
}
|
||||
|
||||
void BillboardObject::setSize(const float size)
|
||||
{
|
||||
mNode->setScale(size, size, size);
|
||||
}
|
||||
|
||||
void BillboardObject::setVisibility(const float visibility)
|
||||
{
|
||||
mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility);
|
||||
}
|
||||
|
||||
void BillboardObject::setPosition(const Vector3& pPosition)
|
||||
{
|
||||
Vector3 normalised = pPosition.normalisedCopy();
|
||||
Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE;
|
||||
|
||||
mBBSet->setCommonDirection( -normalised );
|
||||
|
||||
mNode->setPosition(finalPosition);
|
||||
}
|
||||
|
||||
Vector3 BillboardObject::getPosition() const
|
||||
{
|
||||
return mNode->getPosition();
|
||||
}
|
||||
|
||||
void BillboardObject::setColour(const ColourValue& pColour)
|
||||
{
|
||||
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||
}
|
||||
|
||||
void BillboardObject::setRenderQueue(unsigned int id)
|
||||
{
|
||||
mBBSet->setRenderQueueGroup(id);
|
||||
}
|
||||
|
||||
SceneNode* BillboardObject::getNode()
|
||||
{
|
||||
return mNode;
|
||||
}
|
||||
|
||||
void BillboardObject::init(const String& textureName,
|
||||
const float initialSize,
|
||||
const Vector3& position,
|
||||
SceneNode* rootNode)
|
||||
{
|
||||
SceneManager* sceneMgr = rootNode->getCreator();
|
||||
|
||||
Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
||||
|
||||
static unsigned int bodyCount=0;
|
||||
|
||||
/// \todo These billboards are not 100% correct, might want to revisit them later
|
||||
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
||||
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
||||
mBBSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2);
|
||||
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
||||
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
||||
mNode = rootNode->createChildSceneNode();
|
||||
mNode->setPosition(finalPosition);
|
||||
mNode->attachObject(mBBSet);
|
||||
mBBSet->createBillboard(0,0,0);
|
||||
|
||||
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
mMaterial->removeAllTechniques();
|
||||
Pass* p = mMaterial->createTechnique()->createPass();
|
||||
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
p->setDepthCheckEnabled(false);
|
||||
p->setDepthWriteEnabled(false);
|
||||
p->setSelfIllumination(1.0,1.0,1.0);
|
||||
p->setDiffuse(0.0,0.0,0.0,1.0);
|
||||
p->setAmbient(0.0,0.0,0.0);
|
||||
p->createTextureUnitState(textureName);
|
||||
mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
|
||||
|
||||
bodyCount++;
|
||||
}
|
||||
|
||||
Moon::Moon( const String& textureName,
|
||||
const float initialSize,
|
||||
const Vector3& position,
|
||||
SceneNode* rootNode)
|
||||
{
|
||||
init(textureName, initialSize, position, rootNode);
|
||||
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
HighLevelGpuProgramPtr vshader;
|
||||
if (mgr.resourceExists("Moon_VP"))
|
||||
vshader = mgr.getByName("Moon_VP");
|
||||
else
|
||||
vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM);
|
||||
vshader->setParameter("profiles", "vs_2_x arbvp1");
|
||||
vshader->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oUV = uv; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
"}";
|
||||
vshader->setSource(outStream.str());
|
||||
vshader->load();
|
||||
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||
|
||||
HighLevelGpuProgramPtr fshader;
|
||||
if (mgr.resourceExists("Moon_FP"))
|
||||
fshader = mgr.getByName("Moon_FP");
|
||||
else
|
||||
fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM);
|
||||
|
||||
fshader->setParameter("profiles", "ps_2_x arbfp1");
|
||||
fshader->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream2;
|
||||
outStream2 <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n"
|
||||
"}";
|
||||
fshader->setSource(outStream2.str());
|
||||
fshader->load();
|
||||
fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
|
||||
|
||||
setVisibility(1.0);
|
||||
|
||||
mPhase = Moon::Phase_Full;
|
||||
}
|
||||
|
||||
void Moon::setType(const Moon::Type& type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
||||
|
||||
/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
|
||||
void Moon::setPhase(const Moon::Phase& phase)
|
||||
{
|
||||
Ogre::String textureName = "textures\\tx_";
|
||||
|
||||
if (mType == Moon::Type_Secunda) textureName += "secunda_";
|
||||
else textureName += "masser_";
|
||||
|
||||
if (phase == Moon::Phase_New) textureName += "new";
|
||||
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
|
||||
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
|
||||
else if (phase == Moon::Phase_WaxingGibbous) textureName += "three_wax";
|
||||
else if (phase == Moon::Phase_WaningCrescent) textureName += "one_wan";
|
||||
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
|
||||
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
|
||||
else if (phase == Moon::Phase_Full) textureName += "full";
|
||||
|
||||
textureName += ".dds";
|
||||
|
||||
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);
|
||||
|
||||
mPhase = phase;
|
||||
}
|
||||
|
||||
Moon::Phase Moon::getPhase() const
|
||||
{
|
||||
return mPhase;
|
||||
}
|
||||
|
||||
unsigned int Moon::getPhaseInt() const
|
||||
{
|
||||
if (mPhase == Moon::Phase_New) return 0;
|
||||
else if (mPhase == Moon::Phase_WaxingCrescent) return 1;
|
||||
else if (mPhase == Moon::Phase_WaningCrescent) return 1;
|
||||
else if (mPhase == Moon::Phase_WaxingHalf) return 2;
|
||||
else if (mPhase == Moon::Phase_WaningHalf) return 2;
|
||||
else if (mPhase == Moon::Phase_WaxingGibbous) return 3;
|
||||
else if (mPhase == Moon::Phase_WaningGibbous) return 3;
|
||||
else if (mPhase == Moon::Phase_Full) return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||
{
|
||||
// Get the vertex colour buffer of this mesh
|
||||
const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE );
|
||||
HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource());
|
||||
|
||||
// Lock
|
||||
void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL);
|
||||
|
||||
// Iterate over all vertices
|
||||
int vertex_size = colourBuffer->getVertexSize();
|
||||
float * currentVertex = NULL;
|
||||
for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i)
|
||||
{
|
||||
protected:
|
||||
Caelum::CaelumSystem* mpCaelumSystem;
|
||||
// Get a pointer to the vertex colour
|
||||
ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex );
|
||||
|
||||
unsigned char alpha;
|
||||
if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
||||
else if (meshType == 1)
|
||||
{
|
||||
if (i>= 49 && i <= 64) alpha = 0; // bottom-most row
|
||||
else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
|
||||
else alpha = 255;
|
||||
}
|
||||
|
||||
uint8 tmpR = static_cast<uint8>(255);
|
||||
uint8 tmpG = static_cast<uint8>(255);
|
||||
uint8 tmpB = static_cast<uint8>(255);
|
||||
uint8 tmpA = static_cast<uint8>(alpha);
|
||||
|
||||
// This does not matter since R and B are always 1.
|
||||
/*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
|
||||
switch (format)
|
||||
{
|
||||
case VET_COLOUR_ARGB:
|
||||
std::swap(tmpR, tmpB);
|
||||
break;
|
||||
case VET_COLOUR_ABGR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}*/
|
||||
|
||||
// Modify
|
||||
*((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);
|
||||
|
||||
// Move to the next vertex
|
||||
pData+=vertex_size;
|
||||
}
|
||||
|
||||
// Unlock
|
||||
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
||||
Ogre::Camera* pCamera,
|
||||
const boost::filesystem::path& resDir);
|
||||
virtual ~CaelumManager ();
|
||||
|
||||
virtual void enable() {}
|
||||
|
||||
virtual void disable() {}
|
||||
|
||||
virtual void setHour (double hour) {}
|
||||
///< will be called even when sky is disabled.
|
||||
|
||||
virtual void setDate (int day, int month) {}
|
||||
///< will be called even when sky is disabled.
|
||||
|
||||
virtual int getMasserPhase() const { return 0; }
|
||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||
/// 3 waxing or waning gibbous, 4 full moon
|
||||
|
||||
virtual int getSecundaPhase() const { return 0; }
|
||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||
/// 3 waxing or waning gibbous, 4 full moon
|
||||
|
||||
virtual void setMoonColour (bool red) {}
|
||||
};
|
||||
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||
mGlareFade(0), mGlareEnabled(false)
|
||||
{
|
||||
mViewport = pCamera->getViewport();
|
||||
mSceneMgr = pMwRoot->getCreator();
|
||||
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
||||
mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates
|
||||
mRootNode->setInheritOrientation(false);
|
||||
|
||||
/// \todo preload all the textures and meshes that are used for sky rendering
|
||||
|
||||
// Create overlay used for thunderstorm
|
||||
MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
|
||||
Pass* pass = material->getTechnique(0)->getPass(0);
|
||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
mThunderTextureUnit = pass->createTextureUnitState();
|
||||
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour
|
||||
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
||||
OverlayManager& ovm = OverlayManager::getSingleton();
|
||||
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
||||
OverlayContainer* overlay_panel;
|
||||
overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel");
|
||||
overlay_panel->_setPosition(0, 0);
|
||||
overlay_panel->_setDimensions(1, 1);
|
||||
overlay_panel->setMaterialName( "ThunderMaterial" );
|
||||
overlay_panel->show();
|
||||
mThunderOverlay->add2D(overlay_panel);
|
||||
mThunderOverlay->hide();
|
||||
|
||||
mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||
mSecunda->setType(Moon::Type_Secunda);
|
||||
mSecunda->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+4);
|
||||
|
||||
mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||
mMasser->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+3);
|
||||
mMasser->setType(Moon::Type_Masser);
|
||||
|
||||
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode);
|
||||
mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode);
|
||||
mSunGlare->setRenderQueue(RENDER_QUEUE_SKIES_LATE);
|
||||
|
||||
CaelumManager::CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
||||
Ogre::Camera* pCamera,
|
||||
const boost::filesystem::path& resDir)
|
||||
: mpCaelumSystem (NULL)
|
||||
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
|
||||
// Stars
|
||||
/// \todo sky_night_02.nif (available in Bloodmoon)
|
||||
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
|
||||
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||
night1_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1);
|
||||
|
||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||
mAtmosphereNight->attachObject(night1_ent);
|
||||
|
||||
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
|
||||
{
|
||||
using namespace Ogre;
|
||||
using namespace Caelum;
|
||||
|
||||
assert(pCamera);
|
||||
assert(pRenderWindow);
|
||||
|
||||
// Load the Caelum resources
|
||||
//
|
||||
ResourceGroupManager::getSingleton().addResourceLocation((resDir / "caelum").string(), "FileSystem", "Caelum");
|
||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
||||
|
||||
// Load the Caelum resources
|
||||
//
|
||||
Ogre::SceneManager* pScene = pCamera->getSceneManager();
|
||||
Caelum::CaelumSystem::CaelumComponent componentMask = CaelumSystem::CAELUM_COMPONENTS_DEFAULT;
|
||||
mpCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), pScene, componentMask);
|
||||
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);
|
||||
|
||||
// Set time acceleration.
|
||||
mpCaelumSystem->getUniversalClock()->setTimeScale(128);
|
||||
mStarsMaterials[i] = mp;
|
||||
}
|
||||
|
||||
// Stars vertex shader
|
||||
HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vshader3->setParameter("profiles", "vs_2_x arbvp1");
|
||||
vshader3->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream4;
|
||||
outStream4 <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float oFade : TEXCOORD1, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oUV = uv; \n"
|
||||
" oFade = (position.z > 50) ? 1.f : 0.f; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
"}";
|
||||
vshader3->setSource(outStream4.str());
|
||||
vshader3->load();
|
||||
vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName());
|
||||
|
||||
// Stars fragment shader
|
||||
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
stars_fp->setParameter("profiles", "ps_2_x arbfp1");
|
||||
stars_fp->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream5;
|
||||
outStream5 <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" in float fade : TEXCOORD1, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" uniform float opacity, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n"
|
||||
"}";
|
||||
stars_fp->setSource(outStream5.str());
|
||||
stars_fp->load();
|
||||
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
|
||||
|
||||
// Atmosphere (day)
|
||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||
|
||||
ModVertexAlpha(atmosphere_ent, 0);
|
||||
|
||||
atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);
|
||||
mAtmosphereDay = mRootNode->createChildSceneNode();
|
||||
mAtmosphereDay->attachObject(atmosphere_ent);
|
||||
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
|
||||
|
||||
// Atmosphere shader
|
||||
HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
|
||||
// Disable fog since OpenMW is handling OGRE fog elsewhere
|
||||
mpCaelumSystem->setManageSceneFog(false);
|
||||
vshader->setParameter("profiles", "vs_2_x arbvp1");
|
||||
vshader->setParameter("entry_point", "main_vp");
|
||||
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" in float4 color : COLOR, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform float4 emissive, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
" oColor = color * emissive; \n"
|
||||
"}";
|
||||
vshader->setSource(outStream.str());
|
||||
vshader->load();
|
||||
|
||||
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||
|
||||
// Change the camera far distance to make sure the sky is not clipped
|
||||
pCamera->setFarClipDistance(50000);
|
||||
// Clouds
|
||||
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
||||
clouds_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+5);
|
||||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||
clouds_node->attachObject(clouds_ent);
|
||||
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||
|
||||
// Clouds vertex shader
|
||||
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vshader2->setParameter("profiles", "vs_2_x arbvp1");
|
||||
vshader2->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream3;
|
||||
outStream3 <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" in float4 color : COLOR, \n"
|
||||
" out float4 oColor : TEXCOORD1, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oUV = uv; \n"
|
||||
" oColor = color; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
"}";
|
||||
vshader2->setSource(outStream3.str());
|
||||
vshader2->load();
|
||||
vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName());
|
||||
|
||||
// Clouds fragment shader
|
||||
mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1");
|
||||
mCloudFragmentShader->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream2;
|
||||
outStream2 <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" in float4 color : TEXCOORD1, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
||||
" uniform float transitionFactor, \n"
|
||||
" uniform float time, \n"
|
||||
" uniform float speed, \n"
|
||||
" uniform float opacity, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" uv += float2(1,1) * time * speed * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
||||
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
||||
"}";
|
||||
mCloudFragmentShader->setSource(outStream2.str());
|
||||
mCloudFragmentShader->load();
|
||||
mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName());
|
||||
setCloudsOpacity(0.75);
|
||||
|
||||
ModVertexAlpha(clouds_ent, 1);
|
||||
|
||||
// I'm not sure if the materials are being used by any other objects
|
||||
// Make a unique "modifiable" copy of the materials to be sure
|
||||
mCloudMaterial = mCloudMaterial->clone("Clouds");
|
||||
clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial);
|
||||
mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere");
|
||||
atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial);
|
||||
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0);
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||
}
|
||||
|
||||
// Register Caelum as an OGRE listener
|
||||
pRenderWindow->addListener(mpCaelumSystem);
|
||||
Root::getSingletonPtr()->addFrameListener(mpCaelumSystem);
|
||||
SkyManager::~SkyManager()
|
||||
{
|
||||
delete mSun;
|
||||
delete mSunGlare;
|
||||
delete mMasser;
|
||||
delete mSecunda;
|
||||
}
|
||||
|
||||
int SkyManager::getMasserPhase() const
|
||||
{
|
||||
return mMasser->getPhaseInt();
|
||||
}
|
||||
|
||||
int SkyManager::getSecundaPhase() const
|
||||
{
|
||||
return mSecunda->getPhaseInt();
|
||||
}
|
||||
|
||||
void SkyManager::update(float duration)
|
||||
{
|
||||
if (!mEnabled) return;
|
||||
|
||||
// UV Scroll the clouds
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1);
|
||||
|
||||
/// \todo improve this
|
||||
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||
|
||||
// increase the strength of the sun glare effect depending
|
||||
// on how directly the player is looking at the sun
|
||||
if (mSunEnabled)
|
||||
{
|
||||
Vector3 sun = mSunGlare->getPosition();
|
||||
sun = Vector3(sun.x, sun.z, -sun.y);
|
||||
Vector3 cam = mViewport->getCamera()->getRealDirection();
|
||||
const Degree angle = sun.angleBetween( cam );
|
||||
float val = 1- (angle.valueDegrees() / 180.f);
|
||||
val = (val*val*val*val)*2;
|
||||
|
||||
if (mGlareEnabled)
|
||||
{
|
||||
mGlareFade += duration*3;
|
||||
if (mGlareFade > 1) mGlareFade = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mGlareFade -= duration*3;
|
||||
if (mGlareFade < 0.3) mGlareFade = 0;
|
||||
}
|
||||
|
||||
mSunGlare->setSize(val * (mGlareFade));
|
||||
}
|
||||
|
||||
mSunGlare->setVisible(mGlareFade>0 && mSunEnabled);
|
||||
mSun->setVisible(mSunEnabled);
|
||||
mMasser->setVisible(mMasserEnabled);
|
||||
mSecunda->setVisible(mSecundaEnabled);
|
||||
}
|
||||
|
||||
void SkyManager::enable()
|
||||
{
|
||||
mRootNode->setVisible(true);
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
void SkyManager::disable()
|
||||
{
|
||||
mRootNode->setVisible(false);
|
||||
mEnabled = false;
|
||||
}
|
||||
|
||||
void SkyManager::setMoonColour (bool red)
|
||||
{
|
||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
||||
: ColourValue(1.0, 1.0, 1.0));
|
||||
}
|
||||
|
||||
void SkyManager::setCloudsOpacity(float opacity)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||
}
|
||||
|
||||
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||
{
|
||||
if (mClouds != weather.mCloudTexture)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture);
|
||||
mClouds = weather.mCloudTexture;
|
||||
}
|
||||
|
||||
if (mNextClouds != weather.mNextCloudTexture)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("textures\\"+weather.mNextCloudTexture);
|
||||
mNextClouds = weather.mNextCloudTexture;
|
||||
}
|
||||
|
||||
if (mCloudBlendFactor != weather.mCloudBlendFactor)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor));
|
||||
mCloudBlendFactor = weather.mCloudBlendFactor;
|
||||
}
|
||||
|
||||
if (mCloudOpacity != weather.mCloudOpacity)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity));
|
||||
mCloudOpacity = weather.mCloudOpacity;
|
||||
}
|
||||
|
||||
if (mCloudColour != weather.mSunColor)
|
||||
{
|
||||
ColourValue clr( weather.mSunColor.r*0.7 + weather.mAmbientColor.r*0.7,
|
||||
weather.mSunColor.g*0.7 + weather.mAmbientColor.g*0.7,
|
||||
weather.mSunColor.b*0.7 + weather.mAmbientColor.b*0.7);
|
||||
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(clr);
|
||||
mCloudColour = weather.mSunColor;
|
||||
}
|
||||
|
||||
if (mSkyColour != weather.mSkyColor)
|
||||
{
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
|
||||
mSkyColour = weather.mSkyColor;
|
||||
}
|
||||
|
||||
if (mCloudSpeed != weather.mCloudSpeed)
|
||||
{
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("speed", Real(weather.mCloudSpeed));
|
||||
mCloudSpeed = weather.mCloudSpeed;
|
||||
}
|
||||
|
||||
if (weather.mNight && mStarsOpacity != weather.mNightFade)
|
||||
{
|
||||
for (int i=0; i<7; ++i)
|
||||
mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade);
|
||||
mStarsOpacity = weather.mNightFade;
|
||||
}
|
||||
|
||||
CaelumManager::~CaelumManager()
|
||||
float strength;
|
||||
float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length());
|
||||
if (timeofday_angle <= 0.44)
|
||||
strength = timeofday_angle/0.44f;
|
||||
else
|
||||
strength = 1.f;
|
||||
|
||||
mSunGlare->setVisibility(weather.mGlareView * strength);
|
||||
|
||||
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||
}
|
||||
|
||||
void SkyManager::setGlare(bool glare)
|
||||
{
|
||||
mGlareEnabled = glare;
|
||||
}
|
||||
|
||||
Vector3 SkyManager::getRealSunPos()
|
||||
{
|
||||
return mSun->getNode()->_getDerivedPosition();
|
||||
}
|
||||
|
||||
void SkyManager::sunEnable()
|
||||
{
|
||||
mSunEnabled = true;
|
||||
}
|
||||
|
||||
void SkyManager::sunDisable()
|
||||
{
|
||||
mSunEnabled = false;
|
||||
}
|
||||
|
||||
void SkyManager::setSunDirection(const Vector3& direction)
|
||||
{
|
||||
mSun->setPosition(direction);
|
||||
mSunGlare->setPosition(direction);
|
||||
}
|
||||
|
||||
void SkyManager::setMasserDirection(const Vector3& direction)
|
||||
{
|
||||
mMasser->setPosition(direction);
|
||||
}
|
||||
|
||||
void SkyManager::setSecundaDirection(const Vector3& direction)
|
||||
{
|
||||
mSecunda->setPosition(direction);
|
||||
}
|
||||
|
||||
void SkyManager::masserEnable()
|
||||
{
|
||||
mMasserEnabled = true;
|
||||
}
|
||||
|
||||
void SkyManager::secundaEnable()
|
||||
{
|
||||
mSecundaEnabled = true;
|
||||
}
|
||||
|
||||
void SkyManager::masserDisable()
|
||||
{
|
||||
mMasserEnabled = false;
|
||||
}
|
||||
|
||||
void SkyManager::secundaDisable()
|
||||
{
|
||||
mSecundaEnabled = false;
|
||||
}
|
||||
|
||||
void SkyManager::setThunder(const float factor)
|
||||
{
|
||||
if (factor > 0.f)
|
||||
{
|
||||
if (mpCaelumSystem)
|
||||
mpCaelumSystem->shutdown (false);
|
||||
mThunderOverlay->show();
|
||||
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, factor*0.6);
|
||||
}
|
||||
else
|
||||
mThunderOverlay->hide();
|
||||
}
|
||||
|
||||
/// Creates and connects the sky rendering component to OGRE.
|
||||
///
|
||||
/// \return NULL on failure.
|
||||
///
|
||||
SkyManager* SkyManager::create (Ogre::RenderWindow* pRenderWindow,
|
||||
Ogre::Camera* pCamera,
|
||||
const boost::filesystem::path& resDir)
|
||||
{
|
||||
SkyManager* pSkyManager = NULL;
|
||||
void SkyManager::setMasserFade(const float fade)
|
||||
{
|
||||
mMasser->setVisibility(fade);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir);
|
||||
}
|
||||
catch (Ogre::Exception& e)
|
||||
{
|
||||
std::cout << "\nOGRE Exception when attempting to add sky: "
|
||||
<< e.getFullDescription().c_str() << std::endl;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "\nException when attempting to add sky: "
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
void SkyManager::setSecundaFade(const float fade)
|
||||
{
|
||||
mSecunda->setVisibility(fade);
|
||||
}
|
||||
|
||||
return pSkyManager;
|
||||
}
|
||||
}
|
||||
void SkyManager::setHour(double hour)
|
||||
{
|
||||
mHour = hour;
|
||||
}
|
||||
|
||||
void SkyManager::setDate(int day, int month)
|
||||
{
|
||||
mDay = day;
|
||||
mMonth = month;
|
||||
}
|
||||
|
|
|
@ -1,40 +1,211 @@
|
|||
#ifndef _GAME_RENDER_SKY_H
|
||||
#define _GAME_RENDER_SKY_H
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <OgreVector3.h>
|
||||
#include <OgreString.h>
|
||||
#include <OgreMaterial.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreHighLevelGpuProgram.h>
|
||||
|
||||
#include "sky.hpp"
|
||||
#include "../mwworld/weather.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class RenderWindow;
|
||||
class SceneNode;
|
||||
class Camera;
|
||||
class Viewport;
|
||||
class SceneManager;
|
||||
class Entity;
|
||||
class BillboardSet;
|
||||
class TextureUnitState;
|
||||
class Overlay;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
///
|
||||
/// Interface for the sky rendering system
|
||||
///
|
||||
class BillboardObject
|
||||
{
|
||||
public:
|
||||
BillboardObject( const Ogre::String& textureName,
|
||||
const float size,
|
||||
const Ogre::Vector3& position,
|
||||
Ogre::SceneNode* rootNode
|
||||
);
|
||||
BillboardObject();
|
||||
|
||||
void setColour(const Ogre::ColourValue& pColour);
|
||||
void setPosition(const Ogre::Vector3& pPosition);
|
||||
void setVisible(const bool visible);
|
||||
void setRenderQueue(unsigned int id);
|
||||
void setSize(const float size);
|
||||
Ogre::Vector3 getPosition() const;
|
||||
|
||||
void setVisibility(const float visibility);
|
||||
|
||||
Ogre::SceneNode* getNode();
|
||||
|
||||
protected:
|
||||
virtual void init(const Ogre::String& textureName,
|
||||
const float size,
|
||||
const Ogre::Vector3& position,
|
||||
Ogre::SceneNode* rootNode);
|
||||
|
||||
Ogre::SceneNode* mNode;
|
||||
Ogre::MaterialPtr mMaterial;
|
||||
Ogre::BillboardSet* mBBSet;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The moons need a seperate class because of their shader (which allows them to be partially transparent)
|
||||
*/
|
||||
class Moon : public BillboardObject
|
||||
{
|
||||
public:
|
||||
Moon( const Ogre::String& textureName,
|
||||
const float size,
|
||||
const Ogre::Vector3& position,
|
||||
Ogre::SceneNode* rootNode
|
||||
);
|
||||
|
||||
enum Phase
|
||||
{
|
||||
Phase_New = 0,
|
||||
Phase_WaxingCrescent,
|
||||
Phase_WaxingHalf,
|
||||
Phase_WaxingGibbous,
|
||||
Phase_Full,
|
||||
Phase_WaningGibbous,
|
||||
Phase_WaningHalf,
|
||||
Phase_WaningCrescent
|
||||
};
|
||||
|
||||
enum Type
|
||||
{
|
||||
Type_Masser = 0,
|
||||
Type_Secunda
|
||||
};
|
||||
|
||||
void setPhase(const Phase& phase);
|
||||
void setType(const Type& type);
|
||||
|
||||
Phase getPhase() const;
|
||||
unsigned int getPhaseInt() const;
|
||||
|
||||
private:
|
||||
Type mType;
|
||||
Phase mPhase;
|
||||
};
|
||||
|
||||
class SkyManager
|
||||
{
|
||||
public:
|
||||
static SkyManager* create (Ogre::RenderWindow* pRenderWindow,
|
||||
Ogre::Camera* pCamera,
|
||||
const boost::filesystem::path& resDir);
|
||||
virtual ~SkyManager() {}
|
||||
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera);
|
||||
~SkyManager();
|
||||
|
||||
virtual void enable() = 0;
|
||||
void update(float duration);
|
||||
|
||||
virtual void disable() = 0;
|
||||
void enable();
|
||||
|
||||
virtual void setHour (double hour) = 0;
|
||||
void disable();
|
||||
|
||||
virtual void setDate (int day, int month) = 0;
|
||||
void setHour (double hour);
|
||||
///< will be called even when sky is disabled.
|
||||
|
||||
virtual int getMasserPhase() const = 0;
|
||||
void setDate (int day, int month);
|
||||
///< will be called even when sky is disabled.
|
||||
|
||||
virtual int getSecundaPhase() const = 0;
|
||||
int getMasserPhase() const;
|
||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||
/// 3 waxing or waning gibbous, 4 full moon
|
||||
|
||||
virtual void setMoonColour (bool red) = 0;
|
||||
int getSecundaPhase() const;
|
||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||
/// 3 waxing or waning gibbous, 4 full moon
|
||||
|
||||
void setMoonColour (bool red);
|
||||
///< change Secunda colour to red
|
||||
|
||||
void setCloudsOpacity(float opacity);
|
||||
///< change opacity of the clouds
|
||||
|
||||
void setWeather(const MWWorld::WeatherResult& weather);
|
||||
|
||||
void sunEnable();
|
||||
|
||||
void sunDisable();
|
||||
|
||||
void setSunDirection(const Ogre::Vector3& direction);
|
||||
|
||||
void setMasserDirection(const Ogre::Vector3& direction);
|
||||
|
||||
void setSecundaDirection(const Ogre::Vector3& direction);
|
||||
|
||||
void setMasserFade(const float fade);
|
||||
|
||||
void setSecundaFade(const float fade);
|
||||
|
||||
void masserEnable();
|
||||
void masserDisable();
|
||||
|
||||
void secundaEnable();
|
||||
void secundaDisable();
|
||||
|
||||
void setThunder(const float factor);
|
||||
|
||||
void setGlare(bool glare);
|
||||
Ogre::Vector3 getRealSunPos();
|
||||
|
||||
private:
|
||||
float mHour;
|
||||
int mDay;
|
||||
int mMonth;
|
||||
|
||||
BillboardObject* mSun;
|
||||
BillboardObject* mSunGlare;
|
||||
Moon* mMasser;
|
||||
Moon* mSecunda;
|
||||
|
||||
Ogre::Viewport* mViewport;
|
||||
Ogre::SceneNode* mRootNode;
|
||||
Ogre::SceneManager* mSceneMgr;
|
||||
|
||||
Ogre::SceneNode* mAtmosphereDay;
|
||||
Ogre::SceneNode* mAtmosphereNight;
|
||||
|
||||
Ogre::MaterialPtr mCloudMaterial;
|
||||
Ogre::MaterialPtr mAtmosphereMaterial;
|
||||
|
||||
Ogre::MaterialPtr mStarsMaterials[7];
|
||||
|
||||
Ogre::HighLevelGpuProgramPtr mCloudFragmentShader;
|
||||
|
||||
// remember some settings so we don't have to apply them again if they didnt change
|
||||
Ogre::String mClouds;
|
||||
Ogre::String mNextClouds;
|
||||
float mCloudBlendFactor;
|
||||
float mCloudOpacity;
|
||||
float mCloudSpeed;
|
||||
float mStarsOpacity;
|
||||
Ogre::ColourValue mCloudColour;
|
||||
Ogre::ColourValue mSkyColour;
|
||||
|
||||
Ogre::Overlay* mThunderOverlay;
|
||||
Ogre::TextureUnitState* mThunderTextureUnit;
|
||||
|
||||
float mRemainingTransitionTime;
|
||||
|
||||
float mGlareFade;
|
||||
|
||||
void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
|
||||
|
||||
bool mEnabled;
|
||||
bool mGlareEnabled;
|
||||
bool mSunEnabled;
|
||||
bool mMasserEnabled;
|
||||
bool mSecundaEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1020,8 +1020,10 @@ namespace Ogre
|
|||
{
|
||||
outStream <<
|
||||
// global normal
|
||||
" float3 normal = expand(tex2D(globalNormal, uv)).rgb;\n"
|
||||
" normal = float3(normal.x, normal.z, -normal.y); \n"; // convert Ogre to MW coordinate system
|
||||
" float3 normal = expand(tex2D(globalNormal, uv)).rgb;\n";
|
||||
|
||||
// not needed anymore apparently
|
||||
//" normal = float3(normal.x, normal.z, -normal.y); \n"; // convert Ogre to MW coordinate system
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
Interpreter::Type_Float x = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
Interpreter::Type_Float z = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
|
@ -53,16 +53,16 @@ namespace MWScript
|
|||
std::string actor = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float duration = runtime[0].mInteger;
|
||||
Interpreter::Type_Float duration = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
Interpreter::Type_Float x = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
Interpreter::Type_Float z = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
|
@ -99,9 +99,9 @@ namespace MWScript
|
|||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
extensions.registerInstruction ("aitravel", "lll/l", opcodeAiTravel,
|
||||
extensions.registerInstruction ("aitravel", "fff/l", opcodeAiTravel,
|
||||
opcodeAiTravelExplicit);
|
||||
extensions.registerInstruction ("aiescort", "cllll/l", opcodeAiEscort,
|
||||
extensions.registerInstruction ("aiescort", "cffff/l", opcodeAiEscort,
|
||||
opcodeAiEscortExplicit);
|
||||
|
||||
extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone,
|
||||
|
|
127
apps/openmw/mwscript/animationextensions.cpp
Normal file
127
apps/openmw/mwscript/animationextensions.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
|
||||
#include "animationextensions.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
#include <components/interpreter/interpreter.hpp>
|
||||
#include <components/interpreter/runtime.hpp>
|
||||
#include <components/interpreter/opcodes.hpp>
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Animation
|
||||
{
|
||||
template<class R>
|
||||
class OpSkipAnim : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
context.getWorld().skipAnimation (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpPlayAnim : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string group = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer mode = 0;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
mode = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (mode<0 || mode>2)
|
||||
throw std::runtime_error ("animation mode out of range");
|
||||
}
|
||||
|
||||
context.getWorld().playAnimationGroup (ptr, group, mode, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpLoopAnim : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string group = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer loops = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (loops<0)
|
||||
throw std::runtime_error ("number of animation loops must be non-negative");
|
||||
|
||||
Interpreter::Type_Integer mode = 0;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
mode = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (mode<0 || mode>2)
|
||||
throw std::runtime_error ("animation mode out of range");
|
||||
}
|
||||
|
||||
context.getWorld().playAnimationGroup (ptr, group, mode, loops);
|
||||
}
|
||||
};
|
||||
|
||||
const int opcodeSkipAnim = 0x2000138;
|
||||
const int opcodeSkipAnimExplicit = 0x2000139;
|
||||
const int opcodePlayAnim = 0x20006;
|
||||
const int opcodePlayAnimExplicit = 0x20007;
|
||||
const int opcodeLoopAnim = 0x20008;
|
||||
const int opcodeLoopAnimExplicit = 0x20009;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
extensions.registerInstruction ("skipanim", "", opcodeSkipAnim, opcodeSkipAnimExplicit);
|
||||
extensions.registerInstruction ("playgroup", "c/l", opcodePlayAnim, opcodePlayAnimExplicit);
|
||||
extensions.registerInstruction ("loopgroup", "cl/l", opcodeLoopAnim, opcodeLoopAnimExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
interpreter.installSegment5 (opcodeSkipAnim, new OpSkipAnim<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeSkipAnimExplicit, new OpSkipAnim<ExplicitRef>);
|
||||
interpreter.installSegment3 (opcodePlayAnim, new OpPlayAnim<ImplicitRef>);
|
||||
interpreter.installSegment3 (opcodePlayAnimExplicit, new OpPlayAnim<ExplicitRef>);
|
||||
interpreter.installSegment3 (opcodeLoopAnim, new OpLoopAnim<ImplicitRef>);
|
||||
interpreter.installSegment3 (opcodeLoopAnimExplicit, new OpLoopAnim<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
24
apps/openmw/mwscript/animationextensions.hpp
Normal file
24
apps/openmw/mwscript/animationextensions.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef GAME_SCRIPT_ANIMATIONEXTENSIONS_H
|
||||
#define GAME_SCRIPT_ANIMATIONEXTENSIONS_H
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Extensions;
|
||||
}
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
class Interpreter;
|
||||
}
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Animation
|
||||
{
|
||||
void registerExtensions (Compiler::Extensions& extensions);
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerutil.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
@ -45,8 +45,7 @@ namespace MWScript
|
|||
|
||||
ref.getPtr().getRefData().setCount (count);
|
||||
|
||||
MWWorld::Class::get (ref.getPtr()).insertIntoContainer (ref.getPtr(),
|
||||
MWWorld::Class::get (ptr).getContainerStore (ptr));
|
||||
MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -59,25 +58,16 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
std::vector<MWWorld::Ptr> list;
|
||||
|
||||
MWWorld::listItemsInContainer (item,
|
||||
MWWorld::Class::get (ptr).getContainerStore (ptr),
|
||||
context.getWorld().getStore(), list);
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
|
||||
Interpreter::Type_Integer sum = 0;
|
||||
|
||||
for (std::vector<MWWorld::Ptr>::iterator iter (list.begin()); iter!=list.end();
|
||||
++iter)
|
||||
{
|
||||
sum += iter->getRefData().getCount();
|
||||
}
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
|
||||
if (iter->getCellRef().refID==item)
|
||||
sum += iter->getRefData().getCount();
|
||||
|
||||
runtime.push (sum);
|
||||
}
|
||||
|
@ -92,9 +82,6 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
|
@ -104,25 +91,23 @@ namespace MWScript
|
|||
if (count<0)
|
||||
throw std::runtime_error ("second argument for RemoveItem must be non-negative");
|
||||
|
||||
std::vector<MWWorld::Ptr> list;
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
|
||||
MWWorld::listItemsInContainer (item,
|
||||
MWWorld::Class::get (ptr).getContainerStore (ptr),
|
||||
context.getWorld().getStore(), list);
|
||||
|
||||
for (std::vector<MWWorld::Ptr>::iterator iter (list.begin());
|
||||
iter!=list.end() && count;
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count;
|
||||
++iter)
|
||||
{
|
||||
if (iter->getRefData().getCount()<=count)
|
||||
if (iter->getCellRef().refID==item)
|
||||
{
|
||||
count -= iter->getRefData().getCount();
|
||||
iter->getRefData().setCount (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->getRefData().setCount (iter->getRefData().getCount()-count);
|
||||
count = 0;
|
||||
if (iter->getRefData().getCount()<=count)
|
||||
{
|
||||
count -= iter->getRefData().getCount();
|
||||
iter->getRefData().setCount (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->getRefData().setCount (iter->getRefData().getCount()-count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
#include "statsextensions.hpp"
|
||||
#include "controlextensions.hpp"
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace MWScript
|
|||
|
||||
bool enabled = context.getWorld().toggleCollisionMode();
|
||||
|
||||
context.report (enabled ? "Collsion -> On" : "Collision -> Off");
|
||||
context.report (enabled ? "Collision -> On" : "Collision -> Off");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ op 0x20002: AiEscort
|
|||
op 0x20003: AiEscort, explicit reference
|
||||
op 0x20004: Lock
|
||||
op 0x20005: Lock, explicit reference
|
||||
opcodes 0x20006-0x3ffff unused
|
||||
op 0x20006: PlayAnim
|
||||
op 0x20007: PlayAnim, explicit reference
|
||||
op 0x20008: LoopAnim
|
||||
op 0x20009: LoopAnim, explicit reference
|
||||
opcodes 0x2000a-0x3ffff unused
|
||||
|
||||
Segment 4:
|
||||
(not implemented yet)
|
||||
|
@ -109,4 +113,12 @@ op 0x2000134: SetJournalIndex
|
|||
op 0x2000135: GetJournalIndex
|
||||
op 0x2000136: GetPCCell
|
||||
op 0x2000137: GetButtonPressed
|
||||
opcodes 0x2000138-0x3ffffff unused
|
||||
op 0x2000138: SkipAnim
|
||||
op 0x2000139: SkipAnim, expplicit reference
|
||||
op 0x200013b: twf
|
||||
op 0x200013c: FadeIn
|
||||
op 0x200013d: FadeOut
|
||||
op 0x200013e: FadeTo
|
||||
op 0x200013f: GetCurrentWeather
|
||||
op 0x2000140: ChangeWeather
|
||||
opcodes 0x2000141-0x3ffffff unused
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "aiextensions.hpp"
|
||||
#include "controlextensions.hpp"
|
||||
#include "dialogueextensions.hpp"
|
||||
#include "animationextensions.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
|
@ -29,6 +30,7 @@ namespace MWScript
|
|||
Ai::registerExtensions (extensions);
|
||||
Control::registerExtensions (extensions);
|
||||
Dialogue::registerExtensions (extensions);
|
||||
Animation::registerExtensions (extensions);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -44,5 +46,6 @@ namespace MWScript
|
|||
Ai::installOpcodes (interpreter);
|
||||
Control::installOpcodes (interpreter);
|
||||
Dialogue::installOpcodes (interpreter);
|
||||
Animation::installOpcodes (interpreter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,75 @@ namespace MWScript
|
|||
context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug);
|
||||
|
||||
context.report (enabled ?
|
||||
"Collsion Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
|
||||
"Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
|
||||
}
|
||||
};
|
||||
|
||||
class OpToggleWireframe : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
bool enabled =
|
||||
context.getWorld().toggleRenderMode (MWWorld::World::Render_Wireframe);
|
||||
|
||||
context.report (enabled ?
|
||||
"Wireframe Rendering -> On" : "Wireframe Rendering -> Off");
|
||||
}
|
||||
};
|
||||
|
||||
class OpFadeIn : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
Interpreter::Type_Float time = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
context.getWorld().getFader()->fadeIn(time);
|
||||
}
|
||||
};
|
||||
|
||||
class OpFadeOut : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
Interpreter::Type_Float time = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
context.getWorld().getFader()->fadeOut(time);
|
||||
}
|
||||
};
|
||||
|
||||
class OpFadeTo : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
Interpreter::Type_Float alpha = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float time = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
context.getWorld().getFader()->fadeTo(alpha, time);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -115,6 +183,10 @@ namespace MWScript
|
|||
const int opcodeUnlock = 0x200008c;
|
||||
const int opcodeUnlockExplicit = 0x200008d;
|
||||
const int opcodeToggleCollisionDebug = 0x2000132;
|
||||
const int opcodeToggleWireframe = 0x200013b;
|
||||
const int opcodeFadeIn = 0x200013c;
|
||||
const int opcodeFadeOut = 0x200013d;
|
||||
const int opcodeFadeTo = 0x200013e;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
|
@ -127,6 +199,11 @@ namespace MWScript
|
|||
extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug);
|
||||
extensions.registerInstruction ("tcb", "", opcodeToggleCollisionDebug);
|
||||
extensions.registerInstruction ("tcg", "", opcodeToggleCollisionDebug);
|
||||
extensions.registerInstruction ("twf", "", opcodeToggleWireframe);
|
||||
extensions.registerInstruction ("togglewireframe", "", opcodeToggleWireframe);
|
||||
extensions.registerInstruction ("fadein", "f", opcodeFadeIn);
|
||||
extensions.registerInstruction ("fadeout", "f", opcodeFadeOut);
|
||||
extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -139,6 +216,10 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeUnlock, new OpUnlock<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock<ExplicitRef>);
|
||||
interpreter.installSegment5 (opcodeToggleCollisionDebug, new OpToggleCollisionDebug);
|
||||
interpreter.installSegment5 (opcodeToggleWireframe, new OpToggleWireframe);
|
||||
interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn);
|
||||
interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut);
|
||||
interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,12 +79,46 @@ namespace MWScript
|
|||
runtime.push (context.getWorld().getSecundaPhase());
|
||||
}
|
||||
};
|
||||
|
||||
class OpGetCurrentWeather : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
runtime.push (context.getWorld().getCurrentWeather());
|
||||
}
|
||||
};
|
||||
|
||||
class OpChangeWeather : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string region = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer id = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
context.getWorld().changeWeather(region, id);
|
||||
}
|
||||
};
|
||||
|
||||
const int opcodeToggleSky = 0x2000021;
|
||||
const int opcodeTurnMoonWhite = 0x2000022;
|
||||
const int opcodeTurnMoonRed = 0x2000023;
|
||||
const int opcodeGetMasserPhase = 0x2000024;
|
||||
const int opcodeGetSecundaPhase = 0x2000025;
|
||||
const int opcodeGetCurrentWeather = 0x200013f;
|
||||
const int opcodeChangeWeather = 0x2000140;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
|
@ -92,8 +126,10 @@ namespace MWScript
|
|||
extensions.registerInstruction ("ts", "", opcodeToggleSky);
|
||||
extensions.registerInstruction ("turnmoonwhite", "", opcodeTurnMoonWhite);
|
||||
extensions.registerInstruction ("turnmoonred", "", opcodeTurnMoonRed);
|
||||
extensions.registerInstruction ("changeweather", "Sl", opcodeChangeWeather);
|
||||
extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase);
|
||||
extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase);
|
||||
extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -103,6 +139,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed);
|
||||
interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase);
|
||||
interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase);
|
||||
interpreter.installSegment5 (opcodeGetCurrentWeather, new OpGetCurrentWeather);
|
||||
interpreter.installSegment5 (opcodeChangeWeather, new OpChangeWeather);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "class.hpp"
|
||||
#include "environment.hpp"
|
||||
#include "world.hpp"
|
||||
#include "containerstore.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -14,8 +15,7 @@ namespace MWWorld
|
|||
// insert into player's inventory
|
||||
MWWorld::Ptr player = environment.mWorld->getPtr ("player", true);
|
||||
|
||||
MWWorld::Class::get (mObject).insertIntoContainer (mObject,
|
||||
MWWorld::Class::get (player).getContainerStore (player));
|
||||
MWWorld::Class::get (player).getContainerStore (player).add (mObject);
|
||||
|
||||
// remove from world
|
||||
environment.mWorld->deleteObject (mObject);
|
||||
|
|
|
@ -63,10 +63,11 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y)
|
|||
|
||||
result = mExteriors.insert (std::make_pair (
|
||||
std::make_pair (x, y), Ptr::CellStore (cell))).first;
|
||||
|
||||
result->second.load (mStore, mReader);
|
||||
}
|
||||
|
||||
if (result->second.mState!=Ptr::CellStore::State_Loaded)
|
||||
result->second.load (mStore, mReader);
|
||||
|
||||
return &result->second;
|
||||
}
|
||||
|
||||
|
@ -79,10 +80,11 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
|||
const ESM::Cell *cell = mStore.cells.findInt (name);
|
||||
|
||||
result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first;
|
||||
|
||||
result->second.load (mStore, mReader);
|
||||
}
|
||||
|
||||
if (result->second.mState!=Ptr::CellStore::State_Loaded)
|
||||
result->second.load (mStore, mReader);
|
||||
|
||||
return &result->second;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "ptr.hpp"
|
||||
#include "nullaction.hpp"
|
||||
#include "containerstore.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -71,16 +72,11 @@ namespace MWWorld
|
|||
return boost::shared_ptr<Action> (new NullAction);
|
||||
}
|
||||
|
||||
ContainerStore<RefData>& Class::getContainerStore (const Ptr& ptr) const
|
||||
ContainerStore& Class::getContainerStore (const Ptr& ptr) const
|
||||
{
|
||||
throw std::runtime_error ("class does not have a container store");
|
||||
}
|
||||
|
||||
void Class::insertIntoContainer (const Ptr& ptr, ContainerStore<RefData>& containerStore) const
|
||||
{
|
||||
throw std::runtime_error ("class does not support inserting into a container");
|
||||
}
|
||||
|
||||
void Class::lock (const Ptr& ptr, int lockLevel) const
|
||||
{
|
||||
throw std::runtime_error ("class does not support locking");
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "action.hpp"
|
||||
#include "containerstore.hpp"
|
||||
#include "refdata.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
#include "physicssystem.hpp"
|
||||
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector3;
|
||||
|
@ -33,6 +33,7 @@ namespace MWWorld
|
|||
{
|
||||
class Ptr;
|
||||
class Environment;
|
||||
class ContainerStore;
|
||||
|
||||
/// \brief Base class for referenceable esm records
|
||||
class Class
|
||||
|
@ -61,8 +62,6 @@ namespace MWWorld
|
|||
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
|
||||
/// (default implementation: throw an exception)
|
||||
|
||||
|
||||
|
||||
virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
|
||||
///< Add reference into a cell for rendering (default implementation: don't render anything).
|
||||
|
@ -105,15 +104,10 @@ namespace MWWorld
|
|||
///< Generate action for using via inventory menu (default implementation: return a
|
||||
/// null action).
|
||||
|
||||
virtual ContainerStore<RefData>& getContainerStore (const Ptr& ptr) const;
|
||||
virtual ContainerStore& getContainerStore (const Ptr& ptr) const;
|
||||
///< Return container store or throw an exception, if class does not have a
|
||||
/// container store (default implementation: throw an exceoption)
|
||||
|
||||
virtual void insertIntoContainer (const Ptr& ptr, ContainerStore<RefData>& containerStore)
|
||||
const;
|
||||
///< Insert into a container or throw an exception, if class does not support inserting into
|
||||
/// a container.
|
||||
|
||||
virtual void lock (const Ptr& ptr, int lockLevel) const;
|
||||
///< Lock object (default implementation: throw an exception)
|
||||
|
||||
|
|
342
apps/openmw/mwworld/containerstore.cpp
Normal file
342
apps/openmw/mwworld/containerstore.cpp
Normal file
|
@ -0,0 +1,342 @@
|
|||
|
||||
#include "containerstore.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
#include <stdexcept>
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::begin (int mask)
|
||||
{
|
||||
return ContainerStoreIterator (mask, this);
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
|
||||
{
|
||||
return ContainerStoreIterator (this);
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::add (const Ptr& ptr)
|
||||
{
|
||||
/// \todo implement item stocking
|
||||
|
||||
switch (getType (ptr))
|
||||
{
|
||||
case Type_Potion: potions.list.push_back (*ptr.get<ESM::Potion>()); break;
|
||||
case Type_Apparatus: appas.list.push_back (*ptr.get<ESM::Apparatus>()); break;
|
||||
case Type_Armor: armors.list.push_back (*ptr.get<ESM::Armor>()); break;
|
||||
case Type_Book: books.list.push_back (*ptr.get<ESM::Book>()); break;
|
||||
case Type_Clothing: clothes.list.push_back (*ptr.get<ESM::Clothing>()); break;
|
||||
case Type_Ingredient: ingreds.list.push_back (*ptr.get<ESM::Ingredient>()); break;
|
||||
case Type_Light: lights.list.push_back (*ptr.get<ESM::Light>()); break;
|
||||
case Type_Lockpick: lockpicks.list.push_back (*ptr.get<ESM::Tool>()); break;
|
||||
case Type_Miscellaneous: miscItems.list.push_back (*ptr.get<ESM::Miscellaneous>()); break;
|
||||
case Type_Probe: probes.list.push_back (*ptr.get<ESM::Probe>()); break;
|
||||
case Type_Repair: repairs.list.push_back (*ptr.get<ESM::Repair>()); break;
|
||||
case Type_Weapon: weapons.list.push_back (*ptr.get<ESM::Weapon>()); break;
|
||||
}
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::getType (const Ptr& ptr)
|
||||
{
|
||||
if (ptr.isEmpty())
|
||||
throw std::runtime_error ("can't put a non-existent object into a container");
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Potion).name())
|
||||
return Type_Potion;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Apparatus).name())
|
||||
return Type_Apparatus;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Armor).name())
|
||||
return Type_Armor;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Book).name())
|
||||
return Type_Book;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Clothing).name())
|
||||
return Type_Clothing;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Ingredient).name())
|
||||
return Type_Ingredient;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Light).name())
|
||||
return Type_Light;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Tool).name())
|
||||
return Type_Lockpick;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Miscellaneous).name())
|
||||
return Type_Miscellaneous;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Probe).name())
|
||||
return Type_Probe;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Repair).name())
|
||||
return Type_Repair;
|
||||
|
||||
if (ptr.getTypeName()==typeid (ESM::Weapon).name())
|
||||
return Type_Weapon;
|
||||
|
||||
throw std::runtime_error (
|
||||
"Object of type " + ptr.getTypeName() + " can not be placed into a container");
|
||||
}
|
||||
|
||||
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container)
|
||||
: mType (-1), mMask (0), mContainer (container)
|
||||
{}
|
||||
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStore *container)
|
||||
: mType (0), mMask (mask), mContainer (container)
|
||||
{
|
||||
nextType();
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStoreIterator::incType()
|
||||
{
|
||||
if (mType==0)
|
||||
mType = 1;
|
||||
else if (mType!=-1)
|
||||
{
|
||||
mType <<= 1;
|
||||
|
||||
if (mType>ContainerStore::Type_Last)
|
||||
mType = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStoreIterator::nextType()
|
||||
{
|
||||
while (mType!=-1)
|
||||
{
|
||||
incType();
|
||||
|
||||
if (mType & mMask)
|
||||
if (resetIterator())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MWWorld::ContainerStoreIterator::resetIterator()
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case ContainerStore::Type_Potion:
|
||||
|
||||
mPotion = mContainer->potions.list.begin();
|
||||
return mPotion!=mContainer->potions.list.end();
|
||||
|
||||
case ContainerStore::Type_Apparatus:
|
||||
|
||||
mApparatus = mContainer->appas.list.begin();
|
||||
return mApparatus!=mContainer->appas.list.end();
|
||||
|
||||
case ContainerStore::Type_Armor:
|
||||
|
||||
mArmor = mContainer->armors.list.begin();
|
||||
return mArmor!=mContainer->armors.list.end();
|
||||
|
||||
case ContainerStore::Type_Book:
|
||||
|
||||
mBook = mContainer->books.list.begin();
|
||||
return mBook!=mContainer->books.list.end();
|
||||
|
||||
case ContainerStore::Type_Clothing:
|
||||
|
||||
mClothing = mContainer->clothes.list.begin();
|
||||
return mClothing!=mContainer->clothes.list.end();
|
||||
|
||||
case ContainerStore::Type_Ingredient:
|
||||
|
||||
mIngredient = mContainer->ingreds.list.begin();
|
||||
return mIngredient!=mContainer->ingreds.list.end();
|
||||
|
||||
case ContainerStore::Type_Light:
|
||||
|
||||
mLight = mContainer->lights.list.begin();
|
||||
return mLight!=mContainer->lights.list.end();
|
||||
|
||||
case ContainerStore::Type_Lockpick:
|
||||
|
||||
mLockpick = mContainer->lockpicks.list.begin();
|
||||
return mLockpick!=mContainer->lockpicks.list.end();
|
||||
|
||||
case ContainerStore::Type_Miscellaneous:
|
||||
|
||||
mMiscellaneous = mContainer->miscItems.list.begin();
|
||||
return mMiscellaneous!=mContainer->miscItems.list.end();
|
||||
|
||||
case ContainerStore::Type_Probe:
|
||||
|
||||
mProbe = mContainer->probes.list.begin();
|
||||
return mProbe!=mContainer->probes.list.end();
|
||||
|
||||
case ContainerStore::Type_Repair:
|
||||
|
||||
mRepair = mContainer->repairs.list.begin();
|
||||
return mRepair!=mContainer->repairs.list.end();
|
||||
|
||||
case ContainerStore::Type_Weapon:
|
||||
|
||||
mWeapon = mContainer->weapons.list.begin();
|
||||
return mWeapon!=mContainer->weapons.list.end();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MWWorld::ContainerStoreIterator::incIterator()
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case ContainerStore::Type_Potion:
|
||||
|
||||
++mPotion;
|
||||
return mPotion==mContainer->potions.list.end();
|
||||
|
||||
case ContainerStore::Type_Apparatus:
|
||||
|
||||
++mApparatus;
|
||||
return mApparatus==mContainer->appas.list.end();
|
||||
|
||||
case ContainerStore::Type_Armor:
|
||||
|
||||
++mArmor;
|
||||
return mArmor==mContainer->armors.list.end();
|
||||
|
||||
case ContainerStore::Type_Book:
|
||||
|
||||
++mBook;
|
||||
return mBook==mContainer->books.list.end();
|
||||
|
||||
case ContainerStore::Type_Clothing:
|
||||
|
||||
++mClothing;
|
||||
return mClothing==mContainer->clothes.list.end();
|
||||
|
||||
case ContainerStore::Type_Ingredient:
|
||||
|
||||
++mIngredient;
|
||||
return mIngredient==mContainer->ingreds.list.end();
|
||||
|
||||
case ContainerStore::Type_Light:
|
||||
|
||||
++mLight;
|
||||
return mLight==mContainer->lights.list.end();
|
||||
|
||||
case ContainerStore::Type_Lockpick:
|
||||
|
||||
++mLockpick;
|
||||
return mLockpick==mContainer->lockpicks.list.end();
|
||||
|
||||
case ContainerStore::Type_Miscellaneous:
|
||||
|
||||
++mMiscellaneous;
|
||||
return mMiscellaneous==mContainer->miscItems.list.end();
|
||||
|
||||
case ContainerStore::Type_Probe:
|
||||
|
||||
++mProbe;
|
||||
return mProbe==mContainer->probes.list.end();
|
||||
|
||||
case ContainerStore::Type_Repair:
|
||||
|
||||
++mRepair;
|
||||
return mRepair==mContainer->repairs.list.end();
|
||||
|
||||
case ContainerStore::Type_Weapon:
|
||||
|
||||
++mWeapon;
|
||||
return mWeapon==mContainer->weapons.list.end();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MWWorld::Ptr *MWWorld::ContainerStoreIterator::operator->() const
|
||||
{
|
||||
mPtr = **this;
|
||||
return &mPtr;
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWWorld::ContainerStoreIterator::operator*() const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case ContainerStore::Type_Potion: return MWWorld::Ptr (&*mPotion, 0);
|
||||
case ContainerStore::Type_Apparatus: return MWWorld::Ptr (&*mApparatus, 0);
|
||||
case ContainerStore::Type_Armor: return MWWorld::Ptr (&*mArmor, 0);
|
||||
case ContainerStore::Type_Book: return MWWorld::Ptr (&*mBook, 0);
|
||||
case ContainerStore::Type_Clothing: return MWWorld::Ptr (&*mClothing, 0);
|
||||
case ContainerStore::Type_Ingredient: return MWWorld::Ptr (&*mIngredient, 0);
|
||||
case ContainerStore::Type_Light: return MWWorld::Ptr (&*mLight, 0);
|
||||
case ContainerStore::Type_Lockpick: return MWWorld::Ptr (&*mLockpick, 0);
|
||||
case ContainerStore::Type_Miscellaneous: return MWWorld::Ptr (&*mMiscellaneous, 0);
|
||||
case ContainerStore::Type_Probe: return MWWorld::Ptr (&*mProbe, 0);
|
||||
case ContainerStore::Type_Repair: return MWWorld::Ptr (&*mRepair, 0);
|
||||
case ContainerStore::Type_Weapon: return MWWorld::Ptr (&*mWeapon, 0);
|
||||
}
|
||||
|
||||
throw std::runtime_error ("invalid pointer");
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator& MWWorld::ContainerStoreIterator::operator++()
|
||||
{
|
||||
do
|
||||
{
|
||||
if (incIterator())
|
||||
nextType();
|
||||
}
|
||||
while (mType!=-1 && !(**this).getRefData().getCount());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStoreIterator::operator++ (int)
|
||||
{
|
||||
ContainerStoreIterator iter (*this);
|
||||
++*this;
|
||||
return iter;
|
||||
}
|
||||
|
||||
bool MWWorld::ContainerStoreIterator::isEqual (const ContainerStoreIterator& iter) const
|
||||
{
|
||||
assert (mContainer==iter.mContainer);
|
||||
|
||||
if (mType!=iter.mType)
|
||||
return false;
|
||||
|
||||
switch (mType)
|
||||
{
|
||||
case ContainerStore::Type_Potion: return mPotion==iter.mPotion;
|
||||
case ContainerStore::Type_Apparatus: return mApparatus==iter.mApparatus;
|
||||
case ContainerStore::Type_Armor: return mArmor==iter.mArmor;
|
||||
case ContainerStore::Type_Book: return mBook==iter.mBook;
|
||||
case ContainerStore::Type_Clothing: return mClothing==iter.mClothing;
|
||||
case ContainerStore::Type_Ingredient: return mIngredient==iter.mIngredient;
|
||||
case ContainerStore::Type_Light: return mLight==iter.mLight;
|
||||
case ContainerStore::Type_Lockpick: return mLockpick==iter.mLockpick;
|
||||
case ContainerStore::Type_Miscellaneous: return mMiscellaneous==iter.mMiscellaneous;
|
||||
case ContainerStore::Type_Probe: return mProbe==iter.mProbe;
|
||||
case ContainerStore::Type_Repair: return mRepair==iter.mRepair;
|
||||
case ContainerStore::Type_Weapon: return mWeapon==iter.mWeapon;
|
||||
case -1: return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStoreIterator::getType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
bool MWWorld::operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right)
|
||||
{
|
||||
return left.isEqual (right);
|
||||
}
|
||||
|
||||
bool MWWorld::operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right)
|
||||
{
|
||||
return !(left==right);
|
||||
}
|
|
@ -3,24 +3,134 @@
|
|||
|
||||
#include <components/esm_store/cell_store.hpp>
|
||||
|
||||
#include "refdata.hpp"
|
||||
#include "ptr.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
template<typename D>
|
||||
struct ContainerStore
|
||||
class ContainerStoreIterator;
|
||||
|
||||
class ContainerStore
|
||||
{
|
||||
ESMS::CellRefList<ESM::Potion, D> potions;
|
||||
ESMS::CellRefList<ESM::Apparatus, D> appas;
|
||||
ESMS::CellRefList<ESM::Armor, D> armors;
|
||||
ESMS::CellRefList<ESM::Book, D> books;
|
||||
ESMS::CellRefList<ESM::Clothing, D> clothes;
|
||||
ESMS::CellRefList<ESM::Ingredient, D> ingreds;
|
||||
ESMS::CellRefList<ESM::Light, D> lights;
|
||||
ESMS::CellRefList<ESM::Tool, D> lockpicks;
|
||||
ESMS::CellRefList<ESM::Miscellaneous, D> miscItems;
|
||||
ESMS::CellRefList<ESM::Probe, D> probes;
|
||||
ESMS::CellRefList<ESM::Repair, D> repairs;
|
||||
ESMS::CellRefList<ESM::Weapon, D> weapons;
|
||||
public:
|
||||
|
||||
static const int Type_Potion = 0x0001;
|
||||
static const int Type_Apparatus = 0x0002;
|
||||
static const int Type_Armor = 0x0004;
|
||||
static const int Type_Book = 0x0008;
|
||||
static const int Type_Clothing = 0x0010;
|
||||
static const int Type_Ingredient = 0x0020;
|
||||
static const int Type_Light = 0x0040;
|
||||
static const int Type_Lockpick = 0x0080;
|
||||
static const int Type_Miscellaneous = 0x0100;
|
||||
static const int Type_Probe = 0x0200;
|
||||
static const int Type_Repair = 0x0400;
|
||||
static const int Type_Weapon = 0x0800;
|
||||
|
||||
static const int Type_Last = Type_Weapon;
|
||||
|
||||
static const int Type_All = 0xffff;
|
||||
|
||||
private:
|
||||
|
||||
ESMS::CellRefList<ESM::Potion, RefData> potions;
|
||||
ESMS::CellRefList<ESM::Apparatus, RefData> appas;
|
||||
ESMS::CellRefList<ESM::Armor, RefData> armors;
|
||||
ESMS::CellRefList<ESM::Book, RefData> books;
|
||||
ESMS::CellRefList<ESM::Clothing, RefData> clothes;
|
||||
ESMS::CellRefList<ESM::Ingredient, RefData> ingreds;
|
||||
ESMS::CellRefList<ESM::Light, RefData> lights;
|
||||
ESMS::CellRefList<ESM::Tool, RefData> lockpicks;
|
||||
ESMS::CellRefList<ESM::Miscellaneous, RefData> miscItems;
|
||||
ESMS::CellRefList<ESM::Probe, RefData> probes;
|
||||
ESMS::CellRefList<ESM::Repair, RefData> repairs;
|
||||
ESMS::CellRefList<ESM::Weapon, RefData> weapons;
|
||||
|
||||
public:
|
||||
|
||||
ContainerStoreIterator begin (int mask = Type_All);
|
||||
|
||||
ContainerStoreIterator end();
|
||||
|
||||
void add (const Ptr& ptr);
|
||||
///< Add the item pointed to by \a ptr to this container.
|
||||
///
|
||||
/// \note The item pointed to is not required to exist beyond this function call.
|
||||
///
|
||||
/// \attention Do not add items to an existing stack by increasing the count instead of
|
||||
/// calling this function!
|
||||
|
||||
static int getType (const Ptr& ptr);
|
||||
///< This function throws an exception, if ptr does not point to an object, that can be
|
||||
/// put into a container.
|
||||
|
||||
friend class ContainerStoreIterator;
|
||||
};
|
||||
|
||||
/// \brief Iteration over a subset of objects in a ContainerStore
|
||||
///
|
||||
/// \note The iterator will automatically skip over deleted objects.
|
||||
class ContainerStoreIterator
|
||||
{
|
||||
int mType;
|
||||
int mMask;
|
||||
ContainerStore *mContainer;
|
||||
mutable Ptr mPtr;
|
||||
|
||||
ESMS::CellRefList<ESM::Potion, RefData>::List::iterator mPotion;
|
||||
ESMS::CellRefList<ESM::Apparatus, RefData>::List::iterator mApparatus;
|
||||
ESMS::CellRefList<ESM::Armor, RefData>::List::iterator mArmor;
|
||||
ESMS::CellRefList<ESM::Book, RefData>::List::iterator mBook;
|
||||
ESMS::CellRefList<ESM::Clothing, RefData>::List::iterator mClothing;
|
||||
ESMS::CellRefList<ESM::Ingredient, RefData>::List::iterator mIngredient;
|
||||
ESMS::CellRefList<ESM::Light, RefData>::List::iterator mLight;
|
||||
ESMS::CellRefList<ESM::Tool, RefData>::List::iterator mLockpick;
|
||||
ESMS::CellRefList<ESM::Miscellaneous, RefData>::List::iterator mMiscellaneous;
|
||||
ESMS::CellRefList<ESM::Probe, RefData>::List::iterator mProbe;
|
||||
ESMS::CellRefList<ESM::Repair, RefData>::List::iterator mRepair;
|
||||
ESMS::CellRefList<ESM::Weapon, RefData>::List::iterator mWeapon;
|
||||
|
||||
private:
|
||||
|
||||
ContainerStoreIterator (ContainerStore *container);
|
||||
///< End-iterator
|
||||
|
||||
ContainerStoreIterator (int mask, ContainerStore *container);
|
||||
///< Begin-iterator
|
||||
|
||||
void incType();
|
||||
|
||||
void nextType();
|
||||
|
||||
bool resetIterator();
|
||||
///< Reset iterator for selected type.
|
||||
///
|
||||
/// \return Type not empty?
|
||||
|
||||
bool incIterator();
|
||||
///< Increment iterator for selected type.
|
||||
///
|
||||
/// \return reached the end?
|
||||
|
||||
public:
|
||||
|
||||
Ptr *operator->() const;
|
||||
|
||||
Ptr operator*() const;
|
||||
|
||||
ContainerStoreIterator& operator++();
|
||||
|
||||
ContainerStoreIterator operator++ (int);
|
||||
|
||||
bool isEqual (const ContainerStoreIterator& iter) const;
|
||||
|
||||
int getType() const;
|
||||
|
||||
friend class ContainerStore;
|
||||
};
|
||||
|
||||
bool operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right);
|
||||
bool operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
|
||||
#include "containerutil.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
void listItemsInContainerImp (const std::string& id,
|
||||
ESMS::CellRefList<T, MWWorld::RefData>& containerStore,
|
||||
const ESMS::RecListT<T>& store, std::vector<MWWorld::Ptr>& list)
|
||||
{
|
||||
if (const T *record = store.search (id))
|
||||
{
|
||||
for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter
|
||||
(containerStore.list.begin());
|
||||
iter!=containerStore.list.end(); ++iter)
|
||||
{
|
||||
if (iter->base==record)
|
||||
list.push_back (MWWorld::Ptr (&*iter, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
void listItemsInContainer (const std::string& id,
|
||||
ContainerStore<MWWorld::RefData>& containerStore,
|
||||
const ESMS::ESMStore& store, std::vector<Ptr>& list)
|
||||
{
|
||||
listItemsInContainerImp (id, containerStore.potions, store.potions, list);
|
||||
listItemsInContainerImp (id, containerStore.appas, store.appas, list);
|
||||
listItemsInContainerImp (id, containerStore.armors, store.armors, list);
|
||||
listItemsInContainerImp (id, containerStore.books, store.books, list);
|
||||
listItemsInContainerImp (id, containerStore.clothes, store.clothes, list);
|
||||
listItemsInContainerImp (id, containerStore.ingreds, store.ingreds, list);
|
||||
listItemsInContainerImp (id, containerStore.lights, store.lights, list);
|
||||
listItemsInContainerImp (id, containerStore.lockpicks, store.lockpicks, list);
|
||||
listItemsInContainerImp (id, containerStore.miscItems, store.miscItems, list);
|
||||
listItemsInContainerImp (id, containerStore.probes, store.probes, list);
|
||||
listItemsInContainerImp (id, containerStore.repairs, store.repairs, list);
|
||||
listItemsInContainerImp (id, containerStore.weapons, store.weapons, list);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef GAME_MWWORLD_CONTAINERUTIL_H
|
||||
#define GAME_MWWORLD_CONTAINERUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm_store/store.hpp>
|
||||
|
||||
#include "containerstore.hpp"
|
||||
#include "ptr.hpp"
|
||||
#include "refdata.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
void listItemsInContainer (const std::string& id, ContainerStore<MWWorld::RefData>& containerStore,
|
||||
const ESMS::ESMStore& store, std::vector<Ptr>& list);
|
||||
///< append all references with the given id to list.
|
||||
}
|
||||
|
||||
#endif
|
17
apps/openmw/mwworld/customdata.hpp
Normal file
17
apps/openmw/mwworld/customdata.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef GAME_MWWORLD_CUSTOMDATA_H
|
||||
#define GAME_MWWORLD_CUSTOMDATA_H
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
/// \brief Base class for the MW-class-specific part of RefData
|
||||
class CustomData
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CustomData() {}
|
||||
|
||||
virtual CustomData *clone() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -82,6 +82,7 @@ namespace MWWorld
|
|||
|
||||
// initialise
|
||||
ESM::CellRef& cellRef = mPtr.getCellRef();
|
||||
cellRef.refID = name;
|
||||
cellRef.refnum = -1;
|
||||
cellRef.scale = 1;
|
||||
cellRef.factIndex = 0;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "physicssystem.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/world.hpp" // FIXME
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
|
||||
#include "OgreRoot.h"
|
||||
#include "OgreRenderWindow.h"
|
||||
|
@ -16,16 +17,24 @@ using namespace Ogre;
|
|||
namespace MWWorld
|
||||
{
|
||||
|
||||
PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng) :
|
||||
mRender(_rend), mEngine(physEng), mFreeFly (true)
|
||||
PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) :
|
||||
mRender(_rend), mEngine(0), mFreeFly (true)
|
||||
{
|
||||
|
||||
// Create physics. shapeLoader is deleted by the physic engine
|
||||
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
|
||||
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
|
||||
}
|
||||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
{
|
||||
|
||||
delete mEngine;
|
||||
|
||||
}
|
||||
OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
|
||||
{
|
||||
return mEngine;
|
||||
}
|
||||
|
||||
std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world)
|
||||
{
|
||||
std::string handle = "";
|
||||
|
@ -41,6 +50,17 @@ namespace MWWorld
|
|||
|
||||
return mEngine->rayTest(from,to);
|
||||
}
|
||||
|
||||
bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to)
|
||||
{
|
||||
btVector3 _from, _to;
|
||||
_from = btVector3(from.x, from.y, from.z);
|
||||
_to = btVector3(to.x, to.y, to.z);
|
||||
|
||||
std::pair<std::string, float> result = mEngine->rayTest(_from, _to);
|
||||
|
||||
return !(result.first == "");
|
||||
}
|
||||
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
|
||||
|
@ -145,6 +165,12 @@ namespace MWWorld
|
|||
|
||||
void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation)
|
||||
{
|
||||
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
|
||||
{
|
||||
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
|
||||
// start positions others than 0, 0, 0
|
||||
act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::scaleObject (const std::string& handle, float scale)
|
||||
|
@ -191,6 +217,7 @@ namespace MWWorld
|
|||
|
||||
void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
|
||||
// std::cout << "Adding node with name" << node->getName();
|
||||
addActor (node->getName(), model, node->getPosition());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MWWorld
|
|||
class PhysicsSystem
|
||||
{
|
||||
public:
|
||||
PhysicsSystem (OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng);
|
||||
PhysicsSystem (OEngine::Render::OgreRenderer &_rend);
|
||||
~PhysicsSystem ();
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration,
|
||||
|
@ -33,11 +33,17 @@ namespace MWWorld
|
|||
void scaleObject (const std::string& handle, float scale);
|
||||
|
||||
bool toggleCollisionMode();
|
||||
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||
|
||||
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||
|
||||
// cast ray, return true if it hit something
|
||||
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);
|
||||
|
||||
void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model);
|
||||
|
||||
void insertActorPhysics(const MWWorld::Ptr&, std::string model);
|
||||
void insertActorPhysics(const MWWorld::Ptr&, std::string model);
|
||||
|
||||
OEngine::Physic::PhysicEngine* getEngine();
|
||||
|
||||
private:
|
||||
OEngine::Render::OgreRenderer &mRender;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "../mwrender/player.hpp"
|
||||
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
|
||||
#include "world.hpp"
|
||||
#include "class.hpp"
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#include <components/esm/loadcell.hpp>
|
||||
|
||||
#include <components/esm_store/cell_store.hpp>
|
||||
|
||||
#include "refdata.hpp"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue