forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'refs/remotes/master/master' into NonTableFields
This commit is contained in:
commit
172f1a1301
307 changed files with 7096 additions and 2714 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -41,7 +41,7 @@ resources
|
||||||
## generated objects
|
## generated objects
|
||||||
apps/openmw/config.hpp
|
apps/openmw/config.hpp
|
||||||
components/version/version.hpp
|
components/version/version.hpp
|
||||||
Docs/mainpage.hpp
|
docs/mainpage.hpp
|
||||||
moc_*.cxx
|
moc_*.cxx
|
||||||
*.cxx_parameters
|
*.cxx_parameters
|
||||||
*qrc_launcher.cxx
|
*qrc_launcher.cxx
|
||||||
|
|
|
@ -56,7 +56,7 @@ include(OpenMWMacros)
|
||||||
|
|
||||||
# doxygen main page
|
# 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_SOURCE_DIR}/docs/mainpage.hpp")
|
||||||
|
|
||||||
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
|
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
|
||||||
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
|
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
|
||||||
|
@ -80,13 +80,6 @@ option(USE_FFMPEG "use ffmpeg for sound" ON)
|
||||||
# OS X deployment
|
# OS X deployment
|
||||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
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
|
# Location of morrowind data files
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||||
|
@ -395,46 +388,36 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
IF(NOT WIN32 AND NOT APPLE)
|
IF(NOT WIN32 AND NOT APPLE)
|
||||||
## Debian and non debian Linux building
|
# Linux building
|
||||||
# Paths
|
# Paths
|
||||||
IF (DPKG_PROGRAM)
|
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||||
## Debian specific
|
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||||
SET(CMAKE_INSTALL_PREFIX "/usr")
|
SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||||
SET(DATAROOTDIR "share" CACHE PATH "Sets the root of data directories to a non-default location")
|
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||||
SET(DATADIR "share/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||||
SET(ICONDIR "share/pixmaps" CACHE PATH "Set icon dir")
|
SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config 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(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(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")
|
|
||||||
|
|
||||||
# Install binaries
|
# Install binaries
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||||
IF(BUILD_LAUNCHER)
|
IF(BUILD_LAUNCHER)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_LAUNCHER)
|
ENDIF(BUILD_LAUNCHER)
|
||||||
IF(BUILD_BSATOOL)
|
IF(BUILD_BSATOOL)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_BSATOOL)
|
ENDIF(BUILD_BSATOOL)
|
||||||
IF(BUILD_ESMTOOL)
|
IF(BUILD_ESMTOOL)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_ESMTOOL)
|
ENDIF(BUILD_ESMTOOL)
|
||||||
IF(BUILD_MWINIIMPORTER)
|
IF(BUILD_MWINIIMPORTER)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_MWINIIMPORTER)
|
ENDIF(BUILD_MWINIIMPORTER)
|
||||||
IF(BUILD_OPENCS)
|
IF(BUILD_OPENCS)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_OPENCS)
|
ENDIF(BUILD_OPENCS)
|
||||||
|
|
||||||
# Install licenses
|
# 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" )
|
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||||
ENDIF (DPKG_PROGRAM)
|
|
||||||
|
|
||||||
# Install icon and desktop file
|
# 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")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
|
@ -463,8 +446,8 @@ if(WIN32)
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
||||||
INSTALL(FILES
|
INSTALL(FILES
|
||||||
"${OpenMW_SOURCE_DIR}/readme.txt"
|
"${OpenMW_SOURCE_DIR}/readme.txt"
|
||||||
"${OpenMW_SOURCE_DIR}/GPL3.txt"
|
"${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt"
|
||||||
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
|
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
|
||||||
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
|
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
|
||||||
|
@ -630,8 +613,10 @@ if (WIN32)
|
||||||
4127 # Conditional expression is constant
|
4127 # Conditional expression is constant
|
||||||
4242 # Storing value in a variable of a smaller type, possible loss of data
|
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)
|
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)
|
4305 # Truncating value (double to float, for example)
|
||||||
4309 # Variable overflow, trying to store 128 in a signed char 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
|
4355 # Using 'this' in member initialization list
|
||||||
4505 # Unreferenced local function has been removed
|
4505 # Unreferenced local function has been removed
|
||||||
4701 # Potentially uninitialized local variable used
|
4701 # Potentially uninitialized local variable used
|
||||||
|
@ -650,7 +635,9 @@ if (WIN32)
|
||||||
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
|
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
|
||||||
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS})
|
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS})
|
||||||
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
# oics uses tinyxml, which has an initialized but unused variable
|
||||||
|
set(OICS_WARNINGS "${WARNINGS} /wd4189")
|
||||||
|
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${OICS_WARNINGS})
|
||||||
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
if (BUILD_LAUNCHER)
|
if (BUILD_LAUNCHER)
|
||||||
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
|
|
@ -682,13 +682,11 @@ void Record<ESM::Faction>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Name: " << mData.mName << std::endl;
|
||||||
std::cout << " Hidden: " << mData.mData.mIsHidden << 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])
|
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
|
||||||
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
||||||
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
||||||
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
<< " (" << 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)
|
if (mData.mData.mSkills[i] != -1)
|
||||||
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
|
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
|
||||||
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
|
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
|
||||||
|
|
|
@ -119,10 +119,6 @@ endif(NOT WIN32)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
add_definitions (--coverage)
|
||||||
target_link_libraries(omwlauncher gcov)
|
target_link_libraries(omwlauncher gcov)
|
||||||
|
|
|
@ -22,8 +22,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
||||||
add_definitions (--coverage)
|
add_definitions (--coverage)
|
||||||
target_link_libraries(mwiniimport gcov)
|
target_link_libraries(mwiniimport gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DPKG_PROGRAM)
|
|
||||||
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ opencs_units (view/render
|
||||||
|
|
||||||
opencs_units_noqt (view/render
|
opencs_units_noqt (view/render
|
||||||
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
|
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
|
||||||
lightingbright
|
lightingbright object cell
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/world
|
opencs_units_noqt (view/world
|
||||||
|
@ -200,10 +200,6 @@ target_link_libraries(opencs
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
|
||||||
if(DPKG_PROGRAM)
|
|
||||||
INSTALL(TARGETS opencs RUNTIME DESTINATION games COMPONENT opencs)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -31,8 +31,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con
|
||||||
&mLoader, SLOT (loadDocument (CSMDoc::Document *)));
|
&mLoader, SLOT (loadDocument (CSMDoc::Document *)));
|
||||||
connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)),
|
connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)),
|
||||||
this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)));
|
this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)));
|
||||||
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)),
|
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *, int)),
|
||||||
this, SIGNAL (nextRecord (CSMDoc::Document *)));
|
this, SIGNAL (nextRecord (CSMDoc::Document *, int)));
|
||||||
connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)),
|
connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)),
|
||||||
&mLoader, SLOT (abortLoading (CSMDoc::Document *)));
|
&mLoader, SLOT (abortLoading (CSMDoc::Document *)));
|
||||||
connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
||||||
|
|
|
@ -79,9 +79,10 @@ namespace CSMDoc
|
||||||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
const std::string& error);
|
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);
|
void cancelLoading (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
#include "state.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()
|
CSMDoc::Loader::Loader()
|
||||||
|
@ -39,13 +39,14 @@ void CSMDoc::Loader::load()
|
||||||
Document *document = iter->first;
|
Document *document = iter->first;
|
||||||
|
|
||||||
int size = static_cast<int> (document->getContentFiles().size());
|
int size = static_cast<int> (document->getContentFiles().size());
|
||||||
|
int editedIndex = size-1; // index of the file to be edited/created
|
||||||
|
|
||||||
if (document->isNew())
|
if (document->isNew())
|
||||||
--size;
|
--size;
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
const int batchingSize = 100;
|
const int batchingSize = 50;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -58,17 +59,21 @@ void CSMDoc::Loader::load()
|
||||||
iter->second.mRecordsLeft = false;
|
iter->second.mRecordsLeft = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
++(iter->second.mRecordsLoaded);
|
||||||
|
|
||||||
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||||
|
|
||||||
|
{ // silence a g++ warning
|
||||||
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
|
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
|
||||||
iter!=messages.end(); ++iter)
|
iter!=messages.end(); ++iter)
|
||||||
{
|
{
|
||||||
document->getReport (log)->add (iter->first, iter->second);
|
document->getReport (log)->add (iter->first, iter->second);
|
||||||
emit loadMessage (document, iter->second);
|
emit loadMessage (document, iter->second);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emit nextRecord (document);
|
emit nextRecord (document, iter->second.mRecordsLoaded);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -77,17 +82,19 @@ void CSMDoc::Loader::load()
|
||||||
{
|
{
|
||||||
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
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.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)
|
else if (iter->second.mFile==size)
|
||||||
{
|
{
|
||||||
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
|
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
|
||||||
iter->second.mRecordsLeft = true;
|
iter->second.mRecordsLeft = true;
|
||||||
|
iter->second.mRecordsLoaded = 0;
|
||||||
|
|
||||||
emit nextStage (document, "Project File", steps/batchingSize);
|
emit nextStage (document, "Project File", steps);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace CSMDoc
|
||||||
struct Stage
|
struct Stage
|
||||||
{
|
{
|
||||||
int mFile;
|
int mFile;
|
||||||
|
int mRecordsLoaded;
|
||||||
bool mRecordsLeft;
|
bool mRecordsLeft;
|
||||||
|
|
||||||
Stage();
|
Stage();
|
||||||
|
@ -56,9 +57,10 @@ namespace CSMDoc
|
||||||
///< Document load has been interrupted either because of a call to abortLoading
|
///< 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.
|
/// 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
|
///< \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
|
/// approximately the total number of records divided by the steps value of the
|
||||||
/// previous nextStage signal.
|
/// previous nextStage signal.
|
||||||
|
|
|
@ -42,7 +42,7 @@ void CSMTools::FactionCheckStage::perform (int stage, Messages& messages)
|
||||||
// test for non-unique skill
|
// test for non-unique skill
|
||||||
std::map<int, int> skills; // ID, number of occurrences
|
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)
|
if (faction.mData.mSkills[i]!=-1)
|
||||||
++skills[faction.mData.mSkills[i]];
|
++skills[faction.mData.mSkills[i]];
|
||||||
|
|
||||||
|
@ -54,4 +54,4 @@ void CSMTools::FactionCheckStage::perform (int stage, Messages& messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \todo check data members that can't be edited in the table view
|
/// \todo check data members that can't be edited in the table view
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ namespace CSMWorld
|
||||||
bool hasEnums (ColumnId column);
|
bool hasEnums (ColumnId column);
|
||||||
|
|
||||||
std::vector<std::string> getEnums (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.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
|
||||||
#include "commanddispatcher.hpp"
|
#include "commanddispatcher.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../doc/document.hpp"
|
#include "../doc/document.hpp"
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
|
@ -88,6 +92,13 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked)
|
||||||
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
|
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
|
||||||
{
|
{
|
||||||
mSelection = 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
|
bool CSMWorld::CommandDispatcher::canDelete() const
|
||||||
|
@ -106,6 +117,20 @@ bool CSMWorld::CommandDispatcher::canRevert() const
|
||||||
return getRevertableRecords().size()!=0;
|
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()
|
void CSMWorld::CommandDispatcher::executeDelete()
|
||||||
{
|
{
|
||||||
if (mLocked)
|
if (mLocked)
|
||||||
|
@ -163,3 +188,80 @@ void CSMWorld::CommandDispatcher::executeRevert()
|
||||||
if (rows.size()>1)
|
if (rows.size()>1)
|
||||||
mDocument.getUndoStack().endMacro();
|
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();
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ namespace CSMWorld
|
||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
UniversalId mId;
|
UniversalId mId;
|
||||||
std::vector<std::string> mSelection;
|
std::vector<std::string> mSelection;
|
||||||
|
std::vector<UniversalId> mExtendedTypes;
|
||||||
|
|
||||||
std::vector<std::string> getDeletableRecords() const;
|
std::vector<std::string> getDeletableRecords() const;
|
||||||
|
|
||||||
|
@ -37,16 +38,31 @@ namespace CSMWorld
|
||||||
|
|
||||||
void setSelection (const std::vector<std::string>& selection);
|
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 canDelete() const;
|
||||||
|
|
||||||
bool canRevert() 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:
|
public slots:
|
||||||
|
|
||||||
void executeDelete();
|
void executeDelete();
|
||||||
|
|
||||||
void executeRevert();
|
void executeRevert();
|
||||||
|
|
||||||
|
void executeExtendedDelete();
|
||||||
|
|
||||||
|
void executeExtendedRevert();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
|
||||||
mFactions.addColumn (new AttributesColumn<ESM::Faction> (0));
|
mFactions.addColumn (new AttributesColumn<ESM::Faction> (0));
|
||||||
mFactions.addColumn (new AttributesColumn<ESM::Faction> (1));
|
mFactions.addColumn (new AttributesColumn<ESM::Faction> (1));
|
||||||
mFactions.addColumn (new HiddenColumn<ESM::Faction>);
|
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));
|
mFactions.addColumn (new SkillsColumn<ESM::Faction> (i));
|
||||||
|
|
||||||
mRaces.addColumn (new StringIdColumn<ESM::Race>);
|
mRaces.addColumn (new StringIdColumn<ESM::Race>);
|
||||||
|
@ -742,4 +742,4 @@ void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex&
|
||||||
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
|
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
emit idListChanged();
|
emit idListChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
||||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||||
baseColumns.mId = &mColumns.back();
|
baseColumns.mId = &mColumns.back();
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
|
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();
|
baseColumns.mModified = &mColumns.back();
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType,
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType,
|
||||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||||
|
|
|
@ -45,7 +45,7 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
||||||
mFileProgress->setValue (0);
|
mFileProgress->setValue (0);
|
||||||
|
|
||||||
// record progress
|
// record progress
|
||||||
mLayout->addWidget (new QLabel ("Records", this));
|
mLayout->addWidget (mRecords = new QLabel ("Records", this));
|
||||||
|
|
||||||
mRecordProgress = new QProgressBar (this);
|
mRecordProgress = new QProgressBar (this);
|
||||||
|
|
||||||
|
@ -75,22 +75,30 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
||||||
connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel()));
|
connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps)
|
void CSVDoc::LoadingDocument::nextStage (const std::string& name, int totalRecords)
|
||||||
{
|
{
|
||||||
mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str()));
|
mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str()));
|
||||||
|
|
||||||
mFileProgress->setValue (mFileProgress->value()+1);
|
mFileProgress->setValue (mFileProgress->value()+1);
|
||||||
|
|
||||||
mRecordProgress->setValue (0);
|
mRecordProgress->setValue (0);
|
||||||
mRecordProgress->setMaximum (steps>0 ? steps : 1);
|
mRecordProgress->setMaximum (totalRecords>0 ? totalRecords : 1);
|
||||||
|
|
||||||
|
mTotalRecords = totalRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::LoadingDocument::nextRecord()
|
void CSVDoc::LoadingDocument::nextRecord (int records)
|
||||||
{
|
{
|
||||||
int value = mRecordProgress->value()+1;
|
if (records<=mTotalRecords)
|
||||||
|
{
|
||||||
|
mRecordProgress->setValue (records);
|
||||||
|
|
||||||
if (value<=mRecordProgress->maximum())
|
std::ostringstream stream;
|
||||||
mRecordProgress->setValue (value);
|
|
||||||
|
stream << "Records: " << records << " of " << mTotalRecords;
|
||||||
|
|
||||||
|
mRecords->setText (QString::fromUtf8 (stream.str().c_str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::LoadingDocument::abort (const std::string& error)
|
void CSVDoc::LoadingDocument::abort (const std::string& error)
|
||||||
|
@ -168,20 +176,21 @@ void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name, int steps)
|
void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name,
|
||||||
|
int totalRecords)
|
||||||
{
|
{
|
||||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||||
|
|
||||||
if (iter!=mDocuments.end())
|
if (iter!=mDocuments.end())
|
||||||
iter->second->nextStage (name, steps);
|
iter->second->nextStage (name, totalRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::Loader::nextRecord (CSMDoc::Document *document)
|
void CSVDoc::Loader::nextRecord (CSMDoc::Document *document, int records)
|
||||||
{
|
{
|
||||||
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||||
|
|
||||||
if (iter!=mDocuments.end())
|
if (iter!=mDocuments.end())
|
||||||
iter->second->nextRecord();
|
iter->second->nextRecord (records);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message)
|
void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message)
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace CSVDoc
|
||||||
|
|
||||||
CSMDoc::Document *mDocument;
|
CSMDoc::Document *mDocument;
|
||||||
QLabel *mFile;
|
QLabel *mFile;
|
||||||
|
QLabel *mRecords;
|
||||||
QProgressBar *mFileProgress;
|
QProgressBar *mFileProgress;
|
||||||
QProgressBar *mRecordProgress;
|
QProgressBar *mRecordProgress;
|
||||||
bool mAborted;
|
bool mAborted;
|
||||||
|
@ -33,6 +34,7 @@ namespace CSVDoc
|
||||||
QLabel *mError;
|
QLabel *mError;
|
||||||
QListWidget *mMessages;
|
QListWidget *mMessages;
|
||||||
QVBoxLayout *mLayout;
|
QVBoxLayout *mLayout;
|
||||||
|
int mTotalRecords;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -42,9 +44,9 @@ namespace CSVDoc
|
||||||
|
|
||||||
LoadingDocument (CSMDoc::Document *document);
|
LoadingDocument (CSMDoc::Document *document);
|
||||||
|
|
||||||
void nextStage (const std::string& name, int steps);
|
void nextStage (const std::string& name, int totalRecords);
|
||||||
|
|
||||||
void nextRecord();
|
void nextRecord (int records);
|
||||||
|
|
||||||
void abort (const std::string& error);
|
void abort (const std::string& error);
|
||||||
|
|
||||||
|
@ -88,9 +90,9 @@ namespace CSVDoc
|
||||||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
const std::string& error);
|
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 loadMessage (CSMDoc::Document *document, const std::string& message);
|
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||||
};
|
};
|
||||||
|
|
|
@ -97,8 +97,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||||
&mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&, int)));
|
&mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&, int)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
&mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)),
|
&mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *, int)),
|
||||||
&mLoader, SLOT (nextRecord (CSMDoc::Document *)));
|
&mLoader, SLOT (nextRecord (CSMDoc::Document *, int)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
&mDocumentManager, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
&mDocumentManager, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
||||||
|
|
|
@ -35,7 +35,11 @@ void CSVFilter::FilterBox::setRecordFilter (const std::string& filter)
|
||||||
|
|
||||||
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
|
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
|
||||||
{
|
{
|
||||||
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<CSMWorld::UniversalId> data = mime->getData();
|
||||||
|
|
||||||
emit recordDropped(data, event->proposedAction());
|
emit recordDropped(data, event->proposedAction());
|
||||||
}
|
}
|
||||||
|
@ -54,4 +58,4 @@ void CSVFilter::FilterBox::createFilterRequest (std::vector< std::pair< std::str
|
||||||
Qt::DropAction action)
|
Qt::DropAction action)
|
||||||
{
|
{
|
||||||
mRecordFilterBox->createFilterRequest(filterSource, action);
|
mRecordFilterBox->createFilterRequest(filterSource, action);
|
||||||
}
|
}
|
||||||
|
|
201
apps/opencs/view/render/cell.cpp
Normal file
201
apps/opencs/view/render/cell.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
|
||||||
|
#include "cell.hpp"
|
||||||
|
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
|
||||||
|
bool CSVRender::Cell::removeObject (const std::string& id)
|
||||||
|
{
|
||||||
|
std::map<std::string, Object *>::iterator iter =
|
||||||
|
mObjects.find (Misc::StringUtils::lowerCase (id));
|
||||||
|
|
||||||
|
if (iter==mObjects.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
delete iter->second;
|
||||||
|
mObjects.erase (iter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::addObjects (int start, int end)
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
|
int idColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
int cellColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Cell);
|
||||||
|
int stateColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (int i=start; i<=end; ++i)
|
||||||
|
{
|
||||||
|
std::string cell = Misc::StringUtils::lowerCase (references.data (
|
||||||
|
references.index (i, cellColumn)).toString().toUtf8().constData());
|
||||||
|
|
||||||
|
int state = references.data (references.index (i, stateColumn)).toInt();
|
||||||
|
|
||||||
|
if (cell==mId && state!=CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
std::string id = Misc::StringUtils::lowerCase (references.data (
|
||||||
|
references.index (i, idColumn)).toString().toUtf8().constData());
|
||||||
|
|
||||||
|
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false)));
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
|
||||||
|
const std::string& id, const Ogre::Vector3& origin)
|
||||||
|
: mData (data), mId (Misc::StringUtils::lowerCase (id))
|
||||||
|
{
|
||||||
|
mCellNode = sceneManager->getRootSceneNode()->createChildSceneNode();
|
||||||
|
mCellNode->setPosition (origin);
|
||||||
|
|
||||||
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
|
int rows = references.rowCount();
|
||||||
|
|
||||||
|
addObjects (0, rows-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::Cell::~Cell()
|
||||||
|
{
|
||||||
|
for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
|
||||||
|
iter!=mObjects.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
mCellNode->getCreator()->destroySceneNode (mCellNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
|
||||||
|
iter!=mObjects.end(); ++iter)
|
||||||
|
if (iter->second->referenceableDataChanged (topLeft, bottomRight))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::referenceableAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
|
||||||
|
iter!=mObjects.end(); ++iter)
|
||||||
|
if (iter->second->referenceableAboutToBeRemoved (parent, start, end))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
|
int idColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
int cellColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Cell);
|
||||||
|
int stateColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
||||||
|
|
||||||
|
// list IDs in cell
|
||||||
|
std::map<std::string, bool> ids; // id, deleted state
|
||||||
|
|
||||||
|
for (int i=topLeft.row(); i<=bottomRight.row(); ++i)
|
||||||
|
{
|
||||||
|
std::string cell = Misc::StringUtils::lowerCase (references.data (
|
||||||
|
references.index (i, cellColumn)).toString().toUtf8().constData());
|
||||||
|
|
||||||
|
if (cell==mId)
|
||||||
|
{
|
||||||
|
std::string id = Misc::StringUtils::lowerCase (references.data (
|
||||||
|
references.index (i, idColumn)).toString().toUtf8().constData());
|
||||||
|
|
||||||
|
int state = references.data (references.index (i, stateColumn)).toInt();
|
||||||
|
|
||||||
|
ids.insert (std::make_pair (id, state==CSMWorld::RecordBase::State_Deleted));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform update and remove where needed
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (std::map<std::string, Object *>::iterator iter (mObjects.begin());
|
||||||
|
iter!=mObjects.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (iter->second->referenceDataChanged (topLeft, bottomRight))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
std::map<std::string, bool>::iterator iter2 = ids.find (iter->first);
|
||||||
|
|
||||||
|
if (iter2!=ids.end())
|
||||||
|
{
|
||||||
|
if (iter2->second)
|
||||||
|
{
|
||||||
|
removeObject (iter->first);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ids.erase (iter2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new objects
|
||||||
|
for (std::map<std::string, bool>::iterator iter (ids.begin()); iter!=ids.end(); ++iter)
|
||||||
|
{
|
||||||
|
mObjects.insert (std::make_pair (
|
||||||
|
iter->first, new Object (mData, mCellNode, iter->first, false)));
|
||||||
|
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::referenceAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
|
int idColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (int row = start; row<=end; ++row)
|
||||||
|
if (removeObject (references.data (
|
||||||
|
references.index (row, idColumn)).toString().toUtf8().constData()))
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return addObjects (start, end);
|
||||||
|
}
|
73
apps/opencs/view/render/cell.hpp
Normal file
73
apps/opencs/view/render/cell.hpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef OPENCS_VIEW_CELL_H
|
||||||
|
#define OPENCS_VIEW_CELL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <OgreVector3.h>
|
||||||
|
|
||||||
|
#include "object.hpp"
|
||||||
|
|
||||||
|
class QModelIndex;
|
||||||
|
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class SceneManager;
|
||||||
|
class SceneNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
class Cell
|
||||||
|
{
|
||||||
|
CSMWorld::Data& mData;
|
||||||
|
std::string mId;
|
||||||
|
Ogre::SceneNode *mCellNode;
|
||||||
|
std::map<std::string, Object *> mObjects;
|
||||||
|
|
||||||
|
/// Ignored if cell does not have an object with the given ID.
|
||||||
|
///
|
||||||
|
/// \return Was the object deleted?
|
||||||
|
bool removeObject (const std::string& id);
|
||||||
|
|
||||||
|
/// Add objects from reference table that are within this cell.
|
||||||
|
///
|
||||||
|
/// \return Have any objects been added?
|
||||||
|
bool addObjects (int start, int end);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
|
||||||
|
const std::string& id, const Ogre::Vector3& origin = Ogre::Vector3 (0, 0, 0));
|
||||||
|
|
||||||
|
~Cell();
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this cell?
|
||||||
|
bool referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this cell?
|
||||||
|
bool referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this cell?
|
||||||
|
bool referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this cell?
|
||||||
|
bool referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this cell?
|
||||||
|
bool referenceAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
213
apps/opencs/view/render/object.cpp
Normal file
213
apps/opencs/view/render/object.cpp
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
|
||||||
|
#include "object.hpp"
|
||||||
|
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
#include <OgreEntity.h>
|
||||||
|
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/ref.hpp"
|
||||||
|
#include "../../model/world/refidcollection.hpp"
|
||||||
|
|
||||||
|
void CSVRender::Object::clearSceneNode (Ogre::SceneNode *node)
|
||||||
|
{
|
||||||
|
for (Ogre::SceneNode::ObjectIterator iter = node->getAttachedObjectIterator();
|
||||||
|
iter.hasMoreElements(); )
|
||||||
|
{
|
||||||
|
Ogre::MovableObject* object = dynamic_cast<Ogre::MovableObject*> (iter.getNext());
|
||||||
|
node->getCreator()->destroyMovableObject (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Ogre::SceneNode::ChildNodeIterator iter = node->getChildIterator();
|
||||||
|
iter.hasMoreElements(); )
|
||||||
|
{
|
||||||
|
Ogre::SceneNode* childNode = dynamic_cast<Ogre::SceneNode*> (iter.getNext());
|
||||||
|
clearSceneNode (childNode);
|
||||||
|
node->getCreator()->destroySceneNode (childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Object::clear()
|
||||||
|
{
|
||||||
|
mObject.setNull();
|
||||||
|
|
||||||
|
clearSceneNode (mBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Object::update()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
std::string model;
|
||||||
|
int error = 0; // 1 referemceanöe does not exist, 2 referenceable does not specify a mesh
|
||||||
|
|
||||||
|
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||||
|
|
||||||
|
int index = referenceables.searchId (mReferenceableId);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
error = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// \todo check for Deleted state (error 1)
|
||||||
|
|
||||||
|
model = referenceables.getData (index,
|
||||||
|
referenceables.findColumnIndex (CSMWorld::Columns::ColumnId_Model)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
if (model.empty())
|
||||||
|
error = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
Ogre::Entity* entity = mBase->getCreator()->createEntity (Ogre::SceneManager::PT_CUBE);
|
||||||
|
entity->setMaterialName("BaseWhite"); /// \todo adjust material according to error
|
||||||
|
|
||||||
|
mBase->attachObject (entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mObject = NifOgre::Loader::createObjects (mBase, "Meshes\\" + model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Object::adjust()
|
||||||
|
{
|
||||||
|
if (mReferenceId.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const CSMWorld::CellRef& reference = getReference();
|
||||||
|
|
||||||
|
// position
|
||||||
|
if (!mForceBaseToZero)
|
||||||
|
mBase->setPosition (Ogre::Vector3 (
|
||||||
|
reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
|
||||||
|
|
||||||
|
// orientation
|
||||||
|
Ogre::Quaternion xr (Ogre::Radian (-reference.mPos.rot[0]), Ogre::Vector3::UNIT_X);
|
||||||
|
|
||||||
|
Ogre::Quaternion yr (Ogre::Radian (-reference.mPos.rot[1]), Ogre::Vector3::UNIT_Y);
|
||||||
|
|
||||||
|
Ogre::Quaternion zr (Ogre::Radian (-reference.mPos.rot[2]), Ogre::Vector3::UNIT_Z);
|
||||||
|
|
||||||
|
mBase->setOrientation (xr*yr*zr);
|
||||||
|
|
||||||
|
// scale
|
||||||
|
mBase->setScale (reference.mScale, reference.mScale, reference.mScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::CellRef& CSVRender::Object::getReference() const
|
||||||
|
{
|
||||||
|
if (mReferenceId.empty())
|
||||||
|
throw std::logic_error ("object does not represent a reference");
|
||||||
|
|
||||||
|
return mData.getReferences().getRecord (mReferenceId).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::Object::Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode,
|
||||||
|
const std::string& id, bool referenceable, bool forceBaseToZero)
|
||||||
|
: mData (data), mBase (0), mForceBaseToZero (forceBaseToZero)
|
||||||
|
{
|
||||||
|
mBase = cellNode->createChildSceneNode();
|
||||||
|
|
||||||
|
if (referenceable)
|
||||||
|
{
|
||||||
|
mReferenceableId = id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mReferenceId = id;
|
||||||
|
mReferenceableId = getReference().mRefID;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
adjust();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::Object::~Object()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
if (mBase)
|
||||||
|
mBase->getCreator()->destroySceneNode (mBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||||
|
|
||||||
|
int index = referenceables.searchId (mReferenceableId);
|
||||||
|
|
||||||
|
if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row())
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
adjust();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Object::referenceableAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||||
|
|
||||||
|
int index = referenceables.searchId (mReferenceableId);
|
||||||
|
|
||||||
|
if (index!=-1 && index>=start && index<=end)
|
||||||
|
{
|
||||||
|
// Deletion of referenceable-type objects is handled outside of Object.
|
||||||
|
if (!mReferenceId.empty())
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
adjust();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
if (mReferenceId.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const CSMWorld::RefCollection& references = mData.getReferences();
|
||||||
|
|
||||||
|
int index = references.searchId (mReferenceId);
|
||||||
|
|
||||||
|
if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row())
|
||||||
|
{
|
||||||
|
int columnIndex =
|
||||||
|
references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
|
||||||
|
|
||||||
|
if (columnIndex>=topLeft.column() && columnIndex<=bottomRight.row())
|
||||||
|
{
|
||||||
|
mReferenceableId =
|
||||||
|
references.getData (index, columnIndex).toString().toUtf8().constData();
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
adjust();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSVRender::Object::getReferenceId() const
|
||||||
|
{
|
||||||
|
return mReferenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSVRender::Object::getReferenceableId() const
|
||||||
|
{
|
||||||
|
return mReferenceableId;
|
||||||
|
}
|
80
apps/opencs/view/render/object.hpp
Normal file
80
apps/opencs/view/render/object.hpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef OPENCS_VIEW_OBJECT_H
|
||||||
|
#define OPENCS_VIEW_OBJECT_H
|
||||||
|
|
||||||
|
#include <components/nifogre/ogrenifloader.hpp>
|
||||||
|
|
||||||
|
class QModelIndex;
|
||||||
|
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class SceneNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class Data;
|
||||||
|
class CellRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
class Object
|
||||||
|
{
|
||||||
|
const CSMWorld::Data& mData;
|
||||||
|
std::string mReferenceId;
|
||||||
|
std::string mReferenceableId;
|
||||||
|
Ogre::SceneNode *mBase;
|
||||||
|
NifOgre::ObjectScenePtr mObject;
|
||||||
|
bool mForceBaseToZero;
|
||||||
|
|
||||||
|
/// Not implemented
|
||||||
|
Object (const Object&);
|
||||||
|
|
||||||
|
/// Not implemented
|
||||||
|
Object& operator= (const Object&);
|
||||||
|
|
||||||
|
/// Destroy all scene nodes and movable objects attached to node.
|
||||||
|
static void clearSceneNode (Ogre::SceneNode *node);
|
||||||
|
|
||||||
|
/// Remove object from node (includes deleting)
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Update model
|
||||||
|
void update();
|
||||||
|
|
||||||
|
/// Adjust position, orientation and scale
|
||||||
|
void adjust();
|
||||||
|
|
||||||
|
/// Throws an exception if *this was constructed with referenceable
|
||||||
|
const CSMWorld::CellRef& getReference() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode,
|
||||||
|
const std::string& id, bool referenceable, bool forceBaseToZero = false);
|
||||||
|
/// \param forceBaseToZero If this is a reference ignore the coordinates and place
|
||||||
|
/// it at 0, 0, 0 instead.
|
||||||
|
|
||||||
|
~Object();
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this object?
|
||||||
|
bool referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this object?
|
||||||
|
bool referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
/// \return Did this call result in a modification of the visual representation of
|
||||||
|
/// this object?
|
||||||
|
bool referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
/// Returns an empty string if this is a refereceable-type object.
|
||||||
|
std::string getReferenceId() const;
|
||||||
|
|
||||||
|
std::string getReferenceableId() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,14 +3,137 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <OgreCamera.h>
|
||||||
|
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include <apps/opencs/model/world/tablemimedata.hpp>
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
|
bool CSVRender::PagedWorldspaceWidget::adjustCells()
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
bool setCamera = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
// remove
|
||||||
|
std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
|
||||||
|
while (iter!=mCells.end())
|
||||||
|
{
|
||||||
|
if (!mSelection.has (iter->first))
|
||||||
|
{
|
||||||
|
delete iter->second;
|
||||||
|
mCells.erase (iter++);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCells.begin()==mCells.end())
|
||||||
|
setCamera = true;
|
||||||
|
|
||||||
|
// add
|
||||||
|
for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
if (mCells.find (*iter)==mCells.end())
|
||||||
|
{
|
||||||
|
if (setCamera)
|
||||||
|
{
|
||||||
|
setCamera = false;
|
||||||
|
getCamera()->setPosition (8192*iter->getX()+4096, 8192*iter->getY()+4096, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCells.insert (std::make_pair (*iter,
|
||||||
|
new Cell (mDocument.getData(), getSceneManager(),
|
||||||
|
iter->getId ("std::default"))));
|
||||||
|
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
if (iter->second->referenceableDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceableAboutToBeRemoved (
|
||||||
|
const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
if (iter->second->referenceableAboutToBeRemoved (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceableAdded (const QModelIndex& parent,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
||||||
|
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
{
|
||||||
|
QModelIndex topLeft = referenceables.index (start, 0);
|
||||||
|
QModelIndex bottomRight =
|
||||||
|
referenceables.index (end, referenceables.columnCount());
|
||||||
|
|
||||||
|
if (iter->second->referenceableDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
if (iter->second->referenceDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceAboutToBeRemoved (const QModelIndex& parent,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
if (iter->second->referenceAboutToBeRemoved (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::referenceAdded (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
if (iter->second->referenceAdded (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
|
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
|
||||||
: WorldspaceWidget (document, parent)
|
: WorldspaceWidget (document, parent), mDocument (document)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget()
|
||||||
|
{
|
||||||
|
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
|
||||||
|
iter!=mCells.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
||||||
{
|
{
|
||||||
if (!hint.empty())
|
if (!hint.empty())
|
||||||
|
@ -47,6 +170,10 @@ void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
||||||
void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSelection& selection)
|
void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSelection& selection)
|
||||||
{
|
{
|
||||||
mSelection = selection;
|
mSelection = selection;
|
||||||
|
|
||||||
|
if (adjustCells())
|
||||||
|
flagAsModified();
|
||||||
|
|
||||||
emit cellSelectionChanged (mSelection);
|
emit cellSelectionChanged (mSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +199,9 @@ void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::
|
||||||
}
|
}
|
||||||
if (selectionChanged)
|
if (selectionChanged)
|
||||||
{
|
{
|
||||||
|
if (adjustCells())
|
||||||
|
flagAsModified();
|
||||||
|
|
||||||
emit cellSelectionChanged(mSelection);
|
emit cellSelectionChanged(mSelection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
||||||
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "../../model/world/cellselection.hpp"
|
#include "../../model/world/cellselection.hpp"
|
||||||
|
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
#include "cell.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
|
@ -11,12 +14,32 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
CSMDoc::Document& mDocument;
|
||||||
CSMWorld::CellSelection mSelection;
|
CSMWorld::CellSelection mSelection;
|
||||||
|
std::map<CSMWorld::CellCoordinates, Cell *> mCells;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::pair<int, int> getCoordinatesFromId(const std::string& record) const;
|
std::pair<int, int> getCoordinatesFromId(const std::string& record) const;
|
||||||
|
|
||||||
|
/// Bring mCells into sync with mSelection again.
|
||||||
|
///
|
||||||
|
/// \return Any cells added or removed?
|
||||||
|
bool adjustCells();
|
||||||
|
|
||||||
|
virtual void referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
virtual void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceableAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
virtual void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
|
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
|
||||||
|
@ -24,6 +47,8 @@ namespace CSVRender
|
||||||
/// no cells are displayed. The cells to be displayed will be specified later through
|
/// no cells are displayed. The cells to be displayed will be specified later through
|
||||||
/// hint system.
|
/// hint system.
|
||||||
|
|
||||||
|
virtual ~PagedWorldspaceWidget();
|
||||||
|
|
||||||
void useViewHint (const std::string& hint);
|
void useViewHint (const std::string& hint);
|
||||||
|
|
||||||
void setCellSelection (const CSMWorld::CellSelection& selection);
|
void setCellSelection (const CSMWorld::CellSelection& selection);
|
||||||
|
|
|
@ -7,194 +7,119 @@
|
||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::setup()
|
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
|
||||||
|
const std::string& id, bool referenceable, QWidget *parent)
|
||||||
|
: SceneWidget (parent), mData (data),
|
||||||
|
mObject (data, getSceneManager()->getRootSceneNode(), id, referenceable, true)
|
||||||
{
|
{
|
||||||
setNavigation (&mOrbit);
|
setNavigation (&mOrbit);
|
||||||
|
|
||||||
mNode = getSceneManager()->getRootSceneNode()->createChildSceneNode();
|
|
||||||
mNode->setPosition (Ogre::Vector3 (0, 0, 0));
|
|
||||||
|
|
||||||
setModel();
|
|
||||||
|
|
||||||
QAbstractItemModel *referenceables =
|
QAbstractItemModel *referenceables =
|
||||||
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);
|
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);
|
||||||
|
|
||||||
connect (referenceables, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
connect (referenceables, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
this, SLOT (ReferenceableDataChanged (const QModelIndex&, const QModelIndex&)));
|
this, SLOT (referenceableDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
this, SLOT (ReferenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
this, SLOT (referenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
}
|
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::setModel()
|
if (!referenceable)
|
||||||
{
|
|
||||||
if (mNode)
|
|
||||||
{
|
{
|
||||||
mObject.setNull();
|
QAbstractItemModel *references =
|
||||||
|
mData.getTableModel (CSMWorld::UniversalId::Type_References);
|
||||||
|
|
||||||
if (mReferenceableId.empty())
|
connect (references, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
return;
|
this, SLOT (referenceDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (references, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
int column =
|
this, SLOT (referenceAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
mData.getReferenceables().findColumnIndex (CSMWorld::Columns::ColumnId_Model);
|
|
||||||
|
|
||||||
int row = mData.getReferenceables().searchId (mReferenceableId);
|
|
||||||
|
|
||||||
if (row==-1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QVariant value = mData.getReferenceables().getData (row, column);
|
|
||||||
|
|
||||||
if (!value.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string model = value.toString().toUtf8().constData();
|
|
||||||
|
|
||||||
if (model.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
mObject = NifOgre::Loader::createObjects (mNode, "Meshes\\" + model);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::adjust()
|
void CSVRender::PreviewWidget::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
{
|
|
||||||
if (mNode)
|
|
||||||
{
|
|
||||||
int row = mData.getReferences().getIndex (mReferenceId);
|
|
||||||
|
|
||||||
float scale = mData.getReferences().getData (row, mData.getReferences().
|
|
||||||
findColumnIndex (CSMWorld::Columns::ColumnId_Scale)).toFloat();
|
|
||||||
float rotX = mData.getReferences().getData (row, mData.getReferences().
|
|
||||||
findColumnIndex (CSMWorld::Columns::ColumnId_PositionXRot)).toFloat();
|
|
||||||
float rotY = mData.getReferences().getData (row, mData.getReferences().
|
|
||||||
findColumnIndex (CSMWorld::Columns::ColumnId_PositionYRot)).toFloat();
|
|
||||||
float rotZ = mData.getReferences().getData (row, mData.getReferences().
|
|
||||||
findColumnIndex (CSMWorld::Columns::ColumnId_PositionZRot)).toFloat();
|
|
||||||
|
|
||||||
mNode->setScale (scale, scale, scale);
|
|
||||||
|
|
||||||
Ogre::Quaternion xr (Ogre::Radian(-rotX), Ogre::Vector3::UNIT_X);
|
|
||||||
|
|
||||||
Ogre::Quaternion yr (Ogre::Radian(-rotY), Ogre::Vector3::UNIT_Y);
|
|
||||||
|
|
||||||
Ogre::Quaternion zr (Ogre::Radian(-rotZ), Ogre::Vector3::UNIT_Z);
|
|
||||||
|
|
||||||
mNode->setOrientation (xr*yr*zr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
|
|
||||||
const std::string& referenceableId, QWidget *parent)
|
|
||||||
: SceneWidget (parent), mData (data), mNode (0), mReferenceableId (referenceableId)
|
|
||||||
{
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
|
|
||||||
const std::string& referenceableId, const std::string& referenceId, QWidget *parent)
|
|
||||||
: SceneWidget (parent), mData (data), mReferenceableId (referenceableId),
|
|
||||||
mReferenceId (referenceId)
|
|
||||||
{
|
|
||||||
setup();
|
|
||||||
|
|
||||||
adjust();
|
|
||||||
|
|
||||||
QAbstractItemModel *references =
|
|
||||||
mData.getTableModel (CSMWorld::UniversalId::Type_References);
|
|
||||||
|
|
||||||
connect (references, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
|
||||||
this, SLOT (ReferenceDataChanged (const QModelIndex&, const QModelIndex&)));
|
|
||||||
connect (references, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
|
||||||
this, SLOT (ReferenceAboutToBeRemoved (const QModelIndex&, int, int)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::ReferenceableDataChanged (const QModelIndex& topLeft,
|
|
||||||
const QModelIndex& bottomRight)
|
const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
if (mReferenceableId.empty())
|
if (mObject.referenceableDataChanged (topLeft, bottomRight))
|
||||||
return;
|
|
||||||
|
|
||||||
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
|
||||||
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
|
||||||
|
|
||||||
QModelIndex index = referenceables.getModelIndex (mReferenceableId, 0);
|
|
||||||
|
|
||||||
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
|
|
||||||
{
|
|
||||||
/// \todo possible optimisation; check columns and only update if relevant columns have
|
|
||||||
/// changed
|
|
||||||
setModel();
|
|
||||||
flagAsModified();
|
flagAsModified();
|
||||||
|
|
||||||
|
if (mObject.getReferenceId().empty())
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
||||||
|
|
||||||
|
QModelIndex index = referenceables.getModelIndex (mObject.getReferenceableId(),
|
||||||
|
referenceables.findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
||||||
|
|
||||||
|
if (referenceables.data (index).toInt()==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start,
|
void CSVRender::PreviewWidget::referenceableAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||||
int end)
|
int end)
|
||||||
{
|
{
|
||||||
if (mReferenceableId.empty())
|
if (mObject.referenceableAboutToBeRemoved (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
|
||||||
|
if (mObject.getReferenceableId().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
||||||
|
|
||||||
QModelIndex index = referenceables.getModelIndex (mReferenceableId, 0);
|
QModelIndex index = referenceables.getModelIndex (mObject.getReferenceableId(), 0);
|
||||||
|
|
||||||
if (index.row()>=start && index.row()<=end)
|
if (index.row()>=start && index.row()<=end)
|
||||||
{
|
{
|
||||||
if (mReferenceId.empty())
|
if (mObject.getReferenceId().empty())
|
||||||
{
|
{
|
||||||
// this is a preview for a referenceble
|
// this is a preview for a referenceble
|
||||||
emit closeRequest();
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// this is a preview for a reference
|
|
||||||
mObject.setNull();
|
|
||||||
flagAsModified();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::ReferenceDataChanged (const QModelIndex& topLeft,
|
void CSVRender::PreviewWidget::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
const QModelIndex& bottomRight)
|
const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
if (mReferenceId.empty())
|
if (mObject.referenceDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
|
||||||
|
if (mObject.getReferenceId().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
|
// check for deleted state
|
||||||
|
{
|
||||||
|
QModelIndex index = references.getModelIndex (mObject.getReferenceId(),
|
||||||
|
references.findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
||||||
|
|
||||||
|
if (references.data (index).toInt()==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
emit closeRequest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int columnIndex = references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
|
int columnIndex = references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
|
||||||
|
|
||||||
QModelIndex index = references.getModelIndex (mReferenceId, columnIndex);
|
QModelIndex index = references.getModelIndex (mObject.getReferenceId(), columnIndex);
|
||||||
|
|
||||||
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
|
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
|
||||||
{
|
|
||||||
/// \todo possible optimisation; check columns and only update if relevant columns have
|
|
||||||
/// changed
|
|
||||||
adjust();
|
|
||||||
|
|
||||||
if (index.column()>=topLeft.column() && index.column()<=bottomRight.row())
|
if (index.column()>=topLeft.column() && index.column()<=bottomRight.row())
|
||||||
{
|
emit referenceableIdChanged (mObject.getReferenceableId());
|
||||||
mReferenceableId = references.data (index).toString().toUtf8().constData();
|
|
||||||
emit referenceableIdChanged (mReferenceableId);
|
|
||||||
setModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
flagAsModified();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PreviewWidget::ReferenceAboutToBeRemoved (const QModelIndex& parent, int start,
|
void CSVRender::PreviewWidget::referenceAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||||
int end)
|
int end)
|
||||||
{
|
{
|
||||||
if (mReferenceId.empty())
|
if (mObject.getReferenceId().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||||
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
||||||
|
|
||||||
QModelIndex index = references.getModelIndex (mReferenceId, 0);
|
QModelIndex index = references.getModelIndex (mObject.getReferenceId(), 0);
|
||||||
|
|
||||||
if (index.row()>=start && index.row()<=end)
|
if (index.row()>=start && index.row()<=end)
|
||||||
emit closeRequest();
|
emit closeRequest();
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
|
#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
|
||||||
#define OPENCS_VIEW_PREVIEWWIDGET_H
|
#define OPENCS_VIEW_PREVIEWWIDGET_H
|
||||||
|
|
||||||
#include <components/nifogre/ogrenifloader.hpp>
|
|
||||||
|
|
||||||
#include "scenewidget.hpp"
|
#include "scenewidget.hpp"
|
||||||
|
|
||||||
#include "navigationorbit.hpp"
|
#include "navigationorbit.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
|
@ -22,26 +21,13 @@ namespace CSVRender
|
||||||
|
|
||||||
CSMWorld::Data& mData;
|
CSMWorld::Data& mData;
|
||||||
CSVRender::NavigationOrbit mOrbit;
|
CSVRender::NavigationOrbit mOrbit;
|
||||||
NifOgre::ObjectScenePtr mObject;
|
Object mObject;
|
||||||
Ogre::SceneNode *mNode;
|
|
||||||
std::string mReferenceId;
|
|
||||||
std::string mReferenceableId;
|
|
||||||
|
|
||||||
void setup();
|
|
||||||
|
|
||||||
void setModel();
|
|
||||||
|
|
||||||
void adjust();
|
|
||||||
///< Adjust referenceable preview according to the reference
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
|
PreviewWidget (CSMWorld::Data& data, const std::string& id, bool referenceable,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
|
|
||||||
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
|
|
||||||
const std::string& referenceId, QWidget *parent = 0);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
@ -50,14 +36,14 @@ namespace CSVRender
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void ReferenceableDataChanged (const QModelIndex& topLeft,
|
void referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
const QModelIndex& bottomRight);
|
const QModelIndex& bottomRight);
|
||||||
|
|
||||||
void ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
void ReferenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
void ReferenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace CSVRender
|
||||||
mCamera->setPosition (300, 0, 0);
|
mCamera->setPosition (300, 0, 0);
|
||||||
mCamera->lookAt (0, 0, 0);
|
mCamera->lookAt (0, 0, 0);
|
||||||
mCamera->setNearClipDistance (0.1);
|
mCamera->setNearClipDistance (0.1);
|
||||||
mCamera->setFarClipDistance (30000);
|
mCamera->setFarClipDistance (300000); ///< \todo make this configurable
|
||||||
mCamera->roll (Ogre::Degree (90));
|
mCamera->roll (Ogre::Degree (90));
|
||||||
|
|
||||||
setLighting (&mLightingDay);
|
setLighting (&mLightingDay);
|
||||||
|
@ -87,7 +87,7 @@ namespace CSVRender
|
||||||
|
|
||||||
std::stringstream windowHandle;
|
std::stringstream windowHandle;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
windowHandle << Ogre::StringConverter::toString((unsigned long)(this->winId()));
|
windowHandle << Ogre::StringConverter::toString((uintptr_t)(this->winId()));
|
||||||
#else
|
#else
|
||||||
windowHandle << this->winId();
|
windowHandle << this->winId();
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,6 +137,11 @@ namespace CSVRender
|
||||||
return mSceneMgr;
|
return mSceneMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ogre::Camera *SceneWidget::getCamera()
|
||||||
|
{
|
||||||
|
return mCamera;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneWidget::flagAsModified()
|
void SceneWidget::flagAsModified()
|
||||||
{
|
{
|
||||||
mUpdate = true;
|
mUpdate = true;
|
||||||
|
|
|
@ -49,6 +49,8 @@ namespace CSVRender
|
||||||
|
|
||||||
Ogre::SceneManager *getSceneManager();
|
Ogre::SceneManager *getSceneManager();
|
||||||
|
|
||||||
|
Ogre::Camera *getCamera();
|
||||||
|
|
||||||
void flagAsModified();
|
void flagAsModified();
|
||||||
|
|
||||||
void setDefaultAmbient (const Ogre::ColourValue& colour);
|
void setDefaultAmbient (const Ogre::ColourValue& colour);
|
||||||
|
|
|
@ -21,6 +21,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
|
||||||
setDefaultAmbient (colour);
|
setDefaultAmbient (colour);
|
||||||
|
|
||||||
/// \todo deal with mSunlight and mFog/mForDensity
|
/// \todo deal with mSunlight and mFog/mForDensity
|
||||||
|
|
||||||
|
flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
|
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
|
||||||
|
@ -29,12 +31,17 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string&
|
||||||
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
|
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
|
||||||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
||||||
|
|
||||||
|
mReferenceablesModel = &dynamic_cast<CSMWorld::IdTable&> (
|
||||||
|
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Referenceables));
|
||||||
|
|
||||||
connect (mCellsModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
connect (mCellsModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
this, SLOT (cellDataChanged (const QModelIndex&, const QModelIndex&)));
|
this, SLOT (cellDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
|
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
|
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
|
||||||
|
@ -72,6 +79,62 @@ void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld
|
||||||
mCellId = data.begin()->getId();
|
mCellId = data.begin()->getId();
|
||||||
update();
|
update();
|
||||||
emit cellChanged(*data.begin());
|
emit cellChanged(*data.begin());
|
||||||
|
|
||||||
|
/// \todo replace mCell
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
if (mCell.get()->referenceableDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceableAboutToBeRemoved (
|
||||||
|
const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
if (mCell.get()->referenceableAboutToBeRemoved (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceableAdded (const QModelIndex& parent,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
{
|
||||||
|
QModelIndex topLeft = mReferenceablesModel->index (start, 0);
|
||||||
|
QModelIndex bottomRight =
|
||||||
|
mReferenceablesModel->index (end, mReferenceablesModel->columnCount());
|
||||||
|
|
||||||
|
if (mCell.get()->referenceableDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
if (mCell.get()->referenceDataChanged (topLeft, bottomRight))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceAboutToBeRemoved (const QModelIndex& parent,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
if (mCell.get()->referenceAboutToBeRemoved (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::referenceAdded (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
if (mCell.get())
|
||||||
|
if (mCell.get()->referenceAdded (parent, start, end))
|
||||||
|
flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
|
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
#define OPENCS_VIEW_UNPAGEDWORLDSPACEWIDGET_H
|
#define OPENCS_VIEW_UNPAGEDWORLDSPACEWIDGET_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
|
#include "cell.hpp"
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
|
@ -25,6 +27,8 @@ namespace CSVRender
|
||||||
|
|
||||||
std::string mCellId;
|
std::string mCellId;
|
||||||
CSMWorld::IdTable *mCellsModel;
|
CSMWorld::IdTable *mCellsModel;
|
||||||
|
CSMWorld::IdTable *mReferenceablesModel;
|
||||||
|
std::auto_ptr<Cell> mCell;
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -37,6 +41,21 @@ namespace CSVRender
|
||||||
|
|
||||||
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
virtual void referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
virtual void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceableAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
virtual void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void referenceAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
|
@ -10,15 +10,30 @@
|
||||||
#include "../world/scenetoolmode.hpp"
|
#include "../world/scenetoolmode.hpp"
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
|
|
||||||
CSVRender::WorldspaceWidget::WorldspaceWidget (const CSMDoc::Document& document, QWidget* parent)
|
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
|
||||||
: SceneWidget (parent), mDocument(document)
|
: SceneWidget (parent), mDocument(document)
|
||||||
{
|
{
|
||||||
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
|
|
||||||
ent->setMaterialName("BaseWhite");
|
|
||||||
|
|
||||||
getSceneManager()->getRootSceneNode()->attachObject(ent);
|
|
||||||
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
|
QAbstractItemModel *referenceables =
|
||||||
|
document.getData().getTableModel (CSMWorld::UniversalId::Type_Referenceables);
|
||||||
|
|
||||||
|
connect (referenceables, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (referenceableDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (referenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (referenceables, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (referenceableAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
QAbstractItemModel *references =
|
||||||
|
document.getData().getTableModel (CSMWorld::UniversalId::Type_References);
|
||||||
|
|
||||||
|
connect (references, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (referenceDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (references, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (referenceAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (referenceAdded (const QModelIndex&, int, int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
|
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
|
||||||
|
@ -120,9 +135,11 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||||
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
|
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
|
||||||
{
|
{
|
||||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return;
|
||||||
|
|
||||||
if (mime->fromDocument (mDocument))
|
if (mime->fromDocument (mDocument))
|
||||||
{
|
{
|
||||||
emit dataDropped(mime->getData());
|
emit dataDropped(mime->getData());
|
||||||
} //not handling drops from different documents at the moment
|
} //not handling drops from different documents at the moment
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace CSVRender
|
||||||
ignored //either mixed cells, or not cells
|
ignored //either mixed cells, or not cells
|
||||||
};
|
};
|
||||||
|
|
||||||
WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0);
|
WorldspaceWidget (CSMDoc::Document& document, QWidget *parent = 0);
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
|
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
|
||||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||||
|
@ -79,6 +79,19 @@ namespace CSVRender
|
||||||
|
|
||||||
void selectNavigationMode (const std::string& mode);
|
void selectNavigationMode (const std::string& mode);
|
||||||
|
|
||||||
|
virtual void referenceableDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight) = 0;
|
||||||
|
|
||||||
|
virtual void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end) = 0;
|
||||||
|
|
||||||
|
virtual void referenceableAdded (const QModelIndex& index, int start, int end) = 0;
|
||||||
|
|
||||||
|
virtual void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) = 0;
|
||||||
|
|
||||||
|
virtual void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end) = 0;
|
||||||
|
|
||||||
|
virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
|
|
@ -23,10 +23,10 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
|
||||||
referenceableIdChanged (referenceableId);
|
referenceableIdChanged (referenceableId);
|
||||||
|
|
||||||
mScene =
|
mScene =
|
||||||
new CSVRender::PreviewWidget (document.getData(), referenceableId, id.getId(), this);
|
new CSVRender::PreviewWidget (document.getData(), id.getId(), false, this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this);
|
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), true, this);
|
||||||
|
|
||||||
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
|
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,9 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return;
|
||||||
|
|
||||||
if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region))
|
if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region))
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region));
|
CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region));
|
||||||
|
@ -402,4 +405,4 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
|
||||||
|
|
||||||
mRegionId = record.getId();
|
mRegionId = record.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,19 +45,36 @@ CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& docum
|
||||||
|
|
||||||
void CSVWorld::ScriptEdit::dragEnterEvent (QDragEnterEvent* event)
|
void CSVWorld::ScriptEdit::dragEnterEvent (QDragEnterEvent* event)
|
||||||
{
|
{
|
||||||
setTextCursor (cursorForPosition (event->pos()));
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
event->acceptProposedAction();
|
if (!mime)
|
||||||
|
QTextEdit::dragEnterEvent(event);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setTextCursor (cursorForPosition (event->pos()));
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event)
|
void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event)
|
||||||
{
|
{
|
||||||
setTextCursor (cursorForPosition (event->pos()));
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
event->accept();
|
if (!mime)
|
||||||
|
QTextEdit::dragMoveEvent(event);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setTextCursor (cursorForPosition (event->pos()));
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
|
void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
|
||||||
{
|
{
|
||||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
{
|
||||||
|
QTextEdit::dropEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setTextCursor (cursorForPosition (event->pos()));
|
setTextCursor (cursorForPosition (event->pos()));
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
|
|
||||||
mDispatcher->setSelection (records);
|
mDispatcher->setSelection (records);
|
||||||
|
|
||||||
|
std::vector<CSMWorld::UniversalId> extendedTypes = mDispatcher->getExtendedTypes();
|
||||||
|
|
||||||
|
mDispatcher->setExtendedTypes (extendedTypes);
|
||||||
|
|
||||||
// create context menu
|
// create context menu
|
||||||
QMenu menu (this);
|
QMenu menu (this);
|
||||||
|
|
||||||
|
@ -63,11 +67,21 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
menu.addAction (mCreateAction);
|
menu.addAction (mCreateAction);
|
||||||
|
|
||||||
if (mDispatcher->canRevert())
|
if (mDispatcher->canRevert())
|
||||||
|
{
|
||||||
menu.addAction (mRevertAction);
|
menu.addAction (mRevertAction);
|
||||||
|
|
||||||
|
if (!extendedTypes.empty())
|
||||||
|
menu.addAction (mExtendedRevertAction);
|
||||||
|
}
|
||||||
|
|
||||||
if (mDispatcher->canDelete())
|
if (mDispatcher->canDelete())
|
||||||
|
{
|
||||||
menu.addAction (mDeleteAction);
|
menu.addAction (mDeleteAction);
|
||||||
|
|
||||||
|
if (!extendedTypes.empty())
|
||||||
|
menu.addAction (mExtendedDeleteAction);
|
||||||
|
}
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
||||||
{
|
{
|
||||||
/// \todo allow reordering of multiple rows
|
/// \todo allow reordering of multiple rows
|
||||||
|
@ -101,12 +115,12 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
|
|
||||||
if (selectedRows.size()==1)
|
if (selectedRows.size()==1)
|
||||||
{
|
{
|
||||||
|
int row = selectedRows.begin()->row();
|
||||||
|
|
||||||
|
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View)
|
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View)
|
||||||
{
|
{
|
||||||
int row = selectedRows.begin()->row();
|
|
||||||
|
|
||||||
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
|
||||||
|
|
||||||
CSMWorld::UniversalId id = mModel->view (row).first;
|
CSMWorld::UniversalId id = mModel->view (row).first;
|
||||||
|
|
||||||
int index = mDocument.getData().getCells().searchId (id.getId());
|
int index = mDocument.getData().getCells().searchId (id.getId());
|
||||||
|
@ -118,7 +132,16 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
||||||
menu.addAction (mPreviewAction);
|
{
|
||||||
|
QModelIndex index = mModel->index (row,
|
||||||
|
mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
||||||
|
|
||||||
|
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State> (
|
||||||
|
mModel->data (index).toInt());
|
||||||
|
|
||||||
|
if (state!=CSMWorld::RecordBase::State_Deleted)
|
||||||
|
menu.addAction (mPreviewAction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.exec (event->globalPos());
|
menu.exec (event->globalPos());
|
||||||
|
@ -203,6 +226,18 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
|
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
|
||||||
addAction (mPreviewAction);
|
addAction (mPreviewAction);
|
||||||
|
|
||||||
|
/// \todo add a user option, that redirects the extended action to an input panel (in
|
||||||
|
/// the bottom bar) that lets the user select which record collections should be
|
||||||
|
/// modified.
|
||||||
|
|
||||||
|
mExtendedDeleteAction = new QAction (tr ("Extended Delete Record"), this);
|
||||||
|
connect (mExtendedDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeExtendedDelete()));
|
||||||
|
addAction (mExtendedDeleteAction);
|
||||||
|
|
||||||
|
mExtendedRevertAction = new QAction (tr ("Extended Revert Record"), this);
|
||||||
|
connect (mExtendedRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeExtendedRevert()));
|
||||||
|
addAction (mExtendedRevertAction);
|
||||||
|
|
||||||
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
this, SLOT (tableSizeUpdate()));
|
this, SLOT (tableSizeUpdate()));
|
||||||
|
|
||||||
|
@ -351,7 +386,12 @@ void CSVWorld::Table::previewRecord()
|
||||||
{
|
{
|
||||||
std::string id = getUniversalId (selectedRows.begin()->row()).getId();
|
std::string id = getUniversalId (selectedRows.begin()->row()).getId();
|
||||||
|
|
||||||
emit editRequest (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Preview, id) , "");
|
QModelIndex index = mModel->getModelIndex (id,
|
||||||
|
mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
||||||
|
|
||||||
|
if (mModel->data (index)!=CSMWorld::RecordBase::State_Deleted)
|
||||||
|
emit editRequest (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Preview, id),
|
||||||
|
"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +478,9 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return;
|
||||||
|
|
||||||
if (mime->fromDocument (mDocument))
|
if (mime->fromDocument (mDocument))
|
||||||
{
|
{
|
||||||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace CSVWorld
|
||||||
QAction *mMoveDownAction;
|
QAction *mMoveDownAction;
|
||||||
QAction *mViewAction;
|
QAction *mViewAction;
|
||||||
QAction *mPreviewAction;
|
QAction *mPreviewAction;
|
||||||
|
QAction *mExtendedDeleteAction;
|
||||||
|
QAction *mExtendedRevertAction;
|
||||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||||
CSMWorld::IdTable *mModel;
|
CSMWorld::IdTable *mModel;
|
||||||
int mRecordStatusDisplay;
|
int mRecordStatusDisplay;
|
||||||
|
|
|
@ -131,6 +131,9 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
|
||||||
{
|
{
|
||||||
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
|
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
|
||||||
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
|
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
|
||||||
|
if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return false;
|
||||||
|
|
||||||
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
|
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
|
||||||
if (handled)
|
if (handled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -256,6 +256,9 @@ void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
|
||||||
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
|
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
|
||||||
{
|
{
|
||||||
const CSMWorld::TableMimeData* data(dynamic_cast<const CSMWorld::TableMimeData*>(event->mimeData()));
|
const CSMWorld::TableMimeData* data(dynamic_cast<const CSMWorld::TableMimeData*>(event->mimeData()));
|
||||||
|
if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||||
|
return;
|
||||||
|
|
||||||
emit tableMimeDataDropped(data->getData(), data->getDocumentPtr());
|
emit tableMimeDataDropped(data->getData(), data->getDocumentPtr());
|
||||||
//WIP
|
//WIP
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,9 +73,9 @@ namespace CSVWorld
|
||||||
~CommandDelegateFactoryCollection();
|
~CommandDelegateFactoryCollection();
|
||||||
|
|
||||||
void add (CSMWorld::ColumnBase::Display display, CommandDelegateFactory *factory);
|
void add (CSMWorld::ColumnBase::Display display, CommandDelegateFactory *factory);
|
||||||
///< The ownership of \æ factory is transferred to *this.
|
///< The ownership of \a factory is transferred to *this.
|
||||||
///
|
///
|
||||||
/// This function must not be called more than once per value of \æ display.
|
/// This function must not be called more than once per value of \a display.
|
||||||
|
|
||||||
CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, QUndoStack& undoStack,
|
CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, QUndoStack& undoStack,
|
||||||
QObject *parent) const;
|
QObject *parent) const;
|
||||||
|
|
|
@ -15,7 +15,7 @@ add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
|
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
|
||||||
actors objects renderinginterface localmap occlusionquery water shadows
|
actors objects renderinginterface localmap occlusionquery water shadows
|
||||||
characterpreview globalmap videoplayer ripplesimulation refraction
|
characterpreview globalmap videoplayer ripplesimulation refraction
|
||||||
terrainstorage renderconst effectmanager weaponanimation
|
terrainstorage renderconst effectmanager weaponanimation terraingrid
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -142,10 +142,6 @@ if(APPLE)
|
||||||
endif()
|
endif()
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
if(DPKG_PROGRAM)
|
|
||||||
INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw)
|
|
||||||
endif(DPKG_PROGRAM)
|
|
||||||
|
|
||||||
if (BUILD_WITH_CODE_COVERAGE)
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
add_definitions (--coverage)
|
add_definitions (--coverage)
|
||||||
target_link_libraries(openmw gcov)
|
target_link_libraries(openmw gcov)
|
||||||
|
|
|
@ -128,7 +128,7 @@ static void gdb_info(pid_t pid)
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/* Create a temp file to put gdb commands into */
|
/* Create a temp file to put gdb commands into */
|
||||||
strcpy(respfile, "gdb-respfile-XXXXXX");
|
strcpy(respfile, "/tmp/gdb-respfile-XXXXXX");
|
||||||
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
|
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
|
||||||
{
|
{
|
||||||
fprintf(f, "attach %d\n"
|
fprintf(f, "attach %d\n"
|
||||||
|
@ -381,10 +381,7 @@ static void crash_handler(const char *logfile)
|
||||||
|
|
||||||
if(logfile)
|
if(logfile)
|
||||||
{
|
{
|
||||||
char cwd[MAXPATHLEN];
|
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + std::string(logfile) + "'.\n Please report this to https://bugs.openmw.org !";
|
||||||
getcwd(cwd, MAXPATHLEN);
|
|
||||||
|
|
||||||
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + std::string(cwd) + "/" + std::string(logfile) + "'.\n Please report this to https://bugs.openmw.org !";
|
|
||||||
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), NULL);
|
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), NULL);
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
|
@ -91,7 +91,11 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
if (mUseSound)
|
if (mUseSound)
|
||||||
MWBase::Environment::get().getSoundManager()->update(frametime);
|
MWBase::Environment::get().getSoundManager()->update(frametime);
|
||||||
|
|
||||||
bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
// GUI active? Most game processing will be paused, but scripts still run.
|
||||||
|
bool guiActive = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
|
||||||
|
// Main menu opened? Then scripts are also paused.
|
||||||
|
bool paused = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu);
|
||||||
|
|
||||||
// update game state
|
// update game state
|
||||||
MWBase::Environment::get().getStateManager()->update (frametime);
|
MWBase::Environment::get().getStateManager()->update (frametime);
|
||||||
|
@ -99,15 +103,18 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||||
MWBase::StateManager::State_Running)
|
MWBase::StateManager::State_Running)
|
||||||
{
|
{
|
||||||
// global scripts
|
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
|
||||||
|
|
||||||
// local scripts
|
|
||||||
executeLocalScripts();
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
|
||||||
|
|
||||||
if (!paused)
|
if (!paused)
|
||||||
|
{
|
||||||
|
// global scripts
|
||||||
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
||||||
|
|
||||||
|
// local scripts
|
||||||
|
executeLocalScripts();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!guiActive)
|
||||||
MWBase::Environment::get().getWorld()->advanceTime(
|
MWBase::Environment::get().getWorld()->advanceTime(
|
||||||
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
|
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
|
||||||
}
|
}
|
||||||
|
@ -118,14 +125,14 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
MWBase::StateManager::State_NoGame)
|
MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getMechanicsManager()->update(frametime,
|
MWBase::Environment::get().getMechanicsManager()->update(frametime,
|
||||||
paused);
|
guiActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||||
MWBase::StateManager::State_Running)
|
MWBase::StateManager::State_Running)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr();
|
MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr();
|
||||||
if(!paused && player.getClass().getCreatureStats(player).isDead())
|
if(!guiActive && player.getClass().getCreatureStats(player).isDead())
|
||||||
MWBase::Environment::get().getStateManager()->endGame();
|
MWBase::Environment::get().getStateManager()->endGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +140,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
if (MWBase::Environment::get().getStateManager()->getState()!=
|
if (MWBase::Environment::get().getStateManager()->getState()!=
|
||||||
MWBase::StateManager::State_NoGame)
|
MWBase::StateManager::State_NoGame)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->update(frametime, paused);
|
MWBase::Environment::get().getWorld()->update(frametime, guiActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update GUI
|
// update GUI
|
||||||
|
@ -357,7 +364,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
// Create input and UI first to set up a bootstrapping environment for
|
// Create input and UI first to set up a bootstrapping environment for
|
||||||
// showing a loading screen and keeping the window responsive while doing so
|
// showing a loading screen and keeping the window responsive while doing so
|
||||||
|
|
||||||
std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input.xml").string();
|
std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input_v1.xml").string();
|
||||||
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
|
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
|
||||||
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab);
|
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab);
|
||||||
mEnvironment.setInputManager (input);
|
mEnvironment.setInputManager (input);
|
||||||
|
@ -489,24 +496,7 @@ void OMW::Engine::activate()
|
||||||
if (ptr.getClass().getName(ptr) == "") // objects without name presented to user can never be activated
|
if (ptr.getClass().getName(ptr) == "") // objects without name presented to user can never be activated
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
MWBase::Environment::get().getWorld()->activate(ptr, MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||||
|
|
||||||
interpreterContext.activate (ptr);
|
|
||||||
|
|
||||||
std::string script = ptr.getClass().getScript (ptr);
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayerPtr());
|
|
||||||
|
|
||||||
if (!script.empty())
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr);
|
|
||||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!interpreterContext.hasActivationBeenHandled())
|
|
||||||
{
|
|
||||||
interpreterContext.executeActivation(ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::screenshot()
|
void OMW::Engine::screenshot()
|
||||||
|
|
|
@ -4,19 +4,20 @@
|
||||||
#include <components/version/version.hpp>
|
#include <components/version/version.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL_messagebox.h>
|
||||||
|
#include <SDL_main.h>
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_CONSOLE)
|
|
||||||
#include <boost/iostreams/concepts.hpp>
|
#include <boost/iostreams/concepts.hpp>
|
||||||
#include <boost/iostreams/stream_buffer.hpp>
|
#include <boost/iostreams/stream_buffer.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
// For OutputDebugString
|
// For OutputDebugString
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
// makes __argc and __argv available on windows
|
// makes __argc and __argv available on windows
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,58 +254,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char**argv)
|
#if defined(_WIN32) && defined(_DEBUG)
|
||||||
{
|
|
||||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
|
||||||
// Unix crash catcher
|
|
||||||
if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached())
|
|
||||||
{
|
|
||||||
int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT };
|
|
||||||
cc_install_handlers(argc, argv, 5, s, "crash.log", NULL);
|
|
||||||
std::cout << "Installing crash catcher" << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
std::cout << "Running in a debugger, not installing crash catcher" << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
|
||||||
// set current dir to bundle path
|
|
||||||
boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path();
|
|
||||||
boost::filesystem::current_path(bundlePath);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Files::ConfigurationManager cfgMgr;
|
|
||||||
OMW::Engine engine(cfgMgr);
|
|
||||||
|
|
||||||
if (parseOptions(argc, argv, engine, cfgMgr))
|
|
||||||
{
|
|
||||||
engine.go();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
|
||||||
if (isatty(fileno(stdin)) || !SDL_WasInit(SDL_INIT_VIDEO))
|
|
||||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Platform specific for Windows when there is no console built into the executable.
|
|
||||||
// Windows will call the WinMain function instead of main in this case, the normal
|
|
||||||
// main function is then called with the __argc and __argv parameters.
|
|
||||||
// In addition if it is a debug build it will redirect cout to the debug console in Visual Studio
|
|
||||||
#if defined(_WIN32) && !defined(_CONSOLE)
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
class DebugOutput : public boost::iostreams::sink
|
class DebugOutput : public boost::iostreams::sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -318,11 +269,11 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
class Logger : public boost::iostreams::sink
|
class Tee : public boost::iostreams::sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Logger(std::ofstream &stream)
|
Tee(std::ostream &stream, std::ostream &stream2)
|
||||||
: out(stream)
|
: out(stream), out2(stream2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,38 +281,107 @@ public:
|
||||||
{
|
{
|
||||||
out.write (str, size);
|
out.write (str, size);
|
||||||
out.flush();
|
out.flush();
|
||||||
|
out2.write (str, size);
|
||||||
|
out2.flush();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ofstream &out;
|
std::ostream &out;
|
||||||
|
std::ostream &out2;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
int main(int argc, char**argv)
|
||||||
{
|
{
|
||||||
std::streambuf* old_rdbuf = std::cout.rdbuf ();
|
// Some objects used to redirect cout and cerr
|
||||||
|
// Scope must be here, so this still works inside the catch block for logging exceptions
|
||||||
|
std::streambuf* cout_rdbuf = std::cout.rdbuf ();
|
||||||
|
std::streambuf* cerr_rdbuf = std::cerr.rdbuf ();
|
||||||
|
|
||||||
|
#if !(defined(_WIN32) && defined(_DEBUG))
|
||||||
|
boost::iostreams::stream_buffer<Tee> coutsb;
|
||||||
|
boost::iostreams::stream_buffer<Tee> cerrsb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::ostream oldcout(cout_rdbuf);
|
||||||
|
std::ostream oldcerr(cerr_rdbuf);
|
||||||
|
|
||||||
|
boost::filesystem::ofstream logfile;
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#if defined(_DEBUG)
|
try
|
||||||
// Redirect cout to VS debug output when running in debug mode
|
|
||||||
{
|
{
|
||||||
|
Files::ConfigurationManager cfgMgr;
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_DEBUG)
|
||||||
|
// Redirect cout and cerr to VS debug output when running in debug mode
|
||||||
boost::iostreams::stream_buffer<DebugOutput> sb;
|
boost::iostreams::stream_buffer<DebugOutput> sb;
|
||||||
sb.open(DebugOutput());
|
sb.open(DebugOutput());
|
||||||
#else
|
|
||||||
// Redirect cout to openmw.log
|
|
||||||
std::ofstream logfile ("openmw.log");
|
|
||||||
{
|
|
||||||
boost::iostreams::stream_buffer<Logger> sb;
|
|
||||||
sb.open (Logger (logfile));
|
|
||||||
#endif
|
|
||||||
std::cout.rdbuf (&sb);
|
std::cout.rdbuf (&sb);
|
||||||
|
std::cerr.rdbuf (&sb);
|
||||||
|
#else
|
||||||
|
// Redirect cout and cerr to openmw.log
|
||||||
|
logfile.open (boost::filesystem::path(cfgMgr.getLogPath() / "/openmw.log"));
|
||||||
|
|
||||||
ret = main (__argc, __argv);
|
coutsb.open (Tee(logfile, oldcout));
|
||||||
|
cerrsb.open (Tee(logfile, oldcerr));
|
||||||
|
|
||||||
std::cout.rdbuf(old_rdbuf);
|
std::cout.rdbuf (&coutsb);
|
||||||
|
std::cerr.rdbuf (&cerrsb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||||
|
// Unix crash catcher
|
||||||
|
if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached())
|
||||||
|
{
|
||||||
|
int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT };
|
||||||
|
cc_install_handlers(argc, argv, 5, s, (cfgMgr.getLogPath() / "crash.log").string().c_str(), NULL);
|
||||||
|
std::cout << "Installing crash catcher" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout << "Running in a debugger, not installing crash catcher" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||||
|
// set current dir to bundle path
|
||||||
|
boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path();
|
||||||
|
boost::filesystem::current_path(bundlePath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OMW::Engine engine(cfgMgr);
|
||||||
|
|
||||||
|
if (parseOptions(argc, argv, engine, cfgMgr))
|
||||||
|
{
|
||||||
|
engine.go();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||||
|
if (isatty(fileno(stdin)))
|
||||||
|
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore cout and cerr
|
||||||
|
std::cout.rdbuf(cout_rdbuf);
|
||||||
|
std::cerr.rdbuf(cerr_rdbuf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Platform specific for Windows when there is no console built into the executable.
|
||||||
|
// Windows will call the WinMain function instead of main in this case, the normal
|
||||||
|
// main function is then called with the __argc and __argv parameters.
|
||||||
|
#if defined(_WIN32) && !defined(_CONSOLE)
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
|
{
|
||||||
|
return main(__argc, __argv);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -76,6 +76,9 @@ namespace MWBase
|
||||||
|
|
||||||
/// @return faction1's opinion of faction2
|
/// @return faction1's opinion of faction2
|
||||||
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;
|
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;
|
||||||
|
|
||||||
|
/// Removes the last added topic response for the given actor from the journal
|
||||||
|
virtual void clearInfoActor (const MWWorld::Ptr& actor) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,12 @@ namespace MWBase
|
||||||
virtual int getJournalIndex (const std::string& id) const = 0;
|
virtual int getJournalIndex (const std::string& id) const = 0;
|
||||||
///< Get the journal index.
|
///< Get the journal index.
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName) = 0;
|
virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor) = 0;
|
||||||
|
/// \note topicId must be lowercase
|
||||||
|
|
||||||
|
virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName) = 0;
|
||||||
|
///< Removes the last topic response added for the given topicId and actor name.
|
||||||
|
/// \note topicId must be lowercase
|
||||||
|
|
||||||
virtual TEntryIter begin() const = 0;
|
virtual TEntryIter begin() const = 0;
|
||||||
///< Iterator pointing to the begin of the main journal.
|
///< Iterator pointing to the begin of the main journal.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,9 @@ namespace Ogre
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Class;
|
struct Class;
|
||||||
|
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -21,6 +25,11 @@ namespace MWWorld
|
||||||
class CellStore;
|
class CellStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Loading
|
||||||
|
{
|
||||||
|
class Listener;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
/// \brief Interface for game mechanics manager (implemented in MWMechanics)
|
/// \brief Interface for game mechanics manager (implemented in MWMechanics)
|
||||||
|
@ -111,6 +120,7 @@ namespace MWBase
|
||||||
/**
|
/**
|
||||||
* @brief Commit a crime. If any actors witness the crime and report it,
|
* @brief Commit a crime. If any actors witness the crime and report it,
|
||||||
* reportCrime will be called automatically.
|
* reportCrime will be called automatically.
|
||||||
|
* @note victim may be empty
|
||||||
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
|
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
|
||||||
* @return was the crime reported?
|
* @return was the crime reported?
|
||||||
*/
|
*/
|
||||||
|
@ -174,6 +184,18 @@ namespace MWBase
|
||||||
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor) = 0;
|
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
virtual void playerLoaded() = 0;
|
virtual void playerLoaded() = 0;
|
||||||
|
|
||||||
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0;
|
||||||
|
|
||||||
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
/// @param bias Can be used to add an additional aggression bias towards the target,
|
||||||
|
/// making it more likely for the function to return true.
|
||||||
|
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, int bias=0, bool ignoreDistance=false) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,7 @@ namespace MWBase
|
||||||
virtual void showCrosshair(bool show) = 0;
|
virtual void showCrosshair(bool show) = 0;
|
||||||
virtual bool getSubtitlesEnabled() = 0;
|
virtual bool getSubtitlesEnabled() = 0;
|
||||||
virtual void toggleHud() = 0;
|
virtual void toggleHud() = 0;
|
||||||
|
virtual bool toggleGui() = 0;
|
||||||
|
|
||||||
virtual void disallowMouse() = 0;
|
virtual void disallowMouse() = 0;
|
||||||
virtual void allowMouse() = 0;
|
virtual void allowMouse() = 0;
|
||||||
|
@ -328,6 +329,8 @@ namespace MWBase
|
||||||
/** Used when one Modal adds another Modal
|
/** Used when one Modal adds another Modal
|
||||||
\param input Pointer to the current modal, to ensure proper modal is removed **/
|
\param input Pointer to the current modal, to ensure proper modal is removed **/
|
||||||
virtual void removeCurrentModal(MWGui::WindowModal* input) = 0;
|
virtual void removeCurrentModal(MWGui::WindowModal* input) = 0;
|
||||||
|
|
||||||
|
virtual void pinWindow (MWGui::GuiWindow window) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,9 @@ namespace MWBase
|
||||||
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
|
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
|
||||||
///< Adjust position after load to be on ground. Must be called after model load.
|
///< Adjust position after load to be on ground. Must be called after model load.
|
||||||
|
|
||||||
|
virtual void fixPosition (const MWWorld::Ptr& actor) = 0;
|
||||||
|
///< Attempt to fix position so that the Ptr is no longer inside collision geometry.
|
||||||
|
|
||||||
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
|
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
||||||
|
@ -407,7 +410,7 @@ namespace MWBase
|
||||||
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
|
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
|
||||||
///< get all items in active cells owned by this Npc
|
///< get all items in active cells owned by this Npc
|
||||||
|
|
||||||
virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0;
|
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0;
|
||||||
///< get Line of Sight (morrowind stupid implementation)
|
///< get Line of Sight (morrowind stupid implementation)
|
||||||
|
|
||||||
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0;
|
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0;
|
||||||
|
@ -470,7 +473,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId,
|
virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId,
|
||||||
float speed, bool stack, const ESM::EffectList& effects,
|
float speed, bool stack, const ESM::EffectList& effects,
|
||||||
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
|
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection) = 0;
|
||||||
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
|
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
|
||||||
const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) = 0;
|
const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) = 0;
|
||||||
|
|
||||||
|
@ -515,8 +518,18 @@ namespace MWBase
|
||||||
/// Spawn a blood effect for \a ptr at \a worldPosition
|
/// Spawn a blood effect for \a ptr at \a worldPosition
|
||||||
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0;
|
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0;
|
||||||
|
|
||||||
|
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0;
|
||||||
|
|
||||||
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
||||||
const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0;
|
const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0;
|
||||||
|
|
||||||
|
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
|
/// @see MWWorld::WeatherManager::isInStorm
|
||||||
|
virtual bool isInStorm() const = 0;
|
||||||
|
|
||||||
|
/// @see MWWorld::WeatherManager::getStormDirection
|
||||||
|
virtual Ogre::Vector3 getStormDirection() const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -168,7 +168,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
||||||
ptr.get<ESM::Armor>();
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
return ref->mBase->mData.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Armor::registerSelf()
|
void Armor::registerSelf()
|
||||||
|
@ -244,7 +244,7 @@ namespace MWClass
|
||||||
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
|
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")";
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")";
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -190,7 +190,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -286,7 +286,12 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
||||||
|
|
||||||
ensureCustomData (ptr);
|
if (!ptr.getRefData().getCustomData())
|
||||||
|
{
|
||||||
|
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||||
|
std::auto_ptr<ContainerCustomData> data (new ContainerCustomData);
|
||||||
|
ptr.getRefData().setCustomData (data.release());
|
||||||
|
}
|
||||||
|
|
||||||
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
||||||
readState (state2.mInventory);
|
readState (state2.mInventory);
|
||||||
|
|
|
@ -59,35 +59,38 @@ namespace
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
const Creature::GMST& Creature::getGmst()
|
||||||
|
{
|
||||||
|
static GMST gmst;
|
||||||
|
static bool inited = false;
|
||||||
|
if (!inited)
|
||||||
|
{
|
||||||
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
gmst.fMinWalkSpeedCreature = store.find("fMinWalkSpeedCreature");
|
||||||
|
gmst.fMaxWalkSpeedCreature = store.find("fMaxWalkSpeedCreature");
|
||||||
|
gmst.fEncumberedMoveEffect = store.find("fEncumberedMoveEffect");
|
||||||
|
gmst.fSneakSpeedMultiplier = store.find("fSneakSpeedMultiplier");
|
||||||
|
gmst.fAthleticsRunBonus = store.find("fAthleticsRunBonus");
|
||||||
|
gmst.fBaseRunMultiplier = store.find("fBaseRunMultiplier");
|
||||||
|
gmst.fMinFlySpeed = store.find("fMinFlySpeed");
|
||||||
|
gmst.fMaxFlySpeed = store.find("fMaxFlySpeed");
|
||||||
|
gmst.fSwimRunBase = store.find("fSwimRunBase");
|
||||||
|
gmst.fSwimRunAthleticsMult = store.find("fSwimRunAthleticsMult");
|
||||||
|
gmst.fKnockDownMult = store.find("fKnockDownMult");
|
||||||
|
gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult");
|
||||||
|
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
return gmst;
|
||||||
|
}
|
||||||
|
|
||||||
void Creature::ensureCustomData (const MWWorld::Ptr& ptr) const
|
void Creature::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
|
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
|
||||||
|
|
||||||
static bool inited = false;
|
|
||||||
if(!inited)
|
|
||||||
{
|
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
|
||||||
|
|
||||||
fMinWalkSpeedCreature = gmst.find("fMinWalkSpeedCreature");
|
|
||||||
fMaxWalkSpeedCreature = gmst.find("fMaxWalkSpeedCreature");
|
|
||||||
fEncumberedMoveEffect = gmst.find("fEncumberedMoveEffect");
|
|
||||||
fSneakSpeedMultiplier = gmst.find("fSneakSpeedMultiplier");
|
|
||||||
fAthleticsRunBonus = gmst.find("fAthleticsRunBonus");
|
|
||||||
fBaseRunMultiplier = gmst.find("fBaseRunMultiplier");
|
|
||||||
fMinFlySpeed = gmst.find("fMinFlySpeed");
|
|
||||||
fMaxFlySpeed = gmst.find("fMaxFlySpeed");
|
|
||||||
fSwimRunBase = gmst.find("fSwimRunBase");
|
|
||||||
fSwimRunAthleticsMult = gmst.find("fSwimRunAthleticsMult");
|
|
||||||
fKnockDownMult = gmst.find("fKnockDownMult");
|
|
||||||
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
|
||||||
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
|
||||||
|
|
||||||
inited = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
// creature stats
|
// creature stats
|
||||||
|
@ -345,7 +348,9 @@ namespace MWClass
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
// Self defense
|
// Self defense
|
||||||
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
|
if (!attacker.isEmpty() && !MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker)
|
||||||
|
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr))) // No retaliation for totally static creatures
|
||||||
|
// (they have no movement or attacks anyway)
|
||||||
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
||||||
|
|
||||||
if(!successful)
|
if(!successful)
|
||||||
|
@ -374,9 +379,9 @@ namespace MWClass
|
||||||
if (damage > 0.f)
|
if (damage > 0.f)
|
||||||
{
|
{
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
|
||||||
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
* iKnockDownOddsMult->getInt() * 0.01 + iKnockDownOddsBase->getInt();
|
* getGmst().iKnockDownOddsMult->getInt() * 0.01 + getGmst().iKnockDownOddsBase->getInt();
|
||||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
||||||
{
|
{
|
||||||
|
@ -520,9 +525,10 @@ namespace MWClass
|
||||||
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
float walkSpeed = fMinWalkSpeedCreature->getFloat() + 0.01 * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
float walkSpeed = gmst.fMinWalkSpeedCreature->getFloat() + 0.01 * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||||
* (fMaxWalkSpeedCreature->getFloat() - fMinWalkSpeedCreature->getFloat());
|
* (gmst.fMaxWalkSpeedCreature->getFloat() - gmst.fMinWalkSpeedCreature->getFloat());
|
||||||
|
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||||
|
@ -531,8 +537,8 @@ namespace MWClass
|
||||||
|
|
||||||
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||||
|
|
||||||
float runSpeed = walkSpeed*(0.01f * getSkill(ptr, ESM::Skill::Athletics) *
|
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
||||||
fAthleticsRunBonus->getFloat() + fBaseRunMultiplier->getFloat());
|
float runSpeed = walkSpeed;
|
||||||
|
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(normalizedEncumbrance >= 1.0f)
|
if(normalizedEncumbrance >= 1.0f)
|
||||||
|
@ -542,8 +548,8 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
||||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||||
flySpeed = std::max(0.0f, flySpeed);
|
flySpeed = std::max(0.0f, flySpeed);
|
||||||
moveSpeed = flySpeed;
|
moveSpeed = flySpeed;
|
||||||
}
|
}
|
||||||
|
@ -553,8 +559,8 @@ namespace MWClass
|
||||||
if(running)
|
if(running)
|
||||||
swimSpeed = runSpeed;
|
swimSpeed = runSpeed;
|
||||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
||||||
fSwimRunAthleticsMult->getFloat();
|
gmst.fSwimRunAthleticsMult->getFloat();
|
||||||
moveSpeed = swimSpeed;
|
moveSpeed = swimSpeed;
|
||||||
}
|
}
|
||||||
else if(running)
|
else if(running)
|
||||||
|
@ -711,7 +717,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
return ref->mBase->mFlags & ESM::Creature::Swims;
|
return ref->mBase->mFlags & ESM::Creature::Swims || ref->mBase->mFlags & ESM::Creature::Bipedal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Creature::canWalk(const MWWorld::Ptr &ptr) const
|
bool Creature::canWalk(const MWWorld::Ptr &ptr) const
|
||||||
|
@ -719,7 +725,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
return ref->mBase->mFlags & ESM::Creature::Walks;
|
return ref->mBase->mFlags & ESM::Creature::Walks || ref->mBase->mFlags & ESM::Creature::Bipedal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name)
|
int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name)
|
||||||
|
@ -796,7 +802,27 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
||||||
|
|
||||||
ensureCustomData (ptr);
|
ensureCustomData(ptr);
|
||||||
|
|
||||||
|
// If we do the following instead we get a sizable speedup, but this causes compatibility issues
|
||||||
|
// with 0.30 savegames, where some state in CreatureStats was not saved yet,
|
||||||
|
// and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release.
|
||||||
|
/*
|
||||||
|
if (!ptr.getRefData().getCustomData())
|
||||||
|
{
|
||||||
|
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||||
|
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
|
||||||
|
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||||
|
data->mContainerStore = new MWWorld::InventoryStore();
|
||||||
|
else
|
||||||
|
data->mContainerStore = new MWWorld::ContainerStore();
|
||||||
|
|
||||||
|
ptr.getRefData().setCustomData (data.release());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
|
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
|
||||||
|
|
||||||
|
@ -835,8 +861,7 @@ namespace MWClass
|
||||||
ptr.getRefData().setCount(1);
|
ptr.getRefData().setCount(1);
|
||||||
|
|
||||||
// Reset to original position
|
// Reset to original position
|
||||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||||
pos = ptr.getCellRef().getPosition();
|
|
||||||
|
|
||||||
ptr.getRefData().setCustomData(NULL);
|
ptr.getRefData().setCustomData(NULL);
|
||||||
}
|
}
|
||||||
|
@ -850,19 +875,4 @@ namespace MWClass
|
||||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
|
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
|
|
||||||
const ESM::GameSetting* Creature::fMaxWalkSpeedCreature;
|
|
||||||
const ESM::GameSetting *Creature::fEncumberedMoveEffect;
|
|
||||||
const ESM::GameSetting *Creature::fSneakSpeedMultiplier;
|
|
||||||
const ESM::GameSetting *Creature::fAthleticsRunBonus;
|
|
||||||
const ESM::GameSetting *Creature::fBaseRunMultiplier;
|
|
||||||
const ESM::GameSetting *Creature::fMinFlySpeed;
|
|
||||||
const ESM::GameSetting *Creature::fMaxFlySpeed;
|
|
||||||
const ESM::GameSetting *Creature::fSwimRunBase;
|
|
||||||
const ESM::GameSetting *Creature::fSwimRunAthleticsMult;
|
|
||||||
const ESM::GameSetting *Creature::fKnockDownMult;
|
|
||||||
const ESM::GameSetting *Creature::iKnockDownOddsMult;
|
|
||||||
const ESM::GameSetting *Creature::iKnockDownOddsBase;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,20 +19,25 @@ namespace MWClass
|
||||||
|
|
||||||
static int getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name);
|
static int getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name);
|
||||||
|
|
||||||
static const ESM::GameSetting *fMinWalkSpeedCreature;
|
// cached GMSTs
|
||||||
static const ESM::GameSetting *fMaxWalkSpeedCreature;
|
struct GMST
|
||||||
static const ESM::GameSetting *fEncumberedMoveEffect;
|
{
|
||||||
static const ESM::GameSetting *fSneakSpeedMultiplier;
|
const ESM::GameSetting *fMinWalkSpeedCreature;
|
||||||
static const ESM::GameSetting *fAthleticsRunBonus;
|
const ESM::GameSetting *fMaxWalkSpeedCreature;
|
||||||
static const ESM::GameSetting *fBaseRunMultiplier;
|
const ESM::GameSetting *fEncumberedMoveEffect;
|
||||||
static const ESM::GameSetting *fMinFlySpeed;
|
const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||||
static const ESM::GameSetting *fMaxFlySpeed;
|
const ESM::GameSetting *fAthleticsRunBonus;
|
||||||
static const ESM::GameSetting *fSwimRunBase;
|
const ESM::GameSetting *fBaseRunMultiplier;
|
||||||
static const ESM::GameSetting *fSwimRunAthleticsMult;
|
const ESM::GameSetting *fMinFlySpeed;
|
||||||
static const ESM::GameSetting *fKnockDownMult;
|
const ESM::GameSetting *fMaxFlySpeed;
|
||||||
static const ESM::GameSetting *iKnockDownOddsMult;
|
const ESM::GameSetting *fSwimRunBase;
|
||||||
static const ESM::GameSetting *iKnockDownOddsBase;
|
const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||||
|
const ESM::GameSetting *fKnockDownMult;
|
||||||
|
const ESM::GameSetting *iKnockDownOddsMult;
|
||||||
|
const ESM::GameSetting *iKnockDownOddsBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GMST& getGmst();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -57,11 +57,13 @@ namespace MWClass
|
||||||
physics.addObject(ptr);
|
physics.addObject(ptr);
|
||||||
|
|
||||||
// Resume the door's opening/closing animation if it wasn't finished
|
// Resume the door's opening/closing animation if it wasn't finished
|
||||||
ensureCustomData(ptr);
|
if (ptr.getRefData().getCustomData())
|
||||||
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
|
|
||||||
if (customData.mDoorState > 0)
|
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState == 1 ? true : false);
|
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
|
||||||
|
if (customData.mDoorState > 0)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState == 1 ? true : false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ namespace MWClass
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
|
MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
|
||||||
unlock(ptr); //Call the function here. because that makes sense.
|
unlock(ptr); //Call the function here. because that makes sense.
|
||||||
// using a key disarms the trap
|
// using a key disarms the trap
|
||||||
ptr.getCellRef().getTrap() = "";
|
ptr.getCellRef().setTrap("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!needKey || hasKey)
|
if (!needKey || hasKey)
|
||||||
|
|
|
@ -144,7 +144,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
|
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
|
||||||
ptr.get<ESM::Lockpick>();
|
ptr.get<ESM::Lockpick>();
|
||||||
|
|
||||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
return ref->mBase->mData.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lockpick::registerSelf()
|
void Lockpick::registerSelf()
|
||||||
|
@ -138,7 +138,7 @@ namespace MWClass
|
||||||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -228,38 +228,44 @@ namespace
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
|
const Npc::GMST& Npc::getGmst()
|
||||||
{
|
{
|
||||||
|
static GMST gmst;
|
||||||
static bool inited = false;
|
static bool inited = false;
|
||||||
if(!inited)
|
if(!inited)
|
||||||
{
|
{
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
fMinWalkSpeed = gmst.find("fMinWalkSpeed");
|
gmst.fMinWalkSpeed = store.find("fMinWalkSpeed");
|
||||||
fMaxWalkSpeed = gmst.find("fMaxWalkSpeed");
|
gmst.fMaxWalkSpeed = store.find("fMaxWalkSpeed");
|
||||||
fEncumberedMoveEffect = gmst.find("fEncumberedMoveEffect");
|
gmst.fEncumberedMoveEffect = store.find("fEncumberedMoveEffect");
|
||||||
fSneakSpeedMultiplier = gmst.find("fSneakSpeedMultiplier");
|
gmst.fSneakSpeedMultiplier = store.find("fSneakSpeedMultiplier");
|
||||||
fAthleticsRunBonus = gmst.find("fAthleticsRunBonus");
|
gmst.fAthleticsRunBonus = store.find("fAthleticsRunBonus");
|
||||||
fBaseRunMultiplier = gmst.find("fBaseRunMultiplier");
|
gmst.fBaseRunMultiplier = store.find("fBaseRunMultiplier");
|
||||||
fMinFlySpeed = gmst.find("fMinFlySpeed");
|
gmst.fMinFlySpeed = store.find("fMinFlySpeed");
|
||||||
fMaxFlySpeed = gmst.find("fMaxFlySpeed");
|
gmst.fMaxFlySpeed = store.find("fMaxFlySpeed");
|
||||||
fSwimRunBase = gmst.find("fSwimRunBase");
|
gmst.fSwimRunBase = store.find("fSwimRunBase");
|
||||||
fSwimRunAthleticsMult = gmst.find("fSwimRunAthleticsMult");
|
gmst.fSwimRunAthleticsMult = store.find("fSwimRunAthleticsMult");
|
||||||
fJumpEncumbranceBase = gmst.find("fJumpEncumbranceBase");
|
gmst.fJumpEncumbranceBase = store.find("fJumpEncumbranceBase");
|
||||||
fJumpEncumbranceMultiplier = gmst.find("fJumpEncumbranceMultiplier");
|
gmst.fJumpEncumbranceMultiplier = store.find("fJumpEncumbranceMultiplier");
|
||||||
fJumpAcrobaticsBase = gmst.find("fJumpAcrobaticsBase");
|
gmst.fJumpAcrobaticsBase = store.find("fJumpAcrobaticsBase");
|
||||||
fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier");
|
gmst.fJumpAcroMultiplier = store.find("fJumpAcroMultiplier");
|
||||||
fJumpRunMultiplier = gmst.find("fJumpRunMultiplier");
|
gmst.fJumpRunMultiplier = store.find("fJumpRunMultiplier");
|
||||||
fWereWolfRunMult = gmst.find("fWereWolfRunMult");
|
gmst.fWereWolfRunMult = store.find("fWereWolfRunMult");
|
||||||
fKnockDownMult = gmst.find("fKnockDownMult");
|
gmst.fKnockDownMult = store.find("fKnockDownMult");
|
||||||
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult");
|
||||||
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
|
||||||
fDamageStrengthBase = gmst.find("fDamageStrengthBase");
|
gmst.fDamageStrengthBase = store.find("fDamageStrengthBase");
|
||||||
fDamageStrengthMult = gmst.find("fDamageStrengthMult");
|
gmst.fDamageStrengthMult = store.find("fDamageStrengthMult");
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
return gmst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
if (!ptr.getRefData().getCustomData())
|
if (!ptr.getRefData().getCustomData())
|
||||||
{
|
{
|
||||||
std::auto_ptr<NpcCustomData> data(new NpcCustomData);
|
std::auto_ptr<NpcCustomData> data(new NpcCustomData);
|
||||||
|
@ -404,11 +410,6 @@ namespace MWClass
|
||||||
ptr.get<ESM::NPC>();
|
ptr.get<ESM::NPC>();
|
||||||
assert(ref->mBase != NULL);
|
assert(ref->mBase != NULL);
|
||||||
|
|
||||||
//std::string headID = ref->mBase->mHead;
|
|
||||||
|
|
||||||
//int end = headID.find_last_of("head_") - 4;
|
|
||||||
//std::string bodyRaceID = headID.substr(0, end);
|
|
||||||
|
|
||||||
std::string model = "meshes\\base_anim.nif";
|
std::string model = "meshes\\base_anim.nif";
|
||||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||||
if(race->mData.mFlags & ESM::Race::Beast)
|
if(race->mData.mFlags & ESM::Race::Beast)
|
||||||
|
@ -423,9 +424,9 @@ namespace MWClass
|
||||||
if(getNpcStats(ptr).isWerewolf())
|
if(getNpcStats(ptr).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
return gmst.find("sWerewolfPopup")->getString();
|
return store.find("sWerewolfPopup")->getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||||
|
@ -450,7 +451,9 @@ namespace MWClass
|
||||||
void Npc::hit(const MWWorld::Ptr& ptr, int type) const
|
void Npc::hit(const MWWorld::Ptr& ptr, int type) const
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
||||||
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||||
|
@ -461,9 +464,9 @@ namespace MWClass
|
||||||
|
|
||||||
// Reduce fatigue
|
// Reduce fatigue
|
||||||
// somewhat of a guess, but using the weapon weight makes sense
|
// somewhat of a guess, but using the weapon weight makes sense
|
||||||
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
|
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
|
||||||
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
|
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
|
||||||
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
|
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
|
||||||
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
|
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
|
||||||
const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr);
|
const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr);
|
||||||
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||||
|
@ -472,10 +475,10 @@ namespace MWClass
|
||||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||||
getCreatureStats(ptr).setFatigue(fatigue);
|
getCreatureStats(ptr).setFatigue(fatigue);
|
||||||
|
|
||||||
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
|
const float fCombatDistance = store.find("fCombatDistance")->getFloat();
|
||||||
float dist = fCombatDistance * (!weapon.isEmpty() ?
|
float dist = fCombatDistance * (!weapon.isEmpty() ?
|
||||||
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
||||||
gmst.find("fHandToHandReach")->getFloat());
|
store.find("fHandToHandReach")->getFloat());
|
||||||
|
|
||||||
// TODO: Use second to work out the hit angle
|
// TODO: Use second to work out the hit angle
|
||||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
||||||
|
@ -522,8 +525,8 @@ namespace MWClass
|
||||||
if(attack)
|
if(attack)
|
||||||
{
|
{
|
||||||
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
||||||
damage *= fDamageStrengthBase->getFloat() +
|
damage *= gmst.fDamageStrengthBase->getFloat() +
|
||||||
(stats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult->getFloat() * 0.1);
|
(stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.fDamageStrengthMult->getFloat() * 0.1);
|
||||||
if(weaphashealth)
|
if(weaphashealth)
|
||||||
{
|
{
|
||||||
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon);
|
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon);
|
||||||
|
@ -535,7 +538,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
// Reduce weapon charge by at least one, but cap at 0
|
// Reduce weapon charge by at least one, but cap at 0
|
||||||
weaphealth -= std::min(std::max(1,
|
weaphealth -= std::min(std::max(1,
|
||||||
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weaphealth);
|
(int)(damage * store.find("fWeaponDamageMult")->getFloat())), weaphealth);
|
||||||
|
|
||||||
weapon.getCellRef().setCharge(weaphealth);
|
weapon.getCellRef().setCharge(weaphealth);
|
||||||
}
|
}
|
||||||
|
@ -552,8 +555,8 @@ namespace MWClass
|
||||||
// Note: MCP contains an option to include Strength in hand-to-hand damage
|
// Note: MCP contains an option to include Strength in hand-to-hand damage
|
||||||
// calculations. Some mods recommend using it, so we may want to include am
|
// calculations. Some mods recommend using it, so we may want to include am
|
||||||
// option for it.
|
// option for it.
|
||||||
float minstrike = gmst.find("fMinHandToHandMult")->getFloat();
|
float minstrike = store.find("fMinHandToHandMult")->getFloat();
|
||||||
float maxstrike = gmst.find("fMaxHandToHandMult")->getFloat();
|
float maxstrike = store.find("fMaxHandToHandMult")->getFloat();
|
||||||
damage = stats.getSkill(weapskill).getModified();
|
damage = stats.getSkill(weapskill).getModified();
|
||||||
damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength());
|
damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength());
|
||||||
|
|
||||||
|
@ -567,7 +570,7 @@ namespace MWClass
|
||||||
damage *= glob.find("WerewolfClawMult")->mValue.getFloat();
|
damage *= glob.find("WerewolfClawMult")->mValue.getFloat();
|
||||||
}
|
}
|
||||||
if(healthdmg)
|
if(healthdmg)
|
||||||
damage *= gmst.find("fHandtoHandHealthPer")->getFloat();
|
damage *= store.find("fHandtoHandHealthPer")->getFloat();
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
if(stats.isWerewolf())
|
if(stats.isWerewolf())
|
||||||
|
@ -585,12 +588,12 @@ namespace MWClass
|
||||||
bool detected = MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, victim);
|
bool detected = MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, victim);
|
||||||
if(!detected)
|
if(!detected)
|
||||||
{
|
{
|
||||||
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
|
damage *= store.find("fCombatCriticalStrikeMult")->getFloat();
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
if (othercls.getCreatureStats(victim).getKnockedDown())
|
if (othercls.getCreatureStats(victim).getKnockedDown())
|
||||||
damage *= gmst.find("fCombatKODamageMult")->getFloat();
|
damage *= store.find("fCombatKODamageMult")->getFloat();
|
||||||
|
|
||||||
// Apply "On hit" enchanted weapons
|
// Apply "On hit" enchanted weapons
|
||||||
std::string enchantmentName = !weapon.isEmpty() ? weapon.getClass().getEnchantment(weapon) : "";
|
std::string enchantmentName = !weapon.isEmpty() ? weapon.getClass().getEnchantment(weapon) : "";
|
||||||
|
@ -624,11 +627,12 @@ namespace MWClass
|
||||||
// NOTE: 'object' and/or 'attacker' may be empty.
|
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||||
|
|
||||||
// Attacking peaceful NPCs is a crime
|
// Attacking peaceful NPCs is a crime
|
||||||
// anything below 80 is considered peaceful (see Actors::updateActor)
|
|
||||||
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).isHostile() &&
|
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).isHostile() &&
|
||||||
ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
|
!MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker))
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
|
bool wasDead = getCreatureStats(ptr).isDead();
|
||||||
|
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
if(!successful)
|
if(!successful)
|
||||||
|
@ -660,6 +664,8 @@ namespace MWClass
|
||||||
// something, alert the character controller, scripts, etc.
|
// something, alert the character controller, scripts, etc.
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
|
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
|
||||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
if (roll < chance)
|
if (roll < chance)
|
||||||
|
@ -668,9 +674,9 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat();
|
||||||
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
* iKnockDownOddsMult->getInt() * 0.01 + iKnockDownOddsBase->getInt();
|
* gmst.iKnockDownOddsMult->getInt() * 0.01 + gmst.iKnockDownOddsBase->getInt();
|
||||||
roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
||||||
{
|
{
|
||||||
|
@ -752,6 +758,22 @@ namespace MWClass
|
||||||
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
||||||
getCreatureStats(ptr).setFatigue(fatigue);
|
getCreatureStats(ptr).setFatigue(fatigue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wasDead && getCreatureStats(ptr).isDead())
|
||||||
|
{
|
||||||
|
// NPC was killed
|
||||||
|
if (!attacker.isEmpty() && attacker.getClass().isNpc() && attacker.getClass().getNpcStats(attacker).isWerewolf())
|
||||||
|
{
|
||||||
|
attacker.getClass().getNpcStats(attacker).addWerewolfKill();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple check for who attacked first: if the player attacked first, a crimeId should be set
|
||||||
|
// Doesn't handle possible edge case where no one reported the assault, but in such a case,
|
||||||
|
// for bystanders it is not possible to tell who attacked first, anyway.
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
if (attacker == player && ptr.getClass().getNpcStats(ptr).getCrimeId() != -1 && ptr != player)
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(player, ptr, MWBase::MechanicsManager::OT_Murder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Npc::block(const MWWorld::Ptr &ptr) const
|
void Npc::block(const MWWorld::Ptr &ptr) const
|
||||||
|
@ -853,6 +875,8 @@ namespace MWClass
|
||||||
float Npc::getSpeed(const MWWorld::Ptr& ptr) const
|
float Npc::getSpeed(const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||||
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
|
||||||
|
|
||||||
|
@ -861,17 +885,17 @@ namespace MWClass
|
||||||
bool sneaking = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
bool sneaking = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
||||||
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||||
|
|
||||||
float walkSpeed = fMinWalkSpeed->getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
float walkSpeed = gmst.fMinWalkSpeed->getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
||||||
(fMaxWalkSpeed->getFloat() - fMinWalkSpeed->getFloat());
|
(gmst.fMaxWalkSpeed->getFloat() - gmst.fMinWalkSpeed->getFloat());
|
||||||
walkSpeed *= 1.0f - fEncumberedMoveEffect->getFloat()*normalizedEncumbrance;
|
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat()*normalizedEncumbrance;
|
||||||
walkSpeed = std::max(0.0f, walkSpeed);
|
walkSpeed = std::max(0.0f, walkSpeed);
|
||||||
if(sneaking)
|
if(sneaking)
|
||||||
walkSpeed *= fSneakSpeedMultiplier->getFloat();
|
walkSpeed *= gmst.fSneakSpeedMultiplier->getFloat();
|
||||||
|
|
||||||
float runSpeed = walkSpeed*(0.01f * npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified() *
|
float runSpeed = walkSpeed*(0.01f * npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified() *
|
||||||
fAthleticsRunBonus->getFloat() + fBaseRunMultiplier->getFloat());
|
gmst.fAthleticsRunBonus->getFloat() + gmst.fBaseRunMultiplier->getFloat());
|
||||||
if(npcdata->mNpcStats.isWerewolf())
|
if(npcdata->mNpcStats.isWerewolf())
|
||||||
runSpeed *= fWereWolfRunMult->getFloat();
|
runSpeed *= gmst.fWereWolfRunMult->getFloat();
|
||||||
|
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(normalizedEncumbrance >= 1.0f)
|
if(normalizedEncumbrance >= 1.0f)
|
||||||
|
@ -881,8 +905,8 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
||||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||||
flySpeed = std::max(0.0f, flySpeed);
|
flySpeed = std::max(0.0f, flySpeed);
|
||||||
moveSpeed = flySpeed;
|
moveSpeed = flySpeed;
|
||||||
}
|
}
|
||||||
|
@ -892,8 +916,8 @@ namespace MWClass
|
||||||
if(running)
|
if(running)
|
||||||
swimSpeed = runSpeed;
|
swimSpeed = runSpeed;
|
||||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||||
fSwimRunAthleticsMult->getFloat();
|
gmst.fSwimRunAthleticsMult->getFloat();
|
||||||
moveSpeed = swimSpeed;
|
moveSpeed = swimSpeed;
|
||||||
}
|
}
|
||||||
else if(running && !sneaking)
|
else if(running && !sneaking)
|
||||||
|
@ -909,9 +933,10 @@ namespace MWClass
|
||||||
float Npc::getJump(const MWWorld::Ptr &ptr) const
|
float Npc::getJump(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
|
||||||
const float encumbranceTerm = fJumpEncumbranceBase->getFloat() +
|
const float encumbranceTerm = gmst.fJumpEncumbranceBase->getFloat() +
|
||||||
fJumpEncumbranceMultiplier->getFloat() *
|
gmst.fJumpEncumbranceMultiplier->getFloat() *
|
||||||
(1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr));
|
(1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr));
|
||||||
|
|
||||||
float a = npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified();
|
float a = npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified();
|
||||||
|
@ -922,14 +947,14 @@ namespace MWClass
|
||||||
a = 50.0f;
|
a = 50.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float x = fJumpAcrobaticsBase->getFloat() +
|
float x = gmst.fJumpAcrobaticsBase->getFloat() +
|
||||||
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->getFloat());
|
||||||
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
x += 3.0f * b * gmst.fJumpAcroMultiplier->getFloat();
|
||||||
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
||||||
x *= encumbranceTerm;
|
x *= encumbranceTerm;
|
||||||
|
|
||||||
if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
|
if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
|
||||||
x *= fJumpRunMultiplier->getFloat();
|
x *= gmst.fJumpRunMultiplier->getFloat();
|
||||||
x *= npcdata->mNpcStats.getFatigueTerm();
|
x *= npcdata->mNpcStats.getFatigueTerm();
|
||||||
x -= -627.2f;/*gravity constant*/
|
x -= -627.2f;/*gravity constant*/
|
||||||
x /= 3.0f;
|
x /= 3.0f;
|
||||||
|
@ -940,19 +965,19 @@ namespace MWClass
|
||||||
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat();
|
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->getFloat();
|
||||||
|
|
||||||
if (fallHeight >= fallDistanceMin)
|
if (fallHeight >= fallDistanceMin)
|
||||||
{
|
{
|
||||||
const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
||||||
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
|
||||||
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
|
||||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
|
||||||
const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat();
|
const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat();
|
||||||
|
|
||||||
float x = fallHeight - fallDistanceMin;
|
float x = fallHeight - fallDistanceMin;
|
||||||
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
||||||
|
@ -1087,14 +1112,14 @@ namespace MWClass
|
||||||
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
|
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
MWMechanics::NpcStats &stats = getNpcStats(ptr);
|
MWMechanics::NpcStats &stats = getNpcStats(ptr);
|
||||||
MWWorld::InventoryStore &invStore = getInventoryStore(ptr);
|
MWWorld::InventoryStore &invStore = getInventoryStore(ptr);
|
||||||
|
|
||||||
int iBaseArmorSkill = gmst.find("iBaseArmorSkill")->getInt();
|
int iBaseArmorSkill = store.find("iBaseArmorSkill")->getInt();
|
||||||
float fUnarmoredBase1 = gmst.find("fUnarmoredBase1")->getFloat();
|
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
|
||||||
float fUnarmoredBase2 = gmst.find("fUnarmoredBase2")->getFloat();
|
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
|
||||||
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
|
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
|
||||||
|
|
||||||
int ratings[MWWorld::InventoryStore::Slots];
|
int ratings[MWWorld::InventoryStore::Slots];
|
||||||
|
@ -1276,7 +1301,18 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
||||||
|
|
||||||
ensureCustomData (ptr);
|
ensureCustomData(ptr);
|
||||||
|
// If we do the following instead we get a sizable speedup, but this causes compatibility issues
|
||||||
|
// with 0.30 savegames, where some state in CreatureStats was not saved yet,
|
||||||
|
// and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release.
|
||||||
|
/*
|
||||||
|
if (!ptr.getRefData().getCustomData())
|
||||||
|
{
|
||||||
|
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||||
|
std::auto_ptr<NpcCustomData> data (new NpcCustomData);
|
||||||
|
ptr.getRefData().setCustomData (data.release());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
|
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
|
||||||
|
|
||||||
|
@ -1325,8 +1361,7 @@ namespace MWClass
|
||||||
ptr.getRefData().setCount(1);
|
ptr.getRefData().setCount(1);
|
||||||
|
|
||||||
// Reset to original position
|
// Reset to original position
|
||||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||||
pos = ptr.getCellRef().getPosition();
|
|
||||||
|
|
||||||
ptr.getRefData().setCustomData(NULL);
|
ptr.getRefData().setCustomData(NULL);
|
||||||
}
|
}
|
||||||
|
@ -1340,27 +1375,4 @@ namespace MWClass
|
||||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
|
store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction());
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::GameSetting *Npc::fMinWalkSpeed;
|
|
||||||
const ESM::GameSetting *Npc::fMaxWalkSpeed;
|
|
||||||
const ESM::GameSetting *Npc::fEncumberedMoveEffect;
|
|
||||||
const ESM::GameSetting *Npc::fSneakSpeedMultiplier;
|
|
||||||
const ESM::GameSetting *Npc::fAthleticsRunBonus;
|
|
||||||
const ESM::GameSetting *Npc::fBaseRunMultiplier;
|
|
||||||
const ESM::GameSetting *Npc::fMinFlySpeed;
|
|
||||||
const ESM::GameSetting *Npc::fMaxFlySpeed;
|
|
||||||
const ESM::GameSetting *Npc::fSwimRunBase;
|
|
||||||
const ESM::GameSetting *Npc::fSwimRunAthleticsMult;
|
|
||||||
const ESM::GameSetting *Npc::fJumpEncumbranceBase;
|
|
||||||
const ESM::GameSetting *Npc::fJumpEncumbranceMultiplier;
|
|
||||||
const ESM::GameSetting *Npc::fJumpAcrobaticsBase;
|
|
||||||
const ESM::GameSetting *Npc::fJumpAcroMultiplier;
|
|
||||||
const ESM::GameSetting *Npc::fJumpRunMultiplier;
|
|
||||||
const ESM::GameSetting *Npc::fWereWolfRunMult;
|
|
||||||
const ESM::GameSetting *Npc::fKnockDownMult;
|
|
||||||
const ESM::GameSetting *Npc::iKnockDownOddsMult;
|
|
||||||
const ESM::GameSetting *Npc::iKnockDownOddsBase;
|
|
||||||
const ESM::GameSetting *Npc::fDamageStrengthBase;
|
|
||||||
const ESM::GameSetting *Npc::fDamageStrengthMult;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,27 +17,32 @@ namespace MWClass
|
||||||
virtual MWWorld::Ptr
|
virtual MWWorld::Ptr
|
||||||
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
|
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
|
||||||
|
|
||||||
static const ESM::GameSetting *fMinWalkSpeed;
|
struct GMST
|
||||||
static const ESM::GameSetting *fMaxWalkSpeed;
|
{
|
||||||
static const ESM::GameSetting *fEncumberedMoveEffect;
|
const ESM::GameSetting *fMinWalkSpeed;
|
||||||
static const ESM::GameSetting *fSneakSpeedMultiplier;
|
const ESM::GameSetting *fMaxWalkSpeed;
|
||||||
static const ESM::GameSetting *fAthleticsRunBonus;
|
const ESM::GameSetting *fEncumberedMoveEffect;
|
||||||
static const ESM::GameSetting *fBaseRunMultiplier;
|
const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||||
static const ESM::GameSetting *fMinFlySpeed;
|
const ESM::GameSetting *fAthleticsRunBonus;
|
||||||
static const ESM::GameSetting *fMaxFlySpeed;
|
const ESM::GameSetting *fBaseRunMultiplier;
|
||||||
static const ESM::GameSetting *fSwimRunBase;
|
const ESM::GameSetting *fMinFlySpeed;
|
||||||
static const ESM::GameSetting *fSwimRunAthleticsMult;
|
const ESM::GameSetting *fMaxFlySpeed;
|
||||||
static const ESM::GameSetting *fJumpEncumbranceBase;
|
const ESM::GameSetting *fSwimRunBase;
|
||||||
static const ESM::GameSetting *fJumpEncumbranceMultiplier;
|
const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||||
static const ESM::GameSetting *fJumpAcrobaticsBase;
|
const ESM::GameSetting *fJumpEncumbranceBase;
|
||||||
static const ESM::GameSetting *fJumpAcroMultiplier;
|
const ESM::GameSetting *fJumpEncumbranceMultiplier;
|
||||||
static const ESM::GameSetting *fJumpRunMultiplier;
|
const ESM::GameSetting *fJumpAcrobaticsBase;
|
||||||
static const ESM::GameSetting *fWereWolfRunMult;
|
const ESM::GameSetting *fJumpAcroMultiplier;
|
||||||
static const ESM::GameSetting *fKnockDownMult;
|
const ESM::GameSetting *fJumpRunMultiplier;
|
||||||
static const ESM::GameSetting *iKnockDownOddsMult;
|
const ESM::GameSetting *fWereWolfRunMult;
|
||||||
static const ESM::GameSetting *iKnockDownOddsBase;
|
const ESM::GameSetting *fKnockDownMult;
|
||||||
static const ESM::GameSetting *fDamageStrengthBase;
|
const ESM::GameSetting *iKnockDownOddsMult;
|
||||||
static const ESM::GameSetting *fDamageStrengthMult;
|
const ESM::GameSetting *iKnockDownOddsBase;
|
||||||
|
const ESM::GameSetting *fDamageStrengthBase;
|
||||||
|
const ESM::GameSetting *fDamageStrengthMult;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GMST& getGmst();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ namespace MWClass
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
|
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
|
||||||
|
|
||||||
|
@ -166,13 +166,8 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
||||||
ptr.get<ESM::Potion>();
|
ptr.get<ESM::Potion>();
|
||||||
|
|
||||||
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
|
|
||||||
// remove used potion (assume it is present in inventory)
|
|
||||||
ptr.getContainerStore()->remove(ptr, 1, actor);
|
|
||||||
|
|
||||||
boost::shared_ptr<MWWorld::Action> action (
|
boost::shared_ptr<MWWorld::Action> action (
|
||||||
new MWWorld::ActionApply (actor, ref->mBase->mId));
|
new MWWorld::ActionApply (ptr, ref->mBase->mId));
|
||||||
|
|
||||||
action->setSound ("Drink");
|
action->setSound ("Drink");
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Probe> *ref =
|
MWWorld::LiveCellRef<ESM::Probe> *ref =
|
||||||
ptr.get<ESM::Probe>();
|
ptr.get<ESM::Probe>();
|
||||||
|
|
||||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
return ref->mBase->mData.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Probe::registerSelf()
|
void Probe::registerSelf()
|
||||||
|
@ -137,7 +137,7 @@ namespace MWClass
|
||||||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||||
ptr.get<ESM::Repair>();
|
ptr.get<ESM::Repair>();
|
||||||
|
|
||||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
return ref->mBase->mData.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Repair::registerSelf()
|
void Repair::registerSelf()
|
||||||
|
@ -141,7 +141,7 @@ namespace MWClass
|
||||||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
|
|
@ -14,9 +14,12 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
{
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Static> *ref =
|
||||||
|
ptr.get<ESM::Static>();
|
||||||
|
|
||||||
const std::string model = getModel(ptr);
|
const std::string model = getModel(ptr);
|
||||||
if (!model.empty()) {
|
if (!model.empty()) {
|
||||||
renderingInterface.getObjects().insertModel(ptr, model);
|
renderingInterface.getObjects().insertModel(ptr, model, !ref->mBase->mPersistent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
||||||
ptr.get<ESM::Weapon>();
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
return ref->mBase->mData.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::registerSelf()
|
void Weapon::registerSelf()
|
||||||
|
@ -343,7 +343,7 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||||
|
|
||||||
info.enchant = ref->mBase->mEnchant;
|
info.enchant = ref->mBase->mEnchant;
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,10 @@ namespace MWDialogue
|
||||||
|
|
||||||
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
// Dialogue with dead actor (e.g. through script) should not be allowed.
|
||||||
|
if (actor.getClass().getCreatureStats(actor).isDead())
|
||||||
|
return;
|
||||||
|
|
||||||
mLastTopic = "";
|
mLastTopic = "";
|
||||||
mPermanentDispositionChange = 0;
|
mPermanentDispositionChange = 0;
|
||||||
mTemporaryDispositionChange = 0;
|
mTemporaryDispositionChange = 0;
|
||||||
|
@ -140,7 +144,11 @@ namespace MWDialogue
|
||||||
mActorKnownTopics.clear();
|
mActorKnownTopics.clear();
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||||
win->startDialogue(actor, actor.getClass().getName (actor));
|
|
||||||
|
// If the dialogue window was already open, keep the existing history
|
||||||
|
bool resetHistory = (!MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Dialogue));
|
||||||
|
|
||||||
|
win->startDialogue(actor, actor.getClass().getName (actor), resetHistory);
|
||||||
|
|
||||||
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
|
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
|
||||||
updateTopics();
|
updateTopics();
|
||||||
|
@ -174,10 +182,20 @@ namespace MWDialogue
|
||||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||||
executeScript (info->mResultScript);
|
executeScript (info->mResultScript);
|
||||||
mLastTopic = Misc::StringUtils::lowerCase(it->mId);
|
mLastTopic = Misc::StringUtils::lowerCase(it->mId);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No greetings found. The dialogue window should not be shown.
|
||||||
|
// If this is a companion, we must show the companion window directly (used by BM_bear_be_unique).
|
||||||
|
bool isCompanion = !mActor.getClass().getScript(mActor).empty()
|
||||||
|
&& mActor.getRefData().getLocals().getIntVar(mActor.getClass().getScript(mActor), "companion");
|
||||||
|
if (isCompanion)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion);
|
||||||
|
MWBase::Environment::get().getWindowManager()->showCompanionWindow(mActor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code)
|
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code)
|
||||||
|
@ -294,7 +312,7 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
if (iter->mId == info->mId)
|
if (iter->mId == info->mId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor.getClass().getName(mActor));
|
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,7 +416,7 @@ namespace MWDialogue
|
||||||
win->setServices (windowServices);
|
win->setServices (windowServices);
|
||||||
|
|
||||||
// sort again, because the previous sort was case-sensitive
|
// sort again, because the previous sort was case-sensitive
|
||||||
keywordList.sort(Misc::StringUtils::ciEqual);
|
keywordList.sort(Misc::StringUtils::ciLess);
|
||||||
win->setKeywords(keywordList);
|
win->setKeywords(keywordList);
|
||||||
|
|
||||||
mChoice = choice;
|
mChoice = choice;
|
||||||
|
@ -472,7 +490,7 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
if (iter->mId == info->mId)
|
if (iter->mId == info->mId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor.getClass().getName(mActor));
|
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,6 +712,15 @@ namespace MWDialogue
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueManager::clearInfoActor(const MWWorld::Ptr &actor) const
|
||||||
|
{
|
||||||
|
if (actor == mActor && !mLastTopic.empty())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getJournal()->removeLastAddedTopicResponse(
|
||||||
|
mLastTopic, actor.getClass().getName(actor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
||||||
{
|
{
|
||||||
std::vector<HyperTextToken> result;
|
std::vector<HyperTextToken> result;
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace MWDialogue
|
||||||
bool mTalkedTo;
|
bool mTalkedTo;
|
||||||
|
|
||||||
int mChoice;
|
int mChoice;
|
||||||
std::string mLastTopic;
|
std::string mLastTopic; // last topic ID, lowercase
|
||||||
bool mIsInChoice;
|
bool mIsInChoice;
|
||||||
|
|
||||||
float mTemporaryDispositionChange;
|
float mTemporaryDispositionChange;
|
||||||
|
@ -99,6 +99,9 @@ namespace MWDialogue
|
||||||
|
|
||||||
/// @return faction1's opinion of faction2
|
/// @return faction1's opinion of faction2
|
||||||
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;
|
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;
|
||||||
|
|
||||||
|
/// Removes the last added topic response for the given actor from the journal
|
||||||
|
virtual void clearInfoActor (const MWWorld::Ptr& actor) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,8 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||||
|
|
||||||
case SelectWrapper::Function_ShouldAttack:
|
case SelectWrapper::Function_ShouldAttack:
|
||||||
|
|
||||||
return mActor.getClass().getCreatureStats(mActor).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() >= 80;
|
return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor,
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||||
|
|
||||||
case SelectWrapper::Function_CreatureTargetted:
|
case SelectWrapper::Function_CreatureTargetted:
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,21 @@
|
||||||
|
|
||||||
#include <components/esm/journalentry.hpp>
|
#include <components/esm/journalentry.hpp>
|
||||||
|
|
||||||
|
#include <components/interpreter/defines.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
Entry::Entry() {}
|
Entry::Entry() {}
|
||||||
|
|
||||||
Entry::Entry (const std::string& topic, const std::string& infoId)
|
Entry::Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||||
: mInfoId (infoId)
|
: mInfoId (infoId)
|
||||||
{
|
{
|
||||||
const ESM::Dialogue *dialogue =
|
const ESM::Dialogue *dialogue =
|
||||||
|
@ -24,8 +29,17 @@ namespace MWDialogue
|
||||||
iter!=dialogue->mInfo.end(); ++iter)
|
iter!=dialogue->mInfo.end(); ++iter)
|
||||||
if (iter->mId == mInfoId)
|
if (iter->mId == mInfoId)
|
||||||
{
|
{
|
||||||
/// \todo text replacement
|
if (actor.isEmpty())
|
||||||
mText = iter->mResponse;
|
{
|
||||||
|
MWScript::InterpreterContext interpreterContext(NULL,MWWorld::Ptr());
|
||||||
|
mText = Interpreter::fixDefinesDialog(iter->mResponse, interpreterContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext interpreterContext(&actor.getRefData().getLocals(),actor);
|
||||||
|
mText = Interpreter::fixDefinesDialog(iter->mResponse, interpreterContext);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +63,8 @@ namespace MWDialogue
|
||||||
|
|
||||||
JournalEntry::JournalEntry() {}
|
JournalEntry::JournalEntry() {}
|
||||||
|
|
||||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId)
|
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||||
: Entry (topic, infoId), mTopic (topic)
|
: Entry (topic, infoId, actor), mTopic (topic)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
JournalEntry::JournalEntry (const ESM::JournalEntry& record)
|
JournalEntry::JournalEntry (const ESM::JournalEntry& record)
|
||||||
|
@ -65,7 +79,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index)
|
JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index)
|
||||||
{
|
{
|
||||||
return JournalEntry (topic, idFromIndex (topic, index));
|
return JournalEntry (topic, idFromIndex (topic, index), MWWorld::Ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JournalEntry::idFromIndex (const std::string& topic, int index)
|
std::string JournalEntry::idFromIndex (const std::string& topic, int index)
|
||||||
|
@ -90,7 +104,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
StampedJournalEntry::StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
StampedJournalEntry::StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
||||||
int day, int month, int dayOfMonth)
|
int day, int month, int dayOfMonth)
|
||||||
: JournalEntry (topic, infoId), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
: JournalEntry (topic, infoId, MWWorld::Ptr()), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
StampedJournalEntry::StampedJournalEntry (const ESM::JournalEntry& record)
|
StampedJournalEntry::StampedJournalEntry (const ESM::JournalEntry& record)
|
||||||
|
|
|
@ -8,6 +8,11 @@ namespace ESM
|
||||||
struct JournalEntry;
|
struct JournalEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
/// \brief Basic quest/dialogue/topic entry
|
/// \brief Basic quest/dialogue/topic entry
|
||||||
|
@ -19,7 +24,8 @@ namespace MWDialogue
|
||||||
|
|
||||||
Entry();
|
Entry();
|
||||||
|
|
||||||
Entry (const std::string& topic, const std::string& infoId);
|
/// actor is optional
|
||||||
|
Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
Entry (const ESM::JournalEntry& record);
|
Entry (const ESM::JournalEntry& record);
|
||||||
|
|
||||||
|
@ -37,7 +43,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
JournalEntry();
|
JournalEntry();
|
||||||
|
|
||||||
JournalEntry (const std::string& topic, const std::string& infoId);
|
JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
JournalEntry (const ESM::JournalEntry& record);
|
JournalEntry (const ESM::JournalEntry& record);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <components/esm/journalentry.hpp>
|
#include <components/esm/journalentry.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -103,15 +104,25 @@ namespace MWDialogue
|
||||||
quest.setIndex (index);
|
quest.setIndex (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName)
|
void Journal::addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
Topic& topic = getTopic (topicId);
|
Topic& topic = getTopic (topicId);
|
||||||
|
|
||||||
JournalEntry entry(topicId, infoId);
|
JournalEntry entry(topicId, infoId, actor);
|
||||||
entry.mActorName = actorName;
|
entry.mActorName = actor.getClass().getName(actor);
|
||||||
topic.addEntry (entry);
|
topic.addEntry (entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Journal::removeLastAddedTopicResponse(const std::string &topicId, const std::string &actorName)
|
||||||
|
{
|
||||||
|
Topic& topic = getTopic (topicId);
|
||||||
|
|
||||||
|
topic.removeLastAddedResponse(actorName);
|
||||||
|
|
||||||
|
if (topic.begin() == topic.end())
|
||||||
|
mTopics.erase(mTopics.find(topicId)); // All responses removed -> remove topic
|
||||||
|
}
|
||||||
|
|
||||||
int Journal::getJournalIndex (const std::string& id) const
|
int Journal::getJournalIndex (const std::string& id) const
|
||||||
{
|
{
|
||||||
TQuestContainer::const_iterator iter = mQuests.find (id);
|
TQuestContainer::const_iterator iter = mQuests.find (id);
|
||||||
|
|
|
@ -38,7 +38,12 @@ namespace MWDialogue
|
||||||
virtual int getJournalIndex (const std::string& id) const;
|
virtual int getJournalIndex (const std::string& id) const;
|
||||||
///< Get the journal index.
|
///< Get the journal index.
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName);
|
virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||||
|
/// \note topicId must be lowercase
|
||||||
|
|
||||||
|
virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName);
|
||||||
|
///< Removes the last topic response added for the given topicId and actor name.
|
||||||
|
/// \note topicId must be lowercase
|
||||||
|
|
||||||
virtual TEntryIter begin() const;
|
virtual TEntryIter begin() const;
|
||||||
///< Iterator pointing to the begin of the main journal.
|
///< Iterator pointing to the begin of the main journal.
|
||||||
|
|
|
@ -59,8 +59,16 @@ namespace MWDialogue
|
||||||
return mEntries.end();
|
return mEntries.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
JournalEntry Topic::getEntry (const std::string& infoId) const
|
void Topic::removeLastAddedResponse (const std::string& actorName)
|
||||||
{
|
{
|
||||||
return JournalEntry (mTopic, infoId);
|
for (std::vector<MWDialogue::Entry>::reverse_iterator it = mEntries.rbegin();
|
||||||
|
it != mEntries.rend(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mActorName == actorName)
|
||||||
|
{
|
||||||
|
mEntries.erase( (++it).base() ); // erase doesn't take a reverse_iterator
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,13 +48,13 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
|
|
||||||
|
void removeLastAddedResponse (const std::string& actorName);
|
||||||
|
|
||||||
TEntryIter begin() const;
|
TEntryIter begin() const;
|
||||||
///< Iterator pointing to the begin of the journal for this topic.
|
///< Iterator pointing to the begin of the journal for this topic.
|
||||||
|
|
||||||
TEntryIter end() const;
|
TEntryIter end() const;
|
||||||
///< Iterator pointing past the end of the journal for this topic.
|
///< Iterator pointing past the end of the journal for this topic.
|
||||||
|
|
||||||
JournalEntry getEntry (const std::string& infoId) const;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -360,10 +360,16 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||||
int spaceLeft = mPageHeight - (curPageStop - curPageStart);
|
int spaceLeft = mPageHeight - (curPageStop - curPageStart);
|
||||||
int sectionHeight = i->mRect.height ();
|
int sectionHeight = i->mRect.height ();
|
||||||
|
|
||||||
if (sectionHeight <= mPageHeight)
|
// This is NOT equal to i->mRect.height(), which doesn't account for section breaks.
|
||||||
|
int spaceRequired = (i->mRect.bottom - curPageStop);
|
||||||
|
if (curPageStart == curPageStop) // If this is a new page, the section break is not needed
|
||||||
|
spaceRequired = i->mRect.height();
|
||||||
|
|
||||||
|
if (spaceRequired <= mPageHeight)
|
||||||
{
|
{
|
||||||
if (sectionHeight > spaceLeft)
|
if (spaceRequired > spaceLeft)
|
||||||
{
|
{
|
||||||
|
// The section won't completely fit on the current page. Finish the current page and start a new one.
|
||||||
assert (curPageStart != curPageStop);
|
assert (curPageStart != curPageStop);
|
||||||
|
|
||||||
mBook->mPages.push_back (Page (curPageStart, curPageStop));
|
mBook->mPages.push_back (Page (curPageStart, curPageStop));
|
||||||
|
|
|
@ -30,9 +30,9 @@ namespace MWGui
|
||||||
|
|
||||||
void ConfirmationDialog::exit()
|
void ConfirmationDialog::exit()
|
||||||
{
|
{
|
||||||
eventCancelClicked();
|
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
|
||||||
|
eventCancelClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
@ -42,8 +42,8 @@ namespace MWGui
|
||||||
|
|
||||||
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
eventOkClicked();
|
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
|
||||||
|
eventOkClicked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,4 +435,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
setSelectedObject(MWWorld::Ptr());
|
setSelectedObject(MWWorld::Ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Console::resetReference()
|
||||||
|
{
|
||||||
|
ReferenceInterface::resetReference();
|
||||||
|
setSelectedObject(MWWorld::Ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,8 @@ namespace MWGui
|
||||||
|
|
||||||
void executeFile (const std::string& path);
|
void executeFile (const std::string& path);
|
||||||
|
|
||||||
|
virtual void resetReference ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void onReferenceUnavailable();
|
virtual void onReferenceUnavailable();
|
||||||
|
|
|
@ -38,6 +38,32 @@ namespace MWGui
|
||||||
mIsOnDragAndDrop = true;
|
mIsOnDragAndDrop = true;
|
||||||
mDragAndDropWidget->setVisible(true);
|
mDragAndDropWidget->setVisible(true);
|
||||||
|
|
||||||
|
// If picking up an item that isn't from the player's inventory, the item gets added to player inventory backend
|
||||||
|
// immediately, even though it's still floating beneath the mouse cursor. A bit counterintuitive,
|
||||||
|
// but this is how it works in vanilla, and not doing so would break quests (BM_beasts for instance).
|
||||||
|
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
|
||||||
|
if (mSourceModel != playerModel)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = mSourceModel->moveItem(mItem, mDraggedCount, playerModel);
|
||||||
|
|
||||||
|
playerModel->update();
|
||||||
|
|
||||||
|
ItemModel::ModelIndex newIndex = -1;
|
||||||
|
for (unsigned int i=0; i<playerModel->getItemCount(); ++i)
|
||||||
|
{
|
||||||
|
if (playerModel->getItem(i).mBase == item)
|
||||||
|
{
|
||||||
|
newIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mItem = playerModel->getItem(newIndex);
|
||||||
|
mSourceModel = playerModel;
|
||||||
|
|
||||||
|
SortFilterItemModel* playerFilterModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getSortFilterModel();
|
||||||
|
mSourceSortModel = playerFilterModel;
|
||||||
|
}
|
||||||
|
|
||||||
std::string sound = mItem.mBase.getClass().getUpSoundId(mItem.mBase);
|
std::string sound = mItem.mBase.getClass().getUpSoundId(mItem.mBase);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||||
|
|
||||||
|
|
|
@ -366,10 +366,11 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory)
|
||||||
{
|
{
|
||||||
mGoodbye = false;
|
mGoodbye = false;
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
|
bool sameActor = (mPtr == actor);
|
||||||
mPtr = actor;
|
mPtr = actor;
|
||||||
mTopicsList->setEnabled(true);
|
mTopicsList->setEnabled(true);
|
||||||
setTitle(npcName);
|
setTitle(npcName);
|
||||||
|
@ -378,9 +379,12 @@ namespace MWGui
|
||||||
|
|
||||||
mTopicsList->clear();
|
mTopicsList->clear();
|
||||||
|
|
||||||
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
if (resetHistory || !sameActor)
|
||||||
delete (*it);
|
{
|
||||||
mHistoryContents.clear();
|
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
||||||
|
delete (*it);
|
||||||
|
mHistoryContents.clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
||||||
delete (*it);
|
delete (*it);
|
||||||
|
@ -582,13 +586,32 @@ namespace MWGui
|
||||||
//Clear the list of topics
|
//Clear the list of topics
|
||||||
mTopicsList->clear();
|
mTopicsList->clear();
|
||||||
|
|
||||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
bool dispositionVisible = false;
|
||||||
|
if (mPtr.getClass().isNpc())
|
||||||
{
|
{
|
||||||
|
dispositionVisible = true;
|
||||||
mDispositionBar->setProgressRange(100);
|
mDispositionBar->setProgressRange(100);
|
||||||
mDispositionBar->setProgressPosition(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr));
|
mDispositionBar->setProgressPosition(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr));
|
||||||
mDispositionText->eraseText(0, mDispositionText->getTextLength());
|
mDispositionText->eraseText(0, mDispositionText->getTextLength());
|
||||||
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
|
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dispositionWasVisible = mDispositionBar->getVisible();
|
||||||
|
|
||||||
|
if (dispositionVisible && !dispositionWasVisible)
|
||||||
|
{
|
||||||
|
mDispositionBar->setVisible(true);
|
||||||
|
float offset = mDispositionBar->getHeight()+5;
|
||||||
|
mTopicsList->setCoord(mTopicsList->getCoord() + MyGUI::IntCoord(0,offset,0,-offset));
|
||||||
|
mTopicsList->adjustSize();
|
||||||
|
}
|
||||||
|
else if (!dispositionVisible && dispositionWasVisible)
|
||||||
|
{
|
||||||
|
mDispositionBar->setVisible(false);
|
||||||
|
float offset = mDispositionBar->getHeight()+5;
|
||||||
|
mTopicsList->setCoord(mTopicsList->getCoord() - MyGUI::IntCoord(0,offset,0,-offset));
|
||||||
|
mTopicsList->adjustSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::goodbye()
|
void DialogueWindow::goodbye()
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace MWGui
|
||||||
|
|
||||||
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
||||||
|
|
||||||
void startDialogue(MWWorld::Ptr actor, std::string npcName);
|
void startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory);
|
||||||
void setKeywords(std::list<std::string> keyWord);
|
void setKeywords(std::list<std::string> keyWord);
|
||||||
|
|
||||||
void addResponse (const std::string& text, const std::string& title="");
|
void addResponse (const std::string& text, const std::string& title="");
|
||||||
|
@ -170,7 +170,7 @@ namespace MWGui
|
||||||
BookPage* mHistory;
|
BookPage* mHistory;
|
||||||
Widgets::MWList* mTopicsList;
|
Widgets::MWList* mTopicsList;
|
||||||
MyGUI::ScrollBar* mScrollBar;
|
MyGUI::ScrollBar* mScrollBar;
|
||||||
MyGUI::ProgressPtr mDispositionBar;
|
MyGUI::Progress* mDispositionBar;
|
||||||
MyGUI::EditBox* mDispositionText;
|
MyGUI::EditBox* mDispositionText;
|
||||||
|
|
||||||
PersuasionDialog mPersuasionDialog;
|
PersuasionDialog mPersuasionDialog;
|
||||||
|
|
|
@ -258,12 +258,16 @@ namespace MWGui
|
||||||
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
||||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||||
|
|
||||||
// More hacks! The french game uses U+2019, which is nowhere to be found in
|
// More hacks! The french game uses several win1252 characters that are not included
|
||||||
// the CP437 encoding of the font. Fall back to 39 (regular apostrophe)
|
// in the cp437 encoding of the font. Fall back to similar available characters.
|
||||||
if (i == 39 && mEncoding == ToUTF8::CP437)
|
// Same for U+2013
|
||||||
|
std::map<int, int> additional;
|
||||||
|
additional[39] = 0x2019; // apostrophe
|
||||||
|
additional[45] = 0x2013; // dash
|
||||||
|
if (additional.find(i) != additional.end() && mEncoding == ToUTF8::CP437)
|
||||||
{
|
{
|
||||||
MyGUI::xml::ElementPtr code = codes->createChild("Code");
|
MyGUI::xml::ElementPtr code = codes->createChild("Code");
|
||||||
code->addAttribute("index", 0x2019);
|
code->addAttribute("index", additional[i]);
|
||||||
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
||||||
+ MyGUI::utility::toString(y1) + " "
|
+ MyGUI::utility::toString(y1) + " "
|
||||||
+ MyGUI::utility::toString(w) + " "
|
+ MyGUI::utility::toString(w) + " "
|
||||||
|
|
|
@ -384,6 +384,8 @@ namespace MWGui
|
||||||
|
|
||||||
void HUD::onFrame(float dt)
|
void HUD::onFrame(float dt)
|
||||||
{
|
{
|
||||||
|
LocalMapBase::onFrame(dt);
|
||||||
|
|
||||||
mCellNameTimer -= dt;
|
mCellNameTimer -= dt;
|
||||||
mWeaponSpellTimer -= dt;
|
mWeaponSpellTimer -= dt;
|
||||||
if (mCellNameTimer < 0)
|
if (mCellNameTimer < 0)
|
||||||
|
|
|
@ -132,6 +132,11 @@ namespace MWGui
|
||||||
adjustPanes();
|
adjustPanes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SortFilterItemModel* InventoryWindow::getSortFilterModel()
|
||||||
|
{
|
||||||
|
return mSortModel;
|
||||||
|
}
|
||||||
|
|
||||||
TradeItemModel* InventoryWindow::getTradeModel()
|
TradeItemModel* InventoryWindow::getTradeModel()
|
||||||
{
|
{
|
||||||
return mTradeModel;
|
return mTradeModel;
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace MWGui
|
||||||
mPreview->rebuild();
|
mPreview->rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SortFilterItemModel* getSortFilterModel();
|
||||||
TradeItemModel* getTradeModel();
|
TradeItemModel* getTradeModel();
|
||||||
ItemModel* getModel();
|
ItemModel* getModel();
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,26 @@ namespace MWGui
|
||||||
|
|
||||||
void ItemWidget::setIcon(const std::string &icon)
|
void ItemWidget::setIcon(const std::string &icon)
|
||||||
{
|
{
|
||||||
|
// HACK HACK HACK: Don't setImageTexture if it hasn't changed.
|
||||||
|
// There is a leak in MyGUI for each setImageTexture on the same widget.
|
||||||
|
// http://www.ogre3d.org/addonforums/viewtopic.php?f=17&t=30251
|
||||||
|
if (mCurrentItemTexture == icon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCurrentItemTexture = icon;
|
||||||
if (mItem)
|
if (mItem)
|
||||||
mItem->setImageTexture(icon);
|
mItem->setImageTexture(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord)
|
void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord)
|
||||||
{
|
{
|
||||||
|
// HACK HACK HACK: Don't setImageTexture if it hasn't changed.
|
||||||
|
// There is a leak in MyGUI for each setImageTexture on the same widget.
|
||||||
|
// http://www.ogre3d.org/addonforums/viewtopic.php?f=17&t=30251
|
||||||
|
if (mCurrentFrameTexture == frame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCurrentFrameTexture = frame;
|
||||||
if (mFrame)
|
if (mFrame)
|
||||||
{
|
{
|
||||||
mFrame->setImageTexture(frame);
|
mFrame->setImageTexture(frame);
|
||||||
|
@ -69,8 +83,21 @@ namespace MWGui
|
||||||
if (ptr.isEmpty())
|
if (ptr.isEmpty())
|
||||||
{
|
{
|
||||||
if (mFrame)
|
if (mFrame)
|
||||||
mFrame->setImageTexture("");
|
{
|
||||||
mItem->setImageTexture("");
|
// HACK HACK HACK: Don't setImageTexture if it hasn't changed.
|
||||||
|
// There is a leak in MyGUI for each setImageTexture on the same widget.
|
||||||
|
// http://www.ogre3d.org/addonforums/viewtopic.php?f=17&t=30251
|
||||||
|
if (!mCurrentFrameTexture.empty())
|
||||||
|
{
|
||||||
|
mFrame->setImageTexture("");
|
||||||
|
mCurrentFrameTexture = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mCurrentItemTexture.empty())
|
||||||
|
{
|
||||||
|
mCurrentItemTexture = "";
|
||||||
|
mItem->setImageTexture("");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::ImageBox* mItem;
|
MyGUI::ImageBox* mItem;
|
||||||
MyGUI::ImageBox* mFrame;
|
MyGUI::ImageBox* mFrame;
|
||||||
|
|
||||||
|
std::string mCurrentItemTexture;
|
||||||
|
std::string mCurrentFrameTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,9 +104,10 @@ namespace MWGui
|
||||||
|
|
||||||
int attribute = mSpentAttributes[i];
|
int attribute = mSpentAttributes[i];
|
||||||
|
|
||||||
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 30;
|
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 20;
|
||||||
|
|
||||||
MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mMainWidget->getAbsolutePosition() - MyGUI::IntPoint(24+xdiff,-4);
|
MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mMainWidget->getAbsolutePosition() - MyGUI::IntPoint(22+xdiff,0);
|
||||||
|
pos.top += (mAttributes[attribute]->getHeight() - image->getHeight())/2;
|
||||||
image->setPosition(pos);
|
image->setPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace MWGui
|
||||||
size_t viewRange = mScrollView->getCanvasSize().height;
|
size_t viewRange = mScrollView->getCanvasSize().height;
|
||||||
if(viewPosition > viewRange)
|
if(viewPosition > viewRange)
|
||||||
viewPosition = viewRange;
|
viewPosition = viewRange;
|
||||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition));
|
mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition * -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWList::setPropertyOverride(const std::string &_key, const std::string &_value)
|
void MWList::setPropertyOverride(const std::string &_key, const std::string &_value)
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace MWGui
|
||||||
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups ();
|
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups ();
|
||||||
for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
|
for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||||
{
|
{
|
||||||
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash_*.tga");
|
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash/*.tga");
|
||||||
mResources.insert(mResources.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end());
|
mResources.insert(mResources.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,10 +68,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (visible)
|
if (visible)
|
||||||
updateMenu();
|
updateMenu();
|
||||||
else
|
|
||||||
showBackground(
|
showBackground(
|
||||||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
||||||
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
||||||
|
|
||||||
OEngine::GUI::Layout::setVisible (visible);
|
OEngine::GUI::Layout::setVisible (visible);
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ namespace MWGui
|
||||||
mVideo = mVideoBackground->createWidget<VideoWidget>("ImageBox", 0,0,1,1,
|
mVideo = mVideoBackground->createWidget<VideoWidget>("ImageBox", 0,0,1,1,
|
||||||
MyGUI::Align::Stretch, "Menu");
|
MyGUI::Align::Stretch, "Menu");
|
||||||
|
|
||||||
mVideo->playVideo("video\\menu_background.bik", false);
|
mVideo->playVideo("video\\menu_background.bik");
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
|
@ -204,7 +204,7 @@ namespace MWGui
|
||||||
if (!mVideo->update())
|
if (!mVideo->update())
|
||||||
{
|
{
|
||||||
// If finished playing, start again
|
// If finished playing, start again
|
||||||
mVideo->playVideo("video\\menu_background.bik", 0);
|
mVideo->playVideo("video\\menu_background.bik");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,6 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
|
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
|
||||||
|
|
||||||
showBackground(state == MWBase::StateManager::State_NoGame);
|
|
||||||
mVersionText->setVisible(state == MWBase::StateManager::State_NoGame);
|
mVersionText->setVisible(state == MWBase::StateManager::State_NoGame);
|
||||||
|
|
||||||
std::vector<std::string> buttons;
|
std::vector<std::string> buttons;
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
||||||
, mLastDirectionX(0.0f)
|
, mLastDirectionX(0.0f)
|
||||||
, mLastDirectionY(0.0f)
|
, mLastDirectionY(0.0f)
|
||||||
, mCompass(NULL)
|
, mCompass(NULL)
|
||||||
|
, mMarkerUpdateTimer(0.0f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +346,18 @@ namespace MWGui
|
||||||
markerWidget->setUserString("IsMarker", "true");
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
markerWidget->setUserData(markerPos);
|
markerWidget->setUserData(markerPos);
|
||||||
markerWidget->setColour(markerColour);
|
markerWidget->setColour(markerColour);
|
||||||
|
mMarkerWidgets.push_back(markerWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::onFrame(float dt)
|
||||||
|
{
|
||||||
|
mMarkerUpdateTimer += dt;
|
||||||
|
|
||||||
|
if (mMarkerUpdateTimer >= 0.25)
|
||||||
|
{
|
||||||
|
mMarkerUpdateTimer = 0;
|
||||||
|
updateMarkers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,6 +431,9 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mGlobalMapRender = new MWRender::GlobalMap("");
|
mGlobalMapRender = new MWRender::GlobalMap("");
|
||||||
mGlobalMapRender->render(loadingListener);
|
mGlobalMapRender->render(loadingListener);
|
||||||
|
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||||
|
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||||
|
|
||||||
mGlobalMapImage->setImageTexture("GlobalMap.png");
|
mGlobalMapImage->setImageTexture("GlobalMap.png");
|
||||||
mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
|
mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
|
||||||
}
|
}
|
||||||
|
@ -471,6 +487,8 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::onFrame(float dt)
|
void MapWindow::onFrame(float dt)
|
||||||
{
|
{
|
||||||
|
LocalMapBase::onFrame(dt);
|
||||||
|
|
||||||
for (std::vector<CellId>::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it)
|
for (std::vector<CellId>::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it)
|
||||||
{
|
{
|
||||||
mGlobalMapRender->exploreCell(it->first, it->second);
|
mGlobalMapRender->exploreCell(it->first, it->second);
|
||||||
|
@ -497,7 +515,6 @@ namespace MWGui
|
||||||
else
|
else
|
||||||
mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff );
|
mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff );
|
||||||
|
|
||||||
|
|
||||||
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,9 +538,6 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::open()
|
void MapWindow::open()
|
||||||
{
|
{
|
||||||
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
|
||||||
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
|
||||||
|
|
||||||
// force markers to foreground
|
// force markers to foreground
|
||||||
for (unsigned int i=0; i<mGlobalMapOverlay->getChildCount (); ++i)
|
for (unsigned int i=0; i<mGlobalMapOverlay->getChildCount (); ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace MWGui
|
||||||
void setPlayerDir(const float x, const float y);
|
void setPlayerDir(const float x, const float y);
|
||||||
void setPlayerPos(const float x, const float y);
|
void setPlayerPos(const float x, const float y);
|
||||||
|
|
||||||
|
void onFrame(float dt);
|
||||||
|
|
||||||
bool toggleFogOfWar();
|
bool toggleFogOfWar();
|
||||||
|
|
||||||
struct MarkerPosition
|
struct MarkerPosition
|
||||||
|
@ -73,12 +75,14 @@ namespace MWGui
|
||||||
virtual void notifyMapChanged() {}
|
virtual void notifyMapChanged() {}
|
||||||
|
|
||||||
// Update markers (Detect X effects, Mark/Recall effects)
|
// Update markers (Detect X effects, Mark/Recall effects)
|
||||||
// Note, door markers handled in setActiveCell
|
// Note, door markers are handled in setActiveCell
|
||||||
void updateMarkers();
|
void updateMarkers();
|
||||||
void addDetectionMarkers(int type);
|
void addDetectionMarkers(int type);
|
||||||
|
|
||||||
OEngine::GUI::Layout* mLayout;
|
OEngine::GUI::Layout* mLayout;
|
||||||
|
|
||||||
|
float mMarkerUpdateTimer;
|
||||||
|
|
||||||
bool mMapDragAndDrop;
|
bool mMapDragAndDrop;
|
||||||
|
|
||||||
float mLastPositionX;
|
float mLastPositionX;
|
||||||
|
|
|
@ -25,6 +25,23 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageBoxManager::clear()
|
||||||
|
{
|
||||||
|
delete mInterMessageBoxe;
|
||||||
|
mInterMessageBoxe = NULL;
|
||||||
|
|
||||||
|
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
|
||||||
|
for (; it != mMessageBoxes.end(); ++it)
|
||||||
|
{
|
||||||
|
if (*it == mStaticMessageBox)
|
||||||
|
mStaticMessageBox = NULL;
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
mMessageBoxes.clear();
|
||||||
|
|
||||||
|
mLastButtonPressed = -1;
|
||||||
|
}
|
||||||
|
|
||||||
void MessageBoxManager::onFrame (float frameDuration)
|
void MessageBoxManager::onFrame (float frameDuration)
|
||||||
{
|
{
|
||||||
std::vector<MessageBox*>::iterator it;
|
std::vector<MessageBox*>::iterator it;
|
||||||
|
|
|
@ -30,6 +30,9 @@ namespace MWGui
|
||||||
bool createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons);
|
bool createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons);
|
||||||
bool isInteractiveMessageBox ();
|
bool isInteractiveMessageBox ();
|
||||||
|
|
||||||
|
/// Remove all message boxes
|
||||||
|
void clear();
|
||||||
|
|
||||||
bool removeMessageBox (MessageBox *msgbox);
|
bool removeMessageBox (MessageBox *msgbox);
|
||||||
void setMessageBoxSpeed (int speed);
|
void setMessageBoxSpeed (int speed);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "spellwindow.hpp"
|
#include "spellwindow.hpp"
|
||||||
|
|
||||||
#include "itemwidget.hpp"
|
#include "itemwidget.hpp"
|
||||||
|
#include "sortfilteritemmodel.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -134,6 +135,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
mItemSelectionDialog->setVisible(true);
|
mItemSelectionDialog->setVisible(true);
|
||||||
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
|
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||||
|
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
||||||
|
|
||||||
mAssignDialog->setVisible (false);
|
mAssignDialog->setVisible (false);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +164,7 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex > 0);
|
assert (mSelectedIndex >= 0);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||||
while (button->getChildCount()) // Destroy number label
|
while (button->getChildCount()) // Destroy number label
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||||
|
@ -184,7 +186,7 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex > 0);
|
assert (mSelectedIndex >= 0);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||||
while (button->getChildCount()) // Destroy number label
|
while (button->getChildCount()) // Destroy number label
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||||
|
@ -203,7 +205,7 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex > 0);
|
assert (mSelectedIndex >= 0);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||||
while (button->getChildCount()) // Destroy number label
|
while (button->getChildCount()) // Destroy number label
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||||
|
@ -245,7 +247,7 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::activateQuickKey(int index)
|
void QuickKeysMenu::activateQuickKey(int index)
|
||||||
{
|
{
|
||||||
assert (index-1 > 0);
|
assert (index-1 >= 0);
|
||||||
ItemWidget* button = mQuickKeyButtons[index-1];
|
ItemWidget* button = mQuickKeyButtons[index-1];
|
||||||
|
|
||||||
QuickKeyType type = mAssigned[index-1];
|
QuickKeyType type = mAssigned[index-1];
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue