forked from teamnwah/openmw-tes3coop
Merge branch 'openmw-29' of https://github.com/zinnschlag/openmw.git into AIFix2
This commit is contained in:
commit
95ff869163
138 changed files with 3380 additions and 757 deletions
17
.travis.yml
17
.travis.yml
|
@ -4,17 +4,16 @@ compiler:
|
|||
branches:
|
||||
only:
|
||||
- master
|
||||
- next
|
||||
- /openmw-.*$/
|
||||
before_install:
|
||||
- pwd
|
||||
- git submodule update --init --recursive
|
||||
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
|
||||
- echo "yes" | sudo apt-add-repository ppa:openmw/openmw
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev uuid-dev
|
||||
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
|
||||
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
|
||||
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
|
||||
- sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock
|
||||
- sudo apt-get install -qq libqt4-dev
|
||||
- sudo apt-get install -qq libopenal-dev
|
||||
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
|
||||
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||
- sudo mkdir /usr/src/gtest/build
|
||||
- cd /usr/src/gtest/build
|
||||
|
@ -37,3 +36,9 @@ notifications:
|
|||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
irc:
|
||||
channels:
|
||||
- "chat.freenode.net#openmw"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
|
|
139
CMakeLists.txt
139
CMakeLists.txt
|
@ -4,40 +4,65 @@ if (APPLE)
|
|||
set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
||||
|
||||
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-F /Library/Frameworks")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-F /Library/Frameworks")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "-F /Library/Frameworks")
|
||||
endif (APPLE)
|
||||
|
||||
# Macros
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
include(OpenMWMacros)
|
||||
|
||||
# Version
|
||||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 28)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
get_git_tag_revision(TAGHASH --tags --max-count=1)
|
||||
get_git_head_revision(REFSPEC COMMITHASH)
|
||||
git_describe(VERSION --tags ${TAGHASH})
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
set(OPENMW_VERSION_TAGHASH "")
|
||||
|
||||
string(REGEX MATCH "^openmw-[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" MATCH "${VERSION}")
|
||||
if (MATCH)
|
||||
string(REGEX REPLACE "^openmw-([0-9]+)\\..*" "\\1" OPENMW_VERSION_MAJOR "${VERSION}")
|
||||
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_MINOR "${VERSION}")
|
||||
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_RELEASE "${VERSION}")
|
||||
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||
|
||||
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
|
||||
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
|
||||
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
|
||||
find_package(Git)
|
||||
|
||||
message(STATUS "Configuring OpenMW ${OPENMW_VERSION}...")
|
||||
else (MATCH)
|
||||
message(FATAL_ERROR "Failed to get valid version information from Git")
|
||||
endif (MATCH)
|
||||
if(GIT_FOUND)
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_tag_revision(TAGHASH --tags --max-count=1)
|
||||
get_git_head_revision(REFSPEC COMMITHASH)
|
||||
git_describe(VERSION --tags ${TAGHASH})
|
||||
|
||||
string(REGEX MATCH "^openmw-[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" MATCH "${VERSION}")
|
||||
if(MATCH)
|
||||
string(REGEX REPLACE "^openmw-([0-9]+)\\..*" "\\1" GIT_VERSION_MAJOR "${VERSION}")
|
||||
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}")
|
||||
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}")
|
||||
|
||||
set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}")
|
||||
|
||||
if(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
||||
message(FATAL_ERROR "Silly Zini forgot to update the version again...")
|
||||
else(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
||||
set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR})
|
||||
set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR})
|
||||
set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE})
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
|
||||
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
|
||||
endif(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
||||
|
||||
message(STATUS "OpenMW version ${OPENMW_VERSION}")
|
||||
else(MATCH)
|
||||
message(WARNING "Failed to get valid version information from Git")
|
||||
endif(MATCH)
|
||||
else(GIT_FOUND)
|
||||
message(WARNING "Git executable not found")
|
||||
endif(GIT_FOUND)
|
||||
else(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
|
||||
message(STATUS "Shallow Git clone detected, not attempting to retrieve version info")
|
||||
endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
|
||||
endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||
|
||||
# Macros
|
||||
include(OpenMWMacros)
|
||||
|
||||
# doxygen main page
|
||||
|
||||
|
@ -206,10 +231,6 @@ if (MSVC10)
|
|||
set(PLATFORM_INCLUDE_DIR "")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
endif (APPLE)
|
||||
|
||||
# Dependencies
|
||||
|
||||
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||
|
@ -260,10 +281,15 @@ link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MY
|
|||
if (APPLE)
|
||||
# List used Ogre plugins
|
||||
SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL}
|
||||
${OGRE_Plugin_OctreeSceneManager_LIBRARY_REL}
|
||||
${OGRE_Plugin_CgProgramManager_LIBRARY_REL}
|
||||
${OGRE_Plugin_ParticleFX_LIBRARY_REL})
|
||||
|
||||
# Actually we must use OGRE_Plugin_CgProgramManager_FOUND but it's
|
||||
# not reliable and equals TRUE even if there's no Ogre Cg plugin
|
||||
if (Cg_FOUND)
|
||||
set(USED_OGRE_PLUGINS ${USED_OGRE_PLUGINS}
|
||||
${OGRE_Plugin_CgProgramManager_LIBRARY_REL})
|
||||
endif ()
|
||||
|
||||
if (${OGRE_PLUGIN_DIR_REL}})
|
||||
set(OGRE_PLUGINS_REL_FOUND TRUE)
|
||||
endif ()
|
||||
|
@ -278,8 +304,6 @@ if (APPLE)
|
|||
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
|
||||
endif ()
|
||||
|
||||
#set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
|
||||
"${APP_BUNDLE_DIR}/Contents/Info.plist")
|
||||
|
||||
|
@ -301,7 +325,8 @@ endif()
|
|||
add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}")
|
||||
add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}")
|
||||
if (APPLE AND OPENMW_OSX_DEPLOYMENT)
|
||||
add_definitions(-DOGRE_PLUGIN_DIR="${APP_BUNDLE_NAME}/Contents/Plugins")
|
||||
# make it empty so plugin loading code can check this and try to find plugins inside app bundle
|
||||
add_definitions(-DOGRE_PLUGIN_DIR="")
|
||||
else()
|
||||
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
|
||||
endif()
|
||||
|
@ -657,14 +682,14 @@ if (APPLE)
|
|||
set(CPACK_GENERATOR "DragNDrop")
|
||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
|
||||
set(OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
|
||||
|
||||
set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/OpenCS.app")
|
||||
set(OPENCS_BUNDLE_NAME "OpenCS.app")
|
||||
set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
|
||||
|
||||
set(PLUGINS "")
|
||||
set(ABSOLUTE_PLUGINS "")
|
||||
|
||||
foreach (PLUGIN ${USED_OGRE_PLUGINS})
|
||||
|
@ -672,12 +697,36 @@ if (APPLE)
|
|||
set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS})
|
||||
endforeach ()
|
||||
|
||||
set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins")
|
||||
install(FILES ${ABSOLUTE_PLUGINS} DESTINATION "${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins" COMPONENT Runtime)
|
||||
foreach (PLUGIN ${ABSOLUTE_PLUGINS})
|
||||
get_filename_component(PLUGIN_RELATIVE ${PLUGIN} NAME)
|
||||
set(PLUGINS ${PLUGINS} "${PLUGIN_INSTALL_BASE}/${PLUGIN_RELATIVE}")
|
||||
endforeach ()
|
||||
install(CODE "
|
||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||
include(BundleUtilities)
|
||||
" COMPONENT Runtime)
|
||||
|
||||
# installs used plugins in bundle at given path (bundle_path must be relative to ${CMAKE_INSTALL_PREFIX})
|
||||
# and returns list of install paths for all installed plugins
|
||||
function (install_plugins_for_bundle bundle_path plugins_var)
|
||||
set(RELATIVE_PLUGIN_INSTALL_BASE "${bundle_path}/Contents/Frameworks")
|
||||
|
||||
set(PLUGINS "")
|
||||
set(PLUGIN_INSTALL_BASE "\${CMAKE_INSTALL_PREFIX}/${RELATIVE_PLUGIN_INSTALL_BASE}")
|
||||
|
||||
foreach (PLUGIN ${ABSOLUTE_PLUGINS})
|
||||
get_filename_component(PLUGIN_RELATIVE ${PLUGIN} NAME)
|
||||
get_filename_component(PLUGIN_RELATIVE_WE ${PLUGIN} NAME_WE)
|
||||
|
||||
set(PLUGIN_DYLIB_IN_BUNDLE "${PLUGIN_INSTALL_BASE}/${PLUGIN_RELATIVE}/${PLUGIN_RELATIVE_WE}")
|
||||
set(PLUGINS ${PLUGINS} "${PLUGIN_DYLIB_IN_BUNDLE}")
|
||||
|
||||
install(CODE "
|
||||
copy_resolved_framework_into_bundle(\"${PLUGIN}/${PLUGIN_RELATIVE_WE}\" \"${PLUGIN_DYLIB_IN_BUNDLE}\")
|
||||
" COMPONENT Runtime)
|
||||
endforeach ()
|
||||
|
||||
set(${plugins_var} ${PLUGINS} PARENT_SCOPE)
|
||||
endfunction (install_plugins_for_bundle)
|
||||
|
||||
install_plugins_for_bundle("${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}" PLUGINS)
|
||||
install_plugins_for_bundle("${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
|
||||
|
||||
#For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail
|
||||
set(DIRS "")
|
||||
|
@ -690,6 +739,7 @@ if (APPLE)
|
|||
# Current limitations:
|
||||
# 1. Handles only frameworks, not simple libs
|
||||
INSTALL(CODE "
|
||||
cmake_policy(SET CMP0009 OLD)
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH})
|
||||
|
@ -721,11 +771,8 @@ if (APPLE)
|
|||
endif()
|
||||
endfunction(gp_resolve_item_override)
|
||||
|
||||
cmake_policy(SET CMP0009 OLD)
|
||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||
include(BundleUtilities)
|
||||
fixup_bundle(\"${OPENMW_APP}\" \"${PLUGINS}\" \"${DIRS}\")
|
||||
fixup_bundle(\"${OPENCS_APP}\" \"\" \"${DIRS}\")
|
||||
fixup_bundle(\"${OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"${DIRS}\")
|
||||
" COMPONENT Runtime)
|
||||
include(CPack)
|
||||
endif (APPLE)
|
||||
|
|
|
@ -76,17 +76,20 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
|
|||
QString revision(OPENMW_VERSION_COMMITHASH);
|
||||
QString tag(OPENMW_VERSION_TAGHASH);
|
||||
|
||||
if (revision == tag) {
|
||||
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
|
||||
} else {
|
||||
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
|
||||
}
|
||||
if (!revision.isEmpty() && !tag.isEmpty())
|
||||
{
|
||||
if (revision == tag) {
|
||||
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
|
||||
} else {
|
||||
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
|
||||
}
|
||||
|
||||
// Add the compile date and time
|
||||
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
|
||||
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
|
||||
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
|
||||
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
|
||||
// Add the compile date and time
|
||||
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
|
||||
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
|
||||
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
|
||||
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
|
||||
}
|
||||
|
||||
createIcons();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ opencs_units (model/world
|
|||
|
||||
opencs_units_noqt (model/world
|
||||
universalid record commands columnbase scriptcontext cell refidcollection
|
||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection
|
||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
|
@ -38,7 +38,7 @@ opencs_units (model/tools
|
|||
|
||||
opencs_units_noqt (model/tools
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referenceablecheck
|
||||
birthsigncheck spellcheck referenceablecheck scriptcheck
|
||||
)
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
|
|||
opencs_units (view/world
|
||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
||||
scenetoolmode infocreator
|
||||
scenetoolmode infocreator scriptedit
|
||||
)
|
||||
|
||||
opencs_units (view/render
|
||||
|
|
|
@ -210,6 +210,8 @@ int CS::Editor::run()
|
|||
if (mLocal.empty())
|
||||
return 1;
|
||||
|
||||
// temporarily disable OGRE-integration (need to fix path problem first)
|
||||
#if 0
|
||||
// TODO: setting
|
||||
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
|
||||
|
||||
|
@ -221,8 +223,12 @@ int CS::Editor::run()
|
|||
params.insert(std::make_pair("FSAA", "0"));
|
||||
params.insert(std::make_pair("vsync", "false"));
|
||||
params.insert(std::make_pair("hidden", "true"));
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
params.insert(std::make_pair("macAPI", "cocoa"));
|
||||
#endif
|
||||
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, ¶ms);
|
||||
hiddenWindow->setActive(false);
|
||||
#endif
|
||||
|
||||
mStartup.show();
|
||||
|
||||
|
|
|
@ -44,8 +44,11 @@ int main(int argc, char *argv[])
|
|||
// SceneWidget destructor will delete the created render window, which would be called _after_ Root has shut down :(
|
||||
|
||||
Application mApplication (argc, argv);
|
||||
// temporarily disable OGRE-integration (need to fix path problem first)
|
||||
#if 0
|
||||
OgreInit::OgreInit ogreInit;
|
||||
ogreInit.init("./opencsOgre.log"); // TODO log path?
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
|
|
|
@ -71,7 +71,10 @@ namespace CSMDoc
|
|||
|
||||
public:
|
||||
|
||||
Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_);
|
||||
Document (const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath,
|
||||
const boost::filesystem::path& resDir, bool new_);
|
||||
|
||||
~Document();
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ namespace CSMDoc
|
|||
|
||||
~DocumentManager();
|
||||
|
||||
Document *addDocument (const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, bool new_);
|
||||
Document *addDocument (const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath,
|
||||
bool new_);
|
||||
///< The ownership of the returned document is not transferred to the caller.
|
||||
///
|
||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||
|
|
103
apps/opencs/model/tools/scriptcheck.cpp
Normal file
103
apps/opencs/model/tools/scriptcheck.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
|
||||
#include "scriptcheck.hpp"
|
||||
|
||||
#include <components/compiler/tokenloc.hpp>
|
||||
#include <components/compiler/scanner.hpp>
|
||||
#include <components/compiler/fileparser.hpp>
|
||||
#include <components/compiler/exception.hpp>
|
||||
#include <components/compiler/extensions0.hpp>
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
||||
Type type)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
stream << id.toString() << "|";
|
||||
|
||||
if (type==ErrorMessage)
|
||||
stream << "error ";
|
||||
else
|
||||
stream << "warning ";
|
||||
|
||||
stream
|
||||
<< "script " << mFile
|
||||
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
||||
<< " (" << loc.mLiteral << "): " << message;
|
||||
|
||||
mMessages->push_back (stream.str());
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
stream << id.toString() << "|";
|
||||
|
||||
if (type==ErrorMessage)
|
||||
stream << "error: ";
|
||||
else
|
||||
stream << "warning: ";
|
||||
|
||||
stream << message;
|
||||
|
||||
mMessages->push_back (stream.str());
|
||||
}
|
||||
|
||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
|
||||
: mData (data), mContext (data), mMessages (0)
|
||||
{
|
||||
/// \todo add an option to configure warning mode
|
||||
setWarningsMode (0);
|
||||
|
||||
Compiler::registerExtensions (mExtensions);
|
||||
mContext.setExtensions (&mExtensions);
|
||||
}
|
||||
|
||||
int CSMTools::ScriptCheckStage::setup()
|
||||
{
|
||||
mContext.clear();
|
||||
mMessages = 0;
|
||||
mId.clear();
|
||||
|
||||
return mData.getScripts().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::perform (int stage, std::vector<std::string>& messages)
|
||||
{
|
||||
mMessages = &messages;
|
||||
mId = mData.getScripts().getId (stage);
|
||||
|
||||
try
|
||||
{
|
||||
mFile = mData.getScripts().getRecord (stage).get().mId;
|
||||
std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText);
|
||||
|
||||
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
||||
|
||||
Compiler::FileParser parser (*this, mContext);
|
||||
|
||||
scanner.scan (parser);
|
||||
}
|
||||
catch (const Compiler::SourceException&)
|
||||
{
|
||||
// error has already been reported via error handler
|
||||
}
|
||||
catch (const std::exception& error)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
stream << id.toString() << "|Critical compile error: " << error.what();
|
||||
|
||||
messages.push_back (stream.str());
|
||||
}
|
||||
|
||||
mMessages = 0;
|
||||
}
|
41
apps/opencs/model/tools/scriptcheck.hpp
Normal file
41
apps/opencs/model/tools/scriptcheck.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef CSM_TOOLS_SCRIPTCHECK_H
|
||||
#define CSM_TOOLS_SCRIPTCHECK_H
|
||||
|
||||
#include <components/compiler/errorhandler.hpp>
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
#include "../world/scriptcontext.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
/// \brief VerifyStage: make sure that scripts compile
|
||||
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
||||
{
|
||||
const CSMWorld::Data& mData;
|
||||
Compiler::Extensions mExtensions;
|
||||
CSMWorld::ScriptContext mContext;
|
||||
std::string mId;
|
||||
std::string mFile;
|
||||
std::vector<std::string> *mMessages;
|
||||
|
||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||
///< Report error to the user.
|
||||
|
||||
virtual void report (const std::string& message, Type type);
|
||||
///< Report a file related error
|
||||
|
||||
public:
|
||||
|
||||
ScriptCheckStage (const CSMWorld::Data& data);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||
///< Messages resulting from this tage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -20,6 +20,7 @@
|
|||
#include "birthsigncheck.hpp"
|
||||
#include "spellcheck.hpp"
|
||||
#include "referenceablecheck.hpp"
|
||||
#include "scriptcheck.hpp"
|
||||
|
||||
CSMDoc::Operation *CSMTools::Tools::get (int type)
|
||||
{
|
||||
|
@ -77,6 +78,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
|||
mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
|
||||
|
||||
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
|
||||
|
||||
mVerifier->appendStage (new ScriptCheckStage (mData));
|
||||
}
|
||||
|
||||
return mVerifier;
|
||||
|
|
|
@ -26,7 +26,49 @@ namespace CSMWorld
|
|||
|
||||
enum Display
|
||||
{
|
||||
Display_None, //Do not use
|
||||
Display_String,
|
||||
|
||||
//CONCRETE TYPES STARTS HERE
|
||||
Display_Skill,
|
||||
Display_Class,
|
||||
Display_Faction,
|
||||
Display_Race,
|
||||
Display_Sound,
|
||||
Display_Region,
|
||||
Display_Birthsign,
|
||||
Display_Spell,
|
||||
Display_Cell,
|
||||
Display_Referenceable,
|
||||
Display_Activator,
|
||||
Display_Potion,
|
||||
Display_Apparatus,
|
||||
Display_Armor,
|
||||
Display_Book,
|
||||
Display_Clothing,
|
||||
Display_Container,
|
||||
Display_Creature,
|
||||
Display_Door,
|
||||
Display_Ingredient,
|
||||
Display_CreatureLevelledList,
|
||||
Display_ItemLevelledList,
|
||||
Display_Light,
|
||||
Display_Lockpick,
|
||||
Display_Miscellaneous,
|
||||
Display_Npc,
|
||||
Display_Probe,
|
||||
Display_Repair,
|
||||
Display_Static,
|
||||
Display_Weapon,
|
||||
Display_Reference,
|
||||
Display_Filter,
|
||||
Display_Topic,
|
||||
Display_Journal,
|
||||
Display_TopicInfo,
|
||||
Display_JournalInfo,
|
||||
Display_Scene,
|
||||
//CONCRETE TYPES ENDS HERE
|
||||
|
||||
Display_Integer,
|
||||
Display_Float,
|
||||
Display_Var,
|
||||
|
|
|
@ -373,7 +373,7 @@ namespace CSMWorld
|
|||
SkillsColumn (int index, bool typePrefix = false, bool major = false)
|
||||
: Column<ESXRecordT> ((typePrefix ? (
|
||||
major ? Columns::ColumnId_MajorSkill1 : Columns::ColumnId_MinorSkill1) :
|
||||
Columns::ColumnId_Skill1) + index, ColumnBase::Display_String),
|
||||
Columns::ColumnId_Skill1) + index, ColumnBase::Display_Skill),
|
||||
mIndex (index), mMajor (major)
|
||||
{}
|
||||
|
||||
|
@ -598,7 +598,7 @@ namespace CSMWorld
|
|||
struct SoundFileColumn : public Column<ESXRecordT>
|
||||
{
|
||||
SoundFileColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_String)
|
||||
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_Sound)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
|
@ -811,7 +811,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct CellColumn : public Column<ESXRecordT>
|
||||
{
|
||||
CellColumn() : Column<ESXRecordT> (Columns::ColumnId_Cell, ColumnBase::Display_String) {}
|
||||
CellColumn() : Column<ESXRecordT> (Columns::ColumnId_Cell, ColumnBase::Display_Cell) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -890,7 +890,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct OwnerColumn : public Column<ESXRecordT>
|
||||
{
|
||||
OwnerColumn() : Column<ESXRecordT> (Columns::ColumnId_Owner, ColumnBase::Display_String) {}
|
||||
OwnerColumn() : Column<ESXRecordT> (Columns::ColumnId_Owner, ColumnBase::Display_Npc) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -915,7 +915,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct SoulColumn : public Column<ESXRecordT>
|
||||
{
|
||||
SoulColumn() : Column<ESXRecordT> (Columns::ColumnId_Soul, ColumnBase::Display_String) {}
|
||||
SoulColumn() : Column<ESXRecordT> (Columns::ColumnId_Soul, ColumnBase::Display_Creature) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -940,7 +940,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct FactionColumn : public Column<ESXRecordT>
|
||||
{
|
||||
FactionColumn() : Column<ESXRecordT> (Columns::ColumnId_Faction, ColumnBase::Display_String) {}
|
||||
FactionColumn() : Column<ESXRecordT> (Columns::ColumnId_Faction, ColumnBase::Display_Faction) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1090,7 +1090,7 @@ namespace CSMWorld
|
|||
struct TeleportCellColumn : public Column<ESXRecordT>
|
||||
{
|
||||
TeleportCellColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_TeleportCell, ColumnBase::Display_String)
|
||||
: Column<ESXRecordT> (Columns::ColumnId_TeleportCell, ColumnBase::Display_Cell)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
|
@ -1146,7 +1146,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct KeyColumn : public Column<ESXRecordT>
|
||||
{
|
||||
KeyColumn() : Column<ESXRecordT> (Columns::ColumnId_Key, ColumnBase::Display_String) {}
|
||||
KeyColumn() : Column<ESXRecordT> (Columns::ColumnId_Key, ColumnBase::Display_Miscellaneous) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1485,7 +1485,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct RaceColumn : public Column<ESXRecordT>
|
||||
{
|
||||
RaceColumn() : Column<ESXRecordT> (Columns::ColumnId_Race, ColumnBase::Display_String) {}
|
||||
RaceColumn() : Column<ESXRecordT> (Columns::ColumnId_Race, ColumnBase::Display_Race) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1510,7 +1510,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct ClassColumn : public Column<ESXRecordT>
|
||||
{
|
||||
ClassColumn() : Column<ESXRecordT> (Columns::ColumnId_Class, ColumnBase::Display_String) {}
|
||||
ClassColumn() : Column<ESXRecordT> (Columns::ColumnId_Class, ColumnBase::Display_Class) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1535,7 +1535,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct PcFactionColumn : public Column<ESXRecordT>
|
||||
{
|
||||
PcFactionColumn() : Column<ESXRecordT> (Columns::ColumnId_PcFaction, ColumnBase::Display_String) {}
|
||||
PcFactionColumn() : Column<ESXRecordT> (Columns::ColumnId_PcFaction, ColumnBase::Display_Faction) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
|
|
@ -33,7 +33,9 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelI
|
|||
|
||||
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
||||
: QSortFilterProxyModel (parent)
|
||||
{}
|
||||
{
|
||||
setSortCaseSensitivity (Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Name, ColumnBase::Display_String));
|
||||
nameColumns.mName = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Script, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Script, ColumnBase::Display_Script));
|
||||
nameColumns.mScript = &mColumns.back();
|
||||
|
||||
InventoryColumns inventoryColumns (nameColumns);
|
||||
|
@ -214,10 +214,10 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
|
||||
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_Sound));
|
||||
const RefIdColumn *openSound = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_CloseSound, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_CloseSound, ColumnBase::Display_Sound));
|
||||
const RefIdColumn *closeSound = &mColumns.back();
|
||||
|
||||
LightColumns lightColumns (inventoryColumns);
|
||||
|
@ -231,7 +231,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Colour, ColumnBase::Display_Integer));
|
||||
lightColumns.mColor = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Sound, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Sound, ColumnBase::Display_Sound));
|
||||
lightColumns.mSound = &mColumns.back();
|
||||
|
||||
static const struct
|
||||
|
@ -263,13 +263,13 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
|
||||
NpcColumns npcColumns (actorsColumns);
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Race, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Race, ColumnBase::Display_Race));
|
||||
npcColumns.mRace = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Class, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Class, ColumnBase::Display_Class));
|
||||
npcColumns.mClass = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_String));
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction));
|
||||
npcColumns.mFaction = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_String));
|
||||
|
@ -432,7 +432,7 @@ void CSMWorld::RefIdCollection::removeRows (int index, int count)
|
|||
|
||||
void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, UniversalId::Type type)
|
||||
{
|
||||
mData.appendRecord (type, id);
|
||||
mData.appendRecord (type, id, false);
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::searchId (const std::string& id) const
|
||||
|
@ -450,7 +450,7 @@ void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record)
|
|||
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
|
||||
void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
|
||||
const std::string& destination,
|
||||
const CSMWorld::UniversalId::Type type)
|
||||
{
|
||||
|
@ -467,7 +467,7 @@ void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
|||
|
||||
int index = mData.getAppendIndex (type);
|
||||
|
||||
mData.appendRecord (type, id);
|
||||
mData.appendRecord (type, id, false);
|
||||
|
||||
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ void CSMWorld::RefIdCollection::load (ESM::ESMReader& reader, bool base, Univers
|
|||
{
|
||||
// new record
|
||||
int index = mData.getAppendIndex (type);
|
||||
mData.appendRecord (type, id);
|
||||
mData.appendRecord (type, id, base);
|
||||
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index)
|
|||
return iter->second->getRecord (index.first);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::string& id)
|
||||
void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::string& id, bool base)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (type);
|
||||
|
@ -139,7 +139,7 @@ void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::strin
|
|||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
iter->second->appendRecord (id);
|
||||
iter->second->appendRecord (id, base);
|
||||
|
||||
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
|
||||
LocalIndex (iter->second->getSize()-1, type)));
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace CSMWorld
|
|||
|
||||
virtual RecordBase& getRecord (int index)= 0;
|
||||
|
||||
virtual void appendRecord (const std::string& id) = 0;
|
||||
|
||||
virtual void appendRecord (const std::string& id, bool base) = 0;
|
||||
|
||||
virtual void insertRecord (RecordBase& record) = 0;
|
||||
|
||||
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
|
||||
|
@ -69,8 +69,8 @@ namespace CSMWorld
|
|||
|
||||
virtual RecordBase& getRecord (int index);
|
||||
|
||||
virtual void appendRecord (const std::string& id);
|
||||
|
||||
virtual void appendRecord (const std::string& id, bool base);
|
||||
|
||||
virtual void insertRecord (RecordBase& record);
|
||||
|
||||
virtual void load (int index, ESM::ESMReader& reader, bool base);
|
||||
|
@ -88,7 +88,7 @@ namespace CSMWorld
|
|||
Record<RecordT>& newRecord = dynamic_cast<Record<RecordT>& >(record);
|
||||
mContainer.push_back(newRecord);
|
||||
}
|
||||
|
||||
|
||||
template<typename RecordT>
|
||||
int RefIdDataContainer<RecordT>::getSize() const
|
||||
{
|
||||
|
@ -108,12 +108,15 @@ namespace CSMWorld
|
|||
}
|
||||
|
||||
template<typename RecordT>
|
||||
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id)
|
||||
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id, bool base)
|
||||
{
|
||||
Record<RecordT> record;
|
||||
|
||||
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||
|
||||
record.mBase.mId = id;
|
||||
record.mModified.mId = id;
|
||||
record.mModified.blank();
|
||||
record.mState = RecordBase::State_ModifiedOnly;
|
||||
(base ? record.mBase : record.mModified).blank();
|
||||
|
||||
mContainer.push_back (record);
|
||||
}
|
||||
|
@ -206,14 +209,14 @@ namespace CSMWorld
|
|||
LocalIndex searchId (const std::string& id) const;
|
||||
|
||||
void erase (int index, int count);
|
||||
|
||||
|
||||
void insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id);
|
||||
|
||||
const RecordBase& getRecord (const LocalIndex& index) const;
|
||||
|
||||
RecordBase& getRecord (const LocalIndex& index);
|
||||
|
||||
void appendRecord (UniversalId::Type type, const std::string& id);
|
||||
void appendRecord (UniversalId::Type type, const std::string& id, bool base);
|
||||
|
||||
int getAppendIndex (UniversalId::Type type) const;
|
||||
|
||||
|
|
|
@ -5,23 +5,92 @@
|
|||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/compiler/quickfileparser.hpp>
|
||||
#include <components/compiler/nullerrorhandler.hpp>
|
||||
#include <components/compiler/scanner.hpp>
|
||||
|
||||
#include "data.hpp"
|
||||
|
||||
CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUpdated (false) {}
|
||||
|
||||
bool CSMWorld::ScriptContext::canDeclareLocals() const
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const
|
||||
{
|
||||
int index = mData.getGlobals().searchId (name);
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
switch (mData.getGlobals().getRecord (index).get().mValue.getType())
|
||||
{
|
||||
case ESM::VT_Short: return 's';
|
||||
case ESM::VT_Long: return 'l';
|
||||
case ESM::VT_Float: return 'f';
|
||||
|
||||
default: return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return ' ';
|
||||
}
|
||||
|
||||
char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std::string& id) const
|
||||
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType (const std::string& name,
|
||||
const std::string& id) const
|
||||
{
|
||||
return ' ';
|
||||
/// \todo invalidate locals cache on change to scripts
|
||||
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
int index = mData.getScripts().searchId (id2);
|
||||
bool reference = false;
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
// ID is not a script ID. Search for a matching referenceable instead.
|
||||
index = mData.getReferenceables().searchId (id2);
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
// Referenceable found.
|
||||
int columnIndex = mData.getReferenceables().searchColumnIndex (Columns::ColumnId_Script);
|
||||
|
||||
if (columnIndex!=-1)
|
||||
{
|
||||
id2 = Misc::StringUtils::lowerCase (mData.getReferenceables().
|
||||
getData (index, columnIndex).toString().toUtf8().constData());
|
||||
|
||||
if (!id2.empty())
|
||||
{
|
||||
// Referenceable has a script -> use it.
|
||||
index = mData.getScripts().searchId (id2);
|
||||
reference = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index==-1)
|
||||
return std::make_pair (' ', false);
|
||||
|
||||
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find (id2);
|
||||
|
||||
if (iter==mLocals.end())
|
||||
{
|
||||
Compiler::Locals locals;
|
||||
|
||||
Compiler::NullErrorHandler errorHandler;
|
||||
std::istringstream stream (mData.getScripts().getRecord (index).get().mScriptText);
|
||||
Compiler::QuickFileParser parser (errorHandler, *this, locals);
|
||||
Compiler::Scanner scanner (errorHandler, stream, getExtensions());
|
||||
scanner.scan (parser);
|
||||
|
||||
iter = mLocals.insert (std::make_pair (id2, locals)).first;
|
||||
}
|
||||
|
||||
return std::make_pair (iter->second.getType (Misc::StringUtils::lowerCase (name)), reference);
|
||||
}
|
||||
|
||||
bool CSMWorld::ScriptContext::isId (const std::string& name) const
|
||||
|
@ -31,6 +100,7 @@ bool CSMWorld::ScriptContext::isId (const std::string& name) const
|
|||
mIds = mData.getIds();
|
||||
|
||||
std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCase);
|
||||
std::sort (mIds.begin(), mIds.end());
|
||||
|
||||
mIdsUpdated = true;
|
||||
}
|
||||
|
@ -38,7 +108,19 @@ bool CSMWorld::ScriptContext::isId (const std::string& name) const
|
|||
return std::binary_search (mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase (name));
|
||||
}
|
||||
|
||||
bool CSMWorld::ScriptContext::isJournalId (const std::string& name) const
|
||||
{
|
||||
return mData.getJournals().searchId (name)!=-1;
|
||||
}
|
||||
|
||||
void CSMWorld::ScriptContext::invalidateIds()
|
||||
{
|
||||
mIdsUpdated = false;
|
||||
}
|
||||
|
||||
void CSMWorld::ScriptContext::clear()
|
||||
{
|
||||
mIds.clear();
|
||||
mIdsUpdated = false;
|
||||
mLocals.clear();
|
||||
}
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <components/compiler/context.hpp>
|
||||
#include <components/compiler/locals.hpp>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
@ -15,6 +17,7 @@ namespace CSMWorld
|
|||
const Data& mData;
|
||||
mutable std::vector<std::string> mIds;
|
||||
mutable bool mIdsUpdated;
|
||||
mutable std::map<std::string, Compiler::Locals> mLocals;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -26,13 +29,23 @@ namespace CSMWorld
|
|||
virtual char getGlobalType (const std::string& name) const;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
|
||||
virtual char getMemberType (const std::string& name, const std::string& id) const;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
virtual std::pair<char, bool> getMemberType (const std::string& name,
|
||||
const std::string& id) const;
|
||||
///< Return type of member variable \a name in script \a id or in script of reference of
|
||||
/// \a id
|
||||
/// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
/// second: true: script of reference
|
||||
|
||||
virtual bool isId (const std::string& name) const;
|
||||
///< Does \a name match an ID, that can be referenced?
|
||||
|
||||
virtual bool isJournalId (const std::string& name) const;
|
||||
///< Does \a name match a journal ID?
|
||||
|
||||
void invalidateIds();
|
||||
|
||||
void clear();
|
||||
///< Remove all cached data.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
446
apps/opencs/model/world/tablemimedata.cpp
Normal file
446
apps/opencs/model/world/tablemimedata.cpp
Normal file
|
@ -0,0 +1,446 @@
|
|||
#include "tablemimedata.hpp"
|
||||
#include <string>
|
||||
|
||||
#include "universalid.hpp"
|
||||
#include "columnbase.hpp"
|
||||
|
||||
CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document& document) :
|
||||
mDocument(document)
|
||||
{
|
||||
mUniversalId.push_back (id);
|
||||
mObjectsFormats << QString::fromStdString ("tabledata/" + id.getTypeName());
|
||||
}
|
||||
|
||||
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
|
||||
mUniversalId (id), mDocument(document)
|
||||
{
|
||||
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
|
||||
{
|
||||
mObjectsFormats << QString::fromStdString ("tabledata/" + it->getTypeName());
|
||||
}
|
||||
}
|
||||
|
||||
QStringList CSMWorld::TableMimeData::formats() const
|
||||
{
|
||||
return mObjectsFormats;
|
||||
}
|
||||
|
||||
CSMWorld::TableMimeData::~TableMimeData()
|
||||
{
|
||||
}
|
||||
|
||||
std::string CSMWorld::TableMimeData::getIcon() const
|
||||
{
|
||||
if (mUniversalId.empty())
|
||||
{
|
||||
throw ("TableMimeData holds no UniversalId");
|
||||
}
|
||||
|
||||
std::string tmpIcon;
|
||||
bool firstIteration = true;
|
||||
|
||||
for (unsigned i = 0; i < mUniversalId.size(); ++i)
|
||||
{
|
||||
if (firstIteration)
|
||||
{
|
||||
firstIteration = false;
|
||||
tmpIcon = mUniversalId[i].getIcon();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmpIcon != mUniversalId[i].getIcon())
|
||||
{
|
||||
return ":/multitype.png"; //icon stolen from gnome
|
||||
}
|
||||
|
||||
tmpIcon = mUniversalId[i].getIcon();
|
||||
}
|
||||
|
||||
return mUniversalId.begin()->getIcon(); //All objects are of the same type;
|
||||
}
|
||||
|
||||
std::vector< CSMWorld::UniversalId > CSMWorld::TableMimeData::getData() const
|
||||
{
|
||||
return mUniversalId;
|
||||
}
|
||||
|
||||
|
||||
bool CSMWorld::TableMimeData::holdsType (CSMWorld::UniversalId::Type type) const
|
||||
{
|
||||
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
|
||||
{
|
||||
if (it->getType() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSMWorld::TableMimeData::holdsType (CSMWorld::ColumnBase::Display type) const
|
||||
{
|
||||
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
|
||||
{
|
||||
if (it->getType() == convertEnums (type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::UniversalId::Type type) const
|
||||
{
|
||||
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
|
||||
{
|
||||
if (it->getType() == type)
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
throw ("TableMimeData object does not hold object of the seeked type");
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
|
||||
{
|
||||
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
|
||||
{
|
||||
if (it->getType() == convertEnums (type))
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
throw ("TableMimeData object does not hold object of the seeked type");
|
||||
}
|
||||
|
||||
bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const
|
||||
{
|
||||
return &document == &mDocument;
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::ColumnBase::Display type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CSMWorld::ColumnBase::Display_Race:
|
||||
return CSMWorld::UniversalId::Type_Race;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Skill:
|
||||
return CSMWorld::UniversalId::Type_Skill;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Class:
|
||||
return CSMWorld::UniversalId::Type_Class;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Faction:
|
||||
return CSMWorld::UniversalId::Type_Faction;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Sound:
|
||||
return CSMWorld::UniversalId::Type_Sound;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Region:
|
||||
return CSMWorld::UniversalId::Type_Region;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Birthsign:
|
||||
return CSMWorld::UniversalId::Type_Birthsign;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Spell:
|
||||
return CSMWorld::UniversalId::Type_Spell;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Cell:
|
||||
return CSMWorld::UniversalId::Type_Cell;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Referenceable:
|
||||
return CSMWorld::UniversalId::Type_Referenceable;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Activator:
|
||||
return CSMWorld::UniversalId::Type_Activator;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Potion:
|
||||
return CSMWorld::UniversalId::Type_Potion;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Apparatus:
|
||||
return CSMWorld::UniversalId::Type_Apparatus;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Armor:
|
||||
return CSMWorld::UniversalId::Type_Armor;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Book:
|
||||
return CSMWorld::UniversalId::Type_Book;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Clothing:
|
||||
return CSMWorld::UniversalId::Type_Clothing;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Container:
|
||||
return CSMWorld::UniversalId::Type_Container;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Creature:
|
||||
return CSMWorld::UniversalId::Type_Creature;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Door:
|
||||
return CSMWorld::UniversalId::Type_Door;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Ingredient:
|
||||
return CSMWorld::UniversalId::Type_Ingredient;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_CreatureLevelledList:
|
||||
return CSMWorld::UniversalId::Type_CreatureLevelledList;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_ItemLevelledList:
|
||||
return CSMWorld::UniversalId::Type_ItemLevelledList;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Light:
|
||||
return CSMWorld::UniversalId::Type_Light;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Lockpick:
|
||||
return CSMWorld::UniversalId::Type_Lockpick;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Miscellaneous:
|
||||
return CSMWorld::UniversalId::Type_Miscellaneous;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Npc:
|
||||
return CSMWorld::UniversalId::Type_Npc;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Probe:
|
||||
return CSMWorld::UniversalId::Type_Probe;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Repair:
|
||||
return CSMWorld::UniversalId::Type_Repair;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Static:
|
||||
return CSMWorld::UniversalId::Type_Static;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Weapon:
|
||||
return CSMWorld::UniversalId::Type_Weapon;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Reference:
|
||||
return CSMWorld::UniversalId::Type_Reference;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Filter:
|
||||
return CSMWorld::UniversalId::Type_Filter;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Topic:
|
||||
return CSMWorld::UniversalId::Type_Topic;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Journal:
|
||||
return CSMWorld::UniversalId::Type_Journal;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_TopicInfo:
|
||||
return CSMWorld::UniversalId::Type_TopicInfo;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_JournalInfo:
|
||||
return CSMWorld::UniversalId::Type_JournalInfo;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Scene:
|
||||
return CSMWorld::UniversalId::Type_Scene;
|
||||
|
||||
|
||||
case CSMWorld::ColumnBase::Display_Script:
|
||||
return CSMWorld::UniversalId::Type_Script;
|
||||
|
||||
|
||||
default:
|
||||
return CSMWorld::UniversalId::Type_None;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::UniversalId::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CSMWorld::UniversalId::Type_Race:
|
||||
return CSMWorld::ColumnBase::Display_Race;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Skill:
|
||||
return CSMWorld::ColumnBase::Display_Skill;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Class:
|
||||
return CSMWorld::ColumnBase::Display_Class;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Faction:
|
||||
return CSMWorld::ColumnBase::Display_Faction;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Sound:
|
||||
return CSMWorld::ColumnBase::Display_Sound;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Region:
|
||||
return CSMWorld::ColumnBase::Display_Region;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Birthsign:
|
||||
return CSMWorld::ColumnBase::Display_Birthsign;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Spell:
|
||||
return CSMWorld::ColumnBase::Display_Spell;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Cell:
|
||||
return CSMWorld::ColumnBase::Display_Cell;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Referenceable:
|
||||
return CSMWorld::ColumnBase::Display_Referenceable;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Activator:
|
||||
return CSMWorld::ColumnBase::Display_Activator;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Potion:
|
||||
return CSMWorld::ColumnBase::Display_Potion;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Apparatus:
|
||||
return CSMWorld::ColumnBase::Display_Apparatus;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Armor:
|
||||
return CSMWorld::ColumnBase::Display_Armor;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Book:
|
||||
return CSMWorld::ColumnBase::Display_Book;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Clothing:
|
||||
return CSMWorld::ColumnBase::Display_Clothing;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Container:
|
||||
return CSMWorld::ColumnBase::Display_Container;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Creature:
|
||||
return CSMWorld::ColumnBase::Display_Creature;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Door:
|
||||
return CSMWorld::ColumnBase::Display_Door;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Ingredient:
|
||||
return CSMWorld::ColumnBase::Display_Ingredient;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_CreatureLevelledList:
|
||||
return CSMWorld::ColumnBase::Display_CreatureLevelledList;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_ItemLevelledList:
|
||||
return CSMWorld::ColumnBase::Display_ItemLevelledList;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Light:
|
||||
return CSMWorld::ColumnBase::Display_Light;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Lockpick:
|
||||
return CSMWorld::ColumnBase::Display_Lockpick;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Miscellaneous:
|
||||
return CSMWorld::ColumnBase::Display_Miscellaneous;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Npc:
|
||||
return CSMWorld::ColumnBase::Display_Npc;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Probe:
|
||||
return CSMWorld::ColumnBase::Display_Probe;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Repair:
|
||||
return CSMWorld::ColumnBase::Display_Repair;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Static:
|
||||
return CSMWorld::ColumnBase::Display_Static;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Weapon:
|
||||
return CSMWorld::ColumnBase::Display_Weapon;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Reference:
|
||||
return CSMWorld::ColumnBase::Display_Reference;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Filter:
|
||||
return CSMWorld::ColumnBase::Display_Filter;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Topic:
|
||||
return CSMWorld::ColumnBase::Display_Topic;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Journal:
|
||||
return CSMWorld::ColumnBase::Display_Journal;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_TopicInfo:
|
||||
return CSMWorld::ColumnBase::Display_TopicInfo;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_JournalInfo:
|
||||
return CSMWorld::ColumnBase::Display_JournalInfo;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Scene:
|
||||
return CSMWorld::ColumnBase::Display_Scene;
|
||||
|
||||
|
||||
case CSMWorld::UniversalId::Type_Script:
|
||||
return CSMWorld::ColumnBase::Display_Script;
|
||||
|
||||
|
||||
default:
|
||||
return CSMWorld::ColumnBase::Display_None;
|
||||
}
|
||||
}
|
63
apps/opencs/model/world/tablemimedata.hpp
Normal file
63
apps/opencs/model/world/tablemimedata.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
#ifndef TABLEMIMEDATA_H
|
||||
#define TABLEMIMEDATA_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QStringList>
|
||||
|
||||
#include "universalid.hpp"
|
||||
#include "columnbase.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
||||
/// \brief Subclass of QmimeData, augmented to contain and transport UniversalIds.
|
||||
///
|
||||
/// This class provides way to construct mimedata object holding the universalid copy
|
||||
/// Universalid is used in the majority of the tables to store type, id, argument types.
|
||||
/// This way universalid grants a way to retrive record from the concrete table.
|
||||
/// Please note, that tablemimedata object can hold multiple universalIds in the vector.
|
||||
|
||||
class TableMimeData : public QMimeData
|
||||
{
|
||||
public:
|
||||
TableMimeData(UniversalId id, const CSMDoc::Document& document);
|
||||
|
||||
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document);
|
||||
|
||||
~TableMimeData();
|
||||
|
||||
virtual QStringList formats() const;
|
||||
|
||||
std::string getIcon() const;
|
||||
|
||||
std::vector<UniversalId> getData() const;
|
||||
|
||||
bool holdsType(UniversalId::Type type) const;
|
||||
|
||||
bool holdsType(CSMWorld::ColumnBase::Display type) const;
|
||||
|
||||
bool fromDocument(const CSMDoc::Document& document) const;
|
||||
|
||||
UniversalId returnMatching(UniversalId::Type type) const;
|
||||
|
||||
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
||||
|
||||
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
||||
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
||||
|
||||
private:
|
||||
std::vector<UniversalId> mUniversalId;
|
||||
QStringList mObjectsFormats;
|
||||
const CSMDoc::Document& mDocument;
|
||||
|
||||
};
|
||||
}
|
||||
#endif // TABLEMIMEDATA_H
|
|
@ -4,6 +4,7 @@
|
|||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -186,7 +187,6 @@ CSMWorld::UniversalId::UniversalId (Type type, const std::string& id)
|
|||
mClass = sIdArg[i].mClass;
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::logic_error ("invalid ID argument UniversalId type");
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "editwidget.hpp"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QString>
|
||||
#include <QApplication>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
|
||||
|
@ -56,3 +58,146 @@ void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int s
|
|||
{
|
||||
textChanged (text());
|
||||
}
|
||||
|
||||
void CSVFilter::EditWidget::createFilterRequest (std::vector< std::pair< std::string, std::vector< std::string > > >& filterSource,
|
||||
Qt::DropAction action)
|
||||
{
|
||||
const unsigned count = filterSource.size();
|
||||
bool multipleElements = false;
|
||||
|
||||
switch (count) //setting multipleElements;
|
||||
{
|
||||
case 0: //empty
|
||||
return; //nothing to do here
|
||||
|
||||
case 1: //only single
|
||||
multipleElements = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
multipleElements = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers key = QApplication::keyboardModifiers();
|
||||
QString oldContent (text());
|
||||
|
||||
bool replaceMode = false;
|
||||
std::string orAnd;
|
||||
|
||||
switch (key) //setting replaceMode and string used to glue expressions
|
||||
{
|
||||
case Qt::ShiftModifier:
|
||||
orAnd = "!or(";
|
||||
replaceMode = false;
|
||||
break;
|
||||
|
||||
case Qt::ControlModifier:
|
||||
orAnd = "!and(";
|
||||
replaceMode = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
replaceMode = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldContent.isEmpty() || !oldContent.contains (QRegExp ("^!.*$", Qt::CaseInsensitive))) //if line edit is empty or it does not contain one shot filter go into replace mode
|
||||
{
|
||||
replaceMode = true;
|
||||
}
|
||||
|
||||
if (!replaceMode)
|
||||
{
|
||||
oldContent.remove ('!');
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
if (multipleElements)
|
||||
{
|
||||
if (replaceMode)
|
||||
{
|
||||
ss<<"!or(";
|
||||
} else {
|
||||
ss << orAnd << oldContent.toStdString() << ',';
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
{
|
||||
ss<<generateFilter (filterSource[i]);
|
||||
|
||||
if (i+1 != count)
|
||||
{
|
||||
ss<<", ";
|
||||
}
|
||||
}
|
||||
|
||||
ss<<')';
|
||||
} else {
|
||||
if (!replaceMode)
|
||||
{
|
||||
ss << orAnd << oldContent.toStdString() <<',';
|
||||
} else {
|
||||
ss<<'!';
|
||||
}
|
||||
|
||||
ss << generateFilter (filterSource[0]);
|
||||
|
||||
if (!replaceMode)
|
||||
{
|
||||
ss<<')';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ss.str().length() >4)
|
||||
{
|
||||
clear();
|
||||
insert (QString::fromUtf8(ss.str().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std::vector< std::string > >& seekedString) const
|
||||
{
|
||||
const unsigned columns = seekedString.second.size();
|
||||
|
||||
bool multipleColumns = false;
|
||||
switch (columns)
|
||||
{
|
||||
case 0: //empty
|
||||
return ""; //no column to filter
|
||||
|
||||
case 1: //one column to look for
|
||||
multipleColumns = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
multipleColumns = true;
|
||||
break;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
if (multipleColumns)
|
||||
{
|
||||
ss<<"or(";
|
||||
for (unsigned i = 0; i < columns; ++i)
|
||||
{
|
||||
ss<<"string("<<'"'<<seekedString.second[i]<<'"'<<','<<'"'<<seekedString.first<<'"'<<')';
|
||||
if (i+1 != columns)
|
||||
ss<<',';
|
||||
}
|
||||
ss<<')';
|
||||
} else {
|
||||
ss<<"string"<<'('<<'"'<<seekedString.second[0]<<"\","<<'"'<<seekedString.first<<"\")";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void CSVFilter::EditWidget::useFilterRequest (const std::string& idOfFilter)
|
||||
{
|
||||
clear();
|
||||
insert(QString::fromUtf8(idOfFilter.c_str()));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <QLineEdit>
|
||||
#include <QPalette>
|
||||
#include <qt4/QtCore/qnamespace.h>
|
||||
|
||||
#include "../../model/filter/parser.hpp"
|
||||
#include "../../model/filter/node.hpp"
|
||||
|
@ -33,6 +34,9 @@ namespace CSVFilter
|
|||
|
||||
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
|
||||
|
||||
private:
|
||||
std::string generateFilter(std::pair<std::string, std::vector<std::string> >& seekedString) const;
|
||||
|
||||
private slots:
|
||||
|
||||
void textChanged (const QString& text);
|
||||
|
@ -42,6 +46,11 @@ namespace CSVFilter
|
|||
void filterRowsRemoved (const QModelIndex& parent, int start, int end);
|
||||
|
||||
void filterRowsInserted (const QModelIndex& parent, int start, int end);
|
||||
|
||||
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
|
||||
Qt::DropAction action);
|
||||
|
||||
void useFilterRequest(const std::string& idOfFilter);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
#include "filterbox.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
#include "recordfilterbox.hpp"
|
||||
|
||||
#include <apps/opencs/model/world/tablemimedata.hpp>
|
||||
|
||||
CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
|
||||
: QWidget (parent)
|
||||
{
|
||||
|
@ -21,4 +24,27 @@ CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
|
|||
connect (recordFilterBox,
|
||||
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
|
||||
this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
|
||||
recordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
|
||||
|
||||
connect(this, SIGNAL(useFilterRequest(const std::string&)), recordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
|
||||
{
|
||||
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();
|
||||
|
||||
emit recordDropped(data, event->proposedAction());
|
||||
}
|
||||
|
||||
void CSVFilter::FilterBox::dragEnterEvent (QDragEnterEvent* event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void CSVFilter::FilterBox::dragMoveEvent (QDragMoveEvent* event)
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#ifndef CSV_FILTER_FILTERBOX_H
|
||||
#define CSV_FILTER_FILTERBOX_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QWidget>
|
||||
#include <qt4/QtCore/qnamespace.h>
|
||||
|
||||
#include "../../model/filter/node.hpp"
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
@ -16,6 +20,12 @@ namespace CSVFilter
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
void dragEnterEvent (QDragEnterEvent* event);
|
||||
|
||||
void dropEvent (QDropEvent* event);
|
||||
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
|
||||
public:
|
||||
|
||||
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
|
||||
|
@ -23,8 +33,13 @@ namespace CSVFilter
|
|||
signals:
|
||||
|
||||
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
|
||||
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action);
|
||||
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
|
||||
Qt::DropAction action);
|
||||
void useFilterRequest(const std::string& idOfFilter);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,4 +24,9 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare
|
|||
connect (
|
||||
editWidget, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
|
||||
this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
|
||||
|
||||
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
|
||||
editWidget, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
|
||||
|
||||
connect(this, SIGNAL(useFilterRequest(const std::string&)), editWidget, SLOT(useFilterRequest(const std::string&)));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <QWidget>
|
||||
#include <qt4/QtCore/qnamespace.h>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
|
@ -27,6 +28,9 @@ namespace CSVFilter
|
|||
signals:
|
||||
|
||||
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
|
||||
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
|
||||
Qt::DropAction action);
|
||||
void useFilterRequest(const std::string& idOfFilter);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,10 @@ namespace CSVRender
|
|||
params.insert(std::make_pair("title", windowTitle.str()));
|
||||
params.insert(std::make_pair("FSAA", "0")); // TODO setting
|
||||
params.insert(std::make_pair("vsync", "false")); // TODO setting
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
params.insert(std::make_pair("macAPI", "cocoa"));
|
||||
params.insert(std::make_pair("macAPICocoaUseNSView", "true"));
|
||||
#endif
|
||||
|
||||
mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms);
|
||||
mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1));
|
||||
|
|
|
@ -133,9 +133,9 @@ void CSVWorld::GenericCreator::create()
|
|||
std::string id = getId();
|
||||
std::auto_ptr<CSMWorld::CloneCommand> command (new CSMWorld::CloneCommand (
|
||||
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType));
|
||||
|
||||
|
||||
mUndoStack.push(command.release());
|
||||
|
||||
|
||||
emit done();
|
||||
emit requestFocus(id);
|
||||
} else {
|
||||
|
|
|
@ -43,12 +43,26 @@ toolbar->addTool (new SceneToolMode (toolbar));
|
|||
toolbar->addTool (new SceneToolMode (toolbar));
|
||||
layout2->addWidget (toolbar, 0);
|
||||
|
||||
|
||||
// temporarily disable OGRE-integration (need to fix path problem first)
|
||||
#if 0
|
||||
CSVRender::SceneWidget* sceneWidget = new CSVRender::SceneWidget(this);
|
||||
|
||||
layout2->addWidget (sceneWidget, 1);
|
||||
|
||||
layout->insertLayout (0, layout2, 1);
|
||||
#endif
|
||||
/// \todo replace with rendering widget
|
||||
QPalette palette2 (palette());
|
||||
palette2.setColor (QPalette::Background, Qt::white);
|
||||
QLabel *placeholder = new QLabel ("Here goes the 3D scene", this);
|
||||
placeholder->setAutoFillBackground (true);
|
||||
placeholder->setPalette (palette2);
|
||||
placeholder->setAlignment (Qt::AlignHCenter);
|
||||
|
||||
layout2->addWidget (placeholder, 1);
|
||||
|
||||
layout->insertLayout (0, layout2, 1);
|
||||
|
||||
|
||||
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
|
||||
|
||||
|
|
88
apps/opencs/view/world/scriptedit.cpp
Normal file
88
apps/opencs/view/world/scriptedit.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "scriptedit.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QRegExp>
|
||||
#include <QString>
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& document) :
|
||||
QTextEdit (parent),
|
||||
mDocument (document),
|
||||
mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive)
|
||||
{
|
||||
mAllowedTypes <<CSMWorld::UniversalId::Type_Journal
|
||||
<<CSMWorld::UniversalId::Type_Global
|
||||
<<CSMWorld::UniversalId::Type_Topic
|
||||
<<CSMWorld::UniversalId::Type_Sound
|
||||
<<CSMWorld::UniversalId::Type_Spell
|
||||
<<CSMWorld::UniversalId::Type_Cell
|
||||
<<CSMWorld::UniversalId::Type_Referenceable
|
||||
<<CSMWorld::UniversalId::Type_Activator
|
||||
<<CSMWorld::UniversalId::Type_Potion
|
||||
<<CSMWorld::UniversalId::Type_Apparatus
|
||||
<<CSMWorld::UniversalId::Type_Armor
|
||||
<<CSMWorld::UniversalId::Type_Book
|
||||
<<CSMWorld::UniversalId::Type_Clothing
|
||||
<<CSMWorld::UniversalId::Type_Container
|
||||
<<CSMWorld::UniversalId::Type_Creature
|
||||
<<CSMWorld::UniversalId::Type_Door
|
||||
<<CSMWorld::UniversalId::Type_Ingredient
|
||||
<<CSMWorld::UniversalId::Type_CreatureLevelledList
|
||||
<<CSMWorld::UniversalId::Type_ItemLevelledList
|
||||
<<CSMWorld::UniversalId::Type_Light
|
||||
<<CSMWorld::UniversalId::Type_Lockpick
|
||||
<<CSMWorld::UniversalId::Type_Miscellaneous
|
||||
<<CSMWorld::UniversalId::Type_Npc
|
||||
<<CSMWorld::UniversalId::Type_Probe
|
||||
<<CSMWorld::UniversalId::Type_Repair
|
||||
<<CSMWorld::UniversalId::Type_Static
|
||||
<<CSMWorld::UniversalId::Type_Weapon;
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptEdit::dragEnterEvent (QDragEnterEvent* event)
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event)
|
||||
{
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
|
||||
{
|
||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||
|
||||
setTextCursor (cursorForPosition (event->pos()));
|
||||
|
||||
if (mime->fromDocument (mDocument))
|
||||
{
|
||||
std::vector<CSMWorld::UniversalId> records (mime->getData());
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId>::iterator it = records.begin(); it != records.end(); ++it)
|
||||
{
|
||||
if (mAllowedTypes.contains (it->getType()))
|
||||
{
|
||||
if (stringNeedsQuote(it->getId()))
|
||||
{
|
||||
insertPlainText(QString::fromStdString ('"' + it->getId() + '"'));
|
||||
} else {
|
||||
insertPlainText(QString::fromStdString (it->getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CSVWorld::ScriptEdit::stringNeedsQuote (const std::string& id) const
|
||||
{
|
||||
const QString string(QString::fromStdString(id)); //<regex> is only for c++11, so let's use qregexp for now.
|
||||
//I'm not quite sure when do we need to put quotes. To be safe we will use quotes for anything other than…
|
||||
return !(string.contains(mWhiteListQoutes));
|
||||
}
|
39
apps/opencs/view/world/scriptedit.hpp
Normal file
39
apps/opencs/view/world/scriptedit.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef SCRIPTEDIT_H
|
||||
#define SCRIPTEDIT_H
|
||||
|
||||
#include <qtextedit.h>
|
||||
#include <QVector>
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
class QWidget;
|
||||
class QRegExp;
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class ScriptEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEdit (QWidget* parent, const CSMDoc::Document& document);
|
||||
|
||||
private:
|
||||
QVector<CSMWorld::UniversalId::Type> mAllowedTypes;
|
||||
const CSMDoc::Document& mDocument;
|
||||
const QRegExp mWhiteListQoutes;
|
||||
|
||||
void dragEnterEvent (QDragEnterEvent* event);
|
||||
|
||||
void dropEvent (QDropEvent* event);
|
||||
|
||||
void dragMoveEvent (QDragMoveEvent* event);
|
||||
|
||||
bool stringNeedsQuote(const std::string& id) const;
|
||||
};
|
||||
}
|
||||
#endif // SCRIPTEDIT_H
|
|
@ -13,6 +13,7 @@
|
|||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
#include "scripthighlighter.hpp"
|
||||
#include "scriptedit.hpp"
|
||||
|
||||
CSVWorld::ScriptSubView::ChangeLock::ChangeLock (ScriptSubView& view) : mView (view)
|
||||
{
|
||||
|
@ -27,7 +28,7 @@ CSVWorld::ScriptSubView::ChangeLock::~ChangeLock()
|
|||
CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||
: SubView (id), mDocument (document), mColumn (-1), mChangeLocked (0)
|
||||
{
|
||||
setWidget (mEditor = new QTextEdit (this));
|
||||
setWidget (mEditor = new ScriptEdit (this, mDocument));
|
||||
|
||||
mEditor->setAcceptRichText (false);
|
||||
mEditor->setLineWrapMode (QTextEdit::NoWrap);
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
#include <QHeaderView>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QMenu>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QString>
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
@ -13,6 +16,8 @@
|
|||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/record.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
#include "recordstatusdelegate.hpp"
|
||||
#include "util.hpp"
|
||||
|
@ -88,7 +93,7 @@ std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
|
|||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
||||
++iter)
|
||||
++iter)
|
||||
{
|
||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||
|
||||
|
@ -158,8 +163,8 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
|||
}
|
||||
|
||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
bool createAndDelete, bool sorting)
|
||||
: mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0)
|
||||
bool createAndDelete, bool sorting, const CSMDoc::Document& document)
|
||||
: mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), mDocument(document)
|
||||
{
|
||||
mModel = &dynamic_cast<CSMWorld::IdTable&> (*data.getTableModel (id));
|
||||
|
||||
|
@ -235,6 +240,8 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
|
|||
|
||||
connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT (selectionSizeUpdate ()));
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void CSVWorld::Table::setEditLock (bool locked)
|
||||
|
@ -432,3 +439,108 @@ void CSVWorld::Table::recordFilterChanged (boost::shared_ptr<CSMFilter::Node> fi
|
|||
{
|
||||
mProxyModel->setFilter (filter);
|
||||
}
|
||||
|
||||
void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
|
||||
{
|
||||
if (event->buttons() & Qt::LeftButton)
|
||||
{
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
if (selectedRows.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QDrag* drag = new QDrag (this);
|
||||
CSMWorld::TableMimeData* mime = NULL;
|
||||
|
||||
if (selectedRows.size() == 1)
|
||||
{
|
||||
mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<CSMWorld::UniversalId> idToDrag;
|
||||
|
||||
foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW.
|
||||
{
|
||||
idToDrag.push_back (getUniversalId (it.row()));
|
||||
}
|
||||
|
||||
mime = new CSMWorld::TableMimeData (idToDrag, mDocument);
|
||||
}
|
||||
|
||||
drag->setMimeData (mime);
|
||||
drag->setPixmap (QString::fromStdString (mime->getIcon()));
|
||||
|
||||
Qt::DropActions action = Qt::IgnoreAction;
|
||||
switch (QApplication::keyboardModifiers())
|
||||
{
|
||||
case Qt::ControlModifier:
|
||||
action = Qt::CopyAction;
|
||||
break;
|
||||
|
||||
case Qt::ShiftModifier:
|
||||
action = Qt::MoveAction;
|
||||
break;
|
||||
}
|
||||
|
||||
drag->exec(action);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void CSVWorld::Table::dropEvent(QDropEvent *event)
|
||||
{
|
||||
QModelIndex index = indexAt (event->pos());
|
||||
|
||||
if (!index.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||
if (mime->fromDocument (mDocument))
|
||||
{
|
||||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||
(mModel->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
|
||||
if (mime->holdsType (display))
|
||||
{
|
||||
CSMWorld::UniversalId record (mime->returnMatching (display));
|
||||
|
||||
std::auto_ptr<CSMWorld::ModifyCommand> command (new CSMWorld::ModifyCommand
|
||||
(*mProxyModel, index, QVariant (QString::fromUtf8 (record.getId().c_str()))));
|
||||
|
||||
mUndoStack.push (command.release());
|
||||
}
|
||||
} //TODO handle drops from different document
|
||||
}
|
||||
|
||||
void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
|
||||
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
|
||||
{
|
||||
const int count = mModel->columnCount();
|
||||
|
||||
std::vector<std::string> titles;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
CSMWorld::ColumnBase::Display columndisplay = static_cast<CSMWorld::ColumnBase::Display>
|
||||
(mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
|
||||
if (display == columndisplay)
|
||||
{
|
||||
titles.push_back(mModel->headerData (i, Qt::Horizontal).toString().toStdString());
|
||||
}
|
||||
}
|
||||
return titles;
|
||||
}
|
|
@ -5,8 +5,14 @@
|
|||
#include <string>
|
||||
|
||||
#include <QTableView>
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
#include "../../model/filter/node.hpp"
|
||||
#include "../../model/world/columnbase.hpp"
|
||||
|
||||
namespace CSMDoc {
|
||||
class Document;
|
||||
}
|
||||
|
||||
class QUndoStack;
|
||||
class QAction;
|
||||
|
@ -42,6 +48,10 @@ namespace CSVWorld
|
|||
bool mEditLock;
|
||||
int mRecordStatusDisplay;
|
||||
|
||||
/// \brief This variable is used exclusivly for checking if dropEvents came from the same document. Most likely you
|
||||
/// should NOT use it for anything else.
|
||||
const CSMDoc::Document& mDocument;
|
||||
|
||||
private:
|
||||
|
||||
void contextMenuEvent (QContextMenuEvent *event);
|
||||
|
@ -50,9 +60,19 @@ namespace CSVWorld
|
|||
|
||||
std::vector<std::string> listDeletableSelectedIds() const;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
public:
|
||||
|
||||
Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete, bool sorting);
|
||||
Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete,
|
||||
bool sorting, const CSMDoc::Document& document);
|
||||
|
||||
///< \param createAndDelete Allow creation and deletion of records.
|
||||
/// \param sorting Allow changing order of rows in the view via column headers.
|
||||
|
||||
|
@ -62,6 +82,8 @@ namespace CSVWorld
|
|||
|
||||
void updateEditorSetting (const QString &settingName, const QString &settingValue);
|
||||
|
||||
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
|
||||
|
||||
signals:
|
||||
|
||||
void editRequest (int row);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#include "tablesubview.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QEvent>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
#include "../filter/filterbox.hpp"
|
||||
#include "table.hpp"
|
||||
|
@ -22,7 +24,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
|
||||
|
||||
layout->insertWidget (0, mTable =
|
||||
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting), 2);
|
||||
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting, document), 2);
|
||||
|
||||
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
|
||||
|
||||
|
@ -43,6 +45,9 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
|
||||
mTable->tableSizeUpdate();
|
||||
mTable->selectionSizeUpdate();
|
||||
mTable->viewport()->installEventFilter(this);
|
||||
mBottom->installEventFilter(this);
|
||||
filterBox->installEventFilter(this);
|
||||
|
||||
if (mBottom->canCreateAndDelete())
|
||||
{
|
||||
|
@ -60,6 +65,14 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
connect (filterBox,
|
||||
SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)),
|
||||
mTable, SLOT (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
|
||||
|
||||
connect(filterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
|
||||
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
|
||||
|
||||
connect(this, SIGNAL(useFilterRequest(const std::string&)), filterBox, SIGNAL(useFilterRequest(const std::string&)));
|
||||
|
||||
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
|
||||
filterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
|
||||
}
|
||||
|
||||
void CSVWorld::TableSubView::setEditLock (bool locked)
|
||||
|
@ -87,3 +100,33 @@ void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
|
|||
{
|
||||
emit cloneRequest(toClone.getId(), toClone.getType());
|
||||
}
|
||||
|
||||
void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::UniversalId>& types, Qt::DropAction action)
|
||||
{
|
||||
std::vector<std::pair<std::string, std::vector<std::string> > > filterSource;
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId>::iterator it = types.begin(); it != types.end(); ++it)
|
||||
{
|
||||
std::pair<std::string, std::vector<std::string> > pair( //splited long line
|
||||
std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType()))));
|
||||
|
||||
filterSource.push_back(pair);
|
||||
}
|
||||
emit createFilterRequest(filterSource, action);
|
||||
}
|
||||
|
||||
bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Drop)
|
||||
{
|
||||
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
|
||||
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
|
||||
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
|
||||
if (handled)
|
||||
{
|
||||
emit useFilterRequest(data->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "../doc/subview.hpp"
|
||||
|
||||
#include <qt4/QtCore/qnamespace.h>
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
namespace CSMWorld
|
||||
|
@ -39,14 +41,22 @@ namespace CSVWorld
|
|||
|
||||
virtual void setStatusBar (bool show);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* object, QEvent *event);
|
||||
|
||||
signals:
|
||||
void cloneRequest(const std::string&,
|
||||
const CSMWorld::UniversalId::Type);
|
||||
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
|
||||
Qt::DropAction action);
|
||||
void useFilterRequest(const std::string& idOfFilter);
|
||||
|
||||
private slots:
|
||||
|
||||
void editRequest (int row);
|
||||
void cloneRequest (const CSMWorld::UniversalId& toClone);
|
||||
void createFilterRequest(std::vector< CSMWorld::UniversalId >& types,
|
||||
Qt::DropAction action);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
|||
, mSkipMenu (false)
|
||||
, mUseSound (true)
|
||||
, mCompileAll (false)
|
||||
, mWarningsMode (1)
|
||||
, mScriptContext (0)
|
||||
, mFSStrict (false)
|
||||
, mScriptConsoleMode (false)
|
||||
|
@ -424,7 +425,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
mScriptContext->setExtensions (&mExtensions);
|
||||
|
||||
mEnvironment.setScriptManager (new MWScript::ScriptManager (MWBase::Environment::get().getWorld()->getStore(),
|
||||
mVerboseScripts, *mScriptContext));
|
||||
mVerboseScripts, *mScriptContext, mWarningsMode));
|
||||
|
||||
// Create game mechanics system
|
||||
MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager;
|
||||
|
@ -612,8 +613,12 @@ void OMW::Engine::setStartupScript (const std::string& path)
|
|||
mStartupScript = path;
|
||||
}
|
||||
|
||||
|
||||
void OMW::Engine::setActivationDistanceOverride (int distance)
|
||||
{
|
||||
mActivationDistanceOverride = distance;
|
||||
}
|
||||
|
||||
void OMW::Engine::setWarningsMode (int mode)
|
||||
{
|
||||
mWarningsMode = mode;
|
||||
}
|
|
@ -74,6 +74,7 @@ namespace OMW
|
|||
bool mSkipMenu;
|
||||
bool mUseSound;
|
||||
bool mCompileAll;
|
||||
int mWarningsMode;
|
||||
std::string mFocusName;
|
||||
std::map<std::string,std::string> mFallbackMap;
|
||||
bool mScriptConsoleMode;
|
||||
|
@ -181,6 +182,8 @@ namespace OMW
|
|||
/// Override the game setting specified activation distance.
|
||||
void setActivationDistanceOverride (int distance);
|
||||
|
||||
void setWarningsMode (int mode);
|
||||
|
||||
private:
|
||||
Files::ConfigurationManager& mCfgMgr;
|
||||
};
|
||||
|
|
|
@ -136,6 +136,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
("script-run", bpo::value<std::string>()->default_value(""),
|
||||
"select a file containing a list of console commands that is executed on startup")
|
||||
|
||||
("script-warn", bpo::value<int>()->implicit_value (1)
|
||||
->default_value (1),
|
||||
"handling of warnings when compiling scripts\n"
|
||||
"\t0 - ignore warning\n"
|
||||
"\t1 - show warning but consider script as correctly compiled anyway\n"
|
||||
"\t2 - treat warnings as errors")
|
||||
|
||||
("skip-menu", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "skip main menu on game startup")
|
||||
|
||||
|
@ -241,6 +248,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
engine.setScriptConsoleMode (variables["script-console"].as<bool>());
|
||||
engine.setStartupScript (variables["script-run"].as<std::string>());
|
||||
engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
|
||||
engine.setWarningsMode (variables["script-warn"].as<int>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <libs/platform/stdint.h>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
|
@ -52,6 +60,12 @@ namespace MWBase
|
|||
virtual void persuade (int type) = 0;
|
||||
virtual int getTemporaryDispositionChange () const = 0;
|
||||
virtual void applyDispositionChange (int delta) = 0;
|
||||
|
||||
virtual int countSavedGameRecords() const = 0;
|
||||
|
||||
virtual void write (ESM::ESMWriter& writer) const = 0;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -766,8 +766,11 @@ namespace MWClass
|
|||
|
||||
ensureCustomData (ptr);
|
||||
|
||||
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore->
|
||||
readState (state2.mInventory);
|
||||
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
customData.mContainerStore->readState (state2.mInventory);
|
||||
customData.mCreatureStats.readState (state2.mCreatureStats);
|
||||
|
||||
}
|
||||
|
||||
void Creature::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||
|
@ -777,8 +780,10 @@ namespace MWClass
|
|||
|
||||
ensureCustomData (ptr);
|
||||
|
||||
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore->
|
||||
writeState (state2.mInventory);
|
||||
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
customData.mContainerStore->writeState (state2.mInventory);
|
||||
customData.mCreatureStats.writeState (state2.mCreatureStats);
|
||||
}
|
||||
|
||||
const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
|
||||
|
|
|
@ -1278,8 +1278,11 @@ namespace MWClass
|
|||
|
||||
ensureCustomData (ptr);
|
||||
|
||||
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
|
||||
readState (state2.mInventory);
|
||||
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
customData.mInventoryStore.readState (state2.mInventory);
|
||||
customData.mNpcStats.readState (state2.mNpcStats);
|
||||
static_cast<MWMechanics::CreatureStats&> (customData.mNpcStats).readState (state2.mCreatureStats);
|
||||
}
|
||||
|
||||
void Npc::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||
|
@ -1289,8 +1292,11 @@ namespace MWClass
|
|||
|
||||
ensureCustomData (ptr);
|
||||
|
||||
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
|
||||
writeState (state2.mInventory);
|
||||
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
customData.mInventoryStore.writeState (state2.mInventory);
|
||||
customData.mNpcStats.writeState (state2.mNpcStats);
|
||||
static_cast<const MWMechanics::CreatureStats&> (customData.mNpcStats).writeState (state2.mCreatureStats);
|
||||
}
|
||||
|
||||
const ESM::GameSetting *Npc::fMinWalkSpeed;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <components/esm/loaddial.hpp>
|
||||
#include <components/esm/loadinfo.hpp>
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
|
||||
#include <components/compiler/exception.hpp>
|
||||
#include <components/compiler/errorhandler.hpp>
|
||||
|
@ -591,6 +592,41 @@ namespace MWDialogue
|
|||
}
|
||||
}
|
||||
|
||||
int DialogueManager::countSavedGameRecords() const
|
||||
{
|
||||
return 1; // known topics
|
||||
}
|
||||
|
||||
void DialogueManager::write (ESM::ESMWriter& writer) const
|
||||
{
|
||||
ESM::DialogueState state;
|
||||
|
||||
for (std::map<std::string, bool>::const_iterator iter (mKnownTopics.begin());
|
||||
iter!=mKnownTopics.end(); ++iter)
|
||||
if (iter->second)
|
||||
state.mKnownTopics.push_back (iter->first);
|
||||
|
||||
writer.startRecord (ESM::REC_DIAS);
|
||||
state.save (writer);
|
||||
writer.endRecord (ESM::REC_DIAS);
|
||||
}
|
||||
|
||||
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
{
|
||||
if (type==ESM::REC_DIAS)
|
||||
{
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
ESM::DialogueState state;
|
||||
state.load (reader);
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (state.mKnownTopics.begin());
|
||||
iter!=state.mKnownTopics.end(); ++iter)
|
||||
if (store.get<ESM::Dialogue>().search (*iter))
|
||||
mKnownTopics.insert (std::make_pair (*iter, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
||||
{
|
||||
|
|
|
@ -78,6 +78,12 @@ namespace MWDialogue
|
|||
virtual void persuade (int type);
|
||||
virtual int getTemporaryDispositionChange () const;
|
||||
virtual void applyDispositionChange (int delta);
|
||||
|
||||
virtual int countSavedGameRecords() const;
|
||||
|
||||
virtual void write (ESM::ESMWriter& writer) const;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -206,9 +206,9 @@ struct JournalViewModelImpl : JournalViewModel
|
|||
|
||||
const MWDialogue::Quest& quest = i->second;
|
||||
// Unfortunately Morrowind.esm has no quest names, since the quest book was added with tribunal.
|
||||
if (quest.getName().empty())
|
||||
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (i->first));
|
||||
else
|
||||
// Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed
|
||||
// to appear in the quest book.
|
||||
if (!quest.getName().empty())
|
||||
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (quest.getName()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
@ -451,7 +452,7 @@ namespace MWInput
|
|||
mInputBinder->adjustMouseRegion(width, height);
|
||||
}
|
||||
|
||||
bool InputManager::keyPressed( const SDL_KeyboardEvent &arg )
|
||||
void InputManager::keyPressed( const SDL_KeyboardEvent &arg )
|
||||
{
|
||||
// Cut, copy & paste
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
|
@ -497,7 +498,6 @@ namespace MWInput
|
|||
|
||||
if (kc != OIS::KC_UNASSIGNED)
|
||||
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputManager::textInput(const SDL_TextInputEvent &arg)
|
||||
|
@ -508,23 +508,21 @@ namespace MWInput
|
|||
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::None, *it);
|
||||
}
|
||||
|
||||
bool InputManager::keyReleased(const SDL_KeyboardEvent &arg )
|
||||
void InputManager::keyReleased(const SDL_KeyboardEvent &arg )
|
||||
{
|
||||
mInputBinder->keyReleased (arg);
|
||||
|
||||
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
|
||||
|
||||
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
|
||||
void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
|
||||
{
|
||||
mInputBinder->mousePressed (arg, id);
|
||||
|
||||
if (id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT)
|
||||
return true; // MyGUI has no use for these events
|
||||
return; // MyGUI has no use for these events
|
||||
|
||||
MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id));
|
||||
if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0)
|
||||
|
@ -535,20 +533,16 @@ namespace MWInput
|
|||
MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
|
||||
void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
|
||||
{
|
||||
mInputBinder->mouseReleased (arg, id);
|
||||
|
||||
MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputManager::mouseMoved(const SFO::MouseMotionEvent &arg )
|
||||
void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg )
|
||||
{
|
||||
mInputBinder->mouseMoved (arg);
|
||||
|
||||
|
@ -596,8 +590,6 @@ namespace MWInput
|
|||
MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputManager::windowFocusChange(bool have_focus)
|
||||
|
@ -647,7 +639,9 @@ namespace MWInput
|
|||
return;
|
||||
|
||||
// Not allowed if no spell selected
|
||||
if (MWBase::Environment::get().getWindowManager()->getSelectedSpell().empty())
|
||||
MWWorld::InventoryStore& inventory = MWWorld::Class::get(mPlayer->getPlayer()).getInventoryStore(mPlayer->getPlayer());
|
||||
if (MWBase::Environment::get().getWindowManager()->getSelectedSpell().empty() &&
|
||||
inventory.getSelectedEnchantItem() == inventory.end())
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
|
|
|
@ -86,13 +86,13 @@ namespace MWInput
|
|||
virtual void resetToDefaultBindings();
|
||||
|
||||
public:
|
||||
virtual bool keyPressed(const SDL_KeyboardEvent &arg );
|
||||
virtual bool keyReleased( const SDL_KeyboardEvent &arg );
|
||||
virtual void keyPressed(const SDL_KeyboardEvent &arg );
|
||||
virtual void keyReleased( const SDL_KeyboardEvent &arg );
|
||||
virtual void textInput (const SDL_TextInputEvent &arg);
|
||||
|
||||
virtual bool mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id );
|
||||
virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
|
||||
virtual bool mouseMoved( const SFO::MouseMotionEvent &arg );
|
||||
virtual void mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id );
|
||||
virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
|
||||
virtual void mouseMoved( const SFO::MouseMotionEvent &arg );
|
||||
|
||||
virtual void windowVisibilityChange( bool visible );
|
||||
virtual void windowFocusChange( bool have_focus );
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
|
||||
#include "npcstats.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "steering.hpp"
|
||||
#include "movement.hpp"
|
||||
#include "character.hpp" // fixme: for getActiveWeapon
|
||||
|
@ -138,11 +138,11 @@ namespace MWMechanics
|
|||
{
|
||||
MWMechanics::DrawState_ state = actor.getClass().getCreatureStats(actor).getDrawState();
|
||||
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||
actor.getClass().getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
||||
actor.getClass().getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
||||
|
||||
//Get weapon speed and range
|
||||
MWWorld::ContainerStoreIterator weaponSlot =
|
||||
MWMechanics::getActiveWeapon(cls.getNpcStats(actor), cls.getInventoryStore(actor), &weaptype);
|
||||
MWMechanics::getActiveWeapon(cls.getCreatureStats(actor), cls.getInventoryStore(actor), &weaptype);
|
||||
if (weaptype == WeapType_HandToHand)
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
|
@ -240,16 +240,20 @@ namespace MWMechanics
|
|||
//target is at far distance: build path to target OR follow target (if previously actor had reached it once)
|
||||
mFollowTarget = false;
|
||||
|
||||
buildNewPath(actor);
|
||||
buildNewPath(actor); //not guaranteed, check before use
|
||||
|
||||
//delete visited path node
|
||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
//try shortcut
|
||||
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
|
||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
|
||||
else
|
||||
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
//if buildNewPath() failed leave mTargetAngle unchanged
|
||||
if(!mPathFinder.getPath().empty())
|
||||
{
|
||||
//try shortcut
|
||||
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
|
||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
|
||||
else
|
||||
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
}
|
||||
mRotate = true;
|
||||
|
||||
mMovement.mPosition[1] = 1;
|
||||
|
@ -300,9 +304,13 @@ namespace MWMechanics
|
|||
dest.mZ = mTarget.getRefData().getPosition().pos[2];
|
||||
Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ);
|
||||
|
||||
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
|
||||
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
|
||||
float dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
|
||||
float dist = -1; //hack to indicate first time, to construct a new path
|
||||
if(!mPathFinder.getPath().empty())
|
||||
{
|
||||
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
|
||||
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
|
||||
dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
|
||||
}
|
||||
|
||||
float targetPosThreshold;
|
||||
bool isOutside = actor.getCell()->mCell->isExterior();
|
||||
|
@ -311,7 +319,7 @@ namespace MWMechanics
|
|||
else
|
||||
targetPosThreshold = 100;
|
||||
|
||||
if(dist > targetPosThreshold)
|
||||
if((dist < 0) || (dist > targetPosThreshold))
|
||||
{
|
||||
//construct new path only if target has moved away more than on <targetPosThreshold>
|
||||
ESM::Position pos = actor.getRefData().getPosition();
|
||||
|
@ -332,8 +340,11 @@ namespace MWMechanics
|
|||
//maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path,
|
||||
//not the actual path length. Here we should know if the new path is actually more effective.
|
||||
//if(pathFinder2.getPathSize() < mPathFinder.getPathSize())
|
||||
newPathFinder.syncStart(mPathFinder.getPath());
|
||||
mPathFinder = newPathFinder;
|
||||
if(!mPathFinder.getPath().empty())
|
||||
{
|
||||
newPathFinder.syncStart(mPathFinder.getPath());
|
||||
mPathFinder = newPathFinder;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <components/esm/creaturestats.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -457,4 +459,21 @@ namespace MWMechanics
|
|||
mAttackStrength = value;
|
||||
}
|
||||
|
||||
void CreatureStats::writeState (ESM::CreatureStats& state) const
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
mAttributes[i].writeState (state.mAttributes[i]);
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
mDynamic[i].writeState (state.mDynamic[i]);
|
||||
}
|
||||
|
||||
void CreatureStats::readState (const ESM::CreatureStats& state)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
mAttributes[i].readState (state.mAttributes[i]);
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
mDynamic[i].readState (state.mDynamic[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#include "aisequence.hpp"
|
||||
#include "drawstate.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct CreatureStats;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
/// \brief Common creature stats
|
||||
|
@ -212,6 +217,10 @@ namespace MWMechanics
|
|||
std::set<int> mBoundItems;
|
||||
// Same as above
|
||||
std::map<int, std::string> mSummonedCreatures;
|
||||
|
||||
void writeState (ESM::CreatureStats& state) const;
|
||||
|
||||
void readState (const ESM::CreatureStats& state);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <components/esm/loadclas.hpp>
|
||||
#include <components/esm/loadgmst.hpp>
|
||||
#include <components/esm/loadfact.hpp>
|
||||
#include <components/esm/npcstats.hpp>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
@ -423,3 +424,89 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
|
|||
assert(time>=0 && time<=20);
|
||||
mTimeToStartDrowning=time;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
||||
{
|
||||
for (std::map<std::string, int>::const_iterator iter (mFactionRank.begin());
|
||||
iter!=mFactionRank.end(); ++iter)
|
||||
state.mFactions[iter->first].mRank = iter->second;
|
||||
|
||||
state.mDisposition = mDisposition;
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
{
|
||||
mSkill[i].writeState (state.mSkills[i].mRegular);
|
||||
mWerewolfSkill[i].writeState (state.mSkills[i].mWerewolf);
|
||||
}
|
||||
|
||||
state.mBounty = mBounty;
|
||||
|
||||
for (std::set<std::string>::const_iterator iter (mExpelled.begin());
|
||||
iter!=mExpelled.end(); ++iter)
|
||||
state.mFactions[*iter].mExpelled = true;
|
||||
|
||||
for (std::map<std::string, int>::const_iterator iter (mFactionReputation.begin());
|
||||
iter!=mFactionReputation.end(); ++iter)
|
||||
state.mFactions[iter->first].mReputation = iter->second;
|
||||
|
||||
state.mReputation = mReputation;
|
||||
state.mWerewolfKills = mWerewolfKills;
|
||||
state.mProfit = mProfit;
|
||||
state.mAttackStrength = mAttackStrength;
|
||||
state.mLevelProgress = mLevelProgress;
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
state.mSkillIncrease[i] = mSkillIncreases[i];
|
||||
|
||||
std::copy (mUsedIds.begin(), mUsedIds.end(), std::back_inserter (state.mUsedIds));
|
||||
|
||||
state.mTimeToStartDrowning = mTimeToStartDrowning;
|
||||
state.mLastDrowningHit = mLastDrowningHit;
|
||||
state.mLevelHealthBonus = mLevelHealthBonus;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
||||
{
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
for (std::map<std::string, ESM::NpcStats::Faction>::const_iterator iter (state.mFactions.begin());
|
||||
iter!=state.mFactions.end(); ++iter)
|
||||
if (store.get<ESM::Faction>().search (iter->first))
|
||||
{
|
||||
if (iter->second.mExpelled)
|
||||
mExpelled.insert (iter->first);
|
||||
|
||||
if (iter->second.mRank)
|
||||
mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank));
|
||||
|
||||
if (iter->second.mReputation)
|
||||
mFactionReputation.insert (std::make_pair (iter->first, iter->second.mReputation));
|
||||
}
|
||||
|
||||
mDisposition = state.mDisposition;
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
{
|
||||
mSkill[i].readState (state.mSkills[i].mRegular);
|
||||
mWerewolfSkill[i].readState (state.mSkills[i].mWerewolf);
|
||||
}
|
||||
|
||||
mBounty = state.mBounty;
|
||||
mReputation = state.mReputation;
|
||||
mWerewolfKills = state.mWerewolfKills;
|
||||
mProfit = state.mProfit;
|
||||
mAttackStrength = state.mAttackStrength;
|
||||
mLevelProgress = state.mLevelProgress;
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
mSkillIncreases[i] = state.mSkillIncrease[i];
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (state.mUsedIds.begin());
|
||||
iter!=state.mUsedIds.end(); ++iter)
|
||||
if (store.find (*iter))
|
||||
mUsedIds.insert (*iter);
|
||||
|
||||
mTimeToStartDrowning = state.mTimeToStartDrowning;
|
||||
mLastDrowningHit = state.mLastDrowningHit;
|
||||
mLevelHealthBonus = state.mLevelHealthBonus;
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
namespace ESM
|
||||
{
|
||||
struct Class;
|
||||
struct NpcStats;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -128,6 +129,10 @@ namespace MWMechanics
|
|||
/// Sets time left for the creature to drown if it stays underwater.
|
||||
/// @param time value from [0,20]
|
||||
void setTimeToStartDrowning(float time);
|
||||
|
||||
void writeState (ESM::NpcStats& state) const;
|
||||
|
||||
void readState (const ESM::NpcStats& state);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -391,6 +391,8 @@ namespace MWMechanics
|
|||
|
||||
void PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path)
|
||||
{
|
||||
if (path.size() < 2)
|
||||
return; //nothing to pop
|
||||
std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin();
|
||||
std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin();
|
||||
|
||||
|
|
29
apps/openmw/mwmechanics/stat.cpp
Normal file
29
apps/openmw/mwmechanics/stat.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
#include "stat.hpp"
|
||||
|
||||
void MWMechanics::AttributeValue::writeState (ESM::StatState<int>& state) const
|
||||
{
|
||||
state.mBase = mBase;
|
||||
state.mMod = mModifier;
|
||||
state.mDamage = mDamage;
|
||||
}
|
||||
|
||||
void MWMechanics::AttributeValue::readState (const ESM::StatState<int>& state)
|
||||
{
|
||||
mBase = state.mBase;
|
||||
mModifier = state.mMod;
|
||||
mDamage = state.mDamage;
|
||||
}
|
||||
|
||||
|
||||
void MWMechanics::SkillValue::writeState (ESM::StatState<int>& state) const
|
||||
{
|
||||
AttributeValue::writeState (state);
|
||||
state.mProgress = mProgress;
|
||||
}
|
||||
|
||||
void MWMechanics::SkillValue::readState (const ESM::StatState<int>& state)
|
||||
{
|
||||
AttributeValue::readState (state);
|
||||
mProgress = state.mProgress;
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <limits>
|
||||
|
||||
#include <components/esm/statstate.hpp>
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
template<typename T>
|
||||
|
@ -86,6 +88,18 @@ namespace MWMechanics
|
|||
{
|
||||
mModified = mBase + modifier;
|
||||
}
|
||||
|
||||
void writeState (ESM::StatState<T>& state) const
|
||||
{
|
||||
state.mBase = mBase;
|
||||
state.mMod = mModified;
|
||||
}
|
||||
|
||||
void readState (const ESM::StatState<T>& state)
|
||||
{
|
||||
mBase = state.mBase;
|
||||
mModified = state.mMod;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -190,6 +204,18 @@ namespace MWMechanics
|
|||
mStatic.setModifier (modifier);
|
||||
setCurrent (getCurrent()+diff);
|
||||
}
|
||||
|
||||
void writeState (ESM::StatState<T>& state) const
|
||||
{
|
||||
mStatic.writeState (state);
|
||||
state.mCurrent = mCurrent;
|
||||
}
|
||||
|
||||
void readState (const ESM::StatState<T>& state)
|
||||
{
|
||||
mStatic.readState (state);
|
||||
mCurrent = state.mCurrent;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -225,6 +251,10 @@ namespace MWMechanics
|
|||
void damage(int damage) { mDamage += damage; }
|
||||
void restore(int amount) { mDamage -= std::min(mDamage, amount); }
|
||||
int getDamage() const { return mDamage; }
|
||||
|
||||
void writeState (ESM::StatState<int>& state) const;
|
||||
|
||||
void readState (const ESM::StatState<int>& state);
|
||||
};
|
||||
|
||||
class SkillValue : public AttributeValue
|
||||
|
@ -234,6 +264,10 @@ namespace MWMechanics
|
|||
SkillValue() : mProgress(0) {}
|
||||
float getProgress() const { return mProgress; }
|
||||
void setProgress(float progress) { mProgress = progress; }
|
||||
|
||||
void writeState (ESM::StatState<int>& state) const;
|
||||
|
||||
void readState (const ESM::StatState<int>& state);
|
||||
};
|
||||
|
||||
inline bool operator== (const AttributeValue& left, const AttributeValue& right)
|
||||
|
|
|
@ -285,6 +285,17 @@ void Animation::addAnimSource(const std::string &model)
|
|||
}
|
||||
}
|
||||
|
||||
if (grp == 0 && dstval->getNode()->getName() == "Bip01")
|
||||
{
|
||||
mNonAccumRoot = dstval->getNode();
|
||||
mAccumRoot = mNonAccumRoot->getParent();
|
||||
if(!mAccumRoot)
|
||||
{
|
||||
std::cerr<< "Non-Accum root for "<<mPtr.getCellRef().mRefID<<" is skeleton root??" <<std::endl;
|
||||
mNonAccumRoot = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctrls[i].setSource(mAnimationTimePtr[grp]);
|
||||
grpctrls[grp].push_back(ctrls[i]);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
Ogre::AxisAlignedBox TerrainStorage::getBounds()
|
||||
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY)
|
||||
{
|
||||
int minX = 0, minY = 0, maxX = 0, maxY = 0;
|
||||
minX = 0, minY = 0, maxX = 0, maxY = 0;
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
@ -39,8 +39,6 @@ namespace MWRender
|
|||
// since grid coords are at cell origin, we need to add 1 cell
|
||||
maxX += 1;
|
||||
maxY += 1;
|
||||
|
||||
return Ogre::AxisAlignedBox(minX, minY, 0, maxX, maxY, 0);
|
||||
}
|
||||
|
||||
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef MWRENDER_TERRAINSTORAGE_H
|
||||
#define MWRENDER_TERRAINSTORAGE_H
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
#include <components/esm/loadltex.hpp>
|
||||
|
||||
#include <components/terrain/storage.hpp>
|
||||
|
||||
namespace MWRender
|
||||
|
@ -14,7 +17,7 @@ namespace MWRender
|
|||
public:
|
||||
|
||||
/// Get bounds of the whole terrain in cell units
|
||||
virtual Ogre::AxisAlignedBox getBounds();
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
|
||||
|
||||
/// Get the minimum and maximum heights of a terrain chunk.
|
||||
/// @note Should only be called for chunks <= 1 cell, i.e. leafs of the quad tree.
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include <components/esm/loaddial.hpp>
|
||||
|
||||
#include <components/compiler/locals.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -28,16 +30,32 @@ namespace MWScript
|
|||
return MWBase::Environment::get().getWorld()->getGlobalVariableType (name);
|
||||
}
|
||||
|
||||
char CompilerContext::getMemberType (const std::string& name, const std::string& id) const
|
||||
std::pair<char, bool> CompilerContext::getMemberType (const std::string& name,
|
||||
const std::string& id) const
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false);
|
||||
std::string script;
|
||||
bool reference = false;
|
||||
|
||||
std::string script = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
if (const ESM::Script *scriptRecord =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().search (id))
|
||||
{
|
||||
script = scriptRecord->mId;
|
||||
}
|
||||
else
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false);
|
||||
|
||||
if (script.empty())
|
||||
return ' ';
|
||||
script = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
reference = true;
|
||||
}
|
||||
|
||||
return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name);
|
||||
char type = ' ';
|
||||
|
||||
if (!script.empty())
|
||||
type = MWBase::Environment::get().getScriptManager()->getLocals (script).getType (
|
||||
Misc::StringUtils::lowerCase (name));
|
||||
|
||||
return std::make_pair (type, reference);
|
||||
}
|
||||
|
||||
bool CompilerContext::isId (const std::string& name) const
|
||||
|
@ -67,4 +85,14 @@ namespace MWScript
|
|||
store.get<ESM::Static>().search (name) ||
|
||||
store.get<ESM::Weapon>().search (name);
|
||||
}
|
||||
|
||||
bool CompilerContext::isJournalId (const std::string& name) const
|
||||
{
|
||||
const MWWorld::ESMStore &store =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const ESM::Dialogue *topic = store.get<ESM::Dialogue>().search (name);
|
||||
|
||||
return topic && topic->mType==ESM::Dialogue::Journal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,11 +30,18 @@ namespace MWScript
|
|||
/// 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
virtual char getGlobalType (const std::string& name) const;
|
||||
|
||||
virtual char getMemberType (const std::string& name, const std::string& id) const;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
virtual std::pair<char, bool> getMemberType (const std::string& name,
|
||||
const std::string& id) const;
|
||||
///< Return type of member variable \a name in script \a id or in script of reference of
|
||||
/// \a id
|
||||
/// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
/// second: true: script of reference
|
||||
|
||||
virtual bool isId (const std::string& name) const;
|
||||
///< Does \a name match an ID, that can be referenced?
|
||||
|
||||
virtual bool isJournalId (const std::string& name) const;
|
||||
///< Does \a name match a journal ID?
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@ op 0x20023: AiFollow, explicit reference
|
|||
op 0x20024: AiFollowCell
|
||||
op 0x20025: AiFollowCell, explicit reference
|
||||
op 0x20026: ModRegion
|
||||
opcodes 0x20027-0x3ffff unused
|
||||
op 0x20027: RemoveSoulGem
|
||||
op 0x20028: RemoveSoulGem, explicit reference
|
||||
opcodes 0x20029-0x3ffff unused
|
||||
|
||||
Segment 4:
|
||||
(not implemented yet)
|
||||
|
@ -308,8 +310,8 @@ op 0x20001f1: GetDetected
|
|||
op 0x20001f2: GetDetected, explicit reference
|
||||
op 0x20001f3: AddSoulGem
|
||||
op 0x20001f4: AddSoulGem, explicit reference
|
||||
op 0x20001f5: RemoveSoulGem
|
||||
op 0x20001f6: RemoveSoulGem, explicit reference
|
||||
op 0x20001f5: unused
|
||||
op 0x20001f6: unused
|
||||
op 0x20001f7: PlayBink
|
||||
op 0x20001f8: Drop
|
||||
op 0x20001f9: Drop, explicit reference
|
||||
|
@ -381,5 +383,7 @@ op 0x200023a: StartCombat
|
|||
op 0x200023b: StartCombatExplicit
|
||||
op 0x200023c: StopCombat
|
||||
op 0x200023d: StopCombatExplicit
|
||||
op 0x200023e: GetPcInJail
|
||||
op 0x200023f: GetPcTraveling
|
||||
|
||||
opcodes 0x200023e-0x3ffffff unused
|
||||
opcodes 0x2000240-0x3ffffff unused
|
||||
|
|
|
@ -148,4 +148,25 @@ namespace MWScript
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
Locals& GlobalScripts::getLocals (const std::string& name)
|
||||
{
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
std::map<std::string, std::pair<bool, Locals> >::iterator iter =
|
||||
mScripts.find (name2);
|
||||
|
||||
if (iter==mScripts.end())
|
||||
{
|
||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
|
||||
{
|
||||
Locals locals;
|
||||
|
||||
locals.configure (*script);
|
||||
|
||||
iter = mScripts.insert (std::make_pair (name, std::make_pair (false, locals))).first;
|
||||
}
|
||||
}
|
||||
|
||||
return iter->second.second;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,10 @@ namespace MWScript
|
|||
///< Records for variables that do not exist are dropped silently.
|
||||
///
|
||||
/// \return Known type?
|
||||
|
||||
Locals& getLocals (const std::string& name);
|
||||
///< If the script \a name has not been added as a global script yet, it is added
|
||||
/// automatically, but is not set to running state.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,47 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
|
||||
const Locals& InterpreterContext::getMemberLocals (std::string& id, bool global)
|
||||
const
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
return MWBase::Environment::get().getScriptManager()->getGlobalScripts().
|
||||
getLocals (id);
|
||||
}
|
||||
else
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
id = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
|
||||
|
||||
return ptr.getRefData().getLocals();
|
||||
}
|
||||
}
|
||||
|
||||
Locals& InterpreterContext::getMemberLocals (std::string& id, bool global)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
return MWBase::Environment::get().getScriptManager()->getGlobalScripts().
|
||||
getLocals (id);
|
||||
}
|
||||
else
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
id = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
|
||||
|
||||
return ptr.getRefData().getLocals();
|
||||
}
|
||||
}
|
||||
|
||||
InterpreterContext::InterpreterContext (
|
||||
MWScript::Locals *locals, MWWorld::Ptr reference)
|
||||
: mLocals (locals), mReference (reference),
|
||||
|
@ -407,82 +448,80 @@ namespace MWScript
|
|||
MWBase::Environment::get().getWorld()->disable (ref);
|
||||
}
|
||||
|
||||
int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const
|
||||
int InterpreterContext::getMemberShort (const std::string& id, const std::string& name,
|
||||
bool global) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 's');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
return ptr.getRefData().getLocals().mShorts[index];
|
||||
return locals.mShorts[index];
|
||||
}
|
||||
|
||||
int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const
|
||||
int InterpreterContext::getMemberLong (const std::string& id, const std::string& name,
|
||||
bool global) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 'l');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
return ptr.getRefData().getLocals().mLongs[index];
|
||||
return locals.mLongs[index];
|
||||
}
|
||||
|
||||
float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const
|
||||
float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name,
|
||||
bool global) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 'f');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
return ptr.getRefData().getLocals().mFloats[index];
|
||||
return locals.mFloats[index];
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value)
|
||||
void InterpreterContext::setMemberShort (const std::string& id, const std::string& name,
|
||||
int value, bool global)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
ptr.getRefData().getLocals().mShorts[index] = value;
|
||||
locals.mShorts[index] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value)
|
||||
void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value, bool global)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
ptr.getRefData().getLocals().mLongs[index] = value;
|
||||
locals.mLongs[index] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value)
|
||||
void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
std::string scriptId (id);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
|
||||
ptr.getRefData().getLocals().mFloats[index] = value;
|
||||
locals.mFloats[index] = value;
|
||||
}
|
||||
|
||||
MWWorld::Ptr InterpreterContext::getReference(bool required)
|
||||
|
|
|
@ -37,6 +37,12 @@ namespace MWScript
|
|||
|
||||
const MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true) const;
|
||||
|
||||
const Locals& getMemberLocals (std::string& id, bool global) const;
|
||||
///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
|
||||
|
||||
Locals& getMemberLocals (std::string& id, bool global);
|
||||
///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
|
||||
|
||||
public:
|
||||
|
||||
InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference);
|
||||
|
@ -75,35 +81,35 @@ namespace MWScript
|
|||
virtual void setGlobalLong (const std::string& name, int value);
|
||||
|
||||
virtual void setGlobalFloat (const std::string& name, float value);
|
||||
|
||||
|
||||
virtual std::vector<std::string> getGlobals () const;
|
||||
|
||||
virtual char getGlobalType (const std::string& name) const;
|
||||
|
||||
|
||||
virtual std::string getActionBinding(const std::string& action) const;
|
||||
|
||||
|
||||
virtual std::string getNPCName() const;
|
||||
|
||||
|
||||
virtual std::string getNPCRace() const;
|
||||
|
||||
|
||||
virtual std::string getNPCClass() const;
|
||||
|
||||
|
||||
virtual std::string getNPCFaction() const;
|
||||
|
||||
virtual std::string getNPCRank() const;
|
||||
|
||||
|
||||
virtual std::string getPCName() const;
|
||||
|
||||
|
||||
virtual std::string getPCRace() const;
|
||||
|
||||
|
||||
virtual std::string getPCClass() const;
|
||||
|
||||
|
||||
virtual std::string getPCRank() const;
|
||||
|
||||
|
||||
virtual std::string getPCNextRank() const;
|
||||
|
||||
|
||||
virtual int getPCBounty() const;
|
||||
|
||||
|
||||
virtual std::string getCurrentCellName() const;
|
||||
|
||||
virtual bool isScriptRunning (const std::string& name) const;
|
||||
|
@ -138,17 +144,17 @@ namespace MWScript
|
|||
|
||||
virtual void disable (const std::string& id = "");
|
||||
|
||||
virtual int getMemberShort (const std::string& id, const std::string& name) const;
|
||||
virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const;
|
||||
|
||||
virtual int getMemberLong (const std::string& id, const std::string& name) const;
|
||||
virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const;
|
||||
|
||||
virtual float getMemberFloat (const std::string& id, const std::string& name) const;
|
||||
virtual float getMemberFloat (const std::string& id, const std::string& name, bool global) const;
|
||||
|
||||
virtual void setMemberShort (const std::string& id, const std::string& name, int value);
|
||||
virtual void setMemberShort (const std::string& id, const std::string& name, int value, bool global);
|
||||
|
||||
virtual void setMemberLong (const std::string& id, const std::string& name, int value);
|
||||
virtual void setMemberLong (const std::string& id, const std::string& name, int value, bool global);
|
||||
|
||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value);
|
||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global);
|
||||
|
||||
MWWorld::Ptr getReference(bool required=true);
|
||||
///< Reference, that the script is running from (can be empty)
|
||||
|
|
|
@ -365,17 +365,21 @@ namespace MWScript
|
|||
};
|
||||
|
||||
template<class R>
|
||||
class OpRemoveSoulGem : public Interpreter::Opcode0
|
||||
class OpRemoveSoulGem : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
// throw away additional arguments
|
||||
for (unsigned int i=0; i<arg0; ++i)
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
|
@ -818,6 +822,28 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpGetPcInJail : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime &runtime)
|
||||
{
|
||||
/// \todo implement jail check
|
||||
runtime.push (0);
|
||||
}
|
||||
};
|
||||
|
||||
class OpGetPcTraveling : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime &runtime)
|
||||
{
|
||||
/// \todo implement traveling check
|
||||
runtime.push (0);
|
||||
}
|
||||
};
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
|
||||
|
@ -850,8 +876,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeAddSoulGem, new OpAddSoulGem<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
|
||||
interpreter.installSegment3 (Compiler::Misc::opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
|
||||
interpreter.installSegment3 (Compiler::Misc::opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDrop, new OpDrop<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDropExplicit, new OpDrop<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDropSoulGem, new OpDropSoulGem<ImplicitRef>);
|
||||
|
@ -888,6 +914,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeCastExplicit, new OpCast<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpell, new OpExplodeSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpellExplicit, new OpExplodeSpell<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetPcInJail, new OpGetPcInJail);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetPcTraveling, new OpGetPcTraveling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,22 +7,28 @@
|
|||
#include <exception>
|
||||
|
||||
#include <components/esm/loadscpt.hpp>
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/compiler/scanner.hpp>
|
||||
#include <components/compiler/context.hpp>
|
||||
#include <components/compiler/exception.hpp>
|
||||
#include <components/compiler/quickfileparser.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "extensions.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
ScriptManager::ScriptManager (const MWWorld::ESMStore& store, bool verbose,
|
||||
Compiler::Context& compilerContext)
|
||||
Compiler::Context& compilerContext, int warningsMode)
|
||||
: mErrorHandler (std::cerr), mStore (store), mVerbose (verbose),
|
||||
mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext),
|
||||
mOpcodesInstalled (false), mGlobalScripts (store)
|
||||
{}
|
||||
{
|
||||
mErrorHandler.setWarningsMode (warningsMode);
|
||||
}
|
||||
|
||||
bool ScriptManager::compile (const std::string& name)
|
||||
{
|
||||
|
@ -138,37 +144,33 @@ namespace MWScript
|
|||
|
||||
Compiler::Locals& ScriptManager::getLocals (const std::string& name)
|
||||
{
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
|
||||
{
|
||||
ScriptCollection::iterator iter = mScripts.find (name);
|
||||
ScriptCollection::iterator iter = mScripts.find (name2);
|
||||
|
||||
if (iter!=mScripts.end())
|
||||
return iter->second.second;
|
||||
}
|
||||
|
||||
{
|
||||
std::map<std::string, Compiler::Locals>::iterator iter = mOtherLocals.find (name);
|
||||
std::map<std::string, Compiler::Locals>::iterator iter = mOtherLocals.find (name2);
|
||||
|
||||
if (iter!=mOtherLocals.end())
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
Compiler::Locals locals;
|
||||
|
||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
|
||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name2))
|
||||
{
|
||||
int index = 0;
|
||||
Compiler::Locals locals;
|
||||
|
||||
for (int i=0; i<script->mData.mNumShorts; ++i)
|
||||
locals.declare ('s', script->mVarNames[index++]);
|
||||
|
||||
for (int i=0; i<script->mData.mNumLongs; ++i)
|
||||
locals.declare ('l', script->mVarNames[index++]);
|
||||
|
||||
for (int i=0; i<script->mData.mNumFloats; ++i)
|
||||
locals.declare ('f', script->mVarNames[index++]);
|
||||
std::istringstream stream (script->mScriptText);
|
||||
Compiler::QuickFileParser parser (mErrorHandler, mCompilerContext, locals);
|
||||
Compiler::Scanner scanner (mErrorHandler, stream, mCompilerContext.getExtensions());
|
||||
scanner.scan (parser);
|
||||
|
||||
std::map<std::string, Compiler::Locals>::iterator iter =
|
||||
mOtherLocals.insert (std::make_pair (name, locals)).first;
|
||||
mOtherLocals.insert (std::make_pair (name2, locals)).first;
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
@ -214,8 +216,10 @@ namespace MWScript
|
|||
throw std::runtime_error ("invalid variable type");
|
||||
}
|
||||
|
||||
std::string variable2 = Misc::StringUtils::lowerCase (variable);
|
||||
|
||||
for (int i=0; i<size; ++i)
|
||||
if (script->mVarNames.at (i+offset)==variable)
|
||||
if (Misc::StringUtils::lowerCase (script->mVarNames.at (i+offset))==variable2)
|
||||
return i;
|
||||
|
||||
throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId);
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace MWScript
|
|||
public:
|
||||
|
||||
ScriptManager (const MWWorld::ESMStore& store, bool verbose,
|
||||
Compiler::Context& compilerContext);
|
||||
Compiler::Context& compilerContext, int warningsMode);
|
||||
|
||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext);
|
||||
///< Run the script with the given name (compile first, if not compiled yet)
|
||||
|
|
|
@ -172,6 +172,7 @@ class OpenAL_SoundStream : public Sound
|
|||
DecoderPtr mDecoder;
|
||||
|
||||
volatile bool mIsFinished;
|
||||
volatile bool mIsInitialBatchEnqueued;
|
||||
|
||||
void updateAll(bool local);
|
||||
|
||||
|
@ -264,7 +265,7 @@ private:
|
|||
|
||||
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, float basevol, float pitch, int flags)
|
||||
: Sound(Ogre::Vector3(0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)
|
||||
, mOutput(output), mSource(src), mSamplesQueued(0), mDecoder(decoder), mIsFinished(true)
|
||||
, mOutput(output), mSource(src), mSamplesQueued(0), mDecoder(decoder), mIsFinished(true), mIsInitialBatchEnqueued(false)
|
||||
{
|
||||
throwALerror();
|
||||
|
||||
|
@ -315,16 +316,8 @@ void OpenAL_SoundStream::play()
|
|||
alSourcei(mSource, AL_BUFFER, 0);
|
||||
throwALerror();
|
||||
mSamplesQueued = 0;
|
||||
|
||||
for(ALuint i = 0;i < sNumBuffers;i++)
|
||||
alBufferData(mBuffers[i], mFormat, this, 0, mSampleRate);
|
||||
throwALerror();
|
||||
|
||||
alSourceQueueBuffers(mSource, sNumBuffers, mBuffers);
|
||||
alSourcePlay(mSource);
|
||||
throwALerror();
|
||||
|
||||
mIsFinished = false;
|
||||
mIsInitialBatchEnqueued = false;
|
||||
mOutput.mStreamThread->add(this);
|
||||
}
|
||||
|
||||
|
@ -332,6 +325,7 @@ void OpenAL_SoundStream::stop()
|
|||
{
|
||||
mOutput.mStreamThread->remove(this);
|
||||
mIsFinished = true;
|
||||
mIsInitialBatchEnqueued = false;
|
||||
|
||||
alSourceStop(mSource);
|
||||
alSourcei(mSource, AL_BUFFER, 0);
|
||||
|
@ -444,6 +438,24 @@ bool OpenAL_SoundStream::process()
|
|||
} while(processed > 0);
|
||||
throwALerror();
|
||||
}
|
||||
else if (!mIsInitialBatchEnqueued) { // nothing enqueued yet
|
||||
std::vector<char> data(mBufferSize);
|
||||
|
||||
for(ALuint i = 0;i < sNumBuffers && !finished;i++)
|
||||
{
|
||||
size_t got = mDecoder->read(&data[0], data.size());
|
||||
finished = (got < data.size());
|
||||
if(got > 0)
|
||||
{
|
||||
ALuint bufid = mBuffers[i];
|
||||
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
|
||||
alSourceQueueBuffers(mSource, 1, &bufid);
|
||||
throwALerror();
|
||||
mSamplesQueued += getBufferSampleCount(bufid);
|
||||
}
|
||||
}
|
||||
mIsInitialBatchEnqueued = true;
|
||||
}
|
||||
|
||||
if(state != AL_PLAYING && state != AL_PAUSED)
|
||||
{
|
||||
|
@ -461,6 +473,7 @@ bool OpenAL_SoundStream::process()
|
|||
std::cout<< "Error updating stream \""<<mDecoder->getName()<<"\"" <<std::endl;
|
||||
mSamplesQueued = 0;
|
||||
mIsFinished = true;
|
||||
mIsInitialBatchEnqueued = false;
|
||||
}
|
||||
return !mIsFinished;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
else
|
||||
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
|
||||
|
||||
std::ofstream stream (slot->mPath.string().c_str());
|
||||
std::ofstream stream (slot->mPath.string().c_str(), std::ios::binary);
|
||||
|
||||
ESM::ESMWriter writer;
|
||||
|
||||
|
@ -193,7 +193,8 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
|
||||
+ 1 // global map
|
||||
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
|
||||
+1 // global map
|
||||
);
|
||||
|
||||
writer.save (stream);
|
||||
|
@ -203,6 +204,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
writer.endRecord (ESM::REC_SAVE);
|
||||
|
||||
MWBase::Environment::get().getJournal()->write (writer);
|
||||
MWBase::Environment::get().getDialogueManager()->write (writer);
|
||||
MWBase::Environment::get().getWorld()->write (writer);
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer);
|
||||
MWBase::Environment::get().getWindowManager()->write(writer);
|
||||
|
@ -245,6 +247,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
|||
MWBase::Environment::get().getJournal()->readRecord (reader, n.val);
|
||||
break;
|
||||
|
||||
case ESM::REC_DIAS:
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->readRecord (reader, n.val);
|
||||
break;
|
||||
|
||||
case ESM::REC_ALCH:
|
||||
case ESM::REC_ARMO:
|
||||
case ESM::REC_BOOK:
|
||||
|
|
|
@ -529,12 +529,6 @@ namespace MWWorld
|
|||
return mPlayer->getPlayer();
|
||||
}
|
||||
|
||||
Ptr ptr = Class::get (mPlayer->getPlayer()).
|
||||
getContainerStore (mPlayer->getPlayer()).search (name);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
|
||||
std::string lowerCaseName = Misc::StringUtils::lowerCase(name);
|
||||
|
||||
// active cells
|
||||
|
@ -548,6 +542,12 @@ namespace MWWorld
|
|||
return ptr;
|
||||
}
|
||||
|
||||
Ptr ptr = Class::get (mPlayer->getPlayer()).
|
||||
getContainerStore (mPlayer->getPlayer()).search (lowerCaseName);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
|
||||
if (!activeOnly)
|
||||
{
|
||||
ret = mCells.getPtr (lowerCaseName);
|
||||
|
@ -610,6 +610,10 @@ namespace MWWorld
|
|||
|
||||
void World::enable (const Ptr& reference)
|
||||
{
|
||||
// enable is a no-op for items in containers
|
||||
if (!reference.isInCell())
|
||||
return;
|
||||
|
||||
if (!reference.getRefData().isEnabled())
|
||||
{
|
||||
reference.getRefData().enable();
|
||||
|
@ -640,6 +644,10 @@ namespace MWWorld
|
|||
|
||||
void World::disable (const Ptr& reference)
|
||||
{
|
||||
// disable is a no-op for items in containers
|
||||
if (!reference.isInCell())
|
||||
return;
|
||||
|
||||
if (reference.getRefData().isEnabled())
|
||||
{
|
||||
reference.getRefData().disable();
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
# Locate SDL library
|
||||
# This module defines
|
||||
# SDL_LIBRARY, the name of the library to link against
|
||||
# SDL_FOUND, if false, do not try to link to SDL
|
||||
# SDL_INCLUDE_DIR, where to find SDL.h
|
||||
#
|
||||
# This module responds to the the flag:
|
||||
# SDL_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL_main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the the proper link flags
|
||||
# as part of the returned SDL_LIBRARY variable.
|
||||
#
|
||||
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDLmain which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL_LIBRARY_TEMP in your configuration
|
||||
# and no SDL_LIBRARY, it means CMake did not find your SDL library
|
||||
# (SDL.dll, libsdl.so, SDL.framework, etc).
|
||||
# Set SDL_LIBRARY_TEMP to point to your SDL library, and configure again.
|
||||
# Similarly, if you see an empty SDLMAIN_LIBRARY, you should set this value
|
||||
# as appropriate. These values are used to generate the final SDL_LIBRARY
|
||||
# variable, but when these values are unset, SDL_LIBRARY does not get created.
|
||||
#
|
||||
#
|
||||
# $SDLDIR is an environment variable that would
|
||||
# correspond to the ./configure --prefix=$SDLDIR
|
||||
# used in building SDL.
|
||||
# l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing.
|
||||
# Added code to assist with automated building by using environmental variables
|
||||
# and providing a more controlled/consistent search behavior.
|
||||
# Added new modifications to recognize OS X frameworks and
|
||||
# additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL guidelines.
|
||||
# Added a search for SDLmain which is needed by some platforms.
|
||||
# Added a search for threads which is needed by some platforms.
|
||||
# Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of
|
||||
# SDL_LIBRARY to override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL convention
|
||||
# is #include "SDL.h", not <SDL/SDL.h>. This is done for portability
|
||||
# reasons because not all systems place things in SDL/ (see FreeBSD).
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
FIND_PATH(SDL_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDLDIR}
|
||||
PATH_SUFFIXES include/SDL include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include/SDL12
|
||||
/usr/local/include/SDL11 # FreeBSD ports
|
||||
/usr/include/SDL12
|
||||
/usr/include/SDL11
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
)
|
||||
#MESSAGE("SDL_INCLUDE_DIR is ${SDL_INCLUDE_DIR}")
|
||||
|
||||
# SDL-1.1 is the name used by FreeBSD ports...
|
||||
# don't confuse it for the version number.
|
||||
FIND_LIBRARY(SDL_LIBRARY_TEMP
|
||||
NAMES SDL SDL-1.1
|
||||
HINTS
|
||||
$ENV{SDLDIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
|
||||
#MESSAGE("SDL_LIBRARY_TEMP is ${SDL_LIBRARY_TEMP}")
|
||||
|
||||
IF(NOT SDL_BUILDING_LIBRARY)
|
||||
IF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDLmain for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
FIND_LIBRARY(SDLMAIN_LIBRARY
|
||||
NAMES SDLmain SDLmain-1.1
|
||||
HINTS
|
||||
$ENV{SDLDIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
ENDIF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
|
||||
ENDIF(NOT SDL_BUILDING_LIBRARY)
|
||||
|
||||
# SDL may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -lmwindows
|
||||
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||
IF(MINGW)
|
||||
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
ENDIF(MINGW)
|
||||
|
||||
SET(SDL_FOUND "NO")
|
||||
IF(SDL_LIBRARY_TEMP)
|
||||
# For SDLmain
|
||||
IF(NOT SDL_BUILDING_LIBRARY)
|
||||
IF(SDLMAIN_LIBRARY)
|
||||
SET(SDL_LIBRARY_TEMP ${SDLMAIN_LIBRARY} ${SDL_LIBRARY_TEMP})
|
||||
ENDIF(SDLMAIN_LIBRARY)
|
||||
ENDIF(NOT SDL_BUILDING_LIBRARY)
|
||||
|
||||
# For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
IF(APPLE)
|
||||
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} "-framework Cocoa")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# For threads, as mentioned Apple doesn't need this.
|
||||
# In fact, there seems to be a problem if I used the Threads package
|
||||
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||
IF(NOT APPLE)
|
||||
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# For MinGW library
|
||||
IF(MINGW)
|
||||
SET(SDL_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL_LIBRARY_TEMP})
|
||||
ENDIF(MINGW)
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
SET(SDL_LIBRARY ${SDL_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found")
|
||||
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||
SET(SDL_LIBRARY_TEMP "${SDL_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||
|
||||
SET(SDL_FOUND "YES")
|
||||
ENDIF(SDL_LIBRARY_TEMP)
|
||||
|
||||
#MESSAGE("SDL_LIBRARY is ${SDL_LIBRARY}")
|
||||
|
|
@ -85,10 +85,6 @@ function(get_git_head_revision _refspecvar _hashvar)
|
|||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
|
||||
#get_git_head_revision(refspec hash)
|
||||
|
||||
if(NOT GIT_FOUND)
|
||||
|
@ -133,7 +129,8 @@ endfunction()
|
|||
|
||||
function(get_git_tag_revision _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
|
|
|
@ -44,7 +44,8 @@ add_component_dir (esm
|
|||
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
|
||||
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
||||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
npcstats creaturestats
|
||||
)
|
||||
|
||||
add_component_dir (misc
|
||||
|
@ -59,7 +60,8 @@ add_component_dir (files
|
|||
add_component_dir (compiler
|
||||
context controlparser errorhandler exception exprparser extensions fileparser generator
|
||||
lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler
|
||||
stringparser tokenloc nullerrorhandler opcodes extensions0
|
||||
stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser
|
||||
quickfileparser
|
||||
)
|
||||
|
||||
add_component_dir (interpreter
|
||||
|
|
|
@ -33,11 +33,18 @@ namespace Compiler
|
|||
virtual char getGlobalType (const std::string& name) const = 0;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
|
||||
virtual char getMemberType (const std::string& name, const std::string& id) const = 0;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
virtual std::pair<char, bool> getMemberType (const std::string& name,
|
||||
const std::string& id) const = 0;
|
||||
///< Return type of member variable \a name in script \a id or in script of reference of
|
||||
/// \a id
|
||||
/// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
/// second: true: script of reference
|
||||
|
||||
virtual bool isId (const std::string& name) const = 0;
|
||||
///< Does \a name match an ID, that can be referenced?
|
||||
|
||||
virtual bool isJournalId (const std::string& name) const = 0;
|
||||
///< Does \a name match a journal ID?
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "scanner.hpp"
|
||||
#include "generator.hpp"
|
||||
#include "errorhandler.hpp"
|
||||
#include "skipparser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -70,7 +72,7 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_else)
|
||||
{
|
||||
mState = IfElseEndState;
|
||||
mState = IfElseJunkState; /// \todo should be IfElseEndState; add an option for that
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -106,7 +108,7 @@ namespace Compiler
|
|||
Codes expr;
|
||||
mExprParser.append (expr);
|
||||
|
||||
Generator::jump (loop, -static_cast<int> (mCodeBlock.size()-expr.size()));
|
||||
Generator::jump (loop, -static_cast<int> (mCodeBlock.size()+expr.size()));
|
||||
|
||||
std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
|
||||
|
||||
|
@ -120,7 +122,7 @@ namespace Compiler
|
|||
|
||||
Codes loop2;
|
||||
|
||||
Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()-expr.size()-skip.size()));
|
||||
Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()+expr.size()+skip.size()));
|
||||
|
||||
if (loop.size()!=loop2.size())
|
||||
throw std::logic_error (
|
||||
|
@ -153,7 +155,7 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
|
||||
ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
ControlParser::ControlParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals)
|
||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||
mLineParser (errorHandler, context, locals, literals, mCodeBlock),
|
||||
|
@ -186,8 +188,11 @@ namespace Compiler
|
|||
{
|
||||
if (mState==StartState)
|
||||
{
|
||||
if (keyword==Scanner::K_if)
|
||||
if (keyword==Scanner::K_if || keyword==Scanner::K_elseif)
|
||||
{
|
||||
if (keyword==Scanner::K_elseif)
|
||||
getErrorHandler().warning ("elseif without matching if", loc);
|
||||
|
||||
mExprParser.reset();
|
||||
scanner.scan (mExprParser);
|
||||
|
||||
|
@ -203,7 +208,8 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState)
|
||||
else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState ||
|
||||
mState==IfElseJunkState)
|
||||
{
|
||||
if (parseIfBody (keyword, loc, scanner))
|
||||
return true;
|
||||
|
@ -226,6 +232,7 @@ namespace Compiler
|
|||
case IfEndState: mState = IfBodyState; return true;
|
||||
case IfElseifEndState: mState = IfElseifBodyState; return true;
|
||||
case IfElseEndState: mState = IfElseBodyState; return true;
|
||||
case IfElseJunkState: mState = IfElseBodyState; return true;
|
||||
|
||||
case WhileEndState: mState = WhileBodyState; return true;
|
||||
|
||||
|
@ -243,7 +250,13 @@ namespace Compiler
|
|||
|
||||
default: ;
|
||||
}
|
||||
|
||||
}
|
||||
else if (code==Scanner::S_open && mState==IfElseJunkState)
|
||||
{
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
mState = IfElseBodyState;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseSpecial (code, loc, scanner);
|
||||
|
|
|
@ -26,7 +26,8 @@ namespace Compiler
|
|||
IfElseEndState, IfElseBodyState,
|
||||
IfEndifState,
|
||||
WhileEndState, WhileBodyState,
|
||||
WhileEndwhileState
|
||||
WhileEndwhileState,
|
||||
IfElseJunkState
|
||||
};
|
||||
|
||||
typedef std::vector<Interpreter::Type_Code> Codes;
|
||||
|
@ -47,7 +48,7 @@ namespace Compiler
|
|||
|
||||
public:
|
||||
|
||||
ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
ControlParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals);
|
||||
|
||||
void appendCode (std::vector<Interpreter::Type_Code>& code) const;
|
||||
|
|
83
components/compiler/declarationparser.cpp
Normal file
83
components/compiler/declarationparser.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
#include "declarationparser.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "scanner.hpp"
|
||||
#include "errorhandler.hpp"
|
||||
#include "skipparser.hpp"
|
||||
#include "locals.hpp"
|
||||
|
||||
Compiler::DeclarationParser::DeclarationParser (ErrorHandler& errorHandler, const Context& context,
|
||||
Locals& locals)
|
||||
: Parser (errorHandler, context), mLocals (locals), mState (State_Begin), mType (0)
|
||||
{}
|
||||
|
||||
bool Compiler::DeclarationParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner)
|
||||
{
|
||||
if (mState==State_Name)
|
||||
{
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
|
||||
char type = mLocals.getType (name2);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
/// \todo add option to make re-declared local variables an error
|
||||
getErrorHandler().warning ("can't re-declare local variable (ignoring declaration)",
|
||||
loc);
|
||||
|
||||
mState = State_End;
|
||||
return true;
|
||||
}
|
||||
|
||||
mLocals.declare (mType, name2);
|
||||
|
||||
mState = State_End;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
bool Compiler::DeclarationParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==State_Begin)
|
||||
{
|
||||
switch (keyword)
|
||||
{
|
||||
case Scanner::K_short: mType = 's'; break;
|
||||
case Scanner::K_long: mType = 'l'; break;
|
||||
case Scanner::K_float: mType = 'f'; break;
|
||||
default: mType = 0;
|
||||
}
|
||||
|
||||
if (mType)
|
||||
{
|
||||
mState = State_Name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (mState==State_Name)
|
||||
{
|
||||
// allow keywords to be used as local variable names. MW script compiler, you suck!
|
||||
/// \todo option to disable this atrocity.
|
||||
return parseName (loc.mLiteral, loc, scanner);
|
||||
}
|
||||
|
||||
return Parser::parseKeyword (keyword, loc, scanner);
|
||||
}
|
||||
|
||||
bool Compiler::DeclarationParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (code==Scanner::S_newline && mState==State_End)
|
||||
return false;
|
||||
|
||||
return Parser::parseSpecial (code, loc, scanner);
|
||||
}
|
||||
|
||||
void Compiler::DeclarationParser::reset()
|
||||
{
|
||||
mState = State_Begin;
|
||||
}
|
43
components/compiler/declarationparser.hpp
Normal file
43
components/compiler/declarationparser.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef COMPILER_DECLARATIONPARSER_H_INCLUDED
|
||||
#define COMPILER_DECLARATIONPARSER_H_INCLUDED
|
||||
|
||||
#include "parser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Locals;
|
||||
|
||||
class DeclarationParser : public Parser
|
||||
{
|
||||
enum State
|
||||
{
|
||||
State_Begin, State_Name, State_End
|
||||
};
|
||||
|
||||
Locals& mLocals;
|
||||
State mState;
|
||||
char mType;
|
||||
|
||||
public:
|
||||
|
||||
DeclarationParser (ErrorHandler& errorHandler, const Context& context, Locals& locals);
|
||||
|
||||
virtual bool parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner);
|
||||
///< Handle a name token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a keyword token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a special character token.
|
||||
/// \return fetch another token?
|
||||
|
||||
void reset();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@ namespace Compiler
|
|||
{
|
||||
// constructor
|
||||
|
||||
ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0) {}
|
||||
ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0), mWarningsMode (1) {}
|
||||
|
||||
// destructor
|
||||
|
||||
|
@ -36,8 +36,13 @@ namespace Compiler
|
|||
|
||||
void ErrorHandler::warning (const std::string& message, const TokenLoc& loc)
|
||||
{
|
||||
++mWarnings;
|
||||
report (message, loc, WarningMessage);
|
||||
if (mWarningsMode==1)
|
||||
{
|
||||
++mWarnings;
|
||||
report (message, loc, WarningMessage);
|
||||
}
|
||||
else if (mWarningsMode==2)
|
||||
error (message, loc);
|
||||
}
|
||||
|
||||
// Generate an error message.
|
||||
|
@ -62,4 +67,9 @@ namespace Compiler
|
|||
{
|
||||
mErrors = mWarnings = 0;
|
||||
}
|
||||
|
||||
void ErrorHandler::setWarningsMode (int mode)
|
||||
{
|
||||
mWarningsMode = mode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Compiler
|
|||
{
|
||||
int mWarnings;
|
||||
int mErrors;
|
||||
int mWarningsMode;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -60,8 +61,11 @@ namespace Compiler
|
|||
void endOfFile();
|
||||
///< Generate an error message for an unexpected EOF.
|
||||
|
||||
virtual void reset();
|
||||
virtual void reset();
|
||||
///< Remove all previous error/warning events
|
||||
|
||||
void setWarningsMode (int mode);
|
||||
///< // 0 ignore, 1 rate as warning, 2 rate as error
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <stack>
|
||||
#include <iterator>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "generator.hpp"
|
||||
#include "scanner.hpp"
|
||||
#include "errorhandler.hpp"
|
||||
|
@ -14,7 +16,6 @@
|
|||
#include "stringparser.hpp"
|
||||
#include "extensions.hpp"
|
||||
#include "context.hpp"
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -203,21 +204,22 @@ namespace Compiler
|
|||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
std::string id = Misc::StringUtils::lowerCase (mExplicit);
|
||||
|
||||
char type = getContext().getMemberType (name2, id);
|
||||
std::pair<char, bool> type = getContext().getMemberType (name2, id);
|
||||
|
||||
if (type!=' ')
|
||||
if (type.first!=' ')
|
||||
{
|
||||
Generator::fetchMember (mCode, mLiterals, type, name2, id);
|
||||
Generator::fetchMember (mCode, mLiterals, type.first, name2, id, !type.second);
|
||||
|
||||
mNextOperand = false;
|
||||
mExplicit.clear();
|
||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||
mOperands.push_back (type.first=='f' ? 'f' : 'l');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
ExprParser::ExprParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals, bool argument)
|
||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||
mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false)
|
||||
|
@ -308,6 +310,22 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
// die in a fire, Morrowind script compiler!
|
||||
if (const Extensions *extensions = getContext().getExtensions())
|
||||
{
|
||||
if (getContext().isJournalId (name2))
|
||||
{
|
||||
// JournalID used as an argument. Use the index of that JournalID
|
||||
Generator::pushString (mCode, mLiterals, name2);
|
||||
int keyword = extensions->searchKeyword ("getjournalindex");
|
||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit, 0);
|
||||
mNextOperand = false;
|
||||
mOperands.push_back ('l');
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (mExplicit.empty() && getContext().isId (name2))
|
||||
{
|
||||
mExplicit = name2;
|
||||
|
@ -326,6 +344,31 @@ namespace Compiler
|
|||
|
||||
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (const Extensions *extensions = getContext().getExtensions())
|
||||
{
|
||||
std::string argumentType; // ignored
|
||||
bool hasExplicit = false; // ignored
|
||||
if (extensions->isInstruction (keyword, argumentType, hasExplicit))
|
||||
{
|
||||
// pretend this is not a keyword
|
||||
return parseName (loc.mLiteral, loc, scanner);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyword==Scanner::K_end || keyword==Scanner::K_begin ||
|
||||
keyword==Scanner::K_short || keyword==Scanner::K_long ||
|
||||
keyword==Scanner::K_float || keyword==Scanner::K_if ||
|
||||
keyword==Scanner::K_endif || keyword==Scanner::K_else ||
|
||||
keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
|
||||
keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
|
||||
keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
|
||||
keyword==Scanner::K_to || keyword==Scanner::K_startscript ||
|
||||
keyword==Scanner::K_stopscript || keyword==Scanner::K_enable ||
|
||||
keyword==Scanner::K_disable)
|
||||
{
|
||||
return parseName (loc.mLiteral, loc, scanner);
|
||||
}
|
||||
|
||||
mFirst = false;
|
||||
|
||||
if (!mExplicit.empty())
|
||||
|
@ -368,8 +411,15 @@ namespace Compiler
|
|||
char returnType;
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
||||
bool hasExplicit = true;
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
|
||||
{
|
||||
if (!hasExplicit)
|
||||
{
|
||||
getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
|
||||
mExplicit.clear();
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
|
@ -490,7 +540,9 @@ namespace Compiler
|
|||
char returnType;
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, false))
|
||||
bool hasExplicit = false;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
|
||||
{
|
||||
mTokenLoc = loc;
|
||||
int optionals = parseArguments (argumentType, scanner);
|
||||
|
@ -518,6 +570,14 @@ namespace Compiler
|
|||
{
|
||||
if (!mExplicit.empty())
|
||||
{
|
||||
if (mRefOp && code==Scanner::S_open)
|
||||
{
|
||||
/// \todo add option to disable this workaround
|
||||
mOperators.push_back ('(');
|
||||
mTokenLoc = loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mRefOp && code==Scanner::S_ref)
|
||||
{
|
||||
mRefOp = true;
|
||||
|
@ -687,11 +747,11 @@ namespace Compiler
|
|||
{
|
||||
optional = true;
|
||||
}
|
||||
else if (*iter=='S' || *iter=='c')
|
||||
else if (*iter=='S' || *iter=='c' || *iter=='x')
|
||||
{
|
||||
stringParser.reset();
|
||||
|
||||
if (optional)
|
||||
if (optional || *iter=='x')
|
||||
stringParser.setOptional (true);
|
||||
|
||||
if (*iter=='c') stringParser.smashCase();
|
||||
|
@ -700,18 +760,21 @@ namespace Compiler
|
|||
if (optional && stringParser.isEmpty())
|
||||
break;
|
||||
|
||||
if (invert)
|
||||
if (*iter!='x')
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
stringParser.append (tmp);
|
||||
if (invert)
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
stringParser.append (tmp);
|
||||
|
||||
stack.push (tmp);
|
||||
stack.push (tmp);
|
||||
}
|
||||
else
|
||||
stringParser.append (code);
|
||||
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
else
|
||||
stringParser.append (code);
|
||||
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Compiler
|
|||
|
||||
public:
|
||||
|
||||
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
ExprParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals, bool argument = false);
|
||||
///< constructor
|
||||
/// \param argument Parser is used to parse function- or instruction-
|
||||
|
@ -101,6 +101,7 @@ namespace Compiler
|
|||
/// \param arguments Each character represents one arguments ('l': integer,
|
||||
/// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
|
||||
/// optional)
|
||||
/// 'x': optional string that will be ignored (die in a fire, MW script compiler!)
|
||||
/// \param invert Store arguments in reverted order.
|
||||
/// \return number of optional arguments
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Compiler
|
|||
}
|
||||
|
||||
bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType,
|
||||
bool explicitReference) const
|
||||
bool& explicitReference) const
|
||||
{
|
||||
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace Compiler
|
|||
return false;
|
||||
|
||||
if (explicitReference && iter->second.mCodeExplicit==-1)
|
||||
return false;
|
||||
explicitReference = false;
|
||||
|
||||
returnType = iter->second.mReturn;
|
||||
argumentType = iter->second.mArguments;
|
||||
|
@ -38,7 +38,7 @@ namespace Compiler
|
|||
}
|
||||
|
||||
bool Extensions::isInstruction (int keyword, std::string& argumentType,
|
||||
bool explicitReference) const
|
||||
bool& explicitReference) const
|
||||
{
|
||||
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace Compiler
|
|||
return false;
|
||||
|
||||
if (explicitReference && iter->second.mCodeExplicit==-1)
|
||||
return false;
|
||||
explicitReference = false;
|
||||
|
||||
argumentType = iter->second.mArguments;
|
||||
return true;
|
||||
|
|
|
@ -47,13 +47,17 @@ namespace Compiler
|
|||
/// - keyword must be all lower case.
|
||||
|
||||
bool isFunction (int keyword, char& returnType, std::string& argumentType,
|
||||
bool explicitReference) const;
|
||||
bool& explicitReference) const;
|
||||
///< Is this keyword registered with a function? If yes, return return and argument
|
||||
/// types.
|
||||
/// \param explicitReference In: has explicit reference; Out: set to false, if
|
||||
/// explicit reference is not available for this instruction.
|
||||
|
||||
bool isInstruction (int keyword, std::string& argumentType,
|
||||
bool explicitReference) const;
|
||||
bool& explicitReference) const;
|
||||
///< Is this keyword registered with a function? If yes, return argument types.
|
||||
/// \param explicitReference In: has explicit reference; Out: set to false, if
|
||||
/// explicit reference is not available for this instruction.
|
||||
|
||||
void registerFunction (const std::string& keyword, char returnType,
|
||||
const std::string& argumentType, int code, int codeExplicit = -1);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Compiler
|
|||
opcodeAiEscortCellExplicit);
|
||||
extensions.registerInstruction ("aiwander", "fff/llllllllll", opcodeAiWander,
|
||||
opcodeAiWanderExplicit);
|
||||
extensions.registerInstruction ("aifollow", "cffff/l", opcodeAiFollow,
|
||||
extensions.registerInstruction ("aifollow", "cffff/llllllll", opcodeAiFollow,
|
||||
opcodeAiFollowExplicit);
|
||||
extensions.registerInstruction ("aifollowcell", "ccffff/l", opcodeAiFollowCell,
|
||||
opcodeAiFollowCellExplicit);
|
||||
|
@ -62,7 +62,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("toggleai", "", opcodeToggleAI, opcodeToggleAI);
|
||||
extensions.registerInstruction ("tai", "", opcodeToggleAI, opcodeToggleAI);
|
||||
extensions.registerInstruction("startcombat", "c", opcodeStartCombat, opcodeStartCombatExplicit);
|
||||
extensions.registerInstruction("stopcombat", "", opcodeStopCombat, opcodeStopCombatExplicit);
|
||||
extensions.registerInstruction("stopcombat", "x", opcodeStopCombat, opcodeStopCombatExplicit);
|
||||
extensions.registerFunction ("gethello", 'l', "", opcodeGetHello, opcodeGetHelloExplicit);
|
||||
extensions.registerFunction ("getfight", 'l', "", opcodeGetFight, opcodeGetFightExplicit);
|
||||
extensions.registerFunction ("getflee", 'l', "", opcodeGetFlee, opcodeGetFleeExplicit);
|
||||
|
@ -190,7 +190,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("enableclassmenu", "", opcodeEnableClassMenu);
|
||||
extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu);
|
||||
extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu);
|
||||
extensions.registerInstruction ("enablestatreviewmenu", "",
|
||||
extensions.registerInstruction ("enablestatreviewmenu", "",
|
||||
opcodeEnableStatsReviewMenu);
|
||||
|
||||
extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu);
|
||||
|
@ -253,7 +253,7 @@ namespace Compiler
|
|||
extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
|
||||
extensions.registerFunction ("geteffect", 'l', "S", opcodeGetEffect, opcodeGetEffectExplicit);
|
||||
extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
|
||||
extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
|
||||
extensions.registerInstruction ("removesoulgem", "c/l", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
|
||||
extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit);
|
||||
extensions.registerInstruction ("dropsoulgem", "c", opcodeDropSoulGem, opcodeDropSoulGemExplicit);
|
||||
extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
|
||||
|
@ -276,6 +276,8 @@ namespace Compiler
|
|||
extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode);
|
||||
extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation);
|
||||
extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation);
|
||||
extensions.registerFunction ("getpcinjail", 'l', "", opcodeGetPcInJail);
|
||||
extensions.registerFunction ("getpctraveling", 'l', "", opcodeGetPcTraveling);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +398,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel);
|
||||
extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel);
|
||||
|
||||
extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("addspell", "cx", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||
opcodeRemoveSpellExplicit);
|
||||
extensions.registerInstruction ("removespelleffects", "c", opcodeRemoveSpellEffects,
|
||||
|
|
|
@ -260,34 +260,34 @@ namespace
|
|||
code.push_back (Compiler::Generator::segment5 (44));
|
||||
}
|
||||
|
||||
void opStoreMemberShort (Compiler::Generator::CodeContainer& code)
|
||||
void opStoreMemberShort (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (59));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 65 : 59));
|
||||
}
|
||||
|
||||
void opStoreMemberLong (Compiler::Generator::CodeContainer& code)
|
||||
void opStoreMemberLong (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (60));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 66 : 60));
|
||||
}
|
||||
|
||||
void opStoreMemberFloat (Compiler::Generator::CodeContainer& code)
|
||||
void opStoreMemberFloat (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (61));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 67 : 61));
|
||||
}
|
||||
|
||||
void opFetchMemberShort (Compiler::Generator::CodeContainer& code)
|
||||
void opFetchMemberShort (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (62));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 68 : 62));
|
||||
}
|
||||
|
||||
void opFetchMemberLong (Compiler::Generator::CodeContainer& code)
|
||||
void opFetchMemberLong (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (63));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 69 : 63));
|
||||
}
|
||||
|
||||
void opFetchMemberFloat (Compiler::Generator::CodeContainer& code)
|
||||
void opFetchMemberFloat (Compiler::Generator::CodeContainer& code, bool global)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (64));
|
||||
code.push_back (Compiler::Generator::segment5 (global ? 70 : 64));
|
||||
}
|
||||
|
||||
void opRandom (Compiler::Generator::CodeContainer& code)
|
||||
|
@ -593,7 +593,7 @@ namespace Compiler
|
|||
else if (offset<0)
|
||||
opJumpBackward (code, -offset);
|
||||
else
|
||||
throw std::logic_error ("inifite loop");
|
||||
throw std::logic_error ("infinite loop");
|
||||
}
|
||||
|
||||
void jumpOnZero (CodeContainer& code, int offset)
|
||||
|
@ -738,7 +738,8 @@ namespace Compiler
|
|||
}
|
||||
|
||||
void assignToMember (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name, const std::string& id, const CodeContainer& value, char valueType)
|
||||
const std::string& name, const std::string& id, const CodeContainer& value,
|
||||
char valueType, bool global)
|
||||
{
|
||||
int index = literals.addString (name);
|
||||
|
||||
|
@ -766,17 +767,17 @@ namespace Compiler
|
|||
{
|
||||
case 'f':
|
||||
|
||||
opStoreMemberFloat (code);
|
||||
opStoreMemberFloat (code, global);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
opStoreMemberShort (code);
|
||||
opStoreMemberShort (code, global);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
opStoreMemberLong (code);
|
||||
opStoreMemberLong (code, global);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -786,7 +787,7 @@ namespace Compiler
|
|||
}
|
||||
|
||||
void fetchMember (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name, const std::string& id)
|
||||
const std::string& name, const std::string& id, bool global)
|
||||
{
|
||||
int index = literals.addString (name);
|
||||
|
||||
|
@ -800,17 +801,17 @@ namespace Compiler
|
|||
{
|
||||
case 'f':
|
||||
|
||||
opFetchMemberFloat (code);
|
||||
opFetchMemberFloat (code, global);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
opFetchMemberShort (code);
|
||||
opFetchMemberShort (code, global);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
opFetchMemberLong (code);
|
||||
opFetchMemberLong (code, global);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -102,10 +102,12 @@ namespace Compiler
|
|||
const std::string& name);
|
||||
|
||||
void assignToMember (CodeContainer& code, Literals& literals, char memberType,
|
||||
const std::string& name, const std::string& id, const CodeContainer& value, char valueType);
|
||||
const std::string& name, const std::string& id, const CodeContainer& value, char valueType, bool global);
|
||||
///< \param global Member of a global script instead of a script of a reference.
|
||||
|
||||
void fetchMember (CodeContainer& code, Literals& literals, char memberType,
|
||||
const std::string& name, const std::string& id);
|
||||
const std::string& name, const std::string& id, bool global);
|
||||
///< \param global Member of a global script instead of a script of a reference.
|
||||
|
||||
void random (CodeContainer& code);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#include "lineparser.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "scanner.hpp"
|
||||
#include "context.hpp"
|
||||
#include "errorhandler.hpp"
|
||||
|
@ -8,7 +10,7 @@
|
|||
#include "locals.hpp"
|
||||
#include "generator.hpp"
|
||||
#include "extensions.hpp"
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include "declarationparser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -48,7 +50,7 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
|
||||
LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
LineParser::LineParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals, std::vector<Interpreter::Type_Code>& code, bool allowExpression)
|
||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code),
|
||||
mState (BeginState), mExprParser (errorHandler, context, locals, literals),
|
||||
|
@ -82,33 +84,9 @@ namespace Compiler
|
|||
bool LineParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner)
|
||||
{
|
||||
if (mState==ShortState || mState==LongState || mState==FloatState)
|
||||
if (mState==PotentialEndState)
|
||||
{
|
||||
if (!getContext().canDeclareLocals())
|
||||
{
|
||||
getErrorHandler().error ("local variables can't be declared in this context", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
|
||||
char type = mLocals.getType (name2);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
/// \todo add option to make re-declared local variables an error
|
||||
getErrorHandler().warning ("can't re-declare local variable", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
mLocals.declare (mState==ShortState ? 's' : (mState==LongState ? 'l' : 'f'),
|
||||
name2);
|
||||
|
||||
getErrorHandler().warning ("stay string argument (ignoring it)", loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
@ -142,12 +120,13 @@ namespace Compiler
|
|||
if (mState==SetMemberVarState)
|
||||
{
|
||||
mMemberName = name;
|
||||
char type = getContext().getMemberType (mMemberName, mName);
|
||||
std::pair<char, bool> type = getContext().getMemberType (mMemberName, mName);
|
||||
|
||||
if (type!=' ')
|
||||
if (type.first!=' ')
|
||||
{
|
||||
mState = SetMemberVarState2;
|
||||
mType = type;
|
||||
mType = type.first;
|
||||
mReferenceMember = type.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -240,6 +219,34 @@ namespace Compiler
|
|||
|
||||
bool LineParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==SetMemberVarState)
|
||||
{
|
||||
mMemberName = loc.mLiteral;
|
||||
std::pair<char, bool> type = getContext().getMemberType (mMemberName, mName);
|
||||
|
||||
if (type.first!=' ')
|
||||
{
|
||||
mState = SetMemberVarState2;
|
||||
mType = type.first;
|
||||
mReferenceMember = type.second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mState==SetPotentialMemberVarState && keyword==Scanner::K_to)
|
||||
{
|
||||
getErrorHandler().warning ("unknown variable (ignoring set instruction)", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mState==SetState)
|
||||
{
|
||||
// allow keywords to be used as variable names when assigning a value to a variable.
|
||||
return parseName (loc.mLiteral, loc, scanner);
|
||||
}
|
||||
|
||||
if (mState==BeginState || mState==ExplicitState)
|
||||
{
|
||||
switch (keyword)
|
||||
|
@ -247,13 +254,13 @@ namespace Compiler
|
|||
case Scanner::K_enable:
|
||||
|
||||
Generator::enable (mCode, mLiterals, mExplicit);
|
||||
mState = EndState;
|
||||
mState = PotentialEndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_disable:
|
||||
|
||||
Generator::disable (mCode, mLiterals, mExplicit);
|
||||
mState = EndState;
|
||||
mState = PotentialEndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,8 +269,15 @@ namespace Compiler
|
|||
{
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState))
|
||||
bool hasExplicit = mState==ExplicitState;
|
||||
if (extensions->isInstruction (keyword, argumentType, hasExplicit))
|
||||
{
|
||||
if (!hasExplicit && mState==ExplicitState)
|
||||
{
|
||||
getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
|
||||
mExplicit.clear();
|
||||
}
|
||||
|
||||
int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true);
|
||||
|
||||
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
|
||||
|
@ -287,9 +301,16 @@ namespace Compiler
|
|||
char returnType;
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType,
|
||||
!mExplicit.empty()))
|
||||
bool hasExplicit = !mExplicit.empty();
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
|
||||
{
|
||||
if (!hasExplicit && !mExplicit.empty())
|
||||
{
|
||||
getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
|
||||
mExplicit.clear();
|
||||
}
|
||||
|
||||
scanner.putbackKeyword (keyword, loc);
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
|
@ -299,13 +320,38 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
|
||||
if (mState==ExplicitState)
|
||||
{
|
||||
// drop stray explicit reference
|
||||
getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
|
||||
mState = BeginState;
|
||||
mExplicit.clear();
|
||||
}
|
||||
|
||||
if (mState==BeginState)
|
||||
{
|
||||
switch (keyword)
|
||||
{
|
||||
case Scanner::K_short: mState = ShortState; return true;
|
||||
case Scanner::K_long: mState = LongState; return true;
|
||||
case Scanner::K_float: mState = FloatState; return true;
|
||||
case Scanner::K_short:
|
||||
case Scanner::K_long:
|
||||
case Scanner::K_float:
|
||||
{
|
||||
if (!getContext().canDeclareLocals())
|
||||
{
|
||||
getErrorHandler().error (
|
||||
"local variables can't be declared in this context", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return true;
|
||||
}
|
||||
|
||||
DeclarationParser declaration (getErrorHandler(), getContext(), mLocals);
|
||||
if (declaration.parseKeyword (keyword, loc, scanner))
|
||||
scanner.scan (declaration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case Scanner::K_set: mState = SetState; return true;
|
||||
case Scanner::K_messagebox: mState = MessageState; return true;
|
||||
|
||||
|
@ -328,6 +374,24 @@ namespace Compiler
|
|||
Generator::stopScript (mCode);
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_else:
|
||||
|
||||
getErrorHandler().warning ("stay else (ignoring it)", loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_endif:
|
||||
|
||||
getErrorHandler().warning ("stay endif (ignoring it)", loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_begin:
|
||||
|
||||
getErrorHandler().warning ("stay begin (ignoring it)", loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
||||
|
@ -365,7 +429,8 @@ namespace Compiler
|
|||
std::vector<Interpreter::Type_Code> code;
|
||||
char type = mExprParser.append (code);
|
||||
|
||||
Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type);
|
||||
Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type,
|
||||
!mReferenceMember);
|
||||
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
@ -389,7 +454,8 @@ namespace Compiler
|
|||
|
||||
bool LineParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (code==Scanner::S_newline && (mState==EndState || mState==BeginState))
|
||||
if (code==Scanner::S_newline &&
|
||||
(mState==EndState || mState==BeginState || mState==PotentialEndState))
|
||||
return false;
|
||||
|
||||
if (code==Scanner::S_comma && mState==MessageState)
|
||||
|
|
|
@ -20,11 +20,10 @@ namespace Compiler
|
|||
enum State
|
||||
{
|
||||
BeginState,
|
||||
ShortState, LongState, FloatState,
|
||||
SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState,
|
||||
SetMemberVarState, SetMemberVarState2,
|
||||
MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState,
|
||||
EndState,
|
||||
EndState, PotentialEndState /* may have a stray string argument */,
|
||||
PotentialExplicitState, ExplicitState, MemberState
|
||||
};
|
||||
|
||||
|
@ -34,6 +33,7 @@ namespace Compiler
|
|||
State mState;
|
||||
std::string mName;
|
||||
std::string mMemberName;
|
||||
bool mReferenceMember;
|
||||
int mButtons;
|
||||
std::string mExplicit;
|
||||
char mType;
|
||||
|
@ -44,7 +44,7 @@ namespace Compiler
|
|||
|
||||
public:
|
||||
|
||||
LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
LineParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
|
||||
Literals& literals, std::vector<Interpreter::Type_Code>& code,
|
||||
bool allowExpression = false);
|
||||
///< \param allowExpression Allow lines consisting of a naked expression
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <ostream>
|
||||
#include <iterator>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
const std::vector<std::string>& Locals::get (char type) const
|
||||
|
@ -97,7 +99,7 @@ namespace Compiler
|
|||
|
||||
void Locals::declare (char type, const std::string& name)
|
||||
{
|
||||
get (type).push_back (name);
|
||||
get (type).push_back (Misc::StringUtils::lowerCase (name));
|
||||
}
|
||||
|
||||
void Locals::clear()
|
||||
|
|
|
@ -203,8 +203,8 @@ namespace Compiler
|
|||
const int opcodeGetEffectExplicit = 0x20001d0;
|
||||
const int opcodeAddSoulGem = 0x20001f3;
|
||||
const int opcodeAddSoulGemExplicit = 0x20001f4;
|
||||
const int opcodeRemoveSoulGem = 0x20001f5;
|
||||
const int opcodeRemoveSoulGemExplicit = 0x20001f6;
|
||||
const int opcodeRemoveSoulGem = 0x20027;
|
||||
const int opcodeRemoveSoulGemExplicit = 0x20028;
|
||||
const int opcodeDrop = 0x20001f8;
|
||||
const int opcodeDropExplicit = 0x20001f9;
|
||||
const int opcodeDropSoulGem = 0x20001fa;
|
||||
|
@ -245,6 +245,8 @@ namespace Compiler
|
|||
const int opcodeCastExplicit = 0x2000228;
|
||||
const int opcodeExplodeSpell = 0x2000229;
|
||||
const int opcodeExplodeSpellExplicit = 0x200022a;
|
||||
const int opcodeGetPcInJail = 0x200023e;
|
||||
const int opcodeGetPcTraveling = 0x200023f;
|
||||
}
|
||||
|
||||
namespace Sky
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Compiler
|
|||
|
||||
// Return context
|
||||
|
||||
Context& Parser::getContext()
|
||||
const Context& Parser::getContext() const
|
||||
{
|
||||
return mContext;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ namespace Compiler
|
|||
return lowerCase;
|
||||
}
|
||||
|
||||
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
||||
Parser::Parser (ErrorHandler& errorHandler, const Context& context)
|
||||
: mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
|
||||
{}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Compiler
|
|||
class Parser
|
||||
{
|
||||
ErrorHandler& mErrorHandler;
|
||||
Context& mContext;
|
||||
const Context& mContext;
|
||||
bool mOptional;
|
||||
bool mEmpty;
|
||||
|
||||
|
@ -38,14 +38,14 @@ namespace Compiler
|
|||
ErrorHandler& getErrorHandler();
|
||||
///< Return error handler
|
||||
|
||||
Context& getContext();
|
||||
const Context& getContext() const;
|
||||
///< Return context
|
||||
|
||||
static std::string toLower (const std::string& name);
|
||||
|
||||
public:
|
||||
|
||||
Parser (ErrorHandler& errorHandler, Context& context);
|
||||
Parser (ErrorHandler& errorHandler, const Context& context);
|
||||
///< constructor
|
||||
|
||||
virtual ~Parser();
|
||||
|
|
52
components/compiler/quickfileparser.cpp
Normal file
52
components/compiler/quickfileparser.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
#include "quickfileparser.hpp"
|
||||
|
||||
#include "skipparser.hpp"
|
||||
#include "scanner.hpp"
|
||||
|
||||
Compiler::QuickFileParser::QuickFileParser (ErrorHandler& errorHandler, const Context& context,
|
||||
Locals& locals)
|
||||
: Parser (errorHandler, context), mDeclarationParser (errorHandler, context, locals)
|
||||
{}
|
||||
|
||||
bool Compiler::QuickFileParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner)
|
||||
{
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Compiler::QuickFileParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (keyword==Scanner::K_end)
|
||||
return false;
|
||||
|
||||
if (keyword==Scanner::K_short || keyword==Scanner::K_long || keyword==Scanner::K_float)
|
||||
{
|
||||
mDeclarationParser.reset();
|
||||
scanner.putbackKeyword (keyword, loc);
|
||||
scanner.scan (mDeclarationParser);
|
||||
return true;
|
||||
}
|
||||
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Compiler::QuickFileParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (code!=Scanner::S_newline)
|
||||
{
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compiler::QuickFileParser::parseEOF (Scanner& scanner)
|
||||
{
|
||||
|
||||
}
|
39
components/compiler/quickfileparser.hpp
Normal file
39
components/compiler/quickfileparser.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef COMPILER_QUICKFILEPARSER_H_INCLUDED
|
||||
#define COMPILER_QUICKFILEPARSER_H_INCLUDED
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "declarationparser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Locals;
|
||||
|
||||
/// \brief File parser variant that ignores everything but variable declarations
|
||||
class QuickFileParser : public Parser
|
||||
{
|
||||
DeclarationParser mDeclarationParser;
|
||||
|
||||
public:
|
||||
|
||||
QuickFileParser (ErrorHandler& errorHandler, const Context& context, Locals& locals);
|
||||
|
||||
virtual bool parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner);
|
||||
///< Handle a name token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a keyword token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a special character token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual void parseEOF (Scanner& scanner);
|
||||
///< Handle EOF token.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -370,9 +370,9 @@ namespace Compiler
|
|||
|
||||
if (c=='\n')
|
||||
special = S_newline;
|
||||
else if (c=='(')
|
||||
else if (c=='(' || c=='[') /// \todo option to disable the use of [ as alias for (
|
||||
special = S_open;
|
||||
else if (c==')')
|
||||
else if (c==')' || c==']') /// \todo option to disable the use of ] as alias for )
|
||||
special = S_close;
|
||||
else if (c=='.')
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Compiler
|
||||
{
|
||||
ScriptParser::ScriptParser (ErrorHandler& errorHandler, Context& context,
|
||||
ScriptParser::ScriptParser (ErrorHandler& errorHandler, const Context& context,
|
||||
Locals& locals, bool end)
|
||||
: Parser (errorHandler, context), mOutput (locals),
|
||||
mLineParser (errorHandler, context, locals, mOutput.getLiterals(), mOutput.getCode()),
|
||||
|
@ -32,7 +32,7 @@ namespace Compiler
|
|||
|
||||
bool ScriptParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (keyword==Scanner::K_while || keyword==Scanner::K_if)
|
||||
if (keyword==Scanner::K_while || keyword==Scanner::K_if || keyword==Scanner::K_elseif)
|
||||
{
|
||||
mControlParser.reset();
|
||||
if (mControlParser.parseKeyword (keyword, loc, scanner))
|
||||
|
@ -71,6 +71,12 @@ namespace Compiler
|
|||
if (code==Scanner::S_newline) // empty line
|
||||
return true;
|
||||
|
||||
if (code==Scanner::S_open) /// \todo Option to switch this off
|
||||
{
|
||||
scanner.putbackSpecial (code, loc);
|
||||
return parseKeyword (Scanner::K_if, loc, scanner);
|
||||
}
|
||||
|
||||
mLineParser.reset();
|
||||
if (mLineParser.parseSpecial (code, loc, scanner))
|
||||
scanner.scan (mLineParser);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue