Merge branch 'cellselect'

This commit is contained in:
Marc Zinnschlag 2014-04-08 09:58:00 +02:00
commit d205d5f0af
17 changed files with 370 additions and 7 deletions

View file

@ -24,7 +24,7 @@ opencs_units (model/world
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world

View file

@ -0,0 +1,60 @@
#include "cellcoordinates.hpp"
#include <ostream>
#include <sstream>
CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {}
CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {}
int CSMWorld::CellCoordinates::getX() const
{
return mX;
}
int CSMWorld::CellCoordinates::getY() const
{
return mY;
}
CSMWorld::CellCoordinates CSMWorld::CellCoordinates::move (int x, int y) const
{
return CellCoordinates (mX + x, mY + y);
}
std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) const
{
// we ignore the worldspace for now, since there is only one (will change in 1.1)
std::ostringstream stream;
stream << "#" << mX << " " << mY;
return stream.str();
}
bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right)
{
return left.getX()==right.getX() && left.getY()==right.getY();
}
bool CSMWorld::operator!= (const CellCoordinates& left, const CellCoordinates& right)
{
return !(left==right);
}
bool CSMWorld::operator< (const CellCoordinates& left, const CellCoordinates& right)
{
if (left.getX()<right.getX())
return true;
if (left.getX()>right.getX())
return false;
return left.getY()<right.getY();
}
std::ostream& CSMWorld::operator<< (std::ostream& stream, const CellCoordinates& coordiantes)
{
return stream << coordiantes.getX() << ", " << coordiantes.getY();
}

View file

@ -0,0 +1,42 @@
#ifndef CSM_WOLRD_CELLCOORDINATES_H
#define CSM_WOLRD_CELLCOORDINATES_H
#include <iosfwd>
#include <string>
#include <QMetaType>
namespace CSMWorld
{
class CellCoordinates
{
int mX;
int mY;
public:
CellCoordinates();
CellCoordinates (int x, int y);
int getX() const;
int getY() const;
CellCoordinates move (int x, int y) const;
///< Return a copy of *this, moved by the given offset.
std::string getId (const std::string& worldspace) const;
///< Return the ID for the cell at these coordinates.
};
bool operator== (const CellCoordinates& left, const CellCoordinates& right);
bool operator!= (const CellCoordinates& left, const CellCoordinates& right);
bool operator< (const CellCoordinates& left, const CellCoordinates& right);
std::ostream& operator<< (std::ostream& stream, const CellCoordinates& coordiantes);
}
Q_DECLARE_METATYPE (CSMWorld::CellCoordinates)
#endif

View file

@ -0,0 +1,83 @@
#include "cellselection.hpp"
#include <cmath>
#include <stdexcept>
#include <limits>
CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::begin() const
{
return mCells.begin();
}
CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::end() const
{
return mCells.end();
}
bool CSMWorld::CellSelection::add (const CellCoordinates& coordinates)
{
return mCells.insert (coordinates).second;
}
void CSMWorld::CellSelection::remove (const CellCoordinates& coordinates)
{
mCells.erase (coordinates);
}
bool CSMWorld::CellSelection::has (const CellCoordinates& coordinates) const
{
return mCells.find (coordinates)!=end();
}
int CSMWorld::CellSelection::getSize() const
{
return mCells.size();
}
CSMWorld::CellCoordinates CSMWorld::CellSelection::getCentre() const
{
if (mCells.empty())
throw std::logic_error ("call of getCentre on empty cell selection");
double x = 0;
double y = 0;
for (Iterator iter = begin(); iter!=end(); ++iter)
{
x += iter->getX();
y += iter->getY();
}
x /= mCells.size();
y /= mCells.size();
Iterator closest = begin();
double distance = std::numeric_limits<double>::max();
for (Iterator iter (begin()); iter!=end(); ++iter)
{
double deltaX = x - iter->getX();
double deltaY = y - iter->getY();
double delta = std::sqrt (deltaX * deltaX + deltaY * deltaY);
if (delta<distance)
{
distance = delta;
closest = iter;
}
}
return *closest;
}
void CSMWorld::CellSelection::move (int x, int y)
{
Container moved;
for (Iterator iter = begin(); iter!=end(); ++iter)
moved.insert (iter->move (x, y));
mCells.swap (moved);
}

View file

