diff --git a/.travis.yml b/.travis.yml index 0910ac546..e314d8e7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ os: - linux # - osx language: cpp +sudo: required +dist: trusty branches: only: - master @@ -18,8 +20,8 @@ addons: name: "OpenMW/openmw" description: "" notification_email: scrawl@baseoftrash.de - build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE" - build_command: "make" + build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE" + build_command: "make -j2" branch_pattern: coverity_scan matrix: include: @@ -38,7 +40,7 @@ before_script: - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi script: - cd ./build - - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi + - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j3; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi diff --git a/AUTHORS.md b/AUTHORS.md index bfbd14a5b..83a625406 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -113,6 +113,7 @@ Programmers Stefan Galowicz (bogglez) Stanislav Bobrov (Jiub) Sylvain Thesnieres (Garvek) + t6 terrorfisch Thomas Luppi (Digmaster) Tom Mason (wheybags) diff --git a/CI/before_install.linux.sh b/CI/before_install.linux.sh index 6e288aa14..1c02bc8d9 100755 --- a/CI/before_install.linux.sh +++ b/CI/before_install.linux.sh @@ -1,22 +1,17 @@ #!/bin/sh if [ "${ANALYZE}" ]; then - if [ $(lsb_release -sc) = "precise" ]; then - echo "yes" | sudo apt-add-repository ppa:ubuntu-toolchain-r/test - fi echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main" wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add - fi 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 -echo "yes" | sudo apt-add-repository ppa:boost-latest/ppa sudo apt-get update -qq sudo apt-get install -qq libgtest-dev google-mock -sudo apt-get install -qq libboost-filesystem1.55-dev libboost-program-options1.55-dev libboost-system1.55-dev libboost-thread1.55-dev -sudo apt-get install -qq ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev +sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev +sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev sudo apt-get install -qq libbullet-dev libopenscenegraph-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev -sudo apt-get install -qq cmake-data #workaround for broken osgqt cmake script in ubuntu 12.04 if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi sudo mkdir /usr/src/gtest/build cd /usr/src/gtest/build diff --git a/CI/before_script.linux.sh b/CI/before_script.linux.sh index 71ddd2040..17667ad28 100755 --- a/CI/before_script.linux.sh +++ b/CI/before_script.linux.sh @@ -1,5 +1,6 @@ #!/bin/sh +free -m mkdir build cd build export CODE_COVERAGE=1 diff --git a/README.md b/README.md index 585805368..b55a89945 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ OpenMW is a recreation of the engine for the popular role-playing game Morrowind OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction Set. -* Version: 0.37.0 +* Version: 0.38.0 * License: GPL (see docs/license/GPL3.txt for more information) * Website: http://www.openmw.org * IRC: #openmw on irc.freenode.net diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index f364e166c..81b2bec14 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -121,7 +121,7 @@ public: { mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel; mContext->mPlayerBase = npc; - std::map empty; + std::map empty; // FIXME: player start spells and birthsign spells aren't listed here, // need to fix openmw to account for this for (std::vector::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it) diff --git a/apps/essimporter/convertinventory.cpp b/apps/essimporter/convertinventory.cpp index f476fe1ee..0799c8d11 100644 --- a/apps/essimporter/convertinventory.cpp +++ b/apps/essimporter/convertinventory.cpp @@ -1,6 +1,7 @@ #include "convertinventory.hpp" #include +#include namespace ESSImport { diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f0e9e6f4b..0bde541bf 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -85,7 +85,7 @@ opencs_units (view/widget opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget - previewwidget editmode instancemode + previewwidget editmode instancemode instanceselectionmode ) opencs_units_noqt (view/render diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 86e96a88d..76bbb6f22 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -1,6 +1,6 @@ #include "messages.hpp" -CSMDoc::Message::Message() {} +CSMDoc::Message::Message() : mSeverity(Severity_Default){} CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint, Severity severity) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index 429feae4e..4041e1a67 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -39,9 +39,6 @@ namespace CSMDoc { public: - // \deprecated Use CSMDoc::Message directly instead. - typedef CSMDoc::Message Message; - typedef std::vector Collection; typedef Collection::const_iterator Iterator; diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp index 5fcf24fe4..ccbed6c8b 100644 --- a/apps/opencs/model/doc/operationholder.cpp +++ b/apps/opencs/model/doc/operationholder.cpp @@ -2,7 +2,9 @@ #include "operation.hpp" -CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false) +CSMDoc::OperationHolder::OperationHolder (Operation *operation) + : mOperation(NULL) + , mRunning (false) { if (operation) setOperation (operation); diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 859fabd11..fd777b133 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -133,6 +133,8 @@ void CSMPrefs::State::declare() declareBool ("show-linenum", "Show Line Numbers", true). setTooltip ("Show line numbers to the left of the script editor window." "The current row and column numbers of the text cursor are shown at the bottom."); + declareBool ("wrap-lines", "Wrap Lines", false). + setTooltip ("Wrap lines longer than width of script editor."); declareBool ("mono-font", "Use monospace font", true); EnumValue warningsNormal ("Normal", "Report warnings as warning"); declareEnum ("warnings", "Warning Mode", warningsNormal). diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index 77a14de84..49de1d651 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -182,7 +182,7 @@ int CSMTools::ReportModel::countErrors() const { int count = 0; - for (std::vector::const_iterator iter (mRows.begin()); + for (std::vector::const_iterator iter (mRows.begin()); iter!=mRows.end(); ++iter) if (iter->mSeverity==CSMDoc::Message::Severity_Error || iter->mSeverity==CSMDoc::Message::Severity_SeriousError) diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 5704970f5..61b4e6307 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -16,7 +16,7 @@ namespace CSMTools { Q_OBJECT - std::vector mRows; + std::vector mRows; // Fixed columns enum Columns diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index d510cd103..097e83f7c 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -14,7 +14,7 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand* parent) -: QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_), mHasRecordState(false) + : QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_), mHasRecordState(false), mOldRecordState(CSMWorld::RecordBase::State_BaseOnly) { if (QAbstractProxyModel *proxy = dynamic_cast (&model)) { diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 40981164d..bd85c8a14 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -22,11 +22,18 @@ bool CSVRender::Cell::removeObject (const std::string& id) if (iter==mObjects.end()) return false; - delete iter->second; - mObjects.erase (iter); + removeObject (iter); return true; } +std::map::iterator CSVRender::Cell::removeObject ( + std::map::iterator iter) +{ + delete iter->second; + mObjects.erase (iter++); + return iter; +} + bool CSVRender::Cell::addObjects (int start, int end) { bool modified = false; @@ -161,8 +168,8 @@ bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft, // perform update and remove where needed bool modified = false; - for (std::map::iterator iter (mObjects.begin()); - iter!=mObjects.end(); ++iter) + std::map::iterator iter = mObjects.begin(); + while (iter!=mObjects.end()) { if (iter->second->referenceDataChanged (topLeft, bottomRight)) modified = true; @@ -171,23 +178,30 @@ bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft, if (iter2!=ids.end()) { - if (iter2->second) + bool deleted = iter2->second; + ids.erase (iter2); + + if (deleted) { - removeObject (iter->first); + iter = removeObject (iter); modified = true; + continue; } - - ids.erase (iter2); } + + ++iter; } // add new objects for (std::map::iterator iter (ids.begin()); iter!=ids.end(); ++iter) { - mObjects.insert (std::make_pair ( - iter->first, new Object (mData, mCellNode, iter->first, false))); + if (!iter->second) + { + mObjects.insert (std::make_pair ( + iter->first, new Object (mData, mCellNode, iter->first, false))); - modified = true; + modified = true; + } } return modified; @@ -249,6 +263,28 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode) } } +void CSVRender::Cell::selectAllWithSameParentId (int elementMask) +{ + std::set ids; + + for (std::map::const_iterator iter (mObjects.begin()); + iter!=mObjects.end(); ++iter) + { + if (iter->second->getSelected()) + ids.insert (iter->second->getReferenceableId()); + } + + for (std::map::const_iterator iter (mObjects.begin()); + iter!=mObjects.end(); ++iter) + { + if (!iter->second->getSelected() && + ids.find (iter->second->getReferenceableId())!=ids.end()) + { + iter->second->setSelected (true); + } + } +} + void CSVRender::Cell::setCellArrows (int mask) { for (int i=0; i<4; ++i) @@ -276,3 +312,16 @@ bool CSVRender::Cell::isDeleted() const { return mDeleted; } + +std::vector > CSVRender::Cell::getSelection (unsigned int elementMask) const +{ + std::vector > result; + + if (elementMask & Mask_Reference) + for (std::map::const_iterator iter (mObjects.begin()); + iter!=mObjects.end(); ++iter) + if (iter->second->getSelected()) + result.push_back (iter->second->getTag()); + + return result; +} diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 59f4cafee..85b9bf21b 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -31,6 +31,8 @@ namespace CSMWorld namespace CSVRender { + class TagBase; + class Cell { CSMWorld::Data& mData; @@ -47,6 +49,10 @@ namespace CSVRender /// \return Was the object deleted? bool removeObject (const std::string& id); + // Remove object and return iterator to next object. + std::map::iterator removeObject ( + std::map::iterator iter); + /// Add objects from reference table that are within this cell. /// /// \return Have any objects been added? @@ -93,12 +99,18 @@ namespace CSVRender void setSelection (int elementMask, Selection mode); + // Select everything that references the same ID as at least one of the elements + // already selected + void selectAllWithSameParentId (int elementMask); + void setCellArrows (int mask); /// Returns 0, 0 in case of an unpaged cell. CSMWorld::CellCoordinates getCoordinates() const; bool isDeleted() const; + + std::vector > getSelection (unsigned int elementMask) const; }; } diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 4725a993f..4b6b2e41f 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -9,16 +9,73 @@ #include "../../model/world/idtree.hpp" #include "../../model/world/commands.hpp" +#include "../widget/scenetoolbar.hpp" +#include "../widget/scenetoolmode.hpp" + #include "mask.hpp" + #include "object.hpp" #include "worldspacewidget.hpp" #include "pagedworldspacewidget.hpp" +#include "instanceselectionmode.hpp" CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing", - parent) + parent), mSubMode (0), mSelectionMode (0) +{ +} + +void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar) +{ + if (!mSubMode) + { + mSubMode = new CSVWidget::SceneToolMode (toolbar, "Edit Sub-Mode"); + mSubMode->addButton (":placeholder", "move", + "Move selected instances" + "
  • Use primary edit to move instances around freely
  • " + "
  • Use secondary edit to move instances around within the grid
  • " + "
" + "Not implemented yet"); + mSubMode->addButton (":placeholder", "rotate", + "Rotate selected instances" + "
  • Use primary edit to rotate instances freely
  • " + "
  • Use secondary edit to rotate instances within the grid
  • " + "
" + "Not implemented yet"); + mSubMode->addButton (":placeholder", "scale", + "Scale selected instances" + "
  • Use primary edit to scale instances freely
  • " + "
  • Use secondary edit to scale instances along the grid
  • " + "
" + "Not implemented yet"); + } + + if (!mSelectionMode) + mSelectionMode = new InstanceSelectionMode (toolbar, getWorldspaceWidget()); + + EditMode::activate (toolbar); + + toolbar->addTool (mSubMode); + toolbar->addTool (mSelectionMode); +} + +void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar) { + if (mSelectionMode) + { + toolbar->removeTool (mSelectionMode); + delete mSelectionMode; + mSelectionMode = 0; + } + + if (mSubMode) + { + toolbar->removeTool (mSubMode); + delete mSubMode; + mSubMode = 0; + } + EditMode::deactivate (toolbar); } void CSVRender::InstanceMode::primaryEditPressed (osg::ref_ptr tag) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 7649c241c..78836878a 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -3,16 +3,29 @@ #include "editmode.hpp" +namespace CSVWidget +{ + class SceneToolMode; +} + namespace CSVRender { + class InstanceSelectionMode; + class InstanceMode : public EditMode { Q_OBJECT + CSVWidget::SceneToolMode *mSubMode; + InstanceSelectionMode *mSelectionMode; public: InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); + virtual void activate (CSVWidget::SceneToolbar *toolbar); + + virtual void deactivate (CSVWidget::SceneToolbar *toolbar); + virtual void primaryEditPressed (osg::ref_ptr tag); virtual void secondaryEditPressed (osg::ref_ptr tag); diff --git a/apps/opencs/view/render/instanceselectionmode.cpp b/apps/opencs/view/render/instanceselectionmode.cpp new file mode 100644 index 000000000..5c3aaa8d1 --- /dev/null +++ b/apps/opencs/view/render/instanceselectionmode.cpp @@ -0,0 +1,93 @@ + +#include "instanceselectionmode.hpp" + +#include +#include + +#include "../../model/world/idtable.hpp" +#include "../../model/world/commands.hpp" + +#include "worldspacewidget.hpp" +#include "object.hpp" + +bool CSVRender::InstanceSelectionMode::createContextMenu (QMenu *menu) +{ + if (menu) + { + menu->addAction (mSelectAll); + menu->addAction (mDeselectAll); + menu->addAction (mSelectSame); + menu->addAction (mDeleteSelection); + } + + return true; +} + +CSVRender::InstanceSelectionMode::InstanceSelectionMode (CSVWidget::SceneToolbar *parent, + WorldspaceWidget& worldspaceWidget) +: CSVWidget::SceneToolMode (parent, "Selection Mode"), mWorldspaceWidget (worldspaceWidget) +{ + addButton (":placeholder", "cube-centre", + "Centred cube" + "
  • Drag with primary (make instances the selection) or secondary (invert selection state) select button from the centre of the selection cube outwards
  • " + "
  • The selection cube is aligned to the word space axis
  • " + "
  • If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect
  • " + "
" + "Not implemented yet"); + addButton (":placeholder", "cube-corner", + "Cube corner to corner" + "
  • Drag with primary (make instances the selection) or secondary (invert selection state) select button from one corner of the selection cube to the opposite corner
  • " + "
  • The selection cube is aligned to the word space axis
  • " + "
  • If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect
  • " + "
" + "Not implemented yet"); + addButton (":placeholder", "sphere", + "Centred sphere" + "
  • Drag with primary (make instances the selection) or secondary (invert selection state) select button from the centre of the selection sphere outwards
  • " + "
  • If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect
  • " + "
" + "Not implemented yet"); + + mSelectAll = new QAction ("Select all instances", this); + mDeselectAll = new QAction ("Clear selection", this); + mDeleteSelection = new QAction ("Delete selected instances", this); + mSelectSame = new QAction ("Extend selection to instances with same object ID", this); + connect (mSelectAll, SIGNAL (triggered ()), this, SLOT (selectAll())); + connect (mDeselectAll, SIGNAL (triggered ()), this, SLOT (clearSelection())); + connect (mDeleteSelection, SIGNAL (triggered ()), this, SLOT (deleteSelection())); + connect (mSelectSame, SIGNAL (triggered ()), this, SLOT (selectSame())); +} + +void CSVRender::InstanceSelectionMode::selectAll() +{ + mWorldspaceWidget.selectAll (Mask_Reference); +} + +void CSVRender::InstanceSelectionMode::clearSelection() +{ + mWorldspaceWidget.clearSelection (Mask_Reference); +} + +void CSVRender::InstanceSelectionMode::deleteSelection() +{ + std::vector > selection = + mWorldspaceWidget.getSelection (Mask_Reference); + + CSMWorld::IdTable& referencesTable = + dynamic_cast (*mWorldspaceWidget.getDocument().getData(). + getTableModel (CSMWorld::UniversalId::Type_References)); + + for (std::vector >::iterator iter (selection.begin()); + iter!=selection.end(); ++iter) + { + CSMWorld::DeleteCommand *command = new CSMWorld::DeleteCommand (referencesTable, + static_cast (iter->get())->mObject->getReferenceId()); + + mWorldspaceWidget.getDocument().getUndoStack().push (command); + } +} + +void CSVRender::InstanceSelectionMode::selectSame() +{ + mWorldspaceWidget.selectAllWithSameParentId (Mask_Reference); +} diff --git a/apps/opencs/view/render/instanceselectionmode.hpp b/apps/opencs/view/render/instanceselectionmode.hpp new file mode 100644 index 000000000..cac2ca8c2 --- /dev/null +++ b/apps/opencs/view/render/instanceselectionmode.hpp @@ -0,0 +1,46 @@ +#ifndef CSV_RENDER_INSTANCE_SELECTION_MODE_H +#define CSV_RENDER_INSTANCE_SELECTION_MODE_H + +#include "../widget/scenetoolmode.hpp" + +class QAction; + +namespace CSVRender +{ + class WorldspaceWidget; + + class InstanceSelectionMode : public CSVWidget::SceneToolMode + { + Q_OBJECT + + WorldspaceWidget& mWorldspaceWidget; + QAction *mSelectAll; + QAction *mDeselectAll; + QAction *mDeleteSelection; + QAction *mSelectSame; + + /// Add context menu items to \a menu. + /// + /// \attention menu can be a 0-pointer + /// + /// \return Have there been any menu items to be added (if menu is 0 and there + /// items to be added, the function must return true anyway. + virtual bool createContextMenu (QMenu *menu); + + public: + + InstanceSelectionMode (CSVWidget::SceneToolbar *parent, WorldspaceWidget& worldspaceWidget); + + private slots: + + void selectAll(); + + void clearSelection(); + + void deleteSelection(); + + void selectSame(); + }; +} + +#endif diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 1821da059..b980b658a 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -187,6 +187,7 @@ CSVRender::Object::~Object() clear(); mParentNode->removeChild(mBaseNode); + mParentNode->removeChild(mOutline); } void CSVRender::Object::setSelected(bool selected) @@ -284,3 +285,8 @@ std::string CSVRender::Object::getReferenceableId() const { return mReferenceableId; } + +osg::ref_ptr CSVRender::Object::getTag() const +{ + return static_cast (mBaseNode->getUserData()); +} diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index e7638e7a9..4a89fe201 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -114,6 +114,8 @@ namespace CSVRender std::string getReferenceId() const; std::string getReferenceableId() const; + + osg::ref_ptr getTag() const; }; } diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 1880beab8..d71446d0b 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -509,6 +509,24 @@ void CSVRender::PagedWorldspaceWidget::clearSelection (int elementMask) flagAsModified(); } +void CSVRender::PagedWorldspaceWidget::selectAll (int elementMask) +{ + for (std::map::iterator iter = mCells.begin(); + iter!=mCells.end(); ++iter) + iter->second->setSelection (elementMask, Cell::Selection_All); + + flagAsModified(); +} + +void CSVRender::PagedWorldspaceWidget::selectAllWithSameParentId (int elementMask) +{ + for (std::map::iterator iter = mCells.begin(); + iter!=mCells.end(); ++iter) + iter->second->selectAllWithSameParentId (elementMask); + + flagAsModified(); +} + std::string CSVRender::PagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const { const int cellSize = 8192; @@ -520,6 +538,23 @@ std::string CSVRender::PagedWorldspaceWidget::getCellId (const osg::Vec3f& point return cellCoordinates.getId (mWorldspace); } +std::vector > CSVRender::PagedWorldspaceWidget::getSelection ( + unsigned int elementMask) const +{ + std::vector > result; + + for (std::map::const_iterator iter = mCells.begin(); + iter!=mCells.end(); ++iter) + { + std::vector > cellResult = + iter->second->getSelection (elementMask); + + result.insert (result.end(), cellResult.begin(), cellResult.end()); + } + + return result; +} + CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector ( CSVWidget::SceneToolbar *parent) { diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 647341d1f..419a2a46a 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -98,8 +98,20 @@ namespace CSVRender /// \param elementMask Elements to be affected by the clear operation virtual void clearSelection (int elementMask); + /// \param elementMask Elements to be affected by the select operation + virtual void selectAll (int elementMask); + + // Select everything that references the same ID as at least one of the elements + // already selected + // + /// \param elementMask Elements to be affected by the select operation + virtual void selectAllWithSameParentId (int elementMask); + virtual std::string getCellId (const osg::Vec3f& point) const; + virtual std::vector > getSelection (unsigned int elementMask) + const; + protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index dad37c946..8d65c3694 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -108,11 +108,29 @@ void CSVRender::UnpagedWorldspaceWidget::clearSelection (int elementMask) flagAsModified(); } +void CSVRender::UnpagedWorldspaceWidget::selectAll (int elementMask) +{ + mCell->setSelection (elementMask, Cell::Selection_All); + flagAsModified(); +} + +void CSVRender::UnpagedWorldspaceWidget::selectAllWithSameParentId (int elementMask) +{ + mCell->selectAllWithSameParentId (elementMask); + flagAsModified(); +} + std::string CSVRender::UnpagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const { return mCellId; } +std::vector > CSVRender::UnpagedWorldspaceWidget::getSelection ( + unsigned int elementMask) const +{ + return mCell->getSelection (elementMask); +} + void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index 70a20c216..a4c517948 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -46,8 +46,20 @@ namespace CSVRender /// \param elementMask Elements to be affected by the clear operation virtual void clearSelection (int elementMask); + /// \param elementMask Elements to be affected by the select operation + virtual void selectAll (int elementMask); + + // Select everything that references the same ID as at least one of the elements + // already selected + // + /// \param elementMask Elements to be affected by the select operation + virtual void selectAllWithSameParentId (int elementMask); + virtual std::string getCellId (const osg::Vec3f& point) const; + virtual std::vector > getSelection (unsigned int elementMask) + const; + private: virtual void referenceableDataChanged (const QModelIndex& topLeft, diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 184477d6b..af90af50c 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -33,8 +33,9 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) : SceneWidget (document.getData().getResourceSystem(), parent), mSceneElements(0), mRun(0), mDocument(document), - mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false), - mToolTipPos (-1, -1) + mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false), mDragX(0), mDragY(0), mDragFactor(0), + mDragWheelFactor(0), mDragShiftFactor(0), + mToolTipPos (-1, -1), mShowToolTips(false), mToolTipDelay(0) { setAcceptDrops(true); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 7a77edad4..ac6426b42 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -127,6 +127,15 @@ namespace CSVRender /// \param elementMask Elements to be affected by the clear operation virtual void clearSelection (int elementMask) = 0; + /// \param elementMask Elements to be affected by the select operation + virtual void selectAll (int elementMask) = 0; + + // Select everything that references the same ID as at least one of the elements + // already selected + // + /// \param elementMask Elements to be affected by the select operation + virtual void selectAllWithSameParentId (int elementMask) = 0; + /// Return the next intersection point with scene elements matched by /// \a interactionMask based on \a localPos and the camera vector. /// If there is no such point, instead a point "in front" of \a localPos will be @@ -140,6 +149,9 @@ namespace CSVRender virtual std::string getCellId (const osg::Vec3f& point) const = 0; + virtual std::vector > getSelection (unsigned int elementMask) + const = 0; + protected: /// Visual elements in a scene diff --git a/apps/opencs/view/widget/modebutton.cpp b/apps/opencs/view/widget/modebutton.cpp index 7c62f6bb1..88f050247 100644 --- a/apps/opencs/view/widget/modebutton.cpp +++ b/apps/opencs/view/widget/modebutton.cpp @@ -7,3 +7,8 @@ CSVWidget::ModeButton::ModeButton (const QIcon& icon, const QString& tooltip, QW void CSVWidget::ModeButton::activate (SceneToolbar *toolbar) {} void CSVWidget::ModeButton::deactivate (SceneToolbar *toolbar) {} + +bool CSVWidget::ModeButton::createContextMenu (QMenu *menu) +{ + return false; +} diff --git a/apps/opencs/view/widget/modebutton.hpp b/apps/opencs/view/widget/modebutton.hpp index ac14afc95..1615ff298 100644 --- a/apps/opencs/view/widget/modebutton.hpp +++ b/apps/opencs/view/widget/modebutton.hpp @@ -3,6 +3,8 @@ #include "pushbutton.hpp" +class QMenu; + namespace CSVWidget { class SceneToolbar; @@ -22,6 +24,14 @@ namespace CSVWidget /// Default-Implementation: do nothing virtual void deactivate (SceneToolbar *toolbar); + + /// Add context menu items to \a menu. Default-implementation: return false + /// + /// \attention menu can be a 0-pointer + /// + /// \return Have there been any menu items to be added (if menu is 0 and there + /// items to be added, the function must return true anyway. + virtual bool createContextMenu (QMenu *menu); }; } diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index a93bb0556..125f4ac79 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -3,10 +3,27 @@ #include #include #include +#include +#include #include "scenetoolbar.hpp" #include "modebutton.hpp" +void CSVWidget::SceneToolMode::contextMenuEvent (QContextMenuEvent *event) +{ + QMenu menu (this); + if (createContextMenu (&menu)) + menu.exec (event->globalPos()); +} + +bool CSVWidget::SceneToolMode::createContextMenu (QMenu *menu) +{ + if (mCurrent) + return mCurrent->createContextMenu (menu); + + return false; +} + void CSVWidget::SceneToolMode::adjustToolTip (const ModeButton *activeMode) { QString toolTip = mToolTip; @@ -15,6 +32,9 @@ void CSVWidget::SceneToolMode::adjustToolTip (const ModeButton *activeMode) toolTip += "

(left click to change mode)"; + if (createContextMenu (0)) + toolTip += "
(right click to access context menu)"; + setToolTip (toolTip); } diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 6828a2269..3aa8e6799 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -6,6 +6,7 @@ #include class QHBoxLayout; +class QMenu; namespace CSVWidget { @@ -29,6 +30,17 @@ namespace CSVWidget void adjustToolTip (const ModeButton *activeMode); + virtual void contextMenuEvent (QContextMenuEvent *event); + + /// Add context menu items to \a menu. Default-implementation: Pass on request to + /// current mode button or return false, if there is no current mode button. + /// + /// \attention menu can be a 0-pointer + /// + /// \return Have there been any menu items to be added (if menu is 0 and there + /// items to be added, the function must return true anyway. + virtual bool createContextMenu (QMenu *menu); + public: SceneToolMode (SceneToolbar *parent, const QString& toolTip); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 44fe94d84..7014b1486 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -122,7 +122,7 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp CSVWidget::SceneToolRun *runTool = widget->makeRunTool (toolbar); toolbar->addTool (runTool); - toolbar->addTool (widget->makeEditModeSelector (toolbar)); + toolbar->addTool (widget->makeEditModeSelector (toolbar), runTool); return toolbar; } diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 9f1abcf97..d0146445a 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -38,20 +38,20 @@ bool CSVWorld::ScriptEdit::event (QEvent *event) return QPlainTextEdit::event (event); } -CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode, - QWidget* parent) - : QPlainTextEdit (parent), - mChangeLocked (0), +CSVWorld::ScriptEdit::ScriptEdit( + const CSMDoc::Document& document, + ScriptHighlighter::Mode mode, + QWidget* parent +) : QPlainTextEdit(parent), + mChangeLocked(0), mShowLineNum(false), mLineNumberArea(0), mDefaultFont(font()), mMonoFont(QFont("Monospace")), - mDocument (document), + mDocument(document), mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive) - { -// setAcceptRichText (false); - setLineWrapMode (QPlainTextEdit::NoWrap); + wrapLines(false); setTabStopWidth (4); setUndoRedoEnabled (false); // we use OpenCS-wide undo/redo instead @@ -194,14 +194,37 @@ bool CSVWorld::ScriptEdit::stringNeedsQuote (const std::string& id) const return !(string.contains(mWhiteListQoutes)); } -void CSVWorld::ScriptEdit::settingChanged (const CSMPrefs::Setting *setting) +void CSVWorld::ScriptEdit::wrapLines(bool wrap) +{ + if (wrap) + { + setLineWrapMode(QPlainTextEdit::WidgetWidth); + } + else + { + setLineWrapMode(QPlainTextEdit::NoWrap); + } +} + +void CSVWorld::ScriptEdit::settingChanged(const CSMPrefs::Setting *setting) { - if (mHighlighter->settingChanged (setting)) + // Determine which setting was changed. + if (mHighlighter->settingChanged(setting)) + { updateHighlighting(); - else if (*setting=="Scripts/mono-font") - setFont (setting->isTrue() ? mMonoFont : mDefaultFont); - else if (*setting=="Scripts/show-linenum") - showLineNum (setting->isTrue()); + } + else if (*setting == "Scripts/mono-font") + { + setFont(setting->isTrue() ? mMonoFont : mDefaultFont); + } + else if (*setting == "Scripts/show-linenum") + { + showLineNum(setting->isTrue()); + } + else if (*setting == "Scripts/wrap-lines") + { + wrapLines(setting->isTrue()); + } } void CSVWorld::ScriptEdit::idListChanged() diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index 941a6295d..1f03f050a 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -22,6 +22,7 @@ namespace CSVWorld { class LineNumberArea; + /// \brief Editor for scripts. class ScriptEdit : public QPlainTextEdit { Q_OBJECT @@ -77,6 +78,7 @@ namespace CSVWorld virtual void resizeEvent(QResizeEvent *e); private: + QVector mAllowedTypes; const CSMDoc::Document& mDocument; const QRegExp mWhiteListQoutes; @@ -89,9 +91,15 @@ namespace CSVWorld bool stringNeedsQuote(const std::string& id) const; + /// \brief Turn line wrapping in script editor on or off. + /// \param wrap Whether or not to wrap lines. + void wrapLines(bool wrap); + private slots: - void settingChanged (const CSMPrefs::Setting *setting); + /// \brief Update editor when related setting is changed. + /// \param setting Setting that was changed. + void settingChanged(const CSMPrefs::Setting *setting); void idListChanged(); diff --git a/apps/opencs/view/world/startscriptcreator.cpp b/apps/opencs/view/world/startscriptcreator.cpp index 69b1b3ff1..7495da035 100644 --- a/apps/opencs/view/world/startscriptcreator.cpp +++ b/apps/opencs/view/world/startscriptcreator.cpp @@ -1,20 +1,118 @@ #include "startscriptcreator.hpp" -CSVWorld::StartScriptCreator::StartScriptCreator(CSMWorld::Data &data, QUndoStack &undoStack, const CSMWorld::UniversalId &id, bool relaxedIdRules): - GenericCreator (data, undoStack, id, true) -{} +#include + +#include "../../model/doc/document.hpp" + +#include "../../model/world/columns.hpp" +#include "../../model/world/commands.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/idcompletionmanager.hpp" +#include "../../model/world/idtable.hpp" + +#include "../widget/droplineedit.hpp" + +std::string CSVWorld::StartScriptCreator::getId() const +{ + return mScript->text().toUtf8().constData(); +} + +CSMWorld::IdTable& CSVWorld::StartScriptCreator::getStartScriptsTable() const +{ + return dynamic_cast ( + *getData().getTableModel(getCollectionId()) + ); +} + +void CSVWorld::StartScriptCreator::configureCreateCommand(CSMWorld::CreateCommand& command) const +{ + CSMWorld::IdTable& table = getStartScriptsTable(); + int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_Id); + + // Set script ID to be added to start scripts table. + command.addValue(column, mScript->text()); +} + +CSVWorld::StartScriptCreator::StartScriptCreator( + CSMWorld::Data &data, + QUndoStack &undoStack, + const CSMWorld::UniversalId &id, + CSMWorld::IdCompletionManager& completionManager +) : GenericCreator(data, undoStack, id, true) +{ + setManualEditing(false); + + // Add script ID input label. + QLabel *label = new QLabel("Script ID", this); + insertBeforeButtons(label, false); + + // Add script ID input with auto-completion. + CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Script; + mScript = new CSVWidget::DropLineEdit(displayType, this); + mScript->setCompleter(completionManager.getCompleter(displayType).get()); + insertBeforeButtons(mScript, true); + + connect(mScript, SIGNAL (textChanged(const QString&)), this, SLOT (scriptChanged())); +} + +void CSVWorld::StartScriptCreator::cloneMode( + const std::string& originId, + const CSMWorld::UniversalId::Type type) +{ + CSVWorld::GenericCreator::cloneMode(originId, type); + + // Look up cloned record in start scripts table and set script ID text. + CSMWorld::IdTable& table = getStartScriptsTable(); + int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_Id); + mScript->setText(table.data(table.getModelIndex(originId, column)).toString()); +} std::string CSVWorld::StartScriptCreator::getErrors() const { - std::string errors; + std::string scriptId = getId(); - errors = getIdValidatorResult(); - if (errors.length() > 0) - return errors; - else if (getData().getScripts().searchId(getId()) == -1) + // Check user input for any errors. + std::string errors; + if (scriptId.empty()) + { + errors = "No Script ID entered"; + } + else if (getData().getScripts().searchId(scriptId) == -1) + { errors = "Script ID not found"; - else if (getData().getStartScripts().searchId(getId()) > -1 ) + } + else if (getData().getStartScripts().searchId(scriptId) > -1) + { errors = "Script with this ID already registered as Start Script"; + } return errors; } + +void CSVWorld::StartScriptCreator::focus() +{ + mScript->setFocus(); +} + +void CSVWorld::StartScriptCreator::reset() +{ + CSVWorld::GenericCreator::reset(); + mScript->setText(""); +} + +void CSVWorld::StartScriptCreator::scriptChanged() +{ + update(); +} + +CSVWorld::Creator *CSVWorld::StartScriptCreatorFactory::makeCreator( + CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const +{ + return new StartScriptCreator( + document.getData(), + document.getUndoStack(), + id, + document.getIdCompletionManager() + ); +} diff --git a/apps/opencs/view/world/startscriptcreator.hpp b/apps/opencs/view/world/startscriptcreator.hpp index 07fe8ff3d..473e2fd5f 100644 --- a/apps/opencs/view/world/startscriptcreator.hpp +++ b/apps/opencs/view/world/startscriptcreator.hpp @@ -3,23 +3,77 @@ #include "genericcreator.hpp" -namespace CSVWorld { +namespace CSMWorld +{ + class IdCompletionManager; + class IdTable; +} + +namespace CSVWidget +{ + class DropLineEdit; +} +namespace CSVWorld +{ + /// \brief Record creator for start scripts. class StartScriptCreator : public GenericCreator { Q_OBJECT + CSVWidget::DropLineEdit *mScript; + + private: + + /// \return script ID entered by user. + virtual std::string getId() const; + + /// \return reference to table containing start scripts. + CSMWorld::IdTable& getStartScriptsTable() const; + + /// \brief Add user input to command for creating start script. + /// \param command Creation command to configure. + virtual void configureCreateCommand(CSMWorld::CreateCommand& command) const; + public: - StartScriptCreator(CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id, bool relaxedIdRules = false); + StartScriptCreator( + CSMWorld::Data& data, + QUndoStack& undoStack, + const CSMWorld::UniversalId& id, + CSMWorld::IdCompletionManager& completionManager); + + /// \brief Set script ID input widget to ID of record to be cloned. + /// \param originId Script ID to be cloned. + /// \param type Type of record to be cloned. + virtual void cloneMode( + const std::string& originId, + const CSMWorld::UniversalId::Type type); + + /// \return Error description for current user input. virtual std::string getErrors() const; - ///< Return formatted error descriptions for the current state of the creator. if an empty - /// string is returned, there is no error. - }; -} + /// \brief Set focus to script ID input widget. + virtual void focus(); + + /// \brief Clear script ID input widget. + virtual void reset(); + private slots: + + /// \brief Check user input for any errors. + void scriptChanged(); + }; + /// \brief Creator factory for start script record creator. + class StartScriptCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator( + CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const; + }; +} #endif // STARTSCRIPTCREATOR_HPP diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 88375caaf..650f344ed 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -52,7 +52,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_StartScripts, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_Cells, new CSVDoc::SubViewFactoryWithCreator >); @@ -136,8 +136,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CreatorFactory > (false)); manager.add (CSMWorld::UniversalId::Type_StartScript, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator(false)); manager.add (CSMWorld::UniversalId::Type_Skill, new CSVDoc::SubViewFactoryWithCreator (false)); @@ -177,7 +176,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_MetaData, new CSVDoc::SubViewFactory); - + //preview manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory); } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 95dfa1034..45e50dba7 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -12,7 +11,6 @@ #include "../../model/doc/document.hpp" -#include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/infotableproxymodel.hpp" #include "../../model/world/idtableproxymodel.hpp" @@ -20,13 +18,10 @@ #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 "../../model/world/commanddispatcher.hpp" #include "../../model/prefs/state.hpp" -#include "recordstatusdelegate.hpp" #include "tableeditidaction.hpp" #include "util.hpp" @@ -231,7 +226,7 @@ void CSVWorld::Table::mouseDoubleClickEvent (QMouseEvent *event) CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) : DragRecordTable(document), mCreateAction (0), - mCloneAction(0),mRecordStatusDisplay (0) + mCloneAction(0), mRecordStatusDisplay (0), mJumpToAddedRecord(false), mUnselectAfterJump(false) { mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); @@ -339,8 +334,6 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), this, SLOT (tableSizeUpdate())); - //connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), - // this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int))); connect (mProxyModel, SIGNAL (rowAdded (const std::string &)), this, SLOT (rowAdded (const std::string &))); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 53249f66f..768ff185d 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -11,7 +11,6 @@ #include "../../model/world/universalid.hpp" #include "dragrecordtable.hpp" -class QUndoStack; class QAction; namespace CSMDoc @@ -21,7 +20,6 @@ namespace CSMDoc namespace CSMWorld { - class Data; class IdTableProxyModel; class IdTableBase; class CommandDispatcher; diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index eed522227..5a25bbc53 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -76,7 +76,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto CSMDoc::Document& document, const CSMWorld::UniversalId& id, QWidget *parent) -: QWidget (parent), mShowStatusBar (false), mEditMode(EditMode_None), mHasPosition(false) +: QWidget (parent), mShowStatusBar (false), mEditMode(EditMode_None), mHasPosition(false), mRow(0), mColumn(0) { for (int i=0; i<4; ++i) mStatusCount[i] = 0; diff --git a/apps/openmw/crashcatcher.cpp b/apps/openmw/crashcatcher.cpp index 0b4ff6304..cafd0e08a 100644 --- a/apps/openmw/crashcatcher.cpp +++ b/apps/openmw/crashcatcher.cpp @@ -24,7 +24,7 @@ #ifndef PR_SET_PTRACER #define PR_SET_PTRACER 0x59616d61 #endif -#elif defined (__APPLE__) +#elif defined (__APPLE__) || defined (__FreeBSD__) #include #endif diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index b8dc90cf7..84da270eb 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1556,7 +1556,7 @@ namespace MWMechanics (target == getPlayer() && MWBase::Environment::get().getWorld()->getGlobalInt("pcknownwerewolf"))) { - const ESM::GameSetting * iWerewolfFightMod = MWBase::Environment::get().getWorld()->getStore().get().search("iWerewolfFightMod"); + const ESM::GameSetting * iWerewolfFightMod = MWBase::Environment::get().getWorld()->getStore().get().find("iWerewolfFightMod"); fight += iWerewolfFightMod->getInt(); } } diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index a88b6b263..2f87d0446 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -44,7 +44,7 @@ namespace MWMechanics { if (mSpells.find (spell)==mSpells.end()) { - std::map random; + std::map random; // Determine the random magnitudes (unless this is a castable spell, in which case // they will be determined when the spell is cast) diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index 1b1993d5e..a46988c4c 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -33,7 +33,7 @@ namespace MWMechanics typedef const ESM::Spell* SpellKey; - typedef std::map > TContainer; // ID, + typedef std::map > TContainer; // ID, typedef TContainer::const_iterator TIterator; struct CorprusStats diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 61ce626fd..c8d0925b0 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -42,6 +42,7 @@ #include "camera.hpp" #include "water.hpp" #include "terrainstorage.hpp" +#include "util.hpp" namespace MWRender { @@ -504,15 +505,6 @@ namespace MWRender mutable bool mDone; }; - - class NoTraverseCallback : public osg::NodeCallback - { - public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) - { - } - }; - void RenderingManager::screenshot(osg::Image *image, int w, int h) { osg::ref_ptr rttCamera (new osg::Camera); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index efe797336..513fc74a3 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -374,8 +375,13 @@ public: } else if (mMeshType == 2) { - osg::Vec4Array* origColors = static_cast(geom->getColorArray()); - alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f; + if (geom->getColorArray()) + { + osg::Vec4Array* origColors = static_cast(geom->getColorArray()); + alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f; + } + else + alpha = 1.f; } (*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha); diff --git a/apps/openmw/mwrender/util.hpp b/apps/openmw/mwrender/util.hpp index d078f0d98..815e34596 100644 --- a/apps/openmw/mwrender/util.hpp +++ b/apps/openmw/mwrender/util.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_MWRENDER_UTIL_H #define OPENMW_MWRENDER_UTIL_H +#include #include #include @@ -16,9 +17,17 @@ namespace Resource namespace MWRender { - void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr node); + // Node callback to entirely skip the traversal. + class NoTraverseCallback : public osg::NodeCallback + { + public: + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + // no traverse() + } + }; } #endif diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 1b19246f5..b2bef7122 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -41,6 +41,7 @@ #include "vismask.hpp" #include "ripplesimulation.hpp" #include "renderbin.hpp" +#include "util.hpp" namespace { @@ -210,16 +211,6 @@ private: osg::Plane mPlane; }; -// Node callback to entirely skip the traversal. -class NoTraverseCallback : public osg::NodeCallback -{ -public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) - { - // no traverse() - } -}; - /// Moves water mesh away from the camera slightly if the camera gets too close on the Z axis. /// The offset works around graphics artifacts that occured with the GL_DEPTH_CLAMP when the camera gets extremely close to the mesh (seen on NVIDIA at least). /// Must be added as a Cull callback. diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 42c204ecb..93219c649 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -447,5 +447,7 @@ op 0x20002fe: RemoveFromLevItem op 0x20002ff: SetFactionReaction op 0x2000300: EnableLevelupMenu op 0x2000301: ToggleScripts +op 0x2000302: Fixme +op 0x2000303: Fixme, explicit -opcodes 0x2000302-0x3ffffff unused +opcodes 0x2000304-0x3ffffff unused diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 60847e745..64c126de1 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -734,6 +734,18 @@ namespace MWScript } }; + template + class OpFixme : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + MWBase::Environment::get().getWorld()->fixPosition(ptr); + } + }; + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5(Compiler::Transformation::opcodeSetScale,new OpSetScale); @@ -774,6 +786,8 @@ namespace MWScript interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngle, new OpGetStartingAngle); interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngleExplicit, new OpGetStartingAngle); interpreter.installSegment5(Compiler::Transformation::opcodeResetActors, new OpResetActors); + interpreter.installSegment5(Compiler::Transformation::opcodeFixme, new OpFixme); + interpreter.installSegment5(Compiler::Transformation::opcodeFixmeExplicit, new OpFixme); } } } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 28d2dad4c..d87ffdb70 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -5,6 +5,7 @@ #include "../mwscript/locals.hpp" +#include #include namespace SceneUtil diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c566a32b5..37743bceb 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -108,7 +108,11 @@ namespace MWWorld } private: +#ifdef HAVE_UNORDERED_MAP + typedef std::unordered_map LoadersContainer; +#else typedef std::tr1::unordered_map LoadersContainer; +#endif LoadersContainer mLoaders; }; @@ -433,7 +437,7 @@ namespace MWWorld // Werewolf (BM) gmst["fWereWolfRunMult"] = ESM::Variant(1.f); gmst["fWereWolfSilverWeaponDamageMult"] = ESM::Variant(1.f); - + gmst["iWerewolfFightMod"] = ESM::Variant(1); std::map globals; // vanilla Morrowind does not define dayspassed. @@ -1311,7 +1315,8 @@ namespace MWWorld actor.getRefData().setPosition(pos); osg::Vec3f traced = mPhysics->traceDown(actor, dist*1.1f); - moveObject(actor, actor.getCell(), traced.x(), traced.y(), traced.z()); + if (traced != pos.asVec3()) + moveObject(actor, actor.getCell(), traced.x(), traced.y(), traced.z()); } void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) @@ -1744,6 +1749,8 @@ namespace MWWorld { cellid.mWorldspace = ref.mRef.getDestCell(); cellid.mPaged = false; + cellid.mIndex.mX = 0; + cellid.mIndex.mY = 0; } else { diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 8c76cdbb8..6916945f9 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -541,6 +541,7 @@ namespace Compiler extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit); extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit); extensions.registerInstruction("resetactors","",opcodeResetActors); + extensions.registerInstruction("fixme","",opcodeFixme, opcodeFixmeExplicit); extensions.registerInstruction("ra","",opcodeResetActors); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index e7d51d934..feed5513e 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -498,6 +498,8 @@ namespace Compiler const int opcodeMoveWorld = 0x2000208; const int opcodeMoveWorldExplicit = 0x2000209; const int opcodeResetActors = 0x20002f4; + const int opcodeFixme = 0x2000302; + const int opcodeFixmeExplicit = 0x2000303; } namespace User diff --git a/components/esm/spellstate.cpp b/components/esm/spellstate.cpp index 3ed3329b4..8845842e9 100644 --- a/components/esm/spellstate.cpp +++ b/components/esm/spellstate.cpp @@ -12,7 +12,7 @@ namespace ESM { std::string id = esm.getHString(); - std::map random; + std::map random; while (esm.isNextSub("INDX")) { int index; @@ -73,8 +73,8 @@ namespace ESM { esm.writeHNString("SPEL", it->first); - const std::map& random = it->second; - for (std::map::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt) + const std::map& random = it->second; + for (std::map::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt) { esm.writeHNT("INDX", rIt->first); esm.writeHNT("RAND", rIt->second); diff --git a/components/esm/spellstate.hpp b/components/esm/spellstate.hpp index 028e6a387..503c3aea9 100644 --- a/components/esm/spellstate.hpp +++ b/components/esm/spellstate.hpp @@ -28,7 +28,7 @@ namespace ESM float mMagnitude; }; - typedef std::map > TContainer; + typedef std::map > TContainer; TContainer mSpells; std::map > mPermanentSpellEffects; diff --git a/components/resource/bulletshape.cpp b/components/resource/bulletshape.cpp index 968dbe6c6..0cbc63a22 100644 --- a/components/resource/bulletshape.cpp +++ b/components/resource/bulletshape.cpp @@ -1,6 +1,7 @@ #include "bulletshape.hpp" #include +#include #include #include diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 1d1c5a365..43ece41f3 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -201,10 +201,22 @@ namespace Resource } catch (std::exception& e) { - std::cerr << "Failed to load '" << name << "': " << e.what() << ", using marker_error.nif instead" << std::endl; - Files::IStreamPtr file = mVFS->get("meshes/marker_error.nif"); - normalized = "meshes/marker_error.nif"; - loaded = load(file, normalized, mTextureManager, mNifFileManager); + static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2" }; + + for (unsigned int i=0; iexists(normalized)) + { + std::cerr << "Failed to load '" << name << "': " << e.what() << ", using marker_error." << sMeshTypes[i] << " instead" << std::endl; + Files::IStreamPtr file = mVFS->get(normalized); + loaded = load(file, normalized, mTextureManager, mNifFileManager); + break; + } + } + + if (!loaded) + throw; } osgDB::Registry::instance()->getOrCreateSharedStateManager()->share(loaded.get()); diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index 07b3b4a62..0d8610ead 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -5,6 +5,7 @@ #include #include +#include namespace SceneUtil { diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 6a2495e26..e4a8387b4 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -14,7 +14,7 @@ [Camera] # Near clipping plane (>0.0, e.g. 0.01 to 18.0). -near clip = 5.0 +near clip = 1 # Cull objects smaller than one pixel. small feature culling = true