Changed: #1302 Redesigned the primitives database and added undo\redo commands for database.

This commit is contained in:
dnk-88 2011-08-03 18:45:14 +03:00
parent 7a0564bdf2
commit b9732cb5bb
11 changed files with 1070 additions and 375 deletions

View file

@ -17,6 +17,9 @@
// Project includes // Project includes
#include "primitive_item.h" #include "primitive_item.h"
#include "world_editor_misc.h" #include "world_editor_misc.h"
#include "world_editor_constants.h"
#include "../landscape_editor/landscape_editor_constants.h"
// NeL includes // NeL includes
#include <nel/ligo/ligo_config.h> #include <nel/ligo/ligo_config.h>
@ -28,87 +31,160 @@
namespace WorldEditor namespace WorldEditor
{ {
BaseTreeItem::BaseTreeItem(BaseTreeItem *parent) Node::Node()
: m_parent(0)
{ {
m_parentItem = parent;
m_itemData << QIcon() << "" << "" << "";
} }
BaseTreeItem::BaseTreeItem(const QList<QVariant> &data, BaseTreeItem *parent) Node::~Node()
{ {
m_parentItem = parent; if (m_parent)
m_itemData = data; m_parent->removeChildNode(this);
qDeleteAll(m_children);
nlassert(m_children.isEmpty());
m_data.clear();
} }
BaseTreeItem::~BaseTreeItem() void Node::prependChildNode(Node *node)
{ {
qDeleteAll(m_childItems); // Node is already a child
nlassert(!m_children.contains(node));
// Node already has a parent
nlassert(!m_children.contains(node));
m_children.prepend(node);
node->m_parent = this;
} }
void BaseTreeItem::appendChild(BaseTreeItem *item) void Node::appendChildNode(Node *node)
{ {
m_childItems.append(item); // Node is already a child
nlassert(!m_children.contains(node));
// Node already has a parent
nlassert(!m_children.contains(node));
m_children.append(node);
node->m_parent = this;
} }
void BaseTreeItem::deleteChild(int row) void Node::insertChildNodeBefore(Node *node, Node *before)
{ {
delete m_childItems.takeAt(row); // Node is already a child
nlassert(!m_children.contains(node));
// Node already has a parent
nlassert(!m_children.contains(node));
int idx = before ? m_children.indexOf(before) : -1;
if (idx == -1)
m_children.append(node);
else
m_children.insert(idx, node);
node->m_parent = this;
} }
BaseTreeItem *BaseTreeItem::child(int row) void Node::insertChildNodeAfter(Node *node, Node *after)
{ {
return m_childItems.value(row); // Node is already a child
nlassert(!m_children.contains(node));
// Node already has a parent
nlassert(!m_children.contains(node));
int idx = after ? m_children.indexOf(after) : -1;
if (idx == -1)
m_children.append(node);
else
m_children.insert(idx + 1, node);
node->m_parent = this;
} }
int BaseTreeItem::childCount() const void Node::removeChildNode(Node *node)
{ {
return m_childItems.count(); nlassert(m_children.contains(node));
nlassert(node->parent() == this);
m_children.removeOne(node);
node->m_parent = 0;
} }
int BaseTreeItem::columnCount() const Node *Node::child(int row)
{ {
return m_itemData.count(); return m_children.at(row);
} }
QVariant BaseTreeItem::data(int column) const int Node::childCount() const
{ {
return m_itemData.value(column); return m_children.count();
} }
void BaseTreeItem::setData(int column, const QVariant &data) QVariant Node::data(int key) const
{ {
m_itemData[column] = data; return m_data[key];
} }
BaseTreeItem *BaseTreeItem::parent() void Node::setData(int key, const QVariant &data)
{ {
return m_parentItem; m_data[key] = data;
} }
int BaseTreeItem::row() const Node *Node::parent()
{ {
if (m_parentItem) return m_parent;
return m_parentItem->m_childItems.indexOf(const_cast<BaseTreeItem *>(this)); }
int Node::row() const
{
if (m_parent)
return m_parent->m_children.indexOf(const_cast<Node *>(this));
return 0; return 0;
} }
void BaseTreeItem::setModified(bool value) Node::NodeType Node::type() const
{ {
m_modified = value; return BasicNodeType;
} }
bool BaseTreeItem::isModified() const WorldEditNode::WorldEditNode(const QString &name)
{ {
return m_modified; setData(Qt::DisplayRole, name);
setData(Qt::DecorationRole, QIcon(Constants::ICON_WORLD_EDITOR));
} }
PrimitiveItem::PrimitiveItem(NLLIGO::IPrimitive *primitive, BaseTreeItem *parent) WorldEditNode::~WorldEditNode()
: BaseTreeItem(parent),
m_primitive(primitive)
{ {
setData(1, QString(m_primitive->getName().c_str())); }
setData(2, QString(m_primitive->getClassName().c_str()));
Node::NodeType WorldEditNode::type() const
{
return WorldEditNodeType;
}
LandscapeNode::LandscapeNode(const QString &name)
{
setData(Qt::DisplayRole, name);
setData(Qt::DecorationRole, QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM));
}
LandscapeNode::~LandscapeNode()
{
}
Node::NodeType LandscapeNode::type() const
{
return LandscapeNodeType;
}
PrimitiveNode::PrimitiveNode(NLLIGO::IPrimitive *primitive)
: m_primitive(primitive)
{
setData(Qt::DisplayRole, QString(m_primitive->getName().c_str()));
setData(Qt::ToolTipRole, QString(m_primitive->getClassName().c_str()));
std::string className; std::string className;
m_primitive->getPropertyByName("class", className); m_primitive->getPropertyByName("class", className);
@ -125,43 +201,57 @@ PrimitiveItem::PrimitiveItem(NLLIGO::IPrimitive *primitive, BaseTreeItem *parent
else else
icon = QIcon("./old_ico/folder_h.ico"); icon = QIcon("./old_ico/folder_h.ico");
} }
setData(0, icon); setData(Qt::DecorationRole, icon);
setData(3, QString(className.c_str())); //setData(3, QString(className.c_str()));
} }
/*
PrimitiveItem::PrimitiveItem(const PrimitiveItem &other) PrimitiveNode::~PrimitiveNode()
{
}
*/
PrimitiveItem::~PrimitiveItem()
{ {
} }
NLLIGO::IPrimitive *PrimitiveItem::primitive() const NLLIGO::IPrimitive *PrimitiveNode::primitive() const
{ {
return m_primitive; return m_primitive;
} }
const NLLIGO::CPrimitiveClass *PrimitiveItem::primitiveClass() const const NLLIGO::CPrimitiveClass *PrimitiveNode::primitiveClass() const
{ {
return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*m_primitive); return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*m_primitive);
} }
RootPrimitiveNode *PrimitiveNode::rootPrimitiveNode()
{
Node *node = this;
while (node && (node->type() != Node::RootPrimitiveNodeType))
node = node->parent();
return (RootPrimitiveNode *)node;
}
RootPrimitiveItem::RootPrimitiveItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent) Node::NodeType PrimitiveNode::type() const
: PrimitiveItem(primitives->RootNode, parent), {
return PrimitiveNodeType;
}
RootPrimitiveNode::RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives)
: PrimitiveNode(primitives->RootNode),
m_primitives(primitives) m_primitives(primitives)
{ {
setData(1, name); setData(Qt::DisplayRole, name);
} }
/*
RootPrimitiveItem::RootPrimitiveItem(const RootPrimitiveItem &other) RootPrimitiveNode::~RootPrimitiveNode()
{ {
} }
*/
RootPrimitiveItem::~RootPrimitiveItem() NLLIGO::CPrimitives *RootPrimitiveNode::primitives() const
{ {
return m_primitives;
}
Node::NodeType RootPrimitiveNode::type() const
{
return RootPrimitiveNodeType;
} }
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -31,69 +31,144 @@
namespace WorldEditor namespace WorldEditor
{ {
class WorldEditNode;
class RootPrimitiveNode;
class LandscapeNode;
class PrimitiveNode;
/* /*
@class BaseTreeItem @class Node
@brief @brief
@details @details
*/ */
class BaseTreeItem class Node
{ {
public: public:
BaseTreeItem(BaseTreeItem *parent = 0);
BaseTreeItem(const QList<QVariant> &data, BaseTreeItem *parent = 0);
virtual ~BaseTreeItem();
void appendChild(BaseTreeItem *child); enum NodeType
void deleteChild(int row); {
BasicNodeType,
WorldEditNodeType,
RootPrimitiveNodeType,
LandscapeNodeType,
PrimitiveNodeType,
UserNodeType = 1024
};
BaseTreeItem *child(int row); Node();
virtual ~Node();
/// Remove child node from the child list.
void removeChildNode(Node *node);
/// Insert node at the beginning of the list.
void prependChildNode(Node *node);
/// Insert node at the end of the list.
void appendChildNode(Node *node);
/// Insert node in front of the node pointed to by the pointer before.
void insertChildNodeBefore(Node *node, Node *before);
/// Insert node in back of the node pointed to by the pointer after.
void insertChildNodeAfter(Node *node, Node *after);
/// Return the node at index position row in the child list.
Node *child(int row);
/// Return the number of nodes in the list.
int childCount() const; int childCount() const;
int columnCount() const;
QVariant data(int column) const; /// Return a row index this node.
void setData(int column, const QVariant &data);
int row() const; int row() const;
BaseTreeItem *parent();
void setModified(bool value); /// Return a pointer to this node's parent item. If this node does not have a parent, 0 is returned.
bool isModified() const; Node *parent();
/// Set this node's custom data for the key key to value.
void setData(int key, const QVariant &data);
/// Return this node's custom data for the key key as a QVariant.
QVariant data(int key) const;
/// Return a type this node.
virtual NodeType type() const;
private: private:
Q_DISABLE_COPY(Node)
bool m_modified; Node *m_parent;
QList<BaseTreeItem *> m_childItems; QList<Node *> m_children;
QList<QVariant> m_itemData; QHash<int, QVariant> m_data;
BaseTreeItem *m_parentItem;
}; };
/* /*
@class PrimitiveItem @class WorldEditNode
@brief @brief
@details @details
*/ */
class PrimitiveItem: public BaseTreeItem class WorldEditNode: public Node
{ {
public: public:
PrimitiveItem(NLLIGO::IPrimitive *primitive, BaseTreeItem *parent); WorldEditNode(const QString &name);
PrimitiveItem(const PrimitiveItem &other); virtual ~WorldEditNode();
virtual ~PrimitiveItem();
virtual NodeType type() const;
private:
};
/*
@class LandscapeNode
@brief
@details
*/
class LandscapeNode: public Node
{
public:
LandscapeNode(const QString &name);
virtual ~LandscapeNode();
virtual NodeType type() const;
private:
};
/*
@class PrimitiveNode
@brief
@details
*/
class PrimitiveNode: public Node
{
public:
PrimitiveNode(NLLIGO::IPrimitive *primitive);
virtual ~PrimitiveNode();
NLLIGO::IPrimitive *primitive() const; NLLIGO::IPrimitive *primitive() const;
const NLLIGO::CPrimitiveClass *primitiveClass() const; const NLLIGO::CPrimitiveClass *primitiveClass() const;
RootPrimitiveNode *rootPrimitiveNode();
virtual NodeType type() const;
private: private:
NLLIGO::IPrimitive *m_primitive; NLLIGO::IPrimitive *m_primitive;
}; };
/* /*
@class PrimitivesItem @class RootPrimitiveNode
@brief @brief
@details @details
*/ */
class RootPrimitiveItem: public PrimitiveItem class RootPrimitiveNode: public PrimitiveNode
{ {
public: public:
RootPrimitiveItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent); RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives);
RootPrimitiveItem(const RootPrimitiveItem &other); virtual ~RootPrimitiveNode();
virtual ~RootPrimitiveItem();
NLLIGO::CPrimitives *primitives() const;
virtual NodeType type() const;
private: private:
NLLIGO::CPrimitives *m_primitives; NLLIGO::CPrimitives *m_primitives;

View file

@ -31,24 +31,26 @@ namespace WorldEditor
{ {
PrimitivesTreeModel::PrimitivesTreeModel(QObject *parent) PrimitivesTreeModel::PrimitivesTreeModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent),
m_worldEditNode(0)
{ {
QList<QVariant> rootData; m_rootNode = new Node();
rootData << "Name" << "Class" << "Class"; m_rootNode->setData(Qt::DisplayRole, "Name");
m_rootItem = new BaseTreeItem(rootData);
} }
PrimitivesTreeModel::~PrimitivesTreeModel() PrimitivesTreeModel::~PrimitivesTreeModel()
{ {
delete m_rootItem; delete m_rootNode;
} }
int PrimitivesTreeModel::columnCount(const QModelIndex &parent) const int PrimitivesTreeModel::columnCount(const QModelIndex &parent) const
{ {
if (parent.isValid()) /* if (parent.isValid())
return static_cast<BaseTreeItem *>(parent.internalPointer())->columnCount(); return static_cast<BaseTreeItem *>(parent.internalPointer())->columnCount();
else else
return m_rootItem->columnCount(); return m_rootItem->columnCount();
*/
return 1;
} }
QVariant PrimitivesTreeModel::data(const QModelIndex &index, int role) const QVariant PrimitivesTreeModel::data(const QModelIndex &index, int role) const
@ -56,20 +58,15 @@ QVariant PrimitivesTreeModel::data(const QModelIndex &index, int role) const
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
BaseTreeItem *item = static_cast<BaseTreeItem *>(index.internalPointer()); Node *item = static_cast<Node *>(index.internalPointer());
switch (role) switch (role)
{ {
// case Qt::TextAlignmentRole: // case Qt::TextAlignmentRole:
// return int(Qt::AlignLeft | Qt::AlignVCenter); // return int(Qt::AlignLeft | Qt::AlignVCenter);
case Qt::DisplayRole: case Qt::DisplayRole:
return item->data(index.column() + 1); return item->data(Qt::DisplayRole);
case Qt::DecorationRole: case Qt::DecorationRole:
{ return item->data(Qt::DecorationRole);
if (index.column() == 0)
return qVariantFromValue(item->data(0));
else
return QVariant();
}
default: default:
return QVariant(); return QVariant();
} }
@ -83,31 +80,30 @@ Qt::ItemFlags PrimitivesTreeModel::flags(const QModelIndex &index) const
return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} }
QVariant PrimitivesTreeModel::headerData(int section, Qt::Orientation orientation, QVariant PrimitivesTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
int role) const
{ {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return m_rootItem->data(section); // return m_rootNode->data(section);
return m_rootNode->data(Qt::DisplayRole);
return QVariant(); return QVariant();
} }
QModelIndex PrimitivesTreeModel::index(int row, int column, const QModelIndex &parent) QModelIndex PrimitivesTreeModel::index(int row, int column, const QModelIndex &parent) const
const
{ {
if (!hasIndex(row, column, parent)) if (!hasIndex(row, column, parent))
return QModelIndex(); return QModelIndex();
BaseTreeItem *parentItem; Node *parentNode;
if (!parent.isValid()) if (!parent.isValid())
parentItem = m_rootItem; parentNode = m_rootNode;
else else
parentItem = static_cast<BaseTreeItem *>(parent.internalPointer()); parentNode = static_cast<Node *>(parent.internalPointer());
BaseTreeItem *childItem = parentItem->child(row); Node *childNode = parentNode->child(row);
if (childItem) if (childNode)
return createIndex(row, column, childItem); return createIndex(row, column, childNode);
else else
return QModelIndex(); return QModelIndex();
} }
@ -117,161 +113,166 @@ QModelIndex PrimitivesTreeModel::parent(const QModelIndex &index) const
if (!index.isValid()) if (!index.isValid())
return QModelIndex(); return QModelIndex();
BaseTreeItem *childItem = static_cast<BaseTreeItem *>(index.internalPointer()); Node *childNode = static_cast<Node *>(index.internalPointer());
BaseTreeItem *parentItem = childItem->parent(); Node *parentNode = childNode->parent();
if (parentItem == m_rootItem) if (parentNode == m_rootNode)
return QModelIndex(); return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem); return createIndex(parentNode->row(), 0, parentNode);
} }
int PrimitivesTreeModel::rowCount(const QModelIndex &parent) const int PrimitivesTreeModel::rowCount(const QModelIndex &parent) const
{ {
BaseTreeItem *parentItem; Node *parentNode;
if (parent.column() > 0) if (parent.column() > 0)
return 0; return 0;
if (!parent.isValid()) if (!parent.isValid())
parentItem = m_rootItem; parentNode = m_rootNode;
else else
parentItem = static_cast<BaseTreeItem *>(parent.internalPointer()); parentNode = static_cast<Node *>(parent.internalPointer());
return parentItem->childCount(); return parentNode->childCount();
} }
NLLIGO::IPrimitive *PrimitivesTreeModel::primitive(const QModelIndex &index) Path PrimitivesTreeModel::pathFromIndex(const QModelIndex &index)
{ {
NLLIGO::IPrimitive *prim = 0; QModelIndex iter = index;
if (index.isValid()) Path path;
while(iter.isValid())
{ {
PrimitiveItem *item = static_cast<PrimitiveItem *>(index.internalPointer()); path.prepend(PathItem(iter.row(), iter.column()));
prim = item->primitive(); iter = iter.parent();
} }
return prim; return path;
} }
const NLLIGO::CPrimitiveClass *PrimitivesTreeModel::primitiveClass(const QModelIndex &index) QModelIndex PrimitivesTreeModel::pathToIndex(const Path &path)
{ {
if (index.isValid()) QModelIndex iter;
for(int i = 0; i < path.size(); i++)
{ {
NLLIGO::IPrimitive *prim = primitive(index); iter = index(path[i].first, path[i].second, iter);
return ligoConfig()->getPrimitiveClass(*prim);
} }
return 0; return iter;
} }
void PrimitivesTreeModel::loadPrimitive(const QString &fileName) void PrimitivesTreeModel::createWorldEditNode(const QString &fileName)
{
NLLIGO::CPrimitives *primitives = new NLLIGO::CPrimitives();
// set the primitive context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = primitives;
NLLIGO::loadXmlPrimitiveFile(*primitives, fileName.toStdString(), *NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig);
// unset the context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL;
addRootPrimitive(fileName, primitives);
}
void PrimitivesTreeModel::newPrimitiveWithoutUndo(const QString &className, uint id, const QModelIndex &parent)
{
const NLLIGO::CPrimitiveClass *primClass = primitiveClass(parent);
float delta = 10;
// TODO: Set the context
//CPrimitiveContext::instance().CurrentPrimitive = &_DataHierarchy[locator._LocateStack[0]].Primitives;
NLLIGO::IPrimitive *newPrimitive = createPrimitive(className.toStdString().c_str(), className.toStdString().c_str()
, NLMISC::CVector(), delta, primClass->DynamicChildren[id].Parameters, primitive(parent));
// unset the context
//CPrimitiveContext::instance().CurrentPrimitive = NULL;
if (newPrimitive != 0)
{
scanPrimitive(newPrimitive, parent);
}
}
void PrimitivesTreeModel::deletePrimitiveWithoutUndo(const QModelIndex &index)
{
deletePrimitive(primitive(index));
removeRows(index.row(), index.parent());
}
void PrimitivesTreeModel::addRootPrimitive(const QString &name, NLLIGO::CPrimitives *primitives)
{ {
beginResetModel(); beginResetModel();
m_worldEditNode = new WorldEditNode(fileName);
m_rootNode->appendChildNode(m_worldEditNode);
endResetModel();
}
// Create root primitive void PrimitivesTreeModel::deleteWorldEditNode()
RootPrimitiveItem *newPrimitives = new RootPrimitiveItem(name, primitives, m_rootItem); {
m_rootItem->appendChild(newPrimitives); beginResetModel();
if (m_worldEditNode != 0)
// Scan childs items and add in tree model
for (uint i = 0; i < primitives->RootNode->getNumChildren(); ++i)
{ {
NLLIGO::IPrimitive *childPrim; delete m_worldEditNode;
primitives->RootNode->getChild(childPrim, i); m_worldEditNode = 0;
scanPrimitive(childPrim, newPrimitives);
} }
endResetModel(); endResetModel();
} }
void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, const QModelIndex &parentIndex) Path PrimitivesTreeModel::createLandscapeNode(const QString &fileName)
{ {
PrimitiveItem *parent = static_cast<PrimitiveItem *>(parentIndex.internalPointer()); if (m_worldEditNode == 0)
createWorldEditNode("NewWorldEdit");
// Add in tree model QModelIndex parentIndex = index(0, 0, QModelIndex());
beginInsertRows(parentIndex, parent->childCount(), parent->childCount()); beginInsertRows(parentIndex, 0, 0);
PrimitiveItem *newItem = new PrimitiveItem(prim, parent); LandscapeNode *newNode = new LandscapeNode(fileName);
parent->appendChild(newItem); m_worldEditNode->prependChildNode(newNode);
endInsertRows();
return pathFromIndex(index(0, 0, index(0, 0, QModelIndex())));
}
Path PrimitivesTreeModel::createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives)
{
if (m_worldEditNode == 0)
createWorldEditNode("NewWorldEdit");
// Get position
int pos = m_worldEditNode->childCount();
QModelIndex parentIndex = index(0, 0, QModelIndex());
// Add root node in tree model
beginInsertRows(parentIndex, pos, pos);
RootPrimitiveNode *newNode = new RootPrimitiveNode(fileName, primitives);
m_worldEditNode->appendChildNode(newNode);
endInsertRows(); endInsertRows();
// Scan childs items and add in tree model QModelIndex rootPrimIndex = index(pos, 0, parentIndex);
QModelIndex childIndex = index(parent->childCount() - 1, 0, parentIndex);
for (uint i = 0; i < prim->getNumChildren(); ++i) // Scan childs items and add in the tree model
for (uint i = 0; i < primitives->RootNode->getNumChildren(); ++i)
{ {
NLLIGO::IPrimitive *childPrim; NLLIGO::IPrimitive *childPrim;
prim->getChild(childPrim, i); primitives->RootNode->getChild(childPrim, i);
scanPrimitive(childPrim, childIndex); createChildNodes(childPrim, rootPrimIndex);
}
return pathFromIndex(rootPrimIndex);
}
Path PrimitivesTreeModel::createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent)
{
QModelIndex parentIndex = pathToIndex(parent);
Node *parentNode = static_cast<Node *>(parentIndex.internalPointer());
int pos = parentNode->childCount();
createChildNodes(primitive, parentIndex);
return pathFromIndex(index(pos, 0, parentIndex));
}
void PrimitivesTreeModel::deleteNode(const Path &path)
{
QModelIndex nodeIndex = pathToIndex(path);
QModelIndex parentIndex = nodeIndex.parent();
Node *node = static_cast<Node *>(nodeIndex.internalPointer());
// Scan childs items and delete from the tree model
removeChildNodes(node, parentIndex);
}
void PrimitivesTreeModel::createChildNodes(NLLIGO::IPrimitive *primitive, const QModelIndex &parent)
{
Node *parentNode = static_cast<Node *>(parent.internalPointer());
int pos = parentNode->childCount();
// Add node in the tree model
beginInsertRows(parent, pos, pos);
PrimitiveNode *newNode = new PrimitiveNode(primitive);
parentNode->appendChildNode(newNode);
endInsertRows();
// Scan childs items and add in the tree model
QModelIndex childIndex = index(pos, 0, parent);
for (uint i = 0; i < primitive->getNumChildren(); ++i)
{
NLLIGO::IPrimitive *childPrim;
primitive->getChild(childPrim, i);
createChildNodes(childPrim, childIndex);
} }
} }
void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem *parent) void PrimitivesTreeModel::removeChildNodes(Node *node, const QModelIndex &parent)
{ {
// Add in tree model // Delete all child nodes from the tree model
PrimitiveItem *newItem = new PrimitiveItem(prim, parent); while (node->childCount() != 0)
parent->appendChild(newItem); removeChildNodes(node->child(node->childCount() - 1), parent.child(node->row(), 0));
// Scan childs items and add in tree model // Delete node from the tree model
for (uint i = 0; i < prim->getNumChildren(); ++i) beginRemoveRows(parent, node->row(), node->row());
{ delete node;
NLLIGO::IPrimitive *childPrim;
prim->getChild(childPrim, i);
scanPrimitive(childPrim, newItem);
}
}
void PrimitivesTreeModel::removeRows(int position, const QModelIndex &parent)
{
BaseTreeItem *item = static_cast<BaseTreeItem *>(parent.internalPointer())->child(position);
// Delete all child items from tree model
while (item->childCount() != 0)
removeRows(0, parent.child(position, 0));
// Delete item
beginRemoveRows(parent, position, position);
static_cast<BaseTreeItem *>(parent.internalPointer())->deleteChild(position);
endRemoveRows(); endRemoveRows();
} }
NLLIGO::CLigoConfig *PrimitivesTreeModel::ligoConfig() const
{
return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig;
}
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -31,9 +31,15 @@
namespace WorldEditor namespace WorldEditor
{ {
class Node;
class WorldEditNode;
class BaseTreeItem; typedef QPair<int, int> PathItem;
class PrimitiveItem; /*
@typedef Path
@brief It store a list of row and column numbers which have to walk through from the root index of the model to reach the need item
*/
typedef QList<PathItem> Path;
/** /**
@class PrimitivesTreeModel @class PrimitivesTreeModel
@ -58,32 +64,34 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const;
// Get primitive /// Convert QModelIndex to the persistent index - @Path.
NLLIGO::IPrimitive *primitive(const QModelIndex &index); /// @Path is a list of [row,column] pairs showing us the way through the model.
Path pathFromIndex(const QModelIndex &index);
// Get primitive class QModelIndex pathToIndex(const Path &path);
const NLLIGO::CPrimitiveClass *primitiveClass(const QModelIndex &index);
// Load primitive from file void createWorldEditNode(const QString &fileName);
void loadPrimitive(const QString &fileName); void deleteWorldEditNode();
// Create new primitive and add in tree model /// Add new landscape node in tree model.
void newPrimitiveWithoutUndo(const QString &className, uint id, const QModelIndex &parent); Path createLandscapeNode(const QString &fileName);
void deletePrimitiveWithoutUndo(const QModelIndex &index); /// Add new root primitive node and all sub-primitives in the tree model.
Path createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives);
NLLIGO::CLigoConfig *ligoConfig() const; /// Add new primitive node and all sub-primitives in the tree model.
Path createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent);
/// Delete node and all child nodes from the tree model
void deleteNode(const Path &path);
private: private:
// Add root primitive in tree model and add all its sub-items. void createChildNodes(NLLIGO::IPrimitive *primitive, const QModelIndex &parent);
void addRootPrimitive(const QString &name, NLLIGO::CPrimitives *primitives);
void scanPrimitive(NLLIGO::IPrimitive *prim, const QModelIndex &parentIndex); void removeChildNodes(Node *node, const QModelIndex &parent);
void scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem *parent = 0);
void removeRows(int position, const QModelIndex &parent); Node *m_rootNode;
WorldEditNode *m_worldEditNode;
BaseTreeItem *m_rootItem;
}; };
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -16,8 +16,13 @@
// Project includes // Project includes
#include "primitives_view.h" #include "primitives_view.h"
//#include "primitive_item.h" #include "primitive_item.h"
#include "primitives_model.h" #include "primitives_model.h"
#include "world_editor_actions.h"
#include "../core/core_constants.h"
#include "../landscape_editor/landscape_editor_constants.h"
#include "../landscape_editor/builder_zone_base.h"
// NeL includes // NeL includes
#include <nel/ligo/primitive.h> #include <nel/ligo/primitive.h>
@ -27,22 +32,56 @@
// Qt includes // Qt includes
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QtGui/QMenu> #include <QtGui/QMenu>
#include <QtGui/QFileDialog>
namespace WorldEditor namespace WorldEditor
{ {
PrimitivesView::PrimitivesView(QWidget *parent) PrimitivesView::PrimitivesView(QWidget *parent)
: QTreeView(parent), : QTreeView(parent),
m_undoStack(0),
m_zoneBuilder(0),
m_primitivesTreeModel(0) m_primitivesTreeModel(0)
{ {
setContextMenuPolicy(Qt::DefaultContextMenu); setContextMenuPolicy(Qt::DefaultContextMenu);
m_deleteAction = new QAction("Delete", this); m_unloadAction = new QAction("Unload", this);
m_selectChildrenAction = new QAction("Select children", this); m_unloadAction->setEnabled(false);
m_helpAction = new QAction("Help", this);
m_showAction = new QAction("Show", this);
m_hideAction = new QAction("Hide", this);
m_saveAction = new QAction("Save", this);
m_saveAction->setEnabled(false);
m_saveAction->setIcon(QIcon(Core::Constants::ICON_SAVE));
m_saveAsAction = new QAction("Save As...", this);
m_saveAsAction->setIcon(QIcon(Core::Constants::ICON_SAVE_AS));
m_saveAsAction->setEnabled(false);
m_loadLandAction = new QAction("Load landscape file", this);
m_loadLandAction->setIcon(QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM));
m_loadPrimitiveAction = new QAction("Load primitive file", this);
m_loadPrimitiveAction->setIcon(QIcon("./old_ico/root.ico"));
m_newPrimitiveAction = new QAction("New primitive", this);
m_deleteAction = new QAction("Delete", this);
m_deleteAction->setEnabled(false);
m_selectChildrenAction = new QAction("Select children", this);
m_helpAction = new QAction("Help", this);
m_helpAction->setEnabled(false);
m_showAction = new QAction("Show", this);
m_showAction->setEnabled(false);
m_hideAction = new QAction("Hide", this);
m_hideAction->setEnabled(false);
connect(m_loadLandAction, SIGNAL(triggered()), this, SLOT(loadLandscape()));
connect(m_loadPrimitiveAction, SIGNAL(triggered()), this, SLOT(loadRootPrimitive()));
connect(m_newPrimitiveAction, SIGNAL(triggered()), this, SLOT(createRootPrimitive()));
connect(m_selectChildrenAction, SIGNAL(triggered()), this, SLOT(selectChildren()));
connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deletePrimitives())); connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deletePrimitives()));
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
@ -54,30 +93,116 @@ PrimitivesView::~PrimitivesView()
{ {
} }
void PrimitivesView::setUndoStack(QUndoStack *undoStack)
{
m_undoStack = undoStack;
}
void PrimitivesView::setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder)
{
m_zoneBuilder = zoneBuilder;
}
void PrimitivesView::setModel(PrimitivesTreeModel *model) void PrimitivesView::setModel(PrimitivesTreeModel *model)
{ {
QTreeView::setModel(model); QTreeView::setModel(model);
m_primitivesTreeModel = model; m_primitivesTreeModel = model;
} }
void PrimitivesView::deletePrimitives() void PrimitivesView::loadRootPrimitive()
{ {
QModelIndexList indexList = selectionModel()->selectedRows(); nlassert(m_undoStack);
nlassert(m_primitivesTreeModel);
// TODO: use QPersistentModelIndex for deleting several items QStringList fileNames = QFileDialog::getOpenFileNames(this,
m_primitivesTreeModel->deletePrimitiveWithoutUndo(indexList.first()); tr("Open NeL Ligo primitive file"), m_lastDir,
tr("All NeL Ligo primitive files (*.primitive)"));
setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty())
{
if (fileNames.count() > 1)
m_undoStack->beginMacro("Load primitive files");
Q_FOREACH(QString fileName, fileNames)
{
m_lastDir = QFileInfo(fileName).absolutePath();
m_undoStack->push(new LoadRootPrimitiveCommand(fileName, m_primitivesTreeModel));
}
if (fileNames.count() > 1)
m_undoStack->endMacro();
}
setCursor(Qt::ArrowCursor);
} }
void PrimitivesView::addNewPrimitive(int value) void PrimitivesView::loadLandscape()
{
nlassert(m_undoStack);
nlassert(m_zoneBuilder);
nlassert(m_primitivesTreeModel);
QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Open NeL Ligo land file"), m_lastDir,
tr("All NeL Ligo land files (*.land)"));
setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty())
{
if (fileNames.count() > 1)
m_undoStack->beginMacro("Load land files");
Q_FOREACH(QString fileName, fileNames)
{
m_lastDir = QFileInfo(fileName).absolutePath();
m_undoStack->push(new LoadLandscapeCommand(fileName, m_primitivesTreeModel, m_zoneBuilder));
}
if (fileNames.count() > 1)
m_undoStack->endMacro();
}
setCursor(Qt::ArrowCursor);
}
void PrimitivesView::createRootPrimitive()
{
nlassert(m_undoStack);
nlassert(m_primitivesTreeModel);
m_undoStack->push(new CreateRootPrimitiveCommand("NewPrimitive", m_primitivesTreeModel));
}
void PrimitivesView::selectChildren()
{ {
QModelIndexList indexList = selectionModel()->selectedRows(); QModelIndexList indexList = selectionModel()->selectedRows();
QModelIndex parentIndex = indexList.first();
const NLLIGO::CPrimitiveClass *primClass = m_primitivesTreeModel->primitiveClass(indexList.first()); selectionModel()->clearSelection();
selectChildren(parentIndex);
}
void PrimitivesView::deletePrimitives()
{
nlassert(m_undoStack);
nlassert(m_primitivesTreeModel);
QModelIndexList indexList = selectionModel()->selectedRows();
}
void PrimitivesView::addNewPrimitiveByClass(int value)
{
nlassert(m_undoStack);
nlassert(m_primitivesTreeModel);
QModelIndexList indexList = selectionModel()->selectedRows();
PrimitiveNode *node = static_cast<PrimitiveNode *>(indexList.first().internalPointer());
// Get class name // Get class name
QString className = primClass->DynamicChildren[value].ClassName.c_str(); QString className = node->primitiveClass()->DynamicChildren[value].ClassName.c_str();
m_primitivesTreeModel->newPrimitiveWithoutUndo(className, value, indexList.first()); m_undoStack->push(new AddPrimitiveByClassCommand(className, m_primitivesTreeModel->pathFromIndex(indexList.first()),
m_primitivesTreeModel));
} }
void PrimitivesView::generatePrimitives(int value) void PrimitivesView::generatePrimitives(int value)
@ -96,96 +221,153 @@ void PrimitivesView::contextMenuEvent(QContextMenuEvent *event)
return; return;
QMenu *popurMenu = new QMenu(this); QMenu *popurMenu = new QMenu(this);
popurMenu->addAction(m_deleteAction);
popurMenu->addAction(m_selectChildrenAction);
popurMenu->addAction(m_helpAction);
popurMenu->addSeparator();
popurMenu->addAction(m_showAction);
popurMenu->addAction(m_hideAction);
popurMenu->addSeparator();
QSignalMapper *addSignalMapper = new QSignalMapper(this);
QSignalMapper *generateSignalMapper = new QSignalMapper(this);
QSignalMapper *openSignalMapper = new QSignalMapper(this);
connect(addSignalMapper, SIGNAL(mapped(int)), this, SLOT(addNewPrimitive(int)));
connect(generateSignalMapper, SIGNAL(mapped(int)), this, SLOT(generatePrimitives(int)));
//connect(openSignalMapper, SIGNAL(mapped(int)), this, SLOT(openItem(int)));
if (indexList.size() == 1) if (indexList.size() == 1)
{ {
const NLLIGO::CPrimitiveClass *primClass = m_primitivesTreeModel->primitiveClass(indexList.first()); Node *node = static_cast<Node *>(indexList.first().internalPointer());
switch (node->type())
// What class is it ?
if (primClass && primClass->DynamicChildren.size())
{ {
popurMenu->addSeparator(); case Node::WorldEditNodeType:
fillMenu_WorldEdit(popurMenu);
// For each child, add a create method break;
for (size_t i = 0; i < primClass->DynamicChildren.size(); i++) case Node::RootPrimitiveNodeType:
{ fillMenu_RootPrimitive(popurMenu, indexList.first());
// Get class name break;
QString className = primClass->DynamicChildren[i].ClassName.c_str(); case Node::LandscapeNodeType:
fillMenu_Landscape(popurMenu);
// Get icon break;
QIcon icon(QString("./old_ico/%1.ico").arg(className)); case Node::PrimitiveNodeType:
fillMenu_Primitive(popurMenu, indexList.first());
// Create and add action in popur menu break;
QAction *action = popurMenu->addAction(icon, QString("Add %1").arg(className)); };
addSignalMapper->setMapping(action, i);
connect(action, SIGNAL(triggered()), addSignalMapper, SLOT(map()));
}
}
// What class is it ?
if (primClass && primClass->GeneratedChildren.size())
{
popurMenu->addSeparator();
// For each child, add a create method
for (size_t i = 0; i < primClass->GeneratedChildren.size(); i++)
{
// Get class name
QString childName = primClass->GeneratedChildren[i].ClassName.c_str();
// Create and add action in popur menu
QAction *action = popurMenu->addAction(QString("Generate %1").arg(childName));
generateSignalMapper->setMapping(action, i);
connect(generateSignalMapper, SIGNAL(triggered()), addSignalMapper, SLOT(map()));
}
}
/*
// What class is it ?
if (primClass)
{
// Look for files
std::vector<std::string> filenames;
// Filenames
buildFilenameVector (*Selection.front (), filenames);
// File names ?
if (!filenames.empty ())
{
// Add separator
popurMenu->addSeparator();
// Found ?
for (uint i = 0; i < filenames.size(); i++)
{
// Add a menu entry
pMenu->AppendMenu (MF_STRING, ID_EDIT_OPEN_FILE_BEGIN+i, ("Open "+NLMISC::CFile::getFilename (filenames[i])).c_str ());
}
}
}
*/
} }
popurMenu->exec(event->globalPos()); popurMenu->exec(event->globalPos());
delete popurMenu; delete popurMenu;
delete addSignalMapper;
delete generateSignalMapper;
delete openSignalMapper;
event->accept(); event->accept();
} }
void PrimitivesView::selectChildren(const QModelIndex &parent)
{
const int rowCount = model()->rowCount(parent);
for (int i = 0; i < rowCount; ++i)
{
QModelIndex childIndex = parent.child(i, 0);
selectionModel()->select(childIndex, QItemSelectionModel::Select);
selectChildren(childIndex);
}
}
void PrimitivesView::fillMenu_WorldEdit(QMenu *menu)
{
menu->addAction(m_unloadAction);
menu->addAction(m_saveAction);
menu->addAction(m_saveAsAction);
menu->addSeparator();
menu->addAction(m_loadLandAction);
menu->addAction(m_loadPrimitiveAction);
menu->addAction(m_newPrimitiveAction);
menu->addSeparator();
menu->addAction(m_helpAction);
}
void PrimitivesView::fillMenu_Landscape(QMenu *menu)
{
menu->addAction(m_deleteAction);
menu->addSeparator();
menu->addAction(m_showAction);
menu->addAction(m_hideAction);
}
void PrimitivesView::fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index)
{
menu->addAction(m_saveAction);
menu->addAction(m_saveAsAction);
fillMenu_Primitive(menu, index);
}
void PrimitivesView::fillMenu_Primitive(QMenu *menu, const QModelIndex &index)
{
menu->addAction(m_deleteAction);
menu->addAction(m_selectChildrenAction);
menu->addAction(m_helpAction);
menu->addSeparator();
menu->addAction(m_showAction);
menu->addAction(m_hideAction);
QSignalMapper *addSignalMapper = new QSignalMapper(menu);
QSignalMapper *generateSignalMapper = new QSignalMapper(menu);
QSignalMapper *openSignalMapper = new QSignalMapper(menu);
connect(addSignalMapper, SIGNAL(mapped(int)), this, SLOT(addNewPrimitiveByClass(int)));
connect(generateSignalMapper, SIGNAL(mapped(int)), this, SLOT(generatePrimitives(int)));
//connect(openSignalMapper, SIGNAL(mapped(int)), this, SLOT(openItem(int)));
PrimitiveNode *node = static_cast<PrimitiveNode *>(index.internalPointer());
const NLLIGO::CPrimitiveClass *primClass = node->primitiveClass();
// What class is it ?
if (primClass && primClass->DynamicChildren.size())
{
menu->addSeparator();
// For each child, add a create method
for (size_t i = 0; i < primClass->DynamicChildren.size(); i++)
{
// Get class name
QString className = primClass->DynamicChildren[i].ClassName.c_str();
// Get icon
QIcon icon(QString("./old_ico/%1.ico").arg(className));
// Create and add action in popur menu
QAction *action = menu->addAction(icon, QString("Add %1").arg(className));
addSignalMapper->setMapping(action, i);
connect(action, SIGNAL(triggered()), addSignalMapper, SLOT(map()));
}
}
// What class is it ?
if (primClass && primClass->GeneratedChildren.size())
{
menu->addSeparator();
// For each child, add a create method
for (size_t i = 0; i < primClass->GeneratedChildren.size(); i++)
{
// Get class name
QString childName = primClass->GeneratedChildren[i].ClassName.c_str();
// Create and add action in popur menu
QAction *action = menu->addAction(QString("Generate %1").arg(childName));
generateSignalMapper->setMapping(action, i);
connect(generateSignalMapper, SIGNAL(triggered()), addSignalMapper, SLOT(map()));
}
}
/*
// What class is it ?
if (primClass)
{
// Look for files
std::vector<std::string> filenames;
// Filenames
buildFilenameVector (*Selection.front (), filenames);
// File names ?
if (!filenames.empty ())
{
// Add separator
popurMenu->addSeparator();
// Found ?
for (uint i = 0; i < filenames.size(); i++)
{
// Add a menu entry
pMenu->AppendMenu (MF_STRING, ID_EDIT_OPEN_FILE_BEGIN+i, ("Open "+NLMISC::CFile::getFilename (filenames[i])).c_str ());
}
}
*/
}
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -28,11 +28,15 @@
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QtCore/QSignalMapper> #include <QtCore/QSignalMapper>
#include <QPersistentModelIndex> #include <QPersistentModelIndex>
#include <QtGui/QUndoStack>
namespace LandscapeEditor
{
class ZoneBuilderBase;
}
namespace WorldEditor namespace WorldEditor
{ {
class BaseTreeItem;
class PrimitivesTreeModel; class PrimitivesTreeModel;
/** /**
@ -48,23 +52,47 @@ public:
PrimitivesView(QWidget *parent = 0); PrimitivesView(QWidget *parent = 0);
~PrimitivesView(); ~PrimitivesView();
void setUndoStack(QUndoStack *undoStack);
void setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder);
virtual void setModel(PrimitivesTreeModel *model); virtual void setModel(PrimitivesTreeModel *model);
private Q_SLOTS: private Q_SLOTS:
void loadLandscape();
void loadRootPrimitive();
void createRootPrimitive();
void selectChildren();
void deletePrimitives(); void deletePrimitives();
void addNewPrimitive(int value); void addNewPrimitiveByClass(int value);
void generatePrimitives(int value); void generatePrimitives(int value);
void openItem(int value); void openItem(int value);
protected: protected:
void contextMenuEvent(QContextMenuEvent *event); void contextMenuEvent(QContextMenuEvent *event);
private:
void selectChildren(const QModelIndex &parent);
void fillMenu_WorldEdit(QMenu *menu);
void fillMenu_Landscape(QMenu *menu);
void fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index);
void fillMenu_Primitive(QMenu *menu, const QModelIndex &index);
QString m_lastDir;
QAction *m_unloadAction;
QAction *m_saveAction;
QAction *m_saveAsAction;
QAction *m_loadLandAction;
QAction *m_loadPrimitiveAction;
QAction *m_newPrimitiveAction;
QAction *m_deleteAction; QAction *m_deleteAction;
QAction *m_selectChildrenAction; QAction *m_selectChildrenAction;
QAction *m_helpAction; QAction *m_helpAction;
QAction *m_showAction; QAction *m_showAction;
QAction *m_hideAction; QAction *m_hideAction;
QUndoStack *m_undoStack;
LandscapeEditor::ZoneBuilderBase *m_zoneBuilder;
PrimitivesTreeModel *m_primitivesTreeModel; PrimitivesTreeModel *m_primitivesTreeModel;
}; };

View file

@ -1,5 +1,4 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> // Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by> // Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -17,31 +16,211 @@
// Project includes // Project includes
#include "world_editor_actions.h" #include "world_editor_actions.h"
#include "world_editor_misc.h"
#include "primitive_item.h"
// Lanscape Editor plugin
#include "../landscape_editor/builder_zone_base.h"
// STL includes
#include <string>
// NeL includes // NeL includes
#include <nel/misc/debug.h> #include <nel/misc/debug.h>
#include <nel/misc/path.h>
#include <nel/ligo/primitive_utils.h>
#include <nel/ligo/primitive.h>
#include <nel/misc/file.h>
// Qt includes // Qt includes
#include <QModelIndex>
namespace WorldEditor namespace WorldEditor
{ {
OpenLandscapeCommand::OpenLandscapeCommand(const QString &fileName, QUndoCommand *parent) CreateWorldCommand::CreateWorldCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent), : QUndoCommand(parent),
m_fileName(fileName) m_fileName(fileName),
m_model(model)
{
setText("Create new world");
}
CreateWorldCommand::~CreateWorldCommand()
{ {
} }
OpenLandscapeCommand::~OpenLandscapeCommand() void CreateWorldCommand::undo()
{
m_model->deleteWorldEditNode();
}
void CreateWorldCommand::redo()
{
m_model->createWorldEditNode(m_fileName);
}
LoadLandscapeCommand::LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model,
LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent)
: QUndoCommand(parent),
m_id(-1),
m_fileName(fileName),
m_model(model),
m_zoneBuilder(zoneBuilder)
{
setText("Load land file");
}
LoadLandscapeCommand::~LoadLandscapeCommand()
{ {
} }
void OpenLandscapeCommand::undo() void LoadLandscapeCommand::undo()
{
m_zoneBuilder->deleteZoneRegion(m_id);
m_model->deleteNode(landIndex);
}
void LoadLandscapeCommand::redo()
{
if (m_id == -1)
m_id = m_zoneBuilder->loadZoneRegion(m_fileName);
else
m_zoneBuilder->loadZoneRegion(m_fileName, m_id);
landIndex = m_model->createLandscapeNode(m_fileName);
}
CreateRootPrimitiveCommand::CreateRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent),
m_fileName(fileName),
m_model(model)
{
setText("Create new primitive");
}
CreateRootPrimitiveCommand::~CreateRootPrimitiveCommand()
{ {
} }
void OpenLandscapeCommand::redo() void CreateRootPrimitiveCommand::undo()
{ {
QModelIndex index = m_model->pathToIndex(m_rootPrimIndex);
RootPrimitiveNode *node = static_cast<RootPrimitiveNode *>(index.internalPointer());
delete node->primitives();
m_model->deleteNode(m_rootPrimIndex);
}
void CreateRootPrimitiveCommand::redo()
{
NLLIGO::CPrimitives *newRootPrim = new NLLIGO::CPrimitives();
m_rootPrimIndex = m_model->createRootPrimitiveNode(m_fileName, newRootPrim);
}
LoadRootPrimitiveCommand::LoadRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent),
m_fileName(fileName),
m_model(model)
{
setText("Load primitive file");
}
LoadRootPrimitiveCommand::~LoadRootPrimitiveCommand()
{
}
void LoadRootPrimitiveCommand::undo()
{
QModelIndex index = m_model->pathToIndex(m_rootPrimIndex);
RootPrimitiveNode *node = static_cast<RootPrimitiveNode *>(index.internalPointer());
delete node->primitives();
m_model->deleteNode(m_rootPrimIndex);
}
void LoadRootPrimitiveCommand::redo()
{
NLLIGO::CPrimitives *primitives = new NLLIGO::CPrimitives();
// set the primitive context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = primitives;
NLLIGO::loadXmlPrimitiveFile(*primitives, m_fileName.toStdString(), *NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig);
// unset the context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL;
// Initialize default values
Utils::recursiveUpdateDefaultValues(primitives->RootNode);
// Check property types
if (Utils::recursiveUpdateDefaultValues(primitives->RootNode))
{
nlwarning("In file (%s) : Some primitives have been modified to initialise their default values\nor to change their properties type.", m_fileName.toStdString().c_str());
}
m_rootPrimIndex = m_model->createRootPrimitiveNode(m_fileName, primitives);
}
AddPrimitiveByClassCommand::AddPrimitiveByClassCommand(const QString &className, const Path &parentIndex,
PrimitivesTreeModel *model, QUndoCommand *parent)
: QUndoCommand(parent),
m_className(className),
m_parentIndex(parentIndex),
m_model(model)
{
setText(QString("Add %1").arg(m_className));
}
AddPrimitiveByClassCommand::~AddPrimitiveByClassCommand()
{
}
void AddPrimitiveByClassCommand::undo()
{
QModelIndex index = m_model->pathToIndex(m_newPrimIndex);
PrimitiveNode *node = static_cast<PrimitiveNode *>(index.internalPointer());
// set the primitive context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = node->rootPrimitiveNode()->primitives();
Utils::deletePrimitive(node->primitive());
// unset the context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL;
m_model->deleteNode(m_newPrimIndex);
}
void AddPrimitiveByClassCommand::redo()
{
QModelIndex parentIndex = m_model->pathToIndex(m_parentIndex);
PrimitiveNode *parentNode = static_cast<PrimitiveNode *>(parentIndex.internalPointer());
const NLLIGO::CPrimitiveClass *primClass = parentNode->primitiveClass();
float delta = 10;
int id = 0;
while (primClass->DynamicChildren[id].ClassName != m_className.toStdString())
++id;
// set the primitive context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = parentNode->rootPrimitiveNode()->primitives();
QString namePrimititve = QString("%1_%2").arg(m_className).arg(parentNode->childCount());
NLLIGO::IPrimitive *newPrimitive = Utils::createPrimitive(m_className.toStdString().c_str(), namePrimititve.toStdString().c_str(),
NLMISC::CVector(), delta, primClass->DynamicChildren[id].Parameters, parentNode->primitive());
// unset the context
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL;
m_newPrimIndex = m_model->createPrimitiveNode(newPrimitive, m_parentIndex);
} }
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -1,5 +1,4 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> // Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by> // Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -19,6 +18,7 @@
#define WORLD_EDITOR_ACTIONS_H #define WORLD_EDITOR_ACTIONS_H
// Project includes // Project includes
#include "primitives_model.h"
// NeL includes // NeL includes
@ -27,20 +27,110 @@
#include <QtGui/QGraphicsScene> #include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsItem> #include <QtGui/QGraphicsItem>
namespace LandscapeEditor
{
class ZoneBuilderBase;
}
namespace WorldEditor namespace WorldEditor
{ {
class OpenLandscapeCommand: public QUndoCommand /**
@class CreateWorldCommand
@brief
@details
*/
class CreateWorldCommand: public QUndoCommand
{ {
public: public:
OpenLandscapeCommand(const QString &fileName, QUndoCommand *parent = 0); CreateWorldCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent = 0);
virtual ~OpenLandscapeCommand(); virtual ~CreateWorldCommand();
virtual void undo(); virtual void undo();
virtual void redo(); virtual void redo();
private: private:
QString m_fileName; const QString m_fileName;
PrimitivesTreeModel *const m_model;
};
/**
@class LoadLandscapeCommand
@brief
@details
*/
class LoadLandscapeCommand: public QUndoCommand
{
public:
LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model,
LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent = 0);
virtual ~LoadLandscapeCommand();
virtual void undo();
virtual void redo();
private:
Path landIndex;
int m_id;
const QString m_fileName;
PrimitivesTreeModel *const m_model;
LandscapeEditor::ZoneBuilderBase *const m_zoneBuilder;
};
class CreateRootPrimitiveCommand: public QUndoCommand
{
public:
CreateRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent = 0);
virtual ~CreateRootPrimitiveCommand();
virtual void undo();
virtual void redo();
private:
const QString m_fileName;
Path m_rootPrimIndex;
PrimitivesTreeModel *const m_model;
};
/**
@class LoadPrimitiveCommand
@brief
@details
*/
class LoadRootPrimitiveCommand: public QUndoCommand
{
public:
LoadRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent = 0);
virtual ~LoadRootPrimitiveCommand();
virtual void undo();
virtual void redo();
private:
Path m_rootPrimIndex;
const QString m_fileName;
PrimitivesTreeModel *const m_model;
};
/**
@class AddPrimitiveCommand
@brief
@details
*/
class AddPrimitiveByClassCommand: public QUndoCommand
{
public:
AddPrimitiveByClassCommand(const QString &className, const Path &parentIndex,
PrimitivesTreeModel *model, QUndoCommand *parent = 0);
virtual ~AddPrimitiveByClassCommand();
virtual void undo();
virtual void redo();
private:
const QString m_className;
Path m_parentIndex, m_newPrimIndex;
PrimitivesTreeModel *m_model;
}; };
} /* namespace WorldEditor */ } /* namespace WorldEditor */

View file

@ -1,5 +1,4 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> // Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by> // Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -20,6 +19,8 @@
#include "world_editor_constants.h" #include "world_editor_constants.h"
#include "primitives_model.h" #include "primitives_model.h"
#include "world_editor_scene.h" #include "world_editor_scene.h"
#include "world_editor_misc.h"
#include "world_editor_actions.h"
// Core // Core
#include "../core/icore.h" #include "../core/icore.h"
@ -28,17 +29,12 @@
// Lanscape Editor plugin // Lanscape Editor plugin
#include "../landscape_editor/builder_zone_base.h" #include "../landscape_editor/builder_zone_base.h"
//#include "../landscape_editor/project_settings_dialog.h"
// NeL includes // NeL includes
#include <nel/misc/path.h> #include <nel/misc/path.h>
#include <nel/ligo/primitive_utils.h> #include <nel/ligo/primitive_utils.h>
#include <nel/ligo/primitive.h> #include <nel/ligo/primitive.h>
#include <nel/ligo/ligo_config.h>
#include <nel/misc/file.h>
#include <nel/misc/i_xml.h>
#include <nel/ligo/primitive_utils.h>
#include <nel/ligo/primitive.h>
// Qt includes // Qt includes
#include <QtCore/QSettings> #include <QtCore/QSettings>
@ -47,7 +43,6 @@
namespace WorldEditor namespace WorldEditor
{ {
QString _lastDir;
WorldEditorWindow::WorldEditorWindow(QWidget *parent) WorldEditorWindow::WorldEditorWindow(QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
@ -57,9 +52,9 @@ WorldEditorWindow::WorldEditorWindow(QWidget *parent)
m_ui.setupUi(this); m_ui.setupUi(this);
m_undoStack = new QUndoStack(this); m_undoStack = new QUndoStack(this);
m_worldEditorScene = new WorldEditorScene(160, this); m_worldEditorScene = new WorldEditorScene(NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->CellSize, this);
m_zoneBuilderBase = new LandscapeEditor::ZoneBuilderBase(m_worldEditorScene); m_zoneBuilderBase = new LandscapeEditor::ZoneBuilderBase(m_worldEditorScene);
m_worldEditorScene->setZoneBuilder(m_zoneBuilderBase); m_worldEditorScene->setZoneBuilder(m_zoneBuilderBase);
m_ui.graphicsView->setScene(m_worldEditorScene); m_ui.graphicsView->setScene(m_worldEditorScene);
@ -78,12 +73,16 @@ WorldEditorWindow::WorldEditorWindow(QWidget *parent)
m_primitivesModel = new PrimitivesTreeModel(); m_primitivesModel = new PrimitivesTreeModel();
m_ui.treePrimitivesView->setModel(m_primitivesModel); m_ui.treePrimitivesView->setModel(m_primitivesModel);
// TODO: ?
m_ui.treePrimitivesView->setUndoStack(m_undoStack);
m_ui.treePrimitivesView->setZoneBuilder(m_zoneBuilderBase);
createMenus(); createMenus();
createToolBars(); createToolBars();
readSettings(); readSettings();
connect(m_ui.newWorldEditAction, SIGNAL(triggered()), this, SLOT(newWorldEditFile())); connect(m_ui.newWorldEditAction, SIGNAL(triggered()), this, SLOT(newWorldEditFile()));
connect(m_ui.saveWorldEditAction, SIGNAL(triggered()), this, SLOT(saveAllWorldEditFiles())); connect(m_ui.saveWorldEditAction, SIGNAL(triggered()), this, SLOT(saveWorldEditFile()));
} }
@ -101,33 +100,64 @@ QUndoStack *WorldEditorWindow::undoStack() const
void WorldEditorWindow::open() void WorldEditorWindow::open()
{ {
QStringList fileNames = QFileDialog::getOpenFileNames(this, QString fileName = QFileDialog::getOpenFileName(this,
tr("Open NeL Ligo primitive file"), _lastDir, tr("Open NeL World Edit file"), m_lastDir,
tr("All NeL Ligo primitive files (*.primitive)")); tr("All NeL World Editor file (*.worldedit)"));
setCursor(Qt::WaitCursor); setCursor(Qt::WaitCursor);
if (!fileNames.isEmpty()) if (!fileName.isEmpty())
{ {
QStringList list = fileNames; m_lastDir = QFileInfo(fileName).absolutePath();
_lastDir = QFileInfo(list.front()).absolutePath(); loadWorldEditFile(fileName);
Q_FOREACH(QString fileName, fileNames)
{
loadPrimitive(fileName);
}
} }
setCursor(Qt::ArrowCursor); setCursor(Qt::ArrowCursor);
} }
void WorldEditorWindow::loadPrimitive(const QString &fileName) void WorldEditorWindow::loadWorldEditFile(const QString &fileName)
{
Utils::WorldEditList worldEditList;
if (!Utils::loadWorldEditFile(fileName.toStdString(), worldEditList))
{
return;
}
m_undoStack->beginMacro(QString("Load %1").arg(fileName));
checkCurrentWorld();
m_undoStack->push(new CreateWorldCommand(fileName, m_primitivesModel));
for (size_t i = 0; i < worldEditList.size(); ++i)
{
switch (worldEditList[i].first)
{
case Utils::DataDirectoryType:
m_zoneBuilderBase->init(QString(worldEditList[i].second.c_str()), true);
break;
case Utils::ContextType:
break;
case Utils::LandscapeType:
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));
break;
};
}
m_undoStack->endMacro();
}
void WorldEditorWindow::checkCurrentWorld()
{ {
m_primitivesModel->loadPrimitive(fileName);
} }
void WorldEditorWindow::newWorldEditFile() void WorldEditorWindow::newWorldEditFile()
{ {
checkCurrentWorld();
m_undoStack->push(new CreateWorldCommand("NewWorldEdit", m_primitivesModel));
} }
void WorldEditorWindow::saveAllWorldEditFiles() void WorldEditorWindow::saveWorldEditFile()
{ {
} }