@ -0,0 +1,57 @@
#ifndef CSM_WOLRD_CELLSELECTION_H
#define CSM_WOLRD_CELLSELECTION_H
#include <set>
#include <QMetaType>
#include "cellcoordinates.hpp"
namespace CSMWorld
{
/// \brief Selection of cells in a paged worldspace
///
/// \note The CellSelection does not specify the worldspace it applies to.
class CellSelection
{
public:
typedef std::set<CellCoordinates> Container;
typedef Container::const_iterator Iterator;
private:
Container mCells;
public:
Iterator begin() const;
Iterator end() const;
bool add (const CellCoordinates& coordinates);
///< Ignored if the cell specified by \a coordinates is already part of the selection.
///
/// \return Was a cell added to the collection?
void remove (const CellCoordinates& coordinates);
///< ignored if the cell specified by \a coordinates is not part of the selection.
bool has (const CellCoordinates& coordinates) const;
///< \return Is the cell specified by \a coordinates part of the selection?
int getSize() const;
///< Return number of cells.
CellCoordinates getCentre() const;
///< Return the selected cell that is closest to the geometric centre of the selection.
///
/// \attention This function must not be called on selections that are empty.
void move (int x, int y);
};
}
Q_DECLARE_METATYPE (CSMWorld::CellSelection)
#endif

View file

@ -1,6 +1,47 @@
#include "pagedworldspacewidget.hpp" #include "pagedworldspacewidget.hpp"
#include <sstream>
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent)
: WorldspaceWidget (parent) : WorldspaceWidget (parent)
{} {}
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
{
if (!hint.empty())
{
CSMWorld::CellSelection selection;
if (hint[0]=='c')
{
// syntax: c:#x1 y1; #x2 y2 (number of coordinate pairs can be 0 or larger)
char ignore;
std::istringstream stream (hint.c_str());
if (stream >> ignore)
{
char ignore1; // : or ;
char ignore2; // #
int x, y;
while (stream >> ignore1 >> ignore2 >> x >> y)
selection.add (CSMWorld::CellCoordinates (x, y));
/// \todo adjust camera position
}
}
else if (hint[0]=='r')
{
/// \todo implement 'r' type hints
}
setCellSelection (selection);
}
}
void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSelection& selection)
{
mSelection = selection;
emit cellSelectionChanged (mSelection);
}

View file

@ -1,6 +1,8 @@
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#include "../../model/world/cellselection.hpp"
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
namespace CSVRender namespace CSVRender
@ -9,9 +11,22 @@ namespace CSVRender
{ {
Q_OBJECT Q_OBJECT
CSMWorld::CellSelection mSelection;
public: public:
PagedWorldspaceWidget (QWidget *parent); PagedWorldspaceWidget (QWidget *parent);
///< \note Sets the cell area selection to an invalid value to indicate that currently
/// no cells are displayed. The cells to be displayed will be specified later through
/// hint system.
virtual void useViewHint (const std::string& hint);
void setCellSelection (const CSMWorld::CellSelection& selection);
signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
}; };
} }

View file

@ -26,6 +26,8 @@ void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
setNavigation (&mOrbit); setNavigation (&mOrbit);
} }
void CSVRender::WorldspaceWidget::useViewHint (const std::string& hint) {}
void CSVRender::WorldspaceWidget::selectDefaultNavigationMode() void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
{ {
setNavigation (&m1st); setNavigation (&m1st);

View file

@ -33,6 +33,9 @@ namespace CSVRender
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();
virtual void useViewHint (const std::string& hint);
///< Default-implementation: ignored.
private slots: private slots:
void selectNavigationMode (const std::string& mode); void selectNavigationMode (const std::string& mode);

View file

@ -28,7 +28,7 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
else else
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this); mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this);
SceneToolbar *toolbar = new SceneToolbar (48, this); SceneToolbar *toolbar = new SceneToolbar (48+6, this);
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar); SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
toolbar->addTool (lightingTool); toolbar->addTool (lightingTool);

View file

@ -1,12 +1,16 @@
#include "scenesubview.hpp" #include "scenesubview.hpp"
#include <sstream>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/cellselection.hpp"
#include "../filter/filterbox.hpp" #include "../filter/filterbox.hpp"
#include "../render/pagedworldspacewidget.hpp" #include "../render/pagedworldspacewidget.hpp"
@ -32,10 +36,15 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
layout2->setContentsMargins (QMargins (0, 0, 0, 0)); layout2->setContentsMargins (QMargins (0, 0, 0, 0));
SceneToolbar *toolbar = new SceneToolbar (48, this); SceneToolbar *toolbar = new SceneToolbar (48+6, this);
if (id.getId()=="sys::default") if (id.getId()=="sys::default")
mScene = new CSVRender::PagedWorldspaceWidget (this); {
CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this);
mScene = widget;
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)),
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
}
else else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
@ -83,7 +92,38 @@ void CSVWorld::SceneSubView::setStatusBar (bool show)
mBottom->setStatusBar (show); mBottom->setStatusBar (show);
} }
void CSVWorld::SceneSubView::useHint (const std::string& hint)
{
mScene->useViewHint (hint);
}
void CSVWorld::SceneSubView::closeRequest() void CSVWorld::SceneSubView::closeRequest()
{ {
deleteLater(); deleteLater();
}
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection)
{
int size = selection.getSize();
std::ostringstream stream;
stream << "Scene: " << getUniversalId().getId();
if (size==0)
stream << " (empty)";
else if (size==1)
{
stream << " (" << *selection.begin() << ")";
}
else
{
stream << " (" << selection.getCentre() << " and " << size-1 << " more ";
if (size>1)
stream << "cells around it)";
else
stream << "cell around it)";
}
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
} }

View file

@ -5,6 +5,11 @@
class QModelIndex; class QModelIndex;
namespace CSMWorld
{
class CellSelection;
}
namespace CSMDoc namespace CSMDoc
{ {
class Document; class Document;
@ -38,9 +43,13 @@ namespace CSVWorld
virtual void setStatusBar (bool show); virtual void setStatusBar (bool show);
virtual void useHint (const std::string& hint);
private slots: private slots:
void closeRequest(); void closeRequest();
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
}; };
} }

View file

@ -6,6 +6,7 @@
CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent) CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent)
{ {
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
setIconSize (QSize (parent->getIconSize(), parent->getIconSize()));
setFixedSize (parent->getButtonSize(), parent->getButtonSize()); setFixedSize (parent->getButtonSize(), parent->getButtonSize());
connect (this, SIGNAL (clicked()), this, SLOT (openRequest())); connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));

View file

@ -6,7 +6,7 @@
#include "scenetool.hpp" #include "scenetool.hpp"
CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent) CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
: QWidget (parent), mButtonSize (buttonSize) : QWidget (parent), mButtonSize (buttonSize), mIconSize (buttonSize-6)
{ {
setFixedWidth (mButtonSize); setFixedWidth (mButtonSize);
@ -26,4 +26,9 @@ void CSVWorld::SceneToolbar::addTool (SceneTool *tool)
int CSVWorld::SceneToolbar::getButtonSize() const int CSVWorld::SceneToolbar::getButtonSize() const
{ {
return mButtonSize; return mButtonSize;
}
int CSVWorld::SceneToolbar::getIconSize() const
{
return mIconSize;
} }

View file

@ -15,6 +15,7 @@ namespace CSVWorld
QVBoxLayout *mLayout; QVBoxLayout *mLayout;
int mButtonSize; int mButtonSize;
int mIconSize;
public: public:
@ -23,6 +24,8 @@ namespace CSVWorld
void addTool (SceneTool *tool); void addTool (SceneTool *tool);
int getButtonSize() const; int getButtonSize() const;
int getIconSize() const;
}; };
} }

View file

@ -8,7 +8,7 @@
#include "scenetoolbar.hpp" #include "scenetoolbar.hpp"
CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent) CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent)
: SceneTool (parent), mButtonSize (parent->getButtonSize()) : SceneTool (parent), mButtonSize (parent->getButtonSize()), mIconSize (parent->getIconSize())
{ {
mPanel = new QFrame (this, Qt::Popup); mPanel = new QFrame (this, Qt::Popup);
@ -29,6 +29,7 @@ void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::str
{ {
QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel); QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel);
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
button->setIconSize (QSize (mIconSize, mIconSize));
button->setFixedSize (mButtonSize, mButtonSize); button->setFixedSize (mButtonSize, mButtonSize);
mLayout->addWidget (button); mLayout->addWidget (button);

View file

@ -20,6 +20,7 @@ namespace CSVWorld
QHBoxLayout *mLayout; QHBoxLayout *mLayout;
std::map<QPushButton *, std::string> mButtons; // widget, id std::map<QPushButton *, std::string> mButtons; // widget, id
int mButtonSize; int mButtonSize;
int mIconSize;
public: public: