Merge branch 'cellselect'
commit
d205d5f0af
@ -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();
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -1,6 +1,47 @@
|
||||
|
||||
#include "pagedworldspacewidget.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *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);
|
||||
}
|
Loading…
Reference in New Issue