diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 9d8dd89e1a..bdfefbb83f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -68,7 +68,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate - scripthighlighter idvalidator dialoguecreator physicssystem physicsmanager + scripthighlighter idvalidator dialoguecreator physicssystem ) opencs_units (view/widget diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index bef83b8ac7..53c6865eb4 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -1,6 +1,8 @@ #include "editor.hpp" +#include + #include #include #include @@ -21,7 +23,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) : mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), - mViewManager (mDocumentManager), mPhysicsManager (0), + mViewManager (mDocumentManager), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) { std::pair > config = readConfig(); @@ -34,7 +36,6 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); mOverlaySystem.reset (new CSVRender::OverlaySystem); - mPhysicsManager.reset (new CSVWorld::PhysicsManager); Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true, mFsStrict); @@ -70,7 +71,10 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) } CS::Editor::~Editor () -{} +{ + // cleanup global resources used by OEngine + delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); +} void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) { diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index d55b0e873e..cd39d53a48 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -28,7 +28,6 @@ #include "view/settings/dialog.hpp" #include "view/render/overlaysystem.hpp" -#include "view/world/physicsmanager.hpp" namespace OgreInit { @@ -45,7 +44,6 @@ namespace CS Files::ConfigurationManager mCfgMgr; CSMSettings::UserSettings mUserSettings; std::auto_ptr mOverlaySystem; - std::auto_ptr mPhysicsManager; CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; CSVDoc::StartupDialogue mStartup; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 4fdfd2e5e4..4abd67a505 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -9,6 +9,8 @@ #include #endif +#include "../../view/world/physicssystem.hpp" + void CSMDoc::Document::addGmsts() { static const char *gmstFloats[] = @@ -2253,7 +2255,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSaving (*this, mProjectPath, encoding), - mRunner (mProjectPath) + mRunner (mProjectPath), mPhysics(boost::shared_ptr()) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); @@ -2464,3 +2466,11 @@ void CSMDoc::Document::progress (int current, int max, int type) { emit progress (current, max, type, 1, this); } + +boost::shared_ptr CSMDoc::Document::getPhysics () +{ + if(!mPhysics) + mPhysics = boost::shared_ptr (new CSVWorld::PhysicsSystem()); + + return mPhysics; +} diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index c5f6d10067..e5aa5eea58 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -3,6 +3,7 @@ #include +#include #include #include @@ -39,6 +40,11 @@ namespace CSMWorld class ResourcesManager; } +namespace CSVWorld +{ + class PhysicsSystem; +} + namespace CSMDoc { class Document : public QObject @@ -57,6 +63,7 @@ namespace CSMDoc boost::filesystem::path mResDir; Blacklist mBlacklist; Runner mRunner; + boost::shared_ptr mPhysics; // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. @@ -129,6 +136,8 @@ namespace CSMDoc QTextDocument *getRunLog(); + boost::shared_ptr getPhysics(); + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6f830e6e3e..eba73cf0b0 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -272,7 +272,7 @@ namespace CSMWorld { ESXRecordT record2 = record.get(); - record2.mData.mUseValue[mIndex] = data.toInt(); + record2.mData.mUseValue[mIndex] = data.toFloat(); record.setModified (record2); } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index d64d36aec7..0d2b6060ef 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -16,7 +16,6 @@ #include "../../model/world/idtable.hpp" #include "../world/subviews.hpp" -#include "../world/physicsmanager.hpp" #include "../tools/subviews.hpp" @@ -407,8 +406,6 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mSubViewFactory.add (CSMWorld::UniversalId::Type_RunLog, new SubViewFactory); connect (mOperations, SIGNAL (abortOperation (int)), this, SLOT (abortOperation (int))); - - CSVWorld::PhysicsManager::instance()->setupPhysics(document); } CSVDoc::View::~View() diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c4fd668843..5f6b6b46a4 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -16,7 +16,6 @@ #include "../world/vartypedelegate.hpp" #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" -#include "../world/physicsmanager.hpp" #include "../../model/settings/usersettings.hpp" @@ -219,7 +218,6 @@ void CSVDoc::ViewManager::removeDocAndView (CSMDoc::Document *document) mDocumentManager.removeDocument(document); (*iter)->deleteLater(); mViews.erase (iter); - CSVWorld::PhysicsManager::instance()->removeDocument(document); updateIndices(); return; diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 75e11cc10a..1fb7809be1 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -60,7 +60,7 @@ bool CSVRender::Cell::addObjects (int start, int end) } CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, - const std::string& id, CSVWorld::PhysicsSystem *physics, const Ogre::Vector3& origin) + const std::string& id, boost::shared_ptr physics, const Ogre::Vector3& origin) : mData (data), mId (Misc::StringUtils::lowerCase (id)), mSceneMgr(sceneManager), mPhysics(physics) { mCellNode = sceneManager->getRootSceneNode()->createChildSceneNode(); diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index d38f0c68d1..9f38b0d9f3 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include @@ -38,7 +40,7 @@ namespace CSVRender Ogre::SceneNode *mCellNode; std::map mObjects; std::auto_ptr mTerrain; - CSVWorld::PhysicsSystem *mPhysics; + boost::shared_ptr mPhysics; Ogre::SceneManager *mSceneMgr; int mX; int mY; @@ -56,7 +58,7 @@ namespace CSVRender public: Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, const std::string& id, - CSVWorld::PhysicsSystem *physics, const Ogre::Vector3& origin = Ogre::Vector3 (0, 0, 0)); + boost::shared_ptr physics, const Ogre::Vector3& origin = Ogre::Vector3 (0, 0, 0)); ~Cell(); diff --git a/apps/opencs/view/render/mousestate.cpp b/apps/opencs/view/render/mousestate.cpp index 45e846f74a..988819fcb1 100644 --- a/apps/opencs/view/render/mousestate.cpp +++ b/apps/opencs/view/render/mousestate.cpp @@ -56,7 +56,7 @@ namespace CSVRender // MouseState::MouseState(WorldspaceWidget *parent) - : mParent(parent), mPhysics(parent->getPhysics()), mSceneManager(parent->getSceneManager()) + : mParent(parent), mPhysics(parent->mDocument.getPhysics()), mSceneManager(parent->getSceneManager()) , mCurrentObj(""), mMouseState(Mouse_Default), mOldPos(0,0), mMouseEventTimer(0), mPlane(0) , mGrabbedSceneNode(""), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3()) , mCurrentMousePos(Ogre::Vector3()), mOffset(0.0f) diff --git a/apps/opencs/view/render/mousestate.hpp b/apps/opencs/view/render/mousestate.hpp index 27907bb331..70e18427f3 100644 --- a/apps/opencs/view/render/mousestate.hpp +++ b/apps/opencs/view/render/mousestate.hpp @@ -2,6 +2,7 @@ #define OPENCS_VIEW_MOUSESTATE_H #include +#include #include #include @@ -43,7 +44,7 @@ namespace CSVRender MouseStates mMouseState; WorldspaceWidget *mParent; - CSVWorld::PhysicsSystem *mPhysics; // local copy + boost::shared_ptr mPhysics; Ogre::SceneManager *mSceneManager; // local copy QPoint mOldPos; diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 21219db8f4..d92b4aaa2d 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -132,7 +132,7 @@ const CSMWorld::CellRef& CSVRender::Object::getReference() const } CSVRender::Object::Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode, - const std::string& id, bool referenceable, CSVWorld::PhysicsSystem *physics, + const std::string& id, bool referenceable, boost::shared_ptr physics, bool forceBaseToZero) : mData (data), mBase (0), mForceBaseToZero (forceBaseToZero), mPhysics(physics) { @@ -156,7 +156,8 @@ CSVRender::Object::~Object() { clear(); - mPhysics->removeObject(mBase->getName()); + if(mPhysics) // preview may not have physics enabled + mPhysics->removeObject(mBase->getName()); if (mBase) mBase->getCreator()->destroySceneNode (mBase); diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index eba2dc8148..05a32fbeab 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -1,6 +1,8 @@ #ifndef OPENCS_VIEW_OBJECT_H #define OPENCS_VIEW_OBJECT_H +#include + #include class QModelIndex; @@ -31,7 +33,7 @@ namespace CSVRender Ogre::SceneNode *mBase; NifOgre::ObjectScenePtr mObject; bool mForceBaseToZero; - CSVWorld::PhysicsSystem *mPhysics; + boost::shared_ptr mPhysics; /// Not implemented Object (const Object&); @@ -58,7 +60,8 @@ namespace CSVRender Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode, const std::string& id, bool referenceable, - CSVWorld::PhysicsSystem *physics = NULL, bool forceBaseToZero = false); + boost::shared_ptr physics = boost::shared_ptr (), + bool forceBaseToZero = false); /// \param forceBaseToZero If this is a reference ignore the coordinates and place /// it at 0, 0, 0 instead. diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 764320a703..cf9edb5483 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -112,7 +112,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() mCells.find (*iter)==mCells.end()) { Cell *cell = new Cell (mDocument.getData(), getSceneManager(), - iter->getId (mWorldspace), getPhysics()); + iter->getId (mWorldspace), mDocument.getPhysics()); mCells.insert (std::make_pair (*iter, cell)); float height = cell->getTerrainHeightAt(Ogre::Vector3( @@ -371,8 +371,11 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget() delete iter->second; } - removeRenderTargetListener(mOverlayMask); - delete mOverlayMask; + if(mOverlayMask) + { + removeRenderTargetListener(mOverlayMask); + delete mOverlayMask; + } } void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) diff --git a/apps/opencs/view/render/previewwidget.cpp b/apps/opencs/view/render/previewwidget.cpp index f972c6361b..da18e7c895 100644 --- a/apps/opencs/view/render/previewwidget.cpp +++ b/apps/opencs/view/render/previewwidget.cpp @@ -10,7 +10,7 @@ CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data, const std::string& id, bool referenceable, QWidget *parent) : SceneWidget (parent), mData (data), - mObject (data, getSceneManager()->getRootSceneNode(), id, referenceable, NULL, true) + mObject (data, getSceneManager()->getRootSceneNode(), id, referenceable, boost::shared_ptr(), true) { setNavigation (&mOrbit); diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 62cbdf1e1f..462b62b7a8 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -49,7 +49,7 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& update(); - mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId, getPhysics())); + mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId, document.getPhysics())); } void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft, @@ -91,7 +91,7 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vectorgetId(); - mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId, getPhysics())); + mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId, getDocument().getPhysics())); update(); emit cellChanged(*data.begin()); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 51dfcd5066..582ccea643 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -16,14 +16,13 @@ #include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetoolrun.hpp" -#include "../world/physicsmanager.hpp" #include "../world/physicssystem.hpp" #include "elements.hpp" #include "editmode.hpp" CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) -: SceneWidget (parent), mDocument(document), mSceneElements(0), mRun(0), mPhysics(0), mMouse(0), +: SceneWidget (parent), mDocument(document), mSceneElements(0), mRun(0), mPhysics(boost::shared_ptr()), mMouse(0), mInteractionMask (0) { setAcceptDrops(true); @@ -56,9 +55,7 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int))); - // associate WorldSpaceWidgets (and their SceneManagers) with Documents - // then create physics if there is a new document - mPhysics = CSVWorld::PhysicsManager::instance()->addSceneWidget(document, this); + mPhysics = document.getPhysics(); // create physics if one doesn't exist mPhysics->addSceneManager(getSceneManager(), this); mMouse = new MouseState(this); } @@ -67,7 +64,6 @@ CSVRender::WorldspaceWidget::~WorldspaceWidget () { delete mMouse; mPhysics->removeSceneManager(getSceneManager()); - CSVWorld::PhysicsManager::instance()->removeSceneWidget(this); } void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) @@ -368,12 +364,6 @@ void CSVRender::WorldspaceWidget::updateOverlay() { } -CSVWorld::PhysicsSystem *CSVRender::WorldspaceWidget::getPhysics() -{ - assert(mPhysics); - return mPhysics; -} - void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) { if(event->buttons() & Qt::RightButton) diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 550b5d4a9a..b19197e36b 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -1,6 +1,8 @@ #ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H #define OPENCS_VIEW_WORLDSPACEWIDGET_H +#include + #include "scenewidget.hpp" #include "mousestate.hpp" @@ -40,7 +42,7 @@ namespace CSVRender CSVWidget::SceneToolToggle2 *mSceneElements; CSVWidget::SceneToolRun *mRun; CSMDoc::Document& mDocument; - CSVWorld::PhysicsSystem *mPhysics; + boost::shared_ptr mPhysics; MouseState *mMouse; unsigned int mInteractionMask; @@ -115,8 +117,6 @@ namespace CSVRender virtual void updateOverlay(); - CSVWorld::PhysicsSystem *getPhysics(); - virtual void mouseMoveEvent (QMouseEvent *event); virtual void mousePressEvent (QMouseEvent *event); virtual void mouseReleaseEvent (QMouseEvent *event); diff --git a/apps/opencs/view/world/physicsmanager.cpp b/apps/opencs/view/world/physicsmanager.cpp deleted file mode 100644 index fa8db9e1e0..0000000000 --- a/apps/opencs/view/world/physicsmanager.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "physicsmanager.hpp" - -#include - -#include - -#include "../render/worldspacewidget.hpp" -#include "physicssystem.hpp" - -namespace CSVWorld -{ - PhysicsManager *PhysicsManager::mPhysicsManagerInstance = 0; - - PhysicsManager::PhysicsManager() - { - assert(!mPhysicsManagerInstance); - mPhysicsManagerInstance = this; - } - - PhysicsManager::~PhysicsManager() - { - std::map::iterator iter = mPhysics.begin(); - for(; iter != mPhysics.end(); ++iter) - delete iter->second; // shouldn't be any left but just in case - } - - PhysicsManager *PhysicsManager::instance() - { - assert(mPhysicsManagerInstance); - return mPhysicsManagerInstance; - } - - // create a physics instance per document, called from CSVDoc::View() to get Document* - void PhysicsManager::setupPhysics(CSMDoc::Document *doc) - { - std::map >::iterator iter = mSceneWidgets.find(doc); - if(iter == mSceneWidgets.end()) - { - mSceneWidgets[doc] = std::list (); // zero elements - mPhysics[doc] = new PhysicsSystem(); - } - } - - // destroy physics, called from CSVDoc::ViewManager - void PhysicsManager::removeDocument(CSMDoc::Document *doc) - { - std::map::iterator iter = mPhysics.find(doc); - if(iter != mPhysics.end()) - { - delete iter->second; - mPhysics.erase(iter); - } - - std::map >::iterator it = mSceneWidgets.find(doc); - if(it != mSceneWidgets.end()) - { - mSceneWidgets.erase(it); - } - - // cleanup global resources used by OEngine - if(mPhysics.empty()) - { - delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); - } - } - - // called from CSVRender::WorldspaceWidget() to get widgets' association with Document& - PhysicsSystem *PhysicsManager::addSceneWidget(CSMDoc::Document &doc, CSVRender::WorldspaceWidget *widget) - { - CSVRender::SceneWidget *sceneWidget = static_cast(widget); - - std::map >::iterator iter = mSceneWidgets.begin(); - for(; iter != mSceneWidgets.end(); ++iter) - { - if((*iter).first == &doc) - { - (*iter).second.push_back(sceneWidget); - return mPhysics[(*iter).first]; // TODO: consider using shared_ptr instead - } - } - - throw std::runtime_error("No physics system found for the given document."); - } - - // deprecated by removeDocument() and may be deleted in future code updates - // however there may be some value in removing the deleted scene widgets from the - // list so that the list does not grow forever - void PhysicsManager::removeSceneWidget(CSVRender::WorldspaceWidget *widget) - { - CSVRender::SceneWidget *sceneWidget = static_cast(widget); - - std::map >::iterator iter = mSceneWidgets.begin(); - for(; iter != mSceneWidgets.end(); ++iter) - { - std::list::iterator itWidget = (*iter).second.begin(); - for(; itWidget != (*iter).second.end(); ++itWidget) - { - if((*itWidget) == sceneWidget) - { - (*iter).second.erase(itWidget); - - //if((*iter).second.empty()) // last one for the document - // NOTE: do not delete physics until the document itself is closed - - break; - } - } - } - } -} diff --git a/apps/opencs/view/world/physicsmanager.hpp b/apps/opencs/view/world/physicsmanager.hpp deleted file mode 100644 index e17c9ac84a..0000000000 --- a/apps/opencs/view/world/physicsmanager.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef CSV_WORLD_PHYSICSMANAGER_H -#define CSV_WORLD_PHYSICSMANAGER_H - -#include -#include - -namespace Ogre -{ - class SceneManager; -} - -namespace CSMDoc -{ - class Document; -} - -namespace CSVRender -{ - class WorldspaceWidget; - class SceneWidget; -} - -namespace CSVWorld -{ - class PhysicsSystem; -} - -namespace CSVWorld -{ - class PhysicsManager - { - static PhysicsManager *mPhysicsManagerInstance; - - std::map > mSceneWidgets; - std::map mPhysics; - - public: - - PhysicsManager(); - ~PhysicsManager(); - - static PhysicsManager *instance(); - - void setupPhysics(CSMDoc::Document *); - - PhysicsSystem *addSceneWidget(CSMDoc::Document &doc, CSVRender::WorldspaceWidget *widget); - - void removeSceneWidget(CSVRender::WorldspaceWidget *widget); - - void removeDocument(CSMDoc::Document *doc); - }; -} - -#endif // CSV_WORLD_PHYSICSMANAGER_H diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index f987c8d9f2..c65e12c609 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -173,6 +173,8 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO { QDoubleSpinBox *dsb = new QDoubleSpinBox(parent); dsb->setRange(FLT_MIN, FLT_MAX); + dsb->setSingleStep(0.01f); + dsb->setDecimals(3); return dsb; }