From b74413dd55d5cf7699716bdb37d048d70feb8ff4 Mon Sep 17 00:00:00 2001 From: dnk-88 Date: Wed, 27 Jul 2011 19:04:46 +0300 Subject: [PATCH] Changed: #1302 Added operations creating and deleting primitives without undo/redo. --HG-- branch : gsoc2011-worldeditorqt --- .../src/plugins/world_editor/CMakeLists.txt | 1 + .../plugins/world_editor/primitive_item.cpp | 40 +- .../src/plugins/world_editor/primitive_item.h | 13 +- .../plugins/world_editor/primitives_model.cpp | 135 ++++- .../plugins/world_editor/primitives_model.h | 28 +- .../plugins/world_editor/primitives_view.cpp | 197 +++++++ .../plugins/world_editor/primitives_view.h | 74 +++ .../world_editor/world_editor_misc.cpp | 494 ++++++++++++++++++ .../plugins/world_editor/world_editor_misc.h | 55 ++ .../world_editor/world_editor_window.cpp | 28 +- .../world_editor/world_editor_window.h | 2 + .../world_editor/world_editor_window.ui | 23 +- 12 files changed, 1051 insertions(+), 39 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt index c8b034444..8b51838d7 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt @@ -12,6 +12,7 @@ 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 primitives_model.h + primitives_view.h ) SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp index 9ec95bdaa..300a30631 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp @@ -16,9 +16,14 @@ // Project includes #include "primitive_item.h" +#include "world_editor_misc.h" + +// NeL includes +#include // Qt includes -#include +#include +#include namespace WorldEditor { @@ -45,6 +50,11 @@ void BaseTreeItem::appendChild(BaseTreeItem *item) m_childItems.append(item); } +void BaseTreeItem::deleteChild(int row) +{ + delete m_childItems.takeAt(row); +} + BaseTreeItem *BaseTreeItem::child(int row) { return m_childItems.value(row); @@ -104,12 +114,13 @@ PrimitiveItem::PrimitiveItem(NLLIGO::IPrimitive *primitive, BaseTreeItem *parent m_primitive->getPropertyByName("class", className); // Set Icon - QIcon icon(QString("./old_ico/%1.ico").arg(className.c_str())); - if (primitive->getParent() == NULL) - icon = QIcon("./old_ico/root.ico"); - if (icon.isNull()) + QString nameIcon = QString("./old_ico/%1.ico").arg(className.c_str()); + QIcon icon(nameIcon); + if (!QFile::exists(nameIcon)) { - if (primitive->getNumChildren() == 0) + if (primitive->getParent() == NULL) + icon = QIcon("./old_ico/root.ico"); + else if (primitive->getNumChildren() == 0) icon = QIcon("./old_ico/property.ico"); else icon = QIcon("./old_ico/folder_h.ico"); @@ -127,18 +138,29 @@ PrimitiveItem::~PrimitiveItem() { } -PrimitivesItem::PrimitivesItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent) +NLLIGO::IPrimitive *PrimitiveItem::primitive() const +{ + return m_primitive; +} + +const NLLIGO::CPrimitiveClass *PrimitiveItem::primitiveClass() const +{ + return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*m_primitive); +} + + +RootPrimitiveItem::RootPrimitiveItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent) : PrimitiveItem(primitives->RootNode, parent), m_primitives(primitives) { setData(1, name); } /* -PrimitivesItem::PrimitivesItem(const PrimitiveItem &other) +RootPrimitiveItem::RootPrimitiveItem(const RootPrimitiveItem &other) { } */ -PrimitivesItem::~PrimitivesItem() +RootPrimitiveItem::~RootPrimitiveItem() { } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h index 26ca70670..5d00e6c92 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h @@ -21,6 +21,7 @@ // NeL includes #include +#include // Qt includes #include @@ -43,6 +44,7 @@ public: virtual ~BaseTreeItem(); void appendChild(BaseTreeItem *child); + void deleteChild(int row); BaseTreeItem *child(int row); int childCount() const; @@ -74,6 +76,9 @@ public: PrimitiveItem(const PrimitiveItem &other); virtual ~PrimitiveItem(); + NLLIGO::IPrimitive *primitive() const; + const NLLIGO::CPrimitiveClass *primitiveClass() const; + private: NLLIGO::IPrimitive *m_primitive; }; @@ -83,12 +88,12 @@ private: @brief @details */ -class PrimitivesItem: public PrimitiveItem +class RootPrimitiveItem: public PrimitiveItem { public: - PrimitivesItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent); - PrimitivesItem(const PrimitiveItem &other); - virtual ~PrimitivesItem(); + RootPrimitiveItem(const QString &name, NLLIGO::CPrimitives *primitives, BaseTreeItem *parent); + RootPrimitiveItem(const RootPrimitiveItem &other); + virtual ~RootPrimitiveItem(); private: NLLIGO::CPrimitives *m_primitives; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp index 8c5af6229..7a41822ab 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp @@ -14,14 +14,18 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#include -#include -#include - -#include - +// Project includes #include "primitive_item.h" #include "primitives_model.h" +#include "world_editor_misc.h" + +// NeL includes +#include +#include +#include + +// Qt includes +#include namespace WorldEditor { @@ -136,11 +140,77 @@ int PrimitivesTreeModel::rowCount(const QModelIndex &parent) const return parentItem->childCount(); } -void PrimitivesTreeModel::addPrimitives(const QString &name, NLLIGO::CPrimitives *primitives) +NLLIGO::IPrimitive *PrimitivesTreeModel::primitive(const QModelIndex &index) +{ + NLLIGO::IPrimitive *prim = 0; + if (index.isValid()) + { + PrimitiveItem *item = static_cast(index.internalPointer()); + prim = item->primitive(); + } + return prim; +} + +const NLLIGO::CPrimitiveClass *PrimitivesTreeModel::primitiveClass(const QModelIndex &index) +{ + if (index.isValid()) + { + NLLIGO::IPrimitive *prim = primitive(index); + return ligoConfig()->getPrimitiveClass(*prim); + } + return 0; +} + +void PrimitivesTreeModel::loadPrimitive(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(); - PrimitivesItem *newPrimitives = new PrimitivesItem(name, primitives, m_rootItem); + + // Create root primitive + RootPrimitiveItem *newPrimitives = new RootPrimitiveItem(name, primitives, m_rootItem); m_rootItem->appendChild(newPrimitives); + + // Scan childs items and add in tree model for (uint i = 0; i < primitives->RootNode->getNumChildren(); ++i) { NLLIGO::IPrimitive *childPrim; @@ -150,17 +220,33 @@ void PrimitivesTreeModel::addPrimitives(const QString &name, NLLIGO::CPrimitives endResetModel(); } -void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem *parent) +void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, const QModelIndex &parentIndex) { -// const NLLIGO::CPrimitiveClass *primClass = NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*prim); -// nlassert (primClass); -// if (primClass->Type == NLLIGO::CPrimitiveClass::Alias) -// return; - if (prim->getClassName() == "CPrimAlias") - return; + PrimitiveItem *parent = static_cast(parentIndex.internalPointer()); + // Add in tree model + beginInsertRows(parentIndex, parent->childCount(), parent->childCount()); PrimitiveItem *newItem = new PrimitiveItem(prim, parent); parent->appendChild(newItem); + endInsertRows(); + + // Scan childs items and add in tree model + QModelIndex childIndex = index(parent->childCount() - 1, 0, parentIndex); + for (uint i = 0; i < prim->getNumChildren(); ++i) + { + NLLIGO::IPrimitive *childPrim; + prim->getChild(childPrim, i); + scanPrimitive(childPrim, childIndex); + } +} + +void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem *parent) +{ + // Add in tree model + PrimitiveItem *newItem = new PrimitiveItem(prim, parent); + parent->appendChild(newItem); + + // Scan childs items and add in tree model for (uint i = 0; i < prim->getNumChildren(); ++i) { NLLIGO::IPrimitive *childPrim; @@ -169,4 +255,23 @@ void PrimitivesTreeModel::scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem * } } +void PrimitivesTreeModel::removeRows(int position, const QModelIndex &parent) +{ + BaseTreeItem *item = static_cast(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(parent.internalPointer())->deleteChild(position); + endRemoveRows(); +} + +NLLIGO::CLigoConfig *PrimitivesTreeModel::ligoConfig() const +{ + return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig; +} + } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h index 5098d1e5e..ab4581a30 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h @@ -18,8 +18,13 @@ #ifndef PRIMITIVES_MODEL_H #define PRIMITIVES_MODEL_H +// NeL includes +#include #include +#include +#include +// Qt includes #include #include #include @@ -28,6 +33,7 @@ namespace WorldEditor { class BaseTreeItem; +class PrimitiveItem; /** @class PrimitivesTreeModel @@ -52,11 +58,31 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; - void addPrimitives(const QString &name, NLLIGO::CPrimitives *primitives); + // Get primitive + NLLIGO::IPrimitive *primitive(const QModelIndex &index); + + // Get primitive class + const NLLIGO::CPrimitiveClass *primitiveClass(const QModelIndex &index); + + // Load primitive from file + void loadPrimitive(const QString &fileName); + + // Create new primitive and add in tree model + void newPrimitiveWithoutUndo(const QString &className, uint id, const QModelIndex &parent); + + void deletePrimitiveWithoutUndo(const QModelIndex &index); + + NLLIGO::CLigoConfig *ligoConfig() const; private: + // Add root primitive in tree model and add all its sub-items. + void addRootPrimitive(const QString &name, NLLIGO::CPrimitives *primitives); + + void scanPrimitive(NLLIGO::IPrimitive *prim, const QModelIndex &parentIndex); void scanPrimitive(NLLIGO::IPrimitive *prim, BaseTreeItem *parent = 0); + void removeRows(int position, const QModelIndex &parent); + BaseTreeItem *m_rootItem; }; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp new file mode 100644 index 000000000..2b36c7446 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp @@ -0,0 +1,197 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 . + +// Project includes +#include "primitives_view.h" +//#include "primitive_item.h" +#include "primitives_model.h" + +// NeL includes +#include +#include +#include + +// Qt includes +#include +#include + +namespace WorldEditor +{ + +PrimitivesView::PrimitivesView(QWidget *parent) + : QTreeView(parent), + m_primitivesTreeModel(0) +{ + setContextMenuPolicy(Qt::DefaultContextMenu); + + m_deleteAction = new QAction("Delete", this); + m_selectChildrenAction = new QAction("Select children", this); + m_helpAction = new QAction("Help", this); + m_showAction = new QAction("Show", this); + m_hideAction = new QAction("Hide", this); + + connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deletePrimitives())); + + connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(clickedItem(QModelIndex))); + +#ifdef Q_OS_DARWIN + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); +#endif +} + +PrimitivesView::~PrimitivesView() +{ +} + +void PrimitivesView::setModel(PrimitivesTreeModel *model) +{ + QTreeView::setModel(model); + m_primitivesTreeModel = model; +} + +void PrimitivesView::clickedItem(const QModelIndex &index) +{ +} + +void PrimitivesView::deletePrimitives() +{ + QModelIndexList indexList = selectionModel()->selectedRows(); + + // TODO: use QPersistentModelIndex for deleting several items + m_primitivesTreeModel->deletePrimitiveWithoutUndo(indexList.first()); +} + +void PrimitivesView::addNewPrimitive(int value) +{ + QModelIndexList indexList = selectionModel()->selectedRows(); + + const NLLIGO::CPrimitiveClass *primClass = m_primitivesTreeModel->primitiveClass(indexList.first()); + + // Get class name + QString className = primClass->DynamicChildren[value].ClassName.c_str(); + + m_primitivesTreeModel->newPrimitiveWithoutUndo(className, value, indexList.first()); +} + +void PrimitivesView::generatePrimitives(int value) +{ +} + +void PrimitivesView::openItem(int value) +{ +} + +void PrimitivesView::contextMenuEvent(QContextMenuEvent *event) +{ + QWidget::contextMenuEvent(event); + QModelIndexList indexList = selectionModel()->selectedRows(); + if (indexList.size() == 0) + return; + + 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) + { + const NLLIGO::CPrimitiveClass *primClass = m_primitivesTreeModel->primitiveClass(indexList.first()); + + // What class is it ? + if (primClass && primClass->DynamicChildren.size()) + { + popurMenu->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 = 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 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()); + delete popurMenu; + delete addSignalMapper; + delete generateSignalMapper; + delete openSignalMapper; + event->accept(); +} + +} /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h new file mode 100644 index 000000000..0cfbe0318 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 . + + +#ifndef PRIMITIVES_VIEW_H +#define PRIMITIVES_VIEW_H + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include + +namespace WorldEditor +{ + +class BaseTreeItem; +class PrimitivesTreeModel; + +/** +@class PrimitivesView +@brief +@details +*/ +class PrimitivesView : public QTreeView +{ + Q_OBJECT + +public: + PrimitivesView(QWidget *parent = 0); + ~PrimitivesView(); + + virtual void setModel(PrimitivesTreeModel *model); + +private Q_SLOTS: + void clickedItem(const QModelIndex &index); + void deletePrimitives(); + void addNewPrimitive(int value); + void generatePrimitives(int value); + void openItem(int value); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + + QAction *m_deleteAction; + QAction *m_selectChildrenAction; + QAction *m_helpAction; + QAction *m_showAction; + QAction *m_hideAction; + + PrimitivesTreeModel *m_primitivesTreeModel; +}; + +} /* namespace WorldEditor */ + +#endif // PRIMITIVES_VIEW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp new file mode 100644 index 000000000..824fe8be6 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp @@ -0,0 +1,494 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 . + +// Project includes +#include "world_editor_misc.h" + +// NeL includes +#include +#include + +// Qt includes + +namespace WorldEditor +{ + +uint32 getUniqueId() +{ + // Wait 1 ms + sint64 time = NLMISC::CTime::getLocalTime (); + sint64 time2; + while ((time2 = NLMISC::CTime::getLocalTime ()) == time) + { + } + + return (uint32)time2; +} + +NLLIGO::IPrimitive *getRootPrimitive(NLLIGO::IPrimitive *primitive) +{ + nlassert(primitive); + + if (primitive->getParent() == NULL) + return primitive; + else + return getRootPrimitive(primitive->getParent()); +} + +void initPrimitiveParameters(const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, + const std::vector &initParameters) +{ + // Other parameters + for (uint p = 0; p < initParameters.size(); ++p) + { + // The property + const NLLIGO::CPrimitiveClass::CInitParameters ¶meter = initParameters[p]; + + // Look for it in the class + uint cp; + for (cp = 0; cp < primClass.Parameters.size(); ++cp) + { + // Good one ? + if (primClass.Parameters[cp].Name == initParameters[p].Name) + break; + } + + // The primitive type + NLLIGO::CPrimitiveClass::CParameter::TType type; + + // Found ? + if (cp < primClass.Parameters.size()) + type = primClass.Parameters[cp].Type; + + // Name ? + if (initParameters[p].Name == "name") + type = NLLIGO::CPrimitiveClass::CParameter::String; + + // Continue ? + if (cp 1) + nlerror("Warning: parameter (%s) in class name (%s) has more than 1 default value (%d).", + parameter.Name.c_str(), primClass.Name.c_str(), parameter.DefaultValue.size()); + + if ((cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) + || parameter.DefaultValue[0].GenID) + { + // Remove this property + primitive.removePropertyByName(parameter.Name.c_str()); + + // Add this property + primitive.addPropertyByName(parameter.Name.c_str(), + new NLLIGO::CPropertyString((parameter.DefaultValue[0].GenID ? NLMISC::toString(getUniqueId()) : "").c_str ())); + } + break; + } + case NLLIGO::CPrimitiveClass::CParameter::ConstStringArray: + case NLLIGO::CPrimitiveClass::CParameter::StringArray: + { + bool Visible = false; + if (cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) + { + Visible = true; + } + for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) + { + // Generate a unique id ? + if (parameter.DefaultValue[i].GenID) + { + Visible = true; + } + } + if (Visible) + { + // Remove this property + primitive.removePropertyByName (parameter.Name.c_str()); + + // Add this property + NLLIGO::CPropertyStringArray *str = new NLLIGO::CPropertyStringArray(); + str->StringArray.resize (parameter.DefaultValue.size()); + for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) + { + // Generate a unique id ? + if (parameter.DefaultValue[i].GenID) + { + str->StringArray[i] = NLMISC::toString(getUniqueId()); + } + else + { + str->StringArray[i] = ""; + } + } + primitive.addPropertyByName(parameter.Name.c_str(), str); + } + break; + } + } + } + } + else + { + // Some feedback + nlerror("Warning: parameter (%s) doesn't exist in class (%s).", + initParameters[p].Name.c_str(), primClass.Name.c_str()); + } + } +} + +NLLIGO::IPrimitive *createPrimitive(const char *className, const char *primName, + const NLMISC::CVector &initPos, float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent) +{ + // Get the prim class + const NLLIGO::CPrimitiveClass *primClass = NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(className); + if (primClass) + { + // Create the base primitive + NLLIGO::IPrimitive *primitive = NULL; + switch (primClass->Type) + { + case NLLIGO::CPrimitiveClass::Node: + primitive = new NLLIGO::CPrimNode; + break; + case NLLIGO::CPrimitiveClass::Point: + { + NLLIGO::CPrimPoint *point = new NLLIGO::CPrimPoint; + primitive = point; + point->Point.CVector::operator = (initPos); + } + break; + case NLLIGO::CPrimitiveClass::Path: + primitive = new NLLIGO::CPrimPath; + break; + case NLLIGO::CPrimitiveClass::Zone: + primitive = new NLLIGO::CPrimZone; + break; + case NLLIGO::CPrimitiveClass::Alias: + primitive = new NLLIGO::CPrimAlias; + break; + case NLLIGO::CPrimitiveClass::Bitmap: + primitive = new NLLIGO::CPrimNode; + break; + } + nlassert(primitive); + + // Add properties + primitive->addPropertyByName("class", new NLLIGO::CPropertyString(className)); + primitive->addPropertyByName("name", new NLLIGO::CPropertyString(primName, primName[0] == 0)); + + // Init with default parameters + std::vector tempParam; + tempParam.reserve(primClass->Parameters.size()); + for (size_t i = 0; i < primClass->Parameters.size(); i++) + tempParam.push_back (primClass->Parameters[i]); + initPrimitiveParameters (*primClass, *primitive, tempParam); + + // Init with option parameters + initPrimitiveParameters(*primClass, *primitive, initParameters); + + parent->insertChild(primitive); + /* + // Insert the primitive + insertPrimitive (locator, primitive); + */ + // The new pos + NLMISC::CVector newPos = initPos; + newPos.x += deltaPos; + + // Create static children + uint c; + for (c = 0; c < primClass->StaticChildren.size(); c++) + { + // The child ref + const NLLIGO::CPrimitiveClass::CChild &child = primClass->StaticChildren[c]; + + // Create the child + const NLLIGO::IPrimitive *childPrim = createPrimitive(child.ClassName.c_str(), child.Name.c_str(), + newPos, deltaPos, primClass->StaticChildren[c].Parameters, primitive); + + // The new pos + newPos.y += deltaPos; + } + + // Canceled ? + if (c < primClass->StaticChildren.size()) + { + deletePrimitive(primitive); + return NULL; + } + + // Prim file ? + if (primClass->Type == NLLIGO::CPrimitiveClass::Bitmap) + { + // Create a dialog file + //CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", TRUE, primClass->FileExtension.c_str (), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, + // (primClass->FileType+" (*."+primClass->FileExtension+")|*."+primClass->FileExtension+"|All Files (*.*)|*.*||").c_str (), getMainFrame ()); + //if (dialog.DoModal() == IDOK) + //{ + // Save filename + // static_cast(primitive)->init(dialog.GetPathName ()); + //} + } + + // Continue ? + if (primitive) + { + // Auto init ? + if (!primClass->AutoInit) + { + // Make a vector of locator + //CDatabaseLocatorPointer locatorPtr; + //getLocator (locatorPtr, locator); + std::list locators; + //locators.push_back (const_cast (locatorPtr.Primitive)); + + // Yes, go + //CDialogProperties dialogProperty (locators, getMainFrame ()); + //dialogProperty.DoModal (); + } + + // Eval the default name property + std::string name; + if (!primitive->getPropertyByName ("name", name) || name.empty()) + { + const NLLIGO::CPrimitiveClass *primClass = NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*primitive); + if (primClass) + { + for (size_t i = 0; i < primClass->Parameters.size(); ++i) + { + if (primClass->Parameters[i].Name == "name") + { + std::string result; + primClass->Parameters[i].getDefaultValue(result, *primitive, *primClass, NULL); + if (!result.empty()) + { + primitive->removePropertyByName("name"); + primitive->addPropertyByName("name", new NLLIGO::CPropertyString(result.c_str(), true)); + } + } + } + } + } + + // Init primitive default values + primitive->initDefaultValues(*NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig); + } + + // Done + return primitive; + } + else + { + nlerror("Unknown primitive class name : %s", className); + } + return 0; +} + +void deletePrimitive(NLLIGO::IPrimitive *primitive) +{ + // Get the parent + NLLIGO::IPrimitive *parent = primitive->getParent(); + nlassert(parent); + + // Get the child id + uint childId; + nlverify(parent->getChildId(childId, primitive)); + + // Delete the child + nlverify(parent->removeChild(childId)); +} + +bool updateDefaultValues(NLLIGO::IPrimitive *primitive) +{ + // Modified + bool modified = false; + + // Get the prim class + const NLLIGO::CPrimitiveClass *primClass = NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig->getPrimitiveClass(*primitive); + nlassert(primClass); + + if (primClass) + { + // For each parameters + for (uint i = 0; i < primClass->Parameters.size(); i++) + { + // First check the primitive property has to good type + NLLIGO::IProperty *prop; + if (primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), prop)) + { + // String to array ? + NLLIGO::CPropertyString *propString = dynamic_cast(prop); + const bool classStringArray = primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray || + primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray; + if (propString && classStringArray) + { + // Build an array string + std::vector strings; + if (!propString->String.empty()) + strings.push_back(propString->String); + prop = new NLLIGO::CPropertyStringArray(strings); + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); + modified = true; + } + + // Array to string ? + NLLIGO::CPropertyStringArray *propStringArray = dynamic_cast(prop); + if (propStringArray && !classStringArray) + { + // Build an array string + std::string str; + if (!propStringArray->StringArray.empty()) + str = propStringArray->StringArray[0]; + prop = new NLLIGO::CPropertyString(str); + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); + modified = true; + } + } + + // String or string array ? + if (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::String) + { + // Default value available ? + if (!primClass->Parameters[i].DefaultValue.empty ()) + { + // Unique Id ? + if (primClass->Parameters[i].DefaultValue[0].GenID) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) + { + // Add it ! + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString(NLMISC::toString(getUniqueId()).c_str())); + modified = true; + } + } + // Hidden ? + else if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName (primClass->Parameters[i].Name.c_str (), result)) + { + // Add it ! + primitive->addPropertyByName (primClass->Parameters[i].Name.c_str (), new NLLIGO::CPropertyString ("")); + modified = true; + } + } + } + } + else if ((primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray) || + (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray)) + { + for (uint j = 0; j < primClass->Parameters[i].DefaultValue.size(); j++) + { + // Unique Id ? + if (primClass->Parameters[i].DefaultValue[j].GenID) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || + (resultPtr->size() <= j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size() <= j) + result.resize(j + 1); + + // Resize to it + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + + // Set the value + result[j] = NLMISC::toString(getUniqueId()); + + // Add the new property array + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); + modified = true; + } + } + // Hidden ? + else if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || (resultPtr->size () <= j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size() <= j) + result.resize(j + 1); + + // Resize to it + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + + // Set the value + result[j] = ""; + + // Add the new property array + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); + modified = true; + } + } + } + } + else + { + // Default value available ? + if (!primClass->Parameters[i].DefaultValue.empty ()) + { + // Hidden ? + if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) + { + // Add it ! + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString("")); + modified = true; + } + } + } + } + } + } + return modified; +} + +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h new file mode 100644 index 000000000..4e75a3edf --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h @@ -0,0 +1,55 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 . + +#ifndef WORLD_EDITOR_MISC_H +#define WORLD_EDITOR_MISC_H + +// Project includes + +// NeL includes +#include +#include +#include + +// Qt includes + +namespace WorldEditor +{ + +// Generate unique identificator +uint32 getUniqueId(); + +// Get root primitive +NLLIGO::IPrimitive *getRootPrimitive(NLLIGO::IPrimitive *primitive); + +// Init a primitive parameters +void initPrimitiveParameters(const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, + const std::vector &initParameters); + +NLLIGO::IPrimitive *createPrimitive(const char *className, const char *primName, + const NLMISC::CVector &initPos, float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent); + +// Remove the primitive and don't delete it. +//void takeAtPrimitive(NLLIGO::IPrimitive *primitive); + +void deletePrimitive(NLLIGO::IPrimitive *primitive); + +} /* namespace WorldEditor */ + +#endif // WORLD_EDITOR_MISC_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp index 8d2c0c7f1..fc1f0e248 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp @@ -20,10 +20,14 @@ #include "world_editor_constants.h" #include "primitives_model.h" +// Core #include "../core/icore.h" #include "../core/imenu_manager.h" #include "../core/core_constants.h" +// Lanscape Editor plugin +//#include "../landscape_editor/project_settings_dialog.h" + // NeL includes #include #include @@ -55,12 +59,12 @@ WorldEditorWindow::WorldEditorWindow(QWidget *parent) createMenus(); createToolBars(); -// readSettings(); + readSettings(); } WorldEditorWindow::~WorldEditorWindow() { -// writeSettings(); + writeSettings(); } QUndoStack *WorldEditorWindow::undoStack() const @@ -89,14 +93,20 @@ void WorldEditorWindow::open() void WorldEditorWindow::loadPrimitive(const QString &fileName) { - NLLIGO::CPrimitives *primitives = new NLLIGO::CPrimitives(); + m_primitivesModel->loadPrimitive(fileName); +} - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = primitives; - - NLLIGO::loadXmlPrimitiveFile(*primitives, fileName.toStdString(), *NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig); - - m_primitivesModel->addPrimitives(fileName, primitives); +void WorldEditorWindow::openProjectSettings() +{ + /* + LandscapeEditor::ProjectSettingsDialog *dialog = new LandscapeEditor::ProjectSettingsDialog("", this); + dialog->show(); + int ok = dialog->exec(); + if (ok == QDialog::Accepted) + { + } + delete dialog; + */ } void WorldEditorWindow::createMenus() diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h index 8311ffcc6..39e741716 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h @@ -43,6 +43,8 @@ public Q_SLOTS: void open(); private Q_SLOTS: + void openProjectSettings(); + private: void createMenus(); void createToolBars(); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui index 6f597ca2a..179a78830 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui @@ -61,7 +61,23 @@ 3 - + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + 250 + + @@ -83,6 +99,11 @@ QGraphicsView
../landscape_editor/landscape_view.h
+ + WorldEditor::PrimitivesView + QTreeView +
primitives_view.h
+