Merge branch 'master' into HEAD

Conflicts:
	CMakeLists.txt
	apps/launcher/CMakeLists.txt
loadfix
scrawl 10 years ago
commit 4fa303d7c4

3
.gitignore vendored

@ -37,11 +37,12 @@ resources
/omwlauncher
/openmw
/opencs
/niftest
## generated objects
apps/openmw/config.hpp
components/version/version.hpp
Docs/mainpage.hpp
docs/mainpage.hpp
moc_*.cxx
*.cxx_parameters
*qrc_launcher.cxx

@ -1,38 +1,25 @@
os:
- linux
- osx
language: cpp
compiler:
- gcc
branches:
only:
- master
- /openmw-.*$/
before_install:
- pwd
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
- echo "yes" | sudo apt-add-repository ppa:openmw/openmw
- sudo apt-get update -qq
- sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock
- sudo apt-get install -qq libqt4-dev
- sudo apt-get install -qq libopenal-dev
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
- sudo mkdir /usr/src/gtest/build
- cd /usr/src/gtest/build
- sudo cmake .. -DBUILD_SHARED_LIBS=1
- sudo make -j4
- sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
- sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_install.osx.sh; fi
before_script:
- cd -
- mkdir build
- cd build
- cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DBUILD_WITH_DPKG=1
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_script.linux.sh; fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script:
- cd ./build
- make -j4
after_script:
- ./openmw_test_suite
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
notifications:
recipients:
- lgromanowski+travis.ci@gmail.com
- corrmage+travis-ci@gmail.com
email:
on_success: change
on_failure: always

@ -0,0 +1,18 @@
#!/bin/sh
export CXX=g++
export CC=gcc
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
echo "yes" | sudo apt-add-repository ppa:openmw/openmw
sudo apt-get update -qq
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 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 mkdir /usr/src/gtest/build
cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1
sudo make -j4
sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so

@ -0,0 +1,9 @@
#!/bin/sh
export CXX=clang++
export CC=clang
brew tap openmw/openmw
brew update
brew unlink boost
brew install cmake openmw-mygui openmw-bullet openmw-sdl2 openmw-ffmpeg pkg-config qt unshield

@ -0,0 +1,5 @@
#!/bin/sh
mkdir build
cd build
cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE

@ -0,0 +1,5 @@
#!/bin/sh
mkdir build
cd build
cmake -DCMAKE_FRAMEWORK_PATH="/usr/local/lib/macosx/Release" -DCMAKE_EXE_LINKER_FLAGS="-F/usr/local/lib/macosx/Release" -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" -DCMAKE_BUILD_TYPE=Debug -DBUILD_MYGUI_PLUGIN=OFF -G"Unix Makefiles" ..

@ -12,8 +12,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 30)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_MINOR 33)
set(OPENMW_VERSION_RELEASE 1)
set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "")
@ -54,9 +54,13 @@ endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
# Macros
include(OpenMWMacros)
if (ANDROID)
set(CMAKE_FIND_ROOT_PATH ${OPENMW_DEPENDENCIES_DIR} "${CMAKE_FIND_ROOT_PATH}")
endif (ANDROID)
# doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp")
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)
@ -66,38 +70,30 @@ option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
# Apps and tools
option(BUILD_BSATOOL "build BSA extractor" OFF)
option(BUILD_BSATOOL "build BSA extractor" ON)
option(BUILD_ESMTOOL "build ESM inspector" ON)
option(BUILD_LAUNCHER "build Launcher" ON)
option(BUILD_MWINIIMPORTER "build MWiniImporter" ON)
option(BUILD_OPENCS "build OpenMW Construction Set" ON)
option(BUILD_WIZARD "build Installation Wizard" ON)
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF)
# Sound source selection
option(USE_FFMPEG "use ffmpeg for sound" ON)
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest and GMock frameworks" 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)
# OS X deployment
option(OPENMW_OSX_DEPLOYMENT OFF)
if(UNIX AND NOT APPLE)
option(BUILD_WITH_DPKG "enable dpkg-based install for debian and debian derivatives" OFF)
if(BUILD_WITH_DPKG)
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
endif(BUILD_WITH_DPKG)
endif(UNIX AND NOT APPLE)
# Location of morrowind data files
if (APPLE)
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
elseif(UNIX)
set(MORROWIND_DATA_FILES "/usr/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "/usr/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
set(MORROWIND_DATA_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
set(OPENMW_RESOURCE_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
else()
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
endif(APPLE)
if (WIN32)
@ -109,33 +105,32 @@ cmake_minimum_required(VERSION 2.6)
# source directory: libs
set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
set(LIBS_DIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/fader.cpp
${LIBDIR}/openengine/ogre/lights.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp
${LIBDIR}/openengine/ogre/imagerotate.cpp
${LIBS_DIR}/openengine/ogre/renderer.cpp
${LIBS_DIR}/openengine/ogre/lights.cpp
${LIBS_DIR}/openengine/ogre/selectionbuffer.cpp
${LIBS_DIR}/openengine/ogre/imagerotate.cpp
)
set(OENGINE_GUI
${LIBDIR}/openengine/gui/loglistener.cpp
${LIBDIR}/openengine/gui/manager.cpp
${LIBDIR}/openengine/gui/layout.hpp
${LIBS_DIR}/openengine/gui/loglistener.cpp
${LIBS_DIR}/openengine/gui/manager.cpp
${LIBS_DIR}/openengine/gui/layout.hpp
)
set(OENGINE_BULLET
${LIBDIR}/openengine/bullet/BtOgre.cpp
${LIBDIR}/openengine/bullet/BtOgreExtras.h
${LIBDIR}/openengine/bullet/BtOgreGP.h
${LIBDIR}/openengine/bullet/BtOgrePG.h
${LIBDIR}/openengine/bullet/physic.cpp
${LIBDIR}/openengine/bullet/physic.hpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.h
${LIBDIR}/openengine/bullet/trace.cpp
${LIBDIR}/openengine/bullet/trace.h
${LIBS_DIR}/openengine/bullet/BtOgre.cpp
${LIBS_DIR}/openengine/bullet/BtOgreExtras.h
${LIBS_DIR}/openengine/bullet/BtOgreGP.h
${LIBS_DIR}/openengine/bullet/BtOgrePG.h
${LIBS_DIR}/openengine/bullet/physic.cpp
${LIBS_DIR}/openengine/bullet/physic.hpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.h
${LIBS_DIR}/openengine/bullet/trace.cpp
${LIBS_DIR}/openengine/bullet/trace.h
)
@ -146,32 +141,24 @@ set(OPENMW_LIBS ${OENGINE_ALL})
set(OPENMW_LIBS_HEADER)
# Sound setup
set(GOT_SOUND_INPUT 0)
set(SOUND_INPUT_INCLUDES "")
set(SOUND_INPUT_LIBRARY "")
set(SOUND_DEFINE "")
if (USE_FFMPEG)
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
find_package(FFmpeg)
if (FFMPEG_FOUND)
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIRS})
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
set(GOT_SOUND_INPUT 1)
endif (FFMPEG_FOUND)
endif (USE_FFMPEG)
if (NOT GOT_SOUND_INPUT)
message(WARNING "--------------------")
message(WARNING "Failed to find any sound input packages")
message(WARNING "--------------------")
endif (NOT GOT_SOUND_INPUT)
if (NOT FFMPEG_FOUND)
message(WARNING "--------------------")
message(WARNING "FFmpeg not found, video playback will be disabled")
message(WARNING "--------------------")
endif (NOT FFMPEG_FOUND)
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
unset(FFMPEG_LIBRARIES CACHE)
find_package(FFmpeg)
if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND )
message(FATAL_ERROR "FFmpeg component required, but not found!")
endif()
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
if( SWRESAMPLE_FOUND )
add_definitions(-DHAVE_LIBSWRESAMPLE)
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
else()
if( AVRESAMPLE_FOUND )
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
else()
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
endif()
endif()
# TinyXML
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
@ -235,32 +222,74 @@ IF(BOOST_STATIC)
endif()
find_package(OGRE REQUIRED)
if (${OGRE_VERSION} VERSION_LESS "1.9")
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)
if (${MYGUI_VERSION} VERSION_LESS "3.2.1")
message(FATAL_ERROR "OpenMW requires MyGUI 3.2.1 or later, please install the latest version from http://mygui.info")
endif()
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(SDL2 REQUIRED)
find_package(OpenAL REQUIRED)
find_package(Bullet REQUIRED)
IF(OGRE_STATIC)
find_package(Cg)
IF(WIN32)
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
ELSE(WIN32)
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
ENDIF(WIN32)
ENDIF(OGRE_STATIC)
set(OGRE_PLUGIN_INCLUDE_DIRS "")
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("."
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS}
${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}
${Boost_INCLUDE_DIR}
${PLATFORM_INCLUDE_DIR}
${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR}
${LIBDIR}
${LIBS_DIR}
)
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
if(MYGUI_STATIC)
add_definitions(-DMYGUI_STATIC)
endif (MYGUI_STATIC)
if (APPLE)
# List used Ogre plugins
SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL}
@ -305,12 +334,14 @@ else ()
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
endif()
add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}")
add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}")
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 (NOT DEFINED ${OGRE_PLUGIN_DIR})
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
endif()
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
endif()
@ -322,8 +353,10 @@ add_subdirectory(files/mygui)
if (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
else (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
endif (APPLE)
# Other files
@ -357,9 +390,6 @@ endif()
if (CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
# Silence warnings in OGRE headers. Remove once OGRE got fixed!
SET(CMAKE_CXX_FLAGS "-Wno-ignored-qualifiers ${CMAKE_CXX_FLAGS}")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
@ -368,23 +398,21 @@ if (CMAKE_COMPILER_IS_GNUCC)
endif (CMAKE_COMPILER_IS_GNUCC)
IF(NOT WIN32 AND NOT APPLE)
## Debian and non debian Linux building
# Linux building
# Paths
IF (DPKG_PROGRAM)
## Debian specific
SET(CMAKE_INSTALL_PREFIX "/usr")
SET(DATAROOTDIR "share" CACHE PATH "Sets the root of data directories to a non-default location")
SET(DATADIR "share/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
SET(ICONDIR "share/pixmaps" CACHE PATH "Set icon dir")
SET(SYSCONFDIR "../etc/openmw" CACHE PATH "Set config dir")
ELSE ()
## Non debian specific
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Where to install libraries")
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir")
IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr")
SET(GLOBAL_CONFIG_PATH "/etc/" CACHE PATH "Set config dir prefix")
ELSE()
SET(GLOBAL_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/etc/" CACHE PATH "Set config dir prefix")
ENDIF()
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
# Install binaries
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
@ -403,15 +431,19 @@ IF(NOT WIN32 AND NOT APPLE)
IF(BUILD_OPENCS)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
ENDIF(BUILD_OPENCS)
IF(BUILD_NIFTEST)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
ENDIF(BUILD_NIFTEST)
IF(BUILD_WIZARD)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/wizard" DESTINATION "${BINDIR}" )
ENDIF(BUILD_WIZARD)
if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" )
ENDIF(BUILD_MYGUI_PLUGIN)
# Install licenses
INSTALL(FILES "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" )
ENDIF (DPKG_PROGRAM)
# Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
@ -440,8 +472,8 @@ if(WIN32)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
INSTALL(FILES
"${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
"${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt"
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
@ -460,7 +492,9 @@ if(WIN32)
IF(BUILD_WIZARD)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-wizard.exe" DESTINATION ".")
ENDIF(BUILD_WIZARD)
if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION ".")
ENDIF(BUILD_MYGUI_PLUGIN)
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
@ -493,8 +527,8 @@ if(WIN32)
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp")
SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe")
@ -525,12 +559,23 @@ endif(WIN32)
# Extern
add_subdirectory (extern/shiny)
add_subdirectory (extern/ogre-ffmpeg-videoplayer)
add_subdirectory (extern/oics)
add_subdirectory (extern/sdl4ogre)
# Components
add_subdirectory (components)
# Plugins
if (BUILD_MYGUI_PLUGIN)
add_subdirectory(plugins/mygui_resource_plugin)
endif()
#Testing
if (BUILD_NIFTEST)
add_subdirectory(components/nif/tests/)
endif(BUILD_NIFTEST)
# Apps and tools
add_subdirectory( apps/openmw )
@ -570,6 +615,16 @@ endif()
if (WIN32)
if (MSVC)
if (MULTITHREADED_BUILD)
set( MT_BUILD "/MP")
endif (MULTITHREADED_BUILD)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)" )
endforeach( OUTPUTCONFIG )
if (USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
@ -610,14 +665,19 @@ if (WIN32)
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'
# caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
# OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type
4100 # Unreferenced formal parameter (-Wunused-parameter)
4127 # Conditional expression is constant
4242 # Storing value in a variable of a smaller type, possible loss of data
4244 # Storing value of one type in variable of another (size_t in int, for example)
4267 # Conversion from 'size_t' to 'int', possible loss of data
4305 # Truncating value (double to float, for example)
4309 # Variable overflow, trying to store 128 in a signed char for example
4351 # New behavior: elements of array 'array' will be default initialized (desired behavior)
4355 # Using 'this' in member initialization list
4505 # Unreferenced local function has been removed
4701 # Potentially uninitialized local variable used
@ -631,31 +691,35 @@ if (WIN32)
# 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})
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
# there's an unreferenced local variable in the ogre platform, suppress it
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS})
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${SHINY_OGRE_WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_BSATOOL)
if (BUILD_ESMTOOL)
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_ESMTOOL)
if (BUILD_WIZARD)
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_WIZARD)
if (BUILD_OPENCS)
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${WARNINGS})
# QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS)
if (BUILD_MWINIIMPORTER)
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC)
@ -789,3 +853,26 @@ if (APPLE)
include(CPack)
endif (APPLE)
# Doxygen Target -- simply run 'make doc' or 'make doc_pages'
# output directory for 'make doc' is "${OpenMW_BINARY_DIR}/docs/Doxygen"
# output directory for 'make doc_pages' is "${DOXYGEN_PAGES_OUTPUT_DIR}" if defined
# or "${OpenMW_BINARY_DIR}/docs/Pages" otherwise
find_package(Doxygen)
if (DOXYGEN_FOUND)
# determine output directory for doc_pages
if (NOT DEFINED DOXYGEN_PAGES_OUTPUT_DIR)
set(DOXYGEN_PAGES_OUTPUT_DIR "${OpenMW_BINARY_DIR}/docs/Pages")
endif ()
configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.cmake ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY)
configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.cmake ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/Doxyfile
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
COMMENT "Generating Doxygen documentation at ${OpenMW_BINARY_DIR}/docs/Doxygen"
VERBATIM)
add_custom_target(doc_pages
${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/DoxyfilePages
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
endif ()

File diff suppressed because it is too large Load Diff

@ -51,7 +51,7 @@ bool parseOptions (int argc, char** argv, Arguments &info)
("help,h", "print help message.")
("version,v", "print version information and quit.")
("long,l", "Include extra information in archive listing.")
("full-path,f", "Create diretory hierarchy on file extraction "
("full-path,f", "Create directory hierarchy on file extraction "
"(always true for extractall).")
;

@ -249,6 +249,9 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n";
std::cout << " Owner: '" << ref.mOwner << "'\n";
std::cout << " Global: '" << ref.mGlobalVariable << "'" << std::endl;
std::cout << " Faction: '" << ref.mFaction << "'" << std::endl;
std::cout << " Faction rank: '" << ref.mFactionRank << "'" << std::endl;
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";

@ -18,6 +18,8 @@
std::string bodyPartLabel(int idx)
{
if (idx >= 0 && idx <= 26)
{
const char *bodyPartLabels[] = {
"Head",
"Hair",
@ -47,15 +49,16 @@ std::string bodyPartLabel(int idx)
"Weapon",
"Tail"
};
if (idx >= 0 && idx <= 26)
return bodyPartLabels[idx];
}
else
return "Invalid";
}
std::string meshPartLabel(int idx)
{
if (idx >= 0 && idx <= ESM::BodyPart::MP_Tail)
{
const char *meshPartLabels[] = {
"Head",
"Hair",
@ -73,29 +76,31 @@ std::string meshPartLabel(int idx)
"Clavicle",
"Tail"
};
if (idx >= 0 && idx <= ESM::BodyPart::MP_Tail)
return meshPartLabels[idx];
}
else
return "Invalid";
}
std::string meshTypeLabel(int idx)
{
if (idx >= 0 && idx <= ESM::BodyPart::MT_Armor)
{
const char *meshTypeLabels[] = {
"Skin",
"Clothing",
"Armor"
};
if (idx >= 0 && idx <= ESM::BodyPart::MT_Armor)
return meshTypeLabels[idx];
}
else
return "Invalid";
}
std::string clothingTypeLabel(int idx)
{
if (idx >= 0 && idx <= 9)
{
const char *clothingTypeLabels[] = {
"Pants",
"Shoes",
@ -108,15 +113,16 @@ std::string clothingTypeLabel(int idx)
"Ring",
"Amulet"
};
if (idx >= 0 && idx <= 9)
return clothingTypeLabels[idx];
}
else
return "Invalid";
}
std::string armorTypeLabel(int idx)
{
if (idx >= 0 && idx <= 10)
{
const char *armorTypeLabels[] = {
"Helmet",
"Cuirass",
@ -130,15 +136,16 @@ std::string armorTypeLabel(int idx)
"Left Bracer",
"Right Bracer"
};
if (idx >= 0 && idx <= 10)
return armorTypeLabels[idx];
}
else
return "Invalid";
}
std::string dialogTypeLabel(int idx)
{
if (idx >= 0 && idx <= 4)
{
const char *dialogTypeLabels[] = {
"Topic",
"Voice",
@ -146,9 +153,8 @@ std::string dialogTypeLabel(int idx)
"Persuasion",
"Journal"
};
if (idx >= 0 && idx <= 4)
return dialogTypeLabels[idx];
}
else if (idx == -1)
return "Deleted";
else
@ -157,6 +163,8 @@ std::string dialogTypeLabel(int idx)
std::string questStatusLabel(int idx)
{
if (idx >= 0 && idx <= 4)
{
const char *questStatusLabels[] = {
"None",
"Name",
@ -164,30 +172,32 @@ std::string questStatusLabel(int idx)
"Restart",
"Deleted"
};
if (idx >= 0 && idx <= 4)
return questStatusLabels[idx];
}
else
return "Invalid";
}
std::string creatureTypeLabel(int idx)
{
if (idx >= 0 && idx <= 3)
{
const char *creatureTypeLabels[] = {
"Creature",
"Daedra",
"Undead",
"Humanoid",
};
if (idx >= 0 && idx <= 3)
return creatureTypeLabels[idx];
}
else
return "Invalid";
}
std::string soundTypeLabel(int idx)
{
if (idx >= 0 && idx <= 7)
{
const char *soundTypeLabels[] = {
"Left Foot",
"Right Foot",
@ -198,15 +208,16 @@ std::string soundTypeLabel(int idx)
"Scream",
"Land"
};
if (idx >= 0 && idx <= 7)
return soundTypeLabels[idx];
}
else
return "Invalid";
}
std::string weaponTypeLabel(int idx)
{
if (idx >= 0 && idx <= 13)
{
const char *weaponTypeLabels[] = {
"Short Blade One Hand",
"Long Blade One Hand",
@ -223,9 +234,8 @@ std::string weaponTypeLabel(int idx)
"Arrow",
"Bolt"
};
if (idx >= 0 && idx <= 13)
return weaponTypeLabels[idx];
}
else
return "Invalid";
}
@ -242,6 +252,8 @@ std::string aiTypeLabel(int type)
std::string magicEffectLabel(int idx)
{
if (idx >= 0 && idx <= 142)
{
const char* magicEffectLabels [] = {
"Water Breathing",
"Swift Swim",
@ -387,14 +399,16 @@ std::string magicEffectLabel(int idx)
"sEffectSummonCreature04",
"sEffectSummonCreature05"
};
if (idx >= 0 && idx <= 142)
return magicEffectLabels[idx];
}
else
return "Invalid";
}
std::string attributeLabel(int idx)
{
if (idx >= 0 && idx <= 7)
{
const char* attributeLabels [] = {
"Strength",
"Intelligence",
@ -405,14 +419,16 @@ std::string attributeLabel(int idx)
"Personality",
"Luck"
};
if (idx >= 0 && idx <= 7)
return attributeLabels[idx];
}
else
return "Invalid";
}
std::string spellTypeLabel(int idx)
{
if (idx >= 0 && idx <= 5)
{
const char* spellTypeLabels [] = {
"Spells",
"Abilities",
@ -421,27 +437,31 @@ std::string spellTypeLabel(int idx)
"Curse",
"Powers"
};
if (idx >= 0 && idx <= 5)
return spellTypeLabels[idx];
}
else
return "Invalid";
}
std::string specializationLabel(int idx)
{
if (idx >= 0 && idx <= 2)
{
const char* specializationLabels [] = {
"Combat",
"Magic",
"Stealth"
};
if (idx >= 0 && idx <= 2)
return specializationLabels[idx];
}
else
return "Invalid";
}
std::string skillLabel(int idx)
{
if (idx >= 0 && idx <= 26)
{
const char* skillLabels [] = {
"Block",
"Armorer",
@ -471,41 +491,47 @@ std::string skillLabel(int idx)
"Speechcraft",
"Hand-to-hand"
};
if (idx >= 0 && idx <= 26)
return skillLabels[idx];
}
else
return "Invalid";
}
std::string apparatusTypeLabel(int idx)
{
if (idx >= 0 && idx <= 3)
{
const char* apparatusTypeLabels [] = {
"Mortar",
"Alembic",
"Calcinator",
"Retort",
};
if (idx >= 0 && idx <= 3)
return apparatusTypeLabels[idx];
}
else
return "Invalid";
}
std::string rangeTypeLabel(int idx)
{
if (idx >= 0 && idx <= 2)
{
const char* rangeTypeLabels [] = {
"Self",
"Touch",
"Target"
};
if (idx >= 0 && idx <= 2)
return rangeTypeLabels[idx];
}
else
return "Invalid";
}
std::string schoolLabel(int idx)
{
if (idx >= 0 && idx <= 5)
{
const char* schoolLabels [] = {
"Alteration",
"Conjuration",
@ -514,28 +540,32 @@ std::string schoolLabel(int idx)
"Mysticism",
"Restoration"
};
if (idx >= 0 && idx <= 5)
return schoolLabels[idx];
}
else
return "Invalid";
}
std::string enchantTypeLabel(int idx)
{
if (idx >= 0 && idx <= 3)
{
const char* enchantTypeLabels [] = {
"Cast Once",
"Cast When Strikes",
"Cast When Used",
"Constant Effect"
};
if (idx >= 0 && idx <= 3)
return enchantTypeLabels[idx];
}
else
return "Invalid";
}
std::string ruleFunction(int idx)
{
if (idx >= 0 && idx <= 72)
{
std::string ruleFunctions[] = {
"Reaction Low",
"Reaction High",
@ -611,8 +641,8 @@ std::string ruleFunction(int idx)
"Should Attack",
"Werewolf"
};
if (idx >= 0 && idx <= 72)
return ruleFunctions[idx];
}
else
return "Invalid";
}
@ -787,6 +817,10 @@ std::string magicEffectFlags(int flags)
if (flags & ESM::MagicEffect::NonRecastable) properties += "NonRecastable ";
if (flags & ESM::MagicEffect::Unreflectable) properties += "Unreflectable ";
if (flags & ESM::MagicEffect::CasterLinked) properties += "CasterLinked ";
if (flags & ESM::MagicEffect::AllowSpellmaking) properties += "AllowSpellmaking ";
if (flags & ESM::MagicEffect::AllowEnchanting) properties += "AllowEnchanting ";
if (flags & ESM::MagicEffect::NegativeLight) properties += "NegativeLight ";
if (flags & 0xFFFC0000) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;

@ -412,7 +412,7 @@ void Record<ESM::Armor>::print()
std::cout << " Armor: " << mData.mData.mArmor << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++)
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
@ -484,7 +484,7 @@ void Record<ESM::BirthSign>::print()
std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl;
std::vector<std::string>::iterator pit;
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); pit++)
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
std::cout << " Power: " << *pit << std::endl;
}
@ -513,7 +513,7 @@ void Record<ESM::Cell>::print()
else
std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl;
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
std::cout << " NAM0: " << mData.mNAM0 << std::endl;
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
}
@ -554,7 +554,7 @@ void Record<ESM::Clothing>::print()
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++)
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
@ -574,7 +574,7 @@ void Record<ESM::Container>::print()
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
}
@ -619,12 +619,12 @@ void Record<ESM::Creature>::print()
std::cout << " Gold: " << mData.mData.mGold << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++)
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
@ -639,7 +639,7 @@ void Record<ESM::Creature>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++)
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
}
@ -682,13 +682,11 @@ void Record<ESM::Faction>::print()
{
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl;
if (mData.mData.mUnknown != -1)
std::cout << " Unknown: " << mData.mData.mUnknown << std::endl;
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
for (int i = 0; i != 6; i++)
for (int i = 0; i < 7; i++)
if (mData.mData.mSkills[i] != -1)
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
@ -708,7 +706,7 @@ void Record<ESM::Faction>::print()
<< mData.mData.mRankData[i].mFactReaction << std::endl;
}
std::map<std::string, int>::iterator rit;
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++)
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); ++rit)
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
}
@ -765,7 +763,7 @@ void Record<ESM::DialInfo>::print()
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++)
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); ++sit)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
if (mData.mResultScript != "")
@ -837,7 +835,7 @@ void Record<ESM::CreatureLevList>::print()
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Creature: Level: " << iit->mLevel
<< " Creature: " << iit->mId << std::endl;
}
@ -849,7 +847,7 @@ void Record<ESM::ItemLevList>::print()
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl;
}
@ -952,9 +950,9 @@ void Record<ESM::MagicEffect>::print()
std::cout << " School: " << schoolLabel(mData.mData.mSchool)
<< " (" << mData.mData.mSchool << ")" << std::endl;
std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl;
std::cout << " Unknown 1: " << mData.mData.mUnknown1 << std::endl;
std::cout << " Speed: " << mData.mData.mSpeed << std::endl;
std::cout << " Size: " << mData.mData.mSize << std::endl;
std::cout << " Size Cap: " << mData.mData.mSizeCap << std::endl;
std::cout << " Unknown 2: " << mData.mData.mUnknown2 << std::endl;
std::cout << " RGB Color: " << "("
<< mData.mData.mRed << ","
<< mData.mData.mGreen << ","
@ -994,7 +992,6 @@ void Record<ESM::NPC>::print()
std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl;
std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl;
std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl;
std::cout << " Faction: " << (int)mData.mNpdt52.mFactionID << std::endl;
std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl;
std::cout << " Unknown1: "
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl;
@ -1009,6 +1006,7 @@ void Record<ESM::NPC>::print()
std::cout << " Reputation: " << (int)mData.mNpdt52.mReputation << std::endl;
std::cout << " Disposition: " << (int)mData.mNpdt52.mDisposition << std::endl;
std::cout << " Rank: " << (int)mData.mNpdt52.mRank << std::endl;
std::cout << " FactionID: " << (int)mData.mNpdt52.mFactionID << std::endl;
std::cout << " Attributes:" << std::endl;
std::cout << " Strength: " << (int)mData.mNpdt52.mStrength << std::endl;
@ -1033,16 +1031,16 @@ void Record<ESM::NPC>::print()
}
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++)
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit;
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); dit++)
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
@ -1068,7 +1066,7 @@ void Record<ESM::NPC>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++)
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
}
@ -1142,7 +1140,7 @@ void Record<ESM::Race>::print()
<< mData.mData.mBonus[i].mBonus << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); sit++)
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
std::cout << " Power: " << *sit << std::endl;
}
@ -1166,7 +1164,7 @@ void Record<ESM::Region>::print()
if (mData.mSleepList != "")
std::cout << " Sleep List: " << mData.mSleepList << std::endl;
std::vector<ESM::Region::SoundRef>::iterator sit;
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); sit++)
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); ++sit)
std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl;
}
@ -1183,12 +1181,12 @@ void Record<ESM::Script>::print()
std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++)
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); ++vit)
std::cout << " Variable: " << *vit << std::endl;
std::cout << " ByteCode: ";
std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++)
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); ++cit)
std::cout << boost::format("%02X") % (int)(*cit);
std::cout << std::endl;

@ -13,7 +13,7 @@ set(LAUNCHER
utils/textinputdialog.cpp
utils/lineedit.cpp
${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc
${CMAKE_SOURCE_DIR}/files/windows/launcher.rc
)
set(LAUNCHER_HEADER
@ -74,19 +74,10 @@ QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
include(${QT_USE_FILE})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(NOT WIN32)
include_directories(${LIBUNSHIELD_INCLUDE})
include_directories(${LIBUNSHIELD_INCLUDE_DIR})
endif(NOT WIN32)
# Main executable
IF(OGRE_STATIC)
IF(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
ELSE(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_GL_LIBRARIES})
ENDIF(WIN32)
ENDIF(OGRE_STATIC)
add_executable(omwlauncher
${GUI_TYPE}
${LAUNCHER}
@ -100,16 +91,13 @@ target_link_libraries(omwlauncher
${Boost_LIBRARIES}
${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SDL2_LIBRARY}
${SDL2_LIBRARY_ONLY}
${QT_LIBRARIES}
components
)
if(DPKG_PROGRAM)
INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher)
endif()
if(BUILD_WITH_CODE_COVERAGE)
if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(omwlauncher gcov)
endif()

@ -33,7 +33,11 @@ QString getAspect(int x, int y)
}
Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
: mCfgMgr(cfg)
: mOgre(NULL)
, mSelectedRenderSystem(NULL)
, mOpenGLRenderSystem(NULL)
, mDirect3DRenderSystem(NULL)
, mCfgMgr(cfg)
, mGraphicsSettings(graphicsSetting)
, QWidget(parent)
{

@ -22,8 +22,3 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(mwiniimport gcov)
endif()
if(DPKG_PROGRAM)
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
endif()

@ -15,6 +15,7 @@ namespace bfs = boost::filesystem;
MwIniImporter::MwIniImporter()
: mVerbose(false)
, mEncoding(ToUTF8::WINDOWS_1250)
{
const char *map[][2] =
{
@ -709,8 +710,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
continue;
}
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
if(map.find(key) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);
@ -746,8 +746,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam
std::string key(line.substr(0,pos));
std::string value(line.substr(pos+1));
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
if(map.find(key) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);

@ -37,6 +37,8 @@ public:
char **get() const { return const_cast<char **>(argv); }
private:
utf8argv(const utf8argv&);
utf8argv& operator=(const utf8argv&);
const char **argv;
std::vector<std::string> args;

@ -1,15 +1,17 @@
set (OPENCS_SRC main.cpp)
set (OPENCS_SRC main.cpp
${CMAKE_SOURCE_DIR}/files/windows/opencs.rc
)
opencs_units (. editor)
set (CMAKE_BUILD_TYPE DEBUG)
opencs_units (model/doc
document operation saving documentmanager loader
document operation saving documentmanager loader runner
)
opencs_units_noqt (model/doc
stage savingstate savingstages
stage savingstate savingstages blacklist
)
opencs_hdrs_noqt (model/doc
@ -18,17 +20,18 @@ opencs_hdrs_noqt (model/doc
opencs_units (model/world
idtable idtableproxymodel regionmap data
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable
)
opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land
)
opencs_hdrs_noqt (model/world
columnimp idcollection collection info
columnimp idcollection collection info subcellcollection
)
@ -38,13 +41,13 @@ opencs_units (model/tools
opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referenceablecheck scriptcheck
birthsigncheck spellcheck referenceablecheck scriptcheck bodypartcheck
)
opencs_units (view/doc
viewmanager view operations operation subview startup filedialog newgame
filewidget adjusterwidget loader
filewidget adjusterwidget loader globaldebugprofilemenu runlogsubview
)
@ -59,23 +62,31 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
cellcreator referenceablecreator referencecreator scenesubview
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
)
opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator physicssystem physicsmanager
)
opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
)
opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget
previewwidget editmode
)
opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
lightingbright
lightingbright object cell terrainstorage textoverlay overlaymask overlaysystem mousestate
)
opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator
opencs_hdrs_noqt (view/render
elements
)
@ -118,12 +129,8 @@ opencs_units_noqt (model/filter
node unarynode narynode leafnode booleannode parser andnode ornode notnode textnode valuenode
)
opencs_hdrs_noqt (model/filter
filter
)
opencs_units (view/filter
filtercreator filterbox recordfilterbox editwidget
filterbox recordfilterbox editwidget
)
set (OPENCS_US
@ -158,7 +165,7 @@ qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${BULLET_INCLUDE_DIRS})
if(APPLE)
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/opencs.icns)
@ -168,6 +175,7 @@ endif(APPLE)
add_executable(opencs
MACOSX_BUNDLE
${OENGINE_BULLET}
${OPENCS_SRC}
${OPENCS_UI_HDR}
${OPENCS_MOC_SRC}
@ -192,16 +200,15 @@ endif(APPLE)
target_link_libraries(opencs
${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SHINY_LIBRARIES}
${Boost_LIBRARIES}
${BULLET_LIBRARIES}
${QT_LIBRARIES}
components
)
if(DPKG_PROGRAM)
INSTALL(TARGETS opencs RUNTIME DESTINATION games COMPONENT opencs)
endif()
if(APPLE)
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
endif()

@ -20,8 +20,9 @@
#include "model/world/data.hpp"
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
mIpcServerName ("org.openmw.OpenCS")
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr),
mViewManager (mDocumentManager), mPhysicsManager (0),
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
{
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
@ -32,9 +33,14 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
mOverlaySystem.reset (new CSVRender::OverlaySystem);
mPhysicsManager.reset (new CSVWorld::PhysicsManager);
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
mFsStrict);
mDocumentManager.listResources();
mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal);
@ -63,6 +69,9 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
this, SLOT (createNewGame (const boost::filesystem::path&)));
}
CS::Editor::~Editor ()
{}
void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
{
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
@ -78,13 +87,17 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()->composing())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
("resources", boost::program_options::value<std::string>()->default_value("resources"))
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
default_value(std::vector<std::string>(), "fallback-archive")->multitoken());
default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
("script-blacklist", boost::program_options::value<std::vector<std::string> >()->default_value(std::vector<std::string>(), "")
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)")
("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
->default_value(true), "enable script blacklisting");
boost::program_options::notify(variables);
@ -95,6 +108,10 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
if (variables["script-blacklist-use"].as<bool>())
mDocumentManager.setBlacklistedScripts (
variables["script-blacklist"].as<std::vector<std::string> >());
mFsStrict = variables["fs-strict"].as<bool>();
Files::PathContainer dataDirs, dataLocal;
@ -179,7 +196,7 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
files.push_back(path.toUtf8().constData());
}
files.push_back(mFileDialog.filename().toUtf8().constData());
files.push_back (savePath);
mDocumentManager.addDocument (files, savePath, true);
@ -249,26 +266,49 @@ int CS::Editor::run()
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
// TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
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", ""));
params.insert(std::make_pair("FSAA", "0"));
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());
@ -276,7 +316,28 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable
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);
@ -284,16 +345,27 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
factory->loadAllFiles();
sh::Factory::getInstance().setGlobalSetting ("fog", "true");
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);
sh::Factory::getInstance().setGlobalSetting ("shadows", "false");
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false");
std::string shadows_pssm = mUserSettings.setting("Shader/shadows_pssm", QString("false")).toStdString();
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", shadows_pssm);
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false");
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");
sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8");
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

@ -16,6 +16,8 @@
#include <components/files/multidircollection.hpp>
#include <components/nifcache/nifcache.hpp>
#include "model/settings/usersettings.hpp"
#include "model/doc/documentmanager.hpp"
@ -25,6 +27,8 @@
#include "view/doc/newgame.hpp"
#include "view/settings/dialog.hpp"
#include "view/render/overlaysystem.hpp"
#include "view/world/physicsmanager.hpp"
namespace OgreInit
{
@ -37,8 +41,11 @@ namespace CS
{
Q_OBJECT
Nif::Cache mNifCache;
Files::ConfigurationManager mCfgMgr;
CSMSettings::UserSettings mUserSettings;
std::auto_ptr<CSVRender::OverlaySystem> mOverlaySystem;
std::auto_ptr<CSVWorld::PhysicsManager> mPhysicsManager;
CSMDoc::DocumentManager mDocumentManager;
CSVDoc::ViewManager mViewManager;
CSVDoc::StartupDialogue mStartup;
@ -61,6 +68,7 @@ namespace CS
public:
Editor (OgreInit::OgreInit& ogreInit);
~Editor ();
bool makeIPCServer();
void connectToIPCServer();

@ -0,0 +1,31 @@
#include "blacklist.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
bool CSMDoc::Blacklist::isBlacklisted (const CSMWorld::UniversalId& id) const
{
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> >::const_iterator iter =
mIds.find (id.getType());
if (iter==mIds.end())
return false;
return std::binary_search (iter->second.begin(), iter->second.end(),
Misc::StringUtils::lowerCase (id.getId()));
}
void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
const std::vector<std::string>& ids)
{
std::vector<std::string>& list = mIds[type];
int size = list.size();
list.resize (size+ids.size());
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
std::sort (list.begin(), list.end());
}

@ -0,0 +1,25 @@
#ifndef CSM_DOC_BLACKLIST_H
#define CSM_DOC_BLACKLIST_H
#include <map>
#include <vector>
#include <string>
#include "../world/universalid.hpp"
namespace CSMDoc
{
/// \brief ID blacklist sorted by UniversalId type
class Blacklist
{
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> > mIds;
public:
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
void add (CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
};
}
#endif

@ -1,6 +1,7 @@
#include "document.hpp"
#include <cassert>
#include <fstream>
#include <boost/filesystem.hpp>
@ -2022,6 +2023,7 @@ void CSMDoc::Document::addOptionalGmsts()
{
ESM::GameSetting gmst;
gmst.mId = sFloats[i];
gmst.blank();
gmst.mValue.setType (ESM::VT_Float);
addOptionalGmst (gmst);
}
@ -2030,6 +2032,7 @@ void CSMDoc::Document::addOptionalGmsts()
{
ESM::GameSetting gmst;
gmst.mId = sIntegers[i];
gmst.blank();
gmst.mValue.setType (ESM::VT_Int);
addOptionalGmst (gmst);
}
@ -2038,6 +2041,7 @@ void CSMDoc::Document::addOptionalGmsts()
{
ESM::GameSetting gmst;
gmst.mId = sStrings[i];
gmst.blank();
gmst.mValue.setType (ESM::VT_String);
gmst.mValue.setString ("<no text>");
addOptionalGmst (gmst);
@ -2058,6 +2062,7 @@ void CSMDoc::Document::addOptionalGlobals()
{
ESM::Global global;
global.mId = sGlobals[i];
global.blank();
global.mValue.setType (ESM::VT_Long);
if (i==0)
@ -2067,6 +2072,19 @@ void CSMDoc::Document::addOptionalGlobals()
}
}
void CSMDoc::Document::addOptionalMagicEffects()
{
for (int i=ESM::MagicEffect::SummonFabricant; i<=ESM::MagicEffect::SummonCreature05; ++i)
{
ESM::MagicEffect effect;
effect.mIndex = i;
effect.mId = ESM::MagicEffect::indexToId (i);
effect.blank();
addOptionalMagicEffect (effect);
}
}
void CSMDoc::Document::addOptionalGmst (const ESM::GameSetting& gmst)
{
if (getData().getGmsts().searchId (gmst.mId)==-1)
@ -2089,6 +2107,17 @@ void CSMDoc::Document::addOptionalGlobal (const ESM::Global& global)
}
}
void CSMDoc::Document::addOptionalMagicEffect (const ESM::MagicEffect& magicEffect)
{
if (getData().getMagicEffects().searchId (magicEffect.mId)==-1)
{
CSMWorld::Record<ESM::MagicEffect> record;
record.mBase = magicEffect;
record.mState = CSMWorld::RecordBase::State_BaseOnly;
getData().getMagicEffects().appendRecord (record);
}
}
void CSMDoc::Document::createBase()
{
static const char *sGlobals[] =
@ -2200,33 +2229,49 @@ void CSMDoc::Document::createBase()
getData().getTopics().add (record);
}
for (int i=0; i<ESM::MagicEffect::Length; ++i)
{
ESM::MagicEffect record;
record.mIndex = i;
record.mId = ESM::MagicEffect::indexToId (i);
record.blank();
getData().getMagicEffects().add (record);
}
}
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding)
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData),
mResDir(resDir),
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
const std::vector<std::string>& blacklistedScripts)
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding)
mSaving (*this, mProjectPath, encoding),
mRunner (mProjectPath)
{
if (mContentFiles.empty())
throw std::runtime_error ("Empty content file sequence");
if (!boost::filesystem::exists (mProjectPath))
{
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
locCustomFiltersPath /= "defaultfilters";
boost::filesystem::path customFiltersPath (configuration.getUserDataPath());
customFiltersPath /= "defaultfilters";
std::ofstream destination (mProjectPath.string().c_str(), std::ios::binary);
if (boost::filesystem::exists (locCustomFiltersPath))
if (boost::filesystem::exists (customFiltersPath))
{
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf();
}
else
{
boost::filesystem::copy_file (mResDir / "defaultfilters", mProjectPath);
destination << std::ifstream(std::string(mResDir.string() + "/defaultfilters").c_str(), std::ios::binary).rdbuf();
}
}
@ -2239,20 +2284,25 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
createBase();
}
mBlacklist.add (CSMWorld::UniversalId::Type_Script, blacklistedScripts);
addOptionalGmsts();
addOptionalGlobals();
addOptionalMagicEffects();
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
connect (
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)));
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
}
CSMDoc::Document::~Document()
@ -2274,6 +2324,9 @@ int CSMDoc::Document::getState() const
if (mSaving.isRunning())
state |= State_Locked | State_Saving | State_Operation;
if (mRunner.isRunning())
state |= State_Locked | State_Running;
if (int operations = mTools.getRunningOperations())
state |= State_Locked | State_Operation | operations;
@ -2338,7 +2391,7 @@ void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std
std::cout << message << std::endl;
}
void CSMDoc::Document::operationDone (int type)
void CSMDoc::Document::operationDone (int type, bool failed)
{
emit stateChanged (getState(), this);
}
@ -2358,6 +2411,55 @@ CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId&
return mTools.getReport (id);
}
bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id)
const
{
return mBlacklist.isBlacklisted (id);
}
void CSMDoc::Document::startRunning (const std::string& profile,
const std::string& startupInstruction)
{
std::vector<std::string> contentFiles;
for (std::vector<boost::filesystem::path>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
contentFiles.push_back (iter->filename().string());
mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles,
startupInstruction);
int state = getState();
if (state & State_Modified)
{
// need to save first
mRunner.start (true);
new SaveWatcher (&mRunner, &mSaving); // no, that is not a memory leak. Qt is weird.
if (!(state & State_Saving))
save();
}
else
mRunner.start();
}
void CSMDoc::Document::stopRunning()
{
mRunner.stop();
}
QTextDocument *CSMDoc::Document::getRunLog()
{
return mRunner.getLog();
}
void CSMDoc::Document::runStateChanged()
{
emit stateChanged (getState(), this);
}
void CSMDoc::Document::progress (int current, int max, int type)
{
emit progress (current, max, type, 1, this);

@ -17,6 +17,8 @@
#include "state.hpp"
#include "saving.hpp"
#include "blacklist.hpp"
#include "runner.hpp"
class QAbstractItemModel;
@ -24,6 +26,7 @@ namespace ESM
{
struct GameSetting;
struct Global;
struct MagicEffect;
}
namespace Files
@ -31,6 +34,11 @@ namespace Files
class ConfigurationManager;
}
namespace CSMWorld
{
class ResourcesManager;
}
namespace CSMDoc
{
class Document : public QObject
@ -47,6 +55,8 @@ namespace CSMDoc
boost::filesystem::path mProjectPath;
Saving mSaving;
boost::filesystem::path mResDir;
Blacklist mBlacklist;
Runner mRunner;
// 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.
@ -64,16 +74,21 @@ namespace CSMDoc
void addOptionalGlobals();
void addOptionalMagicEffects();
void addOptionalGmst (const ESM::GameSetting& gmst);
void addOptionalGlobal (const ESM::Global& global);
void addOptionalMagicEffect (const ESM::MagicEffect& effect);
public:
Document (const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding);
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
const std::vector<std::string>& blacklistedScripts);
~Document();
@ -105,6 +120,15 @@ namespace CSMDoc
CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id);
///< The ownership of the returned report is not transferred.
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
void startRunning (const std::string& profile,
const std::string& startupInstruction = "");
void stopRunning();
QTextDocument *getRunLog();
signals:
void stateChanged (int state, CSMDoc::Document *document);
@ -118,7 +142,9 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type);
void operationDone (int type);
void operationDone (int type, bool failed);
void runStateChanged();
public slots:

@ -31,8 +31,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con
&mLoader, SLOT (loadDocument (CSMDoc::Document *)));
connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)),
this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)));
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)),
this, SIGNAL (nextRecord (CSMDoc::Document *)));
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *, int)),
this, SIGNAL (nextRecord (CSMDoc::Document *, int)));
connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)),
&mLoader, SLOT (abortLoading (CSMDoc::Document *)));
connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager()
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
bool new_)
{
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding);
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
mDocuments.push_back (document);
@ -85,6 +85,16 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
mEncoding = encoding;
}
void CSMDoc::DocumentManager::setBlacklistedScripts (const std::vector<std::string>& scriptIds)
{
mBlacklistedScripts = scriptIds;
}
void CSMDoc::DocumentManager::listResources()
{
mResourcesManager.listResources();
}
void CSMDoc::DocumentManager::documentLoaded (Document *document)
{
emit documentAdded (document);

@ -11,6 +11,8 @@
#include <components/to_utf8/to_utf8.hpp>
#include "../world/resourcesmanager.hpp"
#include "loader.hpp"
namespace Files
@ -31,6 +33,8 @@ namespace CSMDoc
QThread mLoaderThread;
Loader mLoader;
ToUTF8::FromType mEncoding;
CSMWorld::ResourcesManager mResourcesManager;
std::vector<std::string> mBlacklistedScripts;
DocumentManager (const DocumentManager&);
DocumentManager& operator= (const DocumentManager&);
@ -50,6 +54,11 @@ namespace CSMDoc
void setEncoding (ToUTF8::FromType encoding);
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
/// Ask OGRE for a list of available resources.
void listResources();
private:
boost::filesystem::path mResDir;
@ -79,9 +88,10 @@ namespace CSMDoc
void loadingStopped (CSMDoc::Document *document, bool completed,
const std::string& error);
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
void nextStage (CSMDoc::Document *document, const std::string& name,
int totalRecords);
void nextRecord (CSMDoc::Document *document);
void nextRecord (CSMDoc::Document *document, int records);
void cancelLoading (CSMDoc::Document *document);

@ -8,7 +8,7 @@
#include "document.hpp"
#include "state.hpp"
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {}
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLoaded (0), mRecordsLeft (false) {}
CSMDoc::Loader::Loader()
@ -39,13 +39,14 @@ void CSMDoc::Loader::load()
Document *document = iter->first;
int size = static_cast<int> (document->getContentFiles().size());
int editedIndex = size-1; // index of the file to be edited/created
if (document->isNew())
--size;
bool done = false;
const int batchingSize = 100;
const int batchingSize = 50;
try
{
@ -58,17 +59,21 @@ void CSMDoc::Loader::load()
iter->second.mRecordsLeft = false;
break;
}
else
++(iter->second.mRecordsLoaded);
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
{ // silence a g++ warning
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
iter!=messages.end(); ++iter)
{
document->getReport (log)->add (iter->first, iter->second);
emit loadMessage (document, iter->second);
}
}
emit nextRecord (document);
emit nextRecord (document, iter->second.mRecordsLoaded);
return;
}
@ -77,17 +82,19 @@ void CSMDoc::Loader::load()
{
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
int steps = document->getData().startLoading (path, iter->second.mFile<size-1, false);
int steps = document->getData().startLoading (path, iter->second.mFile!=editedIndex, false);
iter->second.mRecordsLeft = true;
iter->second.mRecordsLoaded = 0;
emit nextStage (document, path.filename().string(), steps/batchingSize);
emit nextStage (document, path.filename().string(), steps);
}
else if (iter->second.mFile==size)
{
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
iter->second.mRecordsLeft = true;
iter->second.mRecordsLoaded = 0;
emit nextStage (document, "Project File", steps/batchingSize);
emit nextStage (document, "Project File", steps);
}
else
{

@ -18,6 +18,7 @@ namespace CSMDoc
struct Stage
{
int mFile;
int mRecordsLoaded;
bool mRecordsLeft;
Stage();
@ -56,9 +57,10 @@ namespace CSMDoc
///< Document load has been interrupted either because of a call to abortLoading
/// or a problem during loading). In the former case error will be an empty string.
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
void nextStage (CSMDoc::Document *document, const std::string& name,
int totalRecords);
void nextRecord (CSMDoc::Document *document);
void nextRecord (CSMDoc::Document *document, int records);
///< \note This signal is only given once per group of records. The group size is
/// approximately the total number of records divided by the steps value of the
/// previous nextStage signal.

@ -27,7 +27,9 @@ void CSMDoc::Operation::prepareStages()
}
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
: mType (type), mOrdered (ordered), mFinalAlways (finalAlways)
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
mFinalAlways (finalAlways), mError(false)
{
connect (this, SIGNAL (finished()), this, SLOT (operationDone()));
}
@ -119,5 +121,5 @@ void CSMDoc::Operation::executeStage()
void CSMDoc::Operation::operationDone()
{
emit done (mType);
emit done (mType, mError);
}

@ -54,7 +54,7 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type);
void done (int type);
void done (int type, bool failed);
public slots:

@ -0,0 +1,162 @@
#include "runner.hpp"
#include <QApplication>
#include <QDir>
#include <QTemporaryFile>
#include <QTextStream>
#include "operation.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath)
{
connect (&mProcess, SIGNAL (finished (int, QProcess::ExitStatus)),
this, SLOT (finished (int, QProcess::ExitStatus)));
connect (&mProcess, SIGNAL (readyReadStandardOutput()),
this, SLOT (readyReadStandardOutput()));
mProcess.setProcessChannelMode (QProcess::MergedChannels);
mProfile.blank();
}
CSMDoc::Runner::~Runner()
{
if (mRunning)
{
disconnect (&mProcess, 0, this, 0);
mProcess.kill();
mProcess.waitForFinished();
}
}
void CSMDoc::Runner::start (bool delayed)
{
if (mStartup)
{
delete mStartup;
mStartup = 0;
}
if (!delayed)
{
mLog.clear();
QString path = "openmw";
#ifdef Q_OS_WIN
path.append(QString(".exe"));
#elif defined(Q_OS_MAC)
QDir dir(QCoreApplication::applicationDirPath());
dir.cdUp();
dir.cdUp();
dir.cdUp();
path = dir.absoluteFilePath(path.prepend("OpenMW.app/Contents/MacOS/"));
#else
path.prepend(QString("./"));
#endif
mStartup = new QTemporaryFile (this);
mStartup->open();
{
QTextStream stream (mStartup);
if (!mStartupInstruction.empty())
stream << QString::fromUtf8 (mStartupInstruction.c_str()) << '\n';
stream << QString::fromUtf8 (mProfile.mScriptText.c_str());
}
mStartup->close();
QStringList arguments;
arguments << "--skip-menu";
if (mProfile.mFlags & ESM::DebugProfile::Flag_BypassNewGame)
arguments << "--new-game=0";
else
arguments << "--new-game=1";
arguments << ("--script-run="+mStartup->fileName());;
arguments <<
QString::fromUtf8 (("--data="+mProjectPath.parent_path().string()).c_str());
for (std::vector<std::string>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
{
arguments << QString::fromUtf8 (("--content="+*iter).c_str());
}
arguments
<< QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str());
mProcess.start (path, arguments);
}
mRunning = true;
emit runStateChanged();
}
void CSMDoc::Runner::stop()
{
delete mStartup;
mStartup = 0;
if (mProcess.state()==QProcess::NotRunning)
{
mRunning = false;
emit runStateChanged();
}
else
mProcess.kill();
}
bool CSMDoc::Runner::isRunning() const
{
return mRunning;
}
void CSMDoc::Runner::configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles, const std::string& startupInstruction)
{
mProfile = profile;
mContentFiles = contentFiles;
mStartupInstruction = startupInstruction;
}
void CSMDoc::Runner::finished (int exitCode, QProcess::ExitStatus exitStatus)
{
mRunning = false;
emit runStateChanged();
}
QTextDocument *CSMDoc::Runner::getLog()
{
return &mLog;
}
void CSMDoc::Runner::readyReadStandardOutput()
{
mLog.setPlainText (
mLog.toPlainText() + QString::fromUtf8 (mProcess.readAllStandardOutput()));
}
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation)
: QObject (runner), mRunner (runner)
{
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));
}
void CSMDoc::SaveWatcher::saveDone (int type, bool failed)
{
if (failed)
mRunner->stop();
else
mRunner->start();
deleteLater();
}

@ -0,0 +1,85 @@
#ifndef CSM_DOC_RUNNER_H
#define CSM_DOC_RUNNER_H
#include <vector>
#include <string>
#include <boost/filesystem/path.hpp>
#include <QObject>
#include <QProcess>
#include <QTextDocument>
#include <components/esm/debugprofile.hpp>
class QTemporaryFile;
namespace CSMDoc
{
class Runner : public QObject
{
Q_OBJECT
QProcess mProcess;
bool mRunning;
ESM::DebugProfile mProfile;
std::vector<std::string> mContentFiles;
std::string mStartupInstruction;
QTemporaryFile *mStartup;
QTextDocument mLog;
boost::filesystem::path mProjectPath;
public:
Runner (const boost::filesystem::path& projectPath);
~Runner();
/// \param delayed Flag as running but do not start the OpenMW process yet (the
/// process must be started by another call of start with delayed==false)
void start (bool delayed = false);
void stop();
/// \note Running state is entered when the start function is called. This
/// is not necessarily identical to the moment the child process is started.
bool isRunning() const;
void configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles,
const std::string& startupInstruction);
QTextDocument *getLog();
signals:
void runStateChanged();
private slots:
void finished (int exitCode, QProcess::ExitStatus exitStatus);
void readyReadStandardOutput();
};
class Operation;
/// \brief Watch for end of save operation and restart or stop runner
class SaveWatcher : public QObject
{
Q_OBJECT
Runner *mRunner;
public:
/// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation);
private slots:
void saveDone (int type, bool failed);
};
}
#endif

@ -17,7 +17,14 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteHeaderStage (mDocument, mState, true));
appendStage (new WriteFilterStage (mDocument, mState, CSMFilter::Filter::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Filter> > (
mDocument.getData().getFilters(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::DebugProfile> > (
mDocument.getData().getDebugProfiles(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> > (
mDocument.getData().getScripts(), mState, CSMWorld::Scope_Project));
appendStage (new CloseSaveStage (mState));
@ -59,13 +66,31 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Spell> >
(mDocument.getData().getSpells(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Enchantment> >
(mDocument.getData().getEnchantments(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::BodyPart> >
(mDocument.getData().getBodyParts(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::SoundGenerator> >
(mDocument.getData().getSoundGens(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
(mDocument.getData().getMagicEffects(), mState));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
appendStage (new CollectionReferencesStage (mDocument, mState));
appendStage (new WriteCellCollectionStage (mDocument, mState));
appendStage (new WritePathgridCollectionStage (mDocument, mState));
// close file and clean up
appendStage (new CloseSaveStage (mState));
appendStage (new FinalSavingStage (mDocument, mState));

@ -9,6 +9,8 @@
#include <components/esm/loaddial.hpp>
#include <components/misc/stringops.hpp>
#include "../world/infocollection.hpp"
#include "document.hpp"
@ -199,20 +201,155 @@ void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages)
}
CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& state,
CSMFilter::Filter::Scope scope)
: WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> > (document.getData().getFilters(),
state),
mDocument (document), mScope (scope)
CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::CollectionReferencesStage::setup()
{
mState.getSubRecords().clear();
int size = mDocument.getData().getReferences().getSize();
int steps = size/100;
if (size%100) ++steps;
return steps;
}
void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
{
int size = mDocument.getData().getReferences().getSize();
for (int i=stage*100; i<stage*100+100 && i<size; ++i)
{
const CSMWorld::Record<CSMWorld::CellRef>& record =
mDocument.getData().getReferences().getRecord (i);
if (record.mState==CSMWorld::RecordBase::State_Deleted ||
record.mState==CSMWorld::RecordBase::State_Modified ||
record.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mCell)]
.push_back (i);
}
}
}
CSMDoc::WriteCellCollectionStage::WriteCellCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::WriteCellCollectionStage::setup()
{
return mDocument.getData().getCells().getSize();
}
void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::Cell>& cell =
mDocument.getData().getCells().getRecord (stage);
std::map<std::string, std::vector<int> >::const_iterator references =
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
if (cell.mState==CSMWorld::RecordBase::State_Modified ||
cell.mState==CSMWorld::RecordBase::State_ModifiedOnly ||
references!=mState.getSubRecords().end())
{
bool interior = cell.get().mId.substr (0, 1)!="#";
// write cell data
mState.getWriter().startRecord (cell.mModified.sRecordId);
mState.getWriter().writeHNOCString ("NAME", cell.get().mName);
ESM::Cell cell2 = cell.get();
if (interior)
cell2.mData.mFlags |= ESM::Cell::Interior;
else
{
cell2.mData.mFlags &= ~ESM::Cell::Interior;
std::istringstream stream (cell.get().mId.c_str());
char ignore;
stream >> ignore >> cell2.mData.mX >> cell2.mData.mY;
}
cell2.save (mState.getWriter());
// write references
if (references!=mState.getSubRecords().end())
{
for (std::vector<int>::const_iterator iter (references->second.begin());
iter!=references->second.end(); ++iter)
{
const CSMWorld::Record<CSMWorld::CellRef>& ref =
mDocument.getData().getReferences().getRecord (*iter);
if (ref.mState==CSMWorld::RecordBase::State_Modified ||
ref.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
ref.get().save (mState.getWriter());
}
else if (ref.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
}
mState.getWriter().endRecord (cell.mModified.sRecordId);
}
else if (cell.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
CSMDoc::WritePathgridCollectionStage::WritePathgridCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages)
int CSMDoc::WritePathgridCollectionStage::setup()
{
const CSMWorld::Record<CSMFilter::Filter>& record =
mDocument.getData().getFilters().getRecord (stage);
return mDocument.getData().getPathgrids().getSize();
}
if (record.get().mScope==mScope)
WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >::perform (stage, messages);
void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
mDocument.getData().getPathgrids().getRecord (stage);
if (pathgrid.mState==CSMWorld::RecordBase::State_Modified ||
pathgrid.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
CSMWorld::Pathgrid record = pathgrid.get();
if (record.mId.substr (0, 1)=="#")
{
std::istringstream stream (record.mId.c_str());
char ignore;
stream >> ignore >> record.mData.mX >> record.mData.mY;
}
else
record.mCell = record.mId;
mState.getWriter().startRecord (record.sRecordId);
record.save (mState.getWriter());
mState.getWriter().endRecord (record.sRecordId);
}
else if (pathgrid.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}

@ -5,8 +5,7 @@
#include "../world/record.hpp"
#include "../world/idcollection.hpp"
#include "../filter/filter.hpp"
#include "../world/scope.hpp"
#include "savingstate.hpp"
@ -67,10 +66,12 @@ namespace CSMDoc
{
const CollectionT& mCollection;
SavingState& mState;
CSMWorld::Scope mScope;
public:
WriteCollectionStage (const CollectionT& collection, SavingState& state);
WriteCollectionStage (const CollectionT& collection, SavingState& state,
CSMWorld::Scope scope = CSMWorld::Scope_Content);
virtual int setup();
///< \return number of steps
@ -81,8 +82,8 @@ namespace CSMDoc
template<class CollectionT>
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
SavingState& state)
: mCollection (collection), mState (state)
SavingState& state, CSMWorld::Scope scope)
: mCollection (collection), mState (state), mScope (scope)
{}
template<class CollectionT>
@ -94,16 +95,14 @@ namespace CSMDoc
template<class CollectionT>
void WriteCollectionStage<CollectionT>::perform (int stage, Messages& messages)
{
if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope)
return;
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic (change ESMWriter interface?)
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter());
@ -152,19 +151,54 @@ namespace CSMDoc
};
class WriteFilterStage : public WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >
class CollectionReferencesStage : public Stage
{
Document& mDocument;
CSMFilter::Filter::Scope mScope;
SavingState& mState;
public:
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
CollectionReferencesStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class WriteCellCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WriteCellCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class WritePathgridCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WritePathgridCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class CloseSaveStage : public Stage
{

@ -25,6 +25,8 @@ void CSMDoc::SavingState::start (Document& document, bool project)
mStream.clear();
mSubRecords.clear();
if (project)
mPath = mProjectPath;
else
@ -61,3 +63,8 @@ bool CSMDoc::SavingState::isProjectFile() const
{
return mProjectFile;
}
std::map<std::string, std::vector<int> >& CSMDoc::SavingState::getSubRecords()
{
return mSubRecords;
}

@ -2,6 +2,7 @@
#define CSM_DOC_SAVINGSTATE_H
#include <fstream>
#include <map>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
@ -25,6 +26,7 @@ namespace CSMDoc
ESM::ESMWriter mWriter;
boost::filesystem::path mProjectPath;
bool mProjectFile;
std::map<std::string, std::vector<int> > mSubRecords; // record ID, list of subrecords
public:
@ -46,6 +48,8 @@ namespace CSMDoc
bool isProjectFile() const;
///< Currently saving project file? (instead of content file)
std::map<std::string, std::vector<int> >& getSubRecords();
};

@ -8,12 +8,13 @@ namespace CSMDoc
State_Modified = 1,
State_Locked = 2,
State_Operation = 4,
State_Running = 8,
State_Saving = 8,
State_Verifying = 16,
State_Compiling = 32, // not implemented yet
State_Searching = 64, // not implemented yet
State_Loading = 128 // pseudo-state; can not be encountered in a loaded document
State_Saving = 16,
State_Verifying = 32,
State_Compiling = 64, // not implemented yet
State_Searching = 128, // not implemented yet
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
};
}

@ -7,7 +7,7 @@ CSMFilter::AndNode::AndNode (const std::vector<boost::shared_ptr<Node> >& nodes)
: NAryNode (nodes, "and")
{}
bool CSMFilter::AndNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::AndNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
int size = getSize();

@ -11,7 +11,7 @@ namespace CSMFilter
AndNode (const std::vector<boost::shared_ptr<Node> >& nodes);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -3,7 +3,7 @@
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
bool CSMFilter::BooleanNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
return mTrue;

@ -13,7 +13,7 @@ namespace CSMFilter
BooleanNode (bool true_);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -1,25 +0,0 @@
#ifndef CSM_FILTER_FILTER_H
#define CSM_FILTER_FILTER_H
#include <vector>
#include <string>
#include <components/esm/filter.hpp>
namespace CSMFilter
{
/// \brief Wrapper for Filter record
struct Filter : public ESM::Filter
{
enum Scope
{
Scope_Project = 0, // per project
Scope_Session = 1, // exists only for one editing session; not saved
Scope_Content = 2 // embedded in the edited content file
};
Scope mScope;
};
}
#endif

@ -11,7 +11,7 @@
namespace CSMWorld
{
class IdTable;
class IdTableBase;
}
namespace CSMFilter
@ -32,7 +32,7 @@ namespace CSMFilter
virtual ~Node();
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const = 0;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -3,7 +3,7 @@
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
bool CSMFilter::NotNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
return !getChild().test (table, row, columns);

@ -11,7 +11,7 @@ namespace CSMFilter
NotNode (boost::shared_ptr<Node> child);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -7,7 +7,7 @@ CSMFilter::OrNode::OrNode (const std::vector<boost::shared_ptr<Node> >& nodes)
: NAryNode (nodes, "or")
{}
bool CSMFilter::OrNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::OrNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
int size = getSize();

@ -11,7 +11,7 @@ namespace CSMFilter
OrNode (const std::vector<boost::shared_ptr<Node> >& nodes);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -550,7 +550,12 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
if (allowPredefined)
token = getNextToken();
if (!allowPredefined || token==Token (Token::Type_OneShot))
if (allowPredefined && token==Token (Token::Type_EOS))
{
mFilter.reset();
return true;
}
else if (!allowPredefined || token==Token (Token::Type_OneShot))
{
boost::shared_ptr<Node> node = parseImp (true, token!=Token (Token::Type_OneShot));
@ -591,7 +596,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
return false;
}
const CSMWorld::Record<CSMFilter::Filter>& record = mData.getFilters().getRecord (index);
const CSMWorld::Record<ESM::Filter>& record = mData.getFilters().getRecord (index);
if (record.isDeleted())
{

@ -7,13 +7,13 @@
#include <QRegExp>
#include "../world/columns.hpp"
#include "../world/idtable.hpp"
#include "../world/idtablebase.hpp"
CSMFilter::TextNode::TextNode (int columnId, const std::string& text)
: mColumnId (columnId), mText (text)
{}
bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::TextNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);

@ -14,7 +14,7 @@ namespace CSMFilter
TextNode (int columnId, const std::string& text);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -5,13 +5,13 @@
#include <stdexcept>
#include "../world/columns.hpp"
#include "../world/idtable.hpp"
#include "../world/idtablebase.hpp"
CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType,
double lower, double upper)
: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){}
bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
bool CSMFilter::ValueNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const
{
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);

@ -27,7 +27,7 @@ namespace CSMFilter
ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper);
virtual bool test (const CSMWorld::IdTable& table, int row,
virtual bool test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const;
///< \return Can the specified table row pass through to filter?
/// \param columns column ID to column index mapping

@ -2,8 +2,8 @@
#include "support.hpp"
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
const QString &pageName)
: mIsEditorSetting (false)
const QString &pageName, const QString& label)
: mIsEditorSetting (true)
{
buildDefaultSetting();
@ -17,6 +17,7 @@ CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
setProperty (Property_SettingType, QVariant (settingType).toString());
setProperty (Property_Page, pageName);
setProperty (Property_Name, settingName);
setProperty (Property_Label, label.isEmpty() ? settingName : label);
}
void CSMSettings::Setting::buildDefaultSetting()
@ -194,6 +195,16 @@ QString CSMSettings::Setting::page() const
return property (Property_Page).at(0);
}
void CSMSettings::Setting::setStyleSheet (const QString &value)
{
setProperty (Property_StyleSheet, value);
}
QString CSMSettings::Setting::styleSheet() const
{
return property (Property_StyleSheet).at(0);
}
void CSMSettings::Setting::setPrefix (const QString &value)
{
setProperty (Property_Prefix, value);
@ -280,14 +291,16 @@ CSMSettings::SettingType CSMSettings::Setting::type() const
Property_SettingType).at(0).toInt());
}
void CSMSettings::Setting::setMaximum (int value)
void CSMSettings::Setting::setRange (int min, int max)
{
setProperty (Property_Maximum, value);
setProperty (Property_Minimum, min);
setProperty (Property_Maximum, max);
}
void CSMSettings::Setting::setMaximum (double value)
void CSMSettings::Setting::setRange (double min, double max)
{
setProperty (Property_Maximum, value);
setProperty (Property_Minimum, min);
setProperty (Property_Maximum, max);
}
QString CSMSettings::Setting::maximum() const
@ -295,16 +308,6 @@ QString CSMSettings::Setting::maximum() const
return property (Property_Maximum).at(0);
}
void CSMSettings::Setting::setMinimum (int value)
{
setProperty (Property_Minimum, value);
}
void CSMSettings::Setting::setMinimum (double value)
{
setProperty (Property_Minimum, value);
}
QString CSMSettings::Setting::minimum() const
{
return property (Property_Minimum).at(0);
@ -362,6 +365,26 @@ bool CSMSettings::Setting::wrapping() const
return (property (Property_Wrapping).at(0) == "true");
}
void CSMSettings::Setting::setLabel (const QString& label)
{
setProperty (Property_Label, label);
}
QString CSMSettings::Setting::getLabel() const
{
return property (Property_Label).at (0);
}
void CSMSettings::Setting::setToolTip (const QString& toolTip)
{
setProperty (Property_ToolTip, toolTip);
}
QString CSMSettings::Setting::getToolTip() const
{
return property (Property_ToolTip).at (0);
}
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
{
setProperty (prop, QStringList() << QVariant (value).toString());

@ -29,8 +29,8 @@ namespace CSMSettings
public:
explicit Setting(SettingType typ, const QString &settingName,
const QString &pageName);
Setting(SettingType typ, const QString &settingName,
const QString &pageName, const QString& label = "");
void addProxy (const Setting *setting, const QStringList &vals);
void addProxy (const Setting *setting, const QList <QStringList> &list);
@ -66,12 +66,11 @@ namespace CSMSettings
void setMask (const QString &value);
QString mask() const;
void setMaximum (int value);
void setMaximum (double value);
void setRange (int min, int max);
void setRange (double min, double max);
QString maximum() const;
void setMinimum (int value);
void setMinimum (double value);
QString minimum() const;
void setName (const QString &value);
@ -80,6 +79,9 @@ namespace CSMSettings
void setPage (const QString &value);
QString page() const;
void setStyleSheet (const QString &value);
QString styleSheet() const;
void setPrefix (const QString &value);
QString prefix() const;
@ -129,6 +131,13 @@ namespace CSMSettings
void setWidgetWidth (int value);
int widgetWidth() const;
/// This is the text the user gets to see.
void setLabel (const QString& label);
QString getLabel() const;
void setToolTip (const QString& toolTip);
QString getToolTip() const;
///returns the specified property value
QStringList property (SettingProperty prop) const;

@ -35,12 +35,15 @@ namespace CSMSettings
Property_TickInterval = 19,
Property_TicksAbove = 20,
Property_TicksBelow = 21,
Property_StyleSheet = 22,
Property_Label = 23,
Property_ToolTip = 24,
//Stringlists should always be the last items
Property_DefaultValues = 22,
Property_DeclaredValues = 23,
Property_DefinedValues = 24,
Property_Proxies = 25
Property_DefaultValues = 25,
Property_DeclaredValues = 26,
Property_DefinedValues = 27,
Property_Proxies = 28
};
///Basic setting widget types.
@ -106,7 +109,7 @@ namespace CSMSettings
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
"is_serializable","column_span", "row_span", "minimum", "maximum",
"special_value_text", "prefix", "suffix", "single_step", "wrapping",
"tick_interval", "ticks_above", "ticks_below",
"tick_interval", "ticks_above", "ticks_below", "stylesheet",
"defaults", "declarations", "definitions", "proxies"
};
@ -135,6 +138,7 @@ namespace CSMSettings
"1", //tick interval
"false", //ticks above
"true", //ticks below
"", //StyleSheet
"", //default values
"", //declared values
"", //defined values

@ -4,12 +4,16 @@
#include <QFile>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
#include <boost/version.hpp>
#include "setting.hpp"
#include "support.hpp"
#include <QTextCodec>
#include <QDebug>
#include <extern/shiny/Main/Factory.hpp>
/**
* Workaround for problems with whitespaces in paths in older versions of Boost library
*/
@ -26,81 +30,184 @@ namespace boost
} /* namespace boost */
#endif /* (BOOST_VERSION <= 104600) */
CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0;
CSMSettings::UserSettings *CSMSettings::UserSettings::sUserSettingsInstance = 0;
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
: mCfgMgr (configurationManager)
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
: mCfgMgr (configurationManager)
, mSettingDefinitions(NULL)
{
assert(!mUserSettingsInstance);
mUserSettingsInstance = this;
mSettingDefinitions = 0;
assert(!sUserSettingsInstance);
sUserSettingsInstance = this;
buildSettingModelDefaults();
}
void CSMSettings::UserSettings::buildSettingModelDefaults()
{
QString section = "Window Size";
{
Setting *width = createSetting (Type_LineEdit, section, "Width");
Setting *height = createSetting (Type_LineEdit, section, "Height");
width->setWidgetWidth (5);
height->setWidgetWidth (8);
width->setDefaultValues (QStringList() << "1024");
height->setDefaultValues (QStringList() << "768");
width->setEditorSetting (true);
height->setEditorSetting (true);
QString section;
height->setViewLocation (2,2);
width->setViewLocation (2,1);
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");
farClipDist->setDefaultValue (300000);
farClipDist->setRange (0, 1000000);
farClipDist->setToolTip ("The maximum distance objects are still rendered at.");
QString defaultValue = "None";
Setting *antialiasing = createSetting (Type_ComboBox, "antialiasing", "Antialiasing");
antialiasing->setDeclaredValues (QStringList()
<< defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16");
antialiasing->setDefaultValue (defaultValue);
}
/*
*Create the proxy setting for predefined values
*/
Setting *preDefined = createSetting (Type_ComboBox, section,
"Pre-Defined");
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);
}
preDefined->setDeclaredValues (QStringList() << "640 x 480"
<< "800 x 600" << "1024 x 768" << "1440 x 900");
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",
"Fast movement factor");
fastFactor->setDefaultValue (4);
fastFactor->setRange (1, 100);
fastFactor->setToolTip (
"Factor by which movement is speed up while the shift key is held down.");
}
declareSection ("window", "Window");
{
Setting *preDefined = createSetting (Type_ComboBox, "pre-defined",
"Default window size");
preDefined->setEditorSetting (false);
preDefined->setDeclaredValues (
QStringList() << "640 x 480" << "800 x 600" << "1024 x 768" << "1440 x 900");
preDefined->setViewLocation (1, 1);
preDefined->setWidgetWidth (10);
preDefined->setColumnSpan (2);
preDefined->setToolTip ("Newly opened top-level windows will open with this size "
"(picked from a list of pre-defined values)");
preDefined->addProxy (width,
QStringList() << "640" << "800" << "1024" << "1440"
);
Setting *width = createSetting (Type_LineEdit, "default-width",
"Default window width");
width->setDefaultValues (QStringList() << "1024");
width->setViewLocation (2, 1);
width->setColumnSpan (1);
width->setToolTip ("Newly opened top-level windows will open with this width.");
preDefined->addProxy (width, QStringList() << "640" << "800" << "1024" << "1440");
preDefined->addProxy (height,
QStringList() << "480" << "600" << "768" << "900"
);
Setting *height = createSetting (Type_LineEdit, "default-height",
"Default window height");
height->setDefaultValues (QStringList() << "768");
height->setViewLocation (2, 2);
height->setColumnSpan (1);
height->setToolTip ("Newly opened top-level windows will open with this height.");
preDefined->addProxy (height, QStringList() << "480" << "600" << "768" << "900");
Setting *reuse = createSetting (Type_CheckBox, "reuse", "Reuse Subviews");
reuse->setDefaultValue ("true");
reuse->setToolTip ("When a new subview is requested and a matching subview already "
" exist, do not open a new subview and use the existing one instead.");
Setting *statusBar = createSetting (Type_CheckBox, "show-statusbar", "Show Status Bar");
statusBar->setDefaultValue ("true");
statusBar->setToolTip ("If a newly open top level window is showing status bars or not. "
" Note that this does not affect existing windows.");
Setting *maxSubView = createSetting (Type_SpinBox, "max-subviews",
"Maximum number of subviews per top-level window");
maxSubView->setDefaultValue (256);
maxSubView->setRange (1, 256);
maxSubView->setToolTip ("If the maximum number is reached and a new subview is opened "
"it will be placed into a new top-level window.");
Setting *hide = createSetting (Type_CheckBox, "hide-subview", "Hide single subview");
hide->setDefaultValue ("false");
hide->setToolTip ("When a view contains only a single subview, hide the subview title "
"bar and if this subview is closed also close the view (unless it is the last "
"view for this document)");
Setting *minWidth = createSetting (Type_SpinBox, "minimum-width",
"Minimum subview width");
minWidth->setDefaultValue (325);
minWidth->setRange (50, 10000);
minWidth->setToolTip ("Minimum width of subviews.");
}
section = "Display Format";
declareSection ("records", "Records");
{
QString defaultValue = "Icon and Text";
QStringList values = QStringList() << defaultValue << "Icon Only" << "Text Only";
QStringList values = QStringList()
<< defaultValue << "Icon Only" << "Text Only";
Setting *rsd = createSetting (Type_RadioButton,
section, "Record Status Display");
Setting *ritd = createSetting (Type_RadioButton,
section, "Referenceable ID Type Display");
Setting *rsd = createSetting (Type_RadioButton, "status-format",
"Modification status display format");
rsd->setDefaultValue (defaultValue);
rsd->setDeclaredValues (values);
Setting *ritd = createSetting (Type_RadioButton, "type-format",
"ID type display format");
ritd->setDefaultValue (defaultValue);
ritd->setDeclaredValues (values);
}
rsd->setEditorSetting (true);
ritd->setEditorSetting (true);
declareSection ("table-input", "Table Input");
{
QString inPlaceEdit ("Edit in Place");
QString editRecord ("Edit Record");
QString view ("View");
QString editRecordAndClose ("Edit Record and Close");
QStringList values;
values
<< "None" << inPlaceEdit << editRecord << view << "Revert" << "Delete"
<< editRecordAndClose << "View and Close";
QString toolTip = "<ul>"
"<li>None</li>"
"<li>Edit in Place: Edit the clicked cell</li>"
"<li>Edit Record: Open a dialogue subview for the clicked record</li>"
"<li>View: Open a scene subview for the clicked record (not available everywhere)</li>"
"<li>Revert: Revert record</li>"
"<li>Delete: Delete recordy</li>"
"<li>Edit Record and Close: Open a dialogue subview for the clicked record and close the table subview</li>"
"<li>View And Close: Open a scene subview for the clicked record and close the table subview</li>"
"</ul>";
Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click");
doubleClick->setDeclaredValues (values);
doubleClick->setDefaultValue (inPlaceEdit);
doubleClick->setToolTip ("Action on double click in table:<p>" + toolTip);
Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s",
"Shift Double Click");
shiftDoubleClick->setDeclaredValues (values);
shiftDoubleClick->setDefaultValue (editRecord);
shiftDoubleClick->setToolTip ("Action on shift double click in table:<p>" + toolTip);
Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c",
"Control Double Click");
ctrlDoubleClick->setDeclaredValues (values);
ctrlDoubleClick->setDefaultValue (view);
ctrlDoubleClick->setToolTip ("Action on control double click in table:<p>" + toolTip);
Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc",
"Shift Control Double Click");
shiftCtrlDoubleClick->setDeclaredValues (values);
shiftCtrlDoubleClick->setDefaultValue (editRecordAndClose);
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip);
}
section = "Proxy Selection Test";
{
/******************************************************************
* There are three types of values:
@ -276,7 +383,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
CSMSettings::UserSettings::~UserSettings()
{
mUserSettingsInstance = 0;
sUserSettingsInstance = 0;
}
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
@ -307,8 +414,21 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName)
(QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this);
}
bool CSMSettings::UserSettings::hasSettingDefinitions
(const QString &viewKey) const
// if the key is not found create one with a default value
QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString &value)
{
if(mSettingDefinitions->contains(viewKey))
return settingValue(viewKey);
else if(value != QString())
{
mSettingDefinitions->setValue (viewKey, QStringList() << value);
return value;
}
return QString();
}
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
{
return (mSettingDefinitions->contains (viewKey));
}
@ -326,10 +446,12 @@ void CSMSettings::UserSettings::saveDefinitions() const
QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
{
QStringList defs;
if (!mSettingDefinitions->contains (settingKey))
return QString();
QStringList defs = mSettingDefinitions->value (settingKey).toStringList();
defs = mSettingDefinitions->value (settingKey).toStringList();
if (defs.isEmpty())
return QString();
@ -339,8 +461,8 @@ QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
{
assert(mUserSettingsInstance);
return *mUserSettingsInstance;
assert(sUserSettingsInstance);
return *sUserSettingsInstance;
}
void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
@ -348,6 +470,15 @@ void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
{
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);
}
@ -387,30 +518,62 @@ void CSMSettings::UserSettings::removeSetting
}
}
CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const
{
SettingPageMap pageMap;
foreach (Setting *setting, mSettings)
pageMap[setting->page()].append (setting);
{
SettingPageMap::iterator iter = pageMap.find (setting->page());
if (iter==pageMap.end())
{
QPair<QString, QList <Setting *> > value;
std::map<QString, QString>::const_iterator iter2 =
mSectionLabels.find (setting->page());
value.first = iter2!=mSectionLabels.end() ? iter2->second : "";
iter = pageMap.insert (setting->page(), value);
}
iter->second.append (setting);
}
return pageMap;
}
CSMSettings::Setting *CSMSettings::UserSettings::createSetting
(CSMSettings::SettingType typ, const QString &page, const QString &name)
(CSMSettings::SettingType type, const QString &name, const QString& label)
{
//get list of all settings for the current setting name
if (findSetting (page, name))
{
qWarning() << "Duplicate declaration encountered: "
<< (name + '/' + page);
return 0;
}
Setting *setting = new Setting (type, name, mSection, label);
// set useful defaults
int row = 1;
if (!mSettings.empty())
row = mSettings.back()->viewRow()+1;
setting->setViewLocation (row, 1);
setting->setColumnSpan (3);
Setting *setting = new Setting (typ, name, page);
int width = 10;
if (type==Type_CheckBox)
width = 40;
setting->setWidgetWidth (width);
if (type==Type_CheckBox)
setting->setStyleSheet ("QGroupBox { border: 0px; }");
if (type==Type_CheckBox)
setting->setDeclaredValues(QStringList() << "true" << "false");
if (type==Type_CheckBox)
setting->setSpecialValueText (setting->getLabel());
//add declaration to the model
mSettings.append (setting);
@ -418,6 +581,12 @@ CSMSettings::Setting *CSMSettings::UserSettings::createSetting
return setting;
}
void CSMSettings::UserSettings::declareSection (const QString& page, const QString& label)
{
mSection = page;
mSectionLabels[page] = label;
}
QStringList CSMSettings::UserSettings::definitions (const QString &viewKey) const
{
if (mSettingDefinitions->contains (viewKey))

@ -1,10 +1,13 @@
#ifndef USERSETTINGS_HPP
#define USERSETTINGS_HPP
#include <map>
#include <QList>
#include <QStringList>
#include <QString>
#include <QMap>
#include <QPair>
#include <boost/filesystem/path.hpp>
#include "support.hpp"
@ -22,18 +25,20 @@ class QSettings;
namespace CSMSettings {
class Setting;
typedef QMap <QString, QList <Setting *> > SettingPageMap;
typedef QMap <QString, QPair<QString, QList <Setting *> > > SettingPageMap;
class UserSettings: public QObject
{
Q_OBJECT
static UserSettings *mUserSettingsInstance;
static UserSettings *sUserSettingsInstance;
const Files::ConfigurationManager& mCfgMgr;
QSettings *mSettingDefinitions;
QList <Setting *> mSettings;
QString mSection;
std::map<QString, QString> mSectionLabels;
public:
@ -62,7 +67,7 @@ namespace CSMSettings {
void removeSetting
(const QString &pageName, const QString &settingName);
///Retreive a map of the settings, keyed by page name
///Retrieve a map of the settings, keyed by page name
SettingPageMap settingPageMap() const;
///Returns a string list of defined vlaues for the specified setting
@ -75,13 +80,20 @@ namespace CSMSettings {
///Save any unsaved changes in the QSettings object
void saveDefinitions() const;
QString setting(const QString &viewKey, const QString &value = QString());
private:
void buildSettingModelDefaults();
///add a new setting to the model and return it
Setting *createSetting (CSMSettings::SettingType typ,
const QString &page, const QString &name);
Setting *createSetting (CSMSettings::SettingType type, const QString &name,
const QString& label);
/// Set the section for createSetting calls.
///
/// Sections can be declared multiple times.
void declareSection (const QString& page, const QString& label);
signals:

@ -0,0 +1,51 @@
#include "bodypartcheck.hpp"
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
const CSMWorld::Resources &meshes,
const CSMWorld::IdCollection<ESM::Race> &races ) :
mBodyParts(bodyParts),
mMeshes(meshes),
mRaces(races)
{ }
int CSMTools::BodyPartCheckStage::setup()
{
return mBodyParts.getSize();
}
void CSMTools::BodyPartCheckStage::perform ( int stage, Messages &messages )
{
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
if ( record.isDeleted() )
return;
const ESM::BodyPart &bodyPart = record.get();
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
// Check BYDT
if (bodyPart.mData.mPart > 14 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range part value." ));
if (bodyPart.mData.mFlags > 3 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range flags value." ));
if (bodyPart.mData.mType > 2 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range type value." ));
// Check MODL
if ( bodyPart.mModel.empty() )
messages.push_back(std::make_pair( id, bodyPart.mId + " has no model." ));
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid model." ));
// Check FNAM
if ( bodyPart.mRace.empty() )
messages.push_back(std::make_pair( id, bodyPart.mId + " has no race." ));
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid race." ));
}

@ -0,0 +1,35 @@
#ifndef CSM_TOOLS_BODYPARTCHECK_H
#define CSM_TOOLS_BODYPARTCHECK_H
#include <components/esm/loadbody.hpp>
#include <components/esm/loadrace.hpp>
#include "../world/resources.hpp"
#include "../world/idcollection.hpp"
#include "../doc/stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that body part records are internally consistent
class BodyPartCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
const CSMWorld::Resources &mMeshes;
const CSMWorld::IdCollection<ESM::Race> &mRaces;
public:
BodyPartCheckStage(
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
const CSMWorld::Resources &meshes,
const CSMWorld::IdCollection<ESM::Race> &races );
virtual int setup();
///< \return number of steps
virtual void perform( int stage, Messages &messages );
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

@ -42,7 +42,7 @@ void CSMTools::FactionCheckStage::perform (int stage, Messages& messages)
// test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences
for (int i=0; i<6; ++i)
for (int i=0; i<7; ++i)
if (faction.mData.mSkills[i]!=-1)
++skills[faction.mData.mSkills[i]];

@ -621,12 +621,6 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
}
else
{
if (npc.mNpdt52.mMana < 0)
messages.push_back (std::make_pair (id, npc.mId + " mana has negative value"));
if (npc.mNpdt52.mFatigue < 0)
messages.push_back (std::make_pair (id, npc.mId + " fatigue has negative value"));
if (npc.mNpdt52.mAgility == 0)
messages.push_back (std::make_pair (id, npc.mId + " agility has zero value"));

@ -7,6 +7,8 @@
#include <components/compiler/exception.hpp>
#include <components/compiler/extensions0.hpp>
#include "../doc/document.hpp"
#include "../world/data.hpp"
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
@ -37,8 +39,8 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
(type==ErrorMessage ? "error: " : "warning: ") + message));
}
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
: mData (data), mContext (data), mMessages (0)
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
: mDocument (document), mContext (document.getData()), mMessages (0)
{
/// \todo add an option to configure warning mode
setWarningsMode (0);
@ -53,18 +55,25 @@ int CSMTools::ScriptCheckStage::setup()
mMessages = 0;
mId.clear();
return mData.getScripts().getSize();
return mDocument.getData().getScripts().getSize();
}
void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages)
{
mId = mDocument.getData().getScripts().getId (stage);
if (mDocument.isBlacklisted (
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
return;
mMessages = &messages;
mId = mData.getScripts().getId (stage);
try
{
mFile = mData.getScripts().getRecord (stage).get().mId;
std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText);
const CSMWorld::Data& data = mDocument.getData();
mFile = data.getScripts().getRecord (stage).get().mId;
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
Compiler::Scanner scanner (*this, input, mContext.getExtensions());

@ -8,12 +8,17 @@
#include "../world/scriptcontext.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMTools
{
/// \brief VerifyStage: make sure that scripts compile
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
{
const CSMWorld::Data& mData;
const CSMDoc::Document& mDocument;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext;
std::string mId;
@ -28,7 +33,7 @@ namespace CSMTools
public:
ScriptCheckStage (const CSMWorld::Data& data);
ScriptCheckStage (const CSMDoc::Document& document);
virtual int setup();
///< \return number of steps

@ -5,6 +5,7 @@
#include "../doc/state.hpp"
#include "../doc/operation.hpp"
#include "../doc/document.hpp"
#include "../world/data.hpp"
#include "../world/universalid.hpp"
@ -21,6 +22,7 @@
#include "spellcheck.hpp"
#include "referenceablecheck.hpp"
#include "scriptcheck.hpp"
#include "bodypartcheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type)
{
@ -44,7 +46,7 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int)));
connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int)));
@ -80,13 +82,21 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mData));
mVerifier->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage(
new BodyPartCheckStage(
mData.getBodyParts(),
mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() ));
}
return mVerifier;
}
CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0)
CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0)
{
// index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));

@ -14,6 +14,7 @@ namespace CSMWorld
namespace CSMDoc
{
class Operation;
class Document;
}
namespace CSMTools
@ -24,6 +25,7 @@ namespace CSMTools
{
Q_OBJECT
CSMDoc::Document& mDocument;
CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier;
std::map<int, ReportModel *> mReports;
@ -44,7 +46,7 @@ namespace CSMTools
public:
Tools (CSMWorld::Data& data);
Tools (CSMDoc::Document& document);
virtual ~Tools();
@ -68,7 +70,7 @@ namespace CSMTools
void progress (int current, int max, int type);
void done (int type);
void done (int type, bool failed);
};
}

@ -18,8 +18,3 @@ void CSMWorld::Cell::load (ESM::ESMReader &esm)
mId = stream.str();
}
}
void CSMWorld::Cell::addRef (const std::string& id)
{
mRefs.push_back (std::make_pair (id, false));
}

@ -15,12 +15,9 @@ namespace CSMWorld
struct Cell : public ESM::Cell
{
std::string mId;
std::vector<std::pair<std::string, bool> > mRefs; // ID, modified
std::vector<std::string> mDeletedRefs;
void load (ESM::ESMReader &esm);
void addRef (const std::string& id);
};
}

@ -68,6 +68,7 @@ namespace CSMWorld
Display_TopicInfo,
Display_JournalInfo,
Display_Scene,
Display_GlobalVariable,
//CONCRETE TYPES ENDS HERE
Display_Integer,
@ -89,7 +90,20 @@ namespace CSMWorld
Display_RefRecordType,
Display_DialogueType,
Display_QuestStatusType,
Display_Gender
Display_EnchantmentType,
Display_BodyPartType,
Display_MeshType,
Display_Gender,
Display_Mesh,
Display_Icon,
Display_Music,
Display_SoundRes,
Display_Texture,
Display_Video,
Display_Colour,
Display_ScriptLines, // console context
Display_SoundGeneratorType,
Display_School
};
int mColumnId;
@ -113,8 +127,6 @@ namespace CSMWorld
template<typename ESXRecordT>
struct Column : public ColumnBase
{
int mFlags;
Column (int columnId, Display displayType, int flags = Flag_Table | Flag_Dialogue)
: ColumnBase (columnId, displayType, flags) {}

@ -1,7 +1,9 @@
#ifndef CSM_WOLRD_COLUMNIMP_H
#define CSM_WOLRD_COLUMNIMP_H
#include <cassert>
#include <sstream>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
@ -463,14 +465,21 @@ namespace CSMWorld
struct FlagColumn : public Column<ESXRecordT>
{
int mMask;
bool mInverted;
FlagColumn (int columnId, int mask)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Boolean), mMask (mask)
FlagColumn (int columnId, int mask, bool inverted = false)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Boolean), mMask (mask),
mInverted (inverted)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return (record.get().mData.mFlags & mMask)!=0;
bool flag = (record.get().mData.mFlags & mMask)!=0;
if (mInverted)
flag = !flag;
return flag;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
@ -479,7 +488,7 @@ namespace CSMWorld
int flags = record2.mData.mFlags & ~mMask;
if (data.toInt())
if ((data.toInt()!=0)!=mInverted)
flags |= mMask;
record2.mData.mFlags = flags;
@ -493,6 +502,47 @@ namespace CSMWorld
}
};
template<typename ESXRecordT>
struct FlagColumn2 : public Column<ESXRecordT>
{
int mMask;
bool mInverted;
FlagColumn2 (int columnId, int mask, bool inverted = false)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Boolean), mMask (mask),
mInverted (inverted)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
bool flag = (record.get().mFlags & mMask)!=0;
if (mInverted)
flag = !flag;
return flag;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
int flags = record2.mFlags & ~mMask;
if ((data.toInt()!=0)!=mInverted)
flags |= mMask;
record2.mFlags = flags;
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct WeightHeightColumn : public Column<ESXRecordT>
{
@ -597,7 +647,7 @@ namespace CSMWorld
struct SoundFileColumn : public Column<ESXRecordT>
{
SoundFileColumn()
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_Sound)
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_SoundRes)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
@ -627,7 +677,7 @@ namespace CSMWorld
{
/// \todo Replace Display_Integer with something that displays the colour value more directly.
MapColourColumn()
: Column<ESXRecordT> (Columns::ColumnId_MapColour, ColumnBase::Display_Integer)
: Column<ESXRecordT> (Columns::ColumnId_MapColour, ColumnBase::Display_Colour)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
@ -759,8 +809,18 @@ namespace CSMWorld
template<typename ESXRecordT>
struct ScriptColumn : public Column<ESXRecordT>
{
ScriptColumn()
: Column<ESXRecordT> (Columns::ColumnId_ScriptText, ColumnBase::Display_Script, 0) {}
enum Type
{
Type_File, // regular script record
Type_Lines, // console context
Type_Info // dialogue context (not implemented yet)
};
ScriptColumn (Type type)
: Column<ESXRecordT> (Columns::ColumnId_ScriptText,
type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines,
type==Type_File ? 0 : ColumnBase::Flag_Dialogue)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
@ -970,13 +1030,13 @@ namespace CSMWorld
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mFactIndex;
return record.get().mFactionRank;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mFactIndex = data.toInt();
record2.mFactionRank = data.toInt();
record.setModified (record2);
}
@ -1217,36 +1277,6 @@ namespace CSMWorld
}
};
template<typename ESXRecordT>
struct ScopeColumn : public Column<ESXRecordT>
{
ScopeColumn()
: Column<ESXRecordT> (Columns::ColumnId_Scope, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mScope);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mScope = static_cast<CSMFilter::Filter::Scope> (data.toInt());
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct PosColumn : public Column<ESXRecordT>
@ -1269,7 +1299,7 @@ namespace CSMWorld
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
ESM::Position& position = record2.*mPosition;
position.pos[mIndex] = data.toFloat();
@ -1303,7 +1333,7 @@ namespace CSMWorld
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
ESM::Position& position = record2.*mPosition;
position.rot[mIndex] = data.toFloat();
@ -1682,6 +1712,559 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct EnchantmentTypeColumn : public Column<ESXRecordT>
{
EnchantmentTypeColumn()
: Column<ESXRecordT> (Columns::ColumnId_EnchantmentType, ColumnBase::Display_EnchantmentType)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mData.mType);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mType = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct ChargesColumn2 : public Column<ESXRecordT>
{
ChargesColumn2() : Column<ESXRecordT> (Columns::ColumnId_Charges, ColumnBase::Display_Integer) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mCharge;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mCharge = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AutoCalcColumn : public Column<ESXRecordT>
{
AutoCalcColumn() : Column<ESXRecordT> (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAutocalc!=0;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAutocalc = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct ModelColumn : public Column<ESXRecordT>
{
ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mModel.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mModel = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct VampireColumn : public Column<ESXRecordT>
{
VampireColumn() : Column<ESXRecordT> (Columns::ColumnId_Vampire, ColumnBase::Display_Boolean)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mVampire!=0;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mVampire = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct BodyPartTypeColumn : public Column<ESXRecordT>
{
BodyPartTypeColumn()
: Column<ESXRecordT> (Columns::ColumnId_BodyPartType, ColumnBase::Display_BodyPartType)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mData.mPart);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mPart = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct MeshTypeColumn : public Column<ESXRecordT>
{
MeshTypeColumn()
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mData.mType);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mType = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct OwnerGlobalColumn : public Column<ESXRecordT>
{
OwnerGlobalColumn()
: Column<ESXRecordT> (Columns::ColumnId_OwnerGlobal, ColumnBase::Display_GlobalVariable)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mGlobalVariable.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mGlobalVariable = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct RefNumCounterColumn : public Column<ESXRecordT>
{
RefNumCounterColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNumCounter, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNumCounter);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRefNumCounter = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct RefNumColumn : public Column<ESXRecordT>
{
RefNumColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNum, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNum.mIndex);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRefNum.mIndex = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct SoundColumn : public Column<ESXRecordT>
{
SoundColumn()
: Column<ESXRecordT> (Columns::ColumnId_Sound, ColumnBase::Display_Sound)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mSound.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mSound = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct CreatureColumn : public Column<ESXRecordT>
{
CreatureColumn()
: Column<ESXRecordT> (Columns::ColumnId_Creature, ColumnBase::Display_Creature)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mCreature.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mCreature = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SoundGeneratorTypeColumn : public Column<ESXRecordT>
{
SoundGeneratorTypeColumn()
: Column<ESXRecordT> (Columns::ColumnId_SoundGeneratorType, ColumnBase::Display_SoundGeneratorType)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mType);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mType = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct BaseCostColumn : public Column<ESXRecordT>
{
BaseCostColumn() : Column<ESXRecordT> (Columns::ColumnId_BaseCost, ColumnBase::Display_Float) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mBaseCost;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mBaseCost = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SchoolColumn : public Column<ESXRecordT>
{
SchoolColumn()
: Column<ESXRecordT> (Columns::ColumnId_School, ColumnBase::Display_School)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mSchool;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mSchool = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct EffectTextureColumn : public Column<ESXRecordT>
{
EffectTextureColumn (Columns::ColumnId columnId)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Texture)
{
assert (this->mColumnId==Columns::ColumnId_Icon ||
this->mColumnId==Columns::ColumnId_Particle);
}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (
(this->mColumnId==Columns::ColumnId_Icon ?
record.get().mIcon : record.get().mParticle).c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
(this->mColumnId==Columns::ColumnId_Icon ?
record2.mIcon : record2.mParticle)
= data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct EffectObjectColumn : public Column<ESXRecordT>
{
EffectObjectColumn (Columns::ColumnId columnId)
: Column<ESXRecordT> (columnId, columnId==Columns::ColumnId_BoltObject ? ColumnBase::Display_Weapon : ColumnBase::Display_Static)
{
assert (this->mColumnId==Columns::ColumnId_CastingObject ||
this->mColumnId==Columns::ColumnId_HitObject ||
this->mColumnId==Columns::ColumnId_AreaObject ||
this->mColumnId==Columns::ColumnId_BoltObject);
}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const std::string *string = 0;
switch (this->mColumnId)
{
case Columns::ColumnId_CastingObject: string = &record.get().mCasting; break;
case Columns::ColumnId_HitObject: string = &record.get().mHit; break;
case Columns::ColumnId_AreaObject: string = &record.get().mArea; break;
case Columns::ColumnId_BoltObject: string = &record.get().mBolt; break;
}
if (!string)
throw std::logic_error ("Unsupported column ID");
return QString::fromUtf8 (string->c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
std::string *string = 0;
ESXRecordT record2 = record.get();
switch (this->mColumnId)
{
case Columns::ColumnId_CastingObject: string = &record2.mCasting; break;
case Columns::ColumnId_HitObject: string = &record2.mHit; break;
case Columns::ColumnId_AreaObject: string = &record2.mArea; break;
case Columns::ColumnId_BoltObject: string = &record2.mBolt; break;
}
if (!string)
throw std::logic_error ("Unsupported column ID");
*string = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct EffectSoundColumn : public Column<ESXRecordT>
{
EffectSoundColumn (Columns::ColumnId columnId)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Sound)
{
assert (this->mColumnId==Columns::ColumnId_CastingSound ||
this->mColumnId==Columns::ColumnId_HitSound ||
this->mColumnId==Columns::ColumnId_AreaSound ||
this->mColumnId==Columns::ColumnId_BoltSound);
}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const std::string *string = 0;
switch (this->mColumnId)
{
case Columns::ColumnId_CastingSound: string = &record.get().mCastSound; break;
case Columns::ColumnId_HitSound: string = &record.get().mHitSound; break;
case Columns::ColumnId_AreaSound: string = &record.get().mAreaSound; break;
case Columns::ColumnId_BoltSound: string = &record.get().mBoltSound; break;
}
if (!string)
throw std::logic_error ("Unsupported column ID");
return QString::fromUtf8 (string->c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
std::string *string = 0;
ESXRecordT record2 = record.get();
switch (this->mColumnId)
{
case Columns::ColumnId_CastingSound: string = &record2.mCastSound; break;
case Columns::ColumnId_HitSound: string = &record2.mHitSound; break;
case Columns::ColumnId_AreaSound: string = &record2.mAreaSound; break;
case Columns::ColumnId_BoltSound: string = &record2.mBoltSound; break;
}
if (!string)
throw std::logic_error ("Unsupported column ID");
*string = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -172,8 +172,35 @@ namespace CSMWorld
{ ColumnId_Rank, "Rank" },
{ ColumnId_Gender, "Gender" },
{ ColumnId_PcRank, "PC Rank" },
{ ColumnId_Scope, "Scope" },
{ ColumnId_ReferenceableId, "Referenceable ID" },
{ ColumnId_CombatState, "Combat" },
{ ColumnId_MagicState, "Magic" },
{ ColumnId_StealthState, "Stealth" },
{ ColumnId_EnchantmentType, "Enchantment Type" },
{ ColumnId_Vampire, "Vampire" },
{ ColumnId_BodyPartType, "Bodypart Type" },
{ ColumnId_MeshType, "Mesh Type" },
{ ColumnId_OwnerGlobal, "Owner Global" },
{ ColumnId_DefaultProfile, "Default Profile" },
{ ColumnId_BypassNewGame, "Bypass New Game" },
{ ColumnId_GlobalProfile, "Global Profile" },
{ ColumnId_RefNumCounter, "RefNum Counter" },
{ ColumnId_RefNum, "RefNum" },
{ ColumnId_Creature, "Creature" },
{ ColumnId_SoundGeneratorType, "Sound Generator Type" },
{ ColumnId_AllowSpellmaking, "Allow Spellmaking" },
{ ColumnId_AllowEnchanting, "Allow Enchanting" },
{ ColumnId_BaseCost, "Base Cost" },
{ ColumnId_School, "School" },
{ ColumnId_Particle, "Particle" },
{ ColumnId_CastingObject, "Casting Object" },
{ ColumnId_HitObject, "Hit Object" },
{ ColumnId_AreaObject, "Area Object" },
{ ColumnId_BoltObject, "Bolt Object" },
{ ColumnId_CastingSound, "Casting Sound" },
{ ColumnId_HitSound, "Hit Sound" },
{ ColumnId_AreaSound, "Area Sound" },
{ ColumnId_BoltSound, "Bolt Sound" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
@ -299,6 +326,33 @@ namespace
"Male", "Female", 0
};
static const char *sEnchantmentTypes[] =
{
"Cast Once", "When Strikes", "When Used", "Constant Effect", 0
};
static const char *sBodyPartTypes[] =
{
"Head", "Hair", "Neck", "Chest", "Groin", "Hand", "Wrist", "Forearm", "Upper Arm",
"Foot", "Ankle", "Knee", "Upper Leg", "Clavicle", "Tail", 0
};
static const char *sMeshTypes[] =
{
"Skin", "Clothing", "Armour", 0
};
static const char *sSoundGeneratorType[] =
{
"Left Foot", "Right Foot", "Swim Left", "Swim Right", "Moan", "Roar", "Scream",
"Land", 0
};
static const char *sSchools[] =
{
"Alteration", "Conjuration", "Destruction", "Illusion", "Mysticism", "Restoration", 0
};
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
{
switch (column)
@ -316,6 +370,11 @@ namespace
case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums;
case CSMWorld::Columns::ColumnId_QuestStatusType: return sQuestStatusTypes;
case CSMWorld::Columns::ColumnId_Gender: return sGenderEnums;
case CSMWorld::Columns::ColumnId_EnchantmentType: return sEnchantmentTypes;
case CSMWorld::Columns::ColumnId_BodyPartType: return sBodyPartTypes;
case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes;
case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType;
case CSMWorld::Columns::ColumnId_School: return sSchools;
default: return 0;
}

@ -165,9 +165,35 @@ namespace CSMWorld
ColumnId_Rank = 152,
ColumnId_Gender = 153,
ColumnId_PcRank = 154,
ColumnId_Scope = 155,
ColumnId_ReferenceableId = 156,
ColumnId_CombatState = 157,
ColumnId_MagicState = 158,
ColumnId_StealthState = 159,
ColumnId_EnchantmentType = 160,
ColumnId_Vampire = 161,
ColumnId_BodyPartType = 162,
ColumnId_MeshType = 163,
ColumnId_OwnerGlobal = 164,
ColumnId_DefaultProfile = 165,
ColumnId_BypassNewGame = 166,
ColumnId_GlobalProfile = 167,
ColumnId_RefNumCounter = 168,
ColumnId_RefNum = 169,
ColumnId_Creature = 170,
ColumnId_SoundGeneratorType = 171,
ColumnId_AllowSpellmaking = 172,
ColumnId_AllowEnchanting = 173,
ColumnId_BaseCost = 174,
ColumnId_School = 175,
ColumnId_Particle = 176,
ColumnId_CastingObject = 177,
ColumnId_HitObject = 178,
ColumnId_AreaObject = 179,
ColumnId_BoltObject = 180,
ColumnId_CastingSound = 177,
ColumnId_HitSound = 178,
ColumnId_AreaSound = 179,
ColumnId_BoltSound = 180,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,
@ -212,7 +238,7 @@ namespace CSMWorld
bool hasEnums (ColumnId column);
std::vector<std::string> getEnums (ColumnId column);
///< Returns an empty vector, if \æ column isn't an enum type column.
///< Returns an empty vector, if \a column isn't an enum type column.
}
}

@ -0,0 +1,267 @@
#include "commanddispatcher.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
#include "../doc/document.hpp"
#include "idtable.hpp"
#include "record.hpp"
#include "commands.hpp"
std::vector<std::string> CSMWorld::CommandDispatcher::getDeletableRecords() const
{
std::vector<std::string> result;
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
iter!=mSelection.end(); ++iter)
{
int row = model.getModelIndex (*iter, 0).row();
// check record state
RecordBase::State state = static_cast<RecordBase::State> (
model.data (model.index (row, stateColumnIndex)).toInt());
if (state==RecordBase::State_Deleted)
continue;
// check other columns (only relevant for a subset of the tables)
int dialogueTypeIndex = model.searchColumnIndex (Columns::ColumnId_DialogueType);
if (dialogueTypeIndex!=-1)
{
int type = model.data (model.index (row, dialogueTypeIndex)).toInt();
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
continue;
}
result.push_back (*iter);
}
return result;
}
std::vector<std::string> CSMWorld::CommandDispatcher::getRevertableRecords() const
{
std::vector<std::string> result;
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
/// \todo Reverting temporarily disabled on tables that support reordering, because
/// revert logic currently can not handle reordering.
if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic)
return result;
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
iter!=mSelection.end(); ++iter)
{
int row = model.getModelIndex (*iter, 0).row();
// check record state
RecordBase::State state = static_cast<RecordBase::State> (
model.data (model.index (row, stateColumnIndex)).toInt());
if (state==RecordBase::State_BaseOnly)
continue;
result.push_back (*iter);
}
return result;
}
CSMWorld::CommandDispatcher::CommandDispatcher (CSMDoc::Document& document,
const CSMWorld::UniversalId& id, QObject *parent)
: QObject (parent), mDocument (document), mId (id), mLocked (false)
{}
void CSMWorld::CommandDispatcher::setEditLock (bool locked)
{
mLocked = locked;
}
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
{
mSelection = selection;
std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::toLower);
std::sort (mSelection.begin(), mSelection.end());
}
void CSMWorld::CommandDispatcher::setExtendedTypes (const std::vector<UniversalId>& types)
{
mExtendedTypes = types;
}
bool CSMWorld::CommandDispatcher::canDelete() const
{
if (mLocked)
return false;
return getDeletableRecords().size()!=0;
}
bool CSMWorld::CommandDispatcher::canRevert() const
{
if (mLocked)
return false;
return getRevertableRecords().size()!=0;
}
std::vector<CSMWorld::UniversalId> CSMWorld::CommandDispatcher::getExtendedTypes() const
{
std::vector<CSMWorld::UniversalId> tables;
if (mId==UniversalId::Type_Cells)
{
tables.push_back (mId);
tables.push_back (UniversalId::Type_References);
/// \todo add other cell-specific types
}
return tables;
}
void CSMWorld::CommandDispatcher::executeDelete()
{
if (mLocked)
return;
std::vector<std::string> rows = getDeletableRecords();
if (rows.empty())
return;
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
if (rows.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id));
}
if (rows.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeRevert()
{
if (mLocked)
return;
std::vector<std::string> rows = getRevertableRecords();
if (rows.empty())
return;
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
if (rows.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id));
}
if (rows.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedDelete()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended delete of multiple records"));
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
{
if (*iter==mId)
executeDelete();
else if (*iter==UniversalId::Type_References)
{
IdTable& model = dynamic_cast<IdTable&> (
*mDocument.getData().getTableModel (*iter));
const RefCollection& collection = mDocument.getData().getReferences();
int size = collection.getSize();
for (int i=size-1; i>=0; --i)
{
const Record<CellRef>& record = collection.getRecord (i);
if (record.mState==RecordBase::State_Deleted)
continue;
if (!std::binary_search (mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::DeleteCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedRevert()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended revert of multiple records"));
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
{
if (*iter==mId)
executeRevert();
else if (*iter==UniversalId::Type_References)
{
IdTable& model = dynamic_cast<IdTable&> (
*mDocument.getData().getTableModel (*iter));
const RefCollection& collection = mDocument.getData().getReferences();
int size = collection.getSize();
for (int i=size-1; i>=0; --i)
{
const Record<CellRef>& record = collection.getRecord (i);
if (!std::binary_search (mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::RevertCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}

@ -0,0 +1,69 @@
#ifndef CSM_WOLRD_COMMANDDISPATCHER_H
#define CSM_WOLRD_COMMANDDISPATCHER_H
#include <vector>
#include <QObject>
#include "universalid.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class CommandDispatcher : public QObject
{
Q_OBJECT
bool mLocked;
CSMDoc::Document& mDocument;
UniversalId mId;
std::vector<std::string> mSelection;
std::vector<UniversalId> mExtendedTypes;
std::vector<std::string> getDeletableRecords() const;
std::vector<std::string> getRevertableRecords() const;
public:
CommandDispatcher (CSMDoc::Document& document, const CSMWorld::UniversalId& id,
QObject *parent = 0);
///< \param id ID of the table the commands should operate on primarily.
void setEditLock (bool locked);
void setSelection (const std::vector<std::string>& selection);
void setExtendedTypes (const std::vector<UniversalId>& types);
///< Set record lists selected by the user for extended operations.
bool canDelete() const;
bool canRevert() const;
/// Return IDs of the record collection that can also be affected when
/// operating on the record collection this dispatcher is used for.
///
/// \note The returned collection contains the ID of the record collection this
/// dispatcher is used for. However if that record collection does not support
/// the extended mode, the returned vector will be empty instead.
std::vector<UniversalId> getExtendedTypes() const;
public slots:
void executeDelete();
void executeRevert();
void executeExtendedDelete();
void executeExtendedRevert();
};
}
#endif

@ -10,13 +10,12 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI
const QVariant& new_, QUndoCommand* parent)
: QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_)
{
mOld = mModel.data (mIndex, Qt::EditRole);
setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
}
void CSMWorld::ModifyCommand::redo()
{
mOld = mModel.data (mIndex, Qt::EditRole);
mModel.setData (mIndex, mNew);
}
@ -25,6 +24,13 @@ void CSMWorld::ModifyCommand::undo()
mModel.setData (mIndex, mOld);
}
void CSMWorld::CreateCommand::applyModifications()
{
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
}
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent)
: QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None)
{
@ -44,9 +50,7 @@ void CSMWorld::CreateCommand::setType (UniversalId::Type type)
void CSMWorld::CreateCommand::redo()
{
mModel.addRecord (mId, mType);
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
applyModifications();
}
void CSMWorld::CreateCommand::undo()
@ -148,27 +152,22 @@ void CSMWorld::ReorderRowsCommand::undo()
CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model,
const std::string& idOrigin,
const std::string& IdDestination,
const std::string& idDestination,
const CSMWorld::UniversalId::Type type,
QUndoCommand* parent) :
QUndoCommand (parent),
mModel (model),
mIdOrigin (idOrigin),
mIdDestination (Misc::StringUtils::lowerCase (IdDestination)),
mType (type)
QUndoCommand* parent)
: CreateCommand (model, idDestination, parent), mIdOrigin (idOrigin)
{
setText ( ("Clone record " + idOrigin + " to the " + IdDestination).c_str());
setType (type);
setText ( ("Clone record " + idOrigin + " to the " + idDestination).c_str());
}
void CSMWorld::CloneCommand::redo()
{
mModel.cloneRecord (mIdOrigin, mIdDestination, mType);
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter != mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mIdDestination, iter->first), iter->second);
mModel.cloneRecord (mIdOrigin, mId, mType);
applyModifications();
}
void CSMWorld::CloneCommand::undo()
{
mModel.removeRow (mModel.getModelIndex (mIdDestination, 0).row());
mModel.removeRow (mModel.getModelIndex (mId, 0).row());
}

@ -39,40 +39,44 @@ namespace CSMWorld
virtual void undo();
};
class CloneCommand : public QUndoCommand
class CreateCommand : public QUndoCommand
{
std::map<int, QVariant> mValues;
protected:
IdTable& mModel;
std::string mIdOrigin;
std::string mIdDestination;
std::string mId;
UniversalId::Type mType;
std::map<int, QVariant> mValues;
protected:
/// Apply modifications set via addValue.
void applyModifications();
public:
CloneCommand (IdTable& model, const std::string& idOrigin,
const std::string& IdDestination,
const UniversalId::Type type,
QUndoCommand* parent = 0);
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
void setType (UniversalId::Type type);
void addValue (int column, const QVariant& value);
virtual void redo();
virtual void undo();
};
class CreateCommand : public QUndoCommand
class CloneCommand : public CreateCommand
{
IdTable& mModel;
std::string mId;
UniversalId::Type mType;
std::map<int, QVariant> mValues;
std::string mIdOrigin;
public:
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
void setType (UniversalId::Type type);
void addValue (int column, const QVariant& value);
CloneCommand (IdTable& model, const std::string& idOrigin,
const std::string& IdDestination,
const UniversalId::Type type,
QUndoCommand* parent = 0);
virtual void redo();

@ -15,12 +15,15 @@
#include "columnimp.hpp"
#include "regionmap.hpp"
#include "columns.hpp"
#include "resourcesmanager.hpp"
#include "resourcetable.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2, bool update)
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
{
mModels.push_back (model);
mModelIndex.insert (std::make_pair (type1, model));
mModelIndex.insert (std::make_pair (type, model));
UniversalId::Type type2 = UniversalId::getParentType (type);
if (type2!=UniversalId::Type_None)
mModelIndex.insert (std::make_pair (type2, model));
@ -55,8 +58,9 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
return number;
}
CSMWorld::Data::Data (ToUTF8::FromType encoding)
: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0)
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
mResourcesManager (resourcesManager), mReader (0), mDialogue (0), mReaderIndex(0)
{
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
@ -67,7 +71,6 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>);
mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>);
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
@ -101,7 +104,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mFactions.addColumn (new AttributesColumn<ESM::Faction> (0));
mFactions.addColumn (new AttributesColumn<ESM::Faction> (1));
mFactions.addColumn (new HiddenColumn<ESM::Faction>);
for (int i=0; i<6; ++i)
for (int i=0; i<7; ++i)
mFactions.addColumn (new SkillsColumn<ESM::Faction> (i));
mRaces.addColumn (new StringIdColumn<ESM::Race>);
@ -127,7 +130,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mScripts.addColumn (new StringIdColumn<ESM::Script>);
mScripts.addColumn (new RecordStateColumn<ESM::Script>);
mScripts.addColumn (new FixedRecordTypeColumn<ESM::Script> (UniversalId::Type_Script));
mScripts.addColumn (new ScriptColumn<ESM::Script>);
mScripts.addColumn (new ScriptColumn<ESM::Script> (ScriptColumn<ESM::Script>::Type_File));
mRegions.addColumn (new StringIdColumn<ESM::Region>);
mRegions.addColumn (new RecordStateColumn<ESM::Region>);
@ -182,7 +185,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mJournalInfos.addColumn (new StringIdColumn<Info> (true));
mJournalInfos.addColumn (new RecordStateColumn<Info>);
mJournalInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_Journal));
mJournalInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_JournalInfo));
mJournalInfos.addColumn (new TopicColumn<Info> (true));
mJournalInfos.addColumn (new QuestStatusTypeColumn<Info>);
mJournalInfos.addColumn (new QuestIndexColumn<Info>);
@ -196,6 +199,60 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>);
mCells.addColumn (new RefNumCounterColumn<Cell>);
mEnchantments.addColumn (new StringIdColumn<ESM::Enchantment>);
mEnchantments.addColumn (new RecordStateColumn<ESM::Enchantment>);
mEnchantments.addColumn (new FixedRecordTypeColumn<ESM::Enchantment> (UniversalId::Type_Enchantment));
mEnchantments.addColumn (new EnchantmentTypeColumn<ESM::Enchantment>);
mEnchantments.addColumn (new CostColumn<ESM::Enchantment>);
mEnchantments.addColumn (new ChargesColumn2<ESM::Enchantment>);
mEnchantments.addColumn (new AutoCalcColumn<ESM::Enchantment>);
mBodyParts.addColumn (new StringIdColumn<ESM::BodyPart>);
mBodyParts.addColumn (new RecordStateColumn<ESM::BodyPart>);
mBodyParts.addColumn (new FixedRecordTypeColumn<ESM::BodyPart> (UniversalId::Type_BodyPart));
mBodyParts.addColumn (new BodyPartTypeColumn<ESM::BodyPart>);
mBodyParts.addColumn (new VampireColumn<ESM::BodyPart>);
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female));
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Playable, ESM::BodyPart::BPF_NotPlayable, true));
mBodyParts.addColumn (new MeshTypeColumn<ESM::BodyPart>);
mBodyParts.addColumn (new ModelColumn<ESM::BodyPart>);
mBodyParts.addColumn (new RaceColumn<ESM::BodyPart>);
mSoundGens.addColumn (new StringIdColumn<ESM::SoundGenerator>);
mSoundGens.addColumn (new RecordStateColumn<ESM::SoundGenerator>);
mSoundGens.addColumn (new FixedRecordTypeColumn<ESM::SoundGenerator> (UniversalId::Type_SoundGen));
mSoundGens.addColumn (new CreatureColumn<ESM::SoundGenerator>);
mSoundGens.addColumn (new SoundColumn<ESM::SoundGenerator>);
mSoundGens.addColumn (new SoundGeneratorTypeColumn<ESM::SoundGenerator>);
mMagicEffects.addColumn (new StringIdColumn<ESM::MagicEffect>);
mMagicEffects.addColumn (new RecordStateColumn<ESM::MagicEffect>);
mMagicEffects.addColumn (new FixedRecordTypeColumn<ESM::MagicEffect> (UniversalId::Type_MagicEffect));
mMagicEffects.addColumn (new SchoolColumn<ESM::MagicEffect>);
mMagicEffects.addColumn (new BaseCostColumn<ESM::MagicEffect>);
mMagicEffects.addColumn (new EffectTextureColumn<ESM::MagicEffect> (Columns::ColumnId_Icon));
mMagicEffects.addColumn (new EffectTextureColumn<ESM::MagicEffect> (Columns::ColumnId_Particle));
mMagicEffects.addColumn (new EffectObjectColumn<ESM::MagicEffect> (Columns::ColumnId_CastingObject));
mMagicEffects.addColumn (new EffectObjectColumn<ESM::MagicEffect> (Columns::ColumnId_HitObject));
mMagicEffects.addColumn (new EffectObjectColumn<ESM::MagicEffect> (Columns::ColumnId_AreaObject));
mMagicEffects.addColumn (new EffectObjectColumn<ESM::MagicEffect> (Columns::ColumnId_BoltObject));
mMagicEffects.addColumn (new EffectSoundColumn<ESM::MagicEffect> (Columns::ColumnId_CastingSound));
mMagicEffects.addColumn (new EffectSoundColumn<ESM::MagicEffect> (Columns::ColumnId_HitSound));
mMagicEffects.addColumn (new EffectSoundColumn<ESM::MagicEffect> (Columns::ColumnId_AreaSound));
mMagicEffects.addColumn (new EffectSoundColumn<ESM::MagicEffect> (Columns::ColumnId_BoltSound));
mMagicEffects.addColumn (new FlagColumn<ESM::MagicEffect> (
Columns::ColumnId_AllowSpellmaking, ESM::MagicEffect::AllowSpellmaking));
mMagicEffects.addColumn (new FlagColumn<ESM::MagicEffect> (
Columns::ColumnId_AllowEnchanting, ESM::MagicEffect::AllowEnchanting));
mMagicEffects.addColumn (new FlagColumn<ESM::MagicEffect> (
Columns::ColumnId_NegativeLight, ESM::MagicEffect::NegativeLight));
mMagicEffects.addColumn (new DescriptionColumn<ESM::MagicEffect>);
mPathgrids.addColumn (new StringIdColumn<Pathgrid>);
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
mRefs.addColumn (new StringIdColumn<CellRef> (true));
mRefs.addColumn (new RecordStateColumn<CellRef>);
@ -227,34 +284,66 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mRefs.addColumn (new LockLevelColumn<CellRef>);
mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
mFilters.addColumn (new FixedRecordTypeColumn<CSMFilter::Filter> (UniversalId::Type_Filter));
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound);
addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script);
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true),
UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
mRefs.addColumn (new OwnerGlobalColumn<CellRef>);
mRefs.addColumn (new RefNumColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<ESM::Filter>);
mFilters.addColumn (new RecordStateColumn<ESM::Filter>);
mFilters.addColumn (new FixedRecordTypeColumn<ESM::Filter> (UniversalId::Type_Filter));
mFilters.addColumn (new FilterColumn<ESM::Filter>);
mFilters.addColumn (new DescriptionColumn<ESM::Filter>);
mDebugProfiles.addColumn (new StringIdColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new RecordStateColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new FixedRecordTypeColumn<ESM::DebugProfile> (UniversalId::Type_DebugProfile));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_DefaultProfile, ESM::DebugProfile::Flag_Default));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_BypassNewGame, ESM::DebugProfile::Flag_BypassNewGame));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_GlobalProfile, ESM::DebugProfile::Flag_Global));
mDebugProfiles.addColumn (new DescriptionColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
ScriptColumn<ESM::DebugProfile>::Type_Lines));
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
addModel (new IdTable (&mClasses), UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Race);
addModel (new IdTable (&mSounds), UniversalId::Type_Sound);
addModel (new IdTable (&mScripts), UniversalId::Type_Script);
addModel (new IdTable (&mRegions), UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spell);
addModel (new IdTable (&mTopics), UniversalId::Type_Topic);
addModel (new IdTable (&mJournals), UniversalId::Type_Journal);
addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
addModel (new IdTable (&mEnchantments), UniversalId::Type_Enchantment);
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
addModel (new IdTable (&mDebugProfiles), UniversalId::Type_DebugProfile);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Meshes)),
UniversalId::Type_Mesh);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Icons)),
UniversalId::Type_Icon);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Musics)),
UniversalId::Type_Music);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_SoundsRes)),
UniversalId::Type_SoundRes);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Textures)),
UniversalId::Type_Texture);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)),
UniversalId::Type_Video);
}
CSMWorld::Data::~Data()
@ -446,16 +535,91 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences()
return mRefs;
}
const CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters() const
const CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters() const
{
return mFilters;
}
CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters()
{
return mFilters;
}
const CSMWorld::IdCollection<ESM::Enchantment>& CSMWorld::Data::getEnchantments() const
{
return mEnchantments;
}
CSMWorld::IdCollection<ESM::Enchantment>& CSMWorld::Data::getEnchantments()
{
return mEnchantments;
}
const CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts() const
{
return mBodyParts;
}
CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts()
{
return mBodyParts;
}
const CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles() const
{
return mDebugProfiles;
}
CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
{
return mDebugProfiles;
}
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
{
return mLand;
}
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
{
return mLandTextures;
}
const CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens() const
{
return mSoundGens;
}
CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens()
{
return mSoundGens;
}
const CSMWorld::IdCollection<ESM::MagicEffect>& CSMWorld::Data::getMagicEffects() const
{
return mMagicEffects;
}
CSMWorld::IdCollection<ESM::MagicEffect>& CSMWorld::Data::getMagicEffects()
{
return mMagicEffects;
}
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids() const
{
return mPathgrids;
}
CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
{
return mPathgrids;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{
return mResourcesManager.get (id.getType());
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
@ -469,8 +633,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId&
if (id.getType()==UniversalId::Type_RegionMap)
{
RegionMap *table = 0;
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
UniversalId::Type_None, false);
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, false);
return table;
}
throw std::logic_error ("No table model available for " + id.toString());
@ -486,12 +649,17 @@ void CSMWorld::Data::merge()
int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project)
{
delete mReader;
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0;
mDialogue = 0;
mRefLoadCache.clear();
mReader = new ESM::ESMReader;
mReader->setEncoder (&mEncoder);
mReader->setIndex(mReaderIndex++);
mReader->open (path.string());
mBase = base;
@ -510,15 +678,21 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
if (!mReader->hasMoreRecs())
{
delete mReader;
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0;
mDialogue = 0;
mRefLoadCache.clear();
return true;
}
ESM::NAME n = mReader->getRecName();
mReader->getRecHeader();
bool unhandledRecord = false;
switch (n.val)
{
case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break;
@ -532,11 +706,22 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_REGN: mRegions.load (*mReader, mBase); break;
case ESM::REC_BSGN: mBirthsigns.load (*mReader, mBase); break;
case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break;
case ESM::REC_ENCH: mEnchantments.load (*mReader, mBase); break;
case ESM::REC_BODY: mBodyParts.load (*mReader, mBase); break;
case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break;
case ESM::REC_MGEF: mMagicEffects.load (*mReader, mBase); break;
case ESM::REC_PGRD: mPathgrids.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
case ESM::REC_LAND: mLand.load(*mReader, mBase); break;
case ESM::REC_CELL:
{
mCells.load (*mReader, mBase);
mRefs.load (*mReader, mCells.getSize()-1, mBase);
std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (mCells.getSize()-1));
mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId], messages);
break;
}
case ESM::REC_ACTI: mReferenceables.load (*mReader, mBase, UniversalId::Type_Activator); break;
case ESM::REC_ALCH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Potion); break;
@ -624,19 +809,33 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_FILT:
if (mProject)
if (!mProject)
{
unhandledRecord = true;
break;
}
mFilters.load (*mReader, mBase);
mFilters.setData (mFilters.getSize()-1,
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
static_cast<int> (CSMFilter::Filter::Scope_Project));
break;
case ESM::REC_DBGP:
if (!mProject)
{
unhandledRecord = true;
break;
}
// fall through (filter record in a content file is an error with format 0)
mDebugProfiles.load (*mReader, mBase);
break;
default:
unhandledRecord = true;
}
if (unhandledRecord)
{
messages.push_back (std::make_pair (UniversalId::Type_None,
"Unsupported record type: " + n.toString()));
@ -663,6 +862,10 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getTopics().searchId (id)!=-1 ||
getJournals().searchId (id)!=-1 ||
getCells().searchId (id)!=-1 ||
getEnchantments().searchId (id)!=-1 ||
getBodyParts().searchId (id)!=-1 ||
getSoundGens().searchId (id)!=-1 ||
getMagicEffects().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1;
}
@ -681,7 +884,14 @@ int CSMWorld::Data::count (RecordBase::State state) const
count (state, mBirthsigns) +
count (state, mSpells) +
count (state, mCells) +
count (state, mReferenceables);
count (state, mEnchantments) +
count (state, mBodyParts) +
count (state, mLand) +
count (state, mLandTextures) +
count (state, mSoundGens) +
count (state, mMagicEffects) +
count (state, mReferenceables) +
count (state, mPathgrids);
}
void CSMWorld::Data::setDescription (const std::string& description)
@ -721,6 +931,10 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
appendIds (ids, mTopics, listDeleted);
appendIds (ids, mJournals, listDeleted);
appendIds (ids, mCells, listDeleted);
appendIds (ids, mEnchantments, listDeleted);
appendIds (ids, mBodyParts, listDeleted);
appendIds (ids, mSoundGens, listDeleted);
appendIds (ids, mMagicEffects, listDeleted);
appendIds (ids, mReferenceables, listDeleted);
std::sort (ids.begin(), ids.end());

@ -21,19 +21,27 @@
#include <components/esm/loadbsgn.hpp>
#include <components/esm/loadspel.hpp>
#include <components/esm/loaddial.hpp>
#include <components/esm/loadench.hpp>
#include <components/esm/loadbody.hpp>
#include <components/esm/loadsndg.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "../filter/filter.hpp"
#include "../doc/stage.hpp"
#include "idcollection.hpp"
#include "universalid.hpp"
#include "cell.hpp"
#include "land.hpp"
#include "landtexture.hpp"
#include "refidcollection.hpp"
#include "refcollection.hpp"
#include "infocollection.hpp"
#include "pathgrid.hpp"
#include "subcellcollection.hpp"
class QAbstractItemModel;
@ -45,6 +53,9 @@ namespace ESM
namespace CSMWorld
{
class ResourcesManager;
class Resources;
class Data : public QObject
{
Q_OBJECT
@ -63,12 +74,21 @@ namespace CSMWorld
IdCollection<ESM::Spell> mSpells;
IdCollection<ESM::Dialogue> mTopics;
IdCollection<ESM::Dialogue> mJournals;
IdCollection<ESM::Enchantment> mEnchantments;
IdCollection<ESM::BodyPart> mBodyParts;
IdCollection<ESM::MagicEffect> mMagicEffects;
SubCellCollection<Pathgrid> mPathgrids;
IdCollection<ESM::DebugProfile> mDebugProfiles;
IdCollection<ESM::SoundGenerator> mSoundGens;
InfoCollection mTopicInfos;
InfoCollection mJournalInfos;
IdCollection<Cell> mCells;
IdCollection<LandTexture> mLandTextures;
IdCollection<Land> mLand;
RefIdCollection mReferenceables;
RefCollection mRefs;
IdCollection<CSMFilter::Filter> mFilters;
IdCollection<ESM::Filter> mFilters;
const ResourcesManager& mResourcesManager;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
std::string mAuthor;
@ -77,13 +97,17 @@ namespace CSMWorld
const ESM::Dialogue *mDialogue; // last loaded dialogue
bool mBase;
bool mProject;
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
int mReaderIndex;
std::vector<boost::shared_ptr<ESM::ESMReader> > mReaders;
// not implemented
Data (const Data&);
Data& operator= (const Data&);
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
void addModel (QAbstractItemModel *model, UniversalId::Type type,
bool update = true);
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted);
@ -93,7 +117,7 @@ namespace CSMWorld
public:
Data (ToUTF8::FromType encoding);
Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager);
virtual ~Data();
@ -169,9 +193,40 @@ namespace CSMWorld
RefCollection& getReferences();
const IdCollection<CSMFilter::Filter>& getFilters() const;
const IdCollection<ESM::Filter>& getFilters() const;
IdCollection<ESM::Filter>& getFilters();
const IdCollection<ESM::Enchantment>& getEnchantments() const;
IdCollection<ESM::Enchantment>& getEnchantments();
const IdCollection<ESM::BodyPart>& getBodyParts() const;
IdCollection<ESM::BodyPart>& getBodyParts();
const IdCollection<ESM::DebugProfile>& getDebugProfiles() const;
IdCollection<ESM::DebugProfile>& getDebugProfiles();
const IdCollection<CSMWorld::Land>& getLand() const;
const IdCollection<CSMWorld::LandTexture>& getLandTextures() const;
const IdCollection<ESM::SoundGenerator>& getSoundGens() const;
IdCollection<ESM::SoundGenerator>& getSoundGens();
const IdCollection<ESM::MagicEffect>& getMagicEffects() const;
IdCollection<ESM::MagicEffect>& getMagicEffects();
const SubCellCollection<Pathgrid>& getPathgrids() const;
SubCellCollection<Pathgrid>& getPathgrids();
IdCollection<CSMFilter::Filter>& getFilters();
/// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const;
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.

@ -11,11 +11,16 @@ namespace CSMWorld
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
{
virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader);
public:
void load (ESM::ESMReader& reader, bool base);
void load (const ESXRecordT& record, bool base);
/// \param index Index at which the record can be found.
/// Special values: -2 index unknown, -1 record does not exist yet and therefore
/// does not have an index
void load (const ESXRecordT& record, bool base, int index = -2);
bool tryDelete (const std::string& id);
///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored.
@ -23,6 +28,13 @@ namespace CSMWorld
/// \return Has the ID been deleted?
};
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::loadRecord (ESXRecordT& record,
ESM::ESMReader& reader)
{
record.load (reader);
}
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
{
@ -56,17 +68,36 @@ namespace CSMWorld
else
{
ESXRecordT record;
int index = this->searchId (id);
if (index==-1)
IdAccessorT().getId (record) = id;
record.load (reader);
else
{
record = this->getRecord (index).get();
}
loadRecord (record, reader);
if (index==-1)
{
std::string newId = IdAccessorT().getId(record);
int newIndex = this->searchId(newId);
if (newIndex != -1 && id != newId)
index = newIndex;
}
load (record, base);
load (record, base, index);
}
}
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base)
void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base,
int index)
{
int index = this->searchId (IdAccessorT().getId (record));
if (index==-2)
index = this->searchId (IdAccessorT().getId (record));
if (index==-1)
{

@ -4,9 +4,8 @@
#include "collectionbase.hpp"
#include "columnbase.hpp"
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
Viewing viewing, bool preview)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
: IdTableBase (features), mIdCollection (idCollection)
{}
CSMWorld::IdTable::~IdTable()
@ -30,7 +29,7 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const
QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
{
if (role!=Qt::DisplayRole && role!=Qt::EditRole)
if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0)
return QVariant();
if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable())
@ -186,27 +185,12 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector<int>& newO
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
}
CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const
{
return mReordering;
}
CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
{
return mViewing;
}
bool CSMWorld::IdTable::hasPreview() const
{
return mPreview;
}
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
{
std::string id;
std::string hint;
if (mViewing==Viewing_Cell)
if (getFeatures() & Feature_ViewCell)
{
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
@ -217,7 +201,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
}
}
else if (mViewing==Viewing_Id)
else if (getFeatures() & Feature_ViewId)
{
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
@ -237,6 +221,11 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
}
bool CSMWorld::IdTable::isDeleted (const std::string& id) const
{
return getRecord (id).isDeleted();
}
int CSMWorld::IdTable::getColumnId(int column) const
{
return mIdCollection->getColumn(column).getId();

@ -3,8 +3,7 @@
#include <vector>
#include <QAbstractItemModel>
#include "idtablebase.hpp"
#include "universalid.hpp"
#include "columns.hpp"
@ -13,33 +12,13 @@ namespace CSMWorld
class CollectionBase;
class RecordBase;
class IdTable : public QAbstractItemModel
class IdTable : public IdTableBase
{
Q_OBJECT
public:
enum Reordering
{
Reordering_None,
Reordering_WithinTopic
};
enum Viewing
{
Viewing_None,
Viewing_Id, // use ID column to generate view request (ID is transformed into
// worldspace and original ID is passed as hint with c: prefix)
Viewing_Cell // use cell column to generate view request (cell ID is transformed
// into worldspace and record ID is passed as hint with r: prefix)
};
private:
CollectionBase *mIdCollection;
Reordering mReordering;
Viewing mViewing;
bool mPreview;
// not implemented
IdTable (const IdTable&);
@ -47,8 +26,7 @@ namespace CSMWorld
public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
Viewing viewing = Viewing_None, bool preview = false);
IdTable (CollectionBase *idCollection, unsigned int features = 0);
///< The ownership of \a idCollection is not transferred.
virtual ~IdTable();
@ -79,17 +57,17 @@ namespace CSMWorld
const std::string& destination,
UniversalId::Type type = UniversalId::Type_None);
QModelIndex getModelIndex (const std::string& id, int column) const;
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
void setRecord (const std::string& id, const RecordBase& record);
///< Add record or overwrite existing recrod.
const RecordBase& getRecord (const std::string& id) const;
int searchColumnIndex (Columns::ColumnId id) const;
virtual int searchColumnIndex (Columns::ColumnId id) const;
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
int findColumnIndex (Columns::ColumnId id) const;
virtual int findColumnIndex (Columns::ColumnId id) const;
///< Return index of column with the given \a id. If no such column exists, an exception is
/// thrown.
@ -97,16 +75,13 @@ namespace CSMWorld
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
Reordering getReordering() const;
Viewing getViewing() const;
bool hasPreview() const;
std::pair<UniversalId, std::string> view (int row) const;
virtual std::pair<UniversalId, std::string> view (int row) const;
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
/// supported by this table, return (UniversalId::Type_None, "").
/// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const;
int getColumnId(int column) const;
};
}

@ -0,0 +1,9 @@
#include "idtablebase.hpp"
CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features) {}
unsigned int CSMWorld::IdTableBase::getFeatures() const
{
return mFeatures;
}

@ -0,0 +1,67 @@
#ifndef CSM_WOLRD_IDTABLEBASE_H
#define CSM_WOLRD_IDTABLEBASE_H
#include <QAbstractItemModel>
#include "columns.hpp"
namespace CSMWorld
{
class UniversalId;
class IdTableBase : public QAbstractItemModel
{
Q_OBJECT
public:
enum Features
{
Feature_ReorderWithinTopic = 1,
/// Use ID column to generate view request (ID is transformed into
/// worldspace and original ID is passed as hint with c: prefix).
Feature_ViewId = 2,
/// Use cell column to generate view request (cell ID is transformed
/// into worldspace and record ID is passed as hint with r: prefix).
Feature_ViewCell = 4,
Feature_View = Feature_ViewId | Feature_ViewCell,
Feature_Preview = 8,
/// Table can not be modified through ordinary means.
Feature_Constant = 16
};
private:
unsigned int mFeatures;
public:
IdTableBase (unsigned int features);
virtual QModelIndex getModelIndex (const std::string& id, int column) const = 0;
/// Return index of column with the given \a id. If no such column exists, -1 is
/// returned.
virtual int searchColumnIndex (Columns::ColumnId id) const = 0;
/// Return index of column with the given \a id. If no such column exists, an
/// exception is thrown.
virtual int findColumnIndex (Columns::ColumnId id) const = 0;
/// Return the UniversalId and the hint for viewing \a row. If viewing is not
/// supported by this table, return (UniversalId::Type_None, "").
virtual std::pair<UniversalId, std::string> view (int row) const = 0;
/// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const = 0;
unsigned int getFeatures() const;
};
}
#endif

@ -3,7 +3,7 @@
#include <vector>
#include "idtable.hpp"
#include "idtablebase.hpp"
void CSMWorld::IdTableProxyModel::updateColumnMap()
{
@ -13,7 +13,7 @@ void CSMWorld::IdTableProxyModel::updateColumnMap()
{
std::vector<int> columns = mFilter->getReferencedColumns();
const IdTable& table = dynamic_cast<const IdTable&> (*sourceModel());
const IdTableBase& table = dynamic_cast<const IdTableBase&> (*sourceModel());
for (std::vector<int>::const_iterator iter (columns.begin()); iter!=columns.end(); ++iter)
mColumnMap.insert (std::make_pair (*iter,
@ -28,7 +28,7 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelI
return true;
return mFilter->test (
dynamic_cast<IdTable&> (*sourceModel()), sourceRow, mColumnMap);
dynamic_cast<IdTableBase&> (*sourceModel()), sourceRow, mColumnMap);
}
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
@ -39,7 +39,7 @@ CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
{
return mapFromSource (dynamic_cast<IdTable&> (*sourceModel()).getModelIndex (id, column));
return mapFromSource (dynamic_cast<IdTableBase&> (*sourceModel()).getModelIndex (id, column));
}
void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::Node>& filter)
@ -48,3 +48,8 @@ void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::
updateColumnMap();
invalidateFilter();
}
bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
return QSortFilterProxyModel::lessThan(left, right);
}

@ -33,6 +33,10 @@ namespace CSMWorld
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
void setFilter (const boost::shared_ptr<CSMFilter::Node>& filter);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};
}

@ -0,0 +1,28 @@
#include "land.hpp"
#include <sstream>
namespace CSMWorld
{
Land::Land()
{
mLand.reset(new ESM::Land());
}
void Land::load(ESM::ESMReader &esm)
{
mLand->load(esm);
std::ostringstream stream;
stream << "#" << mLand->mX << " " << mLand->mY;
mId = stream.str();
}
void Land::blank()
{
/// \todo
}
}

@ -0,0 +1,29 @@
#ifndef CSM_WORLD_LAND_H
#define CSM_WORLD_LAND_H
#include <string>
#include <boost/shared_ptr.hpp>
#include <components/esm/loadland.hpp>
namespace CSMWorld
{
/// \brief Wrapper for Land record. Encodes X and Y cell index in the ID.
///
/// \todo Add worldspace support to the Land record.
/// \todo Add a proper copy constructor (currently worked around using shared_ptr)
struct Land
{
Land();
boost::shared_ptr<ESM::Land> mLand;
std::string mId;
/// Loads the metadata and ID
void load (ESM::ESMReader &esm);
void blank();
};
}
#endif

@ -0,0 +1,21 @@
#include "landtexture.hpp"
#include <components/esm/esmreader.hpp>
namespace CSMWorld
{
void LandTexture::load(ESM::ESMReader &esm)
{
ESM::LandTexture::load(esm);
int plugin = esm.getIndex();
std::ostringstream stream;
stream << mIndex << "_" << plugin;
mId = stream.str();
}
}

@ -0,0 +1,22 @@
#ifndef CSM_WORLD_LANDTEXTURE_H
#define CSM_WORLD_LANDTEXTURE_H
#include <string>
#include <components/esm/loadltex.hpp>
namespace CSMWorld
{
/// \brief Wrapper for LandTexture record. Encodes mIndex and the plugin index (obtained from ESMReader)
/// in the ID.
///
/// \attention The mId field of the ESM::LandTexture struct is not used.
struct LandTexture : public ESM::LandTexture
{
std::string mId;
void load (ESM::ESMReader &esm);
};
}
#endif

@ -0,0 +1,35 @@
#include "pathgrid.hpp"
#include <sstream>
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm, const IdCollection<Cell>& cells)
{
load (esm);
// correct ID
if (!mId.empty() && mId[0]!='#' && cells.searchId (mId)==-1)
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
}
}
void CSMWorld::Pathgrid::load (ESM::ESMReader &esm)
{
ESM::Pathgrid::load (esm);
if (mCell.empty())
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
}
else
mId = mCell;
}

@ -0,0 +1,28 @@
#ifndef CSM_WOLRD_PATHGRID_H
#define CSM_WOLRD_PATHGRID_H
#include <vector>
#include <string>
#include <components/esm/loadpgrd.hpp>
#include "idcollection.hpp"
#include "cell.hpp"
namespace CSMWorld
{
/// \brief Wrapper for Pathgrid record
///
/// \attention The mData.mX and mData.mY fields of the ESM::Pathgrid struct are not used.
/// Exterior cell coordinates are encoded in the pathgrid ID.
struct Pathgrid : public ESM::Pathgrid
{
std::string mId;
void load (ESM::ESMReader &esm, const IdCollection<Cell>& cells);
void load (ESM::ESMReader &esm);
};
}
#endif

@ -1,12 +1,8 @@
#include "ref.hpp"
#include "cell.hpp"
void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string& id)
CSMWorld::CellRef::CellRef()
{
mId = id;
mCell = cell.mId;
cell.addRef (mId);
mRefNum.mIndex = 0;
mRefNum.mContentFile = 0;
}

@ -3,11 +3,6 @@
#include <components/esm/cellref.hpp>
namespace ESM
{
class ESMReader;
}
namespace CSMWorld
{
class Cell;
@ -18,8 +13,7 @@ namespace CSMWorld
std::string mId;
std::string mCell;
void load (ESM::ESMReader &esm, Cell& cell, const std::string& id);
///< Load cell ref and register it with \a cell.
CellRef();
};
}

@ -3,12 +3,15 @@
#include <sstream>
#include <components/misc/stringops.hpp>
#include "ref.hpp"
#include "cell.hpp"
#include "universalid.hpp"
#include "record.hpp"
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base)
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base,
std::map<ESM::RefNum, std::string>& cache, CSMDoc::Stage::Messages& messages)
{
Record<Cell> cell = mCells.getRecord (cellIndex);
@ -17,19 +20,73 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
CellRef ref;
bool deleted = false;
while (cell2.getNextRef (reader, ref, deleted))
while (ESM::Cell::getNextRef (reader, ref, deleted))
{
ref.mCell = cell2.mId;
/// \todo handle moved references
std::map<ESM::RefNum, std::string>::iterator iter = cache.find (ref.mRefNum);
if (deleted)
{
if (iter==cache.end())
{
/// \todo handle deleted and moved references
ref.load (reader, cell2, getNewId());
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell,
mCells.getId (cellIndex));
Record<CellRef> record2;
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record2.mBase : record2.mModified) = ref;
messages.push_back (std::make_pair (id,
"Attempt to delete a non-existing reference"));
appendRecord (record2);
continue;
}
int index = getIndex (iter->second);
Record<CellRef> record = getRecord (index);
if (record.mState==RecordBase::State_BaseOnly)
{
removeRows (index, 1);
cache.erase (iter);
}
else
{
record.mState = RecordBase::State_Deleted;
setRecord (index, record);
}
mCells.setRecord (cellIndex, cell);
continue;
}
if (iter==cache.end())
{
// new reference
ref.mId = getNewId();
Record<CellRef> record;
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record.mBase : record.mModified) = ref;
appendRecord (record);
cache.insert (std::make_pair (ref.mRefNum, ref.mId));
}
else
{
// old reference -> merge
ref.mId = iter->second;
int index = getIndex (ref.mId);
Record<CellRef> record = getRecord (index);
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_Modified;
(base ? record.mBase : record.mModified) = ref;
setRecord (index, record);
}
}
}
std::string CSMWorld::RefCollection::getNewId()

@ -1,6 +1,10 @@
#ifndef CSM_WOLRD_REFCOLLECTION_H
#define CSM_WOLRD_REFCOLLECTION_H
#include <map>
#include "../doc/stage.hpp"
#include "collection.hpp"
#include "ref.hpp"
#include "record.hpp"
@ -22,7 +26,9 @@ namespace CSMWorld
: mCells (cells), mNextId (0)
{}
void load (ESM::ESMReader& reader, int cellIndex, bool base);
void load (ESM::ESMReader& reader, int cellIndex, bool base,
std::map<ESM::RefNum, std::string>& cache,
CSMDoc::Stage::Messages& messages);
///< Load a sequence of references.
std::string getNewId();

@ -248,6 +248,15 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
if (column==mColumns.mOriginal)
return QString::fromUtf8 (record.get().mOriginal.c_str());
if (column==mColumns.mCombat)
return static_cast<int> (record.get().mData.mCombat);
if (column==mColumns.mMagic)
return static_cast<int> (record.get().mData.mMagic);
if (column==mColumns.mStealth)
return static_cast<int> (record.get().mData.mStealth);
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
@ -271,6 +280,12 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
record.get().mScale = value.toFloat();
else if (column==mColumns.mOriginal)
record.get().mOriginal = value.toString().toUtf8().constData();
else if (column==mColumns.mCombat)
record.get().mData.mCombat = value.toInt();
else if (column==mColumns.mMagic)
record.get().mData.mMagic = value.toInt();
else if (column==mColumns.mStealth)
record.get().mData.mStealth = value.toInt();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =

@ -631,6 +631,9 @@ namespace CSMWorld
const RefIdColumn *mSoul;
const RefIdColumn *mScale;
const RefIdColumn *mOriginal;
const RefIdColumn *mCombat;
const RefIdColumn *mMagic;
const RefIdColumn *mStealth;
CreatureColumns (const ActorColumns& actorColumns);
};

@ -44,7 +44,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true, false));
baseColumns.mModified = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
@ -52,7 +52,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
ModelColumns modelColumns (baseColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_Mesh));
modelColumns.mModel = &mColumns.back();
NameColumns nameColumns (modelColumns);
@ -64,7 +64,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
InventoryColumns inventoryColumns (nameColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_Icon));
inventoryColumns.mIcon = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Weight, ColumnBase::Display_Float));
inventoryColumns.mWeight = &mColumns.back();
@ -175,6 +175,15 @@ CSMWorld::RefIdCollection::RefIdCollection()
creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_String));
creatureColumns.mOriginal = &mColumns.back();
mColumns.push_back (
RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer));
creatureColumns.mCombat = &mColumns.back();
mColumns.push_back (
RefIdColumn (Columns::ColumnId_MagicState, ColumnBase::Display_Integer));
creatureColumns.mMagic = &mColumns.back();
mColumns.push_back (
RefIdColumn (Columns::ColumnId_StealthState, ColumnBase::Display_Integer));
creatureColumns.mStealth = &mColumns.back();
static const struct
{
@ -304,10 +313,17 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float));
weaponColumns.mReach = &mColumns.back();
for (int i=0; i<6; ++i)
for (int i=0; i<3; ++i)
{
const RefIdColumn **column =
i==0 ? weaponColumns.mChop : (i==1 ? weaponColumns.mSlash : weaponColumns.mThrust);
for (int j=0; j<2; ++j)
{
mColumns.push_back (RefIdColumn (Columns::ColumnId_MinChop + i, ColumnBase::Display_Integer));
weaponColumns.mChop[i] = &mColumns.back();
mColumns.push_back (
RefIdColumn (Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer));
column[j] = &mColumns.back();
}
}
static const struct

@ -0,0 +1,103 @@
#include "resources.hpp"
#include <sstream>
#include <stdexcept>
#include <OgreResourceGroupManager.h>
#include <components/misc/stringops.hpp>
CSMWorld::Resources::Resources (const std::string& baseDirectory, UniversalId::Type type,
const char * const *extensions)
: mBaseDirectory (baseDirectory), mType (type)
{
int baseSize = mBaseDirectory.size();
Ogre::StringVector resourcesGroups =
Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
for (Ogre::StringVector::iterator iter (resourcesGroups.begin());
iter!=resourcesGroups.end(); ++iter)
{
if (*iter=="General" || *iter=="Internal" || *iter=="Autodetect")
continue;
Ogre::StringVectorPtr resources =
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 ||
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)
continue;
std::string extension = iter->substr (index+1);
int i = 0;
for (; extensions[i]; ++i)
if (extensions[i]==extension)
break;
if (!extensions[i])
continue;
}
std::string file = iter->substr (baseSize+1);
mFiles.push_back (file);
mIndex.insert (std::make_pair (file, static_cast<int> (mFiles.size())-1));
}
}
}
int CSMWorld::Resources::getSize() const
{
return mFiles.size();
}
std::string CSMWorld::Resources::getId (int index) const
{
return mFiles.at (index);
}
int CSMWorld::Resources::getIndex (const std::string& id) const
{
int index = searchId (id);
if (index==-1)
{
std::ostringstream stream;
stream << "Invalid resource: " << mBaseDirectory << '/' << id;
throw std::runtime_error (stream.str().c_str());
}
return index;
}
int CSMWorld::Resources::searchId (const std::string& id) const
{
std::string id2 = Misc::StringUtils::lowerCase (id);
std::map<std::string, int>::const_iterator iter = mIndex.find (id2);
if (iter==mIndex.end())
return -1;
return iter->second;
}
CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const
{
return mType;
}

@ -0,0 +1,37 @@
#ifndef CSM_WOLRD_RESOURCES_H
#define CSM_WOLRD_RESOURCES_H
#include <string>
#include <map>
#include <vector>
#include "universalid.hpp"
namespace CSMWorld
{
class Resources
{
std::map<std::string, int> mIndex;
std::vector<std::string> mFiles;
std::string mBaseDirectory;
UniversalId::Type mType;
public:
/// \param type Type of resources in this table.
Resources (const std::string& baseDirectory, UniversalId::Type type,
const char * const *extensions = 0);
int getSize() const;
std::string getId (int index) const;
int getIndex (const std::string& id) const;
int searchId (const std::string& id) const;
UniversalId::Type getType() const;
};
}
#endif

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

Loading…
Cancel
Save