Merge remote-tracking branch 'scrawl/osg' into appveyor-osg

coverity_scan
Alexander "Ace" Olofsson 10 years ago
commit c40f59179f

@ -5,6 +5,7 @@ language: cpp
branches: branches:
only: only:
- master - master
- osg
- coverity_scan - coverity_scan
- /openmw-.*$/ - /openmw-.*$/
env: env:
@ -48,9 +49,9 @@ notifications:
email: email:
on_success: change on_success: change
on_failure: always on_failure: always
irc: #irc:
channels: # channels:
- "chat.freenode.net#openmw" # - "chat.freenode.net#openmw"
on_success: change # on_success: change
on_failure: always # on_failure: always
use_notice: true # use_notice: true

@ -12,9 +12,10 @@ echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_
echo "yes" | sudo apt-add-repository ppa:openmw/openmw echo "yes" | sudo apt-add-repository ppa:openmw/openmw
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq libgtest-dev google-mock sudo apt-get install -qq libgtest-dev google-mock
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev sudo apt-get install -qq libbullet-dev libopenscenegraph-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
sudo apt-get install -qq cmake-data #workaround for broken osgqt cmake script in ubuntu 12.04
if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi
sudo mkdir /usr/src/gtest/build sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build cd /usr/src/gtest/build

@ -54,15 +54,13 @@ endif (ANDROID)
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp") configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp")
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE) option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE) option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE) option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
set(CUSTOM_OGRE_PLUGIN_DIR "" CACHE PATH "Specify a custom directory for Ogre plugins (autodetected by default)")
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE) option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
# Apps and tools # Apps and tools
option(BUILD_OPENMW "build OpenMW" ON)
option(BUILD_BSATOOL "build BSA extractor" ON) option(BUILD_BSATOOL "build BSA extractor" ON)
option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_ESMTOOL "build ESM inspector" ON)
option(BUILD_LAUNCHER "build Launcher" ON) option(BUILD_LAUNCHER "build Launcher" ON)
@ -72,7 +70,6 @@ option(BUILD_OPENCS "build OpenMW Construction Set" ON)
option(BUILD_WIZARD "build Installation Wizard" ON) option(BUILD_WIZARD "build Installation Wizard" ON)
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
option(BUILD_NIFTEST "build nif file tester" OFF)
option(BUILD_MYGUI_PLUGIN "build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON) option(BUILD_MYGUI_PLUGIN "build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON)
# OS X deployment # OS X deployment
@ -136,17 +133,11 @@ endif()
if (WIN32) if (WIN32)
if(NOT MINGW) if(NOT MINGW)
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
set(PLATFORM_INCLUDE_DIR "platform")
add_definitions(-DBOOST_ALL_NO_LIB) add_definitions(-DBOOST_ALL_NO_LIB)
endif(NOT MINGW) endif(NOT MINGW)
# Suppress WinMain(), provided by SDL # Suppress WinMain(), provided by SDL
add_definitions(-DSDL_MAIN_HANDLED) add_definitions(-DSDL_MAIN_HANDLED)
else (WIN32)
set(PLATFORM_INCLUDE_DIR "")
endif (WIN32)
if (MSVC10)
set(PLATFORM_INCLUDE_DIR "")
endif() endif()
# Dependencies # Dependencies
@ -180,10 +171,8 @@ IF(BOOST_STATIC)
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
endif() endif()
find_package(OGRE REQUIRED) find_package(OpenSceneGraph 3.2.0 REQUIRED osgDB osgViewer osgGA osgAnimation osgParticle osgQt osgUtil osgFX)
if (${OGRE_VERSION} VERSION_LESS "1.9") include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
message(FATAL_ERROR "OpenMW requires Ogre 1.9 or later, please install the latest stable version from http://ogre3d.org")
endif()
find_package(MyGUI REQUIRED) find_package(MyGUI REQUIRED)
if (${MYGUI_VERSION} VERSION_LESS "3.2.1") if (${MYGUI_VERSION} VERSION_LESS "3.2.1")
@ -195,87 +184,22 @@ find_package(SDL2 REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet REQUIRED) find_package(Bullet REQUIRED)
set(OGRE_PLUGIN_INCLUDE_DIRS "") include_directories("."
set(OGRE_STATIC_PLUGINS "")
macro(add_static_ogre_plugin PLUGIN)
if(OGRE_${PLUGIN}_FOUND)
# strip RenderSystem_ or Plugin_ prefix from plugin name
string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN})
string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP})
add_definitions(-DENABLE_PLUGIN_${PLUGIN_NAME})
list(APPEND OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_${PLUGIN}_INCLUDE_DIRS})
list(APPEND OGRE_STATIC_PLUGINS ${OGRE_${PLUGIN}_LIBRARIES})
endif(OGRE_${PLUGIN}_FOUND)
endmacro(add_static_ogre_plugin)
if(OGRE_STATIC)
# set up OGRE_PLUGIN_INCLUDE_DIRS and OGRE_STATIC_PLUGINS
add_static_ogre_plugin(Plugin_OctreeSceneManager)
add_static_ogre_plugin(Plugin_ParticleFX)
find_package(Cg)
if(Cg_FOUND)
add_static_ogre_plugin(Plugin_CgProgramManager)
list(APPEND OGRE_STATIC_PLUGINS ${Cg_LIBRARIES})
endif(Cg_FOUND)
if (ANDROID)
add_static_ogre_plugin(RenderSystem_GLES2)
else ()
add_static_ogre_plugin(RenderSystem_GL)
endif ()
if(WIN32)
add_static_ogre_plugin(RenderSystem_Direct3D9)
endif(WIN32)
endif(OGRE_STATIC)
include_directories("." ${LIBS_DIR}
SYSTEM SYSTEM
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR}
${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
${PLATFORM_INCLUDE_DIR}
${MYGUI_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${BULLET_INCLUDE_DIRS} ${BULLET_INCLUDE_DIRS}
) )
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${MYGUI_LIB_DIR})
if(MYGUI_STATIC) if(MYGUI_STATIC)
add_definitions(-DMYGUI_STATIC) add_definitions(-DMYGUI_STATIC)
endif (MYGUI_STATIC) endif (MYGUI_STATIC)
if (APPLE) if (APPLE)
# List used Ogre plugins
SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL}
${OGRE_Plugin_ParticleFX_LIBRARY_REL})
# Actually we must use OGRE_Plugin_CgProgramManager_FOUND but it's
# not reliable and equals TRUE even if there's no Ogre Cg plugin
if (Cg_FOUND)
set(USED_OGRE_PLUGINS ${USED_OGRE_PLUGINS}
${OGRE_Plugin_CgProgramManager_LIBRARY_REL})
endif ()
if (${OGRE_PLUGIN_DIR_REL}})
set(OGRE_PLUGINS_REL_FOUND TRUE)
endif ()
if (${OGRE_PLUGIN_DIR_DBG})
set(OGRE_PLUGINS_DBG_FOUND TRUE)
endif ()
if (${OGRE_PLUGINS_REL_FOUND})
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
else ()
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
endif ()
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
"${APP_BUNDLE_DIR}/Contents/Info.plist") "${APP_BUNDLE_DIR}/Contents/Info.plist")
@ -286,30 +210,7 @@ endif (APPLE)
# Set up DEBUG define # Set up DEBUG define
set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1) set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1)
# Set up Ogre plugin folder & debug suffix
if (APPLE)
# Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt)
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="")
else ()
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
endif()
if (APPLE AND OPENMW_OSX_DEPLOYMENT)
# make it empty so plugin loading code can check this and try to find plugins inside app bundle
add_definitions(-DOGRE_PLUGIN_DIR="")
else()
if (CUSTOM_OGRE_PLUGIN_DIR STREQUAL "")
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
else()
set(OGRE_PLUGIN_DIR ${CUSTOM_OGRE_PLUGIN_DIR})
endif()
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
endif()
add_subdirectory(files/) add_subdirectory(files/)
add_subdirectory(files/mygui)
# Specify build paths # Specify build paths
@ -326,9 +227,6 @@ endif (APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}/settings-default.cfg") "${OpenMW_BINARY_DIR}/settings-default.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/transparency-overrides.cfg
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
"${OpenMW_BINARY_DIR}/openmw.cfg") "${OpenMW_BINARY_DIR}/openmw.cfg")
@ -394,7 +292,9 @@ IF(NOT WIN32 AND NOT APPLE)
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir") SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
# Install binaries # Install binaries
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" ) IF(BUILD_OPENMW)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
ENDIF(BUILD_OPENMW)
IF(BUILD_LAUNCHER) IF(BUILD_LAUNCHER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-launcher" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-launcher" DESTINATION "${BINDIR}" )
ENDIF(BUILD_LAUNCHER) ENDIF(BUILD_LAUNCHER)
@ -413,19 +313,15 @@ IF(NOT WIN32 AND NOT APPLE)
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-cs" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-cs" DESTINATION "${BINDIR}" )
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
IF(BUILD_NIFTEST)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
ENDIF(BUILD_NIFTEST)
IF(BUILD_WIZARD) IF(BUILD_WIZARD)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" )
ENDIF(BUILD_WIZARD) ENDIF(BUILD_WIZARD)
if(BUILD_MYGUI_PLUGIN) #if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" ) # INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" )
ENDIF(BUILD_MYGUI_PLUGIN) #ENDIF(BUILD_MYGUI_PLUGIN)
# Install licenses # Install licenses
INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
# Install icon and desktop file # Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
@ -437,7 +333,6 @@ IF(NOT WIN32 AND NOT APPLE)
# Install global configuration files # Install global configuration files
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
@ -460,7 +355,6 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt" "${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt"
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt"
"${OpenMW_BINARY_DIR}/Release/openmw.exe" "${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".") DESTINATION ".")
@ -546,31 +440,22 @@ if(WIN32)
include(CPack) include(CPack)
endif(WIN32) endif(WIN32)
# Libs
include_directories(libs)
add_subdirectory(libs/openengine)
# Extern # Extern
add_subdirectory (extern/shiny) add_subdirectory (extern/osg-ffmpeg-videoplayer)
add_subdirectory (extern/ogre-ffmpeg-videoplayer)
add_subdirectory (extern/oics) add_subdirectory (extern/oics)
add_subdirectory (extern/sdl4ogre)
# Components # Components
add_subdirectory (components) add_subdirectory (components)
# Plugins # Plugins
if (BUILD_MYGUI_PLUGIN) #if (BUILD_MYGUI_PLUGIN)
add_subdirectory(plugins/mygui_resource_plugin) # add_subdirectory(plugins/mygui_resource_plugin)
endif() #endif()
#Testing
if (BUILD_NIFTEST)
add_subdirectory(components/nif/tests/)
endif(BUILD_NIFTEST)
# Apps and tools # Apps and tools
add_subdirectory( apps/openmw ) if (BUILD_OPENMW)
add_subdirectory( apps/openmw )
endif()
if (BUILD_BSATOOL) if (BUILD_BSATOOL)
add_subdirectory( apps/bsatool ) add_subdirectory( apps/bsatool )
@ -652,12 +537,6 @@ if (WIN32)
4987 # nonstandard extension used (triggered by setjmp.h) 4987 # nonstandard extension used (triggered by setjmp.h)
4996 # Function was declared deprecated 4996 # Function was declared deprecated
# cause by ogre extensivly
4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
4315 # undocumented, 'this' pointer for member might not be aligned (OgreMemoryStlAllocator.h)
# caused by boost # caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
@ -685,10 +564,6 @@ if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} ${MT_BUILD}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} ${MT_BUILD}")
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable # oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189") set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}") set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
@ -714,7 +589,6 @@ if (APPLE)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop") set(CPACK_GENERATOR "DragNDrop")
@ -728,90 +602,14 @@ if (APPLE)
set(OPENCS_BUNDLE_NAME "OpenMW-CS.app") set(OPENCS_BUNDLE_NAME "OpenMW-CS.app")
set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}") set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
set(ABSOLUTE_PLUGINS "")
foreach (PLUGIN ${USED_OGRE_PLUGINS})
get_filename_component(PLUGIN_ABS ${PLUGIN} REALPATH)
set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS})
endforeach ()
install(CODE " install(CODE "
set(BU_CHMOD_BUNDLE_ITEMS ON) set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities) include(BundleUtilities)
" COMPONENT Runtime) " COMPONENT Runtime)
# installs used plugins in bundle at given path (bundle_path must be relative to ${CMAKE_INSTALL_PREFIX})
# and returns list of install paths for all installed plugins
function (install_plugins_for_bundle bundle_path plugins_var)
set(RELATIVE_PLUGIN_INSTALL_BASE "${bundle_path}/Contents/Frameworks")
set(PLUGINS "")
set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${RELATIVE_PLUGIN_INSTALL_BASE}")
foreach (PLUGIN ${ABSOLUTE_PLUGINS})
get_filename_component(PLUGIN_RELATIVE ${PLUGIN} NAME)
get_filename_component(PLUGIN_RELATIVE_WE ${PLUGIN} NAME_WE)
set(PLUGIN_DYLIB_IN_BUNDLE "${PLUGIN_INSTALL_BASE}/${PLUGIN_RELATIVE}/${PLUGIN_RELATIVE_WE}")
set(PLUGINS ${PLUGINS} "${PLUGIN_DYLIB_IN_BUNDLE}")
install(CODE "
copy_resolved_framework_into_bundle(\"${PLUGIN}/${PLUGIN_RELATIVE_WE}\" \"${PLUGIN_DYLIB_IN_BUNDLE}\")
" COMPONENT Runtime)
endforeach ()
set(${plugins_var} ${PLUGINS} PARENT_SCOPE)
endfunction (install_plugins_for_bundle)
install_plugins_for_bundle("${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}" PLUGINS)
install_plugins_for_bundle("${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
#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 #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 "") set(DIRS "")
# Overriding item resolving during installation, it needed if
# some library already has been "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 "
cmake_policy(SET CMP0009 OLD)
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} \${CMAKE_SYSTEM_FRAMEWORK_PATH})
if (ri)
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)
endif()
else()
# code path for standard (non-framework) libs (ogre & qt pugins)
get_filename_component(fname \"\${item}\" NAME_WE)
string(REGEX REPLACE \"^lib\" \"\" fname \${fname})
find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /usr/lib /usr/local/lib)
if (ri)
set(\${resolved_item_var} \${ri} PARENT_SCOPE)
set(\${resolved_var} 1 PARENT_SCOPE)
endif ()
endif()
endif()
endfunction(gp_resolve_item_override)
fixup_bundle(\"${OPENMW_APP}\" \"${PLUGINS}\" \"${DIRS}\")
fixup_bundle(\"${OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"${DIRS}\")
" COMPONENT Runtime)
include(CPack) include(CPack)
endif (APPLE) endif (APPLE)

@ -1,4 +1,5 @@
#include <iostream> #include <iostream>
#include <iomanip>
#include <vector> #include <vector>
#include <exception> #include <exception>
@ -237,12 +238,14 @@ int extract(Bsa::BSAFile& bsa, Arguments& info)
} }
// Get a stream for the file to extract // Get a stream for the file to extract
Ogre::DataStreamPtr data = bsa.getFile(archivePath.c_str()); Files::IStreamPtr stream = bsa.getFile(archivePath.c_str());
bfs::ofstream out(target, std::ios::binary); bfs::ofstream out(target, std::ios::binary);
// Write the file to disk // Write the file to disk
std::cout << "Extracting " << info.extractfile << " to " << target << std::endl; std::cout << "Extracting " << info.extractfile << " to " << target << std::endl;
out.write(data->getAsString().c_str(), data->size());
out << stream->rdbuf();
out.close(); out.close();
return 0; return 0;
@ -276,12 +279,12 @@ int extractAll(Bsa::BSAFile& bsa, Arguments& info)
// Get a stream for the file to extract // Get a stream for the file to extract
// (inefficient because getFile iter on the list again) // (inefficient because getFile iter on the list again)
Ogre::DataStreamPtr data = bsa.getFile(archivePath); Files::IStreamPtr data = bsa.getFile(archivePath);
bfs::ofstream out(target, std::ios::binary); bfs::ofstream out(target, std::ios::binary);
// Write the file to disk // Write the file to disk
std::cout << "Extracting " << target << std::endl; std::cout << "Extracting " << target << std::endl;
out.write(data->getAsString().c_str(), data->size()); out << data->rdbuf();
out.close(); out.close();
} }

@ -4,6 +4,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include <set> #include <set>
#include <fstream>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@ -284,7 +285,7 @@ void printRaw(ESM::ESMReader &esm)
esm.getRecHeader(); esm.getRecHeader();
while(esm.hasMoreSubs()) while(esm.hasMoreSubs())
{ {
uint64_t offs = esm.getOffset(); size_t offs = esm.getFileOffset();
esm.getSubName(); esm.getSubName();
esm.skipHSub(); esm.skipHSub();
n = esm.retSubName(); n = esm.retSubName();

@ -2,8 +2,7 @@
#include <stdexcept> #include <stdexcept>
#include <OgreImage.h> #include <osgDB/WriteFile>
#include <OgreColourValue.h>
#include <components/esm/creaturestate.hpp> #include <components/esm/creaturestate.hpp>
#include <components/esm/containerstate.hpp> #include <components/esm/containerstate.hpp>
@ -15,12 +14,14 @@
namespace namespace
{ {
void convertImage(char* data, int size, int width, int height, Ogre::PixelFormat pf, const std::string& out) void convertImage(char* data, int size, int width, int height, GLenum pf, const std::string& out)
{ {
Ogre::Image screenshot; osg::ref_ptr<osg::Image> image (new osg::Image);
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(data, size)); image->allocateImage(width, height, 1, pf, GL_UNSIGNED_BYTE);
screenshot.loadRawData(stream, width, height, 1, pf); memcpy(image->data(), data, size);
screenshot.save(out); image->flipVertical();
osgDB::writeImageFile(*image, out);
} }
@ -71,17 +72,20 @@ namespace ESSImport
data.resize(esm.getSubSize()); data.resize(esm.getSubSize());
esm.getExact(&data[0], data.size()); esm.getExact(&data[0], data.size());
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(&data[0], data.size())); mGlobalMapImage = new osg::Image;
mGlobalMapImage.loadRawData(stream, maph.size, maph.size, 1, Ogre::PF_BYTE_RGB); mGlobalMapImage->allocateImage(maph.size, maph.size, 1, GL_RGB, GL_UNSIGNED_BYTE);
memcpy(mGlobalMapImage->data(), &data[0], data.size());
// to match openmw size // to match openmw size
mGlobalMapImage.resize(maph.size*2, maph.size*2, Ogre::Image::FILTER_BILINEAR); // FIXME: filtering?
mGlobalMapImage->scaleImage(maph.size*2, maph.size*2, 1, GL_UNSIGNED_BYTE);
} }
void ConvertFMAP::write(ESM::ESMWriter &esm) void ConvertFMAP::write(ESM::ESMWriter &esm)
{ {
int numcells = mGlobalMapImage.getWidth() / 18; // NB truncating, doesn't divide perfectly int numcells = mGlobalMapImage->s() / 18; // NB truncating, doesn't divide perfectly
// with the 512x512 map the game has by default // with the 512x512 map the game has by default
int cellSize = mGlobalMapImage.getWidth()/numcells; int cellSize = mGlobalMapImage->s()/numcells;
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2) // Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
@ -90,12 +94,14 @@ namespace ESSImport
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2; mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2; mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
Ogre::Image image2; osg::ref_ptr<osg::Image> image2 (new osg::Image);
std::vector<Ogre::uint8> data;
int width = cellSize*numcells; int width = cellSize*numcells;
int height = cellSize*numcells; int height = cellSize*numcells;
std::vector<unsigned char> data;
data.resize(width*height*4, 0); data.resize(width*height*4, 0);
image2.loadDynamicImage(&data[0], width, height, Ogre::PF_BYTE_RGBA);
image2->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
memcpy(image2->data(), &data[0], data.size());
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it) for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
{ {
@ -108,8 +114,8 @@ namespace ESSImport
continue; continue;
} }
int imageLeftSrc = mGlobalMapImage.getWidth()/2; int imageLeftSrc = mGlobalMapImage->s()/2;
int imageTopSrc = mGlobalMapImage.getHeight()/2; int imageTopSrc = mGlobalMapImage->t()/2;
imageLeftSrc += it->first * cellSize; imageLeftSrc += it->first * cellSize;
imageTopSrc -= it->second * cellSize; imageTopSrc -= it->second * cellSize;
int imageLeftDst = width/2; int imageLeftDst = width/2;
@ -118,13 +124,31 @@ namespace ESSImport
imageTopDst -= it->second * cellSize; imageTopDst -= it->second * cellSize;
for (int x=0; x<cellSize; ++x) for (int x=0; x<cellSize; ++x)
for (int y=0; y<cellSize; ++y) for (int y=0; y<cellSize; ++y)
image2.setColourAt(mGlobalMapImage.getColourAt(imageLeftSrc+x, imageTopSrc+y, 0) {
, imageLeftDst+x, imageTopDst+y, 0); unsigned int col = *(unsigned int*)mGlobalMapImage->data(imageLeftSrc+x, imageTopSrc+y, 0);
*(unsigned int*)image2->data(imageLeftDst+x, imageTopDst+y, 0) = col;
}
}
std::stringstream ostream;
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
if (!readerwriter)
{
std::cerr << "can't write global map image, no png readerwriter found" << std::endl;
return;
}
image2->flipVertical();
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image2, ostream);
if (!result.success())
{
std::cerr << "can't write global map image: " << result.message() << std::endl;
return;
} }
Ogre::DataStreamPtr encoded = image2.encode("png"); std::string outData = ostream.str();
mContext->mGlobalMapState.mImageData.resize(encoded->size()); mContext->mGlobalMapState.mImageData = std::vector<char>(outData.begin(), outData.end());
encoded->read(&mContext->mGlobalMapState.mImageData[0], encoded->size());
esm.startRecord(ESM::REC_GMAP); esm.startRecord(ESM::REC_GMAP);
mContext->mGlobalMapState.save(esm); mContext->mGlobalMapState.save(esm);
@ -194,7 +218,7 @@ namespace ESSImport
std::ostringstream filename; std::ostringstream filename;
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga"; filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, Ogre::PF_BYTE_RGBA, filename.str()); convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, GL_RGBA, filename.str());
} }
} }

@ -1,7 +1,10 @@
#ifndef OPENMW_ESSIMPORT_CONVERTER_H #ifndef OPENMW_ESSIMPORT_CONVERTER_H
#define OPENMW_ESSIMPORT_CONVERTER_H #define OPENMW_ESSIMPORT_CONVERTER_H
#include <OgreImage.h> #include <limits>
#include <osg/Image>
#include <osg/ref_ptr>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
@ -311,7 +314,7 @@ public:
virtual void write(ESM::ESMWriter &esm); virtual void write(ESM::ESMWriter &esm);
private: private:
Ogre::Image mGlobalMapImage; osg::ref_ptr<osg::Image> mGlobalMapImage;
}; };
class ConvertCell : public Converter class ConvertCell : public Converter

@ -1,7 +1,11 @@
#include "importer.hpp" #include "importer.hpp"
#include <iomanip>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <OgreRoot.h> #include <osgDB/ReadFile>
#include <osg/ImageUtils>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
@ -32,13 +36,48 @@ namespace
void writeScreenshot(const ESM::Header& fileHeader, ESM::SavedGame& out) void writeScreenshot(const ESM::Header& fileHeader, ESM::SavedGame& out)
{ {
Ogre::Image screenshot; if (fileHeader.mSCRS.size() != 128*128*4)
std::vector<unsigned char> screenshotData = fileHeader.mSCRS; // MemoryDataStream doesn't work with const data :( {
Ogre::DataStreamPtr screenshotStream (new Ogre::MemoryDataStream(&screenshotData[0], screenshotData.size())); std::cerr << "unexpected screenshot size " << std::endl;
screenshot.loadRawData(screenshotStream, 128, 128, 1, Ogre::PF_BYTE_BGRA); return;
Ogre::DataStreamPtr encoded = screenshot.encode("jpg"); }
out.mScreenshot.resize(encoded->size());
encoded->read(&out.mScreenshot[0], encoded->size()); osg::ref_ptr<osg::Image> image (new osg::Image);
image->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);
// need to convert pixel format from BGRA to RGB as the jpg readerwriter doesn't support it otherwise
std::vector<unsigned char>::const_iterator it = fileHeader.mSCRS.begin();
for (int y=0; y<128; ++y)
{
for (int x=0; x<128; ++x)
{
*(image->data(x,y)+2) = *it++;
*(image->data(x,y)+1) = *it++;
*image->data(x,y) = *it++;
it++; // skip alpha
}
}
image->flipVertical();
std::stringstream ostream;
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
if (!readerwriter)
{
std::cerr << "can't write screenshot: no jpg readerwriter found" << std::endl;
return;
}
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image, ostream);
if (!result.success())
{
std::cerr << "can't write screenshot: " << result.message() << " code " << result.status() << std::endl;
return;
}
std::string data = ostream.str();
out.mScreenshot = std::vector<char>(data.begin(), data.end());
} }
} }
@ -203,10 +242,6 @@ namespace ESSImport
void Importer::run() void Importer::run()
{ {
// construct Ogre::Root to gain access to image codecs
Ogre::LogManager logman;
Ogre::Root root;
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding)); ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding));
ESM::ESMReader esm; ESM::ESMReader esm;
esm.open(mEssFile); esm.open(mEssFile);

@ -89,8 +89,6 @@ add_executable(openmw-launcher
target_link_libraries(openmw-launcher target_link_libraries(openmw-launcher
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SDL2_LIBRARY_ONLY} ${SDL2_LIBRARY_ONLY}
${QT_LIBRARIES} ${QT_LIBRARIES}
components components

@ -12,9 +12,6 @@
#include <SDL_video.h> #include <SDL_video.h>
#include <OgreRoot.h>
#include <OgreRenderSystem.h>
#include <boost/math/common_factor.hpp> #include <boost/math/common_factor.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
@ -37,10 +34,6 @@ QString getAspect(int x, int y)
Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent) Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, mOgre(NULL)
, mSelectedRenderSystem(NULL)
, mOpenGLRenderSystem(NULL)
, mDirect3DRenderSystem(NULL)
, mCfgMgr(cfg) , mCfgMgr(cfg)
, mGraphicsSettings(graphicsSetting) , mGraphicsSettings(graphicsSetting)
{ {
@ -52,79 +45,12 @@ Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsS
customWidthSpinBox->setMaximum(res.width()); customWidthSpinBox->setMaximum(res.width());
customHeightSpinBox->setMaximum(res.height()); customHeightSpinBox->setMaximum(res.height());
connect(rendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&)));
connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int))); connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int)));
connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool))); connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool)));
connect(screenComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(screenChanged(int))); connect(screenComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(screenChanged(int)));
} }
bool Launcher::GraphicsPage::setupOgre()
{
try
{
mOgre = mOgreInit.init(mCfgMgr.getLogPath().string() + "/launcherOgre.log");
}
catch(Ogre::Exception &ex)
{
QString ogreError = QString::fromUtf8(ex.getFullDescription().c_str());
QMessageBox msgBox;
msgBox.setWindowTitle("Error creating Ogre::Root");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Failed to create the Ogre::Root object</b><br><br> \
Press \"Show Details...\" for more information.<br>"));
msgBox.setDetailedText(ogreError);
msgBox.exec();
qCritical("Error creating Ogre::Root, the error reported was:\n %s", qPrintable(ogreError));
return false;
}
// Get the available renderers and put them in the combobox
const Ogre::RenderSystemList &renderers = mOgre->getAvailableRenderers();
for (Ogre::RenderSystemList::const_iterator r = renderers.begin(); r != renderers.end(); ++r) {
mSelectedRenderSystem = *r;
rendererComboBox->addItem((*r)->getName().c_str());
}
QString openGLName = QString("OpenGL Rendering Subsystem");
QString direct3DName = QString("Direct3D9 Rendering Subsystem");
// Create separate rendersystems
mOpenGLRenderSystem = mOgre->getRenderSystemByName(openGLName.toStdString());
mDirect3DRenderSystem = mOgre->getRenderSystemByName(direct3DName.toStdString());
if (!mOpenGLRenderSystem && !mDirect3DRenderSystem) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error creating renderer"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not select a valid render system</b><br><br> \
Please make sure Ogre plugins were installed correctly.<br>"));
msgBox.exec();
return false;
}
// Now fill the GUI elements
int index = rendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system")));
if ( index != -1) {
rendererComboBox->setCurrentIndex(index);
} else {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
rendererComboBox->setCurrentIndex(rendererComboBox->findText(direct3DName));
#else
rendererComboBox->setCurrentIndex(rendererComboBox->findText(openGLName));
#endif
}
antiAliasingComboBox->clear();
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
return true;
}
bool Launcher::GraphicsPage::setupSDL() bool Launcher::GraphicsPage::setupSDL()
{ {
int displays = SDL_GetNumVideoDisplays(); int displays = SDL_GetNumVideoDisplays();
@ -153,8 +79,6 @@ bool Launcher::GraphicsPage::loadSettings()
{ {
if (!setupSDL()) if (!setupSDL())
return false; return false;
if (!mOgre && !setupOgre())
return false;
if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true"))
vSyncCheckBox->setCheckState(Qt::Checked); vSyncCheckBox->setCheckState(Qt::Checked);
@ -203,7 +127,6 @@ void Launcher::GraphicsPage::saveSettings()
: mGraphicsSettings.setValue(QString("Video/window border"), QString("false")); : mGraphicsSettings.setValue(QString("Video/window border"), QString("false"));
mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText()); mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText());
mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText());
if (standardRadioButton->isChecked()) { if (standardRadioButton->isChecked()) {
@ -221,39 +144,6 @@ void Launcher::GraphicsPage::saveSettings()
mGraphicsSettings.setValue(QString("Video/screen"), QString::number(screenComboBox->currentIndex())); mGraphicsSettings.setValue(QString("Video/screen"), QString::number(screenComboBox->currentIndex()));
} }
QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
{
QStringList result;
uint row = 0;
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); ++i, ++row)
{
Ogre::StringVector::iterator opt_it;
uint idx = 0;
for (opt_it = i->second.possibleValues.begin();
opt_it != i->second.possibleValues.end(); ++opt_it, ++idx)
{
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromUtf8((*opt_it).c_str()).simplified();
}
}
}
// Sort ascending
qSort(result.begin(), result.end(), naturalSortLessThanCI);
// Replace the zero option with Off
int index = result.indexOf("MSAA 0");
if (index != -1)
result.replace(index, tr("Off"));
return result;
}
QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen) QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
{ {
QStringList result; QStringList result;
@ -316,15 +206,6 @@ QRect Launcher::GraphicsPage::getMaximumResolution()
return max; return max;
} }
void Launcher::GraphicsPage::rendererChanged(const QString &renderer)
{
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
antiAliasingComboBox->clear();
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
}
void Launcher::GraphicsPage::screenChanged(int screen) void Launcher::GraphicsPage::screenChanged(int screen)
{ {
if (screen >= 0) { if (screen >= 0) {

@ -3,12 +3,8 @@
#include <QWidget> #include <QWidget>
#include <components/ogreinit/ogreinit.hpp>
#include "ui_graphicspage.h" #include "ui_graphicspage.h"
namespace Ogre { class Root; class RenderSystem; }
namespace Files { struct ConfigurationManager; } namespace Files { struct ConfigurationManager; }
namespace Launcher namespace Launcher
@ -26,7 +22,6 @@ namespace Launcher
bool loadSettings(); bool loadSettings();
public slots: public slots:
void rendererChanged(const QString &renderer);
void screenChanged(int screen); void screenChanged(int screen);
private slots: private slots:
@ -34,20 +29,12 @@ namespace Launcher
void slotStandardToggled(bool checked); void slotStandardToggled(bool checked);
private: private:
OgreInit::OgreInit mOgreInit;
Ogre::Root *mOgre;
Ogre::RenderSystem *mSelectedRenderSystem;
Ogre::RenderSystem *mOpenGLRenderSystem;
Ogre::RenderSystem *mDirect3DRenderSystem;
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;
GraphicsSettings &mGraphicsSettings; GraphicsSettings &mGraphicsSettings;
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
QStringList getAvailableResolutions(int screen); QStringList getAvailableResolutions(int screen);
QRect getMaximumResolution(); QRect getMaximumResolution();
bool setupOgre();
bool setupSDL(); bool setupSDL();
}; };
} }

@ -199,7 +199,7 @@ bool Launcher::MainDialog::setup()
// Now create the pages as they need the settings // Now create the pages as they need the settings
createPages(); createPages();
// Call this so we can exit on Ogre/SDL errors before mainwindow is shown // Call this so we can exit on SDL errors before mainwindow is shown
if (!mGraphicsPage->loadSettings()) if (!mGraphicsPage->loadSettings())
return false; return false;
@ -490,7 +490,7 @@ bool Launcher::MainDialog::writeSettings()
// Game settings // Game settings
QFile file(userPath + QString("openmw.cfg")); QFile file(userPath + QString("openmw.cfg"));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
// File cannot be opened or created // File cannot be opened or created
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
@ -503,10 +503,8 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
mGameSettings.writeFile(stream); mGameSettings.writeFileWithComments(file);
file.close(); file.close();
// Graphics settings // Graphics settings
@ -525,6 +523,7 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setDevice(&file); stream.setDevice(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8")); stream.setCodec(QTextCodec::codecForName("UTF-8"));

@ -26,6 +26,7 @@ opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
idcompletionmanager
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -68,12 +69,12 @@ opencs_units (view/world
opencs_units_noqt (view/world opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator physicssystem scripthighlighter idvalidator dialoguecreator idcompletiondelegate
) )
opencs_units (view/widget opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
scenetooltoggle2 scenetooltoggle2 completerpopup
) )
opencs_units (view/render opencs_units (view/render
@ -82,8 +83,8 @@ opencs_units (view/render
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight lighting lightingday lightingnight
lightingbright object cell terrainstorage textoverlay overlaymask overlaysystem mousestate lightingbright object cell terrainstorage
) )
opencs_hdrs_noqt (view/render opencs_hdrs_noqt (view/render
@ -152,14 +153,14 @@ if(WIN32)
set(QT_USE_QTMAIN TRUE) set(QT_USE_QTMAIN TRUE)
endif(WIN32) endif(WIN32)
set(BOOST_COMPONENTS system filesystem program_options thread wave) set(BOOST_COMPONENTS system filesystem program_options thread)
if(WIN32) if(WIN32)
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
endif(WIN32) endif(WIN32)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtOpenGL REQUIRED)
include(${QT_USE_FILE}) include(${QT_USE_FILE})
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
@ -200,13 +201,8 @@ if(APPLE)
endif(APPLE) endif(APPLE)
target_link_libraries(openmw-cs target_link_libraries(openmw-cs
${OENGINE_LIBRARY} ${OPENSCENEGRAPH_LIBRARIES}
${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SHINY_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${BULLET_LIBRARIES}
${QT_LIBRARIES} ${QT_LIBRARIES}
components components
) )

@ -1,28 +1,22 @@
#include "editor.hpp" #include "editor.hpp"
#include <openengine/bullet/BulletShapeLoader.h>
#include <QApplication> #include <QApplication>
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
#include <QMessageBox> #include <QMessageBox>
#include <OgreRoot.h> #include <components/vfs/manager.hpp>
#include <OgreRenderWindow.h> #include <components/vfs/registerarchives.hpp>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/nifosg/nifloader.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include <components/bsa/resources.hpp>
#include "model/doc/document.hpp" #include "model/doc/document.hpp"
#include "model/world/data.hpp" #include "model/world/data.hpp"
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), CS::Editor::Editor ()
: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr),
mViewManager (mDocumentManager), mPid(""), mViewManager (mDocumentManager), mPid(""),
mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
{ {
@ -33,16 +27,13 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
CSMSettings::UserSettings::instance().loadSettings ("opencs.ini"); CSMSettings::UserSettings::instance().loadSettings ("opencs.ini");
mSettings.setModel (CSMSettings::UserSettings::instance()); mSettings.setModel (CSMSettings::UserSettings::instance());
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); NifOsg::Loader::setShowMarkers(true);
NifOgre::Loader::setShowMarkers(true); mVFS.reset(new VFS::Manager(mFsStrict));
mOverlaySystem.reset (new CSVRender::OverlaySystem); VFS::registerArchives(mVFS.get(), Files::Collections(config.first, !mFsStrict), config.second, true);
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true, mDocumentManager.setVFS(mVFS.get());
mFsStrict);
mDocumentManager.listResources();
mNewGame.setLocalData (mLocal); mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal); mFileDialog.setLocalData (mLocal);
@ -81,9 +72,6 @@ CS::Editor::~Editor ()
if(mServer && boost::filesystem::exists(mPid)) if(mServer && boost::filesystem::exists(mPid))
static_cast<void> ( // silence coverity warning static_cast<void> ( // silence coverity warning
remove(mPid.string().c_str())); // ignore any error remove(mPid.string().c_str())); // ignore any error
// cleanup global resources used by OEngine
delete OEngine::Physic::BulletShapeManager::getSingletonPtr();
} }
void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
@ -354,114 +342,6 @@ int CS::Editor::run()
return QApplication::exec(); return QApplication::exec();
} }
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
std::string renderer =
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
"Direct3D9 Rendering Subsystem";
#else
"OpenGL Rendering Subsystem";
#endif
std::string renderSystem = mUserSettings.setting("Video/render system", renderer.c_str()).toStdString();
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName(renderSystem));
// Initialise Ogre::OverlaySystem after Ogre::Root but before initialisation
mOverlaySystem.get();
Ogre::Root::getSingleton().initialise(false);
// Create a hidden background window to keep resources
Ogre::NameValuePairList params;
params.insert(std::make_pair("title", ""));
std::string antialiasing = mUserSettings.settingValue("Video/antialiasing").toStdString();
if(antialiasing == "MSAA 16") antialiasing = "16";
else if(antialiasing == "MSAA 8") antialiasing = "8";
else if(antialiasing == "MSAA 4") antialiasing = "4";
else if(antialiasing == "MSAA 2") antialiasing = "2";
else antialiasing = "0";
params.insert(std::make_pair("FSAA", antialiasing));
params.insert(std::make_pair("vsync", "false"));
params.insert(std::make_pair("hidden", "true"));
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
params.insert(std::make_pair("macAPI", "cocoa"));
#endif
// NOTE: fullscreen mode not supported (doesn't really make sense for opencs)
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false);
sh::OgrePlatform* platform =
new sh::OgrePlatform ("General", (mResources / "materials").string());
// for font used in overlays
Ogre::Root::getSingleton().addResourceLocation ((mResources / "mygui").string(),
"FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
if (!boost::filesystem::exists (mCfgMgr.getCachePath()))
boost::filesystem::create_directories (mCfgMgr.getCachePath());
platform->setCacheFolder (mCfgMgr.getCachePath().string());
std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
QString shLang = mUserSettings.settingValue("General/shader mode");
QString rend = renderSystem.c_str();
bool openGL = rend.contains(QRegExp("^OpenGL", Qt::CaseInsensitive));
bool glES = rend.contains(QRegExp("^OpenGL ES", Qt::CaseInsensitive));
// force shader language based on render system
if(shLang == ""
|| (openGL && shLang == "hlsl")
|| (!openGL && shLang == "glsl")
|| (glES && shLang != "glsles"))
{
shLang = openGL ? (glES ? "glsles" : "glsl") : "hlsl";
//no group means "General" group in the "ini" file standard
mUserSettings.setDefinitions("shader mode", (QStringList() << shLang));
}
enum sh::Language lang;
if(shLang == "glsl") lang = sh::Language_GLSL;
else if(shLang == "glsles") lang = sh::Language_GLSLES;
else if(shLang == "hlsl") lang = sh::Language_HLSL;
else lang = sh::Language_CG;
factory->setCurrentLanguage (lang);
factory->setWriteSourceCache (true);
factory->setReadSourceCache (true);
factory->setReadMicrocodeCache (true);
factory->setWriteMicrocodeCache (true);
factory->loadAllFiles();
bool shaders = mUserSettings.setting("3d-render/shaders", QString("true")) == "true" ? true : false;
sh::Factory::getInstance ().setShadersEnabled (shaders);
std::string fog = mUserSettings.setting("Shader/fog", QString("true")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("fog", fog);
std::string shadows = mUserSettings.setting("Shader/shadows", QString("false")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("shadows", shadows);
std::string shadows_pssm = mUserSettings.setting("Shader/shadows_pssm", QString("false")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", shadows_pssm);
std::string render_refraction = mUserSettings.setting("Shader/render_refraction", QString("false")).toStdString();
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", render_refraction);
// internal setting - may be switched on or off by the use of shader configurations
sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false");
std::string num_lights = mUserSettings.setting("3d-render-adv/num_lights", QString("8")).toStdString();
sh::Factory::getInstance ().setGlobalSetting ("num_lights", num_lights);
/// \todo add more configurable shiny settings
return factory;
}
void CS::Editor::documentAdded (CSMDoc::Document *document) void CS::Editor::documentAdded (CSMDoc::Document *document)
{ {
mViewManager.addView (document); mViewManager.addView (document);

@ -11,16 +11,12 @@
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
#include <extern/shiny/Main/Factory.hpp>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif #endif
#include <components/files/multidircollection.hpp> #include <components/files/multidircollection.hpp>
#include <components/nifcache/nifcache.hpp>
#include "model/settings/usersettings.hpp" #include "model/settings/usersettings.hpp"
#include "model/doc/documentmanager.hpp" #include "model/doc/documentmanager.hpp"
@ -30,11 +26,10 @@
#include "view/doc/newgame.hpp" #include "view/doc/newgame.hpp"
#include "view/settings/dialog.hpp" #include "view/settings/dialog.hpp"
#include "view/render/overlaysystem.hpp"
namespace OgreInit namespace VFS
{ {
class OgreInit; class Manager;
} }
namespace CS namespace CS
@ -43,10 +38,11 @@ namespace CS
{ {
Q_OBJECT Q_OBJECT
Nif::Cache mNifCache; // FIXME: should be moved to document, so we can have different resources for each opened project
std::auto_ptr<VFS::Manager> mVFS;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
CSMSettings::UserSettings mUserSettings; CSMSettings::UserSettings mUserSettings;
std::auto_ptr<CSVRender::OverlaySystem> mOverlaySystem;
CSMDoc::DocumentManager mDocumentManager; CSMDoc::DocumentManager mDocumentManager;
CSVDoc::ViewManager mViewManager; CSVDoc::ViewManager mViewManager;
CSVDoc::StartupDialogue mStartup; CSVDoc::StartupDialogue mStartup;
@ -71,7 +67,7 @@ namespace CS
public: public:
Editor (OgreInit::OgreInit& ogreInit); Editor ();
~Editor (); ~Editor ();
bool makeIPCServer(); bool makeIPCServer();
@ -80,9 +76,6 @@ namespace CS
int run(); int run();
///< \return error status ///< \return error status
std::auto_ptr<sh::Factory> setupGraphics();
///< The returned factory must persist at least as long as *this.
private slots: private slots:
void createGame(); void createGame();

@ -9,10 +9,6 @@
#include <QIcon> #include <QIcon>
#include <QMetaType> #include <QMetaType>
#include <extern/shiny/Main/Factory.hpp>
#include <components/ogreinit/ogreinit.hpp>
#include "model/world/universalid.hpp" #include "model/world/universalid.hpp"
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -48,15 +44,14 @@ int main(int argc, char *argv[])
{ {
try try
{ {
// To allow background thread drawing in OSG
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
Q_INIT_RESOURCE (resources); Q_INIT_RESOURCE (resources);
qRegisterMetaType<std::string> ("std::string"); qRegisterMetaType<std::string> ("std::string");
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId"); qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
OgreInit::OgreInit ogreInit;
std::auto_ptr<sh::Factory> shinyFactory;
Application application (argc, argv); Application application (argc, argv);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -80,15 +75,13 @@ int main(int argc, char *argv[])
application.setWindowIcon (QIcon (":./openmw-cs.png")); application.setWindowIcon (QIcon (":./openmw-cs.png"));
CS::Editor editor (ogreInit); CS::Editor editor;
if(!editor.makeIPCServer()) if(!editor.makeIPCServer())
{ {
editor.connectToIPCServer(); editor.connectToIPCServer();
return 0; return 0;
} }
shinyFactory = editor.setupGraphics();
return editor.run(); return editor.run();
} }
catch (std::exception& e) catch (std::exception& e)

@ -2,6 +2,7 @@
#include <cassert> #include <cassert>
#include <fstream> #include <fstream>
#include <iostream>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -9,8 +10,6 @@
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif #endif
#include "../../view/world/physicssystem.hpp"
void CSMDoc::Document::addGmsts() void CSMDoc::Document::addGmsts()
{ {
static const char *gmstFloats[] = static const char *gmstFloats[] =
@ -2245,19 +2244,19 @@ void CSMDoc::Document::createBase()
} }
} }
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_, const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
const std::vector<std::string>& blacklistedScripts) const std::vector<std::string>& blacklistedScripts)
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), : mVFS(vfs), mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
mTools (*this), mTools (*this),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSavingOperation (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation), mSaving (&mSavingOperation),
mResDir(resDir), mResDir(resDir),
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()) mRunner (mProjectPath), mIdCompletionManager(mData)
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())
throw std::runtime_error ("Empty content file sequence"); throw std::runtime_error ("Empty content file sequence");
@ -2313,6 +2312,11 @@ CSMDoc::Document::~Document()
{ {
} }
const VFS::Manager *CSMDoc::Document::getVFS() const
{
return mVFS;
}
QUndoStack& CSMDoc::Document::getUndoStack() QUndoStack& CSMDoc::Document::getUndoStack()
{ {
return mUndoStack; return mUndoStack;
@ -2481,10 +2485,7 @@ void CSMDoc::Document::progress (int current, int max, int type)
emit progress (current, max, type, 1, this); emit progress (current, max, type, 1, this);
} }
boost::shared_ptr<CSVWorld::PhysicsSystem> CSMDoc::Document::getPhysics () CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager()
{ {
if(!mPhysics) return mIdCompletionManager;
mPhysics = boost::shared_ptr<CSVWorld::PhysicsSystem> (new CSVWorld::PhysicsSystem());
return mPhysics;
} }

@ -13,6 +13,7 @@
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "../world/data.hpp" #include "../world/data.hpp"
#include "../world/idcompletionmanager.hpp"
#include "../tools/tools.hpp" #include "../tools/tools.hpp"
@ -24,6 +25,12 @@
class QAbstractItemModel; class QAbstractItemModel;
namespace VFS
{
class Manager;
}
namespace ESM namespace ESM
{ {
struct GameSetting; struct GameSetting;
@ -41,11 +48,6 @@ namespace CSMWorld
class ResourcesManager; class ResourcesManager;
} }
namespace CSVWorld
{
class PhysicsSystem;
}
namespace CSMDoc namespace CSMDoc
{ {
class Document : public QObject class Document : public QObject
@ -54,6 +56,7 @@ namespace CSMDoc
private: private:
const VFS::Manager* mVFS;
boost::filesystem::path mSavePath; boost::filesystem::path mSavePath;
std::vector<boost::filesystem::path> mContentFiles; std::vector<boost::filesystem::path> mContentFiles;
bool mNew; bool mNew;
@ -65,7 +68,8 @@ namespace CSMDoc
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
CSMWorld::IdCompletionManager mIdCompletionManager;
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
@ -93,7 +97,7 @@ namespace CSMDoc
public: public:
Document (const Files::ConfigurationManager& configuration, Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_, const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
@ -101,6 +105,8 @@ namespace CSMDoc
~Document(); ~Document();
const VFS::Manager* getVFS() const;
QUndoStack& getUndoStack(); QUndoStack& getUndoStack();
int getState() const; int getState() const;
@ -142,7 +148,7 @@ namespace CSMDoc
QTextDocument *getRunLog(); QTextDocument *getRunLog();
boost::shared_ptr<CSVWorld::PhysicsSystem> getPhysics(); CSMWorld::IdCompletionManager &getIdCompletionManager();
signals: signals:

@ -13,7 +13,7 @@
#include "document.hpp" #include "document.hpp"
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration) CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252) : mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252), mVFS(NULL)
{ {
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects"; boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
@ -57,7 +57,7 @@ bool CSMDoc::DocumentManager::isEmpty()
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath, void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
bool new_) bool new_)
{ {
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts); Document *document = new Document (mVFS, mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
mDocuments.push_back (document); mDocuments.push_back (document);
@ -95,11 +95,6 @@ void CSMDoc::DocumentManager::setBlacklistedScripts (const std::vector<std::stri
mBlacklistedScripts = scriptIds; mBlacklistedScripts = scriptIds;
} }
void CSMDoc::DocumentManager::listResources()
{
mResourcesManager.listResources();
}
void CSMDoc::DocumentManager::documentLoaded (Document *document) void CSMDoc::DocumentManager::documentLoaded (Document *document)
{ {
emit documentAdded (document); emit documentAdded (document);
@ -113,3 +108,9 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::
if (error.empty()) // do not remove the document yet, if we have an error if (error.empty()) // do not remove the document yet, if we have an error
removeDocument (document); removeDocument (document);
} }
void CSMDoc::DocumentManager::setVFS(const VFS::Manager *vfs)
{
mResourcesManager.setVFS(vfs);
mVFS = vfs;
}

@ -15,6 +15,11 @@
#include "loader.hpp" #include "loader.hpp"
namespace VFS
{
class Manager;
}
namespace Files namespace Files
{ {
struct ConfigurationManager; struct ConfigurationManager;
@ -35,6 +40,7 @@ namespace CSMDoc
ToUTF8::FromType mEncoding; ToUTF8::FromType mEncoding;
CSMWorld::ResourcesManager mResourcesManager; CSMWorld::ResourcesManager mResourcesManager;
std::vector<std::string> mBlacklistedScripts; std::vector<std::string> mBlacklistedScripts;
const VFS::Manager* mVFS;
DocumentManager (const DocumentManager&); DocumentManager (const DocumentManager&);
DocumentManager& operator= (const DocumentManager&); DocumentManager& operator= (const DocumentManager&);
@ -56,8 +62,7 @@ namespace CSMDoc
void setBlacklistedScripts (const std::vector<std::string>& scriptIds); void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
/// Ask OGRE for a list of available resources. void setVFS(const VFS::Manager* vfs);
void listResources();
bool isEmpty(); bool isEmpty();

@ -12,8 +12,6 @@
#include <QTextCodec> #include <QTextCodec>
#include <QDebug> #include <QDebug>
#include <extern/shiny/Main/Factory.hpp>
/** /**
* Workaround for problems with whitespaces in paths in older versions of Boost library * Workaround for problems with whitespaces in paths in older versions of Boost library
*/ */
@ -44,13 +42,9 @@ CSMSettings::UserSettings *CSMSettings::UserSettings::sUserSettingsInstance = 0;
void CSMSettings::UserSettings::buildSettingModelDefaults() void CSMSettings::UserSettings::buildSettingModelDefaults()
{ {
QString section; /*
declareSection ("3d-render", "3D Rendering"); declareSection ("3d-render", "3D Rendering");
{ {
Setting *shaders = createSetting (Type_CheckBox, "shaders", "Enable Shaders");
shaders->setDefaultValue ("true");
Setting *farClipDist = createSetting (Type_DoubleSpinBox, "far-clip-distance", "Far clipping distance"); Setting *farClipDist = createSetting (Type_DoubleSpinBox, "far-clip-distance", "Far clipping distance");
farClipDist->setDefaultValue (300000); farClipDist->setDefaultValue (300000);
farClipDist->setRange (0, 1000000); farClipDist->setRange (0, 1000000);
@ -62,23 +56,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
<< defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16"); << defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16");
antialiasing->setDefaultValue (defaultValue); antialiasing->setDefaultValue (defaultValue);
} }
*/
declareSection ("3d-render-adv", "3D Rendering (Advanced)"); /*
{
Setting *numLights = createSetting (Type_SpinBox, "num_lights",
"Number of lights per pass");
numLights->setDefaultValue (8);
numLights->setRange (1, 100);
}
declareSection ("scene-input", "Scene Input"); declareSection ("scene-input", "Scene Input");
{ {
Setting *timer = createSetting (Type_SpinBox, "timer", "Input responsiveness");
timer->setDefaultValue (20);
timer->setRange (1, 100);
timer->setToolTip ("The time between two checks for user input in milliseconds.<p>"
"Lower value result in higher responsiveness.");
Setting *fastFactor = createSetting (Type_SpinBox, "fast-factor", Setting *fastFactor = createSetting (Type_SpinBox, "fast-factor",
"Fast movement factor"); "Fast movement factor");
fastFactor->setDefaultValue (4); fastFactor->setDefaultValue (4);
@ -86,6 +68,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
fastFactor->setToolTip ( fastFactor->setToolTip (
"Factor by which movement is speed up while the shift key is held down."); "Factor by which movement is speed up while the shift key is held down.");
} }
*/
declareSection ("window", "Window"); declareSection ("window", "Window");
{ {
@ -562,15 +545,6 @@ void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
{ {
mSettingDefinitions->setValue (settingKey ,list); mSettingDefinitions->setValue (settingKey ,list);
if(settingKey == "3d-render-adv/num_lights" && !list.empty())
{
sh::Factory::getInstance ().setGlobalSetting ("num_lights", list.at(0).toStdString());
}
else if(settingKey == "3d-render/shaders" && !list.empty())
{
sh::Factory::getInstance ().setShadersEnabled (list.at(0).toStdString() == "true" ? true : false);
}
emit userSettingUpdated (settingKey, list); emit userSettingUpdated (settingKey, list);
} }

@ -65,6 +65,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
Display_JournalInfo, Display_JournalInfo,
Display_Scene, Display_Scene,
Display_GlobalVariable, Display_GlobalVariable,
Display_BodyPart,
Display_Enchantment,
Display_Script, Display_Script,
Display_Mesh, Display_Mesh,

@ -74,6 +74,8 @@ namespace CSMWorld
Display_JournalInfo, Display_JournalInfo,
Display_Scene, Display_Scene,
Display_GlobalVariable, Display_GlobalVariable,
Display_BodyPart,
Display_Enchantment,
//CONCRETE TYPES ENDS HERE //CONCRETE TYPES ENDS HERE
Display_Integer, Display_Integer,

@ -709,7 +709,7 @@ namespace CSMWorld
struct SleepListColumn : public Column<ESXRecordT> struct SleepListColumn : public Column<ESXRecordT>
{ {
SleepListColumn() SleepListColumn()
: Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_String) : Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_CreatureLevelledList)
{} {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
@ -735,7 +735,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TextureColumn : public Column<ESXRecordT> struct TextureColumn : public Column<ESXRecordT>
{ {
TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_String) {} TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_Texture) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1269,7 +1269,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TrapColumn : public Column<ESXRecordT> struct TrapColumn : public Column<ESXRecordT>
{ {
TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_String) {} TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_Spell) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1294,7 +1294,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct FilterColumn : public Column<ESXRecordT> struct FilterColumn : public Column<ESXRecordT>
{ {
FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_String) {} FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_Filter) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1497,7 +1497,10 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TopicColumn : public Column<ESXRecordT> struct TopicColumn : public Column<ESXRecordT>
{ {
TopicColumn (bool journal) : Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic, ColumnBase::Display_String) {} TopicColumn (bool journal)
: Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic,
journal ? ColumnBase::Display_Journal : ColumnBase::Display_Topic)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1527,7 +1530,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ActorColumn : public Column<ESXRecordT> struct ActorColumn : public Column<ESXRecordT>
{ {
ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_String) {} ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_Npc) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1830,7 +1833,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ModelColumn : public Column<ESXRecordT> struct ModelColumn : public Column<ESXRecordT>
{ {
ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_String) {} ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_Mesh) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -2158,7 +2161,9 @@ namespace CSMWorld
struct EffectTextureColumn : public Column<ESXRecordT> struct EffectTextureColumn : public Column<ESXRecordT>
{ {
EffectTextureColumn (Columns::ColumnId columnId) EffectTextureColumn (Columns::ColumnId columnId)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Texture) : Column<ESXRecordT> (columnId,
columnId == Columns::ColumnId_Particle ? ColumnBase::Display_Texture
: ColumnBase::Display_Icon)
{ {
assert (this->mColumnId==Columns::ColumnId_Icon || assert (this->mColumnId==Columns::ColumnId_Icon ||
this->mColumnId==Columns::ColumnId_Particle); this->mColumnId==Columns::ColumnId_Particle);

@ -62,7 +62,7 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager) CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells), : mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0) mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0), mResourceSystem(resourcesManager.getVFS())
{ {
int index = 0; int index = 0;
@ -115,7 +115,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mFactions.getColumns()-1; index = mFactions.getColumns()-1;
mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ())); mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ()));
mFactions.getNestableColumn(index)->addColumn( mFactions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction));
mFactions.getNestableColumn(index)->addColumn( mFactions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer)); new NestedChildColumn (Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer));
@ -135,7 +135,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mRaces.getColumns()-1; index = mRaces.getColumns()-1;
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race> ())); mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race> ()));
mRaces.getNestableColumn(index)->addColumn( mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
// Race attributes // Race attributes
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes)); mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes));
index = mRaces.getColumns()-1; index = mRaces.getColumns()-1;
@ -180,7 +180,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mRegions.getColumns()-1; index = mRegions.getColumns()-1;
mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ())); mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ()));
mRegions.getNestableColumn(index)->addColumn( mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
mRegions.getNestableColumn(index)->addColumn( mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer)); new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer));
@ -196,7 +196,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mBirthsigns.addAdapter (std::make_pair(&mBirthsigns.getColumn(index), mBirthsigns.addAdapter (std::make_pair(&mBirthsigns.getColumn(index),
new SpellListAdapter<ESM::BirthSign> ())); new SpellListAdapter<ESM::BirthSign> ()));
mBirthsigns.getNestableColumn(index)->addColumn( mBirthsigns.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
mSpells.addColumn (new StringIdColumn<ESM::Spell>); mSpells.addColumn (new StringIdColumn<ESM::Spell>);
mSpells.addColumn (new RecordStateColumn<ESM::Spell>); mSpells.addColumn (new RecordStateColumn<ESM::Spell>);
@ -527,6 +527,16 @@ CSMWorld::Data::~Data()
delete mReader; delete mReader;
} }
Resource::ResourceSystem* CSMWorld::Data::getResourceSystem()
{
return &mResourceSystem;
}
const Resource::ResourceSystem* CSMWorld::Data::getResourceSystem() const
{
return &mResourceSystem;
}
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
{ {
return mGlobals; return mGlobals;
@ -1159,3 +1169,8 @@ void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
{ {
emit idListChanged(); emit idListChanged();
} }
const VFS::Manager* CSMWorld::Data::getVFS() const
{
return mResourcesManager.getVFS();
}

@ -29,6 +29,8 @@
#include <components/esm/debugprofile.hpp> #include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp> #include <components/esm/filter.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "../doc/stage.hpp" #include "../doc/stage.hpp"
@ -50,6 +52,11 @@
class QAbstractItemModel; class QAbstractItemModel;
namespace VFS
{
class Manager;
}
namespace ESM namespace ESM
{ {
class ESMReader; class ESMReader;
@ -106,6 +113,8 @@ namespace CSMWorld
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache; std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
int mReaderIndex; int mReaderIndex;
Resource::ResourceSystem mResourceSystem;
std::vector<boost::shared_ptr<ESM::ESMReader> > mReaders; std::vector<boost::shared_ptr<ESM::ESMReader> > mReaders;
// not implemented // not implemented
@ -127,6 +136,12 @@ namespace CSMWorld
virtual ~Data(); virtual ~Data();
const VFS::Manager* getVFS() const;
Resource::ResourceSystem* getResourceSystem();
const Resource::ResourceSystem* getResourceSystem() const;
const IdCollection<ESM::Global>& getGlobals() const; const IdCollection<ESM::Global>& getGlobals() const;
IdCollection<ESM::Global>& getGlobals(); IdCollection<ESM::Global>& getGlobals();

@ -0,0 +1,110 @@
#include "idcompletionmanager.hpp"
#include <boost/make_shared.hpp>
#include <QCompleter>
#include "../../view/widget/completerpopup.hpp"
#include "data.hpp"
#include "idtablebase.hpp"
namespace
{
std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type> generateModelTypes()
{
std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type> types;
types[CSMWorld::ColumnBase::Display_BodyPart ] = CSMWorld::UniversalId::Type_BodyPart;
types[CSMWorld::ColumnBase::Display_Cell ] = CSMWorld::UniversalId::Type_Cell;
types[CSMWorld::ColumnBase::Display_Class ] = CSMWorld::UniversalId::Type_Class;
types[CSMWorld::ColumnBase::Display_CreatureLevelledList] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Creature ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Enchantment ] = CSMWorld::UniversalId::Type_Enchantment;
types[CSMWorld::ColumnBase::Display_Faction ] = CSMWorld::UniversalId::Type_Faction;
types[CSMWorld::ColumnBase::Display_GlobalVariable ] = CSMWorld::UniversalId::Type_Global;
types[CSMWorld::ColumnBase::Display_Icon ] = CSMWorld::UniversalId::Type_Icon;
types[CSMWorld::ColumnBase::Display_Mesh ] = CSMWorld::UniversalId::Type_Mesh;
types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Race ] = CSMWorld::UniversalId::Type_Race;
types[CSMWorld::ColumnBase::Display_Region ] = CSMWorld::UniversalId::Type_Region;
types[CSMWorld::ColumnBase::Display_Referenceable ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Script ] = CSMWorld::UniversalId::Type_Script;
types[CSMWorld::ColumnBase::Display_Skill ] = CSMWorld::UniversalId::Type_Skill;
types[CSMWorld::ColumnBase::Display_Sound ] = CSMWorld::UniversalId::Type_Sound;
types[CSMWorld::ColumnBase::Display_SoundRes ] = CSMWorld::UniversalId::Type_SoundRes;
types[CSMWorld::ColumnBase::Display_Spell ] = CSMWorld::UniversalId::Type_Spell;
types[CSMWorld::ColumnBase::Display_Static ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Texture ] = CSMWorld::UniversalId::Type_Texture;
types[CSMWorld::ColumnBase::Display_Weapon ] = CSMWorld::UniversalId::Type_Referenceable;
return types;
}
typedef std::map<CSMWorld::ColumnBase::Display,
CSMWorld::UniversalId::Type>::const_iterator ModelTypeConstIterator;
}
const std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type>
CSMWorld::IdCompletionManager::sCompleterModelTypes = generateModelTypes();
std::vector<CSMWorld::ColumnBase::Display> CSMWorld::IdCompletionManager::getDisplayTypes()
{
std::vector<CSMWorld::ColumnBase::Display> types;
ModelTypeConstIterator current = sCompleterModelTypes.begin();
ModelTypeConstIterator end = sCompleterModelTypes.end();
for (; current != end; ++current)
{
types.push_back(current->first);
}
return types;
}
CSMWorld::IdCompletionManager::IdCompletionManager(CSMWorld::Data &data)
{
generateCompleters(data);
}
bool CSMWorld::IdCompletionManager::hasCompleterFor(CSMWorld::ColumnBase::Display display) const
{
return mCompleters.find(display) != mCompleters.end();
}
boost::shared_ptr<QCompleter> CSMWorld::IdCompletionManager::getCompleter(CSMWorld::ColumnBase::Display display)
{
if (!hasCompleterFor(display))
{
throw std::logic_error("This column doesn't have an ID completer");
}
return mCompleters[display];
}
void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data)
{
ModelTypeConstIterator current = sCompleterModelTypes.begin();
ModelTypeConstIterator end = sCompleterModelTypes.end();
for (; current != end; ++current)
{
QAbstractItemModel *model = data.getTableModel(current->second);
CSMWorld::IdTableBase *table = dynamic_cast<CSMWorld::IdTableBase *>(model);
if (table != NULL)
{
int idColumn = table->searchColumnIndex(CSMWorld::Columns::ColumnId_Id);
if (idColumn != -1)
{
boost::shared_ptr<QCompleter> completer = boost::make_shared<QCompleter>(table);
completer->setCompletionColumn(idColumn);
// The completion role must be Qt::DisplayRole to get the ID values from the model
completer->setCompletionRole(Qt::DisplayRole);
completer->setCaseSensitivity(Qt::CaseInsensitive);
QAbstractItemView *popup = new CSVWidget::CompleterPopup();
completer->setPopup(popup); // The completer takes ownership of the popup
completer->setMaxVisibleItems(10);
mCompleters[current->first] = completer;
}
}
}
}

@ -0,0 +1,41 @@
#ifndef CSM_WORLD_IDCOMPLETIONMANAGER_HPP
#define CSM_WORLD_IDCOMPLETIONMANAGER_HPP
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include "columnbase.hpp"
#include "universalid.hpp"
class QCompleter;
namespace CSMWorld
{
class Data;
/// \brief Creates and stores all ID completers
class IdCompletionManager
{
static const std::map<ColumnBase::Display, UniversalId::Type> sCompleterModelTypes;
std::map<ColumnBase::Display, boost::shared_ptr<QCompleter> > mCompleters;
// Don't allow copying
IdCompletionManager(const IdCompletionManager &);
IdCompletionManager &operator = (const IdCompletionManager &);
void generateCompleters(Data &data);
public:
static std::vector<ColumnBase::Display> getDisplayTypes();
IdCompletionManager(Data &data);
bool hasCompleterFor(ColumnBase::Display display) const;
boost::shared_ptr<QCompleter> getCompleter(ColumnBase::Display display);
};
}
#endif

@ -33,6 +33,9 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
if (index.row() < 0 || index.column() < 0) if (index.row() < 0 || index.column() < 0)
return QVariant(); return QVariant();
if (role==ColumnBase::Role_Display)
return QVariant(mIdCollection->getColumn(index.column()).mDisplayType);
if (role==ColumnBase::Role_ColumnId) if (role==ColumnBase::Role_ColumnId)
return QVariant (getColumnId (index.column())); return QVariant (getColumnId (index.column()));
@ -84,6 +87,9 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value
Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const
{ {
if (!index.isValid())
return 0;
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
if (mIdCollection->getColumn (index.column()).isUserEditable()) if (mIdCollection->getColumn (index.column()).isUserEditable())

@ -21,6 +21,18 @@ void CSMWorld::IdTableProxyModel::updateColumnMap()
} }
} }
bool CSMWorld::IdTableProxyModel::filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent)
const
{
int flags =
sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
if (flags & CSMWorld::ColumnBase::Flag_Table)
return true;
else
return false;
}
bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent)
const const
{ {

@ -24,8 +24,6 @@ namespace CSMWorld
void updateColumnMap(); void updateColumnMap();
bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
public: public:
IdTableProxyModel (QObject *parent = 0); IdTableProxyModel (QObject *parent = 0);
@ -39,6 +37,10 @@ namespace CSMWorld
protected: protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
virtual bool filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent) const;
}; };
} }

@ -35,28 +35,29 @@ QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0)
return QVariant();
if (index.internalId() != 0) if (index.internalId() != 0)
{ {
std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId())); std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId()));
const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(parentAddress.second);
if (role == Qt::EditRole && if (role == ColumnBase::Role_Display)
!mNestedCollection->getNestableColumn(parentAddress.second)->nestedColumn(index.column()).isEditable()) return parentColumn->nestedColumn(index.column()).mDisplayType;
{
if (role == ColumnBase::Role_ColumnId)
return parentColumn->nestedColumn(index.column()).mColumnId;
if (role == Qt::EditRole && !parentColumn->nestedColumn(index.column()).isEditable())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::EditRole)
return QVariant(); return QVariant();
}
return mNestedCollection->getNestedData(parentAddress.first, return mNestedCollection->getNestedData(parentAddress.first,
parentAddress.second, index.row(), index.column()); parentAddress.second, index.row(), index.column());
} }
else else
{ {
if (role==Qt::EditRole && !idCollection()->getColumn (index.column()).isEditable()) return IdTable::data(index, role);
return QVariant();
return idCollection()->getData (index.row(), index.column());
} }
} }
@ -79,6 +80,9 @@ QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Ori
if (role==ColumnBase::Role_Display) if (role==ColumnBase::Role_Display)
return parentColumn->nestedColumn(subSection).mDisplayType; return parentColumn->nestedColumn(subSection).mDisplayType;
if (role==ColumnBase::Role_ColumnId)
return parentColumn->nestedColumn(subSection).mColumnId;
return QVariant(); return QVariant();
} }

@ -906,7 +906,7 @@ namespace CSMWorld
NestedTableWrapperBase* RaceAttributeAdapter::table(const Record<ESM::Race>& record) const NestedTableWrapperBase* RaceAttributeAdapter::table(const Record<ESM::Race>& record) const
{ {
std::vector<typename ESM::Race::RADTstruct> wrap; std::vector<ESM::Race::RADTstruct> wrap;
wrap.push_back(record.get().mData); wrap.push_back(record.get().mData);
// deleted by dtor of NestedTableStoring // deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap); return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap);
@ -983,7 +983,7 @@ namespace CSMWorld
NestedTableWrapperBase* RaceSkillsBonusAdapter::table(const Record<ESM::Race>& record) const NestedTableWrapperBase* RaceSkillsBonusAdapter::table(const Record<ESM::Race>& record) const
{ {
std::vector<typename ESM::Race::RADTstruct> wrap; std::vector<ESM::Race::RADTstruct> wrap;
wrap.push_back(record.get().mData); wrap.push_back(record.get().mData);
// deleted by dtor of NestedTableStoring // deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap); return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap);

@ -576,7 +576,7 @@ void CSMWorld::NpcAttributesRefIdAdapter::setNestedTable (const RefIdColumn* col
// store the whole struct // store the whole struct
npc.mNpdt52 = npc.mNpdt52 =
static_cast<const NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0); static_cast<const NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
record.setModified (npc); record.setModified (npc);
} }
@ -588,10 +588,10 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::NpcAttributesRefIdAdapter::nestedTab
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
// return the whole struct // return the whole struct
std::vector<typename ESM::NPC::NPDTstruct52> wrap; std::vector<ESM::NPC::NPDTstruct52> wrap;
wrap.push_back(record.get().mNpdt52); wrap.push_back(record.get().mNpdt52);
// deleted by dtor of NestedTableStoring // deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> >(wrap); return new NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> >(wrap);
} }
QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *column, QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *column,
@ -694,7 +694,7 @@ void CSMWorld::NpcSkillsRefIdAdapter::setNestedTable (const RefIdColumn* column,
// store the whole struct // store the whole struct
npc.mNpdt52 = npc.mNpdt52 =
static_cast<const NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0); static_cast<const NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
record.setModified (npc); record.setModified (npc);
} }
@ -706,10 +706,10 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::NpcSkillsRefIdAdapter::nestedTable (
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
// return the whole struct // return the whole struct
std::vector<typename ESM::NPC::NPDTstruct52> wrap; std::vector<ESM::NPC::NPDTstruct52> wrap;
wrap.push_back(record.get().mNpdt52); wrap.push_back(record.get().mNpdt52);
// deleted by dtor of NestedTableStoring // deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> >(wrap); return new NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> >(wrap);
} }
QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *column, QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *column,

@ -99,7 +99,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
EnchantableColumns enchantableColumns (inventoryColumns); EnchantableColumns enchantableColumns (inventoryColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment));
enchantableColumns.mEnchantment = &mColumns.back(); enchantableColumns.mEnchantment = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer)); mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer));
enchantableColumns.mEnchantmentPoints = &mColumns.back(); enchantableColumns.mEnchantmentPoints = &mColumns.back();
@ -135,7 +135,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedInventoryRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedInventoryRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer));
@ -150,7 +150,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedSpellRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedSpellRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_Spell));
// Nested table // Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations,
@ -163,7 +163,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedTravelRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedTravelRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_Cell));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float));
mColumns.back().addColumn( mColumns.back().addColumn(
@ -289,7 +289,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedInventoryRefIdAdapter<ESM::Container> (UniversalId::Type_Container))); new NestedInventoryRefIdAdapter<ESM::Container> (UniversalId::Type_Container)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer));
@ -301,7 +301,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
creatureColumns.mSoul = &mColumns.back(); creatureColumns.mSoul = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float));
creatureColumns.mScale = &mColumns.back(); creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_Creature));
creatureColumns.mOriginal = &mColumns.back(); creatureColumns.mOriginal = &mColumns.back();
mColumns.push_back ( mColumns.push_back (
RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer)); RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer));
@ -409,10 +409,10 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction));
npcColumns.mFaction = &mColumns.back(); npcColumns.mFaction = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_BodyPart));
npcColumns.mHair = &mColumns.back(); npcColumns.mHair = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart));
npcColumns.mHead = &mColumns.back(); npcColumns.mHead = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean));
@ -539,9 +539,9 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType)); new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_BodyPart));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_BodyPart));
LevListColumns levListColumns (baseColumns); LevListColumns levListColumns (baseColumns);
@ -556,7 +556,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedLevListRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList))); new NestedLevListRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer));

@ -5,61 +5,49 @@
#include <stdexcept> #include <stdexcept>
#include <algorithm> #include <algorithm>
#include <OgreResourceGroupManager.h> #include <components/vfs/manager.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
CSMWorld::Resources::Resources (const std::string& baseDirectory, UniversalId::Type type, CSMWorld::Resources::Resources (const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type,
const char * const *extensions) const char * const *extensions)
: mBaseDirectory (baseDirectory), mType (type) : mBaseDirectory (baseDirectory), mType (type)
{ {
int baseSize = mBaseDirectory.size(); int baseSize = mBaseDirectory.size();
Ogre::StringVector resourcesGroups = const std::map<std::string, VFS::File*>& index = vfs->getIndex();
Ogre::ResourceGroupManager::getSingleton().getResourceGroups(); for (std::map<std::string, VFS::File*>::const_iterator it = index.begin(); it != index.end(); ++it)
for (Ogre::StringVector::iterator iter (resourcesGroups.begin());
iter!=resourcesGroups.end(); ++iter)
{ {
if (*iter=="General" || *iter=="Internal" || *iter=="Autodetect") std::string filepath = it->first;
if (static_cast<int> (filepath.size())<baseSize+1 ||
filepath.substr (0, baseSize)!=mBaseDirectory ||
(filepath[baseSize]!='/' && filepath[baseSize]!='\\'))
continue; continue;
Ogre::StringVectorPtr resources = if (extensions)
Ogre::ResourceGroupManager::getSingleton().listResourceNames (*iter);
for (Ogre::StringVector::const_iterator iter (resources->begin());
iter!=resources->end(); ++iter)
{ {
if (static_cast<int> (iter->size())<baseSize+1 || std::string::size_type index = filepath.find_last_of ('.');
iter->substr (0, baseSize)!=mBaseDirectory ||
((*iter)[baseSize]!='/' && (*iter)[baseSize]!='\\'))
continue;
if (extensions)
{
std::string::size_type index = iter->find_last_of ('.');
if (index==std::string::npos) if (index==std::string::npos)
continue; continue;
std::string extension = iter->substr (index+1);
int i = 0; std::string extension = filepath.substr (index+1);
for (; extensions[i]; ++i) int i = 0;
if (extensions[i]==extension)
break;
if (!extensions[i]) for (; extensions[i]; ++i)
continue; if (extensions[i]==extension)
} break;
std::string file = iter->substr (baseSize+1); if (!extensions[i])
mFiles.push_back (file); continue;
std::replace (file.begin(), file.end(), '\\', '/');
mIndex.insert (std::make_pair (
Misc::StringUtils::lowerCase (file), static_cast<int> (mFiles.size())-1));
} }
std::string file = filepath.substr (baseSize+1);
mFiles.push_back (file);
std::replace (file.begin(), file.end(), '\\', '/');
mIndex.insert (std::make_pair (
Misc::StringUtils::lowerCase (file), static_cast<int> (mFiles.size())-1));
} }
} }

@ -7,6 +7,11 @@
#include "universalid.hpp" #include "universalid.hpp"
namespace VFS
{
class Manager;
}
namespace CSMWorld namespace CSMWorld
{ {
class Resources class Resources
@ -19,7 +24,7 @@ namespace CSMWorld
public: public:
/// \param type Type of resources in this table. /// \param type Type of resources in this table.
Resources (const std::string& baseDirectory, UniversalId::Type type, Resources (const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type,
const char * const *extensions = 0); const char * const *extensions = 0);
int getSize() const; int getSize() const;

@ -3,6 +3,11 @@
#include <stdexcept> #include <stdexcept>
CSMWorld::ResourcesManager::ResourcesManager()
: mVFS(NULL)
{
}
void CSMWorld::ResourcesManager::addResources (const Resources& resources) void CSMWorld::ResourcesManager::addResources (const Resources& resources)
{ {
mResources.insert (std::make_pair (resources.getType(), resources)); mResources.insert (std::make_pair (resources.getType(), resources));
@ -10,16 +15,24 @@ void CSMWorld::ResourcesManager::addResources (const Resources& resources)
resources)); resources));
} }
void CSMWorld::ResourcesManager::listResources() void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
{ {
mVFS = vfs;
mResources.clear();
static const char * const sMeshTypes[] = { "nif", 0 }; static const char * const sMeshTypes[] = { "nif", 0 };
addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes)); addResources (Resources (vfs, "meshes", UniversalId::Type_Mesh, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icon)); addResources (Resources (vfs, "icons", UniversalId::Type_Icon));
addResources (Resources ("music", UniversalId::Type_Music)); addResources (Resources (vfs, "music", UniversalId::Type_Music));
addResources (Resources ("sound", UniversalId::Type_SoundRes)); addResources (Resources (vfs, "sound", UniversalId::Type_SoundRes));
addResources (Resources ("textures", UniversalId::Type_Texture)); addResources (Resources (vfs, "textures", UniversalId::Type_Texture));
addResources (Resources ("videos", UniversalId::Type_Video)); addResources (Resources (vfs, "videos", UniversalId::Type_Video));
}
const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const
{
return mVFS;
} }
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const

@ -6,11 +6,17 @@
#include "universalid.hpp" #include "universalid.hpp"
#include "resources.hpp" #include "resources.hpp"
namespace VFS
{
class Manager;
}
namespace CSMWorld namespace CSMWorld
{ {
class ResourcesManager class ResourcesManager
{ {
std::map<UniversalId::Type, Resources> mResources; std::map<UniversalId::Type, Resources> mResources;
const VFS::Manager* mVFS;
private: private:
@ -18,8 +24,11 @@ namespace CSMWorld
public: public:
/// Ask OGRE for a list of available resources. ResourcesManager();
void listResources();
const VFS::Manager* getVFS() const;
void setVFS(const VFS::Manager* vfs);
const Resources& get (UniversalId::Type type) const; const Resources& get (UniversalId::Type type) const;
}; };

@ -1,6 +1,7 @@
#include "viewmanager.hpp" #include "viewmanager.hpp"
#include <vector>
#include <map> #include <map>
#include <QApplication> #include <QApplication>
@ -10,12 +11,14 @@
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../../model/world/idcompletionmanager.hpp"
#include "../world/util.hpp" #include "../world/util.hpp"
#include "../world/enumdelegate.hpp" #include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp" #include "../world/vartypedelegate.hpp"
#include "../world/recordstatusdelegate.hpp" #include "../world/recordstatusdelegate.hpp"
#include "../world/idtypedelegate.hpp" #include "../world/idtypedelegate.hpp"
#include "../world/idcompletiondelegate.hpp"
#include "../../model/settings/usersettings.hpp" #include "../../model/settings/usersettings.hpp"
@ -60,6 +63,14 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
new CSVWorld::IdTypeDelegateFactory()); new CSVWorld::IdTypeDelegateFactory());
std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes();
for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin();
current != idCompletionColumns.end();
++current)
{
mDelegateFactories->add(*current, new CSVWorld::IdCompletionDelegateFactory());
}
struct Mapping struct Mapping
{ {
CSMWorld::ColumnBase::Display mDisplay; CSMWorld::ColumnBase::Display mDisplay;

@ -1,8 +1,7 @@
#include "cell.hpp" #include "cell.hpp"
#include <OgreSceneManager.h> #include <osg/Group>
#include <OgreSceneNode.h>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
@ -11,7 +10,6 @@
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/refcollection.hpp" #include "../../model/world/refcollection.hpp"
#include "../world/physicssystem.hpp"
#include "elements.hpp" #include "elements.hpp"
#include "terrainstorage.hpp" #include "terrainstorage.hpp"
@ -45,7 +43,7 @@ bool CSVRender::Cell::addObjects (int start, int end)
{ {
std::string id = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mId); std::string id = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mId);
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false, mPhysics))); mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false)));
modified = true; modified = true;
} }
} }
@ -53,12 +51,11 @@ bool CSVRender::Cell::addObjects (int start, int end)
return modified; return modified;
} }
CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id)
const std::string& id, boost::shared_ptr<CSVWorld::PhysicsSystem> physics, const Ogre::Vector3& origin) : mData (data), mId (Misc::StringUtils::lowerCase (id)), mX(0), mY(0)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mPhysics(physics), mSceneMgr(sceneManager), mX(0), mY(0)
{ {
mCellNode = sceneManager->getRootSceneNode()->createChildSceneNode(); mCellNode = new osg::Group;
mCellNode->setPosition (origin); rootNode->addChild(mCellNode);
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> ( CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References)); *mData.getTableModel (CSMWorld::UniversalId::Type_References));
@ -74,31 +71,23 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get(); const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get();
if(esmLand && esmLand->mDataTypes&ESM::Land::DATA_VHGT) if(esmLand && esmLand->mDataTypes&ESM::Land::DATA_VHGT)
{ {
mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true, mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem(), NULL, new TerrainStorage(mData), Element_Terrain<<1));
Terrain::Align_XY));
mTerrain->loadCell(esmLand->mX, mTerrain->loadCell(esmLand->mX,
esmLand->mY); esmLand->mY);
float verts = ESM::Land::LAND_SIZE;
float worldsize = ESM::Land::REAL_SIZE;
mX = esmLand->mX; mX = esmLand->mX;
mY = esmLand->mY; mY = esmLand->mY;
mPhysics->addHeightField(sceneManager,
esmLand->mLandData->mHeights, mX, mY, 0, worldsize / (verts-1), verts);
} }
} }
} }
CSVRender::Cell::~Cell() CSVRender::Cell::~Cell()
{ {
if (mTerrain.get())
mPhysics->removeHeightField(mSceneMgr, mX, mY);
for (std::map<std::string, Object *>::iterator iter (mObjects.begin()); for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
iter!=mObjects.end(); ++iter) iter!=mObjects.end(); ++iter)
delete iter->second; delete iter->second;
mCellNode->getCreator()->destroySceneNode (mCellNode); mCellNode->getParent(0)->removeChild(mCellNode);
} }
bool CSVRender::Cell::referenceableDataChanged (const QModelIndex& topLeft, bool CSVRender::Cell::referenceableDataChanged (const QModelIndex& topLeft,
@ -186,7 +175,7 @@ bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft,
for (std::map<std::string, bool>::iterator iter (ids.begin()); iter!=ids.end(); ++iter) for (std::map<std::string, bool>::iterator iter (ids.begin()); iter!=ids.end(); ++iter)
{ {
mObjects.insert (std::make_pair ( mObjects.insert (std::make_pair (
iter->first, new Object (mData, mCellNode, iter->first, false, mPhysics))); iter->first, new Object (mData, mCellNode, iter->first, false)));
modified = true; modified = true;
} }
@ -222,11 +211,3 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
return addObjects (start, end); return addObjects (start, end);
} }
float CSVRender::Cell::getTerrainHeightAt(const Ogre::Vector3 &pos) const
{
if(mTerrain.get() != NULL)
return mTerrain->getHeightAt(pos);
else
return -std::numeric_limits<float>::max();
}

@ -7,7 +7,7 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <OgreVector3.h> #include <osg/ref_ptr>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <components/terrain/terraingrid.hpp> #include <components/terrain/terraingrid.hpp>
@ -17,10 +17,9 @@
class QModelIndex; class QModelIndex;
namespace Ogre namespace osg
{ {
class SceneManager; class Group;
class SceneNode;
} }
namespace CSMWorld namespace CSMWorld
@ -28,22 +27,15 @@ namespace CSMWorld
class Data; class Data;
} }
namespace CSVWorld
{
class PhysicsSystem;
}
namespace CSVRender namespace CSVRender
{ {
class Cell class Cell
{ {
CSMWorld::Data& mData; CSMWorld::Data& mData;
std::string mId; std::string mId;
Ogre::SceneNode *mCellNode; osg::ref_ptr<osg::Group> mCellNode;
std::map<std::string, Object *> mObjects; std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain; std::auto_ptr<Terrain::TerrainGrid> mTerrain;
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
Ogre::SceneManager *mSceneMgr;
int mX; int mX;
int mY; int mY;
@ -59,8 +51,7 @@ namespace CSVRender
public: public:
Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, const std::string& id, Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id);
boost::shared_ptr<CSVWorld::PhysicsSystem> physics, const Ogre::Vector3& origin = Ogre::Vector3 (0, 0, 0));
~Cell(); ~Cell();
@ -84,8 +75,6 @@ namespace CSVRender
/// \return Did this call result in a modification of the visual representation of /// \return Did this call result in a modification of the visual representation of
/// this cell? /// this cell?
bool referenceAdded (const QModelIndex& parent, int start, int end); bool referenceAdded (const QModelIndex& parent, int start, int end);
float getTerrainHeightAt(const Ogre::Vector3 &pos) const;
}; };
} }

@ -1,4 +1,5 @@
#include "lighting.hpp" #include "lighting.hpp"
#include <osg/LightSource>
CSVRender::Lighting::~Lighting() {} CSVRender::Lighting::~Lighting() {}

@ -1,10 +1,13 @@
#ifndef OPENCS_VIEW_LIGHTING_H #ifndef OPENCS_VIEW_LIGHTING_H
#define OPENCS_VIEW_LIGHTING_H #define OPENCS_VIEW_LIGHTING_H
namespace Ogre #include <osg/ref_ptr>
namespace osg
{ {
class SceneManager; class Vec4f;
class ColourValue; class LightSource;
class Group;
} }
namespace CSVRender namespace CSVRender
@ -13,14 +16,19 @@ namespace CSVRender
{ {
public: public:
Lighting() : mRootNode(0) {}
virtual ~Lighting(); virtual ~Lighting();
virtual void activate (Ogre::SceneManager *sceneManager, virtual void activate (osg::Group* rootNode) = 0;
const Ogre::ColourValue *defaultAmbient = 0) = 0;
virtual void deactivate() = 0; virtual void deactivate() = 0;
virtual void setDefaultAmbient (const Ogre::ColourValue& colour) = 0; virtual osg::Vec4f getAmbientColour(osg::Vec4f* defaultAmbient) = 0;
protected:
osg::ref_ptr<osg::LightSource> mLightSource;
osg::Group* mRootNode;
}; };
} }

@ -1,30 +1,35 @@
#include "lightingbright.hpp" #include "lightingbright.hpp"
#include <OgreSceneManager.h> #include <osg/LightSource>
CSVRender::LightingBright::LightingBright() : mSceneManager (0), mLight (0) {} CSVRender::LightingBright::LightingBright() {}
void CSVRender::LightingBright::activate (Ogre::SceneManager *sceneManager, void CSVRender::LightingBright::activate (osg::Group* rootNode)
const Ogre::ColourValue *defaultAmbient)
{ {
mSceneManager = sceneManager; mRootNode = rootNode;
mSceneManager->setAmbientLight (Ogre::ColourValue (1.0, 1.0, 1.0, 1)); mLightSource = (new osg::LightSource);
mLight = mSceneManager->createLight(); osg::ref_ptr<osg::Light> light (new osg::Light);
mLight->setType (Ogre::Light::LT_DIRECTIONAL); light->setAmbient(osg::Vec4f(0.f, 0.f, 0.f, 1.f));
mLight->setDirection (Ogre::Vector3 (0, 0, -1)); light->setPosition(osg::Vec4f(0.f, 0.f, 1.f, 0.f));
mLight->setDiffuseColour (Ogre::ColourValue (1.0, 1.0, 1.0)); light->setDiffuse(osg::Vec4f(1.f, 1.f, 1.f, 1.f));
light->setSpecular(osg::Vec4f(0.f, 0.f, 0.f, 0.f));
light->setConstantAttenuation(1.f);
mLightSource->setLight(light);
mRootNode->addChild(mLightSource);
} }
void CSVRender::LightingBright::deactivate() void CSVRender::LightingBright::deactivate()
{ {
if (mLight) if (mRootNode && mLightSource.get())
{ mRootNode->removeChild(mLightSource);
mSceneManager->destroyLight (mLight);
mLight = 0;
}
} }
void CSVRender::LightingBright::setDefaultAmbient (const Ogre::ColourValue& colour) {} osg::Vec4f CSVRender::LightingBright::getAmbientColour(osg::Vec4f* /*defaultAmbient*/)
{
return osg::Vec4f(1.f, 1.f, 1.f, 1.f);
}

@ -3,28 +3,25 @@
#include "lighting.hpp" #include "lighting.hpp"
namespace Ogre namespace osg
{ {
class Light; class Light;
class Group;
} }
namespace CSVRender namespace CSVRender
{ {
class LightingBright : public Lighting class LightingBright : public Lighting
{ {
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public: public:
LightingBright(); LightingBright();
virtual void activate (Ogre::SceneManager *sceneManager, virtual void activate (osg::Group* rootNode);
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate(); virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour); virtual osg::Vec4f getAmbientColour(osg::Vec4f* defaultAmbient);
}; };
} }

@ -1,36 +1,36 @@
#include "lightingday.hpp" #include "lightingday.hpp"
#include <OgreSceneManager.h> #include <osg/LightSource>
CSVRender::LightingDay::LightingDay() : mSceneManager (0), mLight (0) {} CSVRender::LightingDay::LightingDay(){}
void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager, void CSVRender::LightingDay::activate (osg::Group* rootNode)
const Ogre::ColourValue *defaultAmbient)
{ {
mSceneManager = sceneManager; mRootNode = rootNode;
if (defaultAmbient) mLightSource = new osg::LightSource;
mSceneManager->setAmbientLight (*defaultAmbient);
else
mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1));
mLight = mSceneManager->createLight(); osg::ref_ptr<osg::Light> light (new osg::Light);
mLight->setType (Ogre::Light::LT_DIRECTIONAL); light->setPosition(osg::Vec4f(0.f, 0.f, 1.f, 0.f));
mLight->setDirection (Ogre::Vector3 (0, 0, -1)); light->setAmbient(osg::Vec4f(0.f, 0.f, 0.f, 1.f));
mLight->setDiffuseColour (Ogre::ColourValue (1, 1, 1)); light->setDiffuse(osg::Vec4f(1.f, 1.f, 1.f, 1.f));
light->setSpecular(osg::Vec4f(0.f, 0.f, 0.f, 0.f));
light->setConstantAttenuation(1.f);
mLightSource->setLight(light);
mRootNode->addChild(mLightSource);
} }
void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::deactivate()
{ {
if (mLight) if (mRootNode && mLightSource.get())
{ mRootNode->removeChild(mLightSource);
mSceneManager->destroyLight (mLight);
mLight = 0;
}
} }
void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) osg::Vec4f CSVRender::LightingDay::getAmbientColour(osg::Vec4f *defaultAmbient)
{ {
mSceneManager->setAmbientLight (colour); if (defaultAmbient)
return *defaultAmbient;
else
return osg::Vec4f(0.7f, 0.7f, 0.7f, 1.f);
} }

@ -3,28 +3,19 @@
#include "lighting.hpp" #include "lighting.hpp"
namespace Ogre
{
class Light;
}
namespace CSVRender namespace CSVRender
{ {
class LightingDay : public Lighting class LightingDay : public Lighting
{ {
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public: public:
LightingDay(); LightingDay();
virtual void activate (Ogre::SceneManager *sceneManager, virtual void activate (osg::Group* rootNode);
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate(); virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour); virtual osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient);
}; };
} }

@ -1,36 +1,37 @@
#include "lightingnight.hpp" #include "lightingnight.hpp"
#include <OgreSceneManager.h> #include <osg/LightSource>
CSVRender::LightingNight::LightingNight() : mSceneManager (0), mLight (0) {} CSVRender::LightingNight::LightingNight() {}
void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager, void CSVRender::LightingNight::activate (osg::Group* rootNode)
const Ogre::ColourValue *defaultAmbient)
{ {
mSceneManager = sceneManager; mRootNode = rootNode;
if (defaultAmbient) mLightSource = new osg::LightSource;
mSceneManager->setAmbientLight (*defaultAmbient);
else osg::ref_ptr<osg::Light> light (new osg::Light);
mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1)); light->setPosition(osg::Vec4f(0.f, 0.f, 1.f, 0.f));
light->setAmbient(osg::Vec4f(0.f, 0.f, 0.f, 1.f));
light->setDiffuse(osg::Vec4f(0.2f, 0.2f, 0.2f, 1.f));
light->setSpecular(osg::Vec4f(0.f, 0.f, 0.f, 0.f));
light->setConstantAttenuation(1.f);
mLight = mSceneManager->createLight(); mLightSource->setLight(light);
mLight->setType (Ogre::Light::LT_DIRECTIONAL);
mLight->setDirection (Ogre::Vector3 (0, 0, -1)); mRootNode->addChild(mLightSource);
mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2));
} }
void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::deactivate()
{ {
if (mLight) if (mRootNode && mLightSource.get())
{ mRootNode->removeChild(mLightSource);
mSceneManager->destroyLight (mLight);
mLight = 0;
}
} }
void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) osg::Vec4f CSVRender::LightingNight::getAmbientColour(osg::Vec4f *defaultAmbient)
{ {
mSceneManager->setAmbientLight (colour); if (defaultAmbient)
return *defaultAmbient;
else
return osg::Vec4f(0.2f, 0.2f, 0.2f, 1.f);
} }

@ -3,28 +3,18 @@
#include "lighting.hpp" #include "lighting.hpp"
namespace Ogre
{
class Light;
}
namespace CSVRender namespace CSVRender
{ {
class LightingNight : public Lighting class LightingNight : public Lighting
{ {
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public: public:
LightingNight(); LightingNight();
virtual void activate (Ogre::SceneManager *sceneManager, virtual void activate (osg::Group* rootNode);
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate(); virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour); virtual osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient);
}; };
} }

@ -1,463 +0,0 @@
#include "mousestate.hpp"
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <OgreMeshManager.h>
#include <QMouseEvent>
#include <QElapsedTimer>
#include <QObject>
#include "../../model/settings/usersettings.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/universalid.hpp"
#include "../world/physicssystem.hpp"
#include "elements.hpp"
#include "worldspacewidget.hpp"
namespace CSVRender
{
// mouse picking
// FIXME: need to virtualise mouse buttons
//
// State machine:
//
// [default] mousePressEvent->check if the mouse is pointing at an object
// if yes, create collision planes then go to [grab]
// else check for terrain
//
// [grab] mouseReleaseEvent->if same button and new obj, go to [edit]
// mouseMoveEvent->if same button, go to [drag]
// other mouse events or buttons, go back to [default] (i.e. like 'cancel')
//
// [drag] mouseReleaseEvent->if same button, place the object at the new
// location, update the document then go to [edit]
// mouseMoveEvent->update position to the user based on ray to the collision
// planes and render the object at the new location, but do not update
// the document yet
//
// [edit] TODO, probably fine positional adjustments or rotations; clone/delete?
//
//
// press press (obj)
// [default] --------> [grab] <-------------------- [edit]
// ^ (obj) | | ------> [drag] -----> ^
// | | | move ^ | release |
// | | | | | |
// | | | +-+ |
// | | | move |
// +----------------+ +--------------------------+
// release release
// (same obj) (new obj)
//
//
MouseState::MouseState(WorldspaceWidget *parent)
: mMouseState(Mouse_Default), mParent(parent), mPhysics(parent->mDocument.getPhysics())
, mSceneManager(parent->getSceneManager()), mOldPos(0,0), mCurrentObj(""), mGrabbedSceneNode("")
, mMouseEventTimer(0), mPlane(0), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3())
, mCurrentMousePos(Ogre::Vector3()), mOffset(0.0f), mIdTableModel(0), mColIndexPosX(0)
, mColIndexPosY(0), mColIndexPosZ(0)
{
const CSMWorld::RefCollection& references = mParent->mDocument.getData().getReferences();
mColIndexPosX = references.findColumnIndex(CSMWorld::Columns::ColumnId_PositionXPos);
mColIndexPosY = references.findColumnIndex(CSMWorld::Columns::ColumnId_PositionYPos);
mColIndexPosZ = references.findColumnIndex(CSMWorld::Columns::ColumnId_PositionZPos);
mIdTableModel = static_cast<CSMWorld::IdTable *>(
mParent->mDocument.getData().getTableModel(CSMWorld::UniversalId::Type_Reference));
mMouseEventTimer = new QElapsedTimer();
mMouseEventTimer->invalidate();
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
mPlane = new Ogre::Plane(planeRes.first, 0);
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createPlane("mouse",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
*mPlane,
300000,300000, // FIXME: use far clip dist?
1,1, // segments
true, // normals
1, // numTexCoordSets
1,1, // uTile, vTile
planeRes.second // upVector
);
}
MouseState::~MouseState ()
{
delete mMouseEventTimer;
delete mPlane;
}
void MouseState::mouseMoveEvent (QMouseEvent *event)
{
switch(mMouseState)
{
case Mouse_Grab:
{
// check if min elapsed time to stop false detection of drag
if(!mMouseEventTimer->isValid() || !mMouseEventTimer->hasExpired(100)) // ms
break;
mMouseEventTimer->invalidate();
mMouseState = Mouse_Drag;
/* FALL_THROUGH */
}
case Mouse_Drag:
{
if(event->pos() != mOldPos) // TODO: maybe don't update less than a quantum?
{
mOldPos = event->pos();
// ray test against the plane to provide feedback to the user the
// relative movement of the object on the x-y plane
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
if(planeResult.first)
{
if(mGrabbedSceneNode != "")
{
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
Ogre::Vector3 pos = mOrigObjPos + planeRes.first*mOffset;
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(pos+planeResult.second-mOrigMousePos);
mCurrentMousePos = planeResult.second;
mPhysics->moveSceneNodes(mGrabbedSceneNode, pos+planeResult.second-mOrigMousePos);
updateSceneWidgets();
}
}
}
break;
}
case Mouse_Edit:
case Mouse_Default:
{
break; // error event, ignore
}
/* NO_DEFAULT_CASE */
}
}
void MouseState::mousePressEvent (QMouseEvent *event)
{
switch(mMouseState)
{
case Mouse_Grab:
case Mouse_Drag:
{
break;
}
case Mouse_Edit:
case Mouse_Default:
{
if(event->buttons() & Qt::RightButton)
{
std::pair<std::string, Ogre::Vector3> result = objectUnderCursor(event->x(), event->y());
if(result.first == "")
break;
mGrabbedSceneNode = result.first;
// ray test agaist the plane to get a starting position of the
// mouse in relation to the object position
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
mPlane->redefine(planeRes.first, result.second);
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
if(planeResult.first)
{
mOrigMousePos = planeResult.second;
mCurrentMousePos = planeResult.second;
mOffset = 0.0f;
}
mOrigObjPos = mSceneManager->getSceneNode(mGrabbedSceneNode)->getPosition();
mMouseEventTimer->start();
mMouseState = Mouse_Grab;
}
break;
}
/* NO_DEFAULT_CASE */
}
}
void MouseState::mouseReleaseEvent (QMouseEvent *event)
{
switch(mMouseState)
{
case Mouse_Grab:
{
std::pair<std::string, Ogre::Vector3> result = objectUnderCursor(event->x(), event->y());
if(result.first != "")
{
if(result.first == mCurrentObj)
{
// unselect object
mMouseState = Mouse_Default;
mCurrentObj = "";
}
else
{
// select object
mMouseState = Mouse_Edit;
mCurrentObj = result.first;
}
}
break;
}
case Mouse_Drag:
{
// final placement
std::pair<bool, Ogre::Vector3> planeResult = mousePositionOnPlane(event->pos(), *mPlane);
if(planeResult.first)
{
if(mGrabbedSceneNode != "")
{
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
Ogre::Vector3 pos = mOrigObjPos+planeRes.first*mOffset+planeResult.second-mOrigMousePos;
// use the saved scene node name since the physics model has not moved yet
std::string referenceId = mPhysics->sceneNodeToRefId(mGrabbedSceneNode);
mParent->mDocument.getUndoStack().beginMacro (QObject::tr("Move Object"));
mParent->mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*mIdTableModel,
mIdTableModel->getModelIndex(referenceId, mColIndexPosX), pos.x));
mParent->mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*mIdTableModel,
mIdTableModel->getModelIndex(referenceId, mColIndexPosY), pos.y));
mParent->mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*mIdTableModel,
mIdTableModel->getModelIndex(referenceId, mColIndexPosZ), pos.z));
mParent->mDocument.getUndoStack().endMacro();
// FIXME: highlight current object?
//mCurrentObj = mGrabbedSceneNode; // FIXME: doesn't work?
mCurrentObj = ""; // whether the object is selected
mMouseState = Mouse_Edit;
// reset states
mCurrentMousePos = Ogre::Vector3(); // mouse pos to use in wheel event
mOrigMousePos = Ogre::Vector3(); // starting pos of mouse in world space
mOrigObjPos = Ogre::Vector3(); // starting pos of object in world space
mGrabbedSceneNode = ""; // id of the object
mOffset = 0.0f; // used for z-axis movement
mOldPos = QPoint(0, 0); // to calculate relative movement of mouse
}
}
break;
}
case Mouse_Edit:
case Mouse_Default:
{
// probably terrain, check
std::pair<std::string, Ogre::Vector3> result = terrainUnderCursor(event->x(), event->y());
if(result.first != "")
{
// FIXME: terrain editing goes here
}
break;
}
/* NO_DEFAULT_CASE */
}
mMouseEventTimer->invalidate();
}
void MouseState::mouseDoubleClickEvent (QMouseEvent *event)
{
event->ignore();
//mPhysics->toggleDebugRendering(mSceneManager);
//mParent->flagAsModified();
}
bool MouseState::wheelEvent (QWheelEvent *event)
{
switch(mMouseState)
{
case Mouse_Grab:
mMouseState = Mouse_Drag;
/* FALL_THROUGH */
case Mouse_Drag:
{
// move the object along the z axis during Mouse_Drag or Mouse_Grab
if (event->delta())
{
// seems positive is up and negative is down
mOffset += (event->delta()/1); // FIXME: arbitrary number, make config option?
std::pair<Ogre::Vector3, Ogre::Vector3> planeRes = planeAxis();
Ogre::Vector3 pos = mOrigObjPos + planeRes.first*mOffset;
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(pos+mCurrentMousePos-mOrigMousePos);
mPhysics->moveSceneNodes(mGrabbedSceneNode, pos+mCurrentMousePos-mOrigMousePos);
updateSceneWidgets();
}
break;
}
case Mouse_Edit:
case Mouse_Default:
{
return false;
}
/* NO_DEFAULT_CASE */
}
return true;
}
void MouseState::cancelDrag()
{
switch(mMouseState)
{
case Mouse_Grab:
case Mouse_Drag:
{
// cancel operation & return the object to the original position
mSceneManager->getSceneNode(mGrabbedSceneNode)->setPosition(mOrigObjPos);
// update all SceneWidgets and their SceneManagers
mPhysics->moveSceneNodes(mGrabbedSceneNode, mOrigObjPos);
updateSceneWidgets();
// reset states
mMouseState = Mouse_Default;
mCurrentMousePos = Ogre::Vector3();
mOrigMousePos = Ogre::Vector3();
mOrigObjPos = Ogre::Vector3();
mGrabbedSceneNode = "";
mCurrentObj = "";
mOldPos = QPoint(0, 0);
mMouseEventTimer->invalidate();
mOffset = 0.0f;
break;
}
case Mouse_Edit:
case Mouse_Default:
{
break;
}
/* NO_DEFAULT_CASE */
}
}
//plane Z, upvector Y, mOffset z : x-y plane, wheel up/down
//plane Y, upvector X, mOffset y : y-z plane, wheel left/right
//plane X, upvector Y, mOffset x : x-z plane, wheel closer/further
std::pair<Ogre::Vector3, Ogre::Vector3> MouseState::planeAxis()
{
const bool screenCoord = true;
Ogre::Vector3 dir = getCamera()->getDerivedDirection();
QString wheelDir = "Closer/Further";
if(wheelDir == "Left/Right")
{
if(screenCoord)
return std::make_pair(getCamera()->getDerivedRight(), getCamera()->getDerivedUp());
else
return std::make_pair(Ogre::Vector3::UNIT_Y, Ogre::Vector3::UNIT_Z);
}
else if(wheelDir == "Up/Down")
{
if(screenCoord)
return std::make_pair(getCamera()->getDerivedUp(), Ogre::Vector3(-dir.x, -dir.y, -dir.z));
else
return std::make_pair(Ogre::Vector3::UNIT_Z, Ogre::Vector3::UNIT_X);
}
else
{
if(screenCoord)
return std::make_pair(Ogre::Vector3(-dir.x, -dir.y, -dir.z), getCamera()->getDerivedRight());
else
return std::make_pair(Ogre::Vector3::UNIT_X, Ogre::Vector3::UNIT_Y);
}
}
std::pair<bool, Ogre::Vector3> MouseState::mousePositionOnPlane(const QPoint &pos, const Ogre::Plane &plane)
{
// using a really small value seems to mess up with the projections
float nearClipDistance = getCamera()->getNearClipDistance(); // save existing
getCamera()->setNearClipDistance(10.0f); // arbitrary number
Ogre::Ray mouseRay = getCamera()->getCameraToViewportRay(
(float) pos.x() / getViewport()->getActualWidth(),
(float) pos.y() / getViewport()->getActualHeight());
getCamera()->setNearClipDistance(nearClipDistance); // restore
std::pair<bool, float> planeResult = mouseRay.intersects(plane);
if(planeResult.first)
return std::make_pair(true, mouseRay.getPoint(planeResult.second));
else
return std::make_pair(false, Ogre::Vector3()); // should only happen if the plane is too small
}
std::pair<std::string, Ogre::Vector3> MouseState::terrainUnderCursor(const int mouseX, const int mouseY)
{
if(!getViewport())
return std::make_pair("", Ogre::Vector3());
float x = (float) mouseX / getViewport()->getActualWidth();
float y = (float) mouseY / getViewport()->getActualHeight();
std::pair<std::string, Ogre::Vector3> result = mPhysics->castRay(x, y, mSceneManager, getCamera());
if(result.first != "")
{
// FIXME: is there a better way to distinguish terrain from objects?
QString name = QString(result.first.c_str());
if(name.contains(QRegExp("^HeightField")))
{
return result;
}
}
return std::make_pair("", Ogre::Vector3());
}
std::pair<std::string, Ogre::Vector3> MouseState::objectUnderCursor(const int mouseX, const int mouseY)
{
if(!getViewport())
return std::make_pair("", Ogre::Vector3());
float x = (float) mouseX / getViewport()->getActualWidth();
float y = (float) mouseY / getViewport()->getActualHeight();
std::pair<std::string, Ogre::Vector3> result = mPhysics->castRay(x, y, mSceneManager, getCamera());
if(result.first != "")
{
// NOTE: anything not terrain is assumed to be an object
QString name = QString(result.first.c_str());
if(!name.contains(QRegExp("^HeightField")))
{
uint32_t visibilityMask = getViewport()->getVisibilityMask();
bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference);
if(!ignoreObjects && mSceneManager->hasSceneNode(result.first))
{
return result;
}
}
}
return std::make_pair("", Ogre::Vector3());
}
void MouseState::updateSceneWidgets()
{
std::map<Ogre::SceneManager*, CSVRender::SceneWidget *> sceneWidgets = mPhysics->sceneWidgets();
std::map<Ogre::SceneManager*, CSVRender::SceneWidget *>::iterator iter = sceneWidgets.begin();
for(; iter != sceneWidgets.end(); ++iter)
{
(*iter).second->updateScene();
}
}
Ogre::Camera *MouseState::getCamera()
{
return mParent->getCamera();
}
Ogre::Viewport *MouseState::getViewport()
{
return mParent->getCamera()->getViewport();
}
}

@ -1,91 +0,0 @@
#ifndef OPENCS_VIEW_MOUSESTATE_H
#define OPENCS_VIEW_MOUSESTATE_H
#include <map>
#include <boost/shared_ptr.hpp>
#include <QPoint>
#include <OgreVector3.h>
class QElapsedTimer;
class QMouseEvent;
class QWheelEvent;
namespace Ogre
{
class Plane;
class SceneManager;
class Camera;
class Viewport;
}
namespace CSVWorld
{
class PhysicsSystem;
}
namespace CSMWorld
{
class IdTable;
}
namespace CSVRender
{
class WorldspaceWidget;
class MouseState
{
enum MouseStates
{
Mouse_Grab,
Mouse_Drag,
Mouse_Edit,
Mouse_Default
};
MouseStates mMouseState;
WorldspaceWidget *mParent;
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
Ogre::SceneManager *mSceneManager; // local copy
QPoint mOldPos;
std::string mCurrentObj;
std::string mGrabbedSceneNode;
QElapsedTimer *mMouseEventTimer;
Ogre::Plane *mPlane;
Ogre::Vector3 mOrigObjPos;
Ogre::Vector3 mOrigMousePos;
Ogre::Vector3 mCurrentMousePos;
float mOffset;
CSMWorld::IdTable *mIdTableModel;
int mColIndexPosX;
int mColIndexPosY;
int mColIndexPosZ;
public:
MouseState(WorldspaceWidget *parent);
~MouseState();
void mouseMoveEvent (QMouseEvent *event);
void mousePressEvent (QMouseEvent *event);
void mouseReleaseEvent (QMouseEvent *event);
void mouseDoubleClickEvent (QMouseEvent *event);
bool wheelEvent (QWheelEvent *event);
void cancelDrag();
private:
std::pair<bool, Ogre::Vector3> mousePositionOnPlane(const QPoint &pos, const Ogre::Plane &plane);
std::pair<std::string, Ogre::Vector3> terrainUnderCursor(const int mouseX, const int mouseY);
std::pair<std::string, Ogre::Vector3> objectUnderCursor(const int mouseX, const int mouseY);
std::pair<Ogre::Vector3, Ogre::Vector3> planeAxis();
void updateSceneWidgets();
Ogre::Camera *getCamera(); // friend access
Ogre::Viewport *getViewport(); // friend access
};
}
#endif // OPENCS_VIEW_MOUSESTATE_H

@ -1,24 +0,0 @@
#include "navigation.hpp"
float CSVRender::Navigation::getFactor (bool mouse) const
{
float factor = mFastModeFactor;
if (mouse)
factor /= 2; /// \todo make this configurable
return factor;
}
CSVRender::Navigation::Navigation()
: mFastModeFactor(1)
{
}
CSVRender::Navigation::~Navigation() {}
void CSVRender::Navigation::setFastModeFactor (float factor)
{
mFastModeFactor = factor;
}

@ -1,47 +0,0 @@
#ifndef OPENCS_VIEW_NAVIGATION_H
#define OPENCS_VIEW_NAVIGATION_H
class QPoint;
namespace Ogre
{
class Camera;
}
namespace CSVRender
{
class Navigation
{
float mFastModeFactor;
protected:
float getFactor (bool mouse) const;
public:
Navigation();
virtual ~Navigation();
void setFastModeFactor (float factor);
///< Set currently applying fast mode factor.
virtual bool activate (Ogre::Camera *camera) = 0;
///< \return Update required?
virtual bool wheelMoved (int delta) = 0;
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode) = 0;
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal) = 0;
///< \return Update required?
virtual bool handleRollKeys (int delta) = 0;
///< \return Update required?
};
}
#endif

@ -1,86 +0,0 @@
#include "navigation1st.hpp"
#include <OgreCamera.h>
#include <QPoint>
CSVRender::Navigation1st::Navigation1st() : mCamera (0) {}
bool CSVRender::Navigation1st::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (true, Ogre::Vector3::UNIT_Z);
Ogre::Radian pitch = mCamera->getOrientation().getPitch();
Ogre::Radian limit (Ogre::Math::PI/2-0.5);
if (pitch>limit)
mCamera->pitch (-(pitch-limit));
else if (pitch<-limit)
mCamera->pitch (pitch-limit);
return true;
}
bool CSVRender::Navigation1st::wheelMoved (int delta)
{
mCamera->move (getFactor (true) * mCamera->getDirection() * delta);
return true;
}
bool CSVRender::Navigation1st::mouseMoved (const QPoint& delta, int mode)
{
if (mode==0)
{
// turn camera
if (delta.x())
mCamera->yaw (Ogre::Degree (getFactor (true) * delta.x()));
if (delta.y())
{
Ogre::Radian oldPitch = mCamera->getOrientation().getPitch();
float deltaPitch = getFactor (true) * delta.y();
Ogre::Radian newPitch = oldPitch + Ogre::Degree (deltaPitch);
if ((deltaPitch>0 && newPitch<Ogre::Radian(Ogre::Math::PI-0.5)) ||
(deltaPitch<0 && newPitch>Ogre::Radian(0.5)))
{
mCamera->pitch (Ogre::Degree (deltaPitch));
}
}
return true;
}
else if (mode==1)
{
// pan camera
if (delta.x())
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * delta.x());
if (delta.y())
mCamera->move (getFactor (true) * -mCamera->getDerivedUp() * delta.y());
return true;
}
return false;
}
bool CSVRender::Navigation1st::handleMovementKeys (int vertical, int horizontal)
{
if (vertical)
mCamera->move (getFactor (false) * mCamera->getDirection() * vertical);
if (horizontal)
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * horizontal);
return true;
}
bool CSVRender::Navigation1st::handleRollKeys (int delta)
{
// we don't roll this way in 1st person mode
return false;
}

@ -1,35 +0,0 @@
#ifndef OPENCS_VIEW_NAVIGATION1ST_H
#define OPENCS_VIEW_NAVIGATION1ST_H
#include "navigation.hpp"
namespace CSVRender
{
/// \brief First person-like camera controls
class Navigation1st : public Navigation
{
Ogre::Camera *mCamera;
public:
Navigation1st();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

@ -1,66 +0,0 @@
#include "navigationfree.hpp"
#include <OgreCamera.h>
#include <QPoint>
CSVRender::NavigationFree::NavigationFree() : mCamera (0) {}
bool CSVRender::NavigationFree::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (false);
return false;
}
bool CSVRender::NavigationFree::wheelMoved (int delta)
{
mCamera->move (getFactor (true) * mCamera->getDirection() * delta);
return true;
}
bool CSVRender::NavigationFree::mouseMoved (const QPoint& delta, int mode)
{
if (mode==0)
{
// turn camera
if (delta.x())
mCamera->yaw (Ogre::Degree (getFactor (true) * delta.x()));
if (delta.y())
mCamera->pitch (Ogre::Degree (getFactor (true) * delta.y()));
return true;
}
else if (mode==1)
{
// pan camera
if (delta.x())
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * delta.x());
if (delta.y())
mCamera->move (getFactor (true) * -mCamera->getDerivedUp() * delta.y());
return true;
}
return false;
}
bool CSVRender::NavigationFree::handleMovementKeys (int vertical, int horizontal)
{
if (vertical)
mCamera->move (getFactor (false) * mCamera->getDerivedUp() * vertical);
if (horizontal)
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * horizontal);
return true;
}
bool CSVRender::NavigationFree::handleRollKeys (int delta)
{
mCamera->roll (Ogre::Degree (getFactor (false) * delta));
return true;
}

@ -1,35 +0,0 @@
#ifndef OPENCS_VIEW_NAVIGATIONFREE_H
#define OPENCS_VIEW_NAVIGATIONFREE_H
#include "navigation.hpp"
namespace CSVRender
{
/// \brief Free camera controls
class NavigationFree : public Navigation
{
Ogre::Camera *mCamera;
public:
NavigationFree();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

@ -1,100 +0,0 @@
#include "navigationorbit.hpp"
#include <OgreCamera.h>
#include <QPoint>
void CSVRender::NavigationOrbit::rotateCamera (const Ogre::Vector3& diff)
{
Ogre::Vector3 pos = mCamera->getPosition();
float distance = (pos-mCentre).length();
Ogre::Vector3 direction = (pos+diff)-mCentre;
direction.normalise();
mCamera->setPosition (mCentre + direction*distance);
mCamera->lookAt (mCentre);
}
CSVRender::NavigationOrbit::NavigationOrbit() : mCamera (0), mCentre (0, 0, 0), mDistance (100)
{}
bool CSVRender::NavigationOrbit::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (false);
if ((mCamera->getPosition()-mCentre).length()<mDistance)
{
// move camera out of the centre area
Ogre::Vector3 direction = mCentre-mCamera->getPosition();
direction.normalise();
if (direction.length()==0)
direction = Ogre::Vector3 (1, 0, 0);
mCamera->setPosition (mCentre - direction * mDistance);
}
mCamera->lookAt (mCentre);
return true;
}
bool CSVRender::NavigationOrbit::wheelMoved (int delta)
{
Ogre::Vector3 diff = getFactor (true) * mCamera->getDirection() * delta;
Ogre::Vector3 pos = mCamera->getPosition();
if (delta>0 && diff.length()>=(pos-mCentre).length()-mDistance)
{
pos = mCentre-(mCamera->getDirection() * mDistance);
}
else
{
pos += diff;
}
mCamera->setPosition (pos);
return true;
}
bool CSVRender::NavigationOrbit::mouseMoved (const QPoint& delta, int mode)
{
Ogre::Vector3 diff =
getFactor (true) * -mCamera->getDerivedRight() * delta.x()
+ getFactor (true) * mCamera->getDerivedUp() * delta.y();
if (mode==0)
{
rotateCamera (diff);
return true;
}
else if (mode==1)
{
mCamera->move (diff);
mCentre += diff;
return true;
}
return false;
}
bool CSVRender::NavigationOrbit::handleMovementKeys (int vertical, int horizontal)
{
rotateCamera (
- getFactor (false) * -mCamera->getDerivedRight() * horizontal
+ getFactor (false) * mCamera->getDerivedUp() * vertical);
return true;
}
bool CSVRender::NavigationOrbit::handleRollKeys (int delta)
{
mCamera->roll (Ogre::Degree (getFactor (false) * delta));
return true;
}

@ -1,42 +0,0 @@
#ifndef OPENCS_VIEW_NAVIGATIONORBIT_H
#define OPENCS_VIEW_NAVIGATIONORBIT_H
#include "navigation.hpp"
#include <OgreVector3.h>
namespace CSVRender
{
/// \brief Orbiting camera controls
class NavigationOrbit : public Navigation
{
Ogre::Camera *mCamera;
Ogre::Vector3 mCentre;
int mDistance;
void rotateCamera (const Ogre::Vector3& diff);
///< Rotate camera around centre.
public:
NavigationOrbit();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

@ -1,53 +1,50 @@
#include "object.hpp" #include "object.hpp"
#include <OgreSceneManager.h> #include <stdexcept>
#include <OgreSceneNode.h>
#include <OgreEntity.h> #include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osg/Geode>
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/ref.hpp" #include "../../model/world/ref.hpp"
#include "../../model/world/refidcollection.hpp" #include "../../model/world/refidcollection.hpp"
#include "../world/physicssystem.hpp" #include <components/resource/scenemanager.hpp>
#include <components/sceneutil/clone.hpp>
#include "elements.hpp" #include "elements.hpp"
void CSVRender::Object::clearSceneNode (Ogre::SceneNode *node) namespace
{ {
for (Ogre::SceneNode::ObjectIterator iter = node->getAttachedObjectIterator();
iter.hasMoreElements(); ) osg::ref_ptr<osg::Geode> createErrorCube()
{ {
Ogre::MovableObject* object = dynamic_cast<Ogre::MovableObject*> (iter.getNext()); osg::ref_ptr<osg::Box> shape(new osg::Box(osg::Vec3f(0,0,0), 50.f));
node->getCreator()->destroyMovableObject (object); osg::ref_ptr<osg::ShapeDrawable> shapedrawable(new osg::ShapeDrawable);
shapedrawable->setShape(shape);
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(shapedrawable);
return geode;
} }
for (Ogre::SceneNode::ChildNodeIterator iter = node->getChildIterator();
iter.hasMoreElements(); )
{
Ogre::SceneNode* childNode = dynamic_cast<Ogre::SceneNode*> (iter.getNext());
clearSceneNode (childNode);
node->getCreator()->destroySceneNode (childNode);
}
} }
void CSVRender::Object::clear() void CSVRender::Object::clear()
{ {
mObject.setNull();
if (mBase)
clearSceneNode (mBase);
} }
void CSVRender::Object::update() void CSVRender::Object::update()
{ {
if(!mObject.isNull())
mPhysics->removePhysicsObject(mBase->getName());
clear(); clear();
std::string model; std::string model;
int error = 0; // 1 referemceanöe does not exist, 2 referenceable does not specify a mesh int error = 0; // 1 referenceable does not exist, 2 referenceable does not specify a mesh
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables(); const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
@ -67,39 +64,29 @@ void CSVRender::Object::update()
error = 2; error = 2;
} }
mBaseNode->removeChildren(0, mBaseNode->getNumChildren());
if (error) if (error)
{ {
Ogre::Entity* entity = mBase->getCreator()->createEntity (Ogre::SceneManager::PT_CUBE); mBaseNode->addChild(createErrorCube());
entity->setMaterialName("BaseWhite"); /// \todo adjust material according to error
entity->setVisibilityFlags (Element_Reference);
mBase->attachObject (entity);
} }
else else
{ {
mObject = NifOgre::Loader::createObjects (mBase, "Meshes\\" + model); try
mObject->setVisibilityFlags (Element_Reference);
if (mPhysics && !mReferenceId.empty())
{ {
const CSMWorld::CellRef& reference = getReference(); std::string path = "meshes\\" + model;
// position
Ogre::Vector3 position;
if (!mForceBaseToZero)
position = Ogre::Vector3(reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]);
// orientation mResourceSystem->getSceneManager()->createInstance(path, mBaseNode);
Ogre::Quaternion xr (Ogre::Radian (-reference.mPos.rot[0]), Ogre::Vector3::UNIT_X); }
Ogre::Quaternion yr (Ogre::Radian (-reference.mPos.rot[1]), Ogre::Vector3::UNIT_Y); catch (std::exception& e)
Ogre::Quaternion zr (Ogre::Radian (-reference.mPos.rot[2]), Ogre::Vector3::UNIT_Z); {
// TODO: use error marker mesh
mPhysics->addObject("meshes\\" + model, mBase->getName(), mReferenceId, reference.mScale, position, xr*yr*zr); std::cerr << e.what() << std::endl;
} }
} }
} }
void CSVRender::Object::adjust() void CSVRender::Object::adjustTransform()
{ {
if (mReferenceId.empty()) if (mReferenceId.empty())
return; return;
@ -107,21 +94,15 @@ void CSVRender::Object::adjust()
const CSMWorld::CellRef& reference = getReference(); const CSMWorld::CellRef& reference = getReference();
// position // position
if (!mForceBaseToZero) mBaseNode->setPosition(mForceBaseToZero ? osg::Vec3() : osg::Vec3f(reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
mBase->setPosition (Ogre::Vector3 (
reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
// orientation // orientation
Ogre::Quaternion xr (Ogre::Radian (-reference.mPos.rot[0]), Ogre::Vector3::UNIT_X); osg::Quat xr (-reference.mPos.rot[0], osg::Vec3f(1,0,0));
osg::Quat yr (-reference.mPos.rot[1], osg::Vec3f(0,1,0));
Ogre::Quaternion yr (Ogre::Radian (-reference.mPos.rot[1]), Ogre::Vector3::UNIT_Y); osg::Quat zr (-reference.mPos.rot[2], osg::Vec3f(0,0,1));
mBaseNode->setAttitude(zr*yr*xr);
Ogre::Quaternion zr (Ogre::Radian (-reference.mPos.rot[2]), Ogre::Vector3::UNIT_Z);
mBase->setOrientation (xr*yr*zr);
// scale mBaseNode->setScale(osg::Vec3(reference.mScale, reference.mScale, reference.mScale));
mBase->setScale (reference.mScale, reference.mScale, reference.mScale);
} }
const CSMWorld::CellRef& CSVRender::Object::getReference() const const CSMWorld::CellRef& CSVRender::Object::getReference() const
@ -132,12 +113,15 @@ const CSMWorld::CellRef& CSVRender::Object::getReference() const
return mData.getReferences().getRecord (mReferenceId).get(); return mData.getReferences().getRecord (mReferenceId).get();
} }
CSVRender::Object::Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode, CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
const std::string& id, bool referenceable, boost::shared_ptr<CSVWorld::PhysicsSystem> physics, const std::string& id, bool referenceable, bool forceBaseToZero)
bool forceBaseToZero) : mData (data), mBaseNode(0), mParentNode(parentNode), mResourceSystem(data.getResourceSystem()), mForceBaseToZero (forceBaseToZero)
: mData (data), mBase (0), mForceBaseToZero (forceBaseToZero), mPhysics(physics)
{ {
mBase = cellNode->createChildSceneNode(); mBaseNode = new osg::PositionAttitudeTransform;
parentNode->addChild(mBaseNode);
// 0x1 reserved for separating cull and update visitors
mBaseNode->setNodeMask(Element_Reference<<1);
if (referenceable) if (referenceable)
{ {
@ -149,21 +133,15 @@ CSVRender::Object::Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode
mReferenceableId = getReference().mRefID; mReferenceableId = getReference().mRefID;
} }
adjustTransform();
update(); update();
adjust();
} }
CSVRender::Object::~Object() CSVRender::Object::~Object()
{ {
clear(); clear();
if (mBase) mParentNode->removeChild(mBaseNode);
{
if(mPhysics) // preview may not have physics enabled
mPhysics->removeObject(mBase->getName());
mBase->getCreator()->destroySceneNode (mBase);
}
} }
bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft, bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
@ -175,8 +153,8 @@ bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row()) if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row())
{ {
adjustTransform();
update(); update();
adjust();
return true; return true;
} }
@ -195,8 +173,8 @@ bool CSVRender::Object::referenceableAboutToBeRemoved (const QModelIndex& parent
// Deletion of referenceable-type objects is handled outside of Object. // Deletion of referenceable-type objects is handled outside of Object.
if (!mReferenceId.empty()) if (!mReferenceId.empty())
{ {
adjustTransform();
update(); update();
adjust();
return true; return true;
} }
} }
@ -219,6 +197,8 @@ bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
int columnIndex = int columnIndex =
references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId); references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
adjustTransform();
if (columnIndex>=topLeft.column() && columnIndex<=bottomRight.row()) if (columnIndex>=topLeft.column() && columnIndex<=bottomRight.row())
{ {
mReferenceableId = mReferenceableId =
@ -227,8 +207,6 @@ bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
update(); update();
} }
adjust();
return true; return true;
} }

@ -1,28 +1,30 @@
#ifndef OPENCS_VIEW_OBJECT_H #ifndef OPENCS_VIEW_OBJECT_H
#define OPENCS_VIEW_OBJECT_H #define OPENCS_VIEW_OBJECT_H
#include <string>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#ifndef Q_MOC_RUN #include <osg/ref_ptr>
#include <components/nifogre/ogrenifloader.hpp>
#endif
class QModelIndex; class QModelIndex;
namespace Ogre
namespace osg
{ {
class SceneNode; class PositionAttitudeTransform;
class Group;
} }
namespace CSMWorld namespace Resource
{ {
class Data; class ResourceSystem;
struct CellRef;
} }
namespace CSVWorld namespace CSMWorld
{ {
class PhysicsSystem; class Data;
struct CellRef;
} }
namespace CSVRender namespace CSVRender
@ -32,10 +34,10 @@ namespace CSVRender
const CSMWorld::Data& mData; const CSMWorld::Data& mData;
std::string mReferenceId; std::string mReferenceId;
std::string mReferenceableId; std::string mReferenceableId;
Ogre::SceneNode *mBase; osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
NifOgre::ObjectScenePtr mObject; osg::Group* mParentNode;
Resource::ResourceSystem* mResourceSystem;
bool mForceBaseToZero; bool mForceBaseToZero;
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
/// Not implemented /// Not implemented
Object (const Object&); Object (const Object&);
@ -43,26 +45,23 @@ namespace CSVRender
/// Not implemented /// Not implemented
Object& operator= (const Object&); Object& operator= (const Object&);
/// Destroy all scene nodes and movable objects attached to node.
static void clearSceneNode (Ogre::SceneNode *node);
/// Remove object from node (includes deleting) /// Remove object from node (includes deleting)
void clear(); void clear();
/// Update model /// Update model
/// @note Make sure adjustTransform() was called first so world space particles get positioned correctly
void update(); void update();
/// Adjust position, orientation and scale /// Adjust position, orientation and scale
void adjust(); void adjustTransform();
/// Throws an exception if *this was constructed with referenceable /// Throws an exception if *this was constructed with referenceable
const CSMWorld::CellRef& getReference() const; const CSMWorld::CellRef& getReference() const;
public: public:
Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode, Object (CSMWorld::Data& data, osg::Group *cellNode,
const std::string& id, bool referenceable, const std::string& id, bool referenceable,
boost::shared_ptr<CSVWorld::PhysicsSystem> physics = boost::shared_ptr<CSVWorld::PhysicsSystem> (),
bool forceBaseToZero = false); bool forceBaseToZero = false);
/// \param forceBaseToZero If this is a reference ignore the coordinates and place /// \param forceBaseToZero If this is a reference ignore the coordinates and place
/// it at 0, 0, 0 instead. /// it at 0, 0, 0 instead.

@ -1,52 +0,0 @@
#include "overlaymask.hpp"
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include "textoverlay.hpp"
#include "../../model/world/cellcoordinates.hpp"
namespace CSVRender
{
// ideas from http://www.ogre3d.org/forums/viewtopic.php?f=5&t=44828#p486334
OverlayMask::OverlayMask(std::map<CSMWorld::CellCoordinates, TextOverlay *> &overlays, Ogre::Viewport* viewport)
: mTextOverlays(overlays), mViewport(viewport)
{
}
OverlayMask::~OverlayMask()
{
}
void OverlayMask::setViewport(Ogre::Viewport *viewport)
{
mViewport = viewport;
}
void OverlayMask::preViewportUpdate(const Ogre::RenderTargetViewportEvent &event)
{
if(event.source == mViewport)
{
Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton();
for(Ogre::OverlayManager::OverlayMapIterator iter = overlayMgr.getOverlayIterator();
iter.hasMoreElements();)
{
Ogre::Overlay* item = iter.getNext();
for(Ogre::Overlay::Overlay2DElementsIterator it = item->get2DElementsIterator();
it.hasMoreElements();)
{
Ogre::OverlayContainer* container = it.getNext();
if(container) container->hide();
}
}
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator it = mTextOverlays.begin();
for(; it != mTextOverlays.end(); ++it)
{
it->second->show(true);
}
}
}
}

@ -1,42 +0,0 @@
#ifndef OPENCS_VIEW_OVERLAYMASK_H
#define OPENCS_VIEW_OVERLAYMASK_H
#include <OgreRenderTargetListener.h>
namespace Ogre
{
class Viewport;
class RendertargetViewportEvent;
}
namespace CSMWorld
{
class CellCoordinates;
}
namespace CSVRender
{
class TextOverlay;
class OverlayMask : public Ogre::RenderTargetListener
{
std::map<CSMWorld::CellCoordinates, TextOverlay *> &mTextOverlays;
Ogre::Viewport* mViewport;
public:
OverlayMask(std::map<CSMWorld::CellCoordinates, TextOverlay *> &overlays,
Ogre::Viewport* viewport);
virtual ~OverlayMask();
void setViewport(Ogre::Viewport *viewport);
protected:
virtual void preViewportUpdate(const Ogre::RenderTargetViewportEvent &event);
};
}
#endif // OPENCS_VIEW_OVERLAYMASK_H

@ -1,34 +0,0 @@
#include "overlaysystem.hpp"
#include <cassert>
#include <OgreOverlaySystem.h>
namespace CSVRender
{
OverlaySystem *OverlaySystem::mOverlaySystemInstance = 0;
OverlaySystem::OverlaySystem()
{
assert(!mOverlaySystemInstance);
mOverlaySystemInstance = this;
mOverlaySystem = new Ogre::OverlaySystem();
}
OverlaySystem::~OverlaySystem()
{
delete mOverlaySystem;
}
OverlaySystem &OverlaySystem::instance()
{
assert(mOverlaySystemInstance);
return *mOverlaySystemInstance;
}
Ogre::OverlaySystem *OverlaySystem::get()
{
return mOverlaySystem;
}
}

@ -1,26 +0,0 @@
#ifndef OPENCS_VIEW_OVERLAYSYSTEM_H
#define OPENCS_VIEW_OVERLAYSYSTEM_H
namespace Ogre
{
class OverlaySystem;
}
namespace CSVRender
{
class OverlaySystem
{
Ogre::OverlaySystem *mOverlaySystem;
static OverlaySystem *mOverlaySystemInstance;
public:
OverlaySystem();
~OverlaySystem();
static OverlaySystem &instance();
Ogre::OverlaySystem *get();
};
}
#endif // OPENCS_VIEW_OVERLAYSYSTEM_H

@ -5,17 +5,9 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <OgreCamera.h> #include <osgGA/TrackballManipulator>
#include <OgreSceneManager.h>
#include <OgreManualObject.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlayManager.h>
#include <OgreRoot.h>
#include <OgreSceneQuery.h>
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
#include "textoverlay.hpp"
#include "overlaymask.hpp"
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
@ -30,7 +22,6 @@
bool CSVRender::PagedWorldspaceWidget::adjustCells() bool CSVRender::PagedWorldspaceWidget::adjustCells()
{ {
bool modified = false; bool modified = false;
bool setCamera = false;
const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells(); const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells();
@ -45,17 +36,6 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
if (!mSelection.has (iter->first) || index==-1 || if (!mSelection.has (iter->first) || index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted) cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted)
{ {
// delete overlays
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator itOverlay = mTextOverlays.find(iter->first);
if(itOverlay != mTextOverlays.end())
{
delete itOverlay->second;
mTextOverlays.erase(itOverlay);
}
// destroy manual objects
getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace));
delete iter->second; delete iter->second;
mCells.erase (iter++); mCells.erase (iter++);
@ -65,43 +45,16 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
{ {
// check if name or region field has changed // check if name or region field has changed
// FIXME: config setting // FIXME: config setting
std::string name = cells.getRecord(index).get().mName; //std::string name = cells.getRecord(index).get().mName;
std::string region = cells.getRecord(index).get().mRegion; //std::string region = cells.getRecord(index).get().mRegion;
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator it = mTextOverlays.find(iter->first); // cell marker update goes here
if(it != mTextOverlays.end())
{
if(it->second->getDesc() != "") // previously had name
{
if(name != it->second->getDesc()) // new name
{
if(name != "")
it->second->setDesc(name);
else // name deleted, use region
it->second->setDesc(region);
it->second->update();
}
}
else if(name != "") // name added
{
it->second->setDesc(name);
it->second->update();
}
else if(region != it->second->getDesc()) // new region
{
it->second->setDesc(region);
it->second->update();
}
modified = true;
}
++iter; ++iter;
} }
} }
} }
if (mCells.begin()==mCells.end())
setCamera = true;
// add // add
for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end(); for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end();
++iter) ++iter)
@ -111,106 +64,18 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted && if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted &&
mCells.find (*iter)==mCells.end()) mCells.find (*iter)==mCells.end())
{ {
Cell *cell = new Cell (mDocument.getData(), getSceneManager(), Cell *cell = new Cell (mDocument.getData(), mRootNode,
iter->getId (mWorldspace), mDocument.getPhysics()); iter->getId (mWorldspace));
mCells.insert (std::make_pair (*iter, cell)); mCells.insert (std::make_pair (*iter, cell));
float height = cell->getTerrainHeightAt(Ogre::Vector3(
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
0));
if (setCamera)
{
setCamera = false;
getCamera()->setPosition (
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height);
// better camera position at the start
getCamera()->move(getCamera()->getDirection() * -6000); // FIXME: config setting
}
Ogre::ManualObject* manual =
getSceneManager()->createManualObject("manual" + iter->getId(mWorldspace));
manual->begin("BaseWhite", Ogre::RenderOperation::OT_LINE_LIST);
// define start and end point (x, y, z)
manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height);
manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height+200); // FIXME: config setting
manual->end();
manual->setBoundingBox(Ogre::AxisAlignedBox(
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height,
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height+200));
getSceneManager()->getRootSceneNode()->createChildSceneNode()->attachObject(manual);
manual->setVisible(false);
CSVRender::TextOverlay *textDisp =
new CSVRender::TextOverlay(manual, getCamera(), iter->getId(mWorldspace));
textDisp->enable(true);
textDisp->setCaption(iter->getId(mWorldspace));
std::string desc = cells.getRecord(index).get().mName;
if(desc == "") desc = cells.getRecord(index).get().mRegion;
textDisp->setDesc(desc); // FIXME: config setting
textDisp->update();
mTextOverlays.insert(std::make_pair(*iter, textDisp));
if(!mOverlayMask)
{
mOverlayMask = new OverlayMask(mTextOverlays, getViewport());
addRenderTargetListener(mOverlayMask);
}
modified = true; modified = true;
} }
} }
return modified; if (modified)
} mView->setCameraManipulator(new osgGA::TrackballManipulator);
void CSVRender::PagedWorldspaceWidget::mousePressEvent (QMouseEvent *event)
{
if(event->button() == Qt::RightButton)
{
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter = mTextOverlays.begin();
for(; iter != mTextOverlays.end(); ++iter)
{
if(mDisplayCellCoord &&
iter->second->isEnabled() && iter->second->container().contains(event->x(), event->y()))
{
return;
}
}
}
WorldspaceWidget::mousePressEvent(event);
}
void CSVRender::PagedWorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
{
if(event->button() == Qt::RightButton)
{
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter = mTextOverlays.begin();
for(; iter != mTextOverlays.end(); ++iter)
{
if(mDisplayCellCoord &&
iter->second->isEnabled() && iter->second->container().contains(event->x(), event->y()))
{
std::cout << "clicked: " << iter->second->getCaption() << std::endl;
return;
}
}
}
WorldspaceWidget::mouseReleaseEvent(event);
}
void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) return modified;
{
WorldspaceWidget::mouseDoubleClickEvent(event);
} }
void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons ( void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons (
@ -241,28 +106,6 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
"terrain-move"); "terrain-move");
} }
void CSVRender::PagedWorldspaceWidget::updateOverlay()
{
if(getCamera()->getViewport())
{
if((uint32_t)getCamera()->getViewport()->getVisibilityMask()
& (uint32_t)CSVRender::Element_CellMarker)
mDisplayCellCoord = true;
else
mDisplayCellCoord = false;
}
if(!mTextOverlays.empty())
{
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator it = mTextOverlays.begin();
for(; it != mTextOverlays.end(); ++it)
{
it->second->enable(mDisplayCellCoord);
it->second->update();
}
}
}
void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight) const QModelIndex& bottomRight)
{ {
@ -328,13 +171,12 @@ void CSVRender::PagedWorldspaceWidget::referenceAdded (const QModelIndex& parent
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction() std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
{ {
Ogre::Vector3 position = getCamera()->getPosition(); osg::Vec3d position = mView->getCamera()->getViewMatrix().getTrans();
std::ostringstream stream; std::ostringstream stream;
stream stream
<< "player->position " << "player->position "
<< position.x << ", " << position.y << ", " << position.z << position.x() << ", " << position.y() << ", " << position.z()
<< ", 0"; << ", 0";
return stream.str(); return stream.str();
@ -342,7 +184,7 @@ std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
: WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"), : WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"),
mControlElements(NULL), mDisplayCellCoord(true), mOverlayMask(NULL) mControlElements(NULL), mDisplayCellCoord(true)
{ {
QAbstractItemModel *cells = QAbstractItemModel *cells =
document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells); document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells);
@ -361,20 +203,6 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget()
iter!=mCells.end(); ++iter) iter!=mCells.end(); ++iter)
{ {
delete iter->second; delete iter->second;
getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace));
}
for (std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter (mTextOverlays.begin());
iter != mTextOverlays.end(); ++iter)
{
delete iter->second;
}
if(mOverlayMask)
{
removeRenderTargetListener(mOverlayMask);
delete mOverlayMask;
} }
} }

@ -28,8 +28,6 @@ namespace CSVRender
std::string mWorldspace; std::string mWorldspace;
CSVWidget::SceneToolToggle *mControlElements; CSVWidget::SceneToolToggle *mControlElements;
bool mDisplayCellCoord; bool mDisplayCellCoord;
std::map<CSMWorld::CellCoordinates, TextOverlay *> mTextOverlays;
OverlayMask *mOverlayMask;
private: private:
@ -87,14 +85,6 @@ namespace CSVRender
virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool);
virtual void updateOverlay();
virtual void mousePressEvent (QMouseEvent *event);
virtual void mouseReleaseEvent (QMouseEvent *event);
virtual void mouseDoubleClickEvent (QMouseEvent *event);
signals: signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection); void cellSelectionChanged (const CSMWorld::CellSelection& selection);

@ -1,18 +1,16 @@
#include "previewwidget.hpp" #include "previewwidget.hpp"
#include <OgreSceneManager.h> #include <osgGA/TrackballManipulator>
#include <OgreSceneNode.h>
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data, CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
const std::string& id, bool referenceable, QWidget *parent) const std::string& id, bool referenceable, QWidget *parent)
: SceneWidget (parent), mData (data), : SceneWidget (data.getResourceSystem()->getSceneManager(), parent), mData (data), mObject(data, mRootNode, id, referenceable)
mObject (data, getSceneManager()->getRootSceneNode(), id, referenceable, boost::shared_ptr<CSVWorld::PhysicsSystem>(), true)
{ {
setNavigation (&mOrbit); mView->setCameraManipulator(new osgGA::TrackballManipulator);
QAbstractItemModel *referenceables = QAbstractItemModel *referenceables =
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables); mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);

@ -3,11 +3,15 @@
#include "scenewidget.hpp" #include "scenewidget.hpp"
#include "navigationorbit.hpp"
#include "object.hpp" #include "object.hpp"
class QModelIndex; class QModelIndex;
namespace VFS
{
class Manager;
}
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
@ -20,8 +24,7 @@ namespace CSVRender
Q_OBJECT Q_OBJECT
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSVRender::NavigationOrbit mOrbit; CSVRender::Object mObject;
Object mObject;
public: public:

@ -4,467 +4,218 @@
#include <QResizeEvent> #include <QResizeEvent>
#include <QTimer> #include <QTimer>
#include <QShortcut> #include <QShortcut>
#include <QLayout>
#include <OgreRoot.h> #include <osgQt/GraphicsWindowQt>
#include <OgreRenderWindow.h> #include <osg/GraphicsContext>
#include <OgreEntity.h> #include <osgViewer/CompositeViewer>
#include <OgreCamera.h> #include <osgViewer/ViewerEventHandlers>
#include <OgreSceneNode.h> #include <osg/LightModel>
#include <OgreViewport.h>
#include <OgreOverlaySystem.h> #include <components/resource/scenemanager.hpp>
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include "../../model/settings/usersettings.hpp" #include "../../model/settings/usersettings.hpp"
#include "navigation.hpp"
#include "lighting.hpp" #include "lighting.hpp"
#include "overlaysystem.hpp"
namespace CSVRender namespace CSVRender
{ {
SceneWidget::SceneWidget(QWidget *parent)
: QWidget(parent)
, mCamera(NULL)
, mSceneMgr(NULL)
, mWindow(NULL)
, mViewport(NULL)
, mNavigation (0), mLighting (0), mUpdate (false), mKeyForward (false)
, mKeyBackward (false), mKeyLeft (false), mKeyRight (false)
, mKeyRollLeft (false), mKeyRollRight (false)
, mFast (false), mDragging (false), mMod1 (false)
, mFastFactor (4)
, mDefaultAmbient (0, 0, 0, 0), mHasDefaultAmbient (false)
{
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
setFocusPolicy (Qt::StrongFocus); RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
: QWidget(parent, f)
, mRootNode(0)
{
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); osgViewer::CompositeViewer& viewer = CompositeViewer::get();
mSceneMgr->setAmbientLight (Ogre::ColourValue (0,0,0,1)); osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
//ds->setNumMultiSamples(8);
mCamera = mSceneMgr->createCamera("foo"); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowName = "";
traits->windowDecoration = true;
traits->x = 0;
traits->y = 0;
traits->width = width();
traits->height = height();
traits->doubleBuffer = true;
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();
// Doesn't make much sense as we're running on demand updates, and there seems to be a bug with the refresh rate when running multiple QGLWidgets
traits->vsync = false;
mCamera->setPosition (300, 0, 0); mView = new osgViewer::View;
mCamera->lookAt (0, 0, 0);
mCamera->setNearClipDistance (0.1);
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); osg::ref_ptr<osgQt::GraphicsWindowQt> window = new osgQt::GraphicsWindowQt(traits.get());
QLayout* layout = new QHBoxLayout(this);
layout->addWidget(window->getGLWidget());
setLayout(layout);
float farClipDist = userSettings.setting("3d-render/far-clip-distance", QString("300000")).toFloat(); mView->getCamera()->setGraphicsContext(window);
mCamera->setFarClipDistance (farClipDist); mView->getCamera()->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
mView->getCamera()->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
mView->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );
mFastFactor = userSettings.setting("scene-input/fast-factor", QString("4")).toInt(); mRootNode = new osg::Group;
mCamera->roll (Ogre::Degree (90)); mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
setLighting (&mLightingDay); mView->setSceneData(mRootNode);
mOverlaySystem = OverlaySystem::instance().get(); // Press S to reveal profiling stats
mSceneMgr->addRenderQueueListener(mOverlaySystem); mView->addEventHandler(new osgViewer::StatsHandler);
QTimer *timer = new QTimer (this); mView->getCamera()->setCullMask(~(0x1));
connect (timer, SIGNAL (timeout()), this, SLOT (update())); viewer.addView(mView);
viewer.setDone(false);
int timerStart = userSettings.setting("scene-input/timer", QString("20")).toInt(); viewer.realize();
timer->start (timerStart); }
/// \todo make shortcut configurable RenderWidget::~RenderWidget()
QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut); {
connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest())); CompositeViewer::get().removeView(mView);
} }
CSVWidget::SceneToolMode *SceneWidget::makeLightingSelector (CSVWidget::SceneToolbar *parent) void RenderWidget::flagAsModified()
{ {
CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Lighting Mode"); mView->requestRedraw();
}
/// \todo replace icons
tool->addButton (":scenetoolbar/day", "day",
"Day"
"<ul><li>Cell specific ambient in interiors</li>"
"<li>Low ambient in exteriors</li>"
"<li>Strong directional light source/lir>"
"<li>This mode closely resembles day time in-game</li></ul>");
tool->addButton (":scenetoolbar/night", "night",
"Night"
"<ul><li>Cell specific ambient in interiors</li>"
"<li>Low ambient in exteriors</li>"
"<li>Weak directional light source</li>"
"<li>This mode closely resembles night time in-game</li></ul>");
tool->addButton (":scenetoolbar/bright", "bright",
"Bright"
"<ul><li>Maximum ambient</li>"
"<li>Strong directional light source</li></ul>");
connect (tool, SIGNAL (modeChanged (const std::string&)),
this, SLOT (selectLightingMode (const std::string&)));
return tool;
}
void SceneWidget::setDefaultAmbient (const Ogre::ColourValue& colour)
{
mDefaultAmbient = colour;
mHasDefaultAmbient = true;
if (mLighting)
mLighting->setDefaultAmbient (colour);
}
void SceneWidget::updateOgreWindow()
{
if (mWindow)
{
Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
mWindow = NULL;
}
std::stringstream windowHandle;
#ifdef WIN32
windowHandle << Ogre::StringConverter::toString((uintptr_t)(this->winId()));
#else
windowHandle << this->winId();
#endif
std::stringstream windowTitle;
static int count=0;
windowTitle << ++count;
Ogre::NameValuePairList params;
params.insert(std::make_pair("externalWindowHandle", windowHandle.str()));
params.insert(std::make_pair("title", windowTitle.str()));
std::string antialiasing =
CSMSettings::UserSettings::instance().settingValue("3d-render/antialiasing").toStdString();
if(antialiasing == "MSAA 16") antialiasing = "16";
else if(antialiasing == "MSAA 8") antialiasing = "8";
else if(antialiasing == "MSAA 4") antialiasing = "4";
else if(antialiasing == "MSAA 2") antialiasing = "2";
else antialiasing = "0";
params.insert(std::make_pair("FSAA", antialiasing));
params.insert(std::make_pair("vsync", "false")); // TODO setting
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
params.insert(std::make_pair("macAPI", "cocoa"));
params.insert(std::make_pair("macAPICocoaUseNSView", "true"));
#endif
mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, &params); void RenderWidget::setVisibilityMask(int mask)
{
mViewport = mWindow->addViewport (mCamera); // 0x1 reserved for separating cull and update visitors
mViewport->setBackgroundColour (Ogre::ColourValue (0.3,0.3,0.3,1)); mView->getCamera()->setCullMask(mask<<1);
}
Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height());
mCamera->setAspectRatio(aspectRatio); // --------------------------------------------------
}
CompositeViewer::CompositeViewer()
SceneWidget::~SceneWidget() {
{ #if QT_VERSION >= 0x050000
if (mWindow) // Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4
Ogre::Root::getSingleton().destroyRenderTarget (mWindow); osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::SingleThreaded;
if (mSceneMgr)
mSceneMgr->removeRenderQueueListener (mOverlaySystem);
if (mSceneMgr)
Ogre::Root::getSingleton().destroySceneManager (mSceneMgr);
}
void SceneWidget::setVisibilityMask (unsigned int mask)
{
mViewport->setVisibilityMask (mask);
}
void SceneWidget::setNavigation (Navigation *navigation)
{
if ((mNavigation = navigation))
{
mNavigation->setFastModeFactor (mFast ? mFastFactor : 1);
if (mNavigation->activate (mCamera))
mUpdate = true;
}
}
void SceneWidget::addRenderTargetListener(Ogre::RenderTargetListener *listener)
{
mWindow->addListener(listener);
}
void SceneWidget::removeRenderTargetListener(Ogre::RenderTargetListener *listener)
{
mWindow->removeListener(listener);
}
Ogre::Viewport *SceneWidget::getViewport()
{
if (!mWindow)
updateOgreWindow();
return mViewport;
}
Ogre::SceneManager *SceneWidget::getSceneManager()
{
return mSceneMgr;
}
Ogre::Camera *SceneWidget::getCamera()
{
return mCamera;
}
void SceneWidget::flagAsModified()
{
mUpdate = true;
}
void SceneWidget::paintEvent(QPaintEvent* e)
{
if (!mWindow)
updateOgreWindow();
mWindow->update();
e->accept();
}
QPaintEngine* SceneWidget::paintEngine() const
{
// We don't want another paint engine to get in the way.
// So we return nothing.
return NULL;
}
void SceneWidget::resizeEvent(QResizeEvent *e)
{
if (!mWindow)
return;
const QSize &newSize = e->size();
// TODO: Fix Ogre to handle this more consistently (fixed in 1.9)
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
mWindow->resize(newSize.width(), newSize.height());
#else #else
mWindow->windowMovedOrResized(); osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
#endif #endif
Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height()); setThreadingModel(threadingModel);
mCamera->setAspectRatio(aspectRatio);
} // disable the default setting of viewer.done() by pressing Escape.
setKeyEventSetsDone(0);
bool SceneWidget::event(QEvent *e)
{ // Only render when the camera position changed, or content flagged dirty
if (e->type() == QEvent::WinIdChange) //setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND);
{ setRunFrameScheme(osgViewer::ViewerBase::CONTINUOUS);
// I haven't actually seen this happen yet.
if (mWindow) connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
updateOgreWindow(); mTimer.start( 10 );
} }
return QWidget::event(e);
} CompositeViewer &CompositeViewer::get()
{
void SceneWidget::keyPressEvent (QKeyEvent *event) static CompositeViewer sThis;
{ return sThis;
switch (event->key()) }
{
case Qt::Key_W: mKeyForward = true; break; void CompositeViewer::update()
case Qt::Key_S: mKeyBackward = true; break; {
case Qt::Key_A: mKeyLeft = true; break; frame();
case Qt::Key_D: mKeyRight = true; break; }
case Qt::Key_Q: mKeyRollLeft = true; break;
case Qt::Key_E: mKeyRollRight = true; break; // ---------------------------------------------------
case Qt::Key_Control: mMod1 = true; break;
SceneWidget::SceneWidget(Resource::SceneManager* sceneManager, QWidget *parent, Qt::WindowFlags f)
case Qt::Key_Shift: : RenderWidget(parent, f)
, mSceneManager(sceneManager)
mFast = true; , mLighting(NULL)
, mHasDefaultAmbient(false)
if (mNavigation) {
mNavigation->setFastModeFactor (mFastFactor); // we handle lighting manually
mView->setLightingMode(osgViewer::View::NO_LIGHT);
break;
setLighting(&mLightingDay);
default: QWidget::keyPressEvent (event); }
}
} SceneWidget::~SceneWidget()
{
void SceneWidget::keyReleaseEvent (QKeyEvent *event) // Since we're holding on to the scene templates past the existance of this graphics context, we'll need to manually release the created objects
{ mSceneManager->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState());
switch (event->key()) }
{
case Qt::Key_W: mKeyForward = false; break; void SceneWidget::setLighting(Lighting *lighting)
case Qt::Key_S: mKeyBackward = false; break; {
case Qt::Key_A: mKeyLeft = false; break; if (mLighting)
case Qt::Key_D: mKeyRight = false; break; mLighting->deactivate();
case Qt::Key_Q: mKeyRollLeft = false; break;
case Qt::Key_E: mKeyRollRight = false; break; mLighting = lighting;
case Qt::Key_Control: mMod1 = false; break; mLighting->activate (mRootNode);
case Qt::Key_Shift: osg::Vec4f ambient = mLighting->getAmbientColour(mHasDefaultAmbient ? &mDefaultAmbient : 0);
setAmbient(ambient);
mFast = false;
flagAsModified();
if (mNavigation) }
mNavigation->setFastModeFactor (1);
void SceneWidget::setAmbient(const osg::Vec4f& ambient)
break; {
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
default: QWidget::keyReleaseEvent (event); osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel;
} lightmodel->setAmbientIntensity(ambient);
} stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHT0, osg::StateAttribute::ON);
void SceneWidget::wheelEvent (QWheelEvent *event) stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
{ mRootNode->setStateSet(stateset);
if (mNavigation) }
if (event->delta())
if (mNavigation->wheelMoved (event->delta())) void SceneWidget::selectLightingMode (const std::string& mode)
mUpdate = true; {
} if (mode=="day")
setLighting (&mLightingDay);
void SceneWidget::leaveEvent (QEvent *event) else if (mode=="night")
{ setLighting (&mLightingNight);
mDragging = false; else if (mode=="bright")
} setLighting (&mLightingBright);
}
void SceneWidget::mouseMoveEvent (QMouseEvent *event)
{ CSVWidget::SceneToolMode *SceneWidget::makeLightingSelector (CSVWidget::SceneToolbar *parent)
if (event->buttons() & Qt::LeftButton) {
{ CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Lighting Mode");
if (mDragging)
{ /// \todo replace icons
QPoint diff = mOldPos-event->pos(); tool->addButton (":scenetoolbar/day", "day",
mOldPos = event->pos(); "Day"
"<ul><li>Cell specific ambient in interiors</li>"
if (mNavigation) "<li>Low ambient in exteriors</li>"
if (mNavigation->mouseMoved (diff, mMod1 ? 1 : 0)) "<li>Strong directional light source</li>"
mUpdate = true; "<li>This mode closely resembles day time in-game</li></ul>");
} tool->addButton (":scenetoolbar/night", "night",
else "Night"
{ "<ul><li>Cell specific ambient in interiors</li>"
mDragging = true; "<li>Low ambient in exteriors</li>"
mOldPos = event->pos(); "<li>Weak directional light source</li>"
} "<li>This mode closely resembles night time in-game</li></ul>");
} tool->addButton (":scenetoolbar/bright", "bright",
} "Bright"
"<ul><li>Maximum ambient</li>"
void SceneWidget::mouseReleaseEvent (QMouseEvent *event) "<li>Strong directional light source</li></ul>");
{
if (!(event->buttons() & Qt::LeftButton)) connect (tool, SIGNAL (modeChanged (const std::string&)),
mDragging = false; this, SLOT (selectLightingMode (const std::string&)));
}
return tool;
void SceneWidget::focusOutEvent (QFocusEvent *event) }
{
mKeyForward = false; void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour)
mKeyBackward = false; {
mKeyLeft = false; mDefaultAmbient = colour;
mKeyRight = false; mHasDefaultAmbient = true;
mFast = false;
mMod1 = false; setAmbient(mLighting->getAmbientColour(&mDefaultAmbient));
}
QWidget::focusOutEvent (event);
}
void SceneWidget::update()
{
if (mNavigation)
{
int horizontal = 0;
int vertical = 0;
if (mKeyForward && !mKeyBackward)
vertical = 1;
else if (!mKeyForward && mKeyBackward)
vertical = -1;
if (mKeyLeft && !mKeyRight)
horizontal = -1;
else if (!mKeyLeft && mKeyRight)
horizontal = 1;
if (horizontal || vertical)
if (mNavigation->handleMovementKeys (vertical, horizontal))
mUpdate = true;
int roll = 0;
if (mKeyRollLeft && !mKeyRollRight)
roll = 1;
else if (!mKeyRollLeft && mKeyRollRight)
roll = -1;
if (roll)
if (mNavigation->handleRollKeys (roll))
mUpdate = true;
}
if (mUpdate && mWindow)
{
mUpdate = false;
mWindow->update();
updateOverlay();
}
}
void SceneWidget::updateScene()
{
flagAsModified();
}
void SceneWidget::updateOverlay()
{ }
void SceneWidget::setLighting (Lighting *lighting)
{
if (mLighting)
mLighting->deactivate();
mLighting = lighting;
mLighting->activate (mSceneMgr, mHasDefaultAmbient ? &mDefaultAmbient : 0);
if (mWindow)
mWindow->update();
}
void SceneWidget::selectLightingMode (const std::string& mode)
{
if (mode=="day")
setLighting (&mLightingDay);
else if (mode=="night")
setLighting (&mLightingNight);
else if (mode=="bright")
setLighting (&mLightingBright);
}
void SceneWidget::updateUserSetting (const QString &key, const QStringList &list)
{
if(key.contains(QRegExp("^\\b(Objects|Shader|Scene)", Qt::CaseInsensitive)))
flagAsModified();
if(key == "3d-render/far-clip-distance" && !list.empty())
{
if(mCamera->getFarClipDistance() != list.at(0).toFloat())
mCamera->setFarClipDistance(list.at(0).toFloat());
}
// minimise unnecessary ogre window creation by updating only when there is a change
if(key == "3d-render/antialiasing")
{
unsigned int aa = mWindow->getFSAA();
unsigned int antialiasing = 0;
if(!list.empty())
{
if(list.at(0) == "MSAA 16") antialiasing = 16;
else if(list.at(0) == "MSAA 8") antialiasing = 8;
else if(list.at(0) == "MSAA 4") antialiasing = 4;
else if(list.at(0) == "MSAA 2") antialiasing = 2;
}
if(aa != antialiasing)
updateOgreWindow();
}
}
} }

@ -2,21 +2,23 @@
#define OPENCS_VIEW_SCENEWIDGET_H #define OPENCS_VIEW_SCENEWIDGET_H
#include <QWidget> #include <QWidget>
#include <QTimer>
#include <OgreColourValue.h>
#include "lightingday.hpp" #include "lightingday.hpp"
#include "lightingnight.hpp" #include "lightingnight.hpp"
#include "lightingbright.hpp" #include "lightingbright.hpp"
namespace Ogre #include <osgViewer/View>
#include <osgViewer/CompositeViewer>
namespace Resource
{ {
class Camera;
class SceneManager; class SceneManager;
class RenderWindow; }
class Viewport;
class OverlaySystem; namespace osg
class RenderTargetListener; {
class Group;
} }
namespace CSVWidget namespace CSVWidget
@ -27,114 +29,81 @@ namespace CSVWidget
namespace CSVRender namespace CSVRender
{ {
class Navigation;
class Lighting; class Lighting;
class SceneWidget : public QWidget class RenderWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
SceneWidget(QWidget *parent); virtual ~RenderWidget();
virtual ~SceneWidget();
QPaintEngine* paintEngine() const;
CSVWidget::SceneToolMode *makeLightingSelector (CSVWidget::SceneToolbar *parent);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function.
virtual void setVisibilityMask (unsigned int mask);
virtual void updateScene();
protected:
void setNavigation (Navigation *navigation);
///< \attention The ownership of \a navigation is not transferred to *this.
void addRenderTargetListener(Ogre::RenderTargetListener *listener);
void removeRenderTargetListener(Ogre::RenderTargetListener *listener); void flagAsModified();
Ogre::Viewport *getViewport(); void setVisibilityMask(int mask);
Ogre::SceneManager *getSceneManager(); protected:
Ogre::Camera *getCamera(); osg::ref_ptr<osgViewer::View> mView;
void flagAsModified(); osg::Group* mRootNode;
void setDefaultAmbient (const Ogre::ColourValue& colour); QTimer mTimer;
///< \note The actual ambient colour may differ based on lighting settings. };
virtual void updateOverlay();
virtual void mouseReleaseEvent (QMouseEvent *event);
virtual void mouseMoveEvent (QMouseEvent *event);
void wheelEvent (QWheelEvent *event);
void keyPressEvent (QKeyEvent *event);
private: // Extension of RenderWidget to support lighting mode selection & toolbar
void paintEvent(QPaintEvent* e); class SceneWidget : public RenderWidget
void resizeEvent(QResizeEvent* e); {
bool event(QEvent* e); Q_OBJECT
public:
SceneWidget(Resource::SceneManager* sceneManager, QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~SceneWidget();
void keyReleaseEvent (QKeyEvent *event); CSVWidget::SceneToolMode *makeLightingSelector (CSVWidget::SceneToolbar *parent);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function.
void focusOutEvent (QFocusEvent *event); void setDefaultAmbient (const osg::Vec4f& colour);
///< \note The actual ambient colour may differ based on lighting settings.
void leaveEvent (QEvent *event); protected:
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.
void updateOgreWindow(); void setAmbient(const osg::Vec4f& ambient);
void setLighting (Lighting *lighting); Resource::SceneManager* mSceneManager;
///< \attention The ownership of \a lighting is not transferred to *this.
Ogre::Camera* mCamera; Lighting* mLighting;
Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow;
Ogre::Viewport *mViewport;
Ogre::OverlaySystem *mOverlaySystem;
Navigation *mNavigation; osg::Vec4f mDefaultAmbient;
Lighting *mLighting; bool mHasDefaultAmbient;
bool mUpdate; LightingDay mLightingDay;
bool mKeyForward; LightingNight mLightingNight;
bool mKeyBackward; LightingBright mLightingBright;
bool mKeyLeft;
bool mKeyRight;
bool mKeyRollLeft;
bool mKeyRollRight;
bool mFast;
bool mDragging;
bool mMod1;
QPoint mOldPos;
int mFastFactor;
Ogre::ColourValue mDefaultAmbient;
bool mHasDefaultAmbient;
LightingDay mLightingDay;
LightingNight mLightingNight;
LightingBright mLightingBright;
public slots: private slots:
void updateUserSetting (const QString &key, const QStringList &list); void selectLightingMode (const std::string& mode);
};
private slots:
void update(); // There are rendering glitches when using multiple Viewer instances, work around using CompositeViewer with multiple views
class CompositeViewer : public QObject, public osgViewer::CompositeViewer
{
Q_OBJECT
public:
CompositeViewer();
void selectLightingMode (const std::string& mode); static CompositeViewer& get();
signals: QTimer mTimer;
void focusToolbarRequest(); public slots:
void update();
}; };
} }
#endif #endif

@ -4,7 +4,8 @@ namespace CSVRender
{ {
TerrainStorage::TerrainStorage(const CSMWorld::Data &data) TerrainStorage::TerrainStorage(const CSMWorld::Data &data)
: mData(data) : ESMTerrain::Storage(data.getResourceSystem()->getVFS())
, mData(data)
{ {
} }

@ -1,359 +0,0 @@
#include "textoverlay.hpp"
#include <OgreCamera.h>
#include <OgreMaterialManager.h>
#include <OgreTechnique.h>
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreFontManager.h>
#include <OgreTextAreaOverlayElement.h>
#include <OgreEntity.h>
#include <OgreViewport.h>
#include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
namespace CSVRender
{
// Things to do:
// - configurable font size in pixels (automatically calulate everything else from it)
// - configurable texture to use
// - try material script
// - decide whether to use QPaint (http://www.ogre3d.org/tikiwiki/Ogre+overlays+using+Qt)
// http://www.ogre3d.org/tikiwiki/ObjectTextDisplay
// http://www.ogre3d.org/tikiwiki/MovableTextOverlay
// http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures
// http://www.ogre3d.org/tikiwiki/ManualObject
TextOverlay::TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String& id)
: mOverlay(0), mCaption(""), mDesc(""), mObj(obj), mCamera(camera), mFontHeight(16), mId(id)
, mEnabled(true), mOnScreen(false), mInstance(0) // FIXME: make font height configurable
{
if(id == "" || !camera || !obj)
throw std::runtime_error("TextOverlay could not be created.");
// setup font
Ogre::FontManager &fontMgr = Ogre::FontManager::getSingleton();
if (fontMgr.resourceExists("DejaVuLGC"))
mFont = fontMgr.getByName("DejaVuLGC","General");
else
{
mFont = fontMgr.create("DejaVuLGC","General");
mFont->setType(Ogre::FT_TRUETYPE);
mFont->setSource("DejaVuLGCSansMono.ttf");
mFont->setTrueTypeSize(mFontHeight);
mFont->setTrueTypeResolution(96);
}
if(!mFont.isNull())
mFont->load();
else
throw std::runtime_error("TextOverlay font not loaded.");
// setup overlay
Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton();
mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
// FIXME: this logic is badly broken as it is possible to delete an earlier instance
while(mOverlay != NULL)
{
mInstance++;
mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
}
mOverlay = overlayMgr.create("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
// create texture
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName("DynamicTransBlue");
if(texture.isNull())
{
texture = Ogre::TextureManager::getSingleton().createManual(
"DynamicTransBlue", // name
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, // type
8, 8, // width & height
0, // number of mipmaps
Ogre::PF_BYTE_BGRA, // pixel format
Ogre::TU_DEFAULT); // usage; should be TU_DYNAMIC_WRITE_ONLY_DISCARDABLE for
// textures updated very often (e.g. each frame)
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
// Fill in some pixel data. This will give a semi-transparent blue,
// but this is of course dependent on the chosen pixel format.
for (size_t j = 0; j < 8; j++)
{
for(size_t i = 0; i < 8; i++)
{
*pDest++ = 255; // B
*pDest++ = 0; // G
*pDest++ = 0; // R
*pDest++ = 63; // A
}
pDest += pixelBox.getRowSkip() * Ogre::PixelUtil::getNumElemBytes(pixelBox.format);
}
pixelBuffer->unlock();
}
// setup material for containers
Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().getByName(
"TransOverlayMaterial");
if(mQuadMaterial.isNull())
{
Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().create(
"TransOverlayMaterial",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true );
Ogre::Pass *pass = mQuadMaterial->getTechnique( 0 )->getPass( 0 );
pass->setLightingEnabled( false );
pass->setDepthWriteEnabled( false );
pass->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
Ogre::TextureUnitState *tex = pass->createTextureUnitState("MyCustomState", 0);
tex->setTextureName("DynamicTransBlue");
tex->setTextureFiltering( Ogre::TFO_ANISOTROPIC );
mQuadMaterial->load();
}
mContainer = static_cast<Ogre::OverlayContainer*>(overlayMgr.createOverlayElement(
"Panel", "container"+mId +"#"+Ogre::StringConverter::toString(mInstance)));
mContainer->setMaterialName("TransOverlayMaterial");
mOverlay->add2D(mContainer);
// setup text area overlay element
mElement = static_cast<Ogre::TextAreaOverlayElement*>(overlayMgr.createOverlayElement(
"TextArea", "text"+mId +"#"+Ogre::StringConverter::toString(mInstance)));
mElement->setMetricsMode(Ogre::GMM_RELATIVE);
mElement->setDimensions(1.0, 1.0);
mElement->setMetricsMode(Ogre::GMM_PIXELS);
mElement->setPosition(2*fontHeight()/3, 1.3*fontHeight()/3); // 1.3 & 2 = fudge factor
mElement->setFontName("DejaVuLGC");
mElement->setCharHeight(fontHeight()); // NOTE: seems that this is required as well as font->setTrueTypeSize()
mElement->setHorizontalAlignment(Ogre::GHA_LEFT);
//mElement->setColour(Ogre::ColourValue(1.0, 1.0, 1.0)); // R, G, B
mElement->setColour(Ogre::ColourValue(1.0, 1.0, 0)); // yellow
mContainer->addChild(mElement);
mOverlay->show();
}
void TextOverlay::getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y)
{
Ogre::Vector3 hcsPosition = mCamera->getProjectionMatrix() * (mCamera->getViewMatrix() * position);
x = 1.0f - ((hcsPosition.x * 0.5f) + 0.5f); // 0 <= x <= 1 // left := 0,right := 1
y = ((hcsPosition.y * 0.5f) + 0.5f); // 0 <= y <= 1 // bottom := 0,top := 1
}
void TextOverlay::getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY,
bool top)
{
MinX = 0, MinY = 0, MaxX = 0, MaxY = 0;
float X[4]; // the 2D dots of the AABB in screencoordinates
float Y[4];
if(!mObj->isInScene())
return;
const Ogre::AxisAlignedBox &AABB = mObj->getWorldBoundingBox(true); // the AABB of the target
Ogre::Vector3 cornersOfAABB[4];
if(top)
{
cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_TOP);
cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_TOP);
cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_TOP);
cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_TOP);
}
else
{
cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM);
cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM);
cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM);
cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM);
}
//The normal vector of the plane. This points directly infront of the camera.
Ogre::Vector3 cameraPlainNormal = mCamera->getDerivedOrientation().zAxis();
//the plane that devides the space before and behind the camera.
Ogre::Plane CameraPlane = Ogre::Plane(cameraPlainNormal, mCamera->getDerivedPosition());
for (int i = 0; i < 4; i++)
{
X[i] = 0;
Y[i] = 0;
getScreenCoordinates(cornersOfAABB[i],X[i],Y[i]); // transfor into 2d dots
if (CameraPlane.getSide(cornersOfAABB[i]) == Ogre::Plane::NEGATIVE_SIDE)
{
if (i == 0) // accept the first set of values, no matter how bad it might be.
{
MinX = X[i];
MinY = Y[i];
MaxX = X[i];
MaxY = Y[i];
}
else // now compare if you get "better" values
{
if (MinX > X[i]) MinX = X[i];
if (MinY > Y[i]) MinY = Y[i];
if (MaxX < X[i]) MaxX = X[i];
if (MaxY < Y[i]) MaxY = Y[i];
}
}
else
{
MinX = 0;
MinY = 0;
MaxX = 0;
MaxY = 0;
break;
}
}
}
TextOverlay::~TextOverlay()
{
Ogre::OverlayManager::OverlayMapIterator iter = Ogre::OverlayManager::getSingleton().getOverlayIterator();
if(!iter.hasMoreElements())
mOverlay->hide();
Ogre::OverlayManager *overlayMgr = Ogre::OverlayManager::getSingletonPtr();
mContainer->removeChild("text"+mId+"#"+Ogre::StringConverter::toString(mInstance));
mOverlay->remove2D(mContainer);
if(!iter.hasMoreElements())
overlayMgr->destroy(mOverlay);
}
void TextOverlay::show(bool show)
{
if(show && mOnScreen)
mContainer->show();
else
mContainer->hide();
}
void TextOverlay::enable(bool enable)
{
if(enable == mOverlay->isVisible())
return;
mEnabled = enable;
if(enable)
mOverlay->show();
else
mOverlay->hide();
}
bool TextOverlay::isEnabled()
{
return mEnabled;
}
void TextOverlay::setCaption(const Ogre::String& text)
{
if(mCaption == text)
return;
mCaption = text;
mElement->setCaption(text);
}
void TextOverlay::setDesc(const Ogre::String& text)
{
if(mDesc == text)
return;
mDesc = text;
mElement->setCaption(mCaption + ((text == "") ? "" : ("\n" + text)));
}
Ogre::FontPtr TextOverlay::getFont()
{
return mFont;
}
int TextOverlay::textWidth()
{
float captionWidth = 0;
float descWidth = 0;
for(Ogre::String::const_iterator i = mCaption.begin(); i < mCaption.end(); ++i)
{
if(*i == 0x0020)
captionWidth += getFont()->getGlyphAspectRatio(0x0030);
else
captionWidth += getFont()->getGlyphAspectRatio(*i);
}
for(Ogre::String::const_iterator i = mDesc.begin(); i < mDesc.end(); ++i)
{
if(*i == 0x0020)
descWidth += getFont()->getGlyphAspectRatio(0x0030);
else
descWidth += getFont()->getGlyphAspectRatio(*i);
}
captionWidth *= fontHeight();
descWidth *= fontHeight();
return (int) std::max(captionWidth, descWidth);
}
int TextOverlay::fontHeight()
{
return mFontHeight;
}
void TextOverlay::update()
{
float min_x, max_x, min_y, max_y;
getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y, false);
if ((min_x>0.0) && (max_x<1.0) && (min_y>0.0) && (max_y<1.0))
{
mOnScreen = true;
mContainer->show();
}
else
{
mOnScreen = false;
mContainer->hide();
return;
}
getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y);
Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton();
float viewportWidth = std::max(overlayMgr.getViewportWidth(), 1); // zero at the start
float viewportHeight = std::max(overlayMgr.getViewportHeight(), 1); // zero at the start
int width = fontHeight()*2/3 + textWidth() + fontHeight()*2/3; // add margins
int height = fontHeight()/3 + fontHeight() + fontHeight()/3;
if(mDesc != "")
height = fontHeight()/3 + 2*fontHeight() + fontHeight()/3;
float relTextWidth = width / viewportWidth;
float relTextHeight = height / viewportHeight;
float posX = 1 - (min_x + max_x + relTextWidth)/2;
float posY = 1 - max_y - (relTextHeight-fontHeight()/3/viewportHeight);
mContainer->setMetricsMode(Ogre::GMM_RELATIVE);
mContainer->setPosition(posX, posY);
mContainer->setDimensions(relTextWidth, relTextHeight);
mPos = QRect(posX*viewportWidth, posY*viewportHeight, width, height);
}
QRect TextOverlay::container()
{
return mPos;
}
}

@ -1,66 +0,0 @@
#ifndef OPENCS_VIEW_TEXTOVERLAY_H
#define OPENCS_VIEW_TEXTOVERLAY_H
#include <QRect>
#include <OgreString.h>
#include <OgreFont.h>
namespace Ogre
{
class MovableObject;
class Camera;
class Font;
class Overlay;
class OverlayContainer;
class TextAreaOverlayElement;
}
namespace CSVRender
{
class TextOverlay
{
Ogre::Overlay* mOverlay;
Ogre::OverlayContainer* mContainer;
Ogre::TextAreaOverlayElement* mElement;
Ogre::String mCaption;
Ogre::String mDesc;
const Ogre::MovableObject* mObj;
const Ogre::Camera* mCamera;
Ogre::FontPtr mFont;
int mFontHeight; // in pixels
Ogre::String mId;
QRect mPos;
bool mEnabled;
bool mOnScreen;
int mInstance;
Ogre::FontPtr getFont();
int textWidth();
int fontHeight();
void getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y);
void getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY,
bool top = true);
public:
TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String &id);
virtual ~TextOverlay();
void enable(bool enable); // controlled from scene widget toolbar visibility mask
void show(bool show); // for updating from render target listener
bool isEnabled();
void setCaption(const Ogre::String& text);
void setDesc(const Ogre::String& text);
void update();
QRect container(); // for detection of mouse click on the overlay
Ogre::String getCaption() { return mCaption; } // FIXME: debug
Ogre::String getDesc() { return mDesc; }
};
}
#endif // OPENCS_VIEW_TEXTOVERLAY_H

@ -3,11 +3,12 @@
#include <sstream> #include <sstream>
#include <OgreColourValue.h> #include <osgGA/TrackballManipulator>
#include <OgreCamera.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include <components/sceneutil/util.hpp>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
@ -24,8 +25,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
const CSMWorld::Record<CSMWorld::Cell>& record = const CSMWorld::Record<CSMWorld::Cell>& record =
dynamic_cast<const CSMWorld::Record<CSMWorld::Cell>&> (mCellsModel->getRecord (mCellId)); dynamic_cast<const CSMWorld::Record<CSMWorld::Cell>&> (mCellsModel->getRecord (mCellId));
Ogre::ColourValue colour; osg::Vec4f colour = SceneUtil::colourFromRGB(record.get().mAmbi.mAmbient);
colour.setAsABGR (record.get().mAmbi.mAmbient);
setDefaultAmbient (colour); setDefaultAmbient (colour);
/// \todo deal with mSunlight and mFog/mForDensity /// \todo deal with mSunlight and mFog/mForDensity
@ -49,7 +50,9 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string&
update(); update();
mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId, document.getPhysics())); mCell.reset (new Cell (document.getData(), mRootNode, mCellId));
mView->setCameraManipulator(new osgGA::TrackballManipulator);
} }
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft, void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
@ -91,7 +94,8 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld:
return false; return false;
mCellId = data.begin()->getId(); mCellId = data.begin()->getId();
mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId, getDocument().getPhysics()));
mCell.reset (new Cell (getDocument().getData(), mRootNode, mCellId));
update(); update();
emit cellChanged(*data.begin()); emit cellChanged(*data.begin());
@ -163,13 +167,13 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction() std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
{ {
Ogre::Vector3 position = getCamera()->getPosition(); osg::Vec3d position = mView->getCamera()->getViewMatrix().getTrans();
std::ostringstream stream; std::ostringstream stream;
stream stream
<< "player->positionCell " << "player->positionCell "
<< position.x << ", " << position.y << ", " << position.z << position.x() << ", " << position.y() << ", " << position.z()
<< ", 0, \"" << mCellId << "\""; << ", 0, \"" << mCellId << "\"";
return stream.str(); return stream.str();

@ -3,12 +3,11 @@
#include <algorithm> #include <algorithm>
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include <osgGA/TrackballManipulator>
#include <osgGA/FirstPersonManipulator>
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
@ -16,13 +15,11 @@
#include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetooltoggle2.hpp"
#include "../widget/scenetoolrun.hpp" #include "../widget/scenetoolrun.hpp"
#include "../world/physicssystem.hpp"
#include "elements.hpp" #include "elements.hpp"
#include "editmode.hpp" #include "editmode.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
: SceneWidget (parent), mSceneElements(0), mRun(0), mDocument(document), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()), mMouse(0), : SceneWidget (document.getData().getResourceSystem()->getSceneManager(), parent), mSceneElements(0), mRun(0), mDocument(document),
mInteractionMask (0) mInteractionMask (0)
{ {
setAcceptDrops(true); setAcceptDrops(true);
@ -54,33 +51,27 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
this, SLOT (debugProfileDataChanged (const QModelIndex&, const QModelIndex&))); this, SLOT (debugProfileDataChanged (const QModelIndex&, const QModelIndex&)));
connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int))); this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int)));
mPhysics = document.getPhysics(); // create physics if one doesn't exist
mPhysics->addSceneManager(getSceneManager(), this);
mMouse = new MouseState(this);
} }
CSVRender::WorldspaceWidget::~WorldspaceWidget () CSVRender::WorldspaceWidget::~WorldspaceWidget ()
{ {
delete mMouse;
mPhysics->removeSceneManager(getSceneManager());
} }
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
{ {
if (mode=="1st") if (mode=="1st")
setNavigation (&m1st); mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
else if (mode=="free") else if (mode=="free")
setNavigation (&mFree); mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
else if (mode=="orbit") else if (mode=="orbit")
setNavigation (&mOrbit); mView->setCameraManipulator(new osgGA::OrbitManipulator);
} }
void CSVRender::WorldspaceWidget::useViewHint (const std::string& hint) {} void CSVRender::WorldspaceWidget::useViewHint (const std::string& hint) {}
void CSVRender::WorldspaceWidget::selectDefaultNavigationMode() void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
{ {
setNavigation (&m1st); mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
} }
CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
@ -368,16 +359,16 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
{ {
if(event->buttons() & Qt::RightButton) if(event->buttons() & Qt::RightButton)
{ {
mMouse->mouseMoveEvent(event); //mMouse->mouseMoveEvent(event);
} }
SceneWidget::mouseMoveEvent(event); RenderWidget::mouseMoveEvent(event);
} }
void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event)
{ {
if(event->buttons() & Qt::RightButton) if(event->buttons() & Qt::RightButton)
{ {
mMouse->mousePressEvent(event); //mMouse->mousePressEvent(event);
} }
//SceneWidget::mousePressEvent(event); //SceneWidget::mousePressEvent(event);
} }
@ -386,37 +377,39 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
{ {
if(event->button() == Qt::RightButton) if(event->button() == Qt::RightButton)
{ {
/*
if(!getViewport()) if(!getViewport())
{ {
SceneWidget::mouseReleaseEvent(event); SceneWidget::mouseReleaseEvent(event);
return; return;
} }
mMouse->mouseReleaseEvent(event); */
//mMouse->mouseReleaseEvent(event);
} }
SceneWidget::mouseReleaseEvent(event); RenderWidget::mouseReleaseEvent(event);
} }
void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event)
{ {
if(event->button() == Qt::RightButton) if(event->button() == Qt::RightButton)
{ {
mMouse->mouseDoubleClickEvent(event); //mMouse->mouseDoubleClickEvent(event);
} }
//SceneWidget::mouseDoubleClickEvent(event); //SceneWidget::mouseDoubleClickEvent(event);
} }
void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event)
{ {
if(!mMouse->wheelEvent(event)) //if(!mMouse->wheelEvent(event))
SceneWidget::wheelEvent(event); RenderWidget::wheelEvent(event);
} }
void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
{ {
if(event->key() == Qt::Key_Escape) if(event->key() == Qt::Key_Escape)
{ {
mMouse->cancelDrag(); //mMouse->cancelDrag();
} }
else else
SceneWidget::keyPressEvent(event); RenderWidget::keyPressEvent(event);
} }

@ -4,11 +4,7 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "scenewidget.hpp" #include "scenewidget.hpp"
#include "mousestate.hpp"
#include "navigation1st.hpp"
#include "navigationfree.hpp"
#include "navigationorbit.hpp"
#include <apps/opencs/model/doc/document.hpp> #include <apps/opencs/model/doc/document.hpp>
#include <apps/opencs/model/world/tablemimedata.hpp> #include <apps/opencs/model/world/tablemimedata.hpp>
@ -25,25 +21,15 @@ namespace CSVWidget
class SceneToolRun; class SceneToolRun;
} }
namespace CSVWorld
{
class PhysicsSystem;
}
namespace CSVRender namespace CSVRender
{ {
class WorldspaceWidget : public SceneWidget class WorldspaceWidget : public SceneWidget
{ {
Q_OBJECT Q_OBJECT
CSVRender::Navigation1st m1st;
CSVRender::NavigationFree mFree;
CSVRender::NavigationOrbit mOrbit;
CSVWidget::SceneToolToggle2 *mSceneElements; CSVWidget::SceneToolToggle2 *mSceneElements;
CSVWidget::SceneToolRun *mRun; CSVWidget::SceneToolRun *mRun;
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
MouseState *mMouse;
unsigned int mInteractionMask; unsigned int mInteractionMask;
public: public:

@ -0,0 +1,28 @@
#include "completerpopup.hpp"
CSVWidget::CompleterPopup::CompleterPopup(QWidget *parent)
: QListView(parent)
{
setEditTriggers(QAbstractItemView::NoEditTriggers);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
}
int CSVWidget::CompleterPopup::sizeHintForRow(int row) const
{
if (model() == NULL)
{
return -1;
}
if (row < 0 || row >= model()->rowCount())
{
return -1;
}
ensurePolished();
QModelIndex index = model()->index(row, modelColumn());
QStyleOptionViewItem option = viewOptions();
QAbstractItemDelegate *delegate = itemDelegate(index);
return delegate->sizeHint(option, index).height();
}

@ -0,0 +1,17 @@
#ifndef CSV_WIDGET_COMPLETERPOPUP_HPP
#define CSV_WIDGET_COMPLETERPOPUP_HPP
#include <QListView>
namespace CSVWidget
{
class CompleterPopup : public QListView
{
public:
CompleterPopup(QWidget *parent = 0);
virtual int sizeHintForRow(int row) const;
};
}
#endif

@ -0,0 +1,39 @@
#include "idcompletiondelegate.hpp"
#include "../../model/world/idcompletionmanager.hpp"
CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent)
: CommandDelegate(dispatcher, document, parent)
{}
QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
return createEditor(parent, option, index, getDisplayTypeFromIndex(index));
}
QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index,
CSMWorld::ColumnBase::Display display) const
{
if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid())
{
return NULL;
}
CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager();
DropLineEdit *editor = new DropLineEdit(parent);
editor->setCompleter(completionManager.getCompleter(display).get());
return editor;
}
CSVWorld::CommandDelegate *CSVWorld::IdCompletionDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent) const
{
return new IdCompletionDelegate(dispatcher, document, parent);
}

@ -0,0 +1,36 @@
#ifndef CSV_WORLD_IDCOMPLETIONDELEGATE_HPP
#define CSV_WORLD_IDCOMPLETIONDELEGATE_HPP
#include "util.hpp"
namespace CSVWorld
{
/// \brief Enables the Id completion for a column
class IdCompletionDelegate : public CommandDelegate
{
public:
IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent);
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index,
CSMWorld::ColumnBase::Display display) const;
};
class IdCompletionDelegateFactory : public CommandDelegateFactory
{
public:
virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
}
#endif

@ -1,324 +0,0 @@
#include "physicssystem.hpp"
#include <iostream>
#include <OgreRay.h>
#include <OgreCamera.h>
#include <OgreSceneManager.h>
#include <openengine/bullet/physic.hpp>
#include <components/nifbullet/bulletnifloader.hpp>
#include "../../model/settings/usersettings.hpp"
#include "../render/elements.hpp"
namespace CSVWorld
{
PhysicsSystem::PhysicsSystem()
{
// Create physics. shapeLoader is deleted by the physic engine
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(true);
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
}
PhysicsSystem::~PhysicsSystem()
{
delete mEngine;
}
// looks up the scene manager based on the scene node name (inefficient)
// NOTE: referenceId is assumed to be unique per document
// NOTE: searching is done here rather than after rayTest, hence slower to load but
// faster to find (guessing, not verified w/ perf test)
void PhysicsSystem::addObject(const std::string &mesh,
const std::string &sceneNodeName, const std::string &referenceId, float scale,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, bool placeable)
{
Ogre::SceneManager *sceneManager = findSceneManager(sceneNodeName);
if(sceneManager)
{
// update maps (NOTE: sometimes replaced)
mSceneNodeToRefId[sceneNodeName] = referenceId;
mSceneNodeToMesh[sceneNodeName] = mesh;
mRefIdToSceneNode[referenceId][sceneManager] = sceneNodeName;
}
else
{
std::cerr << "Attempt to add an object without a corresponding SceneManager: "
+ referenceId + " : " + sceneNodeName << std::endl;
return;
}
// update physics, only one physics model per referenceId
if(mEngine->getRigidBody(referenceId, true) == NULL)
{
mEngine->createAndAdjustRigidBody(mesh,
referenceId, scale, position, rotation,
0, // scaledBoxTranslation
0, // boxRotation
true, // raycasting
placeable);
}
}
// normal delete (e.g closing a scene subview or ~Object())
// the scene node is destroyed so the mappings should be removed
//
// TODO: should think about using some kind of reference counting within RigidBody
void PhysicsSystem::removeObject(const std::string &sceneNodeName)
{
std::string referenceId = mSceneNodeToRefId[sceneNodeName];
if(referenceId != "")
{
mSceneNodeToRefId.erase(sceneNodeName);
mSceneNodeToMesh.erase(sceneNodeName);
// find which SceneManager has this object
Ogre::SceneManager *sceneManager = findSceneManager(sceneNodeName);
if(!sceneManager)
{
std::cerr << "Attempt to remove an object without a corresponding SceneManager: "
+ sceneNodeName << std::endl;
return;
}
// illustration: erase the object "K" from the object map
//
// RidigBody SubView Ogre
// --------------- -------------- -------------
// ReferenceId "A" (SceneManager X SceneNode "J")
// (SceneManager Y SceneNode "K") <--- erase
// (SceneManager Z SceneNode "L")
//
// ReferenceId "B" (SceneManager X SceneNode "M")
// (SceneManager Y SceneNode "N") <--- notice not deleted
// (SceneManager Z SceneNode "O")
std::map<std::string, std::map<Ogre::SceneManager *, std::string> >::iterator itRef =
mRefIdToSceneNode.begin();
for(; itRef != mRefIdToSceneNode.end(); ++itRef)
{
if((*itRef).second.find(sceneManager) != (*itRef).second.end())
{
(*itRef).second.erase(sceneManager);
break;
}
}
// check whether the physics model should be deleted
if(mRefIdToSceneNode.find(referenceId) == mRefIdToSceneNode.end())
{
mEngine->removeRigidBody(referenceId);
mEngine->deleteRigidBody(referenceId);
}
}
}
// Object::clear() is called when reference data is changed. It clears all
// contents of the SceneNode and removes the physics object
//
// A new physics object will be created and assigned to this sceneNodeName by
// Object::update()
void PhysicsSystem::removePhysicsObject(const std::string &sceneNodeName)
{
std::string referenceId = mSceneNodeToRefId[sceneNodeName];
if(referenceId != "")
{
mEngine->removeRigidBody(referenceId);
mEngine->deleteRigidBody(referenceId);
}
}
void PhysicsSystem::replaceObject(const std::string &sceneNodeName, float scale,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, bool placeable)
{
std::string referenceId = mSceneNodeToRefId[sceneNodeName];
std::string mesh = mSceneNodeToMesh[sceneNodeName];
if(referenceId != "")
{
// delete the physics object
mEngine->removeRigidBody(referenceId);
mEngine->deleteRigidBody(referenceId);
// create a new physics object
mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation,
0, 0, true, placeable);
// update other scene managers if they have the referenceId
// FIXME: rotation or scale not updated
moveSceneNodeImpl(sceneNodeName, referenceId, position);
}
}
// FIXME: adjustRigidBody() seems to lose objects, work around by deleting and recreating objects
void PhysicsSystem::moveObject(const std::string &sceneNodeName,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation)
{
mEngine->adjustRigidBody(mEngine->getRigidBody(sceneNodeName, true /*raycasting*/),
position, rotation);
}
void PhysicsSystem::moveSceneNodeImpl(const std::string sceneNodeName,
const std::string referenceId, const Ogre::Vector3 &position)
{
std::map<Ogre::SceneManager *, CSVRender::SceneWidget *>::const_iterator iter = mSceneWidgets.begin();
for(; iter != mSceneWidgets.end(); ++iter)
{
std::string name = refIdToSceneNode(referenceId, (*iter).first);
if(name != sceneNodeName && (*iter).first->hasSceneNode(name))
{
(*iter).first->getSceneNode(name)->setPosition(position);
}
}
}
void PhysicsSystem::moveSceneNodes(const std::string sceneNodeName, const Ogre::Vector3 &position)
{
moveSceneNodeImpl(sceneNodeName, sceneNodeToRefId(sceneNodeName), position);
}
void PhysicsSystem::addHeightField(Ogre::SceneManager *sceneManager,
float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts)
{
std::string name = "HeightField_"
+ QString::number(x).toStdString() + "_" + QString::number(y).toStdString();
if(mTerrain.find(name) == mTerrain.end())
mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts);
mTerrain.insert(std::pair<std::string, Ogre::SceneManager *>(name, sceneManager));
}
void PhysicsSystem::removeHeightField(Ogre::SceneManager *sceneManager, int x, int y)
{
std::string name = "HeightField_"
+ QString::number(x).toStdString() + "_" + QString::number(y).toStdString();
if(mTerrain.count(name) == 1)
mEngine->removeHeightField(x, y);
std::multimap<std::string, Ogre::SceneManager *>::iterator iter = mTerrain.begin();
for(; iter != mTerrain.end(); ++iter)
{
if((*iter).second == sceneManager)
{
mTerrain.erase(iter);
break;
}
}
}
// sceneMgr: to lookup the scene node name from the object's referenceId
// camera: primarily used to get the visibility mask for the viewport
//
// returns the found object's scene node name and its position in the world space
//
// WARNING: far clip distance is a global setting, if it changes in future
// this method will need to be updated
std::pair<std::string, Ogre::Vector3> PhysicsSystem::castRay(float mouseX,
float mouseY, Ogre::SceneManager *sceneMgr, Ogre::Camera *camera)
{
// NOTE: there could be more than one camera for the scene manager
// TODO: check whether camera belongs to sceneMgr
if(!sceneMgr || !camera || !camera->getViewport())
return std::make_pair("", Ogre::Vector3(0,0,0)); // FIXME: this should be an exception
// using a really small value seems to mess up with the projections
float nearClipDistance = camera->getNearClipDistance(); // save existing
camera->setNearClipDistance(10.0f); // arbitrary number
Ogre::Ray ray = camera->getCameraToViewportRay(mouseX, mouseY);
camera->setNearClipDistance(nearClipDistance); // restore
Ogre::Vector3 from = ray.getOrigin();
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
float farClipDist = userSettings.setting("Scene/far clip distance", QString("300000")).toFloat();
Ogre::Vector3 to = ray.getPoint(farClipDist);
btVector3 _from, _to;
_from = btVector3(from.x, from.y, from.z);
_to = btVector3(to.x, to.y, to.z);
uint32_t visibilityMask = camera->getViewport()->getVisibilityMask();
bool ignoreHeightMap = !(visibilityMask & (uint32_t)CSVRender::Element_Terrain);
bool ignoreObjects = !(visibilityMask & (uint32_t)CSVRender::Element_Reference);
Ogre::Vector3 norm; // not used
std::pair<std::string, float> result =
mEngine->rayTest(_from, _to, !ignoreObjects, ignoreHeightMap, &norm);
// result.first is the object's referenceId
if(result.first == "")
return std::make_pair("", Ogre::Vector3(0,0,0));
else
{
std::string name = refIdToSceneNode(result.first, sceneMgr);
if(name == "")
name = result.first;
else
name = refIdToSceneNode(result.first, sceneMgr);
return std::make_pair(name, ray.getPoint(farClipDist*result.second));
}
}
std::string PhysicsSystem::refIdToSceneNode(std::string referenceId, Ogre::SceneManager *sceneMgr)
{
return mRefIdToSceneNode[referenceId][sceneMgr];
}
std::string PhysicsSystem::sceneNodeToRefId(std::string sceneNodeName)
{
return mSceneNodeToRefId[sceneNodeName];
}
void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget *sceneWidget)
{
mSceneWidgets[sceneMgr] = sceneWidget;
mEngine->createDebugDraw(sceneMgr);
}
std::map<Ogre::SceneManager*, CSVRender::SceneWidget *> PhysicsSystem::sceneWidgets()
{
return mSceneWidgets;
}
void PhysicsSystem::removeSceneManager(Ogre::SceneManager *sceneMgr)
{
mEngine->removeDebugDraw(sceneMgr);
mSceneWidgets.erase(sceneMgr);
}
Ogre::SceneManager *PhysicsSystem::findSceneManager(std::string sceneNodeName)
{
std::map<Ogre::SceneManager *, CSVRender::SceneWidget *>::const_iterator iter = mSceneWidgets.begin();
for(; iter != mSceneWidgets.end(); ++iter)
{
if((*iter).first->hasSceneNode(sceneNodeName))
{
return (*iter).first;
}
}
return NULL;
}
void PhysicsSystem::toggleDebugRendering(Ogre::SceneManager *sceneMgr)
{
// FIXME: should check if sceneMgr is in the list
if(!sceneMgr)
return;
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
if(!(userSettings.setting("debug/mouse-picking", QString("false")) == "true" ? true : false))
{
std::cerr << "Turn on mouse-picking debug option to see collision shapes." << std::endl;
return;
}
mEngine->toggleDebugRendering(sceneMgr);
mEngine->stepDebug(sceneMgr);
}
}

@ -1,94 +0,0 @@
#ifndef CSV_WORLD_PHYSICSSYSTEM_H
#define CSV_WORLD_PHYSICSSYSTEM_H
#include <string>
#include <map>
namespace Ogre
{
class Vector3;
class Quaternion;
class SceneManager;
class Camera;
}
namespace OEngine
{
namespace Physic
{
class PhysicEngine;
}
}
namespace CSVRender
{
class SceneWidget;
}
namespace CSVWorld
{
class PhysicsSystem
{
std::map<std::string, std::string> mSceneNodeToRefId;
std::map<std::string, std::map<Ogre::SceneManager *, std::string> > mRefIdToSceneNode;
std::map<std::string, std::string> mSceneNodeToMesh;
std::map<Ogre::SceneManager*, CSVRender::SceneWidget *> mSceneWidgets;
OEngine::Physic::PhysicEngine* mEngine;
std::multimap<std::string, Ogre::SceneManager *> mTerrain;
public:
PhysicsSystem();
~PhysicsSystem();
void addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene);
void removeSceneManager(Ogre::SceneManager *sceneMgr);
void addObject(const std::string &mesh,
const std::string &sceneNodeName, const std::string &referenceId, float scale,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
bool placeable=false);
void removeObject(const std::string &sceneNodeName);
void removePhysicsObject(const std::string &sceneNodeName);
void replaceObject(const std::string &sceneNodeName,
float scale, const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation, bool placeable=false);
void moveObject(const std::string &sceneNodeName,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation);
void moveSceneNodes(const std::string sceneNodeName, const Ogre::Vector3 &position);
void addHeightField(Ogre::SceneManager *sceneManager,
float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts);
void removeHeightField(Ogre::SceneManager *sceneManager, int x, int y);
void toggleDebugRendering(Ogre::SceneManager *sceneMgr);
// return the object's SceneNode name and position for the given SceneManager
std::pair<std::string, Ogre::Vector3> castRay(float mouseX,
float mouseY, Ogre::SceneManager *sceneMgr, Ogre::Camera *camera);
std::string sceneNodeToRefId(std::string sceneNodeName);
// for multi-scene manager per physics engine
std::map<Ogre::SceneManager*, CSVRender::SceneWidget *> sceneWidgets();
private:
void moveSceneNodeImpl(const std::string sceneNodeName,
const std::string referenceId, const Ogre::Vector3 &position);
void updateSelectionHighlight(std::string sceneNode, const Ogre::Vector3 &position);
std::string refIdToSceneNode(std::string referenceId, Ogre::SceneManager *sceneMgr);
Ogre::SceneManager *findSceneManager(std::string sceneNodeName);
};
}
#endif // CSV_WORLD_PHYSICSSYSTEM_H

@ -111,6 +111,12 @@ CSMDoc::Document& CSVWorld::CommandDelegate::getDocument() const
return mDocument; return mDocument;
} }
CSMWorld::ColumnBase::Display CSVWorld::CommandDelegate::getDisplayTypeFromIndex(const QModelIndex &index) const
{
int rawDisplay = index.data(CSMWorld::ColumnBase::Role_Display).toInt();
return static_cast<CSMWorld::ColumnBase::Display>(rawDisplay);
}
void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const const QModelIndex& index) const
{ {
@ -146,7 +152,17 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const const QModelIndex& index) const
{ {
return createEditor (parent, option, index, CSMWorld::ColumnBase::Display_None); CSMWorld::ColumnBase::Display display = getDisplayTypeFromIndex(index);
// This createEditor() method is called implicitly from tables.
// For boolean values in tables use the default editor (combobox).
// Checkboxes is looking ugly in the table view.
// TODO: Find a better solution?
if (display == CSMWorld::ColumnBase::Display_Boolean)
{
return QStyledItemDelegate::createEditor(parent, option, index);
}
return createEditor (parent, option, index, display);
} }
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,

@ -124,6 +124,8 @@ namespace CSVWorld
CSMDoc::Document& getDocument() const; CSMDoc::Document& getDocument() const;
CSMWorld::ColumnBase::Display getDisplayTypeFromIndex(const QModelIndex &index) const;
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const; const QModelIndex& index) const;

@ -20,10 +20,9 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER}) source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
actors objects renderinginterface localmap occlusionquery water shadows creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
characterpreview globalmap ripplesimulation refraction bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage
terrainstorage renderconst effectmanager weaponanimation
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
@ -31,7 +30,7 @@ add_openmw_dir (mwinput
) )
add_openmw_dir (mwgui add_openmw_dir (mwgui
textinput widgets race class birth review windowmanagerimp console dialogue layout textinput widgets race class birth review windowmanagerimp console dialogue
windowbase statswindow messagebox journalwindow charactercreation windowbase statswindow messagebox journalwindow charactercreation
mapwindow windowpinnablebase tooltips scrollwindow bookwindow mapwindow windowpinnablebase tooltips scrollwindow bookwindow
formatting inventorywindow container hud countdialog tradewindow settingswindow formatting inventorywindow container hud countdialog tradewindow settingswindow
@ -61,12 +60,16 @@ add_openmw_dir (mwsound
) )
add_openmw_dir (mwworld add_openmw_dir (mwworld
refdata worldimp physicssystem scene globals class action nullaction actionteleport refdata worldimp scene globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellfunctors failedaction containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread cells localscripts customdata inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist projectilemanager cellref contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
)
add_openmw_dir (mwphysics
physicssystem trace collisiontype actor convert
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
@ -75,10 +78,11 @@ add_openmw_dir (mwclass
) )
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects mechanicsmanagerimp stat creaturestats magiceffects movement
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
character actors objects aistate
) )
add_openmw_dir (mwstate add_openmw_dir (mwstate
@ -92,9 +96,9 @@ add_openmw_dir (mwbase
# Main executable # Main executable
if (ANDROID) if (ANDROID)
set(BOOST_COMPONENTS system filesystem program_options thread wave atomic) set(BOOST_COMPONENTS system filesystem program_options thread atomic)
else () else ()
set(BOOST_COMPONENTS system filesystem program_options thread wave) set(BOOST_COMPONENTS system filesystem program_options thread)
endif () endif ()
if(WIN32) if(WIN32)
@ -122,36 +126,27 @@ endif ()
include_directories(${SOUND_INPUT_INCLUDES}) include_directories(${SOUND_INPUT_INCLUDES})
target_link_libraries(openmw target_link_libraries(openmw
${OENGINE_LIBRARY} ${OPENSCENEGRAPH_LIBRARIES}
${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SHINY_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPENAL_LIBRARY} ${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY} ${SOUND_INPUT_LIBRARY}
${BULLET_LIBRARIES} ${BULLET_LIBRARIES}
${MYGUI_LIBRARIES} ${MYGUI_LIBRARIES}
${SDL2_LIBRARY} ${SDL2_LIBRARY}
${MYGUI_PLATFORM_LIBRARIES} "osg-ffmpeg-videoplayer"
"ogre-ffmpeg-videoplayer"
"oics" "oics"
"sdl4ogre"
components components
) )
if (ANDROID) if (ANDROID)
target_link_libraries(openmw target_link_libraries(openmw
${OGRE_STATIC_PLUGINS}
EGL EGL
android android
log log
dl dl
MyGUI.OgrePlatform
MyGUIEngineStatic MyGUIEngineStatic
Plugin_StrangeButtonStatic
cpufeatures cpufeatures
BulletCollision BulletCollision
BulletDynamics
LinearMath LinearMath
) )
endif (ANDROID) endif (ANDROID)

@ -25,7 +25,7 @@
/// \namespace MWRender /// \namespace MWRender
/// \ingroup openmw /// \ingroup openmw
/// \brief Rendering via Ogre /// \brief Rendering
/// \namespace MWWorld /// \namespace MWWorld
/// \ingroup openmw /// \ingroup openmw

@ -3,24 +3,29 @@
#include <stdexcept> #include <stdexcept>
#include <iomanip> #include <iomanip>
#include <OgreRoot.h> #include <boost/filesystem/fstream.hpp>
#include <OgreRenderWindow.h>
#include <MyGUI_WidgetManager.h> #include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <SDL.h> #include <SDL.h>
#include <openengine/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/vfs/manager.hpp>
#include <components/vfs/registerarchives.hpp>
#include <components/sdlutil/sdlgraphicswindow.hpp>
#include <components/sdlutil/imagetosurface.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/texturemanager.hpp>
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/bsa/resources.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/nifoverrides/nifoverrides.hpp>
#include <components/nifbullet/bulletnifloader.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include <components/esm/loadcell.hpp> #include <components/esm/loadcell.hpp>
@ -38,6 +43,8 @@
#include "mwworld/player.hpp" #include "mwworld/player.hpp"
#include "mwworld/worldimp.hpp" #include "mwworld/worldimp.hpp"
#include "mwrender/vismask.hpp"
#include "mwclass/classes.hpp" #include "mwclass/classes.hpp"
#include "mwdialogue/dialoguemanagerimp.hpp" #include "mwdialogue/dialoguemanagerimp.hpp"
@ -66,23 +73,11 @@ void OMW::Engine::executeLocalScripts()
localScripts.setIgnore (MWWorld::Ptr()); localScripts.setIgnore (MWWorld::Ptr());
} }
bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt) double OMW::Engine::frame(float frametime)
{
if (MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame)
{
bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode();
MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame, paused);
MWBase::Environment::get().getWindowManager ()->frameStarted(evt.timeSinceLastFrame);
}
return true;
}
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{ {
try try
{ {
float frametime = evt.timeSinceLastFrame; mStartTick = mViewer->getStartTick();
mEnvironment.setFrameDuration (frametime); mEnvironment.setFrameDuration (frametime);
// update input // update input
@ -90,8 +85,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// When the window is minimized, pause everything. Currently this *has* to be here to work around a MyGUI bug. // When the window is minimized, pause everything. Currently this *has* to be here to work around a MyGUI bug.
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures. // If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures.
if (!mOgre->getWindow()->isActive() || !mOgre->getWindow()->isVisible()) //if (!mOgre->getWindow()->isActive() || !mOgre->getWindow()->isVisible())
return true; // return true;
// sound // sound
if (mUseSound) if (mUseSound)
@ -99,6 +94,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// GUI active? Most game processing will be paused, but scripts still run. // GUI active? Most game processing will be paused, but scripts still run.
bool guiActive = MWBase::Environment::get().getWindowManager()->isGuiMode(); bool guiActive = MWBase::Environment::get().getWindowManager()->isGuiMode();
if (!guiActive)
mSimulationTime += frametime;
// Main menu opened? Then scripts are also paused. // Main menu opened? Then scripts are also paused.
bool paused = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu); bool paused = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu);
@ -106,6 +103,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// update game state // update game state
MWBase::Environment::get().getStateManager()->update (frametime); MWBase::Environment::get().getStateManager()->update (frametime);
osg::Timer_t beforeScriptTick = osg::Timer::instance()->tick();
if (MWBase::Environment::get().getStateManager()->getState()== if (MWBase::Environment::get().getStateManager()->getState()==
MWBase::StateManager::State_Running) MWBase::StateManager::State_Running)
{ {
@ -127,15 +125,17 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
MWBase::Environment::get().getWorld()->advanceTime( MWBase::Environment::get().getWorld()->advanceTime(
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600); frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
} }
osg::Timer_t afterScriptTick = osg::Timer::instance()->tick();
// update actors // update actors
osg::Timer_t beforeMechanicsTick = osg::Timer::instance()->tick();
if (MWBase::Environment::get().getStateManager()->getState()!= if (MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame) MWBase::StateManager::State_NoGame)
{ {
MWBase::Environment::get().getMechanicsManager()->update(frametime, MWBase::Environment::get().getMechanicsManager()->update(frametime,
guiActive); guiActive);
} }
osg::Timer_t afterMechanicsTick = osg::Timer::instance()->tick();
if (MWBase::Environment::get().getStateManager()->getState()== if (MWBase::Environment::get().getStateManager()->getState()==
MWBase::StateManager::State_Running) MWBase::StateManager::State_Running)
@ -146,37 +146,51 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
} }
// update world // update world
osg::Timer_t beforePhysicsTick = osg::Timer::instance()->tick();;
if (MWBase::Environment::get().getStateManager()->getState()!= if (MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame) MWBase::StateManager::State_NoGame)
{ {
MWBase::Environment::get().getWorld()->update(frametime, guiActive); MWBase::Environment::get().getWorld()->update(frametime, guiActive);
} }
osg::Timer_t afterPhysicsTick = osg::Timer::instance()->tick();
// update GUI // update GUI
MWBase::Environment::get().getWindowManager()->onFrame(frametime); MWBase::Environment::get().getWindowManager()->onFrame(frametime);
if (MWBase::Environment::get().getStateManager()->getState()!= if (MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame) MWBase::StateManager::State_NoGame)
{ {
Ogre::RenderWindow* window = mOgre->getWindow(); #if 0
unsigned int tri, batch; MWBase::Environment::get().getWindowManager()->wmUpdateFps(fps);
MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); #endif
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
MWBase::Environment::get().getWindowManager()->update(); MWBase::Environment::get().getWindowManager()->update();
} }
int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
osg::Stats* stats = mViewer->getViewerStats();
stats->setAttribute(frameNumber, "script_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeScriptTick));
stats->setAttribute(frameNumber, "script_time_taken", osg::Timer::instance()->delta_s(beforeScriptTick, afterScriptTick));
stats->setAttribute(frameNumber, "script_time_end", osg::Timer::instance()->delta_s(mStartTick, afterScriptTick));
stats->setAttribute(frameNumber, "mechanics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeMechanicsTick));
stats->setAttribute(frameNumber, "mechanics_time_taken", osg::Timer::instance()->delta_s(beforeMechanicsTick, afterMechanicsTick));
stats->setAttribute(frameNumber, "mechanics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterMechanicsTick));
stats->setAttribute(frameNumber, "physics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforePhysicsTick));
stats->setAttribute(frameNumber, "physics_time_taken", osg::Timer::instance()->delta_s(beforePhysicsTick, afterPhysicsTick));
stats->setAttribute(frameNumber, "physics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterPhysicsTick));
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
std::cerr << "Error in framelistener: " << e.what() << std::endl; std::cerr << "Error in framelistener: " << e.what() << std::endl;
} }
return mSimulationTime;
return true;
} }
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
: mEncoding(ToUTF8::WINDOWS_1252) : mWindow(NULL)
, mEncoding(ToUTF8::WINDOWS_1252)
, mEncoder(NULL) , mEncoder(NULL)
, mOgre (0)
, mVerboseScripts (false) , mVerboseScripts (false)
, mSkipMenu (false) , mSkipMenu (false)
, mUseSound (true) , mUseSound (true)
@ -191,10 +205,10 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mFSStrict (false) , mFSStrict (false)
, mScriptBlacklistUse (true) , mScriptBlacklistUse (true)
, mNewGame (false) , mNewGame (false)
, mSimulationTime(0.0)
, mCfgMgr(configurationManager) , mCfgMgr(configurationManager)
{ {
OEngine::Misc::Rng::init(); Misc::Rng::init();
std::srand ( static_cast<unsigned int>(std::time(NULL)) );
MWClass::registerClasses(); MWClass::registerClasses();
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK; Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK;
@ -206,31 +220,28 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
throw std::runtime_error("Could not initialize SDL! " + std::string(SDL_GetError())); throw std::runtime_error("Could not initialize SDL! " + std::string(SDL_GetError()));
} }
} }
mStartTick = osg::Timer::instance()->tick();
} }
OMW::Engine::~Engine() OMW::Engine::~Engine()
{ {
if (mOgre)
mOgre->restoreWindowGammaRamp();
mEnvironment.cleanup(); mEnvironment.cleanup();
delete mScriptContext; delete mScriptContext;
delete mOgre; mScriptContext = NULL;
SDL_Quit();
}
// add resources directory mResourceSystem.reset();
// \note This function works recursively.
void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path) mViewer = NULL;
{
mOgre->getRoot()->addResourceLocation (path.string(), "FileSystem",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
}
void OMW::Engine::addZipResource (const boost::filesystem::path& path) if (mWindow)
{ {
mOgre->getRoot()->addResourceLocation (path.string(), "Zip", SDL_DestroyWindow(mWindow);
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false); mWindow = NULL;
}
SDL_Quit();
} }
void OMW::Engine::enableFSStrict(bool fsStrict) void OMW::Engine::enableFSStrict(bool fsStrict)
@ -299,71 +310,146 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
if (boost::filesystem::exists(settingspath)) if (boost::filesystem::exists(settingspath))
settings.loadUser(settingspath); settings.loadUser(settingspath);
// load nif overrides
NifOverrides::Overrides nifOverrides;
std::string transparencyOverrides = "/transparency-overrides.cfg";
std::string materialOverrides = "/material-overrides.cfg";
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + transparencyOverrides))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + transparencyOverrides);
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + transparencyOverrides))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + transparencyOverrides);
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + materialOverrides))
nifOverrides.loadMaterialOverrides(mCfgMgr.getLocalPath().string() + materialOverrides);
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + materialOverrides))
nifOverrides.loadMaterialOverrides(mCfgMgr.getGlobalPath().string() + materialOverrides);
return settingspath; return settingspath;
} }
void OMW::Engine::prepareEngine (Settings::Manager & settings) void OMW::Engine::createWindow(Settings::Manager& settings)
{ {
mEnvironment.setStateManager ( int screen = settings.getInt("screen", "Video");
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0))); int width = settings.getInt("resolution x", "Video");
int height = settings.getInt("resolution y", "Video");
bool fullscreen = settings.getBool("fullscreen", "Video");
bool windowBorder = settings.getBool("window border", "Video");
bool vsync = settings.getBool("vsync", "Video");
int antialiasing = settings.getInt("antialiasing", "Video");
std::string renderSystem = settings.getString("render system", "Video"); int pos_x = SDL_WINDOWPOS_CENTERED_DISPLAY(screen),
if (renderSystem == "") pos_y = SDL_WINDOWPOS_CENTERED_DISPLAY(screen);
if(fullscreen)
{ {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 pos_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(screen);
renderSystem = "Direct3D9 Rendering Subsystem"; pos_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(screen);
#else
renderSystem = "OpenGL Rendering Subsystem";
#endif
} }
mOgre = new OEngine::Render::OgreRenderer; Uint32 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE;
if(fullscreen)
flags |= SDL_WINDOW_FULLSCREEN;
if (!windowBorder)
flags |= SDL_WINDOW_BORDERLESS;
mOgre->configure( SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
mCfgMgr.getLogPath().string(), settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
renderSystem,
Settings::Manager::getString("opengl rtt mode", "Video")); if (antialiasing > 0)
{
if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) != 0)
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing) != 0)
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
}
while (!mWindow)
{
mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags);
if (!mWindow)
{
// Try with a lower AA
if (antialiasing > 0)
{
std::cout << "Note: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2 << std::endl;
antialiasing /= 2;
Settings::Manager::setInt("antialiasing", "Video", antialiasing);
if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing) != 0)
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
continue;
}
else
{
std::stringstream error;
error << "Failed to create SDL window: " << SDL_GetError() << std::endl;
throw std::runtime_error(error.str());
}
}
}
// This has to be added BEFORE MyGUI is initialized, as it needs setWindowIcon();
// to find core.xml here.
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
SDL_GetWindowPosition(mWindow, &traits->x, &traits->y);
SDL_GetWindowSize(mWindow, &traits->width, &traits->height);
traits->windowName = SDL_GetWindowTitle(mWindow);
traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS);
traits->screenNum = SDL_GetWindowDisplayIndex(mWindow);
// FIXME: Some way to get these settings back from the SDL window?
traits->red = 8;
traits->green = 8;
traits->blue = 8;
traits->alpha = 8;
traits->depth = 24;
traits->stencil = 8;
traits->vsync = vsync;
traits->doubleBuffer = true;
traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow);
osg::ref_ptr<SDLUtil::GraphicsWindowSDL2> graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits);
if(!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext");
osg::ref_ptr<osg::Camera> camera = mViewer->getCamera();
camera->setGraphicsContext(graphicsWindow);
camera->setViewport(0, 0, width, height);
mViewer->realize();
}
void OMW::Engine::setWindowIcon()
{
boost::filesystem::ifstream windowIconStream;
std::string windowIcon = (mResDir / "mygui" / "openmw.png").string();
windowIconStream.open(windowIcon);
if (windowIconStream.fail())
std::cerr << "Failed to open " << windowIcon << std::endl;
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
if (!reader)
{
std::cerr << "Failed to read window icon, no png readerwriter found" << std::endl;
return;
}
osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream);
if (!result.success())
std::cerr << "Failed to read " << windowIcon << ": " << result.message() << std::endl;
else
{
osg::ref_ptr<osg::Image> image = result.getImage();
SDL_Surface* surface = SDLUtil::imageToSurface(image, true);
SDL_SetWindowIcon(mWindow, surface);
SDL_FreeSurface(surface);
}
}
addResourcesDirectory(mCfgMgr.getCachePath ().string()); void OMW::Engine::prepareEngine (Settings::Manager & settings)
{
mEnvironment.setStateManager (
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0)));
addResourcesDirectory(mResDir / "mygui"); createWindow(settings);
addResourcesDirectory(mResDir / "water");
addResourcesDirectory(mResDir / "shadows");
addResourcesDirectory(mResDir / "materials");
OEngine::Render::WindowSettings windowSettings; osg::ref_ptr<osg::Group> rootNode (new osg::Group);
windowSettings.fullscreen = settings.getBool("fullscreen", "Video"); mViewer->setSceneData(rootNode);
windowSettings.window_border = settings.getBool("window border", "Video");
windowSettings.window_x = settings.getInt("resolution x", "Video");
windowSettings.window_y = settings.getInt("resolution y", "Video");
windowSettings.screen = settings.getInt("screen", "Video");
windowSettings.vsync = settings.getBool("vsync", "Video");
windowSettings.icon = "openmw.png";
std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, mVFS.reset(new VFS::Manager(mFSStrict));
settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
mOgre->createWindow("OpenMW", windowSettings); VFS::registerArchives(mVFS.get(), mFileCollections, mArchives, true);
Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict); mResourceSystem.reset(new Resource::ResourceSystem(mVFS.get()));
mResourceSystem->getTextureManager()->setUnRefImageDataAfterApply(true);
osg::Texture::FilterMode min = osg::Texture::LINEAR_MIPMAP_NEAREST;
osg::Texture::FilterMode mag = osg::Texture::LINEAR;
if (Settings::Manager::getString("texture filtering", "General") == "trilinear")
min = osg::Texture::LINEAR_MIPMAP_LINEAR;
int maxAnisotropy = Settings::Manager::getInt("anisotropy", "General");
mResourceSystem->getTextureManager()->setFilterSettings(min, mag, maxAnisotropy);
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // showing a loading screen and keeping the window responsive while doing so
@ -390,29 +476,32 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
else else
gameControllerdb = ""; //if it doesn't exist, pass in an empty string gameControllerdb = ""; //if it doesn't exist, pass in an empty string
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, gameControllerdb, mGrab); // FIXME: shouldn't depend on Engine
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, *this, keybinderUser, keybinderUserExists, gameControllerdb, mGrab);
mEnvironment.setInputManager (input); mEnvironment.setInputManager (input);
MWGui::WindowManager* window = new MWGui::WindowManager( std::string myguiResources = (mResDir / "mygui").string();
mExtensions, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap); guiRoot->setNodeMask(MWRender::Mask_GUI);
rootNode->addChild(guiRoot);
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(),
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap);
mEnvironment.setWindowManager (window); mEnvironment.setWindowManager (window);
// Create sound system // Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
mOgre->setWindowGammaContrast(Settings::Manager::getFloat("gamma", "General"), Settings::Manager::getFloat("contrast", "General"));
if (!mSkipMenu) if (!mSkipMenu)
{ {
std::string logo = mFallbackMap["Movies_Company_Logo"]; std::string logo = mFallbackMap["Movies_Company_Logo"];
if (!logo.empty()) if (!logo.empty())
window->playVideo(logo, 1); window->playVideo(logo, true);
} }
// Create the world // Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(),
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, mFileCollections, mContentFiles, mEncoder, mFallbackMap,
mActivationDistanceOverride, mCellName, mStartupScript)); mActivationDistanceOverride, mCellName, mStartupScript));
MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->setupPlayer();
input->setPlayer(&mEnvironment.getWorld()->getPlayer()); input->setPlayer(&mEnvironment.getWorld()->getPlayer());
@ -443,8 +532,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setJournal (new MWDialogue::Journal);
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
mOgre->getRoot()->addFrameListener (this);
// scripts // scripts
if (mCompileAll) if (mCompileAll)
{ {
@ -468,18 +555,83 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
} }
} }
class WriteScreenshotToFileOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation
{
public:
WriteScreenshotToFileOperation(const std::string& screenshotPath, const std::string& screenshotFormat)
: mScreenshotPath(screenshotPath)
, mScreenshotFormat(screenshotFormat)
{
}
virtual void operator()(const osg::Image& image, const unsigned int context_id)
{
// Count screenshots.
int shotCount = 0;
// Find the first unused filename with a do-while
std::ostringstream stream;
do
{
// Reset the stream
stream.str("");
stream.clear();
stream << mScreenshotPath << "/screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << "." << mScreenshotFormat;
} while (boost::filesystem::exists(stream.str()));
boost::filesystem::ofstream outStream;
outStream.open(boost::filesystem::path(stream.str()), std::ios::binary);
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension(mScreenshotFormat);
if (!readerwriter)
{
std::cerr << "Can't write screenshot, no '" << mScreenshotFormat << "' readerwriter found" << std::endl;
return;
}
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(image, outStream);
if (!result.success())
{
std::cerr << "Can't write screenshot: " << result.message() << std::endl;
}
}
private:
std::string mScreenshotPath;
std::string mScreenshotFormat;
};
// Initialise and enter main loop. // Initialise and enter main loop.
void OMW::Engine::go() void OMW::Engine::go()
{ {
assert (!mContentFiles.empty()); assert (!mContentFiles.empty());
assert (!mOgre);
mViewer = new osgViewer::Viewer;
osg::ref_ptr<osgViewer::StatsHandler> statshandler = new osgViewer::StatsHandler;
statshandler->setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3);
statshandler->addUserStatsLine("Script", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f),
"script_time_taken", 1000.0, true, false, "script_time_begin", "script_time_end", 10000);
statshandler->addUserStatsLine("Mechanics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f),
"mechanics_time_taken", 1000.0, true, false, "mechanics_time_begin", "mechanics_time_end", 10000);
statshandler->addUserStatsLine("Physics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f),
"physics_time_taken", 1000.0, true, false, "physics_time_begin", "physics_time_end", 10000);
mViewer->addEventHandler(statshandler);
Settings::Manager settings; Settings::Manager settings;
std::string settingspath; std::string settingspath;
settingspath = loadSettings (settings); settingspath = loadSettings (settings);
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
Settings::Manager::getString("screenshot format", "General")));
mViewer->addEventHandler(mScreenCaptureHandler);
// Create encoder // Create encoder
ToUTF8::Utf8Encoder encoder (mEncoding); ToUTF8::Utf8Encoder encoder (mEncoding);
mEncoder = &encoder; mEncoder = &encoder;
@ -514,15 +666,17 @@ void OMW::Engine::go()
} }
// Start the main rendering loop // Start the main rendering loop
Ogre::Timer timer; osg::Timer frameTimer;
while (!MWBase::Environment::get().getStateManager()->hasQuitRequest()) while (!mViewer->done() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
{ {
float dt = timer.getMilliseconds()/1000.f; double dt = frameTimer.time_s();
dt = std::min(dt, 0.2f); frameTimer.setStartTick();
dt = std::min(dt, 0.2);
timer.reset(); double simulationTime = frame(dt);
Ogre::Root::getSingleton().renderOneFrame(dt); mViewer->frame(simulationTime);
} }
// Save user settings // Save user settings
settings.saveUser(settingspath); settings.saveUser(settingspath);
@ -560,24 +714,8 @@ void OMW::Engine::activate()
void OMW::Engine::screenshot() void OMW::Engine::screenshot()
{ {
// Count screenshots. mScreenCaptureHandler->setFramesToCapture(1);
int shotCount = 0; mScreenCaptureHandler->captureNextFrame(*mViewer);
const std::string& screenshotPath = mCfgMgr.getUserDataPath().string();
std::string format = Settings::Manager::getString("screenshot format", "General");
// 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++ << "." << format;
} while (boost::filesystem::exists(stream.str()));
mOgre->screenshot(stream.str(), format);
} }
void OMW::Engine::setCompileAll (bool all) void OMW::Engine::setCompileAll (bool all)

@ -1,19 +1,28 @@
#ifndef ENGINE_H #ifndef ENGINE_H
#define ENGINE_H #define ENGINE_H
#include <OgreFrameListener.h>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
#include <components/files/collections.hpp> #include <components/files/collections.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/nifcache/nifcache.hpp>
#include <osgViewer/Viewer>
#include "mwbase/environment.hpp" #include "mwbase/environment.hpp"
#include "mwworld/ptr.hpp" #include "mwworld/ptr.hpp"
namespace Resource
{
class ResourceSystem;
}
namespace VFS
{
class Manager;
}
namespace Compiler namespace Compiler
{ {
class Context; class Context;
@ -39,36 +48,34 @@ namespace MWGui
class WindowManager; class WindowManager;
} }
namespace OEngine namespace Files
{ {
namespace GUI struct ConfigurationManager;
{
class MyGUIManager;
}
namespace Render
{
class OgreRenderer;
}
} }
namespace Files namespace osgViewer
{ {
struct ConfigurationManager; class ScreenCaptureHandler;
} }
struct SDL_Window;
namespace OMW namespace OMW
{ {
/// \brief Main engine class, that brings together all the components of OpenMW /// \brief Main engine class, that brings together all the components of OpenMW
class Engine : private Ogre::FrameListener class Engine
{ {
SDL_Window* mWindow;
std::auto_ptr<VFS::Manager> mVFS;
std::auto_ptr<Resource::ResourceSystem> mResourceSystem;
MWBase::Environment mEnvironment; MWBase::Environment mEnvironment;
ToUTF8::FromType mEncoding; ToUTF8::FromType mEncoding;
ToUTF8::Utf8Encoder* mEncoder; ToUTF8::Utf8Encoder* mEncoder;
Files::PathContainer mDataDirs; Files::PathContainer mDataDirs;
std::vector<std::string> mArchives; std::vector<std::string> mArchives;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer *mOgre; osg::ref_ptr<osgViewer::Viewer> mViewer;
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
std::string mCellName; std::string mCellName;
std::vector<std::string> mContentFiles; std::vector<std::string> mContentFiles;
bool mVerboseScripts; bool mVerboseScripts;
@ -98,23 +105,17 @@ namespace OMW
bool mScriptBlacklistUse; bool mScriptBlacklistUse;
bool mNewGame; bool mNewGame;
Nif::Cache mNifCache; osg::Timer_t mStartTick;
double mSimulationTime;
// not implemented // not implemented
Engine (const Engine&); Engine (const Engine&);
Engine& operator= (const Engine&); Engine& operator= (const Engine&);
/// add resources directory
/// \note This function works recursively.
void addResourcesDirectory (const boost::filesystem::path& path);
/// add a .zip resource
void addZipResource (const boost::filesystem::path& path);
void executeLocalScripts(); void executeLocalScripts();
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); /// @return The new simulationTime
virtual bool frameStarted (const Ogre::FrameEvent& evt); double frame (float dt);
/// Load settings from various files, returns the path to the user settings file /// Load settings from various files, returns the path to the user settings file
std::string loadSettings (Settings::Manager & settings); std::string loadSettings (Settings::Manager & settings);
@ -122,6 +123,9 @@ namespace OMW
/// Prepare engine for game play /// Prepare engine for game play
void prepareEngine (Settings::Manager & settings); void prepareEngine (Settings::Manager & settings);
void createWindow(Settings::Manager& settings);
void setWindowIcon();
public: public:
Engine(Files::ConfigurationManager& configurationManager); Engine(Files::ConfigurationManager& configurationManager);
virtual ~Engine(); virtual ~Engine();

@ -21,17 +21,18 @@
#endif #endif
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE #if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
#define USE_CRASH_CATCHER 1
#else
#define USE_CRASH_CATCHER 0
#endif
#if USE_CRASH_CATCHER
#include <csignal> #include <csignal>
extern int cc_install_handlers(int argc, char **argv, int num_signals, int *sigs, const char *logfile, int (*user_info)(char*, char*)); extern int cc_install_handlers(int argc, char **argv, int num_signals, int *sigs, const char *logfile, int (*user_info)(char*, char*));
extern int is_debugger_attached(void); extern int is_debugger_attached(void);
#endif #endif
// for Ogre::macBundlePath
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#include <OSX/macUtils.h>
#endif
#include <boost/version.hpp> #include <boost/version.hpp>
/** /**
* Workaround for problems with whitespaces in paths in older versions of Boost library * Workaround for problems with whitespaces in paths in older versions of Boost library
@ -362,7 +363,7 @@ int main(int argc, char**argv)
#endif #endif
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE #if USE_CRASH_CATCHER
// Unix crash catcher // Unix crash catcher
if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached()) if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached())
{ {
@ -374,10 +375,10 @@ int main(int argc, char**argv)
std::cout << "Running in a debugger, not installing crash catcher" << std::endl; std::cout << "Running in a debugger, not installing crash catcher" << std::endl;
#endif #endif
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE #ifdef __APPLE__
// set current dir to bundle path // FIXME: set current dir to bundle path
boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path(); //boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path();
boost::filesystem::current_path(bundlePath); //boost::filesystem::current_path(bundlePath);
#endif #endif
engine.reset(new OMW::Engine(cfgMgr)); engine.reset(new OMW::Engine(cfgMgr));
@ -389,7 +390,7 @@ int main(int argc, char**argv)
} }
catch (std::exception &e) catch (std::exception &e)
{ {
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE #if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
if (!isatty(fileno(stdin))) if (!isatty(fileno(stdin)))
#endif #endif
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL); SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);

@ -6,9 +6,9 @@
#include <list> #include <list>
#include <stdint.h> #include <stdint.h>
namespace Ogre namespace osg
{ {
class Vector3; class Vec3f;
} }
namespace ESM namespace ESM
@ -174,8 +174,8 @@ namespace MWBase
virtual bool toggleAI() = 0; virtual bool toggleAI() = 0;
virtual bool isAIActive() = 0; virtual bool isAIActive() = 0;
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0; virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects) = 0; virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects) = 0;
///return the list of actors which are following the given actor ///return the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor**/ /**ie AiFollow is active and the target is the actor**/

@ -7,11 +7,6 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
namespace Ogre
{
class Vector3;
}
namespace MWWorld namespace MWWorld
{ {
class CellStore; class CellStore;
@ -125,7 +120,7 @@ namespace MWBase
///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified.
///< @param offset Value from [0,1] meaning from which fraction the sound the playback starts. ///< @param offset Value from [0,1] meaning from which fraction the sound the playback starts.
virtual MWBase::SoundPtr playManualSound3D(const Ogre::Vector3& initialPos, const std::string& soundId, virtual MWBase::SoundPtr playManualSound3D(const osg::Vec3f& initialPos, const std::string& soundId,
float volume, float pitch, PlayType type, PlayMode mode, float offset=0) = 0; float volume, float pitch, PlayType type, PlayMode mode, float offset=0) = 0;
///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated manually using Sound::setPosition. ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated manually using Sound::setPosition.
@ -162,7 +157,7 @@ namespace MWBase
virtual void update(float duration) = 0; virtual void update(float duration) = 0;
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0; virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up) = 0;
virtual void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0; virtual void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0;

@ -26,14 +26,6 @@ namespace MyGUI
class UString; class UString;
} }
namespace OEngine
{
namespace GUI
{
class Layout;
}
}
namespace ESM namespace ESM
{ {
struct Class; struct Class;
@ -58,6 +50,8 @@ namespace MWWorld
namespace MWGui namespace MWGui
{ {
class Layout;
class Console; class Console;
class SpellWindow; class SpellWindow;
class TradeWindow; class TradeWindow;
@ -158,7 +152,7 @@ namespace MWBase
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0; virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0; virtual void wmUpdateFps(float fps) = 0;
/// Set value for the given ID. /// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
@ -184,12 +178,6 @@ namespace MWBase
virtual void changeCell(MWWorld::CellStore* cell) = 0; virtual void changeCell(MWWorld::CellStore* cell) = 0;
///< change the active cell ///< change the active cell
virtual void setPlayerPos(int cellX, int cellY, const float x, const float y) = 0;
///< set player position in map space
virtual void setPlayerDir(const float x, const float y) = 0;
///< set player view direction in map space
virtual void setFocusObject(const MWWorld::Ptr& focus) = 0; virtual void setFocusObject(const MWWorld::Ptr& focus) = 0;
virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0; virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0;
@ -241,7 +229,7 @@ namespace MWBase
virtual void addVisitedLocation(const std::string& name, int x, int y) = 0; virtual void addVisitedLocation(const std::string& name, int x, int y) = 0;
/// Hides dialog and schedules dialog to be deleted. /// Hides dialog and schedules dialog to be deleted.
virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0; virtual void removeDialog(MWGui::Layout* dialog) = 0;
///Gracefully attempts to exit the topmost GUI mode ///Gracefully attempts to exit the topmost GUI mode
/** No guarentee of actually closing the window **/ /** No guarentee of actually closing the window **/
@ -303,8 +291,6 @@ namespace MWBase
virtual void showSoulgemDialog (MWWorld::Ptr item) = 0; virtual void showSoulgemDialog (MWWorld::Ptr item) = 0;
virtual void frameStarted(float dt) = 0;
virtual void changePointer (const std::string& name) = 0; virtual void changePointer (const std::string& name) = 0;
virtual void setEnemy (const MWWorld::Ptr& enemy) = 0; virtual void setEnemy (const MWWorld::Ptr& enemy) = 0;
@ -361,6 +347,15 @@ namespace MWBase
virtual void cycleSpell(bool next) = 0; virtual void cycleSpell(bool next) = 0;
/// Cycle to next or previous weapon /// Cycle to next or previous weapon
virtual void cycleWeapon(bool next) = 0; virtual void cycleWeapon(bool next) = 0;
// In WindowManager for now since there isn't a VFS singleton
virtual std::string correctIconPath(const std::string& path) = 0;
virtual std::string correctBookartPath(const std::string& path, int width, int height) = 0;
virtual std::string correctTexturePath(const std::string& path) = 0;
virtual void requestMap(std::set<MWWorld::CellStore*> cells) = 0;
virtual void removeCell(MWWorld::CellStore* cell) = 0;
virtual void writeFog(MWWorld::CellStore* cell) = 0;
}; };
} }

@ -9,11 +9,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
namespace Ogre #include "../mwrender/rendermode.hpp"
namespace osg
{ {
class Vector2; class Vec3f;
class Vector3; class Quat;
class Quaternion;
class Image; class Image;
} }
@ -78,14 +79,6 @@ namespace MWBase
public: public:
enum RenderMode
{
Render_CollisionDebug,
Render_Wireframe,
Render_Pathgrid,
Render_BoundingBoxes
};
struct DoorMarker struct DoorMarker
{ {
std::string name; std::string name;
@ -125,8 +118,6 @@ namespace MWBase
virtual void adjustSky() = 0; virtual void adjustSky() = 0;
virtual void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) = 0;
virtual const MWWorld::Fallback *getFallback () const = 0; virtual const MWWorld::Fallback *getFallback () const = 0;
virtual MWWorld::Player& getPlayer() = 0; virtual MWWorld::Player& getPlayer() = 0;
@ -145,21 +136,12 @@ namespace MWBase
virtual bool isCellQuasiExterior() const = 0; virtual bool isCellQuasiExterior() const = 0;
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0; virtual osg::Vec2f getNorthVector (MWWorld::CellStore* cell) = 0;
///< get north vector for given interior cell ///< get north vector for given interior cell
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0; virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
///< get a list of teleport door markers for a given cell, to be displayed on the local map ///< get a list of teleport door markers for a given cell, to be displayed on the local map
virtual void worldToInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
///< see MWRender::LocalMap::worldToInteriorMapPosition
virtual Ogre::Vector2 interiorMapToWorldPosition (float nX, float nY, int x, int y) = 0;
///< see MWRender::LocalMap::interiorMapToWorldPosition
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0;
///< see MWRender::LocalMap::isPositionExplored
virtual void setGlobalInt (const std::string& name, int value) = 0; virtual void setGlobalInt (const std::string& name, int value) = 0;
///< Set value independently from real type. ///< Set value independently from real type.
@ -192,12 +174,6 @@ namespace MWBase
///< Return a pointer to a liveCellRef with the given name. ///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells. /// \param activeOnly do non search inactive cells.
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
///< Return a pointer to a liveCellRef with the given Ogre handle.
virtual MWWorld::Ptr searchPtrViaHandle (const std::string& handle) = 0;
///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
///< Search is limited to the active cells. ///< Search is limited to the active cells.
@ -271,7 +247,7 @@ namespace MWBase
/// Returns a pointer to the object the provided object would hit (if within the /// Returns a pointer to the object the provided object would hit (if within the
/// specified distance), and the point where the hit occurs. This will attempt to /// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis. /// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0; virtual std::pair<MWWorld::Ptr,osg::Vec3f> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
virtual void adjustPosition (const MWWorld::Ptr& ptr, bool force) = 0; virtual void adjustPosition (const MWWorld::Ptr& ptr, bool force) = 0;
///< Adjust position after load to be on ground. Must be called after model load. ///< Adjust position after load to be on ground. Must be called after model load.
@ -305,7 +281,7 @@ namespace MWBase
virtual void positionToIndex (float x, float y, int &cellX, int &cellY) const = 0; virtual void positionToIndex (float x, float y, int &cellX, int &cellY) const = 0;
///< Convert position to cell numbers ///< Convert position to cell numbers
virtual void queueMovement(const MWWorld::Ptr &ptr, const Ogre::Vector3 &velocity) = 0; virtual void queueMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity) = 0;
///< Queues movement for \a ptr (in local space), to be applied in the next call to ///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// doPhysics. /// doPhysics.
@ -317,7 +293,7 @@ namespace MWBase
/// collisions and gravity. /// collisions and gravity.
/// \return Resulting mode /// \return Resulting mode
virtual bool toggleRenderMode (RenderMode mode) = 0; virtual bool toggleRenderMode (MWRender::RenderMode mode) = 0;
///< Toggle a render mode. ///< Toggle a render mode.
///< \return Resulting mode ///< \return Resulting mode
@ -395,7 +371,7 @@ namespace MWBase
virtual bool isWading(const MWWorld::Ptr &object) const = 0; virtual bool isWading(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0; virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const = 0; virtual bool isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const = 0;
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0; virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
virtual void togglePOV() = 0; virtual void togglePOV() = 0;
@ -439,7 +415,7 @@ namespace MWBase
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0; virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0;
///< get Line of Sight (morrowind stupid implementation) ///< get Line of Sight (morrowind stupid implementation)
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0; virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist) = 0;
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0; virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
@ -455,8 +431,7 @@ namespace MWBase
virtual void reattachPlayerCamera() = 0; virtual void reattachPlayerCamera() = 0;
/// \todo this does not belong here /// \todo this does not belong here
virtual void frameStarted (float dt, bool paused) = 0; virtual void screenshot (osg::Image* image, int w, int h) = 0;
virtual void screenshot (Ogre::Image& image, int w, int h) = 0;
/// Find default position inside exterior cell specified by name /// Find default position inside exterior cell specified by name
/// \return false if exterior with given name not exists, true otherwise /// \return false if exterior with given name not exists, true otherwise
@ -503,9 +478,9 @@ namespace MWBase
virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId, virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId,
float speed, bool stack, const ESM::EffectList& effects, float speed, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection) = 0; const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0;
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) = 0; const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed) = 0;
virtual const std::vector<std::string>& getContentFiles() const = 0; virtual const std::vector<std::string>& getContentFiles() const = 0;
@ -514,7 +489,7 @@ namespace MWBase
// Are we in an exterior or pseudo-exterior cell and it's night? // Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const = 0; virtual bool isDark() const = 0;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0; virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker) /// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// @note id must be lower case /// @note id must be lower case
@ -546,11 +521,11 @@ namespace MWBase
virtual void spawnRandomCreature(const std::string& creatureList) = 0; virtual void spawnRandomCreature(const std::string& creatureList) = 0;
/// Spawn a blood effect for \a ptr at \a worldPosition /// Spawn a blood effect for \a ptr at \a worldPosition
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0; virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0; virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0;
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, virtual void explodeSpell (const osg::Vec3f& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0; const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
@ -559,7 +534,7 @@ namespace MWBase
virtual bool isInStorm() const = 0; virtual bool isInStorm() const = 0;
/// @see MWWorld::WeatherManager::getStormDirection /// @see MWWorld::WeatherManager::getStormDirection
virtual Ogre::Vector3 getStormDirection() const = 0; virtual osg::Vec3f getStormDirection() const = 0;
/// Resets all actors in the current active cells to their original location within that cell. /// Resets all actors in the current active cells to their original location within that cell.
virtual void resetActors() = 0; virtual void resetActors() = 0;

@ -11,12 +11,13 @@
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/action.hpp" #include "../mwworld/action.hpp"
#include "../mwworld/failedaction.hpp" #include "../mwworld/failedaction.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwrender/actors.hpp" #include "../mwphysics/physicssystem.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -34,12 +35,11 @@ namespace MWClass
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty()) {
MWRender::Actors& actors = renderingInterface.getActors(); renderingInterface.getObjects().insertModel(ptr, model, true);
actors.insertActivator(ptr, model);
} }
} }
void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
{ {
if(!model.empty()) if(!model.empty())
physics.addObject(ptr, model); physics.addObject(ptr, model);

@ -19,7 +19,7 @@ namespace MWClass
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering ///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);

@ -11,7 +11,7 @@
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/actionalchemy.hpp" #include "../mwworld/actionalchemy.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwphysics/physicssystem.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
@ -33,10 +33,9 @@ namespace MWClass
} }
} }
void Apparatus::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Apparatus::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
{ {
if(!model.empty()) // TODO: add option somewhere to enable collision for placeable objects
physics.addObject(ptr, model, true);
} }
std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const

@ -21,7 +21,7 @@ namespace MWClass
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering ///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);

@ -15,7 +15,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwphysics/physicssystem.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
@ -38,10 +38,9 @@ namespace MWClass
} }
} }
void Armor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Armor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const
{ {
if(!model.empty()) // TODO: add option somewhere to enable collision for placeable objects
physics.addObject(ptr, model, true);
} }
std::string Armor::getModel(const MWWorld::Ptr &ptr) const std::string Armor::getModel(const MWWorld::Ptr &ptr) const

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

Loading…
Cancel
Save