Changed: #1302 Added additional visual elements (Point, Path, Zone) in 2d render without undo/redo operations(move, rotate, scale).

--HG--
branch : gsoc2011-worldeditorqt
This commit is contained in:
dnk-88 2011-08-09 23:56:26 +03:00
parent b93f59ae10
commit d19feac70c
19 changed files with 1688 additions and 46 deletions

View file

@ -12,11 +12,14 @@ SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.
SET(OVQT_PLUGIN_WORLD_EDITOR_HDR world_editor_plugin.h
world_editor_window.h
world_editor_scene.h
world_editor_scene_item.h
primitives_model.h
primitives_view.h
project_settings_dialog.h
)
SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui
project_settings_dialog.ui
)
SET(OVQT_PLUGIN_WORLD_EDITOR_RCS world_editor.qrc)

View file

@ -68,6 +68,8 @@ public:
/// @Path is a list of [row,column] pairs showing us the way through the model.
Path pathFromIndex(const QModelIndex &index);
//Path pathFromNode(Node *index);
QModelIndex pathToIndex(const Path &path);
void createWorldEditNode(const QString &fileName);

View file

@ -40,6 +40,7 @@ namespace WorldEditor
PrimitivesView::PrimitivesView(QWidget *parent)
: QTreeView(parent),
m_undoStack(0),
m_worldEditorScene(0),
m_zoneBuilder(0),
m_primitivesTreeModel(0)
{
@ -103,6 +104,11 @@ void PrimitivesView::setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilde
m_zoneBuilder = zoneBuilder;
}
void PrimitivesView::setWorldScene(WorldEditorScene *worldEditorScene)
{
m_worldEditorScene = worldEditorScene;
}
void PrimitivesView::setModel(PrimitivesTreeModel *model)
{
QTreeView::setModel(model);
@ -127,7 +133,7 @@ void PrimitivesView::loadRootPrimitive()
Q_FOREACH(QString fileName, fileNames)
{
m_lastDir = QFileInfo(fileName).absolutePath();
m_undoStack->push(new LoadRootPrimitiveCommand(fileName, m_primitivesTreeModel));
m_undoStack->push(new LoadRootPrimitiveCommand(fileName, m_worldEditorScene, m_primitivesTreeModel));
}
if (fileNames.count() > 1)

View file

@ -27,7 +27,6 @@
#include <QtCore/QModelIndex>
#include <QtCore/QVariant>
#include <QtCore/QSignalMapper>
#include <QPersistentModelIndex>
#include <QtGui/QUndoStack>
namespace LandscapeEditor
@ -38,6 +37,7 @@ class ZoneBuilderBase;
namespace WorldEditor
{
class PrimitivesTreeModel;
class WorldEditorScene;
/**
@class PrimitivesView
@ -54,6 +54,7 @@ public:
void setUndoStack(QUndoStack *undoStack);
void setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder);
void setWorldScene(WorldEditorScene *worldEditorScene);
virtual void setModel(PrimitivesTreeModel *model);
private Q_SLOTS:
@ -92,6 +93,7 @@ private:
QAction *m_hideAction;
QUndoStack *m_undoStack;
WorldEditorScene *m_worldEditorScene;
LandscapeEditor::ZoneBuilderBase *m_zoneBuilder;
PrimitivesTreeModel *m_primitivesTreeModel;
};

View file

@ -0,0 +1,59 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Project includes
#include "project_settings_dialog.h"
#include "../core/icore.h"
#include "../core/core_constants.h"
// NeL includes
#include <nel/misc/debug.h>
// Qt includes
#include <QtCore/QSettings>
#include <QtGui/QFileDialog>
#include <QtGui/QFileDialog>
namespace WorldEditor
{
ProjectSettingsDialog::ProjectSettingsDialog(const QString &dataPath, QWidget *parent)
: QDialog(parent)
{
m_ui.setupUi(this);
m_ui.pathLineEdit->setText(dataPath);
setFixedHeight(sizeHint().height());
connect(m_ui.selectPathButton, SIGNAL(clicked()), this, SLOT(selectPath()));
}
ProjectSettingsDialog::~ProjectSettingsDialog()
{
}
QString ProjectSettingsDialog::dataPath() const
{
return m_ui.pathLineEdit->text();
}
void ProjectSettingsDialog::selectPath()
{
QString dataPath = QFileDialog::getExistingDirectory(this, tr("Select data path"), m_ui.pathLineEdit->text());
if (!dataPath.isEmpty())
m_ui.pathLineEdit->setText(dataPath);
}
} /* namespace WorldEditor */

View file

@ -0,0 +1,48 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef PROJECT_SETTINGS_DIALOG_WE_H
#define PROJECT_SETTINGS_DIALOG_WE_H
// Project includes
#include "ui_project_settings_dialog.h"
// Qt includes
namespace WorldEditor
{
class ProjectSettingsDialog: public QDialog
{
Q_OBJECT
public:
ProjectSettingsDialog(const QString &dataPath, QWidget *parent = 0);
~ProjectSettingsDialog();
QString dataPath() const;
private Q_SLOTS:
void selectPath();
private:
Ui::ProjectSettingsDialog m_ui;
}; /* class ProjectSettingsDialog */
} /* namespace WorldEditor */
#endif // PROJECT_SETTINGS_DIALOG_WE_H

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectSettingsDialog</class>
<widget class="QDialog" name="ProjectSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>419</width>
<height>93</height>
</rect>
</property>
<property name="windowTitle">
<string>Project settings</string>
</property>
<property name="windowIcon">
<iconset resource="../landscape_editor/landscape_editor.qrc">
<normaloff>:/icons/ic_nel_landscape_settings.png</normaloff>:/icons/ic_nel_landscape_settings.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Data directory:</string>
</property>
<property name="buddy">
<cstring>pathLineEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="pathLineEdit"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="selectPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Context:</string>
</property>
<property name="buddy">
<cstring>contextComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="contextComboBox"/>
</item>
<item row="2" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../landscape_editor/landscape_editor.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ProjectSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ProjectSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -18,6 +18,8 @@
#include "world_editor_actions.h"
#include "world_editor_misc.h"
#include "primitive_item.h"
#include "world_editor_scene.h"
#include "world_editor_scene_item.h"
// Lanscape Editor plugin
#include "../landscape_editor/builder_zone_base.h"
@ -30,6 +32,7 @@
#include <nel/misc/path.h>
#include <nel/ligo/primitive_utils.h>
#include <nel/ligo/primitive.h>
#include <nel/ligo/primitive_class.h>
#include <nel/misc/file.h>
// Qt includes
@ -38,6 +41,92 @@
namespace WorldEditor
{
void addNewGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene)
{
PrimitiveNode *node = static_cast<PrimitiveNode *>(primIndex.internalPointer());
float cellSize = Utils::ligoConfig()->CellSize;
if (node != 0)
{
NLLIGO::IPrimitive *primitive = node->primitive();
NLLIGO::CPrimVector *vec = 0;
QGraphicsItem *item;
switch (node->primitiveClass()->Type)
{
case NLLIGO::CPrimitiveClass::Point:
{
vec = primitive->getPrimVector();
item = scene->addWorldItemPoint(QPointF(vec->x, -vec->y + cellSize), 0);
break;
}
case NLLIGO::CPrimitiveClass::Path:
{
QPolygonF polygon;
vec = primitive->getPrimVector();
int sizeVec = primitive->getNumVector();
for (int i = 0; i < sizeVec; ++i)
{
polygon << QPointF(vec->x, -vec->y + cellSize);
++vec;
}
item = scene->addWorldItemPath(polygon);
break;
}
case NLLIGO::CPrimitiveClass::Zone:
{
QPolygonF polygon;
vec = primitive->getPrimVector();
int sizeVec = primitive->getNumVector();
for (int i = 0; i < sizeVec; ++i)
{
polygon << QPointF(vec->x, -vec->y + cellSize);
++vec;
}
item = scene->addWorldItemZone(polygon);
break;
}
}
node->setGraphicsData(GRAPHICS_DATA_QT2D, item);
}
int count = model->rowCount(primIndex);
for (int i = 0; i < count; ++i)
{
addNewGraphicsItems(primIndex.child(i, 0), model, scene);
}
}
void removeGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene)
{
PrimitiveNode *node = static_cast<PrimitiveNode *>(primIndex.internalPointer());
if (node != 0)
{
switch (node->primitiveClass()->Type)
{
case NLLIGO::CPrimitiveClass::Point:
case NLLIGO::CPrimitiveClass::Path:
case NLLIGO::CPrimitiveClass::Zone:
{
QGraphicsItem *item = static_cast<QGraphicsItem *>(node->graphicsData(GRAPHICS_DATA_QT2D));
if (item != 0)
delete item;
break;
}
}
}
int count = model->rowCount(primIndex);
for (int i = 0; i < count; ++i)
{
removeGraphicsItems(primIndex.child(i, 0), model, scene);
}
}
CreateWorldCommand::CreateWorldCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent),
m_fileName(fileName),
@ -121,9 +210,11 @@ void CreateRootPrimitiveCommand::redo()
}
LoadRootPrimitiveCommand::LoadRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent)
LoadRootPrimitiveCommand::LoadRootPrimitiveCommand(const QString &fileName, WorldEditorScene *scene,
PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent),
m_fileName(fileName),
m_scene(scene),
m_model(model)
{
setText("Load primitive file");
@ -137,6 +228,8 @@ void LoadRootPrimitiveCommand::undo()
{
QModelIndex index = m_model->pathToIndex(m_rootPrimIndex);
removeGraphicsItems(index, m_model, m_scene);
RootPrimitiveNode *node = static_cast<RootPrimitiveNode *>(index.internalPointer());
delete node->primitives();
@ -167,6 +260,8 @@ void LoadRootPrimitiveCommand::redo()
}
m_rootPrimIndex = m_model->createRootPrimitiveNode(m_fileName, primitives);
addNewGraphicsItems(m_model->pathToIndex(m_rootPrimIndex), m_model, m_scene);
}
AddPrimitiveByClassCommand::AddPrimitiveByClassCommand(const QString &className, const Path &parentIndex,

View file

@ -34,6 +34,10 @@ class ZoneBuilderBase;
namespace WorldEditor
{
class WorldEditorScene;
void addNewGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene);
void removeGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene);
/**
@class CreateWorldCommand
@ -100,7 +104,8 @@ private:
class LoadRootPrimitiveCommand: public QUndoCommand
{
public:
LoadRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent = 0);
LoadRootPrimitiveCommand(const QString &fileName, WorldEditorScene *scene,
PrimitivesTreeModel *model, QUndoCommand *parent = 0);
virtual ~LoadRootPrimitiveCommand();
virtual void undo();
@ -109,6 +114,7 @@ private:
Path m_rootPrimIndex;
const QString m_fileName;
WorldEditorScene *const m_scene;
PrimitivesTreeModel *const m_model;
};

View file

@ -30,6 +30,7 @@ const char *const WORLD_WINDOW_STATE = "WorldWindowState";
const char *const WORLD_WINDOW_GEOMETRY = "WorldWindowGeometry";
const char *const WORLD_EDITOR_CELL_SIZE = "WorldEditorCellSize";
const char *const WORLD_EDITOR_SNAP = "WorldEditorSnap";
const char *const WORLD_EDITOR_USE_OPENGL = "WorldEditorUseOpenGL";
const char *const ZONE_SNAPSHOT_RES = "WorldEditorZoneSnapshotRes";
const char *const PRIMITIVE_CLASS_FILENAME = "WorldEditorPrimitiveClassFilename";

View file

@ -688,5 +688,10 @@ bool recursiveUpdateDefaultValues(NLLIGO::IPrimitive *primitive)
return modified;
}
NLLIGO::CLigoConfig *ligoConfig()
{
return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig;
}
} /* namespace Utils */
} /* namespace WorldEditor */

View file

@ -74,6 +74,8 @@ bool updateDefaultValues(NLLIGO::IPrimitive *primitive);
bool recursiveUpdateDefaultValues(NLLIGO::IPrimitive *primitive);
NLLIGO::CLigoConfig *ligoConfig();
} /* namespace Utils */
} /* namespace WorldEditor */

View file

@ -30,42 +30,304 @@ namespace WorldEditor
{
WorldEditorScene::WorldEditorScene(int sizeCell, QObject *parent)
: LandscapeEditor::LandscapeSceneBase(sizeCell, parent)
: LandscapeEditor::LandscapeSceneBase(sizeCell, parent),
m_editedSelectedItems(false),
m_lastPickedPrimitive(0),
m_mode(SelectMode),
m_editMode(false)
{
setItemIndexMethod(NoIndex);
m_pen.setColor(QColor(50, 255, 155));
m_pen.setWidth(0);
m_brush.setColor(QColor(50, 255, 155, 80));
m_brush.setStyle(Qt::SolidPattern);
}
WorldEditorScene::~WorldEditorScene()
{
}
/*
void LandscapeSceneBase::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
QGraphicsItem *WorldEditorScene::addWorldItemPoint(const QPointF &point, const float angle)
{
QGraphicsScene::mousePressEvent(mouseEvent);
WorldItemPoint *item = new WorldItemPoint(point, angle);
addItem(item);
return item;
}
QGraphicsItem *WorldEditorScene::addWorldItemPath(const QPolygonF &polyline)
{
WorldItemPath *item = new WorldItemPath(polyline);
addItem(item);
return item;
}
QGraphicsItem *WorldEditorScene::addWorldItemZone(const QPolygonF &polygon)
{
WorldItemZone *item = new WorldItemZone(polygon);
addItem(item);
return item;
}
void WorldEditorScene::setModeEdit(WorldEditorScene::ModeEdit mode)
{
if (mode == WorldEditorScene::SelectMode)
m_editedSelectedItems = false;
m_selectionArea = QRectF();
m_mode = mode;
}
WorldEditorScene::ModeEdit WorldEditorScene::editMode() const
{
return m_mode;
}
bool WorldEditorScene::isEnabledEditPoint() const
{
return m_editMode;
}
void WorldEditorScene::setEnabledEditPoint(bool enabled)
{
m_editMode = enabled;
}
void WorldEditorScene::drawForeground(QPainter *painter, const QRectF &rect)
{
QGraphicsScene::drawForeground(painter, rect);
if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0))
{
painter->setPen(m_pen);
painter->setBrush(m_brush);
painter->drawRect(m_selectionArea);
}
}
void WorldEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent);
qreal x = mouseEvent->scenePos().x();
qreal y = mouseEvent->scenePos().y();
m_posX = sint32(floor(x / m_cellSize));
m_posY = sint32(-floor(y / m_cellSize));
m_mouseButton = mouseEvent->button();
if (mouseEvent->button() != Qt::LeftButton)
return;
// if ((!m_editedSelectedItems) && (m_mode != WorldEditorScene::SelectMode))
if ((!m_editedSelectedItems && m_selectedItems.isEmpty()) ||
(!calcBoundingShape(m_selectedItems).contains(mouseEvent->scenePos())))
{
updatePickSelection(mouseEvent->scenePos());
m_firstSelection = true;
}
m_editedSelectedItems = false;
switch (m_mode)
{
case WorldEditorScene::SelectMode:
{
m_selectionArea.setTopLeft(mouseEvent->scenePos());
break;
}
case WorldEditorScene::MoveMode:
{
break;
}
case WorldEditorScene::RotateMode:
break;
case WorldEditorScene::ScaleMode:
break;
case WorldEditorScene::TurnMode:
break;
case WorldEditorScene::RadiusMode:
break;
};
// if (m_selectedItems.isEmpty())
// m_selectionArea.setTopLeft(mouseEvent->scenePos());
}
void LandscapeSceneBase::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
void WorldEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
m_mouseX = mouseEvent->scenePos().x();
if (QApplication::mouseButtons() == Qt::LeftButton)
{
QPointF offset(mouseEvent->scenePos() - mouseEvent->lastScenePos());
m_selectionArea.setBottomRight(mouseEvent->scenePos());
switch (m_mode)
{
case WorldEditorScene::SelectMode:
break;
case WorldEditorScene::MoveMode:
{
Q_FOREACH(QGraphicsItem *item, m_selectedItems)
{
qgraphicsitem_cast<AbstractWorldItem *>(item)->moveOn(offset);
}
break;
}
case WorldEditorScene::RotateMode:
{
QRectF pivot = calcBoundingRect(m_selectedItems);
// Caluculate angle between two line
QLineF firstLine(pivot.center(), mouseEvent->lastScenePos());
QLineF secondLine(pivot.center(), mouseEvent->scenePos());
qreal angle = secondLine.angleTo(firstLine);
Q_FOREACH(QGraphicsItem *item, m_selectedItems)
{
qgraphicsitem_cast<AbstractWorldItem *>(item)->rotateOn(pivot.center(), angle);
}
break;
}
case WorldEditorScene::ScaleMode:
{
// float scale = (_SelectionMin.x - _SelectionMax.x + _SelectionMax.y - _SelectionMin.y) * SCALE_PER_PIXEL + 1.f;
// moveAction->setScale (std::max (0.001f, scale), _MainFrame->getTransformMode ()==CMainFrame::Scale, radius);
// TODO: perfomance
QRectF pivot = calcBoundingRect(m_selectedItems);
Q_FOREACH(QGraphicsItem *item, m_selectedItems)
{
qgraphicsitem_cast<AbstractWorldItem *>(item)->scaleOn(pivot.center(), offset);
}
break;
}
case WorldEditorScene::TurnMode:
break;
case WorldEditorScene::RadiusMode:
break;
};
if ((editMode() != WorldEditorScene::SelectMode) && (!m_selectedItems.isEmpty()))
m_editedSelectedItems = true;
else
m_editedSelectedItems = false;
update();
}
/*m_mouseX = mouseEvent->scenePos().x();
m_mouseY = mouseEvent->scenePos().y() - m_cellSize;
m_posX = sint32(floor(m_mouseX / m_cellSize));
m_posY = sint32(-floor(m_mouseY / m_cellSize));
*/
QGraphicsScene::mouseMoveEvent(mouseEvent);
}
void LandscapeSceneBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
void WorldEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0))
{
QList<QGraphicsItem *> listItems;
// Clear selection
updateSelectedItems(false);
m_selectedItems.clear();
if (m_selectionArea.left() < m_selectionArea.right())
{
listItems = items(m_selectionArea, Qt::IntersectsItemShape,
Qt::AscendingOrder);
}
else
{
listItems = items(m_selectionArea, Qt::ContainsItemShape,
Qt::AscendingOrder);
}
Q_FOREACH(QGraphicsItem *item, listItems)
{
if (qgraphicsitem_cast<AbstractWorldItem *>(item) == 0)
continue;
m_selectedItems.push_back(item);
}
updateSelectedItems(true);
m_selectionArea = QRectF();
update();
}
else
{
if ((!m_editedSelectedItems) && (!m_firstSelection))
updatePickSelection(mouseEvent->scenePos());
else
m_firstSelection = false;
}
// Huck for standart selection model
// clearSelection();
// updateSelectedItems(true);
QGraphicsScene::mouseReleaseEvent(mouseEvent);
m_mouseButton = Qt::NoButton;
}
*/
QRectF WorldEditorScene::calcBoundingRect(const QList<QGraphicsItem *> &listItems)
{
QRectF rect;
Q_FOREACH(QGraphicsItem *item, listItems)
{
QRectF itemRect = item->boundingRect();
rect = rect.united(itemRect.translated(item->pos()));
}
return rect;
}
QPainterPath WorldEditorScene::calcBoundingShape(const QList<QGraphicsItem *> &listItems)
{
QPainterPath painterPath;
Q_FOREACH(QGraphicsItem *item, listItems)
{
QPainterPath itemPath = item->shape();
painterPath = painterPath.united(itemPath.translated(item->pos()));
}
return painterPath;
}
void WorldEditorScene::updateSelectedItems(bool value)
{
Q_FOREACH(QGraphicsItem *item, m_selectedItems)
{
if (value)
{
item->setFlag(QGraphicsItem::ItemIsSelectable);
//item->setZValue(SELECTED_LAYER);
}
else
{
item->setFlag(QGraphicsItem::ItemIsSelectable, false);
//item->setZValue(UNSELECTED_LAYER);
}
item->setSelected(value);
}
}
void WorldEditorScene::updatePickSelection(const QPointF &point)
{
//clearSelection();
updateSelectedItems(false);
m_selectedItems.clear();
QList<QGraphicsItem *> listItems = items(point, Qt::ContainsItemShape,
Qt::AscendingOrder);
if (!listItems.isEmpty())
{
// Next primitives
m_lastPickedPrimitive++;
m_lastPickedPrimitive %= listItems.size();
QGraphicsItem *selectedItem = listItems.at(m_lastPickedPrimitive);
if (qgraphicsitem_cast<AbstractWorldItem *>(selectedItem) != 0)
m_selectedItems.push_back(selectedItem);
updateSelectedItems(true);
}
}
} /* namespace WorldEditor */

View file

@ -19,6 +19,7 @@
// Project includes
#include "world_editor_global.h"
#include "world_editor_scene_item.h"
#include "../landscape_editor/landscape_scene_base.h"
@ -39,17 +40,56 @@ class WORLD_EDITOR_EXPORT WorldEditorScene : public LandscapeEditor::LandscapeSc
Q_OBJECT
public:
enum ModeEdit
{
SelectMode = 0,
MoveMode,
RotateMode,
ScaleMode,
TurnMode,
RadiusMode
};
WorldEditorScene(int sizeCell = 160, QObject *parent = 0);
virtual ~WorldEditorScene();
QGraphicsItem *addWorldItemPoint(const QPointF &point, const float angle);
QGraphicsItem *addWorldItemPath(const QPolygonF &polyline);
QGraphicsItem *addWorldItemZone(const QPolygonF &polygon);
void setModeEdit(WorldEditorScene::ModeEdit mode);
WorldEditorScene::ModeEdit editMode() const;
bool isEnabledEditPoint() const;
public Q_SLOTS:
void setEnabledEditPoint(bool enabled);
protected:
// virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
// virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
// virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
virtual void drawForeground(QPainter *painter, const QRectF &rect);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
QRectF calcBoundingRect(const QList<QGraphicsItem *> &listItems);
QPainterPath calcBoundingShape(const QList<QGraphicsItem *> &listItems);
void updateSelectedItems(bool value);
void updatePickSelection(const QPointF &point);
QPen m_pen;
QBrush m_brush;
QRectF m_selectionArea;
qreal m_firstPickX, m_firstPickY;
QList<QGraphicsItem *> m_selectedItems;
bool m_editedSelectedItems, m_firstSelection;
uint m_lastPickedPrimitive;
ModeEdit m_mode;
bool m_editMode;
};
} /* namespace WorldEditor */

View file

@ -0,0 +1,649 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Project includes
#include "world_editor_scene_item.h"
// NeL includes
#include <nel/misc/debug.h>
// Qt includes
#include <QtGui/QPainter>
#include <QtCore/QRectF>
#include <QPolygonF>
#include <QTransform>
#include <QStyleOptionGraphicsItem>
#include <QPropertyAnimation>
namespace WorldEditor
{
static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
{
// We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
// if we pass a value of 0.0 to QPainterPathStroker::setWidth()
const qreal penWidthZero = qreal(0.00000001);
if (path == QPainterPath())
return path;
QPainterPathStroker ps;
ps.setCapStyle(pen.capStyle());
if (pen.widthF() <= 0.0)
ps.setWidth(penWidthZero);
else
ps.setWidth(pen.widthF());
ps.setJoinStyle(pen.joinStyle());
ps.setMiterLimit(pen.miterLimit());
QPainterPath p = ps.createStroke(path);
p.addPath(path);
return p;
}
/*
GraphicsItemNode::GraphicsItemNode(GraphicsItemZone *itemZone, QGraphicsItem *parent)
: QGraphicsObject(parent)
{
m_itemZone = itemZone;
m_color = QColor(12, 150, 215);
//setFlag(ItemIgnoresTransformations, true);
//setFlag(ItemClipsToShape);
QPropertyAnimation *animation = new QPropertyAnimation(this, "colorNode");
animation->setDuration(3000);
animation->setStartValue(QColor(10, 0, 50));
animation->setKeyValueAt(0.5, QColor(155, 255, 0));
animation->setEndValue(QColor(10, 0, 50));
animation->setLoopCount(2000);
animation->setEasingCurve(QEasingCurve::OutInExpo);
animation->start();
setFlag(ItemIsSelectable);
setFlag(ItemIsMovable);
setFlag(ItemSendsScenePositionChanges);
m_type = EdgeType;
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
setZValue(10000000);
}
GraphicsItemNode::~GraphicsItemNode()
{
}
void GraphicsItemNode::setColorNode(const QColor &color)
{
m_color = color;
update();
}
void GraphicsItemNode::setNodeType(NodeType nodeType)
{
m_type = nodeType;
if (m_type == EdgeType)
{
setFlag(ItemIsSelectable);
setFlag(ItemIsMovable);
setFlag(ItemSendsScenePositionChanges);
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
setZValue(10000);
}
else if (m_type == MiddleType)
{
setFlag(ItemIsSelectable, false);
setFlag(ItemIsMovable, false);
setFlag(ItemSendsScenePositionChanges, false);
setAcceptedMouseButtons(Qt::LeftButton);
setZValue(10001);
}
update();
}
QRectF GraphicsItemNode::boundingRect() const
{
return QRectF(QPointF(0, 0), QSizeF(20, 20));
}
void GraphicsItemNode::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *)
{
// Here comes the magic:
//painter->setClipRect(option->exposedRect);
painter->setPen(Qt::NoPen);
if (m_type == EdgeType)
{
painter->setBrush(QColor(255, 0, 0));
}
else if (m_type == MiddleType)
{
painter->setBrush(QColor(0, 0, 255));
}
if (option->state & QStyle::State_Selected)
{
painter->setBrush(QColor(0, 255, 0));
}
painter->drawRect(2, 2, 18, 18);
}
QVariant GraphicsItemNode::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == ItemPositionHasChanged)
{
m_itemZone->updateZone();
}
return QGraphicsItem::itemChange(change, value);
}
void GraphicsItemNode::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if ((m_type == MiddleType) && (event->button() == Qt::LeftButton))
{
m_itemZone->updateMiddleNode(this);
setNodeType(EdgeType);
}
else if ((m_type == EdgeType) && (event->button() == Qt::RightButton))
{
if (m_itemZone->deleteEdgePoint(this))
setNodeType(MiddleType);
}
}
GraphicsItemZone::GraphicsItemZone(QGraphicsScene *scene, QGraphicsItem *parent)
: QGraphicsPolygonItem(parent)
{
m_scene = scene;
m_color = QColor(12, 150, 215);
setBrush(QBrush(QColor(100, 100, 255, 128)));
updateZone();
setZValue(100);
//setFlag(ItemClipsToShape);
//setFlag(ItemIsSelectable, true);
//setFlag(ItemIsMovable, true);
//setFlag(ItemHasNoContents, true);
}
GraphicsItemZone::~GraphicsItemZone()
{
}
void GraphicsItemZone::updateMiddleNode(GraphicsItemNode *node)
{
for (int i = 0; i < m_listLines.size(); ++i)
{
if (node == m_listLines.at(i).itemPoint)
{
LineItem oldLineItem = m_listLines[i];
GraphicsItemNode *newNode1 = new GraphicsItemNode(this);
newNode1->setPos((oldLineItem.lineNode.first->pos() + node->pos()) / 2);
newNode1->setNodeType(GraphicsItemNode::MiddleType);
m_scene->addItem(newNode1);
GraphicsItemNode *newNode2 = new GraphicsItemNode(this);
newNode2->setPos((oldLineItem.lineNode.second->pos() + node->pos()) / 2);
newNode2->setNodeType(GraphicsItemNode::MiddleType);
m_scene->addItem(newNode2);
LineItem newLineItem1;
newLineItem1.itemPoint = newNode1;
newLineItem1.lineNode = LineNode(oldLineItem.lineNode.first, node);
m_listLines.push_back(newLineItem1);
LineItem newLineItem2;
newLineItem2.itemPoint = newNode2;
newLineItem2.lineNode = LineNode(node, oldLineItem.lineNode.second);
m_listLines.push_back(newLineItem2);
m_listLines.removeAt(i);
int pos = m_listItems.indexOf(oldLineItem.lineNode.second);
m_listItems.insert(pos, node);
break;
}
}
}
bool GraphicsItemZone::deleteEdgePoint(GraphicsItemNode *node)
{
if (m_listItems.size() < 4)
return false;
int pos = m_listItems.indexOf(node);
m_listItems.takeAt(pos);
LineItem newLineItem;
newLineItem.itemPoint = node;
for (int i = 0; i < m_listLines.size(); ++i)
{
if (node == m_listLines.at(i).lineNode.first)
{
// Saving second point for new line
newLineItem.lineNode.second = m_listLines.at(i).lineNode.second;
delete m_listLines.at(i).itemPoint;
m_listLines.removeAt(i);
break;
}
}
for (int i = 0; i < m_listLines.size(); ++i)
{
if (node == m_listLines.at(i).lineNode.second)
{
newLineItem.lineNode.first = m_listLines.at(i).lineNode.first;
delete m_listLines.at(i).itemPoint;
m_listLines.removeAt(i);
break;
}
}
node->setPos((newLineItem.lineNode.first->pos() + newLineItem.lineNode.second->pos()) / 2);
m_listLines.push_back(newLineItem);
return true;
}
void GraphicsItemZone::scanPolygon(const QPolygonF &polygon)
{
GraphicsItemNode *node1;
node1 = new GraphicsItemNode(this);
node1->setPos(*polygon.begin());
m_listItems.push_back(node1);
m_scene->addItem(node1);
for (int i = 1; i < polygon.count(); ++i)
{
GraphicsItemNode *node2 = new GraphicsItemNode(this);
node2->setPos(polygon.at(i));
m_listItems.push_back(node2);
GraphicsItemNode *node3 = new GraphicsItemNode(this);
node3->setPos((node1->pos() + node2->pos()) / 2);
node3->setNodeType(GraphicsItemNode::MiddleType);
m_scene->addItem(node3);
LineItem newLineItem;
newLineItem.itemPoint = node3;
newLineItem.lineNode = LineNode(node1, node2);
m_listLines.push_back(newLineItem);
node1 = node2;
m_scene->addItem(node1);
}
setPolygon(polygon);
}
void GraphicsItemZone::updateZone()
{
QPolygonF polygon;
Q_FOREACH(GraphicsItemNode *node, m_listItems)
{
polygon << node->pos();
}
for (int i = 0; i < m_listLines.size(); ++i)
{
m_listLines.at(i).itemPoint->setPos((m_listLines.at(i).lineNode.first->pos() + m_listLines.at(i).lineNode.second->pos()) / 2);
}
setPolygon(polygon);
}
*/
AbstractWorldItem::AbstractWorldItem(QGraphicsItem *parent)
: QGraphicsItem(parent)
{
}
AbstractWorldItem::~AbstractWorldItem()
{
}
int AbstractWorldItem::type() const
{
return Type;
}
WorldItemPoint::WorldItemPoint(const QPointF &point, const float angle, QGraphicsItem *parent)
: AbstractWorldItem(parent),
m_angle(angle)
{
setZValue(WORLD_POINT_LAYER);
setPos(point);
m_rect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT);
m_pen.setColor(QColor(255, 100, 10));
m_pen.setWidth(5);
m_selectedPen.setColor(QColor(0, 255, 0));
m_selectedPen.setWidth(5);
m_brush.setColor(QColor(255, 100, 10));
m_brush.setStyle(Qt::SolidPattern);
m_selectedBrush.setColor(QColor(0, 255, 0));
m_selectedBrush.setStyle(Qt::SolidPattern);
//setFlag(ItemIsSelectable);
}
WorldItemPoint::~WorldItemPoint()
{
}
void WorldItemPoint::moveOn(const QPointF &offset)
{
prepareGeometryChange();
setPos(pos() + offset);
}
void WorldItemPoint::rotateOn(const QPointF &pivot, const qreal deltaAngle)
{
prepareGeometryChange();
QPolygonF rotatedPolygon(m_rect);
// TODO
rotatedPolygon.translate(pos());
rotatedPolygon.translate(-pivot);
QTransform trans;
trans = trans.rotate(deltaAngle);
rotatedPolygon = trans.map(rotatedPolygon);
rotatedPolygon.translate(pivot);
setPos(rotatedPolygon.boundingRect().center());
}
void WorldItemPoint::scaleOn(const QPointF &pivot, const QPointF &offset)
{
prepareGeometryChange();
QPolygonF scaledPolygon(m_rect);
// TODO
scaledPolygon.translate(pos());
scaledPolygon.translate(-pivot);
QTransform trans;
trans = trans.scale(1.0 + (offset.x() / 5000), 1.0 + (-offset.y() / 5000));
scaledPolygon = trans.map(scaledPolygon);
scaledPolygon.translate(pivot);
setPos(scaledPolygon.boundingRect().center());
}
void WorldItemPoint::turnOn(const QPointF &offset)
{
}
void WorldItemPoint::radiusOn(const qreal radius)
{
}
QPainterPath WorldItemPoint::shape() const
{
QPainterPath path;
path.addRect(m_rect);
return qt_graphicsItem_shapeFromPath(path, m_pen);
}
QRectF WorldItemPoint::boundingRect() const
{
return m_rect;
}
void WorldItemPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
// Here comes the magic:
//painter->setClipRect(option->exposedRect);
painter->setPen(Qt::NoPen);
if (option->state & QStyle::State_Selected)
{
painter->setBrush(m_selectedBrush);
}
else
{
painter->setBrush(m_brush);
}
painter->drawRect(m_rect);
}
QVariant WorldItemPoint::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionHasChanged)
{
}
return QGraphicsItem::itemChange(change, value);
}
WorldItemPath::WorldItemPath(const QPolygonF &polygon, QGraphicsItem *parent)
: AbstractWorldItem(parent),
m_polygon(polygon)
{
//setFlag(ItemIsSelectable);
setZValue(WORLD_PATH_LAYER);
m_pen.setColor(QColor(0, 0, 0));
m_pen.setWidth(5);
m_selectedPen.setColor(QColor(255, 0, 0));
m_selectedPen.setWidth(5);
}
WorldItemPath::~WorldItemPath()
{
}
void WorldItemPath::moveOn(const QPointF &offset)
{
prepareGeometryChange();
m_polygon.translate(offset);
}
void WorldItemPath::rotateOn(const QPointF &pivot, const qreal deltaAngle)
{
prepareGeometryChange();
QPolygonF rotatedPolygon(m_polygon);
rotatedPolygon.translate(-pivot);
QTransform trans;
trans = trans.rotate(deltaAngle);
m_polygon = trans.map(rotatedPolygon);
m_polygon.translate(pivot);
}
void WorldItemPath::scaleOn(const QPointF &pivot, const QPointF &offset)
{
prepareGeometryChange();
QPolygonF scaledPolygon(m_polygon);
scaledPolygon.translate(-pivot);
QTransform trans;
trans = trans.scale(1.0 + (offset.x() / 5000), 1.0 + (-offset.y() / 5000));
m_polygon = trans.map(scaledPolygon);
m_polygon.translate(pivot);
}
void WorldItemPath::turnOn(const QPointF &offset)
{
}
void WorldItemPath::radiusOn(const qreal radius)
{
}
QPainterPath WorldItemPath::shape() const
{
QPainterPath path;
path.moveTo(m_polygon.first());
for (int i = 1; i < m_polygon.count(); ++i)
path.lineTo(m_polygon.at(i));
return qt_graphicsItem_shapeFromPath(path, m_pen);
}
QRectF WorldItemPath::boundingRect() const
{
return m_polygon.boundingRect();
}
void WorldItemPath::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
// Here comes the magic:
//painter->setClipRect(option->exposedRect);
if (option->state & QStyle::State_Selected)
painter->setPen(m_selectedPen);
else
painter->setPen(m_pen);
painter->drawPolyline(m_polygon);
}
QVariant WorldItemPath::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionHasChanged)
{
}
return QGraphicsItem::itemChange(change, value);
}
WorldItemZone::WorldItemZone(const QPolygonF &polygon, QGraphicsItem *parent)
: AbstractWorldItem(parent),
m_polygon(polygon)
{
//setFlag(ItemIsSelectable);
setZValue(WORLD_ZONE_LAYER);
m_pen.setColor(QColor(20, 100, 255));
m_pen.setWidth(0);
m_selectedPen.setColor(QColor(255, 0, 0));
m_selectedPen.setWidth(0);
m_brush.setColor(QColor(20, 100, 255, 28));
m_brush.setStyle(Qt::SolidPattern);
m_selectedBrush.setColor(QColor(255, 0, 0, 128));
m_selectedBrush.setStyle(Qt::SolidPattern);
}
WorldItemZone::~WorldItemZone()
{
}
void WorldItemZone::moveOn(const QPointF &offset)
{
prepareGeometryChange();
m_polygon.translate(offset);
}
void WorldItemZone::rotateOn(const QPointF &pivot, const qreal deltaAngle)
{
prepareGeometryChange();
QPolygonF rotatedPolygon(m_polygon);
rotatedPolygon.translate(-pivot);
QTransform trans;
trans = trans.rotate(deltaAngle);
m_polygon = trans.map(rotatedPolygon);
m_polygon.translate(pivot);
}
void WorldItemZone::scaleOn(const QPointF &pivot, const QPointF &offset)
{
prepareGeometryChange();
QPolygonF scaledPolygon(m_polygon);
scaledPolygon.translate(-pivot);
QTransform trans;
trans = trans.scale(1.0 + (offset.x() / 5000), 1.0 + (-offset.y() / 5000));
m_polygon = trans.map(scaledPolygon);
m_polygon.translate(pivot);
}
void WorldItemZone::turnOn(const QPointF &offset)
{
}
void WorldItemZone::radiusOn(const qreal radius)
{
}
QRectF WorldItemZone::boundingRect() const
{
return m_polygon.boundingRect();
}
QPainterPath WorldItemZone::shape() const
{
QPainterPath path;
path.addPolygon(m_polygon);
return qt_graphicsItem_shapeFromPath(path, m_pen);
}
void WorldItemZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
if (option->state & QStyle::State_Selected)
{
painter->setPen(m_selectedPen);
painter->setBrush(m_selectedBrush);
}
else
{
painter->setPen(m_pen);
painter->setBrush(m_brush);
}
painter->drawPolygon(m_polygon);
}
QVariant WorldItemZone::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionHasChanged)
{
}
return QGraphicsItem::itemChange(change, value);
}
} /* namespace WorldEditor */

View file

@ -0,0 +1,237 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef WORLD_EDITOR_SCENE_ITEM_H
#define WORLD_EDITOR_SCENE_ITEM_H
// Project includes
#include "world_editor_global.h"
// NeL includes
// Qt includes
#include <QtCore/QPair>
#include <QtGui/QGraphicsObject>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsPolygonItem>
#include <QtGui/QGraphicsRectItem>
#include <QtGui/QGraphicsSceneMouseEvent>
namespace WorldEditor
{
class GraphicsItemZone;
class GraphicsItemNode;
typedef QPair<GraphicsItemNode *, GraphicsItemNode *> LineNode;
const int SELECTED_LAYER = 200;
const int UNSELECTED_LAYER = 100;
const int WORLD_ZONE_LAYER = 100;
const int WORLD_POINT_LAYER = 200;
const int WORLD_PATH_LAYER = 200;
const int MIDDLE_POINT_LAYER = 201;
const int EDGE_POINT_LAYER = 201;
/*
// Deprecated
class GraphicsItemNode: public QGraphicsObject
{
Q_OBJECT
Q_PROPERTY(QColor colorNode READ colorNode WRITE setColorNode)
public:
enum NodeType
{
EdgeType = 0,
MiddleType
};
GraphicsItemNode(GraphicsItemZone *itemZone, QGraphicsItem *parent = 0);
virtual ~GraphicsItemNode();
void setColorNode(const QColor &color);
QColor colorNode() const
{
return m_color;
}
void setNodeType(NodeType nodeType);
virtual QRectF boundingRect() const;
//QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
private:
NodeType m_type;
GraphicsItemZone *m_itemZone;
QColor m_color;
};
// Deprecated
class GraphicsItemZone: public QGraphicsPolygonItem
{
public:
GraphicsItemZone(QGraphicsScene *scene, QGraphicsItem *parent = 0);
virtual ~GraphicsItemZone();
void scanPolygon(const QPolygonF &polygon);
void updateMiddleNode(GraphicsItemNode *node);
bool deleteEdgePoint(GraphicsItemNode *node);
//void addNode(GraphicsItemNode *node);
void updateZone();
//QRectF boundingRect() const;
//void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
// QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
struct LineItem
{
GraphicsItemNode *itemPoint;
LineNode lineNode;
};
QGraphicsScene *m_scene;
QColor m_color;
QList<GraphicsItemNode *> m_listItems;
QList<LineItem> m_listLines;
};
*/
/*
@class WorldItemPoint
@brief
@details
*/
class AbstractWorldItem: public QGraphicsItem
{
public:
AbstractWorldItem(QGraphicsItem *parent = 0);
virtual ~AbstractWorldItem();
enum { Type = QGraphicsItem::UserType + 1 };
virtual void moveOn(const QPointF &offset) = 0;
virtual void rotateOn(const QPointF &pivot, const qreal deltaAngle) = 0;
// TODO: add modes: IgnoreAspectRatio, KeepAspectRatio
virtual void scaleOn(const QPointF &pivot, const QPointF &offset) = 0;
virtual void turnOn(const QPointF &offset) = 0;
virtual void radiusOn(const qreal radius) = 0;
// Enable the use of qgraphicsitem_cast with this item.
int type() const;
};
/*
@class WorldItemPoint
@brief
@details
*/
class WorldItemPoint: public AbstractWorldItem
{
public:
WorldItemPoint(const QPointF &point, const float angle, QGraphicsItem *parent = 0);
virtual ~WorldItemPoint();
virtual void moveOn(const QPointF &offset);
virtual void rotateOn(const QPointF &pivot, const qreal deltaAngle);
virtual void scaleOn(const QPointF &pivot, const QPointF &offset);
virtual void turnOn(const QPointF &offset);
virtual void radiusOn(const qreal radius);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
// TODO
static const int SIZE_POINT = 7;
QPen m_pen, m_selectedPen;
QBrush m_brush, m_selectedBrush;
QRectF m_rect;
float m_angle;
};
/*
@class WorldItemPath
@brief
@details
*/
class WorldItemPath: public AbstractWorldItem
{
public:
WorldItemPath(const QPolygonF &polygon, QGraphicsItem *parent = 0);
virtual ~WorldItemPath();
virtual void moveOn(const QPointF &offset);
virtual void rotateOn(const QPointF &pivot, const qreal deltaAngle);
virtual void scaleOn(const QPointF &pivot, const QPointF &offset);
virtual void turnOn(const QPointF &offset);
virtual void radiusOn(const qreal radius);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
QPen m_pen, m_selectedPen;
QPolygonF m_polygon;
};
/*
@class WorldItemZone
@brief
@details
*/
class WorldItemZone: public AbstractWorldItem
{
public:
WorldItemZone(const QPolygonF &polygon, QGraphicsItem *parent = 0);
virtual ~WorldItemZone();
virtual void moveOn(const QPointF &offset);
virtual void rotateOn(const QPointF &pivot, const qreal deltaAngle);
virtual void scaleOn(const QPointF &pivot, const QPointF &offset);
virtual void turnOn(const QPointF &offset);
virtual void radiusOn(const qreal radius);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
QPen m_pen, m_selectedPen;
QBrush m_brush, m_selectedBrush;
QPolygonF m_polygon;
};
} /* namespace WorldEditor */
#endif // WORLD_EDITOR_SCENE_ITEM_H

View file

@ -21,6 +21,8 @@
#include "world_editor_scene.h"
#include "world_editor_misc.h"
#include "world_editor_actions.h"
#include "world_editor_scene_item.h"
#include "project_settings_dialog.h"
// Core
#include "../core/icore.h"
@ -31,14 +33,9 @@
#include "../landscape_editor/builder_zone_base.h"
// NeL includes
#include <nel/misc/path.h>
#include <nel/ligo/primitive_utils.h>
#include <nel/ligo/primitive.h>
#include <nel/ligo/ligo_config.h>
// Qt includes
#include <QtCore/QSettings>
#include <QtCore/QSignalMapper>
#include <QtGui/QFileDialog>
namespace WorldEditor
@ -57,6 +54,7 @@ WorldEditorWindow::WorldEditorWindow(QWidget *parent)
m_worldEditorScene->setZoneBuilder(m_zoneBuilderBase);
m_ui.graphicsView->setScene(m_worldEditorScene);
m_ui.graphicsView->setVisibleText(false);
QActionGroup *sceneModeGroup = new QActionGroup(this);
sceneModeGroup->addAction(m_ui.selectAction);
@ -70,20 +68,38 @@ WorldEditorWindow::WorldEditorWindow(QWidget *parent)
m_ui.newWorldEditAction->setIcon(QIcon(Core::Constants::ICON_NEW));
m_ui.saveWorldEditAction->setIcon(QIcon(Core::Constants::ICON_SAVE));
m_primitivesModel = new PrimitivesTreeModel();
m_primitivesModel = new PrimitivesTreeModel(this);
m_ui.treePrimitivesView->setModel(m_primitivesModel);
// TODO: ?
m_ui.treePrimitivesView->setUndoStack(m_undoStack);
m_ui.treePrimitivesView->setZoneBuilder(m_zoneBuilderBase);
m_ui.treePrimitivesView->setWorldScene(m_worldEditorScene);
createMenus();
createToolBars();
readSettings();
QSignalMapper *m_modeMapper = new QSignalMapper(this);
connect(m_ui.selectAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.selectAction, 0);
connect(m_ui.moveAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.moveAction, 1);
connect(m_ui.rotateAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.rotateAction, 2);
connect(m_ui.scaleAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.scaleAction, 3);
connect(m_ui.turnAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.turnAction, 4);
connect(m_ui.radiusAction, SIGNAL(triggered()), m_modeMapper, SLOT(map()));
m_modeMapper->setMapping(m_ui.radiusAction, 5);
connect(m_modeMapper, SIGNAL(mapped(int)), this, SLOT(setMode(int)));
connect(m_ui.pointsAction, SIGNAL(triggered(bool)), m_worldEditorScene, SLOT(setEnabledEditPoint(bool)));
connect(m_ui.settingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings()));
connect(m_ui.newWorldEditAction, SIGNAL(triggered()), this, SLOT(newWorldEditFile()));
connect(m_ui.saveWorldEditAction, SIGNAL(triggered()), this, SLOT(saveWorldEditFile()));
}
WorldEditorWindow::~WorldEditorWindow()
@ -118,6 +134,7 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName)
Utils::WorldEditList worldEditList;
if (!Utils::loadWorldEditFile(fileName.toStdString(), worldEditList))
{
// TODO: add the message box
return;
}
@ -139,7 +156,7 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName)
m_undoStack->push(new LoadLandscapeCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel, m_zoneBuilderBase));
break;
case Utils::PrimitiveType:
m_undoStack->push(new LoadRootPrimitiveCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel));
m_undoStack->push(new LoadRootPrimitiveCommand(QString(worldEditList[i].second.c_str()), m_worldEditorScene, m_primitivesModel));
break;
};
}
@ -163,15 +180,55 @@ void WorldEditorWindow::saveWorldEditFile()
void WorldEditorWindow::openProjectSettings()
{
/*
LandscapeEditor::ProjectSettingsDialog *dialog = new LandscapeEditor::ProjectSettingsDialog("", this);
dialog->show();
int ok = dialog->exec();
if (ok == QDialog::Accepted)
{
}
delete dialog;
*/
ProjectSettingsDialog *dialog = new ProjectSettingsDialog(m_zoneBuilderBase->dataPath(), this);
dialog->show();
int ok = dialog->exec();
if (ok == QDialog::Accepted)
{
m_zoneBuilderBase->init(dialog->dataPath(), true);
}
delete dialog;
}
void WorldEditorWindow::setMode(int value)
{
switch (value)
{
case 0:
m_worldEditorScene->setModeEdit(WorldEditorScene::SelectMode);
break;
case 1:
m_worldEditorScene->setModeEdit(WorldEditorScene::MoveMode);
break;
case 2:
m_worldEditorScene->setModeEdit(WorldEditorScene::RotateMode);
break;
case 3:
m_worldEditorScene->setModeEdit(WorldEditorScene::ScaleMode);
break;
case 4:
m_worldEditorScene->setModeEdit(WorldEditorScene::TurnMode);
break;
case 5:
m_worldEditorScene->setModeEdit(WorldEditorScene::RadiusMode);
break;
}
}
void WorldEditorWindow::showEvent(QShowEvent *showEvent)
{
QMainWindow::showEvent(showEvent);
if (m_oglWidget != 0)
m_oglWidget->makeCurrent();
//m_statusInfo->show();
//m_statusBarTimer->start(100);
}
void WorldEditorWindow::hideEvent(QHideEvent *hideEvent)
{
QMainWindow::hideEvent(hideEvent);
//m_statusInfo->hide();
//m_statusBarTimer->stop();
}
void WorldEditorWindow::createMenus()
@ -211,6 +268,14 @@ void WorldEditorWindow::readSettings()
settings->beginGroup(Constants::WORLD_EDITOR_SECTION);
restoreState(settings->value(Constants::WORLD_WINDOW_STATE).toByteArray());
restoreGeometry(settings->value(Constants::WORLD_WINDOW_GEOMETRY).toByteArray());
// Use OpenGL graphics system instead raster graphics system
if (settings->value(Constants::WORLD_EDITOR_USE_OPENGL, true).toBool())
{
m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer));
m_ui.graphicsView->setViewport(m_oglWidget);
}
settings->endGroup();
}

View file

@ -22,6 +22,8 @@
// Qt includes
#include <QtGui/QUndoStack>
#include <QtCore/QSignalMapper>
#include <QtOpenGL/QGLWidget>
namespace LandscapeEditor
{
@ -52,6 +54,12 @@ private Q_SLOTS:
void saveWorldEditFile();
void openProjectSettings();
void setMode(int value);
protected:
virtual void showEvent(QShowEvent *showEvent);
virtual void hideEvent(QHideEvent *hideEvent);
private:
void createMenus();
void createToolBars();
@ -67,6 +75,8 @@ private:
QUndoStack *m_undoStack;
WorldEditorScene *m_worldEditorScene;
LandscapeEditor::ZoneBuilderBase *m_zoneBuilderBase;
QSignalMapper m_modeMapper;
QGLWidget *m_oglWidget;
Ui::WorldEditorWindow m_ui;
}; /* class WorldEditorWindow */

View file

@ -21,8 +21,14 @@
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LandscapeEditor::LandscapeView" name="graphicsView">
<property name="interactive">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="dragMode">
<enum>QGraphicsView::RubberBandDrag</enum>
<enum>QGraphicsView::NoDrag</enum>
</property>
<property name="transformationAnchor">
<enum>QGraphicsView::AnchorUnderMouse</enum>
@ -30,6 +36,12 @@
<property name="resizeAnchor">
<enum>QGraphicsView::AnchorUnderMouse</enum>
</property>
<property name="viewportUpdateMode">
<enum>QGraphicsView::BoundingRectViewportUpdate</enum>
</property>
<property name="optimizationFlags">
<set>QGraphicsView::DontAdjustForAntialiasing|QGraphicsView::DontClipPainter</set>
</property>
</widget>
</item>
</layout>
@ -87,9 +99,6 @@
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="animated">
<bool>true</bool>
</property>
<attribute name="headerCascadingSectionResizes">
<bool>true</bool>
</attribute>
@ -117,6 +126,8 @@
<addaction name="visibleDetailsAction"/>
<addaction name="visibleGridAction"/>
<addaction name="visibleGridPointsAction"/>
<addaction name="separator"/>
<addaction name="settingsAction"/>
</widget>
<action name="loadPrimitiveAction">
<property name="text">
@ -137,19 +148,22 @@
<string>loadLand</string>
</property>
</action>
<action name="landSettingsAction">
<action name="settingsAction">
<property name="icon">
<iconset resource="../landscape_editor/landscape_editor.qrc">
<normaloff>:/icons/ic_nel_landscape_settings.png</normaloff>:/icons/ic_nel_landscape_settings.png</iconset>
</property>
<property name="text">
<string>LandSettings</string>
<string>Settings</string>
</property>
</action>
<action name="visibleLandAction">
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S/H Land</string>
</property>
@ -158,6 +172,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S/H Primitives</string>
</property>
@ -166,6 +183,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S/H Layers</string>
</property>
@ -174,6 +194,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S/H Details</string>
</property>
@ -182,6 +205,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../landscape_editor/landscape_editor.qrc">
<normaloff>:/icons/ic_grid.png</normaloff>:/icons/ic_grid.png</iconset>
@ -194,6 +220,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>S/H Grid points</string>
</property>
@ -260,6 +289,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="world_editor.qrc">
<normaloff>:/icons/ic_nel_turn.png</normaloff>:/icons/ic_nel_turn.png</iconset>
@ -272,6 +304,9 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Radius</string>
</property>
@ -280,10 +315,22 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Edit points</string>
</property>
</action>
<action name="projectSettingsAction">
<property name="icon">
<iconset resource="../landscape_editor/landscape_editor.qrc">
<normaloff>:/icons/ic_nel_landscape_settings.png</normaloff>:/icons/ic_nel_landscape_settings.png</iconset>
</property>
<property name="text">
<string>Project settings</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>