mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 21:15:33 +00:00
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
|
||||
apps/openmw/config.hpp
|
||||
components/version/version.hpp
|
||||
Docs/mainpage.hpp
|
||||
docs/mainpage.hpp
|
||||
moc_*.cxx
|
||||
*.cxx_parameters
|
||||
*qrc_launcher.cxx
|
||||
|
|
|
@ -56,7 +56,7 @@ include(OpenMWMacros)
|
|||
|
||||
# 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(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
|
||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(BUILD_WITH_DPKG "enable dpkg-based install for debian and debian derivatives" OFF)
|
||||
if(BUILD_WITH_DPKG)
|
||||
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
|
||||
endif(BUILD_WITH_DPKG)
|
||||
endif(UNIX AND NOT APPLE)
|
||||
|
||||
# Location of morrowind data files
|
||||
if (APPLE)
|
||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||
|
@ -395,46 +388,36 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
|||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
## Debian and non debian Linux building
|
||||
# Linux building
|
||||
# Paths
|
||||
IF (DPKG_PROGRAM)
|
||||
## Debian specific
|
||||
SET(CMAKE_INSTALL_PREFIX "/usr")
|
||||
SET(DATAROOTDIR "share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(DATADIR "share/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "share/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(SYSCONFDIR "../etc/openmw" CACHE PATH "Set config dir")
|
||||
ELSE ()
|
||||
## Non debian specific
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(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")
|
||||
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(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_BSATOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_BSATOOL)
|
||||
IF(BUILD_ESMTOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_OPENCS)
|
||||
# Install binaries
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_BSATOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_BSATOOL)
|
||||
IF(BUILD_ESMTOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_OPENCS)
|
||||
|
||||
# Install licenses
|
||||
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||
ENDIF (DPKG_PROGRAM)
|
||||
# Install licenses
|
||||
INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||
|
||||
# Install icon and desktop file
|
||||
INSTALL(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_SOURCE_DIR}/readme.txt"
|
||||
"${OpenMW_SOURCE_DIR}/GPL3.txt"
|
||||
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
|
||||
"${OpenMW_SOURCE_DIR}/Docs/license/GPL3.txt"
|
||||
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
|
||||
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
||||
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
|
||||
|
@ -630,8 +613,10 @@ if (WIN32)
|
|||
4127 # Conditional expression is constant
|
||||
4242 # Storing value in a variable of a smaller type, possible loss of data
|
||||
4244 # Storing value of one type in variable of another (size_t in int, for example)
|
||||
4267 # Conversion from 'size_t' to 'int', possible loss of data
|
||||
4305 # Truncating value (double to float, for example)
|
||||
4309 # Variable overflow, trying to store 128 in a signed char for example
|
||||
4351 # New behavior: elements of array 'array' will be default initialized (desired behavior)
|
||||
4355 # Using 'this' in member initialization list
|
||||
4505 # Unreferenced local function has been removed
|
||||
4701 # Potentially uninitialized local variable used
|
||||
|
@ -650,7 +635,9 @@ if (WIN32)
|
|||
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
|
||||
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS})
|
||||
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||
# 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})
|
||||
if (BUILD_LAUNCHER)
|
||||
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 << " Hidden: " << mData.mData.mIsHidden << std::endl;
|
||||
if (mData.mData.mUnknown != -1)
|
||||
std::cout << " Unknown: " << mData.mData.mUnknown << std::endl;
|
||||
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
|
||||
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
||||
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
||||
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
||||
for (int i = 0; i != 6; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
if (mData.mData.mSkills[i] != -1)
|
||||
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
|
||||
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
|
||||
|
|
|
@ -119,10 +119,6 @@ endif(NOT WIN32)
|
|||
|
||||
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(omwlauncher gcov)
|
||||
|
|
|
@ -22,8 +22,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||
add_definitions (--coverage)
|
||||
target_link_libraries(mwiniimport gcov)
|
||||
endif()
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ opencs_units (view/render
|
|||
|
||||
opencs_units_noqt (view/render
|
||||
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
|
||||
lightingbright
|
||||
lightingbright object cell
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/world
|
||||
|
@ -200,10 +200,6 @@ target_link_libraries(opencs
|
|||
components
|
||||
)
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS opencs RUNTIME DESTINATION games COMPONENT opencs)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
endif()
|
||||
|
|
|
@ -31,8 +31,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con
|
|||
&mLoader, SLOT (loadDocument (CSMDoc::Document *)));
|
||||
connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)),
|
||||
this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)));
|
||||
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)),
|
||||
this, SIGNAL (nextRecord (CSMDoc::Document *)));
|
||||
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *, int)),
|
||||
this, SIGNAL (nextRecord (CSMDoc::Document *, int)));
|
||||
connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)),
|
||||
&mLoader, SLOT (abortLoading (CSMDoc::Document *)));
|
||||
connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
||||
|
|
|
@ -79,9 +79,10 @@ namespace CSMDoc
|
|||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||
const std::string& error);
|
||||
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name,
|
||||
int totalRecords);
|
||||
|
||||
void nextRecord (CSMDoc::Document *document);
|
||||
void nextRecord (CSMDoc::Document *document, int records);
|
||||
|
||||
void cancelLoading (CSMDoc::Document *document);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "document.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {}
|
||||
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLoaded (0), mRecordsLeft (false) {}
|
||||
|
||||
|
||||
CSMDoc::Loader::Loader()
|
||||
|
@ -39,13 +39,14 @@ void CSMDoc::Loader::load()
|
|||
Document *document = iter->first;
|
||||
|
||||
int size = static_cast<int> (document->getContentFiles().size());
|
||||
int editedIndex = size-1; // index of the file to be edited/created
|
||||
|
||||
if (document->isNew())
|
||||
--size;
|
||||
|
||||
bool done = false;
|
||||
|
||||
const int batchingSize = 100;
|
||||
const int batchingSize = 50;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -58,17 +59,21 @@ void CSMDoc::Loader::load()
|
|||
iter->second.mRecordsLeft = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
++(iter->second.mRecordsLoaded);
|
||||
|
||||
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||
|
||||
{ // silence a g++ warning
|
||||
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
|
||||
iter!=messages.end(); ++iter)
|
||||
{
|
||||
document->getReport (log)->add (iter->first, iter->second);
|
||||
emit loadMessage (document, iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
emit nextRecord (document);
|
||||
emit nextRecord (document, iter->second.mRecordsLoaded);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -77,17 +82,19 @@ void CSMDoc::Loader::load()
|
|||
{
|
||||
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
||||
|
||||
int steps = document->getData().startLoading (path, iter->second.mFile<size-1, false);
|
||||
int steps = document->getData().startLoading (path, iter->second.mFile!=editedIndex, false);
|
||||
iter->second.mRecordsLeft = true;
|
||||
iter->second.mRecordsLoaded = 0;
|
||||
|
||||
emit nextStage (document, path.filename().string(), steps/batchingSize);
|
||||
emit nextStage (document, path.filename().string(), steps);
|
||||
}
|
||||
else if (iter->second.mFile==size)
|
||||
{
|
||||
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
|
||||
iter->second.mRecordsLeft = true;
|
||||
iter->second.mRecordsLoaded = 0;
|
||||
|
||||
emit nextStage (document, "Project File", steps/batchingSize);
|
||||
emit nextStage (document, "Project File", steps);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace CSMDoc
|
|||
struct Stage
|
||||
{
|
||||
int mFile;
|
||||
int mRecordsLoaded;
|
||||
bool mRecordsLeft;
|
||||
|
||||
Stage();
|
||||
|
@ -56,9 +57,10 @@ namespace CSMDoc
|
|||
///< Document load has been interrupted either because of a call to abortLoading
|
||||
/// or a problem during loading). In the former case error will be an empty string.
|
||||
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name,
|
||||
int totalRecords);
|
||||
|
||||
void nextRecord (CSMDoc::Document *document);
|
||||
void nextRecord (CSMDoc::Document *document, int records);
|
||||
///< \note This signal is only given once per group of records. The group size is
|
||||
/// approximately the total number of records divided by the steps value of the
|
||||
/// previous nextStage signal.
|
||||
|
|
|
@ -42,7 +42,7 @@ void CSMTools::FactionCheckStage::perform (int stage, Messages& messages)
|
|||
// test for non-unique skill
|
||||
std::map<int, int> skills; // ID, number of occurrences
|
||||
|
||||
for (int i=0; i<6; ++i)
|
||||
for (int i=0; i<7; ++i)
|
||||
if (faction.mData.mSkills[i]!=-1)
|
||||
++skills[faction.mData.mSkills[i]];
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ namespace CSMWorld
|
|||
bool hasEnums (ColumnId column);
|
||||
|
||||
std::vector<std::string> getEnums (ColumnId column);
|
||||
///< Returns an empty vector, if \æ column isn't an enum type column.
|
||||
///< Returns an empty vector, if \a column isn't an enum type column.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
|
||||
#include "commanddispatcher.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
#include "idtable.hpp"
|
||||
|
@ -88,6 +92,13 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked)
|
|||
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
|
||||
{
|
||||
mSelection = selection;
|
||||
std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::toLower);
|
||||
std::sort (mSelection.begin(), mSelection.end());
|
||||
}
|
||||
|
||||
void CSMWorld::CommandDispatcher::setExtendedTypes (const std::vector<UniversalId>& types)
|
||||
{
|
||||
mExtendedTypes = types;
|
||||
}
|
||||
|
||||
bool CSMWorld::CommandDispatcher::canDelete() const
|
||||
|
@ -106,6 +117,20 @@ bool CSMWorld::CommandDispatcher::canRevert() const
|
|||
return getRevertableRecords().size()!=0;
|
||||
}
|
||||
|
||||
std::vector<CSMWorld::UniversalId> CSMWorld::CommandDispatcher::getExtendedTypes() const
|
||||
{
|
||||
std::vector<CSMWorld::UniversalId> tables;
|
||||
|
||||
if (mId==UniversalId::Type_Cells)
|
||||
{
|
||||
tables.push_back (mId);
|
||||
tables.push_back (UniversalId::Type_References);
|
||||
/// \todo add other cell-specific types
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
void CSMWorld::CommandDispatcher::executeDelete()
|
||||
{
|
||||
if (mLocked)
|
||||
|
@ -163,3 +188,80 @@ void CSMWorld::CommandDispatcher::executeRevert()
|
|||
if (rows.size()>1)
|
||||
mDocument.getUndoStack().endMacro();
|
||||
}
|
||||
|
||||
void CSMWorld::CommandDispatcher::executeExtendedDelete()
|
||||
{
|
||||
if (mExtendedTypes.size()>1)
|
||||
mDocument.getUndoStack().beginMacro (tr ("Extended delete of multiple records"));
|
||||
|
||||
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
|
||||
iter!=mExtendedTypes.end(); ++iter)
|
||||
{
|
||||
if (*iter==mId)
|
||||
executeDelete();
|
||||
else if (*iter==UniversalId::Type_References)
|
||||
{
|
||||
IdTable& model = dynamic_cast<IdTable&> (
|
||||
*mDocument.getData().getTableModel (*iter));
|
||||
|
||||
const RefCollection& collection = mDocument.getData().getReferences();
|
||||
|
||||
int size = collection.getSize();
|
||||
|
||||
for (int i=size-1; i>=0; --i)
|
||||
{
|
||||
const Record<CellRef>& record = collection.getRecord (i);
|
||||
|
||||
if (record.mState==RecordBase::State_Deleted)
|
||||
continue;
|
||||
|
||||
if (!std::binary_search (mSelection.begin(), mSelection.end(),
|
||||
Misc::StringUtils::lowerCase (record.get().mCell)))
|
||||
continue;
|
||||
|
||||
mDocument.getUndoStack().push (
|
||||
new CSMWorld::DeleteCommand (model, record.get().mId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mExtendedTypes.size()>1)
|
||||
mDocument.getUndoStack().endMacro();
|
||||
}
|
||||
|
||||
void CSMWorld::CommandDispatcher::executeExtendedRevert()
|
||||
{
|
||||
if (mExtendedTypes.size()>1)
|
||||
mDocument.getUndoStack().beginMacro (tr ("Extended revert of multiple records"));
|
||||
|
||||
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
|
||||
iter!=mExtendedTypes.end(); ++iter)
|
||||
{
|
||||
if (*iter==mId)
|
||||
executeRevert();
|
||||
else if (*iter==UniversalId::Type_References)
|
||||
{
|
||||
IdTable& model = dynamic_cast<IdTable&> (
|
||||
*mDocument.getData().getTableModel (*iter));
|
||||
|
||||
const RefCollection& collection = mDocument.getData().getReferences();
|
||||
|
||||
int size = collection.getSize();
|
||||
|
||||
for (int i=size-1; i>=0; --i)
|
||||
{
|
||||
const Record<CellRef>& record = collection.getRecord (i);
|
||||
|
||||
if (!std::binary_search (mSelection.begin(), mSelection.end(),
|
||||
Misc::StringUtils::lowerCase (record.get().mCell)))
|
||||
continue;
|
||||
|
||||
mDocument.getUndoStack().push (
|
||||
new CSMWorld::RevertCommand (model, record.get().mId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mExtendedTypes.size()>1)
|
||||
mDocument.getUndoStack().endMacro();
|
||||
}
|
|
@ -22,6 +22,7 @@ namespace CSMWorld
|
|||
CSMDoc::Document& mDocument;
|
||||
UniversalId mId;
|
||||
std::vector<std::string> mSelection;
|
||||
std::vector<UniversalId> mExtendedTypes;
|
||||
|
||||
std::vector<std::string> getDeletableRecords() const;
|
||||
|
||||
|
@ -37,16 +38,31 @@ namespace CSMWorld
|
|||
|
||||
void setSelection (const std::vector<std::string>& selection);
|
||||
|
||||
void setExtendedTypes (const std::vector<UniversalId>& types);
|
||||
///< Set record lists selected by the user for extended operations.
|
||||
|
||||
bool canDelete() const;
|
||||
|
||||
bool canRevert() const;
|
||||
|
||||
/// Return IDs of the record collection that can also be affected when
|
||||
/// operating on the record collection this dispatcher is used for.
|
||||
///
|
||||
/// \note The returned collection contains the ID of the record collection this
|
||||
/// dispatcher is used for. However if that record collection does not support
|
||||
/// the extended mode, the returned vector will be empty instead.
|
||||
std::vector<UniversalId> getExtendedTypes() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void executeDelete();
|
||||
|
||||
void executeRevert();
|
||||
|
||||
void executeExtendedDelete();
|
||||
|
||||
void executeExtendedRevert();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
|
|||
mFactions.addColumn (new AttributesColumn<ESM::Faction> (0));
|
||||
mFactions.addColumn (new AttributesColumn<ESM::Faction> (1));
|
||||
mFactions.addColumn (new HiddenColumn<ESM::Faction>);
|
||||
for (int i=0; i<6; ++i)
|
||||
for (int i=0; i<7; ++i)
|
||||
mFactions.addColumn (new SkillsColumn<ESM::Faction> (i));
|
||||
|
||||
mRaces.addColumn (new StringIdColumn<ESM::Race>);
|
||||
|
@ -742,4 +742,4 @@ void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex&
|
|||
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
|
||||
{
|
||||
emit idListChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||
baseColumns.mId = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
|
||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true, false));
|
||||
baseColumns.mModified = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType,
|
||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||
|
|
|
@ -45,7 +45,7 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
|||
mFileProgress->setValue (0);
|
||||
|
||||
// record progress
|
||||
mLayout->addWidget (new QLabel ("Records", this));
|
||||
mLayout->addWidget (mRecords = new QLabel ("Records", this));
|
||||
|
||||
mRecordProgress = new QProgressBar (this);
|
||||
|
||||
|
@ -75,22 +75,30 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
|||
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()));
|
||||
|
||||
mFileProgress->setValue (mFileProgress->value()+1);
|
||||
|
||||
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())
|
||||
mRecordProgress->setValue (value);
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "Records: " << records << " of " << mTotalRecords;
|
||||
|
||||
mRecords->setText (QString::fromUtf8 (stream.str().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
if (iter!=mDocuments.end())
|
||||
iter->second->nextRecord();
|
||||
iter->second->nextRecord (records);
|
||||
}
|
||||
|
||||
void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message)
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace CSVDoc
|
|||
|
||||
CSMDoc::Document *mDocument;
|
||||
QLabel *mFile;
|
||||
QLabel *mRecords;
|
||||
QProgressBar *mFileProgress;
|
||||
QProgressBar *mRecordProgress;
|
||||
bool mAborted;
|
||||
|
@ -33,6 +34,7 @@ namespace CSVDoc
|
|||
QLabel *mError;
|
||||
QListWidget *mMessages;
|
||||
QVBoxLayout *mLayout;
|
||||
int mTotalRecords;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -42,9 +44,9 @@ namespace CSVDoc
|
|||
|
||||
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);
|
||||
|
||||
|
@ -88,9 +90,9 @@ namespace CSVDoc
|
|||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||
const std::string& error);
|
||||
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||
void nextStage (CSMDoc::Document *document, const std::string& name, int totalRecords);
|
||||
|
||||
void nextRecord (CSMDoc::Document *document);
|
||||
void nextRecord (CSMDoc::Document *document, int records);
|
||||
|
||||
void 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)));
|
||||
|
||||
connect (
|
||||
&mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)),
|
||||
&mLoader, SLOT (nextRecord (CSMDoc::Document *)));
|
||||
&mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *, int)),
|
||||
&mLoader, SLOT (nextRecord (CSMDoc::Document *, int)));
|
||||
|
||||
connect (
|
||||
&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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
@ -54,4 +58,4 @@ void CSVFilter::FilterBox::createFilterRequest (std::vector< std::pair< std::str
|
|||
Qt::DropAction 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 <OgreCamera.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)
|
||||
: 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)
|
||||
{
|
||||
if (!hint.empty())
|
||||
|
@ -47,6 +170,10 @@ void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
|||
void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSelection& selection)
|
||||
{
|
||||
mSelection = selection;
|
||||
|
||||
if (adjustCells())
|
||||
flagAsModified();
|
||||
|
||||
emit cellSelectionChanged (mSelection);
|
||||
}
|
||||
|
||||
|
@ -72,6 +199,9 @@ void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::
|
|||
}
|
||||
if (selectionChanged)
|
||||
{
|
||||
if (adjustCells())
|
||||
flagAsModified();
|
||||
|
||||
emit cellSelectionChanged(mSelection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
||||
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../../model/world/cellselection.hpp"
|
||||
|
||||
#include "worldspacewidget.hpp"
|
||||
#include "cell.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
|
@ -11,12 +14,32 @@ namespace CSVRender
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMDoc::Document& mDocument;
|
||||
CSMWorld::CellSelection mSelection;
|
||||
std::map<CSMWorld::CellCoordinates, Cell *> mCells;
|
||||
|
||||
private:
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
/// hint system.
|
||||
|
||||
virtual ~PagedWorldspaceWidget();
|
||||
|
||||
void useViewHint (const std::string& hint);
|
||||
|
||||
void setCellSelection (const CSMWorld::CellSelection& selection);
|
||||
|
|
|
@ -7,194 +7,119 @@
|
|||
#include "../../model/world/data.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);
|
||||
|
||||
mNode = getSceneManager()->getRootSceneNode()->createChildSceneNode();
|
||||
mNode->setPosition (Ogre::Vector3 (0, 0, 0));
|
||||
|
||||
setModel();
|
||||
|
||||
QAbstractItemModel *referenceables =
|
||||
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);
|
||||
|
||||
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)),
|
||||
this, SLOT (ReferenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||
}
|
||||
this, SLOT (referenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||
|
||||
void CSVRender::PreviewWidget::setModel()
|
||||
{
|
||||
if (mNode)
|
||||
if (!referenceable)
|
||||
{
|
||||
mObject.setNull();
|
||||
QAbstractItemModel *references =
|
||||
mData.getTableModel (CSMWorld::UniversalId::Type_References);
|
||||
|
||||
if (mReferenceableId.empty())
|
||||
return;
|
||||
|
||||
int column =
|
||||
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);
|
||||
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::adjust()
|
||||
{
|
||||
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,
|
||||
void CSVRender::PreviewWidget::referenceableDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
if (mReferenceableId.empty())
|
||||
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();
|
||||
if (mObject.referenceableDataChanged (topLeft, bottomRight))
|
||||
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)
|
||||
{
|
||||
if (mReferenceableId.empty())
|
||||
if (mObject.referenceableAboutToBeRemoved (parent, start, end))
|
||||
flagAsModified();
|
||||
|
||||
if (mObject.getReferenceableId().empty())
|
||||
return;
|
||||
|
||||
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
|
||||
*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 (mReferenceId.empty())
|
||||
if (mObject.getReferenceId().empty())
|
||||
{
|
||||
// this is a preview for a referenceble
|
||||
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)
|
||||
{
|
||||
if (mReferenceId.empty())
|
||||
if (mObject.referenceDataChanged (topLeft, bottomRight))
|
||||
flagAsModified();
|
||||
|
||||
if (mObject.getReferenceId().empty())
|
||||
return;
|
||||
|
||||
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||
*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);
|
||||
|
||||
QModelIndex index = references.getModelIndex (mReferenceId, columnIndex);
|
||||
QModelIndex index = references.getModelIndex (mObject.getReferenceId(), columnIndex);
|
||||
|
||||
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())
|
||||
{
|
||||
mReferenceableId = references.data (index).toString().toUtf8().constData();
|
||||
emit referenceableIdChanged (mReferenceableId);
|
||||
setModel();
|
||||
}
|
||||
|
||||
flagAsModified();
|
||||
}
|
||||
emit referenceableIdChanged (mObject.getReferenceableId());
|
||||
}
|
||||
|
||||
void CSVRender::PreviewWidget::ReferenceAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||
void CSVRender::PreviewWidget::referenceAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||
int end)
|
||||
{
|
||||
if (mReferenceId.empty())
|
||||
if (mObject.getReferenceId().empty())
|
||||
return;
|
||||
|
||||
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
||||
*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)
|
||||
emit closeRequest();
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
|
||||
#define OPENCS_VIEW_PREVIEWWIDGET_H
|
||||
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
|
||||
#include "scenewidget.hpp"
|
||||
|
||||
#include "navigationorbit.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
|
@ -22,26 +21,13 @@ namespace CSVRender
|
|||
|
||||
CSMWorld::Data& mData;
|
||||
CSVRender::NavigationOrbit mOrbit;
|
||||
NifOgre::ObjectScenePtr mObject;
|
||||
Ogre::SceneNode *mNode;
|
||||
std::string mReferenceId;
|
||||
std::string mReferenceableId;
|
||||
|
||||
void setup();
|
||||
|
||||
void setModel();
|
||||
|
||||
void adjust();
|
||||
///< Adjust referenceable preview according to the reference
|
||||
Object mObject;
|
||||
|
||||
public:
|
||||
|
||||
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
|
||||
PreviewWidget (CSMWorld::Data& data, const std::string& id, bool referenceable,
|
||||
QWidget *parent = 0);
|
||||
|
||||
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
|
||||
const std::string& referenceId, QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
void closeRequest();
|
||||
|
@ -50,14 +36,14 @@ namespace CSVRender
|
|||
|
||||
private slots:
|
||||
|
||||
void ReferenceableDataChanged (const QModelIndex& topLeft,
|
||||
void referenceableDataChanged (const QModelIndex& topLeft,
|
||||
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->lookAt (0, 0, 0);
|
||||
mCamera->setNearClipDistance (0.1);
|
||||
mCamera->setFarClipDistance (30000);
|
||||
mCamera->setFarClipDistance (300000); ///< \todo make this configurable
|
||||
mCamera->roll (Ogre::Degree (90));
|
||||
|
||||
setLighting (&mLightingDay);
|
||||
|
@ -87,7 +87,7 @@ namespace CSVRender
|
|||
|
||||
std::stringstream windowHandle;
|
||||
#ifdef WIN32
|
||||
windowHandle << Ogre::StringConverter::toString((unsigned long)(this->winId()));
|
||||
windowHandle << Ogre::StringConverter::toString((uintptr_t)(this->winId()));
|
||||
#else
|
||||
windowHandle << this->winId();
|
||||
#endif
|
||||
|
@ -137,6 +137,11 @@ namespace CSVRender
|
|||
return mSceneMgr;
|
||||
}
|
||||
|
||||
Ogre::Camera *SceneWidget::getCamera()
|
||||
{
|
||||
return mCamera;
|
||||
}
|
||||
|
||||
void SceneWidget::flagAsModified()
|
||||
{
|
||||
mUpdate = true;
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace CSVRender
|
|||
|
||||
Ogre::SceneManager *getSceneManager();
|
||||
|
||||
Ogre::Camera *getCamera();
|
||||
|
||||
void flagAsModified();
|
||||
|
||||
void setDefaultAmbient (const Ogre::ColourValue& colour);
|
||||
|
|
|
@ -21,6 +21,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
|
|||
setDefaultAmbient (colour);
|
||||
|
||||
/// \todo deal with mSunlight and mFog/mForDensity
|
||||
|
||||
flagAsModified();
|
||||
}
|
||||
|
||||
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&> (
|
||||
*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&)),
|
||||
this, SLOT (cellDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||
|
||||
update();
|
||||
|
||||
mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId));
|
||||
}
|
||||
|
||||
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
|
||||
|
@ -72,6 +79,62 @@ void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld
|
|||
mCellId = data.begin()->getId();
|
||||
update();
|
||||
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
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define OPENCS_VIEW_UNPAGEDWORLDSPACEWIDGET_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "worldspacewidget.hpp"
|
||||
#include "cell.hpp"
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
|
@ -25,6 +27,8 @@ namespace CSVRender
|
|||
|
||||
std::string mCellId;
|
||||
CSMWorld::IdTable *mCellsModel;
|
||||
CSMWorld::IdTable *mReferenceablesModel;
|
||||
std::auto_ptr<Cell> mCell;
|
||||
|
||||
void update();
|
||||
|
||||
|
@ -37,6 +41,21 @@ namespace CSVRender
|
|||
|
||||
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:
|
||||
|
||||
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||
|
|
|
@ -10,15 +10,30 @@
|
|||
#include "../world/scenetoolmode.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)
|
||||
{
|
||||
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
|
||||
ent->setMaterialName("BaseWhite");
|
||||
|
||||
getSceneManager()->getRootSceneNode()->attachObject(ent);
|
||||
|
||||
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)
|
||||
|
@ -120,9 +135,11 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
|
|||
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
|
||||
{
|
||||
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))
|
||||
{
|
||||
emit dataDropped(mime->getData());
|
||||
} //not handling drops from different documents at the moment
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CSVRender
|
|||
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);
|
||||
///< \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);
|
||||
|
||||
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:
|
||||
|
||||
void closeRequest();
|
||||
|
|
|
@ -23,10 +23,10 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
|
|||
referenceableIdChanged (referenceableId);
|
||||
|
||||
mScene =
|
||||
new CSVRender::PreviewWidget (document.getData(), referenceableId, id.getId(), this);
|
||||
new CSVRender::PreviewWidget (document.getData(), id.getId(), false, this);
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
|
@ -382,6 +382,9 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
|
|||
}
|
||||
|
||||
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))
|
||||
{
|
||||
CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region));
|
||||
|
@ -402,4 +405,4 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
|
|||
|
||||
mRegionId = record.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,19 +45,36 @@ CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& docum
|
|||
|
||||
void CSVWorld::ScriptEdit::dragEnterEvent (QDragEnterEvent* event)
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->acceptProposedAction();
|
||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||
if (!mime)
|
||||
QTextEdit::dragEnterEvent(event);
|
||||
else
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event)
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->accept();
|
||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||
if (!mime)
|
||||
QTextEdit::dragMoveEvent(event);
|
||||
else
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
|
||||
{
|
||||
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()));
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
|
||||
mDispatcher->setSelection (records);
|
||||
|
||||
std::vector<CSMWorld::UniversalId> extendedTypes = mDispatcher->getExtendedTypes();
|
||||
|
||||
mDispatcher->setExtendedTypes (extendedTypes);
|
||||
|
||||
// create context menu
|
||||
QMenu menu (this);
|
||||
|
||||
|
@ -63,11 +67,21 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
menu.addAction (mCreateAction);
|
||||
|
||||
if (mDispatcher->canRevert())
|
||||
{
|
||||
menu.addAction (mRevertAction);
|
||||
|
||||
if (!extendedTypes.empty())
|
||||
menu.addAction (mExtendedRevertAction);
|
||||
}
|
||||
|
||||
if (mDispatcher->canDelete())
|
||||
{
|
||||
menu.addAction (mDeleteAction);
|
||||
|
||||
if (!extendedTypes.empty())
|
||||
menu.addAction (mExtendedDeleteAction);
|
||||
}
|
||||
|
||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
||||
{
|
||||
/// \todo allow reordering of multiple rows
|
||||
|
@ -101,12 +115,12 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
|
||||
if (selectedRows.size()==1)
|
||||
{
|
||||
int row = selectedRows.begin()->row();
|
||||
|
||||
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
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());
|
||||
|
@ -203,6 +226,18 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
|
||||
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)),
|
||||
this, SLOT (tableSizeUpdate()));
|
||||
|
||||
|
@ -351,7 +386,12 @@ void CSVWorld::Table::previewRecord()
|
|||
{
|
||||
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());
|
||||
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||
return;
|
||||
|
||||
if (mime->fromDocument (mDocument))
|
||||
{
|
||||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace CSVWorld
|
|||
QAction *mMoveDownAction;
|
||||
QAction *mViewAction;
|
||||
QAction *mPreviewAction;
|
||||
QAction *mExtendedDeleteAction;
|
||||
QAction *mExtendedRevertAction;
|
||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||
CSMWorld::IdTable *mModel;
|
||||
int mRecordStatusDisplay;
|
||||
|
|
|
@ -131,6 +131,9 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
|
|||
{
|
||||
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
|
||||
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);
|
||||
if (handled)
|
||||
{
|
||||
|
|
|
@ -256,6 +256,9 @@ void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
|
|||
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
|
||||
{
|
||||
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());
|
||||
//WIP
|
||||
}
|
||||
|
|
|
@ -73,9 +73,9 @@ namespace CSVWorld
|
|||
~CommandDelegateFactoryCollection();
|
||||
|
||||
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,
|
||||
QObject *parent) const;
|
||||
|
|
|
@ -15,7 +15,7 @@ add_openmw_dir (mwrender
|
|||
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
|
||||
actors objects renderinginterface localmap occlusionquery water shadows
|
||||
characterpreview globalmap videoplayer ripplesimulation refraction
|
||||
terrainstorage renderconst effectmanager weaponanimation
|
||||
terrainstorage renderconst effectmanager weaponanimation terraingrid
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -142,10 +142,6 @@ if(APPLE)
|
|||
endif()
|
||||
endif(APPLE)
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw)
|
||||
endif(DPKG_PROGRAM)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw gcov)
|
||||
|
|
|
@ -128,7 +128,7 @@ static void gdb_info(pid_t pid)
|
|||
int fd;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
fprintf(f, "attach %d\n"
|
||||
|
@ -381,10 +381,7 @@ static void crash_handler(const char *logfile)
|
|||
|
||||
if(logfile)
|
||||
{
|
||||
char cwd[MAXPATHLEN];
|
||||
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 !";
|
||||
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 !";
|
||||
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), NULL);
|
||||
}
|
||||
exit(0);
|
||||
|
|
|
@ -91,7 +91,11 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
if (mUseSound)
|
||||
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
|
||||
MWBase::Environment::get().getStateManager()->update (frametime);
|
||||
|
@ -99,15 +103,18 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||
MWBase::StateManager::State_Running)
|
||||
{
|
||||
// global scripts
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
||||
|
||||
// local scripts
|
||||
executeLocalScripts();
|
||||
|
||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||
|
||||
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(
|
||||
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
|
||||
}
|
||||
|
@ -118,14 +125,14 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
MWBase::StateManager::State_NoGame)
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->update(frametime,
|
||||
paused);
|
||||
guiActive);
|
||||
}
|
||||
|
||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||
MWBase::StateManager::State_Running)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -133,7 +140,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
if (MWBase::Environment::get().getStateManager()->getState()!=
|
||||
MWBase::StateManager::State_NoGame)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->update(frametime, paused);
|
||||
MWBase::Environment::get().getWorld()->update(frametime, guiActive);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab);
|
||||
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
|
||||
return;
|
||||
|
||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
||||
|
||||
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);
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->activate(ptr, MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||
}
|
||||
|
||||
void OMW::Engine::screenshot()
|
||||
|
|
|
@ -4,19 +4,20 @@
|
|||
#include <components/version/version.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_messagebox.h>
|
||||
#include <SDL_main.h>
|
||||
#include "engine.hpp"
|
||||
|
||||
#if defined(_WIN32) && !defined(_CONSOLE)
|
||||
#include <boost/iostreams/concepts.hpp>
|
||||
#include <boost/iostreams/stream_buffer.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#if defined(_WIN32)
|
||||
// For OutputDebugString
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
// makes __argc and __argv available on windows
|
||||
#include <cstdlib>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -253,58 +254,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
#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 defined(_WIN32) && defined(_DEBUG)
|
||||
|
||||
#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
|
||||
{
|
||||
public:
|
||||
|
@ -318,11 +269,11 @@ public:
|
|||
}
|
||||
};
|
||||
#else
|
||||
class Logger : public boost::iostreams::sink
|
||||
class Tee : public boost::iostreams::sink
|
||||
{
|
||||
public:
|
||||
Logger(std::ofstream &stream)
|
||||
: out(stream)
|
||||
Tee(std::ostream &stream, std::ostream &stream2)
|
||||
: out(stream), out2(stream2)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -330,38 +281,107 @@ public:
|
|||
{
|
||||
out.write (str, size);
|
||||
out.flush();
|
||||
out2.write (str, size);
|
||||
out2.flush();
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ofstream &out;
|
||||
std::ostream &out;
|
||||
std::ostream &out2;
|
||||
};
|
||||
#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;
|
||||
#if defined(_DEBUG)
|
||||
// Redirect cout to VS debug output when running in debug mode
|
||||
try
|
||||
{
|
||||
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;
|
||||
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::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;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -76,6 +76,9 @@ namespace MWBase
|
|||
|
||||
/// @return faction1's opinion of faction2
|
||||
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;
|
||||
///< 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;
|
||||
///< Iterator pointing to the begin of the main journal.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
|
@ -13,6 +14,9 @@ namespace Ogre
|
|||
namespace ESM
|
||||
{
|
||||
struct Class;
|
||||
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
|
@ -21,6 +25,11 @@ namespace MWWorld
|
|||
class CellStore;
|
||||
}
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
/// \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,
|
||||
* 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.
|
||||
* @return was the crime reported?
|
||||
*/
|
||||
|
@ -174,6 +184,18 @@ namespace MWBase
|
|||
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor) = 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 bool getSubtitlesEnabled() = 0;
|
||||
virtual void toggleHud() = 0;
|
||||
virtual bool toggleGui() = 0;
|
||||
|
||||
virtual void disallowMouse() = 0;
|
||||
virtual void allowMouse() = 0;
|
||||
|
@ -328,6 +329,8 @@ namespace MWBase
|
|||
/** Used when one Modal adds another Modal
|
||||
\param input Pointer to the current modal, to ensure proper modal is removed **/
|
||||
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;
|
||||
///< 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 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;
|
||||
///< 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)
|
||||
|
||||
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,
|
||||
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,
|
||||
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
|
||||
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,
|
||||
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;
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -168,7 +168,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
||||
ptr.get<ESM::Armor>();
|
||||
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue;
|
||||
}
|
||||
|
||||
void Armor::registerSelf()
|
||||
|
@ -244,7 +244,7 @@ namespace MWClass
|
|||
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
|
||||
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -190,7 +190,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -286,7 +286,12 @@ namespace MWClass
|
|||
{
|
||||
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.
|
||||
readState (state2.mInventory);
|
||||
|
|
|
@ -59,35 +59,38 @@ namespace
|
|||
|
||||
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
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
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>();
|
||||
|
||||
// creature stats
|
||||
|
@ -345,7 +348,9 @@ namespace MWClass
|
|||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
// 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);
|
||||
|
||||
if(!successful)
|
||||
|
@ -374,9 +379,9 @@ namespace MWClass
|
|||
if (damage > 0.f)
|
||||
{
|
||||
// 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()
|
||||
* 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]
|
||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
||||
{
|
||||
|
@ -520,9 +525,10 @@ namespace MWClass
|
|||
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||
const GMST& gmst = getGmst();
|
||||
|
||||
float walkSpeed = fMinWalkSpeedCreature->getFloat() + 0.01 * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||
* (fMaxWalkSpeedCreature->getFloat() - fMinWalkSpeedCreature->getFloat());
|
||||
float walkSpeed = gmst.fMinWalkSpeedCreature->getFloat() + 0.01 * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||
* (gmst.fMaxWalkSpeedCreature->getFloat() - gmst.fMinWalkSpeedCreature->getFloat());
|
||||
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||
|
@ -531,8 +537,8 @@ namespace MWClass
|
|||
|
||||
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||
|
||||
float runSpeed = walkSpeed*(0.01f * getSkill(ptr, ESM::Skill::Athletics) *
|
||||
fAthleticsRunBonus->getFloat() + fBaseRunMultiplier->getFloat());
|
||||
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
||||
float runSpeed = walkSpeed;
|
||||
|
||||
float moveSpeed;
|
||||
if(normalizedEncumbrance >= 1.0f)
|
||||
|
@ -542,8 +548,8 @@ namespace MWClass
|
|||
{
|
||||
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = std::max(0.0f, flySpeed);
|
||||
moveSpeed = flySpeed;
|
||||
}
|
||||
|
@ -553,8 +559,8 @@ namespace MWClass
|
|||
if(running)
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
||||
fSwimRunAthleticsMult->getFloat();
|
||||
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
||||
gmst.fSwimRunAthleticsMult->getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
}
|
||||
else if(running)
|
||||
|
@ -711,7 +717,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||
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
|
||||
|
@ -719,7 +725,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||
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)
|
||||
|
@ -796,7 +802,27 @@ namespace MWClass
|
|||
{
|
||||
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());
|
||||
|
||||
|
@ -835,8 +861,7 @@ namespace MWClass
|
|||
ptr.getRefData().setCount(1);
|
||||
|
||||
// Reset to original position
|
||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
||||
pos = ptr.getCellRef().getPosition();
|
||||
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||
|
||||
ptr.getRefData().setCustomData(NULL);
|
||||
}
|
||||
|
@ -850,19 +875,4 @@ namespace MWClass
|
|||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
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 const ESM::GameSetting *fMinWalkSpeedCreature;
|
||||
static const ESM::GameSetting *fMaxWalkSpeedCreature;
|
||||
static const ESM::GameSetting *fEncumberedMoveEffect;
|
||||
static const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||
static const ESM::GameSetting *fAthleticsRunBonus;
|
||||
static const ESM::GameSetting *fBaseRunMultiplier;
|
||||
static const ESM::GameSetting *fMinFlySpeed;
|
||||
static const ESM::GameSetting *fMaxFlySpeed;
|
||||
static const ESM::GameSetting *fSwimRunBase;
|
||||
static const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||
static const ESM::GameSetting *fKnockDownMult;
|
||||
static const ESM::GameSetting *iKnockDownOddsMult;
|
||||
static const ESM::GameSetting *iKnockDownOddsBase;
|
||||
// cached GMSTs
|
||||
struct GMST
|
||||
{
|
||||
const ESM::GameSetting *fMinWalkSpeedCreature;
|
||||
const ESM::GameSetting *fMaxWalkSpeedCreature;
|
||||
const ESM::GameSetting *fEncumberedMoveEffect;
|
||||
const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||
const ESM::GameSetting *fAthleticsRunBonus;
|
||||
const ESM::GameSetting *fBaseRunMultiplier;
|
||||
const ESM::GameSetting *fMinFlySpeed;
|
||||
const ESM::GameSetting *fMaxFlySpeed;
|
||||
const ESM::GameSetting *fSwimRunBase;
|
||||
const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||
const ESM::GameSetting *fKnockDownMult;
|
||||
const ESM::GameSetting *iKnockDownOddsMult;
|
||||
const ESM::GameSetting *iKnockDownOddsBase;
|
||||
};
|
||||
|
||||
static const GMST& getGmst();
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -57,11 +57,13 @@ namespace MWClass
|
|||
physics.addObject(ptr);
|
||||
|
||||
// Resume the door's opening/closing animation if it wasn't finished
|
||||
ensureCustomData(ptr);
|
||||
const DoorCustomData& customData = dynamic_cast<const DoorCustomData&>(*ptr.getRefData().getCustomData());
|
||||
if (customData.mDoorState > 0)
|
||||
if (ptr.getRefData().getCustomData())
|
||||
{
|
||||
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}");
|
||||
unlock(ptr); //Call the function here. because that makes sense.
|
||||
// using a key disarms the trap
|
||||
ptr.getCellRef().getTrap() = "";
|
||||
ptr.getCellRef().setTrap("");
|
||||
}
|
||||
|
||||
if (!needKey || hasKey)
|
||||
|
|
|
@ -144,7 +144,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
|
||||
ptr.get<ESM::Lockpick>();
|
||||
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue;
|
||||
}
|
||||
|
||||
void Lockpick::registerSelf()
|
||||
|
@ -138,7 +138,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -228,38 +228,44 @@ namespace
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
const Npc::GMST& Npc::getGmst()
|
||||
{
|
||||
static GMST gmst;
|
||||
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>();
|
||||
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||
|
||||
fMinWalkSpeed = gmst.find("fMinWalkSpeed");
|
||||
fMaxWalkSpeed = gmst.find("fMaxWalkSpeed");
|
||||
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");
|
||||
fJumpEncumbranceBase = gmst.find("fJumpEncumbranceBase");
|
||||
fJumpEncumbranceMultiplier = gmst.find("fJumpEncumbranceMultiplier");
|
||||
fJumpAcrobaticsBase = gmst.find("fJumpAcrobaticsBase");
|
||||
fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier");
|
||||
fJumpRunMultiplier = gmst.find("fJumpRunMultiplier");
|
||||
fWereWolfRunMult = gmst.find("fWereWolfRunMult");
|
||||
fKnockDownMult = gmst.find("fKnockDownMult");
|
||||
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
||||
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
||||
fDamageStrengthBase = gmst.find("fDamageStrengthBase");
|
||||
fDamageStrengthMult = gmst.find("fDamageStrengthMult");
|
||||
gmst.fMinWalkSpeed = store.find("fMinWalkSpeed");
|
||||
gmst.fMaxWalkSpeed = store.find("fMaxWalkSpeed");
|
||||
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.fJumpEncumbranceBase = store.find("fJumpEncumbranceBase");
|
||||
gmst.fJumpEncumbranceMultiplier = store.find("fJumpEncumbranceMultiplier");
|
||||
gmst.fJumpAcrobaticsBase = store.find("fJumpAcrobaticsBase");
|
||||
gmst.fJumpAcroMultiplier = store.find("fJumpAcroMultiplier");
|
||||
gmst.fJumpRunMultiplier = store.find("fJumpRunMultiplier");
|
||||
gmst.fWereWolfRunMult = store.find("fWereWolfRunMult");
|
||||
gmst.fKnockDownMult = store.find("fKnockDownMult");
|
||||
gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult");
|
||||
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
|
||||
gmst.fDamageStrengthBase = store.find("fDamageStrengthBase");
|
||||
gmst.fDamageStrengthMult = store.find("fDamageStrengthMult");
|
||||
|
||||
inited = true;
|
||||
}
|
||||
return gmst;
|
||||
}
|
||||
|
||||
void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
std::auto_ptr<NpcCustomData> data(new NpcCustomData);
|
||||
|
@ -404,11 +410,6 @@ namespace MWClass
|
|||
ptr.get<ESM::NPC>();
|
||||
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";
|
||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||
if(race->mData.mFlags & ESM::Race::Beast)
|
||||
|
@ -423,9 +424,9 @@ namespace MWClass
|
|||
if(getNpcStats(ptr).isWerewolf())
|
||||
{
|
||||
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>();
|
||||
|
@ -450,7 +451,9 @@ namespace MWClass
|
|||
void Npc::hit(const MWWorld::Ptr& ptr, int type) const
|
||||
{
|
||||
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())
|
||||
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||
|
@ -461,9 +464,9 @@ namespace MWClass
|
|||
|
||||
// Reduce fatigue
|
||||
// somewhat of a guess, but using the weapon weight makes sense
|
||||
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
|
||||
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
|
||||
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
|
||||
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
|
||||
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
|
||||
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
|
||||
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
|
||||
const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr);
|
||||
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||
|
@ -472,10 +475,10 @@ namespace MWClass
|
|||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||
getCreatureStats(ptr).setFatigue(fatigue);
|
||||
|
||||
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
|
||||
const float fCombatDistance = store.find("fCombatDistance")->getFloat();
|
||||
float dist = fCombatDistance * (!weapon.isEmpty() ?
|
||||
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
||||
gmst.find("fHandToHandReach")->getFloat());
|
||||
store.find("fHandToHandReach")->getFloat());
|
||||
|
||||
// TODO: Use second to work out the hit angle
|
||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
||||
|
@ -522,8 +525,8 @@ namespace MWClass
|
|||
if(attack)
|
||||
{
|
||||
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
||||
damage *= fDamageStrengthBase->getFloat() +
|
||||
(stats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult->getFloat() * 0.1);
|
||||
damage *= gmst.fDamageStrengthBase->getFloat() +
|
||||
(stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.fDamageStrengthMult->getFloat() * 0.1);
|
||||
if(weaphashealth)
|
||||
{
|
||||
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon);
|
||||
|
@ -535,7 +538,7 @@ namespace MWClass
|
|||
{
|
||||
// Reduce weapon charge by at least one, but cap at 0
|
||||
weaphealth -= std::min(std::max(1,
|
||||
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weaphealth);
|
||||
(int)(damage * store.find("fWeaponDamageMult")->getFloat())), weaphealth);
|
||||
|
||||
weapon.getCellRef().setCharge(weaphealth);
|
||||
}
|
||||
|
@ -552,8 +555,8 @@ namespace MWClass
|
|||
// 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
|
||||
// option for it.
|
||||
float minstrike = gmst.find("fMinHandToHandMult")->getFloat();
|
||||
float maxstrike = gmst.find("fMaxHandToHandMult")->getFloat();
|
||||
float minstrike = store.find("fMinHandToHandMult")->getFloat();
|
||||
float maxstrike = store.find("fMaxHandToHandMult")->getFloat();
|
||||
damage = stats.getSkill(weapskill).getModified();
|
||||
damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength());
|
||||
|
||||
|
@ -567,7 +570,7 @@ namespace MWClass
|
|||
damage *= glob.find("WerewolfClawMult")->mValue.getFloat();
|
||||
}
|
||||
if(healthdmg)
|
||||
damage *= gmst.find("fHandtoHandHealthPer")->getFloat();
|
||||
damage *= store.find("fHandtoHandHealthPer")->getFloat();
|
||||
|
||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
if(stats.isWerewolf())
|
||||
|
@ -585,12 +588,12 @@ namespace MWClass
|
|||
bool detected = MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, victim);
|
||||
if(!detected)
|
||||
{
|
||||
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
|
||||
damage *= store.find("fCombatCriticalStrikeMult")->getFloat();
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
||||
}
|
||||
if (othercls.getCreatureStats(victim).getKnockedDown())
|
||||
damage *= gmst.find("fCombatKODamageMult")->getFloat();
|
||||
damage *= store.find("fCombatKODamageMult")->getFloat();
|
||||
|
||||
// Apply "On hit" enchanted weapons
|
||||
std::string enchantmentName = !weapon.isEmpty() ? weapon.getClass().getEnchantment(weapon) : "";
|
||||
|
@ -624,11 +627,12 @@ namespace MWClass
|
|||
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||
|
||||
// Attacking peaceful NPCs is a crime
|
||||
// anything below 80 is considered peaceful (see Actors::updateActor)
|
||||
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);
|
||||
|
||||
bool wasDead = getCreatureStats(ptr).isDead();
|
||||
|
||||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
if(!successful)
|
||||
|
@ -660,6 +664,8 @@ namespace MWClass
|
|||
// something, alert the character controller, scripts, etc.
|
||||
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
const GMST& gmst = getGmst();
|
||||
|
||||
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < chance)
|
||||
|
@ -668,9 +674,9 @@ namespace MWClass
|
|||
}
|
||||
|
||||
// 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()
|
||||
* 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]
|
||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
||||
{
|
||||
|
@ -752,6 +758,22 @@ namespace MWClass
|
|||
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
||||
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
|
||||
|
@ -853,6 +875,8 @@ namespace MWClass
|
|||
float Npc::getSpeed(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const GMST& gmst = getGmst();
|
||||
|
||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
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 running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||
|
||||
float walkSpeed = fMinWalkSpeed->getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
||||
(fMaxWalkSpeed->getFloat() - fMinWalkSpeed->getFloat());
|
||||
walkSpeed *= 1.0f - fEncumberedMoveEffect->getFloat()*normalizedEncumbrance;
|
||||
float walkSpeed = gmst.fMinWalkSpeed->getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
||||
(gmst.fMaxWalkSpeed->getFloat() - gmst.fMinWalkSpeed->getFloat());
|
||||
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat()*normalizedEncumbrance;
|
||||
walkSpeed = std::max(0.0f, walkSpeed);
|
||||
if(sneaking)
|
||||
walkSpeed *= fSneakSpeedMultiplier->getFloat();
|
||||
walkSpeed *= gmst.fSneakSpeedMultiplier->getFloat();
|
||||
|
||||
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())
|
||||
runSpeed *= fWereWolfRunMult->getFloat();
|
||||
runSpeed *= gmst.fWereWolfRunMult->getFloat();
|
||||
|
||||
float moveSpeed;
|
||||
if(normalizedEncumbrance >= 1.0f)
|
||||
|
@ -881,8 +905,8 @@ namespace MWClass
|
|||
{
|
||||
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = std::max(0.0f, flySpeed);
|
||||
moveSpeed = flySpeed;
|
||||
}
|
||||
|
@ -892,8 +916,8 @@ namespace MWClass
|
|||
if(running)
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||
fSwimRunAthleticsMult->getFloat();
|
||||
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||
gmst.fSwimRunAthleticsMult->getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
}
|
||||
else if(running && !sneaking)
|
||||
|
@ -909,9 +933,10 @@ namespace MWClass
|
|||
float Npc::getJump(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
const GMST& gmst = getGmst();
|
||||
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
|
||||
const float encumbranceTerm = fJumpEncumbranceBase->getFloat() +
|
||||
fJumpEncumbranceMultiplier->getFloat() *
|
||||
const float encumbranceTerm = gmst.fJumpEncumbranceBase->getFloat() +
|
||||
gmst.fJumpEncumbranceMultiplier->getFloat() *
|
||||
(1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr));
|
||||
|
||||
float a = npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified();
|
||||
|
@ -922,14 +947,14 @@ namespace MWClass
|
|||
a = 50.0f;
|
||||
}
|
||||
|
||||
float x = fJumpAcrobaticsBase->getFloat() +
|
||||
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
||||
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
||||
float x = gmst.fJumpAcrobaticsBase->getFloat() +
|
||||
std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->getFloat());
|
||||
x += 3.0f * b * gmst.fJumpAcroMultiplier->getFloat();
|
||||
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
||||
x *= encumbranceTerm;
|
||||
|
||||
if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
|
||||
x *= fJumpRunMultiplier->getFloat();
|
||||
x *= gmst.fJumpRunMultiplier->getFloat();
|
||||
x *= npcdata->mNpcStats.getFatigueTerm();
|
||||
x -= -627.2f;/*gravity constant*/
|
||||
x /= 3.0f;
|
||||
|
@ -940,19 +965,19 @@ namespace MWClass
|
|||
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) 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>();
|
||||
|
||||
const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat();
|
||||
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->getFloat();
|
||||
|
||||
if (fallHeight >= fallDistanceMin)
|
||||
{
|
||||
const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
||||
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||
const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat();
|
||||
const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
|
||||
const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat();
|
||||
|
||||
float x = fallHeight - fallDistanceMin;
|
||||
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
||||
|
@ -1087,14 +1112,14 @@ namespace MWClass
|
|||
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
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);
|
||||
MWWorld::InventoryStore &invStore = getInventoryStore(ptr);
|
||||
|
||||
int iBaseArmorSkill = gmst.find("iBaseArmorSkill")->getInt();
|
||||
float fUnarmoredBase1 = gmst.find("fUnarmoredBase1")->getFloat();
|
||||
float fUnarmoredBase2 = gmst.find("fUnarmoredBase2")->getFloat();
|
||||
int iBaseArmorSkill = store.find("iBaseArmorSkill")->getInt();
|
||||
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
|
||||
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
|
||||
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
|
||||
|
||||
int ratings[MWWorld::InventoryStore::Slots];
|
||||
|
@ -1276,7 +1301,18 @@ namespace MWClass
|
|||
{
|
||||
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());
|
||||
|
||||
|
@ -1325,8 +1361,7 @@ namespace MWClass
|
|||
ptr.getRefData().setCount(1);
|
||||
|
||||
// Reset to original position
|
||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
||||
pos = ptr.getCellRef().getPosition();
|
||||
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||
|
||||
ptr.getRefData().setCustomData(NULL);
|
||||
}
|
||||
|
@ -1340,27 +1375,4 @@ namespace MWClass
|
|||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
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
|
||||
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
|
||||
|
||||
static const ESM::GameSetting *fMinWalkSpeed;
|
||||
static const ESM::GameSetting *fMaxWalkSpeed;
|
||||
static const ESM::GameSetting *fEncumberedMoveEffect;
|
||||
static const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||
static const ESM::GameSetting *fAthleticsRunBonus;
|
||||
static const ESM::GameSetting *fBaseRunMultiplier;
|
||||
static const ESM::GameSetting *fMinFlySpeed;
|
||||
static const ESM::GameSetting *fMaxFlySpeed;
|
||||
static const ESM::GameSetting *fSwimRunBase;
|
||||
static const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||
static const ESM::GameSetting *fJumpEncumbranceBase;
|
||||
static const ESM::GameSetting *fJumpEncumbranceMultiplier;
|
||||
static const ESM::GameSetting *fJumpAcrobaticsBase;
|
||||
static const ESM::GameSetting *fJumpAcroMultiplier;
|
||||
static const ESM::GameSetting *fJumpRunMultiplier;
|
||||
static const ESM::GameSetting *fWereWolfRunMult;
|
||||
static const ESM::GameSetting *fKnockDownMult;
|
||||
static const ESM::GameSetting *iKnockDownOddsMult;
|
||||
static const ESM::GameSetting *iKnockDownOddsBase;
|
||||
static const ESM::GameSetting *fDamageStrengthBase;
|
||||
static const ESM::GameSetting *fDamageStrengthMult;
|
||||
struct GMST
|
||||
{
|
||||
const ESM::GameSetting *fMinWalkSpeed;
|
||||
const ESM::GameSetting *fMaxWalkSpeed;
|
||||
const ESM::GameSetting *fEncumberedMoveEffect;
|
||||
const ESM::GameSetting *fSneakSpeedMultiplier;
|
||||
const ESM::GameSetting *fAthleticsRunBonus;
|
||||
const ESM::GameSetting *fBaseRunMultiplier;
|
||||
const ESM::GameSetting *fMinFlySpeed;
|
||||
const ESM::GameSetting *fMaxFlySpeed;
|
||||
const ESM::GameSetting *fSwimRunBase;
|
||||
const ESM::GameSetting *fSwimRunAthleticsMult;
|
||||
const ESM::GameSetting *fJumpEncumbranceBase;
|
||||
const ESM::GameSetting *fJumpEncumbranceMultiplier;
|
||||
const ESM::GameSetting *fJumpAcrobaticsBase;
|
||||
const ESM::GameSetting *fJumpAcroMultiplier;
|
||||
const ESM::GameSetting *fJumpRunMultiplier;
|
||||
const ESM::GameSetting *fWereWolfRunMult;
|
||||
const ESM::GameSetting *fKnockDownMult;
|
||||
const ESM::GameSetting *iKnockDownOddsMult;
|
||||
const ESM::GameSetting *iKnockDownOddsBase;
|
||||
const ESM::GameSetting *fDamageStrengthBase;
|
||||
const ESM::GameSetting *fDamageStrengthMult;
|
||||
};
|
||||
|
||||
static const GMST& getGmst();
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -166,13 +166,8 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
||||
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 (
|
||||
new MWWorld::ActionApply (actor, ref->mBase->mId));
|
||||
new MWWorld::ActionApply (ptr, ref->mBase->mId));
|
||||
|
||||
action->setSound ("Drink");
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Probe> *ref =
|
||||
ptr.get<ESM::Probe>();
|
||||
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue;
|
||||
}
|
||||
|
||||
void Probe::registerSelf()
|
||||
|
@ -137,7 +137,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
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()) {
|
||||
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||
ptr.get<ESM::Repair>();
|
||||
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue;
|
||||
}
|
||||
|
||||
void Repair::registerSelf()
|
||||
|
@ -141,7 +141,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
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()) {
|
||||
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
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Static> *ref =
|
||||
ptr.get<ESM::Static>();
|
||||
|
||||
const std::string model = getModel(ptr);
|
||||
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 =
|
||||
ptr.get<ESM::Weapon>();
|
||||
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(getItemHealth(ptr)) / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue;
|
||||
}
|
||||
|
||||
void Weapon::registerSelf()
|
||||
|
@ -343,7 +343,7 @@ namespace MWClass
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -125,6 +125,10 @@ namespace MWDialogue
|
|||
|
||||
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 = "";
|
||||
mPermanentDispositionChange = 0;
|
||||
mTemporaryDispositionChange = 0;
|
||||
|
@ -140,7 +144,11 @@ namespace MWDialogue
|
|||
mActorKnownTopics.clear();
|
||||
|
||||
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
|
||||
updateTopics();
|
||||
|
@ -174,10 +182,20 @@ namespace MWDialogue
|
|||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
executeScript (info->mResultScript);
|
||||
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)
|
||||
|
@ -294,7 +312,7 @@ namespace MWDialogue
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -398,7 +416,7 @@ namespace MWDialogue
|
|||
win->setServices (windowServices);
|
||||
|
||||
// sort again, because the previous sort was case-sensitive
|
||||
keywordList.sort(Misc::StringUtils::ciEqual);
|
||||
keywordList.sort(Misc::StringUtils::ciLess);
|
||||
win->setKeywords(keywordList);
|
||||
|
||||
mChoice = choice;
|
||||
|
@ -472,7 +490,7 @@ namespace MWDialogue
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -694,6 +712,15 @@ namespace MWDialogue
|
|||
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> result;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace MWDialogue
|
|||
bool mTalkedTo;
|
||||
|
||||
int mChoice;
|
||||
std::string mLastTopic;
|
||||
std::string mLastTopic; // last topic ID, lowercase
|
||||
bool mIsInChoice;
|
||||
|
||||
float mTemporaryDispositionChange;
|
||||
|
@ -99,6 +99,9 @@ namespace MWDialogue
|
|||
|
||||
/// @return faction1's opinion of faction2
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
@ -5,16 +5,21 @@
|
|||
|
||||
#include <components/esm/journalentry.hpp>
|
||||
|
||||
#include <components/interpreter/defines.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwscript/interpretercontext.hpp"
|
||||
|
||||
|
||||
namespace MWDialogue
|
||||
{
|
||||
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)
|
||||
{
|
||||
const ESM::Dialogue *dialogue =
|
||||
|
@ -24,8 +29,17 @@ namespace MWDialogue
|
|||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mId == mInfoId)
|
||||
{
|
||||
/// \todo text replacement
|
||||
mText = iter->mResponse;
|
||||
if (actor.isEmpty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -49,8 +63,8 @@ namespace MWDialogue
|
|||
|
||||
JournalEntry::JournalEntry() {}
|
||||
|
||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId)
|
||||
: Entry (topic, infoId), mTopic (topic)
|
||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||
: Entry (topic, infoId, actor), mTopic (topic)
|
||||
{}
|
||||
|
||||
JournalEntry::JournalEntry (const ESM::JournalEntry& record)
|
||||
|
@ -65,7 +79,7 @@ namespace MWDialogue
|
|||
|
||||
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)
|
||||
|
@ -90,7 +104,7 @@ namespace MWDialogue
|
|||
|
||||
StampedJournalEntry::StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
||||
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)
|
||||
|
|
|
@ -8,6 +8,11 @@ namespace ESM
|
|||
struct JournalEntry;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
}
|
||||
|
||||
namespace MWDialogue
|
||||
{
|
||||
/// \brief Basic quest/dialogue/topic entry
|
||||
|
@ -19,7 +24,8 @@ namespace MWDialogue
|
|||
|
||||
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);
|
||||
|
||||
|
@ -37,7 +43,7 @@ namespace MWDialogue
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/esm/journalentry.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -103,15 +104,25 @@ namespace MWDialogue
|
|||
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);
|
||||
|
||||
JournalEntry entry(topicId, infoId);
|
||||
entry.mActorName = actorName;
|
||||
JournalEntry entry(topicId, infoId, actor);
|
||||
entry.mActorName = actor.getClass().getName(actor);
|
||||
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
|
||||
{
|
||||
TQuestContainer::const_iterator iter = mQuests.find (id);
|
||||
|
|
|
@ -38,7 +38,12 @@ namespace MWDialogue
|
|||
virtual int getJournalIndex (const std::string& id) const;
|
||||
///< 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;
|
||||
///< Iterator pointing to the begin of the main journal.
|
||||
|
|
|
@ -59,8 +59,16 @@ namespace MWDialogue
|
|||
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;
|
||||
|
||||
void removeLastAddedResponse (const std::string& actorName);
|
||||
|
||||
TEntryIter begin() const;
|
||||
///< Iterator pointing to the begin of the journal for this topic.
|
||||
|
||||
TEntryIter end() const;
|
||||
///< 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 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);
|
||||
|
||||
mBook->mPages.push_back (Page (curPageStart, curPageStop));
|
||||
|
|
|
@ -30,9 +30,9 @@ namespace MWGui
|
|||
|
||||
void ConfirmationDialog::exit()
|
||||
{
|
||||
eventCancelClicked();
|
||||
|
||||
setVisible(false);
|
||||
|
||||
eventCancelClicked();
|
||||
}
|
||||
|
||||
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
|
@ -42,8 +42,8 @@ namespace MWGui
|
|||
|
||||
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventOkClicked();
|
||||
|
||||
setVisible(false);
|
||||
|
||||
eventOkClicked();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,4 +435,10 @@ namespace MWGui
|
|||
{
|
||||
setSelectedObject(MWWorld::Ptr());
|
||||
}
|
||||
|
||||
void Console::resetReference()
|
||||
{
|
||||
ReferenceInterface::resetReference();
|
||||
setSelectedObject(MWWorld::Ptr());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ namespace MWGui
|
|||
|
||||
void executeFile (const std::string& path);
|
||||
|
||||
virtual void resetReference ();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void onReferenceUnavailable();
|
||||
|
|
|
@ -38,6 +38,32 @@ namespace MWGui
|
|||
mIsOnDragAndDrop = 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);
|
||||
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;
|
||||
mEnabled = true;
|
||||
bool sameActor = (mPtr == actor);
|
||||
mPtr = actor;
|
||||
mTopicsList->setEnabled(true);
|
||||
setTitle(npcName);
|
||||
|
@ -378,9 +379,12 @@ namespace MWGui
|
|||
|
||||
mTopicsList->clear();
|
||||
|
||||
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
||||
delete (*it);
|
||||
mHistoryContents.clear();
|
||||
if (resetHistory || !sameActor)
|
||||
{
|
||||
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)
|
||||
delete (*it);
|
||||
|
@ -582,13 +586,32 @@ namespace MWGui
|
|||
//Clear the list of topics
|
||||
mTopicsList->clear();
|
||||
|
||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||
bool dispositionVisible = false;
|
||||
if (mPtr.getClass().isNpc())
|
||||
{
|
||||
dispositionVisible = true;
|
||||
mDispositionBar->setProgressRange(100);
|
||||
mDispositionBar->setProgressPosition(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr));
|
||||
mDispositionText->eraseText(0, mDispositionText->getTextLength());
|
||||
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()
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace MWGui
|
|||
|
||||
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 addResponse (const std::string& text, const std::string& title="");
|
||||
|
@ -170,7 +170,7 @@ namespace MWGui
|
|||
BookPage* mHistory;
|
||||
Widgets::MWList* mTopicsList;
|
||||
MyGUI::ScrollBar* mScrollBar;
|
||||
MyGUI::ProgressPtr mDispositionBar;
|
||||
MyGUI::Progress* mDispositionBar;
|
||||
MyGUI::EditBox* mDispositionText;
|
||||
|
||||
PersuasionDialog mPersuasionDialog;
|
||||
|
|
|
@ -258,12 +258,16 @@ namespace MWGui
|
|||
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||
|
||||
// More hacks! The french game uses U+2019, which is nowhere to be found in
|
||||
// the CP437 encoding of the font. Fall back to 39 (regular apostrophe)
|
||||
if (i == 39 && mEncoding == ToUTF8::CP437)
|
||||
// More hacks! The french game uses several win1252 characters that are not included
|
||||
// in the cp437 encoding of the font. Fall back to similar available characters.
|
||||
// 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");
|
||||
code->addAttribute("index", 0x2019);
|
||||
code->addAttribute("index", additional[i]);
|
||||
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
||||
+ MyGUI::utility::toString(y1) + " "
|
||||
+ MyGUI::utility::toString(w) + " "
|
||||
|
|
|
@ -384,6 +384,8 @@ namespace MWGui
|
|||
|
||||
void HUD::onFrame(float dt)
|
||||
{
|
||||
LocalMapBase::onFrame(dt);
|
||||
|
||||
mCellNameTimer -= dt;
|
||||
mWeaponSpellTimer -= dt;
|
||||
if (mCellNameTimer < 0)
|
||||
|
|
|
@ -132,6 +132,11 @@ namespace MWGui
|
|||
adjustPanes();
|
||||
}
|
||||
|
||||
SortFilterItemModel* InventoryWindow::getSortFilterModel()
|
||||
{
|
||||
return mSortModel;
|
||||
}
|
||||
|
||||
TradeItemModel* InventoryWindow::getTradeModel()
|
||||
{
|
||||
return mTradeModel;
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace MWGui
|
|||
mPreview->rebuild();
|
||||
}
|
||||
|
||||
SortFilterItemModel* getSortFilterModel();
|
||||
TradeItemModel* getTradeModel();
|
||||
ItemModel* getModel();
|
||||
|
||||
|
|
|
@ -33,12 +33,26 @@ namespace MWGui
|
|||
|
||||
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)
|
||||
mItem->setImageTexture(icon);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
mFrame->setImageTexture(frame);
|
||||
|
@ -69,8 +83,21 @@ namespace MWGui
|
|||
if (ptr.isEmpty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace MWGui
|
|||
|
||||
MyGUI::ImageBox* mItem;
|
||||
MyGUI::ImageBox* mFrame;
|
||||
|
||||
std::string mCurrentItemTexture;
|
||||
std::string mCurrentFrameTexture;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -104,9 +104,10 @@ namespace MWGui
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace MWGui
|
|||
size_t viewRange = mScrollView->getCanvasSize().height;
|
||||
if(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)
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWGui
|
|||
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups ();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,10 +68,10 @@ namespace MWGui
|
|||
{
|
||||
if (visible)
|
||||
updateMenu();
|
||||
else
|
||||
showBackground(
|
||||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
||||
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
||||
|
||||
showBackground(
|
||||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
||||
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
||||
|
||||
OEngine::GUI::Layout::setVisible (visible);
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ namespace MWGui
|
|||
mVideo = mVideoBackground->createWidget<VideoWidget>("ImageBox", 0,0,1,1,
|
||||
MyGUI::Align::Stretch, "Menu");
|
||||
|
||||
mVideo->playVideo("video\\menu_background.bik", false);
|
||||
mVideo->playVideo("video\\menu_background.bik");
|
||||
}
|
||||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
@ -204,7 +204,7 @@ namespace MWGui
|
|||
if (!mVideo->update())
|
||||
{
|
||||
// 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();
|
||||
|
||||
showBackground(state == MWBase::StateManager::State_NoGame);
|
||||
mVersionText->setVisible(state == MWBase::StateManager::State_NoGame);
|
||||
|
||||
std::vector<std::string> buttons;
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
|||
, mLastDirectionX(0.0f)
|
||||
, mLastDirectionY(0.0f)
|
||||
, mCompass(NULL)
|
||||
, mMarkerUpdateTimer(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -345,6 +346,18 @@ namespace MWGui
|
|||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
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->render(loadingListener);
|
||||
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||
|
||||
mGlobalMapImage->setImageTexture("GlobalMap.png");
|
||||
mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
|
||||
}
|
||||
|
@ -471,6 +487,8 @@ namespace MWGui
|
|||
|
||||
void MapWindow::onFrame(float dt)
|
||||
{
|
||||
LocalMapBase::onFrame(dt);
|
||||
|
||||
for (std::vector<CellId>::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it)
|
||||
{
|
||||
mGlobalMapRender->exploreCell(it->first, it->second);
|
||||
|
@ -497,7 +515,6 @@ namespace MWGui
|
|||
else
|
||||
mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff );
|
||||
|
||||
|
||||
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||
}
|
||||
|
||||
|
@ -521,9 +538,6 @@ namespace MWGui
|
|||
|
||||
void MapWindow::open()
|
||||
{
|
||||
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||
|
||||
// force markers to foreground
|
||||
for (unsigned int i=0; i<mGlobalMapOverlay->getChildCount (); ++i)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace MWGui
|
|||
void setPlayerDir(const float x, const float y);
|
||||
void setPlayerPos(const float x, const float y);
|
||||
|
||||
void onFrame(float dt);
|
||||
|
||||
bool toggleFogOfWar();
|
||||
|
||||
struct MarkerPosition
|
||||
|
@ -73,12 +75,14 @@ namespace MWGui
|
|||
virtual void notifyMapChanged() {}
|
||||
|
||||
// Update markers (Detect X effects, Mark/Recall effects)
|
||||
// Note, door markers handled in setActiveCell
|
||||
// Note, door markers are handled in setActiveCell
|
||||
void updateMarkers();
|
||||
void addDetectionMarkers(int type);
|
||||
|
||||
OEngine::GUI::Layout* mLayout;
|
||||
|
||||
float mMarkerUpdateTimer;
|
||||
|
||||
bool mMapDragAndDrop;
|
||||
|
||||
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)
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it;
|
||||
|
|
|
@ -30,6 +30,9 @@ namespace MWGui
|
|||
bool createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons);
|
||||
bool isInteractiveMessageBox ();
|
||||
|
||||
/// Remove all message boxes
|
||||
void clear();
|
||||
|
||||
bool removeMessageBox (MessageBox *msgbox);
|
||||
void setMessageBoxSpeed (int speed);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "spellwindow.hpp"
|
||||
|
||||
#include "itemwidget.hpp"
|
||||
#include "sortfilteritemmodel.hpp"
|
||||
|
||||
|
||||
namespace MWGui
|
||||
|
@ -134,6 +135,7 @@ namespace MWGui
|
|||
}
|
||||
mItemSelectionDialog->setVisible(true);
|
||||
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
||||
|
||||
mAssignDialog->setVisible (false);
|
||||
}
|
||||
|
@ -162,7 +164,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -184,7 +186,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -203,7 +205,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -245,7 +247,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::activateQuickKey(int index)
|
||||
{
|
||||
assert (index-1 > 0);
|
||||
assert (index-1 >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[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