View file

@ -1,5 +1,4 @@
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> // Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by> // Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -50,7 +49,7 @@ public Q_SLOTS:
private Q_SLOTS: private Q_SLOTS:
void newWorldEditFile(); void newWorldEditFile();
void saveAllWorldEditFiles(); void saveWorldEditFile();
void openProjectSettings(); void openProjectSettings();
private: private:
@ -59,7 +58,10 @@ private:
void readSettings(); void readSettings();
void writeSettings(); void writeSettings();
void loadPrimitive(const QString &fileName); void loadWorldEditFile(const QString &fileName);
void checkCurrentWorld();
QString m_lastDir;
PrimitivesTreeModel *m_primitivesModel; PrimitivesTreeModel *m_primitivesModel;
QUndoStack *m_undoStack; QUndoStack *m_undoStack;

View file

@ -20,7 +20,17 @@
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="LandscapeEditor::LandscapeView" name="graphicsView"/> <widget class="LandscapeEditor::LandscapeView" name="graphicsView">
<property name="dragMode">
<enum>QGraphicsView::RubberBandDrag</enum>
</property>
<property name="transformationAnchor">
<enum>QGraphicsView::AnchorUnderMouse</enum>
</property>
<property name="resizeAnchor">
<enum>QGraphicsView::AnchorUnderMouse</enum>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